publication.php 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. <?php
  2. /**
  3. * Publication Model Class
  4. * Handles all publication-related database operations
  5. */
  6. class Publication {
  7. public $db;
  8. public function __construct() {
  9. $this->db = Database::getInstance();
  10. }
  11. public function getAll($status = 'published', $limit = null, $offset = 0) {
  12. $sql = "SELECT p.*, GROUP_CONCAT(c.name) as categories
  13. FROM publications p
  14. LEFT JOIN publication_categories pc ON p.id = pc.publication_id
  15. LEFT JOIN categories c ON pc.category_id = c.id";
  16. $params = [];
  17. if ($status !== 'all') {
  18. $sql .= " WHERE p.status = ?";
  19. $params[] = $status;
  20. }
  21. $sql .= " GROUP BY p.id ORDER BY p.created_at DESC";
  22. if ($limit) {
  23. $sql .= " LIMIT ? OFFSET ?";
  24. $params[] = (int)$limit;
  25. $params[] = (int)$offset;
  26. }
  27. return $this->db->fetchAll($sql, $params);
  28. }
  29. public function getById($id) {
  30. $sql = "SELECT p.*, GROUP_CONCAT(c.name) as categories
  31. FROM publications p
  32. LEFT JOIN publication_categories pc ON p.id = pc.publication_id
  33. LEFT JOIN categories c ON pc.category_id = c.id
  34. WHERE p.id = ?
  35. GROUP BY p.id";
  36. $publication = $this->db->fetch($sql, [$id]);
  37. if ($publication && $publication['categories']) {
  38. $publication['categories_array'] = explode(',', $publication['categories']);
  39. } else {
  40. $publication['categories_array'] = [];
  41. }
  42. return $publication;
  43. }
  44. public function getBySlug($slug) {
  45. $sql = "SELECT p.*, GROUP_CONCAT(c.name) as categories
  46. FROM publications p
  47. LEFT JOIN publication_categories pc ON p.id = pc.publication_id
  48. LEFT JOIN categories c ON pc.category_id = c.id
  49. WHERE p.slug = ?
  50. GROUP BY p.id";
  51. $publication = $this->db->fetch($sql, [$slug]);
  52. if ($publication && $publication['categories']) {
  53. $publication['categories_array'] = explode(',', $publication['categories']);
  54. } else {
  55. $publication['categories_array'] = [];
  56. }
  57. return $publication;
  58. }
  59. public function create($data, $categories = []) {
  60. $this->db->beginTransaction();
  61. try {
  62. // Generate slug from title
  63. $slug = $this->generateSlug($data['title']);
  64. $data['slug'] = $slug;
  65. // Set published_at if status is published
  66. if ($data['status'] === 'published' && !isset($data['published_at'])) {
  67. $data['published_at'] = date('Y-m-d H:i:s');
  68. }
  69. $publicationId = $this->db->insert('publications', $data);
  70. // Add categories
  71. if (!empty($categories)) {
  72. $this->updateCategories($publicationId, $categories);
  73. }
  74. $this->db->commit();
  75. return $publicationId;
  76. } catch (Exception $e) {
  77. $this->db->rollback();
  78. throw $e;
  79. }
  80. }
  81. public function update($id, $data, $categories = []) {
  82. $this->db->beginTransaction();
  83. try {
  84. // Update slug if title changed
  85. if (isset($data['title'])) {
  86. $data['slug'] = $this->generateSlug($data['title'], $id);
  87. }
  88. // Set published_at if status changed to published
  89. if (isset($data['status']) && $data['status'] === 'published') {
  90. $current = $this->getById($id);
  91. if ($current['status'] !== 'published') {
  92. $data['published_at'] = date('Y-m-d H:i:s');
  93. }
  94. }
  95. $this->db->update('publications', $data, 'id = ?', [$id]);
  96. // Update categories if provided
  97. if (!empty($categories)) {
  98. $this->updateCategories($id, $categories);
  99. }
  100. $this->db->commit();
  101. return true;
  102. } catch (Exception $e) {
  103. $this->db->rollback();
  104. throw $e;
  105. }
  106. }
  107. public function delete($id) {
  108. $this->db->beginTransaction();
  109. try {
  110. // Delete category associations
  111. $this->db->delete('publication_categories', 'publication_id = ?', [$id]);
  112. // Delete publication
  113. $this->db->delete('publications', 'id = ?', [$id]);
  114. $this->db->commit();
  115. return true;
  116. } catch (Exception $e) {
  117. $this->db->rollback();
  118. throw $e;
  119. }
  120. }
  121. public function search($query, $status = 'published') {
  122. $sql = "SELECT p.*, GROUP_CONCAT(c.name) as categories
  123. FROM publications p
  124. LEFT JOIN publication_categories pc ON p.id = pc.publication_id
  125. LEFT JOIN categories c ON pc.category_id = c.id
  126. WHERE (p.title LIKE ? OR p.content LIKE ? OR p.summary LIKE ?)";
  127. $params = ["%$query%", "%$query%", "%$query%"];
  128. if ($status !== 'all') {
  129. $sql .= " AND p.status = ?";
  130. $params[] = $status;
  131. }
  132. $sql .= " GROUP BY p.id ORDER BY p.created_at DESC";
  133. return $this->db->fetchAll($sql, $params);
  134. }
  135. public function getByCategory($categoryName, $status = 'published') {
  136. $sql = "SELECT p.*, GROUP_CONCAT(c.name) as categories
  137. FROM publications p
  138. LEFT JOIN publication_categories pc ON p.id = pc.publication_id
  139. LEFT JOIN categories c ON pc.category_id = c.id
  140. WHERE c.name = ?";
  141. $params = [$categoryName];
  142. if ($status !== 'all') {
  143. $sql .= " AND p.status = ?";
  144. $params[] = $status;
  145. }
  146. $sql .= " GROUP BY p.id ORDER BY p.created_at DESC";
  147. return $this->db->fetchAll($sql, $params);
  148. }
  149. public function getCategories() {
  150. $sql = "SELECT c.*, COUNT(pc.publication_id) as publication_count
  151. FROM categories c
  152. LEFT JOIN publication_categories pc ON c.id = pc.category_id
  153. LEFT JOIN publications p ON pc.publication_id = p.id AND p.status = 'published'
  154. GROUP BY c.id
  155. ORDER BY c.name";
  156. return $this->db->fetchAll($sql);
  157. }
  158. private function updateCategories($publicationId, $categories) {
  159. // Delete existing category associations
  160. $this->db->delete('publication_categories', 'publication_id = ?', [$publicationId]);
  161. // Add new category associations
  162. foreach ($categories as $categoryId) {
  163. $this->db->insert('publication_categories', [
  164. 'publication_id' => $publicationId,
  165. 'category_id' => $categoryId
  166. ]);
  167. }
  168. }
  169. private function generateSlug($title, $excludeId = null) {
  170. $slug = strtolower($title);
  171. $slug = preg_replace('/[^a-z0-9]+/', '-', $slug);
  172. $slug = trim($slug, '-');
  173. // Check for uniqueness
  174. $sql = "SELECT COUNT(*) as count FROM publications WHERE slug = ?";
  175. $params = [$slug];
  176. if ($excludeId) {
  177. $sql .= " AND id != ?";
  178. $params[] = $excludeId;
  179. }
  180. $result = $this->db->fetch($sql, $params);
  181. if ($result['count'] > 0) {
  182. $slug .= '-' . time();
  183. }
  184. return $slug;
  185. }
  186. public function getStats() {
  187. $stats = [];
  188. $stats['total'] = $this->db->fetch("SELECT COUNT(*) as count FROM publications")['count'];
  189. $stats['published'] = $this->db->fetch("SELECT COUNT(*) as count FROM publications WHERE status = 'published'")['count'];
  190. $stats['draft'] = $this->db->fetch("SELECT COUNT(*) as count FROM publications WHERE status = 'draft'")['count'];
  191. $stats['archived'] = $this->db->fetch("SELECT COUNT(*) as count FROM publications WHERE status = 'archived'")['count'];
  192. return $stats;
  193. }
  194. }