349 lines
11 KiB
PHP
349 lines
11 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace KupShop\ContentBundle\Util;
|
|
|
|
use Doctrine\DBAL\Exception as DBALException;
|
|
use Doctrine\DBAL\Types\Type;
|
|
use KupShop\ContentBundle\Entity\Slider;
|
|
use KupShop\I18nBundle\Translations\PhotosTranslation;
|
|
use KupShop\I18nBundle\Translations\SlidersImagesTranslation;
|
|
use KupShop\I18nBundle\Translations\SlidersTranslation;
|
|
use KupShop\KupShopBundle\Util\Entity\EntityUtil;
|
|
use KupShop\KupShopBundle\Util\StringUtil;
|
|
use KupShop\KupShopBundle\Util\System\PathFinder;
|
|
use Query\Operator;
|
|
use Query\QueryBuilder;
|
|
use Query\Translation;
|
|
use Symfony\Component\Serializer\Exception\ExceptionInterface as SerializerException;
|
|
|
|
class SliderUtil
|
|
{
|
|
private EntityUtil $entityUtil;
|
|
private ImageLocator $imageLocator;
|
|
private PathFinder $pathFinder;
|
|
|
|
public function __construct(EntityUtil $entityUtil, ImageLocator $imageLocator, PathFinder $pathFinder)
|
|
{
|
|
$this->entityUtil = $entityUtil;
|
|
$this->imageLocator = $imageLocator;
|
|
$this->pathFinder = $pathFinder;
|
|
}
|
|
|
|
public function get(int $id, bool $random = false): ?Slider
|
|
{
|
|
$sliders = $this->fetchSliders(
|
|
Operator::andX(
|
|
Operator::equals(['sl.id' => $id]),
|
|
static::specRandomSlider($random),
|
|
),
|
|
);
|
|
|
|
return count($sliders) > 0 ? array_values($sliders)[0] : null;
|
|
}
|
|
|
|
public function getByName(string $name, bool $random = false): ?Slider
|
|
{
|
|
$sliders = $this->fetchSliders(
|
|
Operator::andX(
|
|
Operator::like(['sl.name' => $name]),
|
|
static::specRandomSlider($random),
|
|
),
|
|
);
|
|
|
|
return count($sliders) > 0 ? array_values($sliders)[0] : null;
|
|
}
|
|
|
|
/**
|
|
* @return Slider[]
|
|
*
|
|
* @throws DBALException|SerializerException
|
|
*/
|
|
public function fetchSliders(?callable $spec = null, string $indexBy = 'id'): array
|
|
{
|
|
$qb = $this->createQueryBuilder();
|
|
if ($spec) {
|
|
$qb->andWhere($spec);
|
|
}
|
|
|
|
$slidersData = [];
|
|
foreach ($qb->execute() as $item) {
|
|
$index = $item[$indexBy];
|
|
|
|
if (!isset($slidersData[$index])) {
|
|
$slidersData[$index] = [
|
|
'id' => (int) $item['id'],
|
|
'name' => $item['name'],
|
|
'custom_data' => array_replace_recursive(
|
|
json_decode($item['slider_data'] ?: '', true) ?: [],
|
|
json_decode($item['slider_data2'] ?: '', true) ?: [],
|
|
),
|
|
'images' => [],
|
|
'_index' => $index,
|
|
];
|
|
|
|
if (!empty($item['id_section'])) {
|
|
$slidersData[$index]['id_section'] = $item['id_section'];
|
|
}
|
|
}
|
|
|
|
if (isset($item['id_photo'])) {
|
|
if ($item['figure'] === 'N') {
|
|
continue;
|
|
}
|
|
|
|
$photo = $this->imageLocator->getImage(
|
|
$this->getImageArrayFromItem($item),
|
|
);
|
|
|
|
$slidersData[$index]['images'][] = [
|
|
'id' => $item['id_slider_image'],
|
|
'link' => $item['link'],
|
|
'description' => $item['description'],
|
|
'image' => '/'.$this->pathFinder->dataPath('photos/'.$photo->getSource().$photo->getImageDesktop()),
|
|
'image_data' => json_decode($item['custom_data'] ?? '', true),
|
|
'photo' => $photo,
|
|
'custom_data' => array_replace_recursive(
|
|
json_decode($item['image_data'] ?: '', true) ?: [],
|
|
json_decode($item['image_data2'] ?: '', true) ?: [],
|
|
),
|
|
];
|
|
}
|
|
}
|
|
|
|
$sliders = [];
|
|
foreach ($slidersData as $index => $sliderData) {
|
|
$sliders[$index] = $slider = $this->entityUtil->createEntity($sliderData, Slider::class);
|
|
|
|
foreach ($slider->images as &$image) {
|
|
$image['slider'] = $slider;
|
|
}
|
|
}
|
|
|
|
return $sliders;
|
|
}
|
|
|
|
public function createQueryBuilder(): QueryBuilder
|
|
{
|
|
$qb = sqlQueryBuilder()
|
|
->from('sliders', 'sl');
|
|
|
|
foreach ($this->getSelectFields() as $alias => $column) {
|
|
$qb->addSelect("{$column} as {$alias}");
|
|
}
|
|
|
|
$qb->leftJoin('sl', 'sliders_images', 'si', 'si.id_slider=sl.id AND ((si.date_from < NOW() OR si.date_from IS NULL) AND (si.date_to > NOW() OR si.date_to IS NULL))')
|
|
->join('si', 'photos', 'ph', 'ph.id = si.id_photo')
|
|
->andWhere(Translation::coalesceTranslatedFields(SlidersTranslation::class, ['name' => 'name', 'data' => 'slider_data2']))
|
|
->andWhere(
|
|
Translation::coalesceTranslatedFields(
|
|
SlidersImagesTranslation::class,
|
|
[
|
|
'description' => 'description',
|
|
'link' => 'link',
|
|
'data' => 'image_data2',
|
|
'figure' => 'figure',
|
|
]
|
|
)
|
|
)
|
|
->andWhere(
|
|
Translation::coalesceTranslatedFields(
|
|
PhotosTranslation::class,
|
|
[
|
|
'descr' => 'photo_descr',
|
|
'image_2' => 'photo_image_2',
|
|
'image_tablet' => 'photo_image_tablet',
|
|
'image_mobile' => 'photo_image_mobile',
|
|
]
|
|
)
|
|
);
|
|
|
|
if (findModule(\Modules::VIDEOS)) {
|
|
$qb->leftJoin('ph', 'videos', 'v', 'v.id_photo = ph.id');
|
|
}
|
|
|
|
return $qb;
|
|
}
|
|
|
|
protected function getSelectFields(): array
|
|
{
|
|
$fields = [
|
|
'id' => 'sl.id',
|
|
'name' => 'sl.name',
|
|
'slider_data' => 'sl.data',
|
|
'link' => 'si.link',
|
|
'description' => 'si.description',
|
|
'id_slider_image' => 'si.id',
|
|
'id_photo' => 'si.id_photo',
|
|
'image_data' => 'si.data',
|
|
|
|
'photo_id' => 'ph.id',
|
|
'photo_filename' => 'ph.filename',
|
|
'photo_descr' => 'ph.descr',
|
|
'photo_source' => 'ph.source',
|
|
'photo_image_2' => 'ph.image_2',
|
|
'photo_image_tablet' => 'ph.image_tablet',
|
|
'photo_image_mobile' => 'ph.image_mobile',
|
|
'photo_date' => 'ph.date',
|
|
'photo_sync_id' => 'ph.sync_id',
|
|
'photo_date_update' => 'ph.date_update',
|
|
'custom_data' => 'ph.data',
|
|
];
|
|
|
|
if (findModule(\Modules::VIDEOS)) {
|
|
$fields['id_video'] = 'v.id_cdn';
|
|
}
|
|
|
|
return $fields;
|
|
}
|
|
|
|
private function getImageArrayFromItem(array $item): array
|
|
{
|
|
$image = [];
|
|
foreach ($item as $key => $value) {
|
|
if (StringUtil::startsWith($key, 'photo_') || $key == 'id_video') {
|
|
$image[ltrim($key, 'photo_')] = $value;
|
|
}
|
|
}
|
|
|
|
return $image;
|
|
}
|
|
|
|
/**
|
|
* @param array{position: string, id_section: int, id_slider: int} $positionsInSections
|
|
*
|
|
* @throws DBALException
|
|
*/
|
|
public function saveSliderPositions(array $positionsInSections, ?array $onDuplicateKeyUpdate = null): void
|
|
{
|
|
if (empty($positionsInSections)) {
|
|
return;
|
|
}
|
|
|
|
$validPositions = static::getPositions();
|
|
$types = [
|
|
'id_section' => Type::INTEGER,
|
|
'id_slider' => Type::INTEGER,
|
|
'position' => Type::STRING,
|
|
];
|
|
|
|
$qb = sqlQueryBuilder()->insert('sliders_in_sections');
|
|
foreach ($positionsInSections as $mapping) {
|
|
ksort($mapping);
|
|
|
|
if (!in_array($mapping['position'], array_keys($validPositions))) {
|
|
throw new \InvalidArgumentException("Invalid position '{$mapping['position']}'");
|
|
}
|
|
|
|
$qb->multiDirectValues($mapping, $types);
|
|
}
|
|
|
|
if ($onDuplicateKeyUpdate) {
|
|
$qb->onDuplicateKeyUpdate($onDuplicateKeyUpdate);
|
|
}
|
|
|
|
$qb->execute();
|
|
}
|
|
|
|
/**
|
|
* @throws DBALException|\InvalidArgumentException
|
|
*/
|
|
public function clearSliderSections(?int $idSlider = null, ?int $idSection = null): void
|
|
{
|
|
if (!isset($idSlider) && !isset($idSection)) {
|
|
throw new \InvalidArgumentException('Both $idSlider and $idSection cannot be empty');
|
|
}
|
|
|
|
$qb = sqlQueryBuilder()->delete('sliders_in_sections');
|
|
if (isset($idSlider)) {
|
|
$qb->andWhere(Operator::equals(['id_slider' => $idSlider]));
|
|
}
|
|
|
|
if (isset($idSection)) {
|
|
$qb->andWhere(Operator::equals(['id_section' => $idSection]));
|
|
}
|
|
|
|
$qb->execute();
|
|
}
|
|
|
|
/**
|
|
* @return Slider[]
|
|
*
|
|
* @throws DBALException|SerializerException
|
|
*/
|
|
public function getSectionSliders(int $sectionID): array
|
|
{
|
|
return $this->fetchSliders(
|
|
function (QueryBuilder $qb) use ($sectionID) {
|
|
$sectionPositions = sqlQueryBuilder()
|
|
->select('DISTINCT sis.id_slider', 'sis.position')
|
|
->from('sliders_in_sections', 'sis')
|
|
->andWhere(Operator::equals(['sis.id_section' => $sectionID]));
|
|
|
|
$qb->addSelect('sis.position AS section_position')
|
|
->joinSubQuery('sl', $sectionPositions, 'sis', 'sl.id = sis.id_slider');
|
|
},
|
|
indexBy: 'section_position',
|
|
);
|
|
}
|
|
|
|
public function getSliderPositions(?callable $spec = null): array
|
|
{
|
|
$qb = sqlQueryBuilder()
|
|
->select('sis.position AS section_position', 'sis.id_section', 'sis.id_slider', 'sl.name')
|
|
->from('sliders_in_sections', 'sis')
|
|
->leftJoin('sis', 'sliders', 'sl', 'sl.id = sis.id_slider')
|
|
->addGroupBy('sis.id_section', 'sis.position');
|
|
|
|
if ($spec !== null) {
|
|
$qb->andWhere($spec);
|
|
}
|
|
|
|
$mapped = [];
|
|
foreach ($qb->execute() as $positionInSection) {
|
|
$sectionID = $positionInSection['id_section'];
|
|
$position = $positionInSection['section_position'];
|
|
|
|
if (!isset($mapped[$sectionID])) {
|
|
$mapped[$sectionID] = [];
|
|
}
|
|
|
|
$mapped[$sectionID][$position] = $positionInSection;
|
|
}
|
|
|
|
return $mapped;
|
|
}
|
|
|
|
/**
|
|
* @return array Slider positions from config <code>($cfg['Modules']['sliders']['positions'])</code>
|
|
*/
|
|
public static function getPositions(): array
|
|
{
|
|
$positions = findModule(\Modules::SLIDERS, 'positions', default: []);
|
|
|
|
if (!array_key_exists('main', $positions)) {
|
|
$positions = array_merge(['main' => 'Hlavní'], $positions);
|
|
}
|
|
|
|
if (findModule(\Modules::SLIDERS, 'additional_section_slider')
|
|
&& !array_key_exists('additional', $positions)) {
|
|
$positions['additional'] = 'Vedlejší';
|
|
}
|
|
|
|
return $positions;
|
|
}
|
|
|
|
private static function specRandomSlider(bool $random): callable
|
|
{
|
|
return function (QueryBuilder $qb) use ($random) {
|
|
if ($random) {
|
|
$qb->orderBy('RAND()')
|
|
->setMaxResults(1);
|
|
} else {
|
|
$qb->orderBy('si.position');
|
|
}
|
|
};
|
|
}
|
|
}
|