170 lines
5.4 KiB
PHP
170 lines
5.4 KiB
PHP
<?php
|
|
|
|
namespace KupShop\ContentBundle\Util;
|
|
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use KupShop\ContentBundle\Entity\Page;
|
|
use KupShop\I18nBundle\Translations\MenuLinksTranslation;
|
|
use Query\Operator;
|
|
use Query\QueryBuilder;
|
|
use Query\Translation;
|
|
|
|
class MenuLinksPage
|
|
{
|
|
private const MAX_RECURSIVE_DEPTH = 50;
|
|
|
|
private $entityManager;
|
|
|
|
public function __construct(EntityManagerInterface $entityManager)
|
|
{
|
|
$this->entityManager = $entityManager;
|
|
}
|
|
|
|
public function getPages(?int $parentId = null): array
|
|
{
|
|
$qb = $this->getBasePageQueryBuilder()
|
|
->andWhere(Operator::equalsNullable(['ml.parent' => $parentId]))
|
|
->orderBy('list_order', 'ASC');
|
|
|
|
$pages = [];
|
|
foreach ($qb->execute() as $item) {
|
|
$pages[$item['id']] = $this->createPageEntity($item);
|
|
$pages[$item['id']]->setChildren(
|
|
$this->getPages($item['id'])
|
|
);
|
|
}
|
|
|
|
return $pages;
|
|
}
|
|
|
|
public function getPage(int $menuLinkId): ?Page
|
|
{
|
|
if (!($page = $this->getBasePageQueryBuilder()
|
|
->andWhere(Operator::equals(['ml.id' => $menuLinkId]))
|
|
->execute()->fetchAssociative())) {
|
|
return null;
|
|
}
|
|
|
|
return $this->createPageEntity($page);
|
|
}
|
|
|
|
public function createPageEntity(array $page, bool $withBlock = true): Page
|
|
{
|
|
$pageEntity = new Page();
|
|
$pageData = array_replace_recursive(json_decode($page['data'], true) ?: [], json_decode($page['data_translated'], true) ?: []);
|
|
$pageEntity->setId($page['id'])
|
|
->setType((int) $page['type'])
|
|
->setParentId($page['parent'] ? (int) $page['parent'] : null)
|
|
->setName($page['name'])
|
|
->setNameShort($page['name_short'])
|
|
->setTemplate($page['template'])
|
|
->setMetaTitle($page['meta_title'] ?: '')
|
|
->setMetaKeywords($page['meta_keywords'] ?: '')
|
|
->setMetaDescription($page['meta_description'] ?: '')
|
|
->setOldIdPage($page['old_id_page'] ?: '')
|
|
->setFigure($page['figure'])
|
|
->setShowInSearch($page['show_in_search'] ?? 'Y')
|
|
->setUrl($page['url'])
|
|
->setLink($page['link'])
|
|
->setTarget($page['target'])
|
|
->setData($pageData);
|
|
|
|
if ($withBlock && !empty($page['id_block'])) {
|
|
$block = $this->entityManager->getRepository(\KupShop\ContentBundle\Entity\Block::class);
|
|
$pageEntity->setBlock($block->find($page['id_block']));
|
|
}
|
|
|
|
return $pageEntity;
|
|
}
|
|
|
|
protected function getBasePageQueryBuilder(): QueryBuilder
|
|
{
|
|
return sqlQueryBuilder()->select('ml.*')
|
|
->from('menu_links', 'ml')
|
|
->andWhere(Translation::coalesceTranslatedFields(MenuLinksTranslation::class,
|
|
function ($columns) {
|
|
$columns['data'] = 'data_translated';
|
|
|
|
return $columns;
|
|
}));
|
|
}
|
|
|
|
public function getPageWithChildren(string $label, bool $withBlocks = true): ?Page
|
|
{
|
|
$pagesResult = $this->createRecursiveQueryBuilder($label)->execute();
|
|
|
|
if (!$rawRootPage = $pagesResult->fetchAssociative()) {
|
|
return null;
|
|
}
|
|
|
|
$rootPage = $this->createPageEntity($rawRootPage, $withBlocks);
|
|
$pagesIterator = $pagesResult->fetchAllAssociative();
|
|
|
|
$this->buildTree([$rootPage->getId() => $rootPage], $pagesIterator, withBlocks: $withBlocks);
|
|
|
|
return $rootPage;
|
|
}
|
|
|
|
/**
|
|
* @param array<int, Page> $parentPages
|
|
*/
|
|
protected function buildTree(array $parentPages, array $restPages, int $depth = 1, bool $withBlocks = true): void
|
|
{
|
|
if (empty($parentPages)) {
|
|
return;
|
|
}
|
|
|
|
$currentLevelPages = [];
|
|
|
|
$i = 0;
|
|
foreach ($restPages as $pageRow) {
|
|
if ($pageRow['level'] > $depth) {
|
|
$this->buildTree($currentLevelPages, array_slice($restPages, $i), $depth + 1, $withBlocks);
|
|
|
|
break;
|
|
}
|
|
|
|
$i++;
|
|
|
|
$page = $this->createPageEntity($pageRow, $withBlocks);
|
|
|
|
$currentLevelPages[$page->getId()] = $page;
|
|
$parentPages[$page->getParentId()]->appendChild($page);
|
|
}
|
|
}
|
|
|
|
protected function createRecursiveQueryBuilder(string $label, ?int $depth = null): QueryBuilder
|
|
{
|
|
// language=MariaDB
|
|
$recursiveQuery = <<<__SQL__
|
|
WITH RECURSIVE cte AS (
|
|
SELECT *,
|
|
0 as level
|
|
FROM menu_links
|
|
WHERE code = :label
|
|
UNION ALL
|
|
SELECT ml.*,
|
|
cte.level + 1 AS level
|
|
FROM menu_links ml
|
|
INNER JOIN cte ON ml.parent = cte.id WHERE level < :depth
|
|
) SELECT * FROM cte
|
|
__SQL__;
|
|
|
|
$qb = sqlQueryBuilder()
|
|
->select('ml.*')
|
|
->from("({$recursiveQuery})", 'ml')
|
|
->setParameter('depth', $depth ?? self::MAX_RECURSIVE_DEPTH)
|
|
->setParameter('label', $label)
|
|
->andWhere(Translation::coalesceTranslatedFields(MenuLinksTranslation::class,
|
|
static function ($columns) {
|
|
$columns['data'] = 'data_translated';
|
|
|
|
return $columns;
|
|
}))
|
|
->addOrderBy('ml.level')
|
|
->addOrderBy('ml.list_order');
|
|
|
|
return $qb;
|
|
}
|
|
}
|