Skip to content

Commit

Permalink
Merge pull request #24 from xiaohutai/feature/split-routes
Browse files Browse the repository at this point in the history
Split routes automatically when exceeding regex limits
  • Loading branch information
xiaohutai authored Oct 1, 2019
2 parents 5463765 + 3cd824c commit c770690
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 8 deletions.
3 changes: 2 additions & 1 deletion config/config.yml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ rules:
# When using Bolt Translate, the Bolt Translate routing should
# take over, so set this to `false`. Bolt Translate integration
# is not working.
#
# bypass-url-generator: Bypasses the URL generator. This is generally kept `false`.

settings:
overwrite-duplicates : true
override-slugs : false
enable-routing : true
bypass-url-generator : false
34 changes: 27 additions & 7 deletions src/Controller/HierarchicalRoutesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,33 @@ public function connect(Application $app)

$requirement = $app['hierarchicalroutes.controller.requirement'];

$ctr
->match("/{slug}", [$this, 'recordExactMatch'])
->assert('slug', $requirement->anyRecordRouteConstraint())
->before('controller.frontend:before')
->after('controller.frontend:after')
->bind('hierarchicalroutes.record.exact')
;
// A site with many pages or deeply nested pages (usually a combination of both)
// results in an error. In this case split into multiple routes. The limit is set
// around 32767 and requires a re-compile of PHP in order to change this limit.
// Downside of this method is to that URL generation also becomes more complicated.
$anyRecordRouteConstraint = $requirement->anyRecordRouteConstraint();
if (strlen($anyRecordRouteConstraint) > 30000) {
$index = 0;
$groups = $requirement->anyRecordRouteConstraintSplitted();
foreach ($groups as $group) {
$ctr
->match("/{slug}", [$this, 'recordExactMatch'])
->assert('slug', $group)
->before('controller.frontend:before')
->after('controller.frontend:after')
->bind('hierarchicalroutes.record.exact_' . $index)
;
$index++;
}
} else {
$ctr
->match("/{slug}", [$this, 'recordExactMatch'])
->assert('slug', $anyRecordRouteConstraint)
->before('controller.frontend:before')
->after('controller.frontend:after')
->bind('hierarchicalroutes.record.exact')
;
}

$ctr
->match("/{slug}", [$this, 'listingExactMatch'])
Expand Down
17 changes: 17 additions & 0 deletions src/Controller/Requirement.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class Requirement
private $listingRoutes = [];
private $potentialParents = [];

private $chunkSize = 100;

/**
* @param HierarchicalRoutesService $service
*/
Expand All @@ -30,6 +32,21 @@ public function __construct(HierarchicalRoutesService $service)
$this->potentialParents = $this->service->getPotentialParents();
}

/**
* @return array
*/
public function anyRecordRouteConstraintSplitted()
{
$result = [];
$chunks = array_chunk($this->recordRoutes, $this->chunkSize);

foreach ($chunks as $chunk) {
$result[] = $this->createConstraints($chunk);
}

return $result;
}

/**
* @return string
*/
Expand Down
20 changes: 20 additions & 0 deletions src/Routing/HierarchicalUrlGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public function generate($name, $parameters = [], $referenceType = UrlGeneratorI
{
$config = $this->app['hierarchicalroutes.config'];
$enableRouting = $config->get('settings/enable-routing', true);
$bypassUrlGenerator = $config->get('settings/bypass-url-generator', false);

if ($enableRouting && $name == 'contentlink') {
$service = $this->app['hierarchicalroutes.service'];
Expand All @@ -55,10 +56,29 @@ public function generate($name, $parameters = [], $referenceType = UrlGeneratorI
$recordRoutes = $service->getRecordRoutes();

if (isset($recordRoutes["$contenttypeslug/$slug"])) {
if ($bypassUrlGenerator) {
return '/' . $recordRoutes["$contenttypeslug/$slug"];
}

$name = 'hierarchicalroutes.record.exact';
$parameters = [
'slug' => $recordRoutes["$contenttypeslug/$slug"],
];

$requirement = $this->app['hierarchicalroutes.controller.requirement'];
$anyRecordRouteConstraint = $requirement->anyRecordRouteConstraint();
if (strlen($anyRecordRouteConstraint) > 30000) {
$groups = $requirement->anyRecordRouteConstraintSplitted();
$index = 0;
foreach ($groups as $group) {
$matches = preg_match("($group)", $parameters['slug']);
if ($matches === 1) {
return $this->wrapped->generate($name . '_' . $index, $parameters, $referenceType);
}
$index++;
}
}

return $this->wrapped->generate($name, $parameters, $referenceType);
}

Expand Down

0 comments on commit c770690

Please sign in to comment.