Articles: finish admin refactor, uploads hardening, and attachment sorting (0.262)
This commit is contained in:
@@ -37,7 +37,15 @@ class ArticleRepository
|
||||
'article_id' => $articleId,
|
||||
'ORDER' => ['o' => 'ASC', 'id' => 'DESC']
|
||||
]);
|
||||
$article['files'] = $this->db->select('pp_articles_files', '*', ['article_id' => $articleId]);
|
||||
try {
|
||||
$article['files'] = $this->db->select('pp_articles_files', '*', [
|
||||
'article_id' => $articleId,
|
||||
'ORDER' => ['o' => 'ASC', 'id' => 'DESC']
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
// Fallback for instances where pp_articles_files does not yet have "o" column.
|
||||
$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;
|
||||
@@ -70,6 +78,8 @@ class ArticleRepository
|
||||
$this->savePages($id, $data['pages'] ?? null, true);
|
||||
$this->assignTempFiles($id);
|
||||
$this->assignTempImages($id);
|
||||
$this->applyGalleryOrderIfProvided($id, $data);
|
||||
$this->applyFilesOrderIfProvided($id, $data);
|
||||
|
||||
\S::htacces();
|
||||
\S::delete_dir('../temp/');
|
||||
@@ -87,6 +97,8 @@ class ArticleRepository
|
||||
$this->savePages($articleId, $data['pages'] ?? null, false);
|
||||
$this->assignTempFiles($articleId);
|
||||
$this->assignTempImages($articleId);
|
||||
$this->applyGalleryOrderIfProvided($articleId, $data);
|
||||
$this->applyFilesOrderIfProvided($articleId, $data);
|
||||
$this->deleteMarkedImages($articleId);
|
||||
$this->deleteMarkedFiles($articleId);
|
||||
|
||||
@@ -99,16 +111,16 @@ class ArticleRepository
|
||||
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,
|
||||
'show_title' => $this->isCheckedValue($data['show_title'] ?? null) ? 1 : 0,
|
||||
'show_date_add' => $this->isCheckedValue($data['show_date_add'] ?? null) ? 1 : 0,
|
||||
'show_date_modify' => $this->isCheckedValue($data['show_date_modify'] ?? null) ? 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,
|
||||
'status' => $this->isCheckedValue($data['status'] ?? null) ? 1 : 0,
|
||||
'repeat_entry' => $this->isCheckedValue($data['repeat_entry'] ?? null) ? 1 : 0,
|
||||
'social_icons' => $this->isCheckedValue($data['social_icons'] ?? null) ? 1 : 0,
|
||||
'show_table_of_contents' => $this->isCheckedValue($data['show_table_of_contents'] ?? null) ? 1 : 0,
|
||||
];
|
||||
|
||||
if ($isNew) {
|
||||
@@ -131,12 +143,32 @@ class ArticleRepository
|
||||
'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,
|
||||
'noindex' => $this->isCheckedValue($data['noindex'][$langId] ?? null) ? 1 : 0,
|
||||
'copy_from' => ($data['copy_from'][$langId] ?? '') != '' ? $data['copy_from'][$langId] : null,
|
||||
'block_direct_access' => ($data['block_direct_access'][$langId] ?? '') == 'on' ? 1 : 0,
|
||||
'block_direct_access' => $this->isCheckedValue($data['block_direct_access'][$langId] ?? null) ? 1 : 0,
|
||||
];
|
||||
}
|
||||
|
||||
private function applyGalleryOrderIfProvided(int $articleId, array $data): void
|
||||
{
|
||||
$order = trim((string)($data['gallery_order'] ?? ''));
|
||||
if ($order === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->saveGalleryOrder($articleId, $order);
|
||||
}
|
||||
|
||||
private function applyFilesOrderIfProvided(int $articleId, array $data): void
|
||||
{
|
||||
$order = trim((string)($data['files_order'] ?? ''));
|
||||
if ($order === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->saveFilesOrder($articleId, $order);
|
||||
}
|
||||
|
||||
private function saveTranslations(int $articleId, array $data, bool $isNew): void
|
||||
{
|
||||
$titles = $data['title'] ?? [];
|
||||
@@ -573,6 +605,182 @@ class ArticleRepository
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Zapisuje kolejnosc zalacznikow artykulu.
|
||||
*/
|
||||
public function saveFilesOrder(int $articleId, string $order): bool
|
||||
{
|
||||
$fileIds = explode(';', $order);
|
||||
if (!is_array($fileIds) || empty($fileIds)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$position = 0;
|
||||
foreach ($fileIds as $fileId) {
|
||||
if ($fileId === '' || $fileId === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->db->update('pp_articles_files', [
|
||||
'o' => $position++,
|
||||
], [
|
||||
'AND' => [
|
||||
'article_id' => $articleId,
|
||||
'id' => (int)$fileId,
|
||||
],
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
// Fallback for instances where pp_articles_files does not yet have "o" column.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Zwraca mape: article_id => etykieta stron (np. " - Strona A / Strona B").
|
||||
*
|
||||
* @param array<int, int> $articleIds
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public function pagesSummaryForArticles(array $articleIds): array
|
||||
{
|
||||
$normalizedIds = [];
|
||||
foreach ($articleIds as $articleId) {
|
||||
$id = (int)$articleId;
|
||||
if ($id > 0) {
|
||||
$normalizedIds[$id] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($normalizedIds)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$placeholders = [];
|
||||
$params = [];
|
||||
foreach (array_values($normalizedIds) as $index => $id) {
|
||||
$key = ':article_id_' . $index;
|
||||
$placeholders[] = $key;
|
||||
$params[$key] = $id;
|
||||
}
|
||||
|
||||
$sql = "
|
||||
SELECT
|
||||
ap.article_id,
|
||||
ap.page_id,
|
||||
(
|
||||
SELECT title
|
||||
FROM pp_pages_langs AS ppl, pp_langs AS pl
|
||||
WHERE ppl.lang_id = pl.id AND ppl.page_id = ap.page_id AND ppl.title != ''
|
||||
ORDER BY pl.o ASC
|
||||
LIMIT 1
|
||||
) AS title
|
||||
FROM pp_articles_pages AS ap
|
||||
WHERE ap.article_id IN (" . implode(', ', $placeholders) . ")
|
||||
ORDER BY ap.article_id ASC, ap.o ASC, ap.page_id ASC
|
||||
";
|
||||
|
||||
$stmt = $this->db->query($sql, $params);
|
||||
$rows = $stmt ? $stmt->fetchAll() : [];
|
||||
if (!is_array($rows)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$titlesByArticle = [];
|
||||
foreach ($rows as $row) {
|
||||
$articleId = (int)($row['article_id'] ?? 0);
|
||||
if ($articleId <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$title = trim((string)($row['title'] ?? ''));
|
||||
if ($title === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$titlesByArticle[$articleId][] = $title;
|
||||
}
|
||||
|
||||
$summary = [];
|
||||
foreach (array_values($normalizedIds) as $articleId) {
|
||||
if (empty($titlesByArticle[$articleId])) {
|
||||
$summary[$articleId] = '';
|
||||
continue;
|
||||
}
|
||||
|
||||
$summary[$articleId] = ' - ' . implode(' / ', $titlesByArticle[$articleId]);
|
||||
}
|
||||
|
||||
return $summary;
|
||||
}
|
||||
|
||||
public function updateImageAlt(int $imageId, string $imageAlt): bool
|
||||
{
|
||||
$result = $this->db->update('pp_articles_images', [
|
||||
'alt' => $imageAlt,
|
||||
], [
|
||||
'id' => $imageId,
|
||||
]);
|
||||
|
||||
\S::delete_cache();
|
||||
|
||||
return (bool)$result;
|
||||
}
|
||||
|
||||
public function updateFileName(int $fileId, string $fileName): bool
|
||||
{
|
||||
$result = $this->db->update('pp_articles_files', [
|
||||
'name' => $fileName,
|
||||
], [
|
||||
'id' => $fileId,
|
||||
]);
|
||||
|
||||
return (bool)$result;
|
||||
}
|
||||
|
||||
public function markFileToDelete(int $fileId): bool
|
||||
{
|
||||
$result = $this->db->update('pp_articles_files', [
|
||||
'to_delete' => 1,
|
||||
], [
|
||||
'id' => $fileId,
|
||||
]);
|
||||
|
||||
return (bool)$result;
|
||||
}
|
||||
|
||||
public function markImageToDelete(int $imageId): bool
|
||||
{
|
||||
$result = $this->db->update('pp_articles_images', [
|
||||
'to_delete' => 1,
|
||||
], [
|
||||
'id' => $imageId,
|
||||
]);
|
||||
|
||||
return (bool)$result;
|
||||
}
|
||||
|
||||
private function isCheckedValue($value): bool
|
||||
{
|
||||
if (is_bool($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (is_numeric($value)) {
|
||||
return ((int)$value) === 1;
|
||||
}
|
||||
|
||||
if (is_string($value)) {
|
||||
$normalized = strtolower(trim($value));
|
||||
return in_array($normalized, ['1', 'on', 'true', 'yes'], true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function appendDateRangeFilter(
|
||||
array &$where,
|
||||
array &$params,
|
||||
|
||||
Reference in New Issue
Block a user