-
Notifications
You must be signed in to change notification settings - Fork 27
[WIP] Create custom behavior for RouteNotFoundException #177
Changes from 3 commits
07f82f1
f84801b
92dcac3
c4b5db8
838326c
6b4ef0d
d488351
a38748f
b43205b
1965165
e24ef17
1f503d9
cc20e5a
d6a4168
ec419eb
a8d8b1a
065f3de
5f728a8
48e18f8
245baf0
ff47fe3
4bf8b4f
0210a96
33a38a9
95501b5
a79d05b
d285952
b0c8c95
ecdaba7
1071d80
2ba2f5f
d7a36ee
0065722
ead1422
b58061a
a344ed1
a3e3a9d
3d0aa64
3cc7e0d
436112e
9dcb337
be8bf38
2f62868
60b5837
2977160
da86417
f7dce24
d235909
35f9ff2
b0d4281
745eb82
a0615c7
3415e86
f574e57
00962cd
bb1257c
e9de76d
d772177
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<?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; | ||
} | ||
|
||
$strategyDefinition = $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('Strategy "%s" must be public.', $id)); | ||
} | ||
|
||
if (!isset($attributes['type'])) { | ||
throw new LogicException('You have to set a BestMatcher type.'); | ||
} | ||
|
||
$strategyDefinition->addMethodCall('addMatcher', array( | ||
new Reference($id), | ||
$attributes['type'] | ||
)); | ||
} | ||
} | ||
} |
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 | ||
{ | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
yes .. |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
<?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 | ||
{ | ||
/** | ||
* Type/shortcut for a best matcher handling the parent. | ||
*/ | ||
const MATCH_TYPE_PARENT = 'parent'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i fear that the type is overcomplicating things here, without the benefit. the user could come up with all kinds of types (i.e. a blog where you search for keywords from the referrer and url, or posts around the same date and so on). i would leave the type out. or if you really think its needed, we should not limit possible types and use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But i would leave a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, i was changing my mind while writing the comment ;-) so yeah, lets group them. maybe alias is not the best name for that. what about There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Jep. When i say:
Maybe now you know what i mean with "asking for some help with the QueryBuilder". parent is easy, but the others means some "join-action". @dbu What would you like to add as custom There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. as i see, its all up to the user what he needs. but to me parent or all anchestors in the tree are both about hierarchy. parent is just a special case. and some system might have another concept of hierarchies (if the first url segment denotes a tag for example, it would be stuff with the same tag). for the tree hierarchy, you can just split on |
||
|
||
/** | ||
* Type/shortcut for best matcher handling the ancestors | ||
*/ | ||
const MATCH_TYPE_ANCESTOR = 'ancestor'; | ||
|
||
/** | ||
* 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 $type => $matcher) { | ||
$bestMatches[$type] = $matcher->create($request); | ||
} | ||
|
||
return new Response($this->twig->render( | ||
$this->findTemplate($request, $_format, $code, $this->debug), | ||
array( | ||
'status_code' => $code, | ||
'status_text' => isset(Response::$statusTexts[$code]) ? Response::$statusTexts[$code] : '', | ||
'exception' => $exception, | ||
'logger' => $logger, | ||
'currentContent' => $currentContent, | ||
'best_matches' => $bestMatches, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. :-( |
||
) | ||
)); | ||
} | ||
|
||
/** | ||
* @param BestMatcherInterface $matcher | ||
* @param string $type | ||
* @throws InvalidArgumentException | ||
*/ | ||
public function addMatcher(BestMatcherInterface $matcher, $type) | ||
{ | ||
if (self::MATCH_TYPE_ANCESTOR !== $type && self::MATCH_TYPE_PARENT !== $type) { | ||
throw new InvalidArgumentException( | ||
sprintf( | ||
'%s is not supported as a matcher type. use one of %s or %s', | ||
$type, | ||
self::MATCH_TYPE_PARENT, | ||
self::MATCH_TYPE_ANCESTOR | ||
) | ||
); | ||
} | ||
|
||
if (array_key_exists($type, $this->matcherChain)) { | ||
throw new InvalidArgumentException(sprintf('You can only add on matcher with type %s.', $type)); | ||
} | ||
|
||
$this->matcherChain[$type] = $matcher; | ||
} | ||
} |
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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<?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 will try to detect a parent route of a given uri. | ||
* | ||
* @author Maximilian Berghoff <Maximilian.Berghoff@gmx.de> | ||
*/ | ||
class ParentBestMatcher extends PhpcrBestMatcher | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) | ||
{ | ||
|
||
} | ||
} |
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); | ||
} | ||
} |
There was a problem hiding this comment.
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