Skip to content

Commit

Permalink
EZP-22735: Make {{ path( ez_urlalias ) }} polymorphic
Browse files Browse the repository at this point in the history
  • Loading branch information
emodric committed Nov 3, 2014
1 parent 7f11bf7 commit 1d02973
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 19 deletions.
1 change: 1 addition & 0 deletions eZ/Bundle/EzPublishCoreBundle/Resources/config/routing.yml
Expand Up @@ -44,6 +44,7 @@ services:
arguments:
- @ezpublish.api.service.location
- @ezpublish.api.service.url_alias
- @ezpublish.api.service.content
- @ezpublish.urlalias_generator
- @?router.request_context
- @?logger
Expand Down
Expand Up @@ -11,6 +11,7 @@

use eZ\Publish\API\Repository\LocationService;
use eZ\Publish\API\Repository\URLAliasService;
use eZ\Publish\API\Repository\ContentService;
use Symfony\Component\Routing\RequestContext;
use eZ\Bundle\EzPublishCoreBundle\Routing\UrlAliasRouter;
use eZ\Publish\API\Repository\Values\Content\URLAlias;
Expand Down Expand Up @@ -43,9 +44,9 @@ protected function setUp()
parent::setUp();
}

protected function getRouter( LocationService $locationService, URLAliasService $urlAliasService, UrlAliasGenerator $urlAliasGenerator, RequestContext $requestContext )
protected function getRouter( LocationService $locationService, URLAliasService $urlAliasService, ContentService $contentService, UrlAliasGenerator $urlAliasGenerator, RequestContext $requestContext )
{
$router = new UrlAliasRouter( $locationService, $urlAliasService, $urlAliasGenerator, $requestContext );
$router = new UrlAliasRouter( $locationService, $urlAliasService, $contentService, $urlAliasGenerator, $requestContext );
$router->setConfigResolver( $this->configResolver );
return $router;
}
Expand Down
80 changes: 77 additions & 3 deletions eZ/Publish/Core/MVC/Symfony/Routing/Tests/UrlAliasRouterTest.php
Expand Up @@ -11,6 +11,7 @@

use eZ\Publish\API\Repository\LocationService;
use eZ\Publish\API\Repository\URLAliasService;
use eZ\Publish\API\Repository\ContentService;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\HttpFoundation\Request;
use eZ\Publish\API\Repository\Values\Content\URLAlias;
Expand All @@ -19,6 +20,9 @@
use eZ\Publish\Core\MVC\Symfony\Routing\UrlAliasRouter;
use eZ\Publish\Core\MVC\Symfony\SiteAccess;
use eZ\Publish\Core\Repository\Values\Content\Location;
use eZ\Publish\API\Repository\Values\Content\ContentInfo;
use eZ\Publish\Core\Repository\Values\Content\Content;
use eZ\Publish\Core\Repository\Values\Content\VersionInfo;
use eZ\Publish\Core\MVC\Symfony\View\Manager as ViewManager;
use PHPUnit_Framework_TestCase;

Expand All @@ -39,6 +43,11 @@ class UrlAliasRouterTest extends PHPUnit_Framework_TestCase
*/
protected $locationService;

/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
protected $contentService;

/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
Expand Down Expand Up @@ -67,6 +76,7 @@ protected function setUp()
->getMock();
$this->urlAliasService = $this->getMock( 'eZ\\Publish\\API\\Repository\\URLAliasService' );
$this->locationService = $this->getMock( 'eZ\\Publish\\API\\Repository\\LocationService' );
$this->contentService = $this->getMock( 'eZ\\Publish\\API\\Repository\\ContentService' );
$this->urlALiasGenerator = $this
->getMockBuilder( 'eZ\\Publish\\Core\\MVC\\Symfony\\Routing\\Generator\\UrlAliasGenerator' )
->setConstructorArgs(
Expand All @@ -79,20 +89,21 @@ protected function setUp()
->getMock();
$this->requestContext = new RequestContext();

$this->router = $this->getRouter( $this->locationService, $this->urlAliasService, $this->urlALiasGenerator, $this->requestContext );
$this->router = $this->getRouter( $this->locationService, $this->urlAliasService, $this->contentService, $this->urlALiasGenerator, $this->requestContext );
}

/**
* @param \eZ\Publish\API\Repository\LocationService $locationService
* @param \eZ\Publish\API\Repository\URLAliasService $urlAliasService
* @param \eZ\Publish\API\Repository\ContentService $contentService
* @param UrlAliasGenerator $urlAliasGenerator
* @param RequestContext $requestContext
*
* @return UrlAliasRouter
*/
protected function getRouter( LocationService $locationService, URLAliasService $urlAliasService, UrlAliasGenerator $urlAliasGenerator, RequestContext $requestContext )
protected function getRouter( LocationService $locationService, URLAliasService $urlAliasService, ContentService $contentService, UrlAliasGenerator $urlAliasGenerator, RequestContext $requestContext )
{
return new UrlAliasRouter( $locationService, $urlAliasService, $urlAliasGenerator, $requestContext );
return new UrlAliasRouter( $locationService, $urlAliasService, $contentService, $urlAliasGenerator, $requestContext );
}

/**
Expand Down Expand Up @@ -666,4 +677,67 @@ public function testGenerateWithLocationAsParameter()
)
);
}

/**
* @covers eZ\Publish\Core\MVC\Symfony\Routing\UrlAliasRouter::__construct
* @covers eZ\Publish\Core\MVC\Symfony\Routing\UrlAliasRouter::generate
*/
public function testGenerateWithContentId()
{
$locationId = 123;
$contentId = 456;
$location = new Location( array( 'id' => $locationId ) );
$contentInfo = new ContentInfo( array( 'id' => $contentId, 'mainLocationId' => $locationId ) );
$parameters = array( 'some' => 'thing' );
$absolute = false;
$generatedLink = '/foo/bar';
$this->contentService
->expects( $this->once() )
->method( 'loadContentInfo' )
->with( $contentId )
->will( $this->returnValue( $contentInfo ) );
$this->locationService
->expects( $this->once() )
->method( 'loadLocation' )
->with( $contentInfo->mainLocationId )
->will( $this->returnValue( $location ) );
$this->urlALiasGenerator
->expects( $this->once() )
->method( 'generate' )
->with( $location, $parameters, $absolute )
->will( $this->returnValue( $generatedLink ) );
$this->assertSame(
$generatedLink,
$this->router->generate(
UrlAliasRouter::URL_ALIAS_ROUTE_NAME,
$parameters + array( 'contentId' => $contentId ),
$absolute
)
);
}

/**
* @covers eZ\Publish\Core\MVC\Symfony\Routing\UrlAliasRouter::__construct
* @covers eZ\Publish\Core\MVC\Symfony\Routing\UrlAliasRouter::generate
*
* @expectedException \LogicException
*/
public function testGenerateWithContentIdWithMissingMainLocation()
{
$contentId = 456;
$contentInfo = new ContentInfo( array( 'id' => $contentId, 'mainLocationId' => null ) );
$parameters = array( 'some' => 'thing' );
$absolute = false;
$this->contentService
->expects( $this->once() )
->method( 'loadContentInfo' )
->with( $contentId )
->will( $this->returnValue( $contentInfo ) );

$this->router->generate(
UrlAliasRouter::URL_ALIAS_ROUTE_NAME,
$parameters + array( 'contentId' => $contentId ),
$absolute
);
}
}
49 changes: 35 additions & 14 deletions eZ/Publish/Core/MVC/Symfony/Routing/UrlAliasRouter.php
Expand Up @@ -11,6 +11,7 @@

use eZ\Publish\API\Repository\LocationService;
use eZ\Publish\API\Repository\URLAliasService;
use eZ\Publish\API\Repository\ContentService;
use eZ\Publish\API\Repository\Values\Content\URLAlias;
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
use eZ\Publish\API\Repository\Values\Content\Location;
Expand All @@ -26,6 +27,8 @@
use Symfony\Component\Routing\Route as SymfonyRoute;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use InvalidArgumentException;
use LogicException;

class UrlAliasRouter implements ChainedRouterInterface, RequestMatcherInterface
{
Expand All @@ -49,9 +52,9 @@ class UrlAliasRouter implements ChainedRouterInterface, RequestMatcherInterface
protected $urlAliasService;

/**
* @var \eZ\Publish\API\Repository\Repository
* @var \eZ\Publish\API\Repository\ContentService
*/
protected $repository;
protected $contentService;

/**
* @var \eZ\Publish\Core\MVC\Symfony\Routing\Generator\UrlAliasGenerator
Expand All @@ -73,13 +76,15 @@ class UrlAliasRouter implements ChainedRouterInterface, RequestMatcherInterface
public function __construct(
LocationService $locationService,
URLAliasService $urlAliasService,
ContentService $contentService,
UrlAliasGenerator $generator,
RequestContext $requestContext,
LoggerInterface $logger = null
)
{
$this->locationService = $locationService;
$this->urlAliasService = $urlAliasService;
$this->contentService = $contentService;
$this->generator = $generator;
$this->requestContext = $requestContext !== null ? $requestContext : new RequestContext();
$this->logger = $logger;
Expand Down Expand Up @@ -311,25 +316,41 @@ public function generate( $name, $parameters = array(), $absolute = false )
// Normal route name
if ( $name === self::URL_ALIAS_ROUTE_NAME )
{
// We must have at least 'location' or 'locationId' to retrieve the UrlAlias
if ( !isset( $parameters['location'] ) && !isset( $parameters['locationId'] ) )
if ( isset( $parameters['location'] ) || isset( $parameters['locationId'] ) )
{
throw new \InvalidArgumentException(
"When generating an UrlAlias route, either 'location' or 'locationId must be provided."
);
// Check if location is a valid Location object
if ( isset( $parameters['location'] ) && !$parameters['location'] instanceof Location )
{
throw new LogicException(
"When generating an UrlAlias route, 'location' parameter must be a valid eZ\\Publish\\API\\Repository\\Values\\Content\\Location."
);
}

$location = isset( $parameters['location'] ) ? $parameters['location'] : $this->locationService->loadLocation( $parameters['locationId'] );
unset( $parameters['location'], $parameters['locationId'], $parameters['viewType'], $parameters['layout'] );
return $this->generator->generate( $location, $parameters, $absolute );
}

// Check if location is a valid Location object
if ( isset( $parameters['location'] ) && !$parameters['location'] instanceof Location )
if ( isset( $parameters['contentId'] ) )
{
throw new \LogicException(
"When generating an UrlAlias route, 'location' parameter must be a valid eZ\\Publish\\API\\Repository\\Values\\Content\\Location."
$contentInfo = $this->contentService->loadContentInfo( $parameters['contentId'] );
unset( $parameters['contentId'], $parameters['viewType'], $parameters['layout'] );

if ( empty( $contentInfo->mainLocationId ) )
{
throw new LogicException( "Cannot generate an UrlAlias route for content without main location." );
}

return $this->generator->generate(
$this->locationService->loadLocation( $contentInfo->mainLocationId ),
$parameters,
$absolute
);
}

$location = isset( $parameters['location'] ) ? $parameters['location'] : $this->locationService->loadLocation( $parameters['locationId'] );
unset( $parameters['location'], $parameters['locationId'], $parameters['viewType'], $parameters['layout'] );
return $this->generator->generate( $location, $parameters, $absolute );
throw new InvalidArgumentException(
"When generating an UrlAlias route, either 'location', 'locationId' or 'contentId' must be provided."
);
}

throw new RouteNotFoundException( 'Could not match route' );
Expand Down

0 comments on commit 1d02973

Please sign in to comment.