Skip to content

Commit 382b225

Browse files
committed
Consolidate naming
* Bundle testing
1 parent 51af85b commit 382b225

24 files changed

+597
-84
lines changed

.gitignore

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
composer.lock
22
vendor/
33
build/
4-
target/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace Bankiru\Seo\DependencyInjection\Compiler;
4+
5+
use Symfony\Component\Config\FileLocator;
6+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
7+
use Symfony\Component\DependencyInjection\ContainerBuilder;
8+
use Symfony\Component\DependencyInjection\Loader;
9+
10+
final class RouterPass implements CompilerPassInterface
11+
{
12+
/** {@inheritdoc} */
13+
public function process(ContainerBuilder $container)
14+
{
15+
if (!$container->has('router')) {
16+
return;
17+
}
18+
19+
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
20+
$loader->load('router.yml');
21+
}
22+
}

DestinationMatcher.php

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace Bankiru\Seo;
4+
5+
use Bankiru\Seo\Exception\MatchingException;
6+
use Bankiru\Seo\Exception\PageException;
7+
use Bankiru\Seo\Target\TargetSorter;
8+
9+
final class DestinationMatcher implements DestinationMatcherInterface
10+
{
11+
/** @var PageRepositoryInterface */
12+
private $pageRepository;
13+
/** @var TargetSorter */
14+
private $sorter;
15+
16+
/**
17+
* DestinationMatcher constructor.
18+
*
19+
* @param TargetSorter $sorter
20+
* @param PageRepositoryInterface $pageRepository
21+
*/
22+
public function __construct(TargetSorter $sorter, PageRepositoryInterface $pageRepository)
23+
{
24+
$this->pageRepository = $pageRepository;
25+
$this->sorter = $sorter;
26+
}
27+
28+
/** {@inheritdoc} */
29+
public function match(DestinationInterface $destination)
30+
{
31+
$target = $this->sorter->getMatchingTarget($destination);
32+
33+
try {
34+
return $this->pageRepository->getByTargetDestination($target, $destination);
35+
} catch (PageException $exception) {
36+
throw new MatchingException($exception->getMessage(), $exception->getCode(), $exception);
37+
}
38+
}
39+
}

ProcessorInterface.php DestinationMatcherInterface.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22

33
namespace Bankiru\Seo;
44

5-
use Bankiru\Seo\Exception\ProcessingException;
5+
use Bankiru\Seo\Exception\MatchingException;
66
use Bankiru\Seo\Page\SeoPageInterface;
77

8-
interface ProcessorInterface
8+
interface DestinationMatcherInterface
99
{
1010
/**
1111
* @param DestinationInterface $destination
1212
*
1313
* @return SeoPageInterface
14-
* @throws ProcessingException
14+
* @throws MatchingException
1515
*/
16-
public function process(DestinationInterface $destination);
16+
public function match(DestinationInterface $destination);
1717
}

Exception/MatchingException.php

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Bankiru\Seo\Exception;
4+
5+
class MatchingException extends \RuntimeException implements SeoExceptionInterface
6+
{
7+
public static function noTarget()
8+
{
9+
return new static('Destination does not match any target');
10+
}
11+
}

Exception/ProcessingException.php

-11
This file was deleted.
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace Bankiru\Seo\Integration\Local;
4+
5+
use Bankiru\Seo\DestinationInterface;
6+
use Bankiru\Seo\Exception\PageException;
7+
use Bankiru\Seo\Page\SeoPageInterface;
8+
use Bankiru\Seo\PageRepositoryInterface;
9+
use Bankiru\Seo\TargetDefinitionInterface;
10+
11+
final class StaticPageRepository implements PageRepositoryInterface
12+
{
13+
/** @var SeoPageInterface[] */
14+
private $pages = [];
15+
16+
public function add(TargetDefinitionInterface $target, SeoPageInterface $page)
17+
{
18+
$this->pages[$target->getRoute()] = $page;
19+
}
20+
21+
/** {@inheritdoc} */
22+
public function getByTargetDestination(TargetDefinitionInterface $target, DestinationInterface $destination = null)
23+
{
24+
if (!array_key_exists($target->getRoute(), $this->pages)) {
25+
throw PageException::notFound($target);
26+
}
27+
28+
return $this->pages[$target->getRoute()];
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace Bankiru\Seo\Integration\Local;
4+
5+
use Bankiru\Seo\TargetDefinitionInterface;
6+
use Bankiru\Seo\TargetRepositoryInterface;
7+
8+
final class StaticTargetRepository implements TargetRepositoryInterface
9+
{
10+
/**
11+
* @var TargetDefinitionInterface[][]
12+
*/
13+
private $targets = [];
14+
15+
public function add(TargetDefinitionInterface $target)
16+
{
17+
$this->targets[$target->getRoute()][] = $target;
18+
}
19+
20+
/** {@inheritdoc} */
21+
public function findByRoute($route)
22+
{
23+
if (!array_key_exists($route, $this->targets)) {
24+
return [];
25+
}
26+
27+
return $this->targets[$route];
28+
}
29+
}

Listener/MasterSeoRequest.php

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
3+
namespace Bankiru\Seo\Listener;
4+
5+
use Bankiru\Seo\DestinationInterface;
6+
use Bankiru\Seo\DestinationMatcherInterface;
7+
use Bankiru\Seo\Exception\MatchingException;
8+
use Bankiru\Seo\Page\SeoPageInterface;
9+
10+
final class MasterSeoRequest
11+
{
12+
/** @var DestinationInterface */
13+
private $destination;
14+
/** @var SeoPageInterface */
15+
private $page;
16+
/** @var DestinationMatcherInterface */
17+
private $matcher;
18+
19+
/**
20+
* MasterSeoRequest constructor.
21+
*
22+
* @param DestinationMatcherInterface $matcher
23+
*/
24+
public function __construct(DestinationMatcherInterface $matcher)
25+
{
26+
$this->matcher = $matcher;
27+
}
28+
29+
30+
/**
31+
* @return DestinationInterface|null
32+
* @throws \LogicException
33+
*/
34+
public function getDestination()
35+
{
36+
if (null === $this->destination) {
37+
throw new \LogicException('Destination is not set');
38+
}
39+
40+
return $this->destination;
41+
}
42+
43+
/**
44+
* @param DestinationInterface $destination
45+
*/
46+
public function setDestination(DestinationInterface $destination)
47+
{
48+
$this->destination = $destination;
49+
}
50+
51+
/**
52+
* @return SeoPageInterface
53+
* @throws \LogicException
54+
* @throws MatchingException
55+
*/
56+
public function getPage()
57+
{
58+
if (null === $this->page) {
59+
$this->page = $this->matcher->match($this->getDestination());
60+
}
61+
62+
return $this->page;
63+
}
64+
}
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace Bankiru\Seo\Listener;
4+
5+
use Bankiru\Seo\Destination;
6+
use Symfony\Component\HttpFoundation\Request;
7+
8+
final class RequestDestinationFactory
9+
{
10+
public static function createFromRequest(Request $request)
11+
{
12+
return new Destination(
13+
$request->attributes->get('_route'),
14+
$request->attributes->get('_route_params')
15+
);
16+
}
17+
}

Listener/SeoRequestListener.php

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
3+
namespace Bankiru\Seo\Listener;
4+
5+
use Bankiru\Seo\Exception\MatchingException;
6+
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
7+
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
8+
use Symfony\Component\Routing\Route;
9+
use Symfony\Component\Routing\RouterInterface;
10+
11+
final class SeoRequestListener
12+
{
13+
/** @var RouterInterface */
14+
private $router;
15+
/**
16+
* @var MasterSeoRequest
17+
*/
18+
private $seoRequest;
19+
20+
/**
21+
* SeoRequestListener constructor.
22+
*
23+
* @param RouterInterface $router
24+
* @param MasterSeoRequest $seoRequest
25+
*/
26+
public function __construct(RouterInterface $router, MasterSeoRequest $seoRequest)
27+
{
28+
$this->router = $router;
29+
$this->seoRequest = $seoRequest;
30+
}
31+
32+
/**
33+
* @param GetResponseEvent $event
34+
*
35+
* @throws \UnexpectedValueException
36+
* @throws NotFoundHttpException
37+
* @throws \LogicException
38+
*/
39+
public function onMasterRequest(GetResponseEvent $event)
40+
{
41+
if (!$event->isMasterRequest()) {
42+
return;
43+
}
44+
45+
$request = $event->getRequest();
46+
47+
$name = $request->attributes->get('route');
48+
$route = $this->router->getRouteCollection()->get($name);
49+
if (!$route) {
50+
return;
51+
}
52+
53+
$seoOptions = $this->normalizeSeoOptions($route, $name);
54+
55+
if (true !== $seoOptions['enabled']) {
56+
return;
57+
}
58+
59+
$this->seoRequest->setDestination(RequestDestinationFactory::createFromRequest($request));
60+
61+
if (false === $seoOptions['match']) {
62+
return;
63+
}
64+
65+
try {
66+
$page = $this->seoRequest->getPage();
67+
} catch (MatchingException $exception) {
68+
throw new NotFoundHttpException(null, $exception);
69+
}
70+
71+
$request->attributes->set('_seo_page', $page);
72+
}
73+
74+
/**
75+
* @param Route $route
76+
* @param string $name
77+
*
78+
* @return array
79+
* @throws \UnexpectedValueException
80+
*/
81+
private function normalizeSeoOptions(Route $route, $name)
82+
{
83+
$seoOptions = $route->getOption('seo');
84+
if (null === $seoOptions) {
85+
return ['enabled' => false];
86+
}
87+
if (is_bool($seoOptions)) {
88+
return ['enabled' => $seoOptions, 'match' => true];
89+
}
90+
if (!is_array($seoOptions)) {
91+
throw new \UnexpectedValueException(
92+
sprintf('Seo options should be either boolean or array for route "%s"', $name)
93+
);
94+
}
95+
96+
return array_replace_recursive(['enabled' => true, 'match' => true], $seoOptions);
97+
}
98+
}

0 commit comments

Comments
 (0)