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 $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; } }