Skip to content
This repository has been archived by the owner on Sep 16, 2021. It is now read-only.

[WIP] Create custom behavior for RouteNotFoundException #177

Closed
wants to merge 58 commits into from
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
07f82f1
first work
ElectricMaxxx Aug 3, 2014
f84801b
created base matcher implementation with config and tests
ElectricMaxxx Aug 3, 2014
92dcac3
get presentations starts working
ElectricMaxxx Aug 3, 2014
c4b5db8
remove type binding by adding an optional grouping
ElectricMaxxx Aug 4, 2014
838326c
add test for compiler pass and fix it
ElectricMaxxx Aug 4, 2014
6b4ef0d
prepare matcher
ElectricMaxxx Aug 4, 2014
d488351
first implementation of both matchers
ElectricMaxxx Aug 12, 2014
a38748f
use PathHelper for parent path
ElectricMaxxx Aug 12, 2014
b43205b
fix some config, re-introduce controller setting
ElectricMaxxx Aug 12, 2014
1965165
fix date
ElectricMaxxx Aug 20, 2014
e24ef17
fix matcher
ElectricMaxxx Aug 20, 2014
1f503d9
first work
ElectricMaxxx Aug 3, 2014
cc20e5a
created base matcher implementation with config and tests
ElectricMaxxx Aug 3, 2014
d6a4168
get presentations starts working
ElectricMaxxx Aug 3, 2014
ec419eb
remove type binding by adding an optional grouping
ElectricMaxxx Aug 4, 2014
a8d8b1a
add test for compiler pass and fix it
ElectricMaxxx Aug 4, 2014
065f3de
prepare matcher
ElectricMaxxx Aug 4, 2014
5f728a8
first implementation of both matchers
ElectricMaxxx Aug 12, 2014
48e18f8
use PathHelper for parent path
ElectricMaxxx Aug 12, 2014
245baf0
fix some config, re-introduce controller setting
ElectricMaxxx Aug 12, 2014
ff47fe3
fix date
ElectricMaxxx Aug 20, 2014
4bf8b4f
fix matcher
ElectricMaxxx Aug 20, 2014
0210a96
follow up to an rebase
ElectricMaxxx Aug 21, 2014
33a38a9
remove unused configuration
ElectricMaxxx Aug 21, 2014
95501b5
remove use stmt
ElectricMaxxx Aug 21, 2014
a79d05b
Merge remote-tracking branch 'origin/custom-exception-or-errors' into…
ElectricMaxxx Aug 23, 2014
d285952
move classes, correct chanlog
ElectricMaxxx Aug 23, 2014
b0c8c95
Merge pull request #189 from cordoval/plug-trait-for-brevity
wouterj Sep 22, 2014
ecdaba7
Added #189 to CHANGELOG
wouterj Sep 22, 2014
1071d80
first work
ElectricMaxxx Aug 3, 2014
2ba2f5f
created base matcher implementation with config and tests
ElectricMaxxx Aug 3, 2014
d7a36ee
get presentations starts working
ElectricMaxxx Aug 3, 2014
0065722
remove type binding by adding an optional grouping
ElectricMaxxx Aug 4, 2014
ead1422
add test for compiler pass and fix it
ElectricMaxxx Aug 4, 2014
b58061a
prepare matcher
ElectricMaxxx Aug 4, 2014
a344ed1
first implementation of both matchers
ElectricMaxxx Aug 12, 2014
a3e3a9d
use PathHelper for parent path
ElectricMaxxx Aug 12, 2014
3d0aa64
fix some config, re-introduce controller setting
ElectricMaxxx Aug 12, 2014
3cc7e0d
fix date
ElectricMaxxx Aug 20, 2014
436112e
fix matcher
ElectricMaxxx Aug 20, 2014
9dcb337
first work
ElectricMaxxx Aug 3, 2014
be8bf38
created base matcher implementation with config and tests
ElectricMaxxx Aug 3, 2014
2f62868
get presentations starts working
ElectricMaxxx Aug 3, 2014
60b5837
remove type binding by adding an optional grouping
ElectricMaxxx Aug 4, 2014
2977160
add test for compiler pass and fix it
ElectricMaxxx Aug 4, 2014
da86417
prepare matcher
ElectricMaxxx Aug 4, 2014
f7dce24
first implementation of both matchers
ElectricMaxxx Aug 12, 2014
d235909
use PathHelper for parent path
ElectricMaxxx Aug 12, 2014
35f9ff2
fix some config, re-introduce controller setting
ElectricMaxxx Aug 12, 2014
b0d4281
fix date
ElectricMaxxx Aug 20, 2014
745eb82
follow up to an rebase
ElectricMaxxx Aug 21, 2014
a0615c7
remove unused configuration
ElectricMaxxx Aug 21, 2014
3415e86
remove use stmt
ElectricMaxxx Aug 21, 2014
f574e57
move classes, correct chanlog
ElectricMaxxx Aug 23, 2014
00962cd
rebase with conflicts, correct wrong solved conflicts
ElectricMaxxx Oct 2, 2014
bb1257c
another merge conflicts
ElectricMaxxx Oct 2, 2014
e9de76d
remove my ide files
ElectricMaxxx Oct 2, 2014
d772177
fix template problem for testi
ElectricMaxxx Oct 3, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Changelog
=========

* **2014-02-08**: Custom exception controller for error handling
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we use european dates, not the confused american ones ;-) so its YYYY-MM-DD

* **2014-06-06**: Updated to PSR-4 autoloading

1.0.0
Expand Down
2 changes: 2 additions & 0 deletions CmfSeoBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Doctrine\Bundle\PHPCRBundle\DependencyInjection\Compiler\DoctrinePhpcrMappingsPass;
use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DoctrineOrmMappingsPass;

use Symfony\Cmf\Bundle\SeoBundle\DependencyInjection\Compiler\RegisterBestMatcherPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\HttpKernel\Bundle\Bundle;
Expand All @@ -25,6 +26,7 @@ class CmfSeoBundle extends Bundle
public function build(ContainerBuilder $container)
{
$container->addCompilerPass(new RegisterExtractorsPass());
$container->addCompilerPass(new RegisterBestMatcherPass());

$this->buildPhpcrCompilerPass($container);
$this->buildOrmCompilerPass($container);
Expand Down
19 changes: 19 additions & 0 deletions DependencyInjection/CmfSeoExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Symfony\Cmf\Bundle\SeoBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
Expand Down Expand Up @@ -70,6 +71,10 @@ public function load(array $configs, ContainerBuilder $container)
if (count($sonataBundles) && $config['sonata_admin_extension']['enabled']) {
$this->loadSonataAdmin($config['sonata_admin_extension'], $loader, $container, $sonataBundles);
}

if ($this->isConfigEnabled($container, $config['error_handling'])) {
$this->loadErrorHandling($config['error_handling'], $loader, $container);
}
}

/**
Expand Down Expand Up @@ -131,4 +136,18 @@ public function getXsdValidationBasePath()
{
return __DIR__.'/../Resources/config/schema';
}

/**
* @param $config
* @param XmlFileLoader $loader
* @param ContainerBuilder $container
*/
private function loadErrorHandling($config, XmlFileLoader $loader, ContainerBuilder $container)
{
if ($container->hasParameter($this->getAlias().'.backend_type_phpcr')
&& $container->getParameter($this->getAlias().'.backend_type_phpcr')
) {
$loader->load('matcher_phpcr.xml');
}
}
}
49 changes: 49 additions & 0 deletions DependencyInjection/Compiler/RegisterBestMatcherPass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php


namespace Symfony\Cmf\Bundle\SeoBundle\DependencyInjection\Compiler;


use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Reference;

/**
* @author Maximilian Berghoff <Maximilian.Berghoff@gmx.de>
*/
class RegisterBestMatcherPass implements CompilerPassInterface
{
/**
* {@inheritDoc}
*
* @throws LogicException If a tagged service is not public.
*/
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('cmf_seo.error_handling.matcher.presentation')) {
return;
}

$presentationDefinition = $container->getDefinition('cmf_seo.error_handling.matcher.presentation');
$taggedServices = $container->findTaggedServiceIds('cmf_seo.best_matcher');

foreach ($taggedServices as $id => $attributes) {
$definition = $container->getDefinition($id);
if (!$definition->isPublic()) {
throw new LogicException(sprintf('Matcher "%s" must be public.', $id));
}

$group = null;
foreach ($attributes as $attribute) {
if (isset($attribute['group'])) {
$group = $attribute['group'];
break;
}
}
$group = null !== $group ? $group : 'default';

$presentationDefinition->addMethodCall('addMatcher', array(new Reference($id), $group));
}
}
}
4 changes: 4 additions & 0 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ public function getConfigTreeBuilder()
->scalarNode('form_group')->defaultValue('form.group_seo')->end()
->end()
->end()
->arrayNode('error_handling')
->addDefaultsIfNotSet()
->canBeEnabled()
->end()
->end()
;

Expand Down
32 changes: 32 additions & 0 deletions ErrorHandling/AncestorBestMatcher.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/*
* This file is part of the Symfony CMF package.
*
* (c) 2011-2014 Symfony CMF
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Cmf\Bundle\SeoBundle\ErrorHandling;

use Symfony\Component\HttpFoundation\Request;

/**
* This BestMatcher tries to create a route collection of
* all ancestors of a given uri.
*
* @author Maximilian Berghoff <Maximilian.Berghoff@gmx.de>
*/
class AncestorBestMatcher extends PhpcrBestMatcher
{

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra blank line

/**
* {@inheritDoc}
*/
public function create(Request $request)
{
// TODO: Implement create() method.
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somebody (@dantleech, @lsmith77) any hints to build a good and fast query for getting all ancestors?
parent -> all children?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't want to use a query but instead want to use getChildren() .. there is a method for this both on the PHPCR as well as the PHPCR ODM level. In both cases you first need to fetch the parent (node or document).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In ErrorHandling/AncestorBestMatcher.php:

+/**

yes ..

}
90 changes: 90 additions & 0 deletions ErrorHandling/BestMatchPresentation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

/*
* This file is part of the Symfony CMF package.
*
* (c) 2011-2014 Symfony CMF
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Cmf\Bundle\SeoBundle\ErrorHandling;

use Symfony\Bundle\TwigBundle\Controller\ExceptionController;
use Symfony\Cmf\Bundle\SeoBundle\Exception\InvalidArgumentException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;

/**
* This presentation model enriches the the values to render the
* error pages by the help of so called BestMatcher.
*
* @author Maximilian Berghoff <Maximilian.Berghoff@gmx.de>
*/
class BestMatchPresentation extends ExceptionController
{
/**
* Chain of matcher.
*
* @var array|BestMatcherInterface[]
*/
protected $matcherChain = array();

/**
* @param Request $request
* @param FlattenException $exception
* @param DebugLoggerInterface $logger
* @param string $_format
* @return Response
*/
public function showAction(
Request $request,
FlattenException $exception,
DebugLoggerInterface $logger = null,
$_format = 'html'
) {
$code = $exception->getStatusCode();

if (404 !== $code) {
return parent::showAction($request, $exception, $logger, $_format);
}

$currentContent = $this->getAndCleanOutputBuffering($request->headers->get('X-Php-Ob-Level', -1));
$bestMatches = array();

foreach ($this->matcherChain as $group => $matcher) {
$bestMatches[$group] = $matcher->create($request);
}

$template = $this->findTemplate($request, $_format, $code, $this->debug);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would a matcher need to provide its own template maybe?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thougt we just can use the common behavior, means: overwrite the TwigTemplate.


return new Response($this->twig->render(
$template,
array(
'status_code' => $code,
'status_text' => isset(Response::$statusTexts[$code]) ? Response::$statusTexts[$code] : '',
'exception' => $exception,
'logger' => $logger,
'currentContent' => $currentContent,
'best_matches' => $bestMatches,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the test template does not use this information if i see correctly. we should have the documentation provide a good example how to use this info

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea, thats exactly my problem, but i have got no solution for it. :-(
The problem is:the template isn't used, the default twig one instead is used, have no clue why.

)
));
}

/**
* @param BestMatcherInterface $matcher
* @param string $group Unique per Chain.
* @throws InvalidArgumentException
*/
public function addMatcher(BestMatcherInterface $matcher, $group)
{
if (array_key_exists($group, $this->matcherChain)) {
throw new InvalidArgumentException(sprintf('You can only add on matcher with group %s.', $group));
}

$this->matcherChain[$group] = $matcher;
}
}
24 changes: 24 additions & 0 deletions ErrorHandling/BestMatcherInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php


namespace Symfony\Cmf\Bundle\SeoBundle\ErrorHandling;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouteCollection;

/**
* Interface to create a BestMatcher.
*
* @author Maximilian Berghoff <Maximilian.Berghoff@gmx.de>
*/
interface BestMatcherInterface
{
/**
* Based on the current request BestMatcher creates collections of
* route as suggestions to navigate to.
*
* @param Request $request
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a blank line after this

* @return RouteCollection
*/
public function create(Request $request);
}
39 changes: 39 additions & 0 deletions ErrorHandling/ParentBestMatcher.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

/*
* This file is part of the Symfony CMF package.
*
* (c) 2011-2014 Symfony CMF
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Cmf\Bundle\SeoBundle\ErrorHandling;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouteCollection;

/**
* This BestMatcher will try to detect a parent route of a given uri.
*
* @author Maximilian Berghoff <Maximilian.Berghoff@gmx.de>
*/
class ParentBestMatcher extends PhpcrBestMatcher
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this not keep phpcr in the class name? or all live in Doctrine\Phpcr?

{
/**
* {@inheritDoc}
*/
public function create(Request $request)
{
$routes = new RouteCollection();
$uriAsArray = explode('/', $request->getUri());
if (count($uriAsArray) <= 1) {
return $routes;
}

$uriAsArray = array_shift($uriAsArray);
$parentUri = implode('/', $uriAsArray);

}
}
54 changes: 54 additions & 0 deletions ErrorHandling/PhpcrBestMatcher.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

/*
* This file is part of the Symfony CMF package.
*
* (c) 2011-2014 Symfony CMF
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Cmf\Bundle\SeoBundle\ErrorHandling;

use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\ODM\PHPCR\DocumentManager;

/**
* Abstract BestMatcher for those who needs make use of base
* phpcr-odm classes.
*
* @author Maximilian Berghoff <Maximilian.Berghoff@gmx.de>
*/
abstract class PhpcrBestMatcher implements BestMatcherInterface
{
/**
* @var ManagerRegistry
*/
protected $managerRegistry;

/**
* @param ManagerRegistry $managerRegistry
*/
public function setManagerRegistry($managerRegistry)
{
$this->managerRegistry = $managerRegistry;
}

/**
* @return ManagerRegistry
*/
public function getManagerRegistry()
{
return $this->managerRegistry;
}

/**
* @param string $class
* @return null|DocumentManager
*/
public function getManagerForClass($class)
{
return $this->managerRegistry->getManagerForClass($class);
}
}
28 changes: 28 additions & 0 deletions Resources/config/matcher_phpcr.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<parameters>
<parameter key="cmf_seo.error_handling.matcher.parent.class">Symfony\Cmf\Bundle\SeoBundle\ErrorHandling\ParentBestMatcher</parameter>
<parameter key="cmf_seo.error_handling.matcher.ancestor.class">Symfony\Cmf\Bundle\SeoBundle\ErrorHandling\AncestorBestMatcher</parameter>
</parameters>

<services>
<service id="cmf_seo.error_handling.matcher.parent" class="%cmf_seo.error_handling.matcher.parent.class%">
<call method="setManagerRegistry">
<argument type="service" id="doctrine_phpcr" />
</call>
<tag name="cmf_seo.best_matcher" group="parent" />
</service>
<service id="cmf_seo.error_handling.matcher.ancestor" class="%cmf_seo.error_handling.matcher.ancestor.class%">
<call method="setManagerRegistry">
<argument type="service" id="doctrine_phpcr" />
</call>
<tag name="cmf_seo.best_matcher" group="ancestor" />
</service>

</services>

</container>
Loading