<?php
namespace App\Entity\Repository;
use App\Entity\Page;
use App\Entity\Route;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Query;
use Gedmo\Translatable\Query\TreeWalker\TranslationWalker;
use Gedmo\Tree\Entity\Repository\NestedTreeRepository;
class PageRepository extends NestedTreeRepository
{
private bool $multilingual = false;
/** @return array<int, Page> */
public function getTree(): array
{
$queryBuilder = $this->getNodesHierarchyQueryBuilder();
$queryBuilder->orderBy('node.lft');
/** @var array<Page> $results */
$results = $queryBuilder->getQuery()->getResult();
return $results;
}
/**
* @param null $locale
*
* @return Page[]
*/
public function getHeaderNavigation($locale = null)
{
/** @var Page|null $headerNavigation */
$headerNavigation = $this->findOneBy([
'alias' => Page::GROUP_TYPE_HEADER_NAVIGATION,
]);
$pages = $this->getNavigation($headerNavigation, true, 'lft');
foreach ($pages as &$page) {
$this->filterChildrenByShowInMenu($page);
$this->realSymlink($page);
}
return $pages;
}
/** @return array<int, Page> */
public function getMenuForSnippet(Page $rootNode): array
{
$pages = $this->getNavigation($rootNode, true, 'lft');
foreach ($pages as &$page) {
$this->filterChildrenByShowInMenu($page);
$this->realSymlink($page);
}
return $pages;
}
private function filterChildrenByShowInMenu(Page $page): Page
{
/** @var ArrayCollection $children */
$children = $page->getChildren()->filter(function (Page $page) {
return $page->isShowInMenu();
});
$page->setChildren($children);
foreach ($page->getChildren() as $child) {
$this->filterChildrenByShowInMenu($child);
}
return $page;
}
public function getSearchableCriteria(string $alias): Criteria
{
return Criteria::create()
->where(Criteria::expr()->eq($alias.'.concept', false));
}
/**
* @return Page[]
*/
public function getFooterNavigation(?string $locale = null)
{
/** @var Page|null $footerNavigation */
$footerNavigation = $this->findOneBy([
'alias' => Page::GROUP_TYPE_FOOTER_NAVIGATION,
]);
if (!$footerNavigation instanceof Page) {
return [];
}
$pages = $this->getNavigation($footerNavigation, false, 'lft');
foreach ($pages as &$page) {
if (\is_string($locale)) {
$page->setRoutes($page->getRoutes()->filter(function (Route $route) use ($locale) {
return $route->getLocale() === $locale;
}));
if (Page::PAGETYPE_SYMLINK === $page->getType()) {
$symLinkedPage = $page->getSymlinkedPage();
$symLinkedPage->setRoutes($symLinkedPage->getRoutes()
->filter(function (Route $route) use ($locale) {
return $route->getLocale() === $locale;
}));
}
}
$this->realSymlink($page);
}
return $pages;
}
/**
* @param null $locale
*
* @return Page[]
*/
public function getFooterBottomNavigation($locale = null)
{
/** @var Page|null $footerBottomNavigation */
$footerBottomNavigation = $this->findOneBy([
'alias' => Page::GROUP_TYPE_FOOTER_BOTTOM_NAVIGATION,
]);
if (!$footerBottomNavigation instanceof Page) {
return [];
}
$pages = $this->getNavigation($footerBottomNavigation, false, 'lft');
foreach ($pages as &$page) {
if ($locale) {
$page->setRoutes($page->getRoutes()->filter(function (Route $route) use ($locale) {
return $route->getLocale() === $locale;
}));
if (Page::PAGETYPE_SYMLINK === $page->getType()) {
$symLinkedPage = $page->getSymlinkedPage();
if (!$symLinkedPage instanceof Page) {
continue;
}
$symLinkedPage->setRoutes($symLinkedPage->getRoutes()
->filter(function (Route $route) use ($locale) {
return $route->getLocale() === $locale;
}));
}
}
$this->realSymlink($page);
}
return $pages;
}
/**
* @param null $locale
*
* @return Page[]
*/
public function getTopNavigation($locale = null)
{
/** @var Page|null $topNavigation */
$topNavigation = $this->findOneBy([
'alias' => Page::GROUP_TYPE_WEBRING,
]);
/** @var array<int, Page> $pages */
$pages = $this->getNavigation($topNavigation, true, 'lft');
foreach ($pages as &$page) {
if ($locale) {
$page->setRoutes($page->getRoutes()->filter(function (Route $route) use ($locale) {
return $route->getLocale() === $locale;
}));
if (Page::PAGETYPE_SYMLINK === $page->getType()) {
$symLinkedPage = $page->getSymlinkedPage();
if (null === $symLinkedPage) {
continue;
}
$symLinkedPage->setRoutes($symLinkedPage->getRoutes()
->filter(function (Route $route) use ($locale) {
return $route->getLocale() === $locale;
}));
}
}
$this->filterChildrenByShowInMenu($page);
$this->realSymlink($page);
}
return $pages;
}
public function findDeleted(): array
{
$this->_em->getFilters()->disable('softdeleteable');
$qb = $this->createQueryBuilder('p');
$qb->where('p.deletedAt IS NOT NULL')
->andWhere('p.type = :type')
->setParameter('type', 'page');
return $qb->getQuery()
->getResult();
}
/**
* @throws \Doctrine\ORM\NoResultException
* @throws \Doctrine\ORM\NonUniqueResultException
*/
public function findOneDeleted(int $id): Page
{
$this->_em->getFilters()->disable('softdeleteable');
$qb = $this->createQueryBuilder('p');
$qb->where('p.id = :id')
->setParameter('id', $id);
return $qb->getQuery()
->getSingleResult();
}
private function realSymlink(Page $page)
{
if (
'symlink' === $page->getType() &&
$page->getSymlinkedPage()->getRoutes()->first() &&
'' !== $page->getSymlinkedPage()->getRoutes()->first()->getName() &&
null !== $page->getSymlinkedPage()
) {
foreach ($page->getSymlinkedPage()->getRoutes() as &$route) {
$route->setName(
str_replace(Route::ALIAS_PREFIX, '', $route->getName())
);
}
}
return $page;
}
/**
* @param Page|null $node
* @param bool $direct
* @param string|null $sortByField
* @param string $direction
* @param false $includeNode
*
* @return array<int, Page>
*/
public function getNavigation(
$node = null,
$direct = false,
$sortByField = null,
$direction = 'ASC',
$includeNode = false,
) {
$queryBuilder = $this->getChildrenQueryBuilder(
$node,
$direct,
$sortByField,
$direction,
$includeNode
);
$queryBuilder->andWhere('node.showInMenu = true');
$queryBuilder->leftJoin('node.routes', 'routes');
$queryBuilder->addSelect('routes');
$query = $queryBuilder->getQuery();
if ($this->multilingual) {
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, TranslationWalker::class);
}
return $query->getResult();
}
/**
* Temporary solution to set multilingual.
*/
public function setMultilingual(bool $multilingual)
{
$this->multilingual = $multilingual;
}
}