Skip to content

Commit

Permalink
[Routing] Simplified php matcher dumper (and optimized generated matc…
Browse files Browse the repository at this point in the history
…her)
  • Loading branch information
arnaud-lb committed Oct 16, 2012
1 parent ccba363 commit e54d749
Show file tree
Hide file tree
Showing 7 changed files with 605 additions and 161 deletions.
101 changes: 101 additions & 0 deletions src/Symfony/Component/Routing/Matcher/Dumper/DumperCollection.php
@@ -0,0 +1,101 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Routing\Matcher\Dumper;

/**
* Collection of routes.
*
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
*/
class DumperCollection implements \IteratorAggregate
{
private $parent;
private $children = array();

/**
* Returns the children routes and collections.
*
* @return array Array of DumperCollection|DumperRoute
*/
public function all()
{
return $this->children;
}

/**
* Adds a route or collection
*
* @param DumperRoute|DumperCollection The route or collection
*/
public function add($child)
{
if ($child instanceof DumperCollection) {
$child->setParent($this);
}
$this->children[] = $child;
}

/**
* Sets children
*
* @param array $children The children
*/
public function setAll(array $children)
{
foreach ($children as $child) {
if ($child instanceof DumperCollection) {
$child->setParent($this);
}
}
$this->children = $children;
}

/**
* Returns an iterator over the children.
*
* @return \Iterator The iterator
*/
public function getIterator()
{
return new \ArrayIterator($this->children);
}

/**
* Returns the root of the collection.
*
* @return DumperCollection The root collection
*/
public function getRoot()
{
return (null !== $this->parent) ? $this->parent->getRoot() : $this;
}

/**
* Returns the parent collection.
*
* @return DumperCollection|null The parent collection or null if the collection has no parent
*/
protected function getParent()
{
return $this->parent;
}

/**
* Sets the parent collection.
*
* @param DumperCollection $parent The parent collection
*/
protected function setParent(DumperCollection $parent)
{
$this->parent = $parent;
}
}
@@ -0,0 +1,103 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Routing\Matcher\Dumper;

/**
* Prefix tree of routes preserving routes order.
*
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
*/
class DumperPrefixCollection extends DumperCollection
{
private $prefix = '';

/**
* Returns the prefix.
*
* @return string The prefix
*/
public function getPrefix()
{
return $this->prefix;
}

/**
* Sets the prefix.
*
* @param string $prefix The prefix
*/
public function setPrefix($prefix)
{
$this->prefix = $prefix;
}

/**
* Adds a route in the tree.
*
* @param DumperRoute $route The route
*
* @return DumperPrefixCollection The node the route was added to
*/
public function addPrefixRoute(DumperRoute $route)
{
$prefix = $route->getRoute()->compile()->getStaticPrefix();

// Same prefix, add to current leave
if ($this->prefix === $prefix) {
$this->add($route);

return $this;
}

// Prefix starts with route's prefix
if ('' === $this->prefix || 0 === strpos($prefix, $this->prefix)) {
$collection = new DumperPrefixCollection();
$collection->setPrefix(substr($prefix, 0, strlen($this->prefix)+1));
$this->add($collection);

return $collection->addPrefixRoute($route);
}

// No match, fallback to parent (recursively)

if (null === $parent = $this->getParent()) {
throw new \LogicException("The collection root must not have a prefix");
}

return $parent->addPrefixRoute($route);
}

/**
* Merges nodes whose prefix ends with a slash
*
* Children of a node whose prefix ends with a slash are moved to the parent node
*/
public function mergeSlashNodes()
{
$children = array();

foreach ($this as $child) {
if ($child instanceof self) {
$child->mergeSlashNodes();
if ('/' === substr($child->prefix, -1)) {
$children = array_merge($children, $child->all());
} else {
$children[] = $child;
}
} else {
$children[] = $child;
}
}

$this->setAll($children);
}
}
58 changes: 58 additions & 0 deletions src/Symfony/Component/Routing/Matcher/Dumper/DumperRoute.php
@@ -0,0 +1,58 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Routing\Matcher\Dumper;

use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;

/**
* Container for a Route.
*
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
*/
class DumperRoute
{
private $name;
private $route;

/**
* Constructor.
*
* @param string $name The route name
* @param Route $route The route
*/
public function __construct($name, Route $route)
{
$this->name = $name;
$this->route = $route;
}

/**
* Returns the route name.
*
* @return string The route name
*/
public function getName()
{
return $this->name;
}

/**
* Returns the route.
*
* @return Route The route
*/
public function getRoute()
{
return $this->route;
}
}

0 comments on commit e54d749

Please sign in to comment.