db = $db; } /** * Pobiera artykul po ID wraz z tlumaczeniami, obrazami, plikami i powiazanymi stronami */ public function find(int $articleId): ?array { $article = $this->db->get('pp_articles', '*', ['id' => $articleId]); if (!$article) { return null; } $results = $this->db->select('pp_articles_langs', '*', ['article_id' => $articleId]); if (is_array($results)) { foreach ($results as $row) { $article['languages'][$row['lang_id']] = $row; } } $article['images'] = $this->db->select('pp_articles_images', '*', [ 'article_id' => $articleId, 'ORDER' => ['o' => 'ASC', 'id' => 'DESC'] ]); $article['files'] = $this->db->select('pp_articles_files', '*', ['article_id' => $articleId]); $article['pages'] = $this->db->select('pp_articles_pages', 'page_id', ['article_id' => $articleId]); return $article; } /** * Zapisuje artykul (tworzy nowy lub aktualizuje istniejacy). * Zwraca ID artykulu. */ public function save(int $articleId, array $data, int $userId): int { if (!$articleId) { return $this->createArticle($data, $userId); } return $this->updateArticle($articleId, $data, $userId); } private function createArticle(array $data, int $userId): int { $this->db->insert('pp_articles', $this->buildArticleRow($data, $userId, true)); $id = $this->db->id(); if (!$id) { return 0; } $this->saveTranslations($id, $data, true); $this->savePages($id, $data['pages'] ?? null, true); $this->assignTempFiles($id); $this->assignTempImages($id); \S::htacces(); \S::delete_dir('../temp/'); return (int)$id; } private function updateArticle(int $articleId, array $data, int $userId): int { $this->db->update('pp_articles', $this->buildArticleRow($data, $userId, false), [ 'id' => $articleId ]); $this->saveTranslations($articleId, $data, false); $this->savePages($articleId, $data['pages'] ?? null, false); $this->assignTempFiles($articleId); $this->assignTempImages($articleId); $this->deleteMarkedImages($articleId); $this->deleteMarkedFiles($articleId); \S::htacces(); \S::delete_dir('../temp/'); return $articleId; } private function buildArticleRow(array $data, int $userId, bool $isNew): array { $row = [ 'show_title' => ($data['show_title'] ?? '') == 'on' ? 1 : 0, 'show_date_add' => ($data['show_date_add'] ?? '') == 'on' ? 1 : 0, 'show_date_modify' => ($data['show_date_modify'] ?? '') == 'on' ? 1 : 0, 'date_modify' => date('Y-m-d H:i:s'), 'modify_by' => $userId, 'layout_id' => !empty($data['layout_id']) ? (int)$data['layout_id'] : null, 'status' => ($data['status'] ?? '') == 'on' ? 1 : 0, 'repeat_entry' => ($data['repeat_entry'] ?? '') == 'on' ? 1 : 0, 'social_icons' => ($data['social_icons'] ?? '') == 'on' ? 1 : 0, 'show_table_of_contents' => ($data['show_table_of_contents'] ?? '') == 'on' ? 1 : 0, ]; if ($isNew) { $row['date_add'] = date('Y-m-d H:i:s'); } return $row; } private function buildLangRow($langId, array $data): array { return [ 'lang_id' => $langId, 'title' => ($data['title'][$langId] ?? '') != '' ? $data['title'][$langId] : null, 'main_image' => ($data['main_image'][$langId] ?? '') != '' ? $data['main_image'][$langId] : null, 'entry' => ($data['entry'][$langId] ?? '') != '' ? $data['entry'][$langId] : null, 'text' => ($data['text'][$langId] ?? '') != '' ? $data['text'][$langId] : null, 'table_of_contents' => ($data['table_of_contents'][$langId] ?? '') != '' ? $data['table_of_contents'][$langId] : null, 'meta_title' => ($data['meta_title'][$langId] ?? '') != '' ? $data['meta_title'][$langId] : null, 'meta_description' => ($data['meta_description'][$langId] ?? '') != '' ? $data['meta_description'][$langId] : null, 'meta_keywords' => ($data['meta_keywords'][$langId] ?? '') != '' ? $data['meta_keywords'][$langId] : null, 'seo_link' => \S::seo($data['seo_link'][$langId] ?? '') != '' ? \S::seo($data['seo_link'][$langId]) : null, 'noindex' => ($data['noindex'][$langId] ?? '') == 'on' ? 1 : 0, 'copy_from' => ($data['copy_from'][$langId] ?? '') != '' ? $data['copy_from'][$langId] : null, 'block_direct_access' => ($data['block_direct_access'][$langId] ?? '') == 'on' ? 1 : 0, ]; } private function saveTranslations(int $articleId, array $data, bool $isNew): void { $titles = $data['title'] ?? []; foreach ($titles as $langId => $val) { $langRow = $this->buildLangRow($langId, $data); if ($isNew) { $langRow['article_id'] = $articleId; $this->db->insert('pp_articles_langs', $langRow); } else { $translationId = $this->db->get('pp_articles_langs', 'id', [ 'AND' => ['article_id' => $articleId, 'lang_id' => $langId] ]); if ($translationId) { $this->db->update('pp_articles_langs', $langRow, ['id' => $translationId]); } else { $langRow['article_id'] = $articleId; $this->db->insert('pp_articles_langs', $langRow); } } } } private function savePages(int $articleId, $pages, bool $isNew): void { if (!$isNew) { $notIn = [0]; if (is_array($pages)) { foreach ($pages as $page) { $notIn[] = $page; } } elseif ($pages) { $notIn[] = $pages; } $this->db->delete('pp_articles_pages', [ 'AND' => ['article_id' => $articleId, 'page_id[!]' => $notIn] ]); $existingPages = $this->db->select('pp_articles_pages', 'page_id', ['article_id' => $articleId]); if (!is_array($pages)) { $pages = [$pages]; } $pages = array_diff($pages, is_array($existingPages) ? $existingPages : []); } else { if (!is_array($pages)) { $pages = $pages ? [$pages] : []; } } if (is_array($pages)) { foreach ($pages as $page) { $order = $this->maxPageOrder() + 1; $this->db->insert('pp_articles_pages', [ 'article_id' => $articleId, 'page_id' => (int)$page, 'o' => $order, ]); } } } private function assignTempFiles(int $articleId): void { $results = $this->db->select('pp_articles_files', '*', ['article_id' => null]); if (!is_array($results)) { return; } $created = false; $dir = '/upload/article_files/article_' . $articleId; foreach ($results as $row) { $newFileName = str_replace('/upload/article_files/tmp', $dir, $row['src']); if (file_exists('..' . $row['src'])) { if (!is_dir('../' . $dir) && $created !== true) { if (mkdir('../' . $dir, 0755, true)) { $created = true; } } rename('..' . $row['src'], '..' . $newFileName); } $this->db->update('pp_articles_files', [ 'src' => $newFileName, 'article_id' => $articleId, ], ['id' => $row['id']]); } } private function assignTempImages(int $articleId): void { $results = $this->db->select('pp_articles_images', '*', ['article_id' => null]); if (!is_array($results)) { return; } $created = false; $dir = '/upload/article_images/article_' . $articleId; foreach ($results as $row) { $newFileName = str_replace('/upload/article_images/tmp', $dir, $row['src']); if (file_exists('../' . $newFileName)) { $ext = strrpos($newFileName, '.'); $fileNameA = substr($newFileName, 0, $ext); $fileNameB = substr($newFileName, $ext); $count = 1; while (file_exists('../' . $fileNameA . '_' . $count . $fileNameB)) { $count++; } $newFileName = $fileNameA . '_' . $count . $fileNameB; } if (file_exists('..' . $row['src'])) { if (!is_dir('../' . $dir) && $created !== true) { if (mkdir('../' . $dir, 0755, true)) { $created = true; } } rename('..' . $row['src'], '..' . $newFileName); } $this->db->update('pp_articles_images', [ 'src' => $newFileName, 'article_id' => $articleId, ], ['id' => $row['id']]); } } private function deleteMarkedImages(int $articleId): void { $results = $this->db->select('pp_articles_images', '*', [ 'AND' => ['article_id' => $articleId, 'to_delete' => 1] ]); if (is_array($results)) { foreach ($results as $row) { if (file_exists('../' . $row['src'])) { unlink('../' . $row['src']); } } } $this->db->delete('pp_articles_images', [ 'AND' => ['article_id' => $articleId, 'to_delete' => 1] ]); } private function deleteMarkedFiles(int $articleId): void { $results = $this->db->select('pp_articles_files', '*', [ 'AND' => ['article_id' => $articleId, 'to_delete' => 1] ]); if (is_array($results)) { foreach ($results as $row) { if (file_exists('../' . $row['src'])) { unlink('../' . $row['src']); } } } $this->db->delete('pp_articles_files', [ 'AND' => ['article_id' => $articleId, 'to_delete' => 1] ]); } private function maxPageOrder(): int { $max = $this->db->max('pp_articles_pages', 'o'); return $max ? (int)$max : 0; } /** * Archiwizuje artykul (ustawia status = -1). */ public function archive(int $articleId): bool { $result = $this->db->update('pp_articles', ['status' => -1], ['id' => $articleId]); return (bool)$result; } /** * Usuwa nieprzypisane pliki artykulow (article_id = null) wraz z plikami z dysku. */ public function deleteNonassignedFiles(): void { $results = $this->db->select('pp_articles_files', '*', ['article_id' => null]); if (is_array($results)) { foreach ($results as $row) { if (file_exists('../' . $row['src'])) { unlink('../' . $row['src']); } } } $this->db->delete('pp_articles_files', ['article_id' => null]); } /** * Usuwa nieprzypisane zdjecia artykulow (article_id = null) wraz z plikami z dysku. */ public function deleteNonassignedImages(): void { $results = $this->db->select('pp_articles_images', '*', ['article_id' => null]); if (is_array($results)) { foreach ($results as $row) { if (file_exists('../' . $row['src'])) { unlink('../' . $row['src']); } } } $this->db->delete('pp_articles_images', ['article_id' => null]); } }