<?php
namespace gnomephp\mvc\router;
class FromField{
private $source;
/**
* This will be set to true if /? is added to from field to allow additional anonymous vars.
* @var boolean
*/
private $anonymousVars=false;
/**
* Allows to match <Regexp> var
* or just var
*
* @var string
*/
const REGEXP_BITS = '/\/\{(?:<(.*?)>)?([A-Za-z0-9_]+)\}/';
public function __construct($source){
$this->source = $source;
}
public function toRegexp(){
// For per bit.
$regexp = '#'.preg_replace_callback(FromField::REGEXP_BITS, function($matches){
$r = '/'.($matches[1] ? '('.$matches[1].')' : '([A-Za-z0-9_-]+)');
return $r;
}, $this->source);
// Allow more arguments! /test/2/? also allows /test/2/1/0/-1/
if (substr($this->source, -2)=='/?'){
$regexp = substr($regexp, 0, -2);
$this->anonymousVars = true;
$regexp .= '(.*?)';
}
$regexp .= '$#';
return $regexp;
}
public function reverse($args){
$url = $this->source;
// Parse {key} to $args[$key] value
foreach($args as $k => $v){
$url = preg_replace('/\/\{(?:<.*?>)?('.$k.')\}/', '/'.$v, $url);
}
// Okay , we got a key set, but what if not all key => value is added....
// Its ok, we set them to empty value ( no value ).
$url = preg_replace('/(\{.*?\})/', '', $url);
// Return false if this doesn't match with anonymous vars.
if (!$this->anonymousVars){
$keys = array_keys($args);
foreach($keys as $k){
if (is_int($k))return false;
}
}else{
// Add support for anonymous vars
$url = substr($url, 0, -2);
foreach($args as $k => $v){
if (is_int($k)){
$url .= '/' . $v;
}
}
}
return new UrlString(substr($url, 1));
}
public function hasAnonymousVars(){
return $this->moreArgs;
}
public function getVars($values = array()){
$vars = array();
preg_match_all(FromField::REGEXP_BITS, $this->source, $vars);
$output = array();
$key = 1;
foreach($vars[2] as $k => $var){
$output[$var] = isset($values[$k+1]) ? $values[$k+1] : null;
$key++;
}
$anon = null;
if (isset ($values[$key]) && $values[$key] != ''){
$anon = explode('/', substr($values[$key], 1));
}
return array('vars' => $output, 'anonymousVars' => $anon);
}
}