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

Commit

Permalink
Move compiling to separate class
Browse files Browse the repository at this point in the history
  • Loading branch information
krzysztof-magosa committed Oct 19, 2014
1 parent ce2c31a commit e3593a5
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 67 deletions.
74 changes: 20 additions & 54 deletions src/KM/Saffron/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
*/
namespace KM\Saffron;

use KM\Saffron\RouteCompiler;
use KM\Saffron\RouteCompiled;

class Route
{
protected $name;
Expand Down Expand Up @@ -164,64 +167,27 @@ public function getPrefix()
return substr($this->uri, 0, $length);
}

public function getUriRegex()
{
$tokens = preg_split(
'#([^}]?\{\w+\})#s',
substr($this->uri, 1),
-1,
PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY
);

$regex = preg_quote(substr($this->uri, 0, 1), '#');
foreach ($tokens as $token) {
if (preg_match('#^(?P<delimiter>.)?\{(?P<placeholder>\w+)\}$#s', $token, $match)) {
$regex .= sprintf(
'(%s(?P<%s>%s))%s',
isset($match['delimiter']) ? preg_quote($match['delimiter'], '#') : '',
preg_quote($match['placeholder'], '#'),
$this->getRequire($match['placeholder']),
$this->hasDefault($match['placeholder']) ? '?' : ''
);
}
else {
$regex .= preg_quote($token, '#');
}
}
public function needsUriRegex()
{
return $this->getPrefix() != $this->getUri();
}

return '#^'.$regex.'$#s';
}

public function getDomainRegex()
{
$tokens = preg_split(
'#({\w+\}[^{]?)#s',
$this->domain,
-1,
PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY
);

$regex = '';
foreach ($tokens as $token) {
if (preg_match('#^\{(?P<placeholder>\w+)\}(?P<delimiter>.)?$#s', $token, $match)) {
$regex .= sprintf(
'((?P<%s>%s)%s)%s',
preg_quote($match['placeholder'], '#'),
$this->getRequire($match['placeholder']),
isset($match['delimiter']) ? preg_quote($match['delimiter'], '#') : '',
$this->hasDefault($match['placeholder']) ? '?' : ''
);
}
else {
$regex .= preg_quote($token, '#');
}
protected function getCompiler()
{
static $compiler;

if (!$compiler) {
$compiler = new RouteCompiler();
}

return '#^'.$regex.'$#s';
}
return $compiler;
}

public function needsUriRegex()
/**
* @return RouteCompiled
*/
public function getCompiled()
{
return $this->getPrefix() != $this->getUri();
return $this->getCompiler()->compile($this);
}
}
59 changes: 59 additions & 0 deletions src/KM/Saffron/RouteCompiled.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php
/**
* Copyright 2014 Krzysztof Magosa
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace KM\Saffron;

class RouteCompiled
{
protected $prefix;
protected $uriRegex;
protected $domainRegex;

public function __construct($prefix, $uriRegex, $domainRegex)
{
$this->prefix = $prefix;
$this->uriRegex = $uriRegex;
$this->domainRegex = $domainRegex;
}

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

/**
* @return string
*/
public function getUriRegex()
{
return $this->uriRegex;
}

/**
* @return string
*/
public function getDomainRegex()
{
return $this->domainRegex;
}

public function hasUriRegex()
{
return null !== $this->uriRegex;
}
}
112 changes: 112 additions & 0 deletions src/KM/Saffron/RouteCompiler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php
/**
* Copyright 2014 Krzysztof Magosa
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace KM\Saffron;

use KM\Saffron\Route;
use KM\Saffron\RouteCompiled;

class RouteCompiler
{
protected function getPrefix(Route $route)
{
// @TODO make it not ugly :)
$pos = strpos($route->getUri(), '{');

if (false !== $pos) {
$length = max($pos - 1, 1);
}
else {
$length = strlen($route->getUri());
}

return substr($route->getUri(), 0, $length);
}

protected function getUriRegex(Route $route)
{
if ($this->getPrefix($route) == $route->getUri()) {
return null;
}

$tokens = preg_split(
'#([^}]?\{\w+\})#s',
substr($route->getUri(), 1),
-1,
PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY
);

$regex = preg_quote(substr($route->getUri(), 0, 1), '#');
foreach ($tokens as $token) {
if (preg_match('#^(?P<delimiter>.)?\{(?P<placeholder>\w+)\}$#s', $token, $match)) {
$regex .= sprintf(
'(%s(?P<%s>%s))%s',
isset($match['delimiter']) ? preg_quote($match['delimiter'], '#') : '',
preg_quote($match['placeholder'], '#'),
$route->getRequire($match['placeholder']),
$route->hasDefault($match['placeholder']) ? '?' : ''
);
}
else {
$regex .= preg_quote($token, '#');
}
}

return '#^'.$regex.'$#s';
}

protected function getDomainRegex(Route $route)
{
if (!$route->hasDomain()) {
return null;
}

$tokens = preg_split(
'#({\w+\}[^{]?)#s',
$route->getDomain(),
-1,
PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY
);

$regex = '';
foreach ($tokens as $token) {
if (preg_match('#^\{(?P<placeholder>\w+)\}(?P<delimiter>.)?$#s', $token, $match)) {
$regex .= sprintf(
'((?P<%s>%s)%s)%s',
preg_quote($match['placeholder'], '#'),
$route->getRequire($match['placeholder']),
isset($match['delimiter']) ? preg_quote($match['delimiter'], '#') : '',
$route->hasDefault($match['placeholder']) ? '?' : ''
);
}
else {
$regex .= preg_quote($token, '#');
}
}

return '#^'.$regex.'$#s';
}

public function compile(Route $route)
{
$compiled = new RouteCompiled(
$this->getPrefix($route),
$this->getUriRegex($route),
$this->getDomainRegex($route)
);

return $compiled;
}
}
34 changes: 21 additions & 13 deletions src/KM/Saffron/UrlMatcher/Generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
namespace KM\Saffron\UrlMatcher;

use KM\Saffron\RoutesCollection;
use KM\Saffron\RouteCompiler;
use KM\Saffron\Route;
use KM\Saffron\Code;

Expand All @@ -37,46 +38,50 @@ public function __construct(RoutesCollection $collection)
$this->code = new Code();
}

protected function conditionPrefix($route, &$conditions)
protected function conditionPrefix(Route $route, &$conditions)
{
if ($route->needsUriRegex()) {
$compiled = $route->getCompiled();

if ($compiled->hasUriRegex()) {
$conditions[] = sprintf(
'0 === strpos($uri, %s)',
var_export($route->getPrefix(), true)
var_export($compiled->getPrefix(), true)
);
}
else {
$conditions[] = sprintf(
'$uri == %s',
var_export($route->getPrefix(), true)
);
var_export($compiled->getPrefix(), true)
);
}
}

protected function conditionUriRegex(Route $route, array &$conditions)
{
if ($route->needsUriRegex()) {
$compiled = $route->getCompiled();

if ($compiled->hasUriRegex()) {
$conditions[] = sprintf(
'preg_match(%s, $uri, $uriMatch)',
var_export($route->getUriRegex(), true)
var_export($compiled->getUriRegex(), true)
);
}
}

protected function conditionHttps(Route $route, array &$conditions)
{
$https = $route->getHttps();
if (null !== $https) {
if ($route->hasHttps()) {
$conditions[] = sprintf(
'$https === %s',
var_export($https, true)
var_export($route->getHttps(), true)
);
}
}

protected function getArraysOfParameters(Route $route)
{
$arrays = [];
$compiled = $route->getCompiled();

if ($route->hasDefaults()) {
$arrays[] = $this->formatArray($route->getDefaults());
Expand All @@ -85,7 +90,7 @@ protected function getArraysOfParameters(Route $route)
if ($route->hasDomain()) {
$arrays[] = '$domainMatch';
}
if ($route->needsUriRegex()) {
if ($compiled->hasUriRegex()) {
$arrays[] = '$uriMatch';
}

Expand Down Expand Up @@ -167,7 +172,7 @@ protected function generateMatchMethod()
{
$this->code
->append('public function match(Request $request) {')
->append('$uri = $request->getUri();')
->append('$uri = $request->getUri();')
->append('$allowedMethods = [];');

if ($this->collection->hasMethod()) {
Expand All @@ -187,7 +192,10 @@ protected function generateMatchMethod()
$this->code->append(
sprintf(
'if (preg_match(%s, $domain, $domainMatch)) {',
var_export($routes->first()->getDomainRegex(), true)
var_export(
$routes->first()->getCompiled()->getDomainRegex(),
true
)
)
);
}
Expand Down

0 comments on commit e3593a5

Please sign in to comment.