Skip to content

Instantly share code, notes, and snippets.

@wizhippo
Created August 6, 2014 15:38
Show Gist options
  • Save wizhippo/530e412becdb821d145c to your computer and use it in GitHub Desktop.
Save wizhippo/530e412becdb821d145c to your computer and use it in GitHub Desktop.
<?php
namespace MyBundle\Menu;
use eZ\Publish\API\Repository\LocationService;
use eZ\Publish\Core\MVC\ConfigResolverInterface;
use eZ\Publish\API\Repository\SearchService;
use eZ\Publish\API\Repository\Values\Content\Location;
use eZ\Publish\API\Repository\Values\Content\LocationQuery;
use eZ\Publish\API\Repository\Values\Content\Query;
use eZ\Publish\API\Repository\Values\Content\Query\Criterion;
use eZ\Publish\API\Repository\Values\Content\Search\SearchHit;
use Knp\Menu\FactoryInterface;
use Knp\Menu\ItemInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouterInterface;
use eZ\Publish\Core\Helper\TranslationHelper;
use eZ\Publish\API\Repository\ContentService;
/**
* A simple eZ Publish menu provider.
*
* Generates a two level menu, starting from the configured root node.
* Locations below the root node and until a relative depth of 2 are included.
* Only visible locations with a ContentType included in `MenuContentSettings.TopIdentifierList` in legacy's `menu.ini`
* are included.
*/
class Builder
{
/**
* @var FactoryInterface
*/
private $factory;
/**
* @var SearchService
*/
private $searchService;
/**
* @var RouterInterface
*/
private $router;
/**
* @var ConfigResolverInterface
*/
private $configResolver;
/**
* @var LocationService
*/
private $locationService;
/**
* @var TranslationHelper
*/
private $translationHelper;
/**
* @var ContentService
*/
private $contentService;
public function __construct(
FactoryInterface $factory,
SearchService $searchService,
RouterInterface $router,
ConfigResolverInterface $configResolver,
LocationService $locationService,
TranslationHelper $translationHelper,
ContentService $contentService
)
{
$this->factory = $factory;
$this->searchService = $searchService;
$this->router = $router;
$this->configResolver = $configResolver;
$this->locationService = $locationService;
$this->translationHelper = $translationHelper;
$this->contentService = $contentService;
}
public function createTopMenu( Request $request )
{
$menu = $this->factory->createItem( 'root' );
$this->addLocationsToMenu(
$menu,
$this->getMenuItems(
$this->configResolver->getParameter( 'content.tree_root.location_id' )
)
);
return $menu;
}
/**
* Adds locations from $searchHit to $menu
*
* @param ItemInterface $menu
* @param SearchHit[] $searchHits
* @return void
*/
private function addLocationsToMenu( ItemInterface $menu, array $searchHits )
{
foreach ( $searchHits as $searchHit )
{
/** @var Location $location */
$location = $searchHit->valueObject;
$menuItem = isset( $menu[$location->parentLocationId] ) ? $menu[$location->parentLocationId] : $menu;
if ( $location->contentInfo->contentTypeId === 11 ) {
$content = $this->contentService->loadContentByContentInfo($location->contentInfo);
$uri = $content->getFieldValue( 'location' );
} else {
$uri = $this->router->generate( $location );
}
$menuItem->addChild(
$location->id,
array(
'label' => $this->translationHelper->getTranslatedContentNameByContentInfo( $location->contentInfo ),
'uri' => $uri,
'attributes' => array(
'id' => 'nav-location-' . $location->id,
'class' => 'content-type-' . $location->contentInfo->contentTypeId
)
)
);
$menuItem->setChildrenAttribute( 'class', 'nav' );
}
}
/**
* Queries the repository for menu items, as locations filtered on the list in TopIdentifierList in menu.ini
* @param int|string $rootLocationId Root location for menu items. Only two levels below this one are searched
* @return SearchHit[]
*/
private function getMenuItems( $rootLocationId )
{
$rootLocation = $this->locationService->loadLocation( $rootLocationId );
$query = new LocationQuery();
$query->query = new Criterion\LogicalAnd(
array(
new Criterion\ContentTypeIdentifier( $this->getTopMenuContentTypeIdentifierList() ),
new Criterion\Visibility( Criterion\Visibility::VISIBLE ),
new Criterion\Location\Depth(
Criterion\Operator::BETWEEN,
array( $rootLocation->depth + 1, $rootLocation->depth + 2 )
),
new Criterion\Subtree( $rootLocation->pathString ),
new Criterion\LanguageCode( $this->configResolver->getParameter( 'languages' ) )
)
);
$query->sortClauses = array( new Query\SortClause\Location\Path() );
return $this->searchService->findLocations( $query )->searchHits;
}
private function getTopMenuContentTypeIdentifierList()
{
return $this->configResolver->getParameter( 'MenuContentSettings.TopIdentifierList', 'menu' );
}
}
services:
mybundle.menu.builder:
class: MyBundle\Menu\Builder
arguments:
- @knp_menu.factory
- @ezpublish.api.service.search
- @router
- @ezpublish.config.resolver
- @ezpublish.api.service.location
- @ezpublish.translation_helper
- @ezpublish.api.service.content
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment