Created
February 10, 2011 22:05
-
-
Save Svel/821450 to your computer and use it in GitHub Desktop.
Extend basic sfRequestRoute to accept optional variables
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Pager block example | |
* | |
* @author Svel <[email protected]> | |
* @url https://gist.github.com/gists/821450 | |
* @param sfDoctrinePager $pager | |
* @param string $route | |
* @param array $params | |
*/ | |
$params = isset($params) ? $params->getRawValue() : array(); | |
$array = create_function('$a,$b', 'return array_merge($b, array(\'page\' => $a,));'); | |
?> | |
<?php if ($pager->haveToPaginate()) : ?> | |
<div class="pagination"> | |
<a href="<?php echo url_for($route, $array($pager->getFirstPage(), $params)) ?>" class="first"><?php echo __('First', null, 'pager') ?></a> | |
<a href="<?php echo url_for($route, $array($pager->getPreviousPage(), $params)) ?>" class="previous"><?php echo __('Previous', null, 'pager') ?></a> | |
<?php foreach ($pager->getLinks() as $page) : ?> | |
<?php if ($page == $pager->getPage()) : ?> | |
<span class="current numbers"><?php echo $page ?></span> | |
<?php else : ?> | |
<a class="numbers" href="<?php echo url_for($route, $array($page, $params)) ?>"><?php echo $page ?></a> | |
<?php endif ?> | |
<?php endforeach ?> | |
<a href="<?php echo url_for($route, $array($pager->getNextPage(), $params)) ?>" class="next"><?php echo __('Next', null, 'pager') ?></a> | |
<a href="<?php echo url_for($route, $array($pager->getLastPage(), $params)) ?>" class="last"><?php echo __('Last', null, 'pager') ?></a> | |
</div> | |
<?php endif ?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Extend basic sfRequestRoute to accept optional variables | |
* use: | |
* url: /text/:variableRequired/:variableOptional.:sf_format | |
* matches: | |
* example.com/text/required/optional.html | |
* example.com/text/required.html | |
* | |
* @see http://trac.symfony-project.org/ticket/2478 | |
* @author Svel <[email protected]> | |
* @url https://gist.github.com/gists/821450 | |
*/ | |
class myExtendedRequestRoute extends sfRequestRoute | |
{ | |
/** | |
* Returns an array of parameters if the URL matches this route, false otherwise. | |
* | |
* @param string $url The URL | |
* @param array $context The context | |
* | |
* @return array An array of parameters | |
*/ | |
public function matchesUrl($url, $context = array()) | |
{ | |
if (!$this->compiled) { | |
$this->compile(); | |
} | |
// check the static prefix uf the URL first. Only use the more expensive preg_match when it matches | |
if ('' !== $this->staticPrefix && 0 !== strpos($url, $this->staticPrefix)) { | |
return false; | |
} | |
if (!preg_match($this->regex, $url, $matches)) { | |
return false; | |
} | |
$defaults = array_merge($this->getDefaultParameters(), $this->defaults); | |
$parameters = array(); | |
// * | |
if (isset($matches['_star'])) { | |
$parameters = $this->parseStarParameter($matches['_star']); | |
unset($matches['_star'], $parameters['module'], $parameters['action']); | |
} | |
// defaults | |
$parameters = $this->mergeArrays($defaults, $parameters); | |
// variables | |
foreach ($matches as $key => $value) { | |
// FIXED: $value must not be empty | |
if (!is_int($key) && $value) { | |
$parameters[$key] = urldecode($value); | |
} | |
} | |
return $parameters; | |
} | |
/** | |
* Generates a URL for the given parameters by using the route tokens. | |
* | |
* | |
* @param array $parameters An array of parameters | |
*/ | |
protected function generateWithTokens($parameters) | |
{ | |
$url = array(); | |
$optional = $this->options['generate_shortest_url']; | |
$first = true; | |
$tokens = array_reverse($this->tokens); | |
foreach ($tokens as $kkey => $token) { | |
switch ($token[0]) { | |
case 'variable': | |
// FIXED | |
if (preg_match('#\?$#', $token[3])) { | |
$token[3] = substr($token[3], 0, strlen($token[3])-1); | |
$optional = true; | |
} | |
if (!$optional || !isset($this->defaults[$token[3]]) || $parameters[$token[3]] != $this->defaults[$token[3]]) { | |
$url[] = urlencode($parameters[$token[3]]); | |
$optional = false; | |
} | |
break; | |
case 'text': | |
$url[] = $token[2]; | |
$optional = false; | |
break; | |
case 'separator': | |
if ( | |
(false === $optional || $first) | |
//&& | |
// custom condition to parse optional request parameters | |
//(array_key_exists($kkey - 1, $tokens) && !preg_match('#\?$#', $tokens[$kkey - 1][3])) | |
) { | |
$url[] = $token[2]; | |
} | |
break; | |
default: | |
// handle custom tokens | |
if ($segment = call_user_func_array(array($this, 'generateFor'.ucfirst(array_shift($token))), array_merge(array($optional, $parameters), $token))) { | |
$url[] = $segment; | |
$optional = false; | |
} | |
break; | |
} | |
$first = false; | |
} | |
$url = implode('', array_reverse($url)); | |
if (!$url) { | |
$url = '/'; | |
} | |
return $url; | |
} | |
/** | |
* Variable compiler extension | |
* Copypasted from sfRoute | |
* | |
* @param $separator | |
* @param $name | |
* @param $variable | |
*/ | |
protected function compileForVariable($separator, $name, $variable) | |
{ | |
$isQuestionMarked = false; | |
if (preg_match('#.+\?$#', $variable)) { | |
$variable = substr($variable, 0, strlen($variable) - 1); | |
$isQuestionMarked = true; | |
} | |
if (!isset($this->requirements[$variable])) { | |
$this->requirements[$variable] = $this->options['variable_content_regex']; | |
} | |
if ($isQuestionMarked) { | |
// makes variable with question mark at the end optional | |
$this->segments[] = '(?:'.preg_quote($separator, '#').'(?P<'.$variable.'>'.$this->requirements[$variable].'))?'; | |
} else { | |
// default way of parsing | |
$this->segments[] = preg_quote($separator, '#').'(?P<'.$variable.'>'.$this->requirements[$variable].')'; | |
} | |
$this->variables[$variable] = $name; | |
if (!isset($this->defaults[$variable])) { | |
$this->firstOptional = count($this->segments); | |
} | |
} | |
/** | |
* Extend user-defined and predefined variable_regex option by ? sign | |
* @see sfRoute | |
*/ | |
protected function initializeOptions() | |
{ | |
parent::initializeOptions(); | |
$this->options['variable_regex'] .= '\??'; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
require_once(dirname(__FILE__) . '/../../bootstrap/all.php'); | |
/** | |
* Route: extended sfRequest test | |
* | |
* @author Svel <[email protected]> | |
* @url https://gist.github.com/gists/821450 | |
*/ | |
class myExtendedRequestRouteTest extends myUnitTestCase | |
{ | |
/** | |
* Static url generation | |
* Check for base generation in case we breaks smth =/ | |
* | |
* @test | |
*/ | |
public function staticRootUrl() | |
{ | |
$route = new myExtendedRequestRoute('/', array(), array(), array('extra_parameters_as_query_string' => true)); | |
$this->assertTrue($route->matchesParameters(array()), 'Route matches request'); | |
$this->assertEquals(array(), $route->matchesUrl('/'), 'Route matches url'); | |
$this->assertTrue($route->matchesParameters(array('foo' => 'bar')), 'Extra parameters in query string'); | |
$this->assertEquals('/', $route->generate($params = array(), $context = array(), $isAbs = false)); | |
$this->assertEquals('/?foo=bar', $route->generate($params = array('foo' => 'bar'), $context = array(), $isAbs = false)); | |
} | |
/** | |
* Required and not required parameters testing | |
* | |
* @test | |
*/ | |
public function params() | |
{ | |
$params = array('required' => 'something', 'sf_format' => 'html'); | |
$paramsWithDefault = array_merge($params, array('param' => 1)); | |
$extended = array_merge($params, array('param' => 5)); | |
$route = new myExtendedRequestRoute( | |
'/static/:param?/:required.:sf_format', | |
array('param' => 1), | |
array(), array('extra_parameters_as_query_string' => true) | |
); | |
$this->assertFalse($route->matchesParameters(array()), 'Route NOT matches empty request'); | |
$this->assertTrue($route->matchesParameters($params), 'Route matches request with required params'); | |
$this->assertEquals($paramsWithDefault, $route->matchesUrl('/static/something.html'), 'Route matches url'); | |
$this->assertEquals('/static/something.html', $route->generate($params, $context = array(), $isAbs = false)); | |
$this->assertTrue($route->matchesParameters($extended), 'Route matches request with all params'); | |
$this->assertEquals($extended, $route->matchesUrl('/static/5/something.html'), 'Route matches url'); | |
$this->assertEquals('/static/5/something.html', $route->generate($extended, $context = array(), $isAbs = false)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# example route | |
cool_route_name: | |
url: /static/:section/static/:isOld?-:page?.:sf_format # special conditions with question mark | |
class: myExtendedRequestRoute | |
params: { module: myModule, action: myAction, page: 1, isOld: false } | |
options: { segment_separators: [/, -, .] } | |
requirements: | |
sf_method: [get, head] | |
sf_format: html | |
section: (?:[a-z0-9]{3,}) | |
page: (?:[2-9]|[1-9]\d+) | |
isOld: (?:1|0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment