Skip to content

Commit

Permalink
added urls parameter to serialization (#187)
Browse files Browse the repository at this point in the history
  • Loading branch information
wachterjohannes authored and alexander-schranz committed Jun 12, 2017
1 parent f0ea23e commit 1375f63
Show file tree
Hide file tree
Showing 3 changed files with 278 additions and 2 deletions.
133 changes: 133 additions & 0 deletions Document/Serializer/WebsiteArticleUrlsSubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<?php

/*
* This file is part of Sulu.
*
* (c) MASSIVE ART WebServices GmbH
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Sulu\Bundle\ArticleBundle\Document\Serializer;

use Doctrine\ORM\NoResultException;
use JMS\Serializer\EventDispatcher\Events;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\ObjectEvent;
use Sulu\Bundle\ArticleBundle\Document\ArticleDocument;
use Sulu\Bundle\RouteBundle\Entity\RouteRepositoryInterface;
use Sulu\Bundle\RouteBundle\Model\RouteInterface;
use Sulu\Component\Webspace\Analyzer\Attributes\RequestAttributes;
use Sulu\Component\Webspace\Webspace;
use Symfony\Component\HttpFoundation\RequestStack;

/**
* Add the urls to the serialized result.
*/
class WebsiteArticleUrlsSubscriber implements EventSubscriberInterface
{
/**
* @var RequestStack
*/
private $requestStack;

/**
* @var RouteRepositoryInterface
*/
private $routeRepository;

/**
* @param RequestStack $requestStack
* @param RouteRepositoryInterface $routeRepository
*/
public function __construct(RequestStack $requestStack, RouteRepositoryInterface $routeRepository)
{
$this->requestStack = $requestStack;
$this->routeRepository = $routeRepository;
}

/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [
[
'event' => Events::POST_SERIALIZE,
'format' => 'array',
'method' => 'addUrlsOnPostSerialize',
],
];
}

/**
* Loops thru current webspace locales and generates routes for them.
*
* @param ObjectEvent $event
*/
public function addUrlsOnPostSerialize(ObjectEvent $event)
{
$article = $event->getObject();
$visitor = $event->getVisitor();
$context = $event->getContext();
$request = $this->requestStack->getCurrentRequest();

if (!$article instanceof ArticleDocument || !$context->attributes->containsKey('website') || !$request) {
return;
}

/** @var RequestAttributes $attributes */
$attributes = $request->get('_sulu');
if (!$attributes) {
return;
}

/** @var Webspace $webspace */
$webspace = $attributes->getAttribute('webspace');
if (!$webspace) {
return;
}

$urls = [];
foreach ($webspace->getAllLocalizations() as $localization) {
$locale = $localization->getLocale();
$route = $this->findByEntity(get_class($article), $article->getUuid(), $locale);

$urls[$locale] = '/';
if ($route) {
$urls[$locale] = $route->getPath();
}
}

$visitor->addData('urls', $context->accept($urls));
}

/**
* Return route for given entity information.
*
* @param string $entityClass
* @param string $entityId
* @param string $locale
*
* TODO replace this with $this->routeRepository->findByEntity when merging to develop
*
* @return RouteInterface
*/
private function findByEntity($entityClass, $entityId, $locale)
{
$query = $this->routeRepository->createQueryBuilder('entity')
->andWhere('entity.entityClass = :entityClass')
->andWhere('entity.entityId = :entityId')
->andWhere('entity.locale = :locale')
->andWhere('entity.history = false')
->getQuery()
->setParameters(['entityClass' => $entityClass, 'entityId' => $entityId, 'locale' => $locale]);

try {
return $query->getSingleResult();
} catch (NoResultException $e) {
return;
}
}
}
12 changes: 10 additions & 2 deletions Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,14 @@
<argument type="service" id="sulu.content.type_manager"/>
<argument type="service" id="sulu_article.content.data_provider.proxy_factory"/>

<tag name="jms_serializer.event_subscriber" />
<tag name="jms_serializer.event_subscriber"/>
</service>
<service id="sulu_article.serializer.urls"
class="Sulu\Bundle\ArticleBundle\Document\Serializer\WebsiteArticleUrlsSubscriber">
<argument type="service" id="request_stack"/>
<argument type="service" id="sulu.repository.route"/>

<tag name="jms_serializer.event_subscriber"/>
</service>
<service id="sulu_article.routing.default_provider"
class="Sulu\Bundle\ArticleBundle\Routing\ArticleRouteDefaultProvider">
Expand Down Expand Up @@ -193,7 +200,8 @@
</service>

<!-- preview -->
<service id="sulu_article.preview.object_provider" class="Sulu\Bundle\ArticleBundle\Preview\ArticleObjectProvider">
<service id="sulu_article.preview.object_provider"
class="Sulu\Bundle\ArticleBundle\Preview\ArticleObjectProvider">
<argument type="service" id="sulu_document_manager.document_manager"/>
<argument type="service" id="serializer"/>

Expand Down
135 changes: 135 additions & 0 deletions Tests/Unit/Document/Serializer/WebsiteArticleUrlsSubscriberTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<?php

/*
* This file is part of Sulu.
*
* (c) MASSIVE ART WebServices GmbH
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Sulu\Bundle\ArticleBundle\Tests\Unit\Document\Serializer;

use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\QueryBuilder;
use JMS\Serializer\EventDispatcher\ObjectEvent;
use JMS\Serializer\SerializationContext;
use PhpCollection\Map;
use Sulu\Bundle\ArticleBundle\Document\ArticleDocument;
use Sulu\Bundle\ArticleBundle\Document\Serializer\WebsiteArticleUrlsSubscriber;
use Sulu\Bundle\RouteBundle\Entity\RouteRepository;
use Sulu\Bundle\RouteBundle\Entity\RouteRepositoryInterface;
use Sulu\Bundle\RouteBundle\Model\RouteInterface;
use Sulu\Component\Localization\Localization;
use Sulu\Component\Serializer\ArraySerializationVisitor;
use Sulu\Component\Webspace\Analyzer\Attributes\RequestAttributes;
use Sulu\Component\Webspace\Webspace;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;

class WebsiteArticleUrlsSubscriberTest extends \PHPUnit_Framework_TestCase
{
/**
* @var RequestStack
*/
private $requestStack;

/**
* @var RouteRepositoryInterface
*/
private $routeRepository;

/**
* @var WebsiteArticleUrlsSubscriber
*/
private $urlsSubscriber;

/**
* {@inheritdoc}
*/
protected function setUp()
{
$this->requestStack = $this->prophesize(RequestStack::class);
$this->routeRepository = $this->prophesize(RouteRepository::class);

$this->urlsSubscriber = new WebsiteArticleUrlsSubscriber(
$this->requestStack->reveal(),
$this->routeRepository->reveal()
);

$webspace = new Webspace();
$webspace->addLocalization(new Localization('en'));
$webspace->addLocalization(new Localization('de'));

$request = $this->prophesize(Request::class);
$request->get('_sulu')->willReturn(new RequestAttributes(['webspace' => $webspace]));
$this->requestStack->getCurrentRequest()->willReturn($request->reveal());
}

public function testAddUrlsOnPostSerialize()
{
$article = $this->prophesize(ArticleDocument::class);
$visitor = $this->prophesize(ArraySerializationVisitor::class);
$context = $this->prophesize(SerializationContext::class);

$entityId = '123-123-123';
$article->getUuid()->willReturn($entityId);

$contextAttributes = $this->prophesize(Map::class);
$contextAttributes->containsKey('website')->willReturn(true);
$context->reveal()->attributes = $contextAttributes->reveal();

$event = $this->prophesize(ObjectEvent::class);
$event->getObject()->willReturn($article->reveal());
$event->getVisitor()->willReturn($visitor->reveal());
$event->getContext()->willReturn($context->reveal());

$expected = ['de' => '/seite', 'en' => '/page'];
$query = $this->mockQuery();

$entityClass = get_class($article->reveal());
foreach ($expected as $locale => $path) {
$route = $this->prophesize(RouteInterface::class);
$route->getPath()->willReturn($path);

$localedQuery = $this->prophesize(AbstractQuery::class);
$query->setParameters(['entityClass' => $entityClass, 'entityId' => $entityId, 'locale' => $locale])
->willReturn($localedQuery->reveal());

$localedQuery->getSingleResult()->willReturn($route->reveal());
}

$context->accept($expected)->willReturn($expected)->shouldBeCalled();
$visitor->addData('urls', $expected)->shouldBeCalled();

$this->urlsSubscriber->addUrlsOnPostSerialize($event->reveal());
}

/**
* @return \Prophecy\Prophecy\ObjectProphecy
*/
private function mockQuery()
{
$queryBuilder = $this->prophesize(QueryBuilder::class);
$queryBuilder->andWhere('entity.entityClass = :entityClass')
->shouldBeCalled()
->willReturn($queryBuilder->reveal());
$queryBuilder->andWhere('entity.entityId = :entityId')
->shouldBeCalled()
->willReturn($queryBuilder->reveal());
$queryBuilder->andWhere('entity.locale = :locale')
->shouldBeCalled()
->willReturn($queryBuilder->reveal());
$queryBuilder->andWhere('entity.history = false')
->shouldBeCalled()
->willReturn($queryBuilder->reveal());

$query = $this->prophesize(AbstractQuery::class);

$this->routeRepository->createQueryBuilder('entity')->willReturn($queryBuilder->reveal());
$queryBuilder->getQuery()->willReturn($query->reveal());

return $query;
}
}

0 comments on commit 1375f63

Please sign in to comment.