db = $db; } /** * @return array{items: array>, total: int} */ public function listForAdmin( array $filters, string $sortColumn = 'id', string $sortDir = 'DESC', int $page = 1, int $perPage = 15 ): array { $allowedSortColumns = [ 'id' => 'q1.id', 'title' => 'q1.title', 'status' => 'q1.status', ]; $sortSql = $allowedSortColumns[$sortColumn] ?? 'q1.id'; $sortDir = strtoupper(trim($sortDir)) === 'ASC' ? 'ASC' : 'DESC'; $page = max(1, $page); $perPage = min(self::MAX_PER_PAGE, max(1, $perPage)); $offset = ($page - 1) * $perPage; $where = ['1 = 1']; $params = []; $title = trim((string)($filters['title'] ?? '')); if ($title !== '') { if (strlen($title) > 255) { $title = substr($title, 0, 255); } $where[] = 'q1.title LIKE :title'; $params[':title'] = '%' . $title . '%'; } $status = trim((string)($filters['status'] ?? '')); if ($status === '0' || $status === '1') { $where[] = 'q1.status = :status'; $params[':status'] = (int)$status; } $whereSql = implode(' AND ', $where); $baseSelect = $this->baseListSelect(); $sqlCount = " SELECT COUNT(0) FROM ({$baseSelect}) AS q1 WHERE {$whereSql} "; $stmtCount = $this->db->query($sqlCount, $params); $countRows = $stmtCount ? $stmtCount->fetchAll() : []; $total = isset($countRows[0][0]) ? (int)$countRows[0][0] : 0; $sql = " SELECT q1.* FROM ({$baseSelect}) AS q1 WHERE {$whereSql} ORDER BY {$sortSql} {$sortDir}, q1.id DESC LIMIT {$perPage} OFFSET {$offset} "; $stmt = $this->db->query($sql, $params); $items = $stmt ? $stmt->fetchAll() : []; return [ 'items' => is_array($items) ? $items : [], 'total' => $total, ]; } public function find(int $containerId): array { if ($containerId <= 0) { return $this->defaultContainer(); } $container = $this->db->get('pp_scontainers', '*', ['id' => $containerId]); if (!is_array($container)) { return $this->defaultContainer(); } $container['languages'] = $this->translationsMap($containerId); return $container; } public function detailsForLanguage(int $containerId, string $langId): ?array { if ($containerId <= 0 || trim($langId) === '') { return null; } $container = $this->db->get('pp_scontainers', '*', ['id' => $containerId]); if (!is_array($container)) { return null; } $translation = $this->db->get('pp_scontainers_langs', '*', [ 'AND' => [ 'container_id' => $containerId, 'lang_id' => $langId, ], ]); $container['languages'] = is_array($translation) ? $translation : [ 'lang_id' => $langId, 'title' => '', 'text' => '', ]; return $container; } public function save(array $data): ?int { $containerId = (int)($data['id'] ?? 0); $status = $this->toSwitchValue($data['status'] ?? 0); $showTitle = $this->toSwitchValue($data['show_title'] ?? 0); $translations = $this->extractTranslations($data); if ($containerId <= 0) { $this->db->insert('pp_scontainers', [ 'status' => $status, 'show_title' => $showTitle, ]); $containerId = (int)$this->db->id(); if ($containerId <= 0) { return null; } } else { $this->db->update('pp_scontainers', [ 'status' => $status, 'show_title' => $showTitle, ], [ 'id' => $containerId, ]); } foreach ($translations as $langId => $row) { $translationId = $this->db->get('pp_scontainers_langs', 'id', [ 'AND' => [ 'container_id' => $containerId, 'lang_id' => $langId, ], ]); if ($translationId) { $this->db->update('pp_scontainers_langs', [ 'title' => (string)($row['title'] ?? ''), 'text' => (string)($row['text'] ?? ''), ], [ 'id' => (int)$translationId, ]); } else { $this->db->insert('pp_scontainers_langs', [ 'container_id' => $containerId, 'lang_id' => $langId, 'title' => (string)($row['title'] ?? ''), 'text' => (string)($row['text'] ?? ''), ]); } } \Shared\Helpers\Helpers::delete_dir('../temp/'); $this->clearFrontCache($containerId); return $containerId; } public function delete(int $containerId): bool { if ($containerId <= 0) { return false; } $result = (bool)$this->db->delete('pp_scontainers', ['id' => $containerId]); if ($result) { $this->clearFrontCache($containerId); } return $result; } private function baseListSelect(): string { return " SELECT ps.id, ps.status, ( SELECT psl.title FROM pp_scontainers_langs AS psl JOIN pp_langs AS pl ON psl.lang_id = pl.id WHERE psl.container_id = ps.id AND psl.title <> '' ORDER BY pl.o ASC LIMIT 1 ) AS title FROM pp_scontainers AS ps "; } // ── Frontend methods ────────────────────────────────────────── public function frontScontainerDetails(int $scontainerId, string $langId): array { $cacheHandler = new \Shared\Cache\CacheHandler(); $cacheKey = "ScontainersRepository::frontScontainerDetails:$scontainerId"; $objectData = $cacheHandler->get($cacheKey); if ($objectData) { $cached = @unserialize($objectData); if (is_array($cached)) { return $cached; } $cacheHandler->delete($cacheKey); } $scontainer = $this->detailsForLanguage($scontainerId, $langId); if (!is_array($scontainer)) { $scontainer = [ 'id' => $scontainerId, 'status' => 0, 'show_title' => 0, 'languages' => [ 'lang_id' => $langId, 'title' => '', 'text' => '', ], ]; } $cacheHandler->set($cacheKey, $scontainer); return $scontainer; } private function clearFrontCache(int $containerId): void { if ($containerId <= 0 || !class_exists('\Shared\Cache\CacheHandler')) { return; } $cacheHandler = new \Shared\Cache\CacheHandler(); $cacheHandler->delete('ScontainersRepository::frontScontainerDetails:' . $containerId); } /** * @return array> */ private function translationsMap(int $containerId): array { $rows = $this->db->select('pp_scontainers_langs', '*', ['container_id' => $containerId]); if (!is_array($rows)) { return []; } $result = []; foreach ($rows as $row) { $langId = (string)($row['lang_id'] ?? ''); if ($langId !== '') { $result[$langId] = $row; } } return $result; } /** * @return array> */ private function extractTranslations(array $data): array { $translations = []; if (isset($data['translations']) && is_array($data['translations'])) { foreach ($data['translations'] as $langId => $row) { if (!is_array($row)) { continue; } $safeLangId = trim((string)$langId); if ($safeLangId === '') { continue; } $translations[$safeLangId] = [ 'title' => (string)($row['title'] ?? ''), 'text' => (string)($row['text'] ?? ''), ]; } } $legacyTitles = isset($data['title']) && is_array($data['title']) ? $data['title'] : []; $legacyTexts = isset($data['text']) && is_array($data['text']) ? $data['text'] : []; foreach ($legacyTitles as $langId => $title) { $safeLangId = trim((string)$langId); if ($safeLangId === '') { continue; } if (!isset($translations[$safeLangId])) { $translations[$safeLangId] = [ 'title' => '', 'text' => '', ]; } $translations[$safeLangId]['title'] = (string)$title; $translations[$safeLangId]['text'] = (string)($legacyTexts[$safeLangId] ?? ''); } return $translations; } private function toSwitchValue($value): int { return ($value === 'on' || $value === 1 || $value === '1' || $value === true) ? 1 : 0; } private function defaultContainer(): array { return [ 'id' => 0, 'status' => 1, 'show_title' => 0, 'languages' => [], ]; } }