Skip to content

Commit d81035a

Browse files
committed
port features from simple cms into routing bundle to simplify things
1 parent b6f9c17 commit d81035a

File tree

21 files changed

+712
-169
lines changed

21 files changed

+712
-169
lines changed

DependencyInjection/CmfRoutingExtension.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ private function setupDynamicRouter(array $config, ContainerBuilder $container,
9999
$locales = $config['locales'];
100100
$container->setParameter($this->getAlias() . '.dynamic.locales', $locales);
101101
}
102+
$container->setParameter($this->getAlias() . '.dynamic.auto_locale_pattern', $config['auto_locale_pattern']);
102103

103104
$loader->load('routing-dynamic.xml');
104105

DependencyInjection/Configuration.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ public function getConfigTreeBuilder()
122122
->arrayNode('locales')
123123
->prototype('scalar')->end()
124124
->end()
125+
->booleanNode('auto_locale_pattern')->defaultValue(false)->end()
125126
->end()
126127
->end()
127128
->end()

Doctrine/Orm/RouteProvider.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public function getRoutesByNames($names = null)
9090
$routes = array();
9191
foreach ($names as $name) {
9292
try {
93-
$routes[] = $this->getRouteByName($name, $parameters);
93+
$routes[] = $this->getRouteByName($name);
9494
} catch (RouteNotFoundException $e) {
9595
// not found
9696
}

Doctrine/Phpcr/IdPrefixListener.php

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,38 @@
1515
use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
1616

1717
/**
18-
* Doctrine PHPCR-ODM listener to set the idPrefix on routes
18+
* Doctrine PHPCR-ODM listener to tell routes what part of their id is the URL.
19+
*
20+
* This listener knows about the RouteProvider and uses its prefixes to
21+
* identify routes that could need the prefix. In case prefixes overlap, the
22+
* order matters as the first matching prefix is taken.
1923
*
2024
* @author David Buchmann <[email protected]>
2125
*/
2226
class IdPrefixListener
2327
{
2428
/**
25-
* The prefix to add to the url to create the repository path
29+
* Used to ask for the possible prefixes to remove from the repository ID
30+
* to create the URL.
2631
*
27-
* @var string
32+
* @var RouteProvider
2833
*/
29-
protected $idPrefix = '';
34+
protected $provider;
3035

31-
public function __construct($prefix)
36+
/**
37+
* @param RouteProvider $provider
38+
*/
39+
public function __construct(RouteProvider $provider)
3240
{
33-
$this->idPrefix = $prefix;
41+
$this->provider = $provider;
3442
}
3543

3644
/**
37-
* @param $prefix
45+
* @return array
3846
*/
39-
public function setPrefix($prefix)
47+
protected function getPrefixes()
4048
{
41-
$this->idPrefix = $prefix;
49+
return $this->provider->getPrefixes();
4250
}
4351

4452
public function postLoad(LifecycleEventArgs $args)
@@ -51,16 +59,24 @@ public function postPersist(LifecycleEventArgs $args)
5159
$this->updateId($args);
5260
}
5361

62+
public function postMove(LifecycleEventArgs $args)
63+
{
64+
$this->updateId($args);
65+
}
66+
5467
protected function updateId(LifecycleEventArgs $args)
5568
{
5669
$doc = $args->getObject();
5770

5871
// only update route objects and only if the prefix can match, to allow
5972
// for more than one listener and more than one route root
60-
if (($doc instanceof PrefixInterface)
61-
&& ! strncmp($this->idPrefix, $doc->getId(), strlen($this->idPrefix))
62-
) {
63-
$doc->setPrefix($this->idPrefix);
73+
if ($doc instanceof PrefixInterface) {
74+
foreach ($this->getPrefixes() as $prefix) {
75+
if (! strncmp($prefix, $doc->getId(), strlen($prefix))) {
76+
$doc->setPrefix($prefix);
77+
break;
78+
}
79+
}
6480
}
6581
}
6682
}

Doctrine/Phpcr/LocaleListener.php

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@
2929
class LocaleListener
3030
{
3131
/**
32-
* The prefix to add to the url to create the repository path
32+
* Used to ask for the possible prefixes to determine the possible locale
33+
* segment of the id.
3334
*
34-
* @var string
35+
* @var RouteProvider
3536
*/
36-
protected $idPrefix = '';
37+
protected $provider;
3738

3839
/**
3940
* List of possible locales to detect on URL after idPrefix
@@ -42,20 +43,24 @@ class LocaleListener
4243
*/
4344
protected $locales;
4445

45-
public function __construct($prefix, array $locales)
46-
{
47-
$this->idPrefix = $prefix;
48-
$this->locales = $locales;
49-
}
46+
/**
47+
* If set, call Route::setAddLocalePattern.
48+
* @var boolean
49+
*/
50+
protected $addLocalePattern;
5051

5152
/**
52-
* The repository path prefix where routes handled by this listener are located.
53-
*
54-
* @param $prefix
53+
* @param RouteProvider $provider To get prefixes from.
54+
* @param array $locales Locales that should be detected.
55+
* @param bool $addLocalePattern Whether to make route prepend the
56+
* locale pattern if it does not have
57+
* one of the allowed locals in its id.
5558
*/
56-
public function setPrefix($prefix)
59+
public function __construct(RouteProvider $provider, array $locales, $addLocalePattern = false)
5760
{
58-
$this->idPrefix = $prefix;
61+
$this->provider = $provider;
62+
$this->locales = $locales;
63+
$this->addLocalePattern = $addLocalePattern;
5964
}
6065

6166
/**
@@ -68,6 +73,17 @@ public function setLocales(array $locales)
6873
$this->locales = $locales;
6974
}
7075

76+
/**
77+
* Whether to make the route prepend the locale pattern if it does not
78+
* have one of the allowed locals in its id.
79+
*
80+
* @param boolean $addLocalePattern
81+
*/
82+
public function setAddLocalePattern($addLocalePattern)
83+
{
84+
$this->addLocalePattern = $addLocalePattern;
85+
}
86+
7187
/**
7288
* Update locale after loading a route.
7389
*
@@ -110,6 +126,14 @@ public function postMove(MoveEventArgs $args)
110126
$this->updateLocale($doc, $args->getTargetPath(), true);
111127
}
112128

129+
/**
130+
* @return array
131+
*/
132+
protected function getPrefixes()
133+
{
134+
return $this->provider->getPrefixes();
135+
}
136+
113137
/**
114138
* Update the locale of a route if $id starts with the prefix and has a
115139
* valid locale right after.
@@ -126,17 +150,19 @@ protected function updateLocale(Route $doc, $id, $force = false)
126150

127151
// only update route objects and only if the prefix can match, to allow
128152
// for more than one listener and more than one route root
129-
if (! preg_match('#' . $this->idPrefix . '/([^/]+)(/|$)#', $id, $matches)) {
153+
if (! preg_match('#(' . implode('|', $this->getPrefixes()) . ')/([^/]+)(/|$)#', $id, $matches)) {
130154
return;
131155
}
132156

133-
if (in_array($matches[1], $this->locales)) {
157+
if (in_array($locale = $matches[2], $this->locales)) {
134158
if ($force || ! $doc->getDefault('_locale')) {
135-
$doc->setDefault('_locale', $matches[1]);
159+
$doc->setDefault('_locale', $locale);
136160
}
137161
if ($force || ! $doc->getRequirement('_locale')) {
138-
$doc->setRequirement('_locale', $matches[1]);
162+
$doc->setRequirement('_locale', $locale);
139163
}
164+
} elseif ($this->addLocalePattern) {
165+
$doc->setAddLocalePattern(true);
140166
}
141167
}
142168
}
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony CMF package.
5+
*
6+
* (c) 2011-2013 Symfony CMF
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
13+
namespace Symfony\Cmf\Bundle\RoutingBundle\Doctrine\Phpcr;
14+
15+
use Symfony\Component\HttpFoundation\Request;
16+
17+
/**
18+
* Loads routes from Doctrine PHPCR-ODM, supporting the locale as first bit
19+
* after the prefix or as variable pattern.
20+
*
21+
* @author Lukas Kahwe Smith <[email protected]>
22+
*/
23+
class LocaleRouteProvider extends RouteProvider
24+
{
25+
/**
26+
* The allowed locales.
27+
*
28+
* @var array
29+
*/
30+
protected $locales = array();
31+
32+
/**
33+
* The detected locale in this request.
34+
*
35+
* @var string
36+
*/
37+
private $locale;
38+
39+
/**
40+
* Set the allowed locales.
41+
*
42+
* @param array $locales
43+
*/
44+
public function setLocales(array $locales = array())
45+
{
46+
$this->locales = $locales;
47+
}
48+
49+
/**
50+
* {@inheritDoc}
51+
*
52+
* Additionally checks if $url starts with a locale, and if so proposes
53+
* additional candidates without the locale.
54+
*/
55+
protected function getCandidates($url)
56+
{
57+
$directCandidates = parent::getCandidates($url);
58+
59+
$dirs = explode('/', ltrim($url, '/'));
60+
if (isset($dirs[0]) && in_array($dirs[0], $this->locales)) {
61+
$this->locale = $dirs[0];
62+
array_shift($dirs);
63+
$url = '/'.implode('/', $dirs);
64+
65+
// the normal listener "waits" until the routing completes
66+
// as the locale could be defined inside the route
67+
$this->getObjectManager()->getLocaleChooserStrategy()->setLocale($this->locale);
68+
69+
return array_merge($directCandidates, parent::getCandidates($url));
70+
}
71+
72+
return $directCandidates;
73+
}
74+
75+
protected function configureLocale($route)
76+
{
77+
crap. that if is about simple cms
78+
if ($this->getObjectManager()->isDocumentTranslatable($route)) {
79+
// add locale requirement
80+
if (!$route->getRequirement('_locale')) {
81+
$locales = $this->getObjectManager()->getLocalesFor($route, true);
82+
$route->setRequirement('_locale', implode('|', $locales));
83+
}
84+
}
85+
}
86+
87+
/**
88+
* {@inheritDoc}
89+
*/
90+
public function getRouteCollectionForRequest(Request $request)
91+
{
92+
$collection = parent::getRouteCollectionForRequest($request);
93+
foreach ($collection as $route) {
94+
$this->configureLocale($route);
95+
}
96+
97+
return $collection;
98+
}
99+
100+
/**
101+
* {@inheritDoc}
102+
*/
103+
public function getRouteByName($name, $parameters = array())
104+
{
105+
$route = parent::getRouteByName($name, $parameters);
106+
$this->configureLocale($route);
107+
108+
return $route;
109+
}
110+
111+
/**
112+
* {@inheritDoc}
113+
*/
114+
public function getRoutesByNames($names = null)
115+
{
116+
$collection = parent::getRoutesByNames($names);
117+
foreach ($collection as $route) {
118+
$this->configureLocale($route);
119+
}
120+
121+
return $collection;
122+
}
123+
}

Doctrine/Phpcr/Route.php

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
namespace Symfony\Cmf\Bundle\RoutingBundle\Doctrine\Phpcr;
1414

15+
use Doctrine\Common\Collections\ArrayCollection;
1516
use Doctrine\Common\Collections\Collection;
1617
use Doctrine\ODM\PHPCR\Document\Generic;
1718
use Doctrine\ODM\PHPCR\Exception\InvalidArgumentException;
@@ -65,18 +66,18 @@ class Route extends RouteModel implements PrefixInterface, ChildInterface
6566
protected $idPrefix;
6667

6768
/**
68-
* Overwrite to be able to create route without pattern
69+
* PHPCR id can not end on '/', so we need an additional option.
6970
*
70-
* @param Boolean $addFormatPattern if to add ".{_format}" to the route pattern
71-
* also implicitly sets a default/require on "_format" to "html"
72-
* @param Boolean $addTrailingSlash whether to add a trailing slash to the route, defaults to not add one
71+
* Additional supported settings are:
72+
*
73+
* * addTrailingSlash: When set, a trailing slash is appended to the route
7374
*/
74-
public function __construct($addFormatPattern = false, $addTrailingSlash = false)
75+
public function __construct(array $settings = array())
7576
{
76-
parent::__construct($addFormatPattern);
77+
parent::__construct($settings);
7778

78-
$this->children = array();
79-
$this->addTrailingSlash = $addTrailingSlash;
79+
$this->children = new ArrayCollection();
80+
$this->addTrailingSlash = empty($settings['addTrailingSlash']);
8081
}
8182

8283
public function getAddTrailingSlash()
@@ -217,7 +218,14 @@ public function setPrefix($idPrefix)
217218
*/
218219
public function getStaticPrefix()
219220
{
220-
return $this->generateStaticPrefix($this->getId(), $this->idPrefix);
221+
$path = $this->getId();
222+
$prefix = $this->getPrefix();
223+
224+
if ($this->addLocalePattern) {
225+
$path = $prefix . '/{_locale}' . substr($path, strlen($prefix));
226+
}
227+
228+
return $this->generateStaticPrefix($path, $prefix);
221229
}
222230

223231
/**
@@ -297,7 +305,7 @@ public function getRouteChildren()
297305
/**
298306
* Get all children of this route including non-routes.
299307
*
300-
* @return array
308+
* @return Collection
301309
*/
302310
public function getChildren()
303311
{

0 commit comments

Comments
 (0)