449 lines
17 KiB
PHP
449 lines
17 KiB
PHP
<?php
|
|
|
|
// ##############################################################
|
|
// TENTO SKRIPT NAPROGRAMOVALO STUDIO wpj s.r.o.
|
|
// UZIVANI TOHOTO DILA JE MOZNE POUZE SE SOUHLASEM AUTORA
|
|
// KONTAKT: joe@wpj.cz
|
|
// ##############################################################
|
|
|
|
use KupShop\CatalogBundle\Util\SectionUtil;
|
|
use KupShop\ContentBundle\Util\ImageLocator;
|
|
use KupShop\ContentBundle\Util\SliderUtil;
|
|
use KupShop\I18nBundle\Translations\SlidersImagesTranslation;
|
|
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
|
use Query\Operator;
|
|
use Query\QueryBuilder;
|
|
|
|
class Sliders extends Window
|
|
{
|
|
public const ON_PAGE = 20;
|
|
|
|
protected SectionUtil $sectionUtil;
|
|
protected SliderUtil $sliderUtil;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->sectionUtil = ServiceContainer::getService(SectionUtil::class);
|
|
$this->sliderUtil = ServiceContainer::getService(SliderUtil::class);
|
|
}
|
|
|
|
public function get_vars()
|
|
{
|
|
$ID = $this->getID();
|
|
$vars = parent::get_vars();
|
|
$pageVars = getVal('body', $vars);
|
|
$pageVars['ID'] = $ID;
|
|
|
|
$pageVars['data']['default_size'] = getVal('size', $GLOBALS['cfg']['Modules']['sliders'], [780, 400]);
|
|
if ($ID == 1) {
|
|
$pageVars['data']['default_size'] = getVal('size_index', $GLOBALS['cfg']['Modules']['sliders'], $pageVars['data']['size']);
|
|
}
|
|
|
|
$pager = $this->createPager();
|
|
|
|
$SQL = sqlQueryBuilder()
|
|
->select('SQL_CALC_FOUND_ROWS si.*')
|
|
->from('sliders_images', 'si')
|
|
->where(Operator::equals(['si.id_slider' => $ID]))
|
|
->andWhere($pager->getSpec())
|
|
->orderBy('position', 'ASC')
|
|
->execute()->fetchAll();
|
|
|
|
$total_count = (int) sqlFetchAssoc(sqlQuery('SELECT FOUND_ROWS() as total_count'))['total_count'];
|
|
$pager->setTotal($total_count);
|
|
|
|
$photos = sqlFetchAll(sqlQueryBuilder()
|
|
->select('*')
|
|
->from('photos')
|
|
->where(Operator::inIntArray(array_map(function ($x) { return $x['id_photo']; }, $SQL), 'id'))
|
|
->execute(), 'id');
|
|
|
|
$imageLocator = ServiceContainer::getService(ImageLocator::class);
|
|
|
|
$images = [];
|
|
foreach ($SQL as $row) {
|
|
$row['img'] = $row['id_photo'] ? $imageLocator->getImage($photos[$row['id_photo']]) : null;
|
|
$row['active'] = $this->isSliderActive($row);
|
|
$this->unserializeCustomData($row);
|
|
$row['sliderTranslationsFigure'] = $this->getTranslationUtil()?->getTranslationsFigure(SlidersImagesTranslation::class, $row['id']);
|
|
$images[] = $row;
|
|
}
|
|
$pageVars['images'] = $images;
|
|
|
|
if (findModule(\Modules::PRODUCTS_SECTIONS)) {
|
|
$pageVars['data']['slider_sections'] = $this->fetchSliderSections((int) $ID);
|
|
}
|
|
|
|
$this->unserializeCustomData($pageVars['data']);
|
|
|
|
$vars['body'] = $pageVars;
|
|
$vars['pager'] = $pager;
|
|
|
|
return $vars;
|
|
}
|
|
|
|
public function createPager()
|
|
{
|
|
$pager = new \Pager();
|
|
$pager->setOnPage(self::ON_PAGE);
|
|
$pager->setPageNumber((int) getVal('page', null, 1));
|
|
$pager->setUrl($_SERVER['REQUEST_URI']);
|
|
|
|
return $pager;
|
|
}
|
|
|
|
public function getData()
|
|
{
|
|
$data = parent::getData();
|
|
if (getVal('Submit')) {
|
|
$this->serializeCustomData($data);
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
public function handleUpdate()
|
|
{
|
|
$OLD_ID = $this->getID();
|
|
$SQL = parent::handleUpdate();
|
|
|
|
$ID = $this->getID();
|
|
|
|
if ($duplicate = $this->isDuplicate()) {
|
|
// duplicate superuser fields (sizes)
|
|
sqlQueryBuilder()
|
|
->update('sliders', 's')
|
|
->join('s', 'sliders', 'so', 'so.id = :oldId')
|
|
->set('s.size', 'so.size')
|
|
->set('s.size_tablet', 'so.size_tablet')
|
|
->set('s.size_mobile', 'so.size_mobile')
|
|
->where(Operator::equals(['s.id' => $this->getID()]))
|
|
->setParameter('oldId', $OLD_ID)
|
|
->execute();
|
|
|
|
// duplicate sliders
|
|
$duplicate_sliders = sqlFetchAll($this->selectSQL('sliders_images', ['id_slider' => $OLD_ID]), 'id');
|
|
foreach ($duplicate_sliders as &$img) {
|
|
$img = $this->insertSlidersImage($img);
|
|
}
|
|
}
|
|
|
|
$data = $this->getData();
|
|
$sliders = getVal('images', $data, []);
|
|
krsort($sliders);
|
|
foreach ($sliders as $id => &$img) {
|
|
$photoId = empty($img['id_photo']) ? null : $img['id_photo'];
|
|
if (!empty($img['delete']) || !$id) {
|
|
if ($id > 0) {
|
|
$delete_id = $img['id'];
|
|
if ($duplicate) {
|
|
$delete_id = $duplicate_sliders[$img['id']]['id'] ?? $img['id'];
|
|
}
|
|
$this->deleteSQL('sliders_images', ['id' => $delete_id, 'id_slider' => $ID]);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
$img['date_from'] = ($img['date_from'] == '') ? null : $this->prepareDateTime($img['date_from']);
|
|
$img['date_to'] = ($img['date_to'] == '') ? null : $this->prepareDateTime($img['date_to']);
|
|
$this->serializeCustomData($img);
|
|
|
|
$uploadedImages = $this->getUploadedImages((int) $id);
|
|
$translateSlidersFigure = $img['translation_figure'] ?? [];
|
|
unset($img['translation_figure']);
|
|
|
|
if ($id < 0) {
|
|
// Skip if desktop image is missing
|
|
if (empty($uploadedImages['desktop'])) {
|
|
continue;
|
|
}
|
|
|
|
// upload new photos when adding slider
|
|
if ($photoId = $this->uploadImages($uploadedImages, null)) {
|
|
$img['id_photo'] = $photoId;
|
|
$img['position'] = 0;
|
|
$img = $this->insertSlidersImage($img);
|
|
}
|
|
} else {
|
|
if ($duplicate) {
|
|
if ($duplicate_img = ($duplicate_sliders[$img['id']] ?? null)) {
|
|
unset($img['id']);
|
|
$duplicate_img = array_replace($duplicate_img, $img);
|
|
$this->updateSQL('sliders_images', $duplicate_img, ['id' => $duplicate_img['id']]);
|
|
$img = $duplicate_img;
|
|
}
|
|
} else {
|
|
// upload photos to existing slider (upload of additional photo versions)
|
|
if ($photoId) {
|
|
$this->uploadImages($uploadedImages, $photoId);
|
|
}
|
|
|
|
$this->updateSQL('sliders_images', $img, ['id' => $img['id']]);
|
|
}
|
|
|
|
$this->getTranslationUtil()?->updateTranslationsFigure(SlidersImagesTranslation::class, $img['id'], $translateSlidersFigure);
|
|
}
|
|
}
|
|
|
|
if (findModule(\Modules::PRODUCTS_SECTIONS)) {
|
|
$this->saveSliderSections(getVal('slider_sections', $data, []));
|
|
}
|
|
|
|
sqlQuery('SELECT @i := 0; UPDATE sliders_images SET position = (select @i := @i + 1) WHERE id_slider=:id ORDER BY position', ['id' => $ID]);
|
|
|
|
MenuSectionTree::invalidateCache();
|
|
clearCache('sliders', true);
|
|
|
|
if ($page = getVal('page')) {
|
|
$_GET['page'] = $page;
|
|
}
|
|
|
|
$this->activityMessage($data['name']);
|
|
$this->returnOK($GLOBALS['txt_str']['status']['saved']);
|
|
}
|
|
|
|
public function uploadImages(array $images, ?int $photoId): int
|
|
{
|
|
$versions = [
|
|
'desktop' => Photos::PHOTO_VERSION_DESKTOP,
|
|
'tablet' => Photos::PHOTO_VERSION_TABLET,
|
|
'mobile' => Photos::PHOTO_VERSION_MOBILE,
|
|
];
|
|
|
|
foreach ($images as $version => $image) {
|
|
if (!empty($image)) {
|
|
$img = Photos::get($photoId, $versions[$version]);
|
|
$img->uploadPhotoOrVideo($image, $image['name']);
|
|
|
|
if ($photoId === null) {
|
|
$photoId = (int) $img->getID();
|
|
}
|
|
}
|
|
}
|
|
|
|
return $photoId;
|
|
}
|
|
|
|
public function getUploadedImages(int $id): array
|
|
{
|
|
$images = $_FILES['image'] ?? [];
|
|
|
|
$result = [];
|
|
foreach (['desktop', 'tablet', 'mobile'] as $type) {
|
|
$result[$type] = ($images['size'][$id][$type] ?? 0) <= 0 ? [] : [
|
|
'name' => $images['name'][$id][$type],
|
|
'type' => $images['type'][$id][$type],
|
|
'tmp_name' => $images['tmp_name'][$id][$type],
|
|
'error' => $images['error'][$id][$type],
|
|
'size' => $images['size'][$id][$type],
|
|
];
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
protected function insertSlidersImage($img)
|
|
{
|
|
unset($img['id']);
|
|
$img['id_slider'] = $this->getID();
|
|
$this->insertSQL('sliders_images', $img);
|
|
$img['id'] = sqlInsertId();
|
|
|
|
return $img;
|
|
}
|
|
|
|
protected function isSliderActive(array $slider): bool
|
|
{
|
|
$today = new DateTime();
|
|
$dateFrom = $slider['date_from'] ? new DateTime($slider['date_from']) : null;
|
|
$dateTo = $slider['date_to'] ? new DateTime($slider['date_to']) : null;
|
|
|
|
if (($dateFrom === null || $dateFrom < $today) && ($dateTo === null || $dateTo > $today)) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public function handleDrag()
|
|
{
|
|
if (($moved_item = getVal('moved_item')) && ($ID = $this->getID())) {
|
|
$this->updateSQL('sliders_images', ['position' => 0], ['id' => $moved_item, 'id_slider' => $ID]);
|
|
sqlQuery('SELECT @i := 0; UPDATE sliders_images SET position = (select @i := @i + 1) WHERE id_slider=:id ORDER BY position', ['id' => $ID]);
|
|
}
|
|
$this->returnOK();
|
|
}
|
|
|
|
public function saveSliderSections(array $sliderSections): void
|
|
{
|
|
$sliderSections = array_map(fn (string $json) => json_decode_strict($json, true), $sliderSections);
|
|
|
|
sqlGetConnection()->transactional(function () use ($sliderSections) {
|
|
$this->sliderUtil->clearSliderSections(idSlider: (int) $this->getID());
|
|
$this->sliderUtil->saveSliderPositions($sliderSections, ['id_slider']);
|
|
});
|
|
}
|
|
|
|
protected function fetchSliderSections(int $sliderId): array
|
|
{
|
|
$sectionIds = sqlQueryBuilder()->select('sis.id_section AS id')
|
|
->from('sliders_in_sections', 'sis')
|
|
->andWhere(Operator::equals(['sis.id_slider' => $sliderId]));
|
|
|
|
$qb = $this->createSliderSectionsQB()
|
|
->andWhere(Operator::inSubquery('s.id', $sectionIds))
|
|
->groupBy('s.id_rootsection', 'sis.id_section', 'sis.id_slider', 'sis.position');
|
|
|
|
$sliderSections = [];
|
|
foreach ($qb->execute() as $flatSection) {
|
|
$sectionId = $flatSection['id_section'];
|
|
|
|
if (!isset($sliderSections[$sectionId])) {
|
|
$sliderSections[$sectionId] = [
|
|
'id' => $sectionId,
|
|
'full_path' => $flatSection['full_path'],
|
|
'name' => $flatSection['section_name'],
|
|
'badges' => $this->getBadges($flatSection),
|
|
'positions' => $this->getEmptyPositions(),
|
|
|
|
'id_rootsection' => $flatSection['id_rootsection'],
|
|
'full_position' => $flatSection['full_position'],
|
|
'section_position' => $flatSection['section_position'],
|
|
];
|
|
}
|
|
|
|
$sliderSections[$sectionId]['positions'][$flatSection['position']] = $flatSection;
|
|
}
|
|
|
|
$orderedSections = [];
|
|
foreach ($sliderSections as $section) {
|
|
$orderedSections[$section['id_rootsection']][] = $section;
|
|
}
|
|
|
|
foreach ($orderedSections as $orderedSection) {
|
|
uasort($orderedSection, function ($a, $b) {
|
|
return $a['section_position'] <=> $b['section_position'];
|
|
});
|
|
}
|
|
|
|
return array_reduce($orderedSections, fn ($carry, $sections) => array_merge($carry, $sections), []);
|
|
}
|
|
|
|
protected function createSliderSectionsQB(?int $idTopsection = null): QueryBuilder
|
|
{
|
|
$whereSection = isset($idTopsection) ? 'id_topsection = :idTopSection' : 'id_topsection IS NULL';
|
|
|
|
$recursiveSections = "
|
|
WITH RECURSIVE cte (id, id_rootsection, id_topsection, name, figure, virtual, show_in_search, full_path, position, full_position) as (
|
|
SELECT id_section,
|
|
id_section AS id_rootsection,
|
|
id_topsection,
|
|
(SELECT name FROM sections WHERE id = id_section LIMIT 1) as name,
|
|
(SELECT figure FROM sections WHERE id = id_section LIMIT 1) as figure,
|
|
(SELECT virtual FROM sections WHERE id = id_section LIMIT 1) as virtual,
|
|
(SELECT show_in_search FROM sections WHERE id = id_section LIMIT 1) as show_in_search,
|
|
(SELECT name FROM sections WHERE id = id_section LIMIT 1) as full_path,
|
|
position,
|
|
CAST(LPAD(position, 5, 0) AS CHAR(500)) AS full_position
|
|
FROM sections_relation
|
|
WHERE {$whereSection}
|
|
UNION ALL
|
|
SELECT sr.id_section,
|
|
cte.id_rootsection,
|
|
sr.id_topsection,
|
|
(SELECT name FROM sections WHERE id = sr.id_section LIMIT 1) as name,
|
|
(SELECT figure FROM sections WHERE id = sr.id_section LIMIT 1) as figure,
|
|
(SELECT virtual FROM sections WHERE id = sr.id_section LIMIT 1) as virtual,
|
|
(SELECT show_in_search FROM sections WHERE id = sr.id_section LIMIT 1) as show_in_search,
|
|
CONCAT(cte.full_path,' > ',(SELECT name FROM sections WHERE id = sr.id_section LIMIT 1)) as full_path,
|
|
CONCAT(full_position, '/', LPAD(sr.position, 5, 0)),
|
|
sr.position
|
|
FROM sections_relation sr
|
|
INNER JOIN cte
|
|
on sr.id_topsection = cte.id
|
|
) SELECT * FROM cte";
|
|
|
|
return sqlQueryBuilder()->select(
|
|
's.id AS id_section',
|
|
's.name AS section_name',
|
|
's.figure',
|
|
's.virtual',
|
|
's.show_in_search',
|
|
's.full_path',
|
|
'sis.id_slider',
|
|
'sis.position',
|
|
'sl.name AS slider_name',
|
|
's.id_topsection',
|
|
's.position AS section_position',
|
|
's.full_position',
|
|
's.id_rootsection'
|
|
)
|
|
->from("({$recursiveSections})", 's')
|
|
->leftJoin('s', 'sliders_in_sections', 'sis', 'sis.id_section = s.id')
|
|
->leftJoin('sis', 'sliders', 'sl', 'sis.id_slider = sl.id');
|
|
}
|
|
|
|
protected function getBadges(array $section): array
|
|
{
|
|
if (!$section) {
|
|
return [];
|
|
}
|
|
|
|
$badges = $this->sectionUtil->getBadges(
|
|
figure: $section['figure'],
|
|
virtual: $section['virtual'],
|
|
showInSearch: $section['show_in_search'],
|
|
);
|
|
|
|
foreach ($badges as &$badge) {
|
|
$badge['title'] = translate($badge['translate_key'], 'sections');
|
|
}
|
|
|
|
return $badges;
|
|
}
|
|
|
|
protected function getEmptyPositions(): array
|
|
{
|
|
return array_fill_keys(array_keys($this->sliderUtil::getPositions()), null);
|
|
}
|
|
|
|
public function handleAjaxSection(): never
|
|
{
|
|
$idSection = getVal('id_section');
|
|
if (!is_numeric($idSection)) {
|
|
throw new \Symfony\Component\HttpFoundation\Exception\BadRequestException('id_section is required');
|
|
}
|
|
|
|
$sections = $this->createSliderSectionsQB()
|
|
->andWhere(Operator::equals(['s.id' => $idSection]));
|
|
|
|
$result = [];
|
|
foreach ($sections->execute() as $sectionRow) {
|
|
if (empty($result)) {
|
|
$result = [
|
|
'id' => $idSection,
|
|
'name' => $sectionRow['section_name'],
|
|
'full_path' => $sectionRow['full_path'],
|
|
'badges' => $this->getBadges($sectionRow),
|
|
'positions' => $this->getEmptyPositions(),
|
|
];
|
|
}
|
|
|
|
if (!empty($sectionRow['id_slider'])) {
|
|
$result['positions'][$sectionRow['position']] = [
|
|
'id_slider' => $sectionRow['id_slider'],
|
|
'slider_name' => $sectionRow['slider_name'],
|
|
];
|
|
}
|
|
}
|
|
|
|
header('Content-Type: application/json');
|
|
echo json_encode($result);
|
|
|
|
exit;
|
|
}
|
|
}
|
|
|
|
$sliders = new Sliders();
|
|
$sliders->run();
|