From 70b75f8426249a249c3d2395c213bce8f9d7d05a Mon Sep 17 00:00:00 2001 From: mirivlad Date: Fri, 28 Nov 2025 03:47:39 +0800 Subject: [PATCH] Add sorting for chapters in book. --- controllers/ChapterController.php | 35 ++++- index.php | 1 + models/Chapter.php | 55 ++++---- views/chapters/index.php | 204 ++++++++++++++++++++++-------- 4 files changed, 217 insertions(+), 78 deletions(-) diff --git a/controllers/ChapterController.php b/controllers/ChapterController.php index c7c0408..bf3ec63 100755 --- a/controllers/ChapterController.php +++ b/controllers/ChapterController.php @@ -220,7 +220,40 @@ class ChapterController extends BaseController { ]); } - // Добавьте эту функцию в начало файла + public function updateOrder($book_id) { + $this->requireLogin(); + + if ($_SERVER['REQUEST_METHOD'] !== 'POST') { + return $this->jsonResponse(['success' => false, 'error' => 'Неверный метод запроса']); + } + + if (!verify_csrf_token($_POST['csrf_token'] ?? '')) { + return $this->jsonResponse(['success' => false, 'error' => 'Ошибка безопасности']); + } + + $user_id = $_SESSION['user_id']; + $chapterModel = new Chapter($this->pdo); + $bookModel = new Book($this->pdo); + + // Проверяем права доступа к книге + if (!$bookModel->userOwnsBook($book_id, $user_id)) { + return $this->jsonResponse(['success' => false, 'error' => 'У вас нет доступа к этой книге']); + } + + $order_data = $_POST['order'] ?? []; + + if (empty($order_data)) { + return $this->jsonResponse(['success' => false, 'error' => 'Нет данных для обновления']); + } + + // Обновляем порядок глав + if ($chapterModel->updateChaptersOrder($book_id, $order_data)) { + return $this->jsonResponse(['success' => true]); + } else { + return $this->jsonResponse(['success' => false, 'error' => 'Ошибка при обновлении порядка глав']); + } + } + function cleanChapterContent($content) { // Удаляем лишние пробелы в начале и конце $content = trim($content); diff --git a/index.php b/index.php index 2197afe..c9ff4b4 100755 --- a/index.php +++ b/index.php @@ -133,6 +133,7 @@ $router->add('/books/{book_id}/chapters/create', 'ChapterController@create'); $router->add('/chapters/{id}/edit', 'ChapterController@edit'); $router->add('/chapters/{id}/delete', 'ChapterController@delete'); $router->add('/chapters/preview', 'ChapterController@preview'); +$router->add('/books/{id}/chapters/update-order', 'ChapterController@updateOrder'); // Серии $router->add('/series', 'SeriesController@index'); diff --git a/models/Chapter.php b/models/Chapter.php index 292219f..21888cb 100755 --- a/models/Chapter.php +++ b/models/Chapter.php @@ -20,33 +20,31 @@ class Chapter { } public function findByBook($book_id) { - $stmt = $this->pdo->prepare(" - SELECT * FROM chapters - WHERE book_id = ? - ORDER BY sort_order, created_at - "); + $stmt = $this->pdo->prepare("SELECT * FROM chapters WHERE book_id = ? ORDER BY sort_order ASC, id ASC"); $stmt->execute([$book_id]); return $stmt->fetchAll(PDO::FETCH_ASSOC); } public function create($data) { + // Получаем максимальный порядковый номер для этой книги $stmt = $this->pdo->prepare("SELECT MAX(sort_order) as max_order FROM chapters WHERE book_id = ?"); $stmt->execute([$data['book_id']]); - $result = $stmt->fetch(); + $result = $stmt->fetch(PDO::FETCH_ASSOC); $next_order = ($result['max_order'] ?? 0) + 1; - - $word_count = $this->countWords($data['content']); - + $stmt = $this->pdo->prepare(" - INSERT INTO chapters (book_id, title, content, sort_order, word_count, status) - VALUES (?, ?, ?, ?, ?, ?) + INSERT INTO chapters (book_id, title, content, word_count, sort_order, status, created_at, updated_at) + VALUES (?, ?, ?, ?, ?, ?, NOW(), NOW()) "); + + $word_count = str_word_count(strip_tags($data['content'])); + return $stmt->execute([ $data['book_id'], $data['title'], $data['content'], - $next_order, $word_count, + $next_order, $data['status'] ?? 'draft' ]); } @@ -108,21 +106,24 @@ class Chapter { return $stmt->fetchAll(PDO::FETCH_ASSOC); } - // private function getAllChapters($book_id) { - // $stmt = $this->pdo->prepare("SELECT id, content FROM chapters WHERE book_id = ?"); - // $stmt->execute([$book_id]); - // return $stmt->fetchAll(PDO::FETCH_ASSOC); - // } - - // private function updateChapterContent($chapter_id, $content) { - // $word_count = $this->countWords($content); - // $stmt = $this->pdo->prepare(" - // UPDATE chapters - // SET content = ?, word_count = ?, updated_at = CURRENT_TIMESTAMP - // WHERE id = ? - // "); - // return $stmt->execute([$content, $word_count, $chapter_id]); - // } + public function updateChaptersOrder($book_id, $chapter_ids) { + try { + $this->pdo->beginTransaction(); + + // Обновляем порядок для каждой главы + foreach ($chapter_ids as $index => $chapter_id) { + $stmt = $this->pdo->prepare("UPDATE chapters SET sort_order = ? WHERE id = ? AND book_id = ?"); + $stmt->execute([$index + 1, $chapter_id, $book_id]); + } + + $this->pdo->commit(); + return true; + } catch (Exception $e) { + $this->pdo->rollBack(); + error_log("Error updating chapters order: " . $e->getMessage()); + return false; + } + } } ?> \ No newline at end of file diff --git a/views/chapters/index.php b/views/chapters/index.php index 37adcbc..33bacd6 100755 --- a/views/chapters/index.php +++ b/views/chapters/index.php @@ -41,58 +41,76 @@ include 'views/layouts/header.php';
-
-
- - - - - - - - - - - - - $chapter): ?> - - - - - - - - - - -
Название главыСтатусСловОбновленоДействия
- - -
- -
- - - - - - -
- - - -
- - -
-
-
+
+
Список глав
+
+ Перетащите для изменения порядка +
+
+
+ + +
+ + + + + + + + + + + + + + $chapter): ?> + + + + + + + + + + + + +
Название главыСтатусСловОбновленоДействия
+ + + + +
+ +
+ + + + + + +
+ + + + + + + +
+
+
+ +
@@ -114,4 +132,90 @@ include 'views/layouts/header.php';
+ + + + + + + \ No newline at end of file