Add view classes for articles, banners, languages, menu, newsletter, containers, shop categories, clients, payment methods, products, and search
- Created `Articles` class for rendering article views including full articles, miniature lists, and news sections. - Added `Banners` class for handling banner displays. - Introduced `Languages` class for rendering language options. - Implemented `Menu` class for rendering page and menu structures. - Developed `Newsletter` class for newsletter rendering. - Created `Scontainers` class for rendering specific containers. - Added `ShopCategory` class for managing shop category views and pagination. - Implemented `ShopClient` class for client-related views including address management and login forms. - Created `ShopPaymentMethod` class for displaying payment methods in the basket. - Added `ShopProduct` class for generating product URLs. - Introduced `ShopSearch` class for rendering a simple search form. - Added `.htaccess` file in the plugins directory to enhance security by restricting access to sensitive files and directories.
This commit is contained in:
345
autoload/Domain/Scontainers/ScontainersRepository.php
Normal file
345
autoload/Domain/Scontainers/ScontainersRepository.php
Normal file
@@ -0,0 +1,345 @@
|
||||
<?php
|
||||
namespace Domain\Scontainers;
|
||||
|
||||
class ScontainersRepository
|
||||
{
|
||||
private const MAX_PER_PAGE = 100;
|
||||
|
||||
private $db;
|
||||
|
||||
public function __construct($db)
|
||||
{
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{items: array<int, array<string, mixed>>, 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<string, array<string, mixed>>
|
||||
*/
|
||||
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<string, array<string, string>>
|
||||
*/
|
||||
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' => [],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user