Autodoc
  • Namespace
  • Class
  • Tree

Namespaces

  • BlueTihi
    • Context
  • Brickrouge
    • Element
      • Nodes
    • Renderer
    • Widget
  • ICanBoogie
    • ActiveRecord
    • AutoConfig
    • CLDR
    • Composer
    • Core
    • Event
    • Exception
    • HTTP
      • Dispatcher
      • Request
    • I18n
      • Translator
    • Mailer
    • Modules
      • Taxonomy
        • Support
      • Thumbnailer
        • Versions
    • Object
    • Operation
      • Dispatcher
    • Prototype
    • Routes
    • Routing
      • Dispatcher
    • Session
  • Icybee
    • ActiveRecord
      • Model
    • ConfigOperation
    • Document
    • EditBlock
    • Element
      • ActionbarContextual
      • ActionbarSearch
      • ActionbarToolbar
    • FormBlock
    • Installer
    • ManageBlock
    • Modules
      • Articles
      • Cache
        • Collection
        • ManageBlock
      • Comments
        • ManageBlock
      • Contents
        • ManageBlock
      • Dashboard
      • Editor
        • Collection
      • Files
        • File
        • ManageBlock
      • Forms
        • Form
        • ManageBlock
      • I18n
      • Images
        • ManageBlock
      • Members
      • Modules
        • ManageBlock
      • Nodes
        • ManageBlock
        • Module
      • Pages
        • BreadcrumbElement
        • LanguagesElement
        • ManageBlock
        • NavigationBranchElement
        • NavigationElement
        • Page
        • PageController
      • Registry
      • Search
      • Seo
      • Sites
        • ManageBlock
      • Taxonomy
        • Terms
          • ManageBlock
        • Vocabulary
          • ManageBlock
      • Users
        • ManageBlock
        • NonceLogin
        • Roles
      • Views
        • ActiveRecordProvider
        • Collection
        • View
    • Operation
      • ActiveRecord
      • Constructor
      • Module
      • Widget
    • Rendering
  • None
  • Patron
  • PHP

Classes

  • Controller
  • Dispatcher
  • Helpers
  • Pattern

Functions

  • contextualize
  • decontextualize
  1 <?php
  2 
  3 /*
  4  * This file is part of the ICanBoogie package.
  5  *
  6  * (c) Olivier Laviale <olivier.laviale@gmail.com>
  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 namespace ICanBoogie\Routing;
 13 
 14 use ICanBoogie\PropertyNotReadable;
 15 
 16 /**
 17  * Representation of a route pattern.
 18  *
 19  * <pre>
 20  * <?php
 21  *
 22  * use ICanBoogie\Routing\Pattern;
 23  *
 24  * $pattern = Pattern::from("/blog/<year:\d{4}>-<month:\d{2}>-:slug.html");
 25  * echo $pattern;       // "/blog/<year:\d{4}>-<month:\d{2}>-:slug.html"
 26  *
 27  * $pathname = $pattern->format(array('year' => "2013", 'month' => "07", 'slug' => "test-is-a-test"));
 28  * echo $pathname;      // "/blog/2013-07-this-is-a-test.html"
 29  *
 30  * $matching = $pattern->match($pathname, $captured);
 31  *
 32  * var_dump($matching); // true
 33  * var_dump($captured); // array('year' => "2013", 'month' => "07", 'slug' => "test-is-a-test")
 34  * </pre>
 35  *
 36  * @property-read string $pattern The pattern.
 37  * @property-read array $interleaved The interleaved parts of the pattern.
 38  * @property-read array $params The names of the pattern params.
 39  * @property-read string $regex The regex of the pattern.
 40  */
 41 class Pattern
 42 {
 43     /**
 44      * Parses a route pattern and returns an array of interleaved paths and parameters, the
 45      * parameter names and the regular expression for the specified pattern.
 46      *
 47      * @param string $pattern A pattern.
 48      *
 49      * @return array
 50      */
 51     static private function parse($pattern)
 52     {
 53         $regex = '#^';
 54         $interleaved = array();
 55         $params = array();
 56         $n = 0;
 57         $catchall = false;
 58 
 59         if ($pattern{strlen($pattern) - 1} == '*')
 60         {
 61             $catchall = true;
 62             $pattern = substr($pattern, 0, -1);
 63         }
 64 
 65         $parts = preg_split('#(:\w+|<(\w+:)?([^>]+)>)#', $pattern, -1, PREG_SPLIT_DELIM_CAPTURE);
 66 
 67         for ($i = 0, $j = count($parts); $i < $j ;)
 68         {
 69             $part = $parts[$i++];
 70 
 71             $regex .= preg_quote($part, '#');
 72             $interleaved[] = $part;
 73 
 74             if ($i == $j)
 75             {
 76                 break;
 77             }
 78 
 79             $part = $parts[$i++];
 80 
 81             if ($part{0} == ':')
 82             {
 83                 $identifier = substr($part, 1);
 84                 $separator = $parts[$i];
 85                 $selector = $separator ? '[^/\\' . $separator{0} . ']+' : '[^/]+';
 86             }
 87             else
 88             {
 89                 $identifier = substr($parts[$i++], 0, -1);
 90 
 91                 if (!$identifier)
 92                 {
 93                     $identifier = $n++;
 94                 }
 95 
 96                 $selector = $parts[$i++];
 97             }
 98 
 99             $regex .= '(' . $selector . ')';
100             $interleaved[] = array($identifier, $selector);
101             $params[] = $identifier;
102         }
103 
104         if (!$catchall)
105         {
106             $regex .= '$';
107         }
108 
109         $regex .= '#';
110 
111         return array($interleaved, $params, $regex);
112     }
113 
114     /**
115      * Checks if the given string is a route pattern.
116      *
117      * @param string $pattern
118      *
119      * @return bool `true` if the given pattern is a route pattern, `false` otherwise.
120      */
121     static public function is_pattern($pattern)
122     {
123         return (strpos($pattern, '<') !== false) || (strpos($pattern, ':') !== false);
124     }
125 
126     static private $instances;
127 
128     /**
129      * Creates a {@link Pattern} instance from the specified pattern.
130      *
131      * @param mixed $pattern
132      *
133      * @return \ICanBoogie\Pattern
134      */
135     static public function from($pattern)
136     {
137         if ($pattern instanceof static)
138         {
139             return $pattern;
140         }
141 
142         if (isset(self::$instances[$pattern]))
143         {
144             return self::$instances[$pattern];
145         }
146 
147         return self::$instances[$pattern] = new static($pattern);
148     }
149 
150     /**
151      * Pattern.
152      *
153      * @var string
154      */
155     protected $pattern;
156 
157     /**
158      * Interleaved pattern.
159      *
160      * @var array
161      */
162     protected $interleaved;
163 
164     /**
165      * Params of the pattern.
166      *
167      * @var array
168      */
169     protected $params;
170 
171     /**
172      * Regex of the pattern.
173      *
174      * @var string
175      */
176     protected $regex;
177 
178     /**
179      * Initializes the {@link $pattern}, {@link $interleaved}, {@link $params} and {@link $regex}
180      * properties.
181      *
182      * @param string $pattern A route pattern.
183      */
184     protected function __construct($pattern)
185     {
186         list($interleaved, $params, $regex) = self::parse($pattern);
187 
188         $this->pattern = $pattern;
189         $this->interleaved = $interleaved;
190         $this->params = $params;
191         $this->regex = $regex;
192     }
193 
194     /**
195      * Returns the route pattern specified during construct.
196      *
197      * @return string
198      */
199     public function __toString()
200     {
201         return $this->pattern;
202     }
203 
204     public function __get($property)
205     {
206         static $gettable = array('pattern', 'interleaved', 'params', 'regex');
207 
208         if (!in_array($property, $gettable))
209         {
210             throw new PropertyNotReadable(array($property, $this));
211         }
212 
213         return $this->$property;
214     }
215 
216     /**
217      * Formats a pattern with the specified values.
218      *
219      * @param mixed $values The values to format the pattern, either as an array or an object.
220      *
221      * @return string
222      */
223     public function format($values=null)
224     {
225         $url = '';
226 
227         if (is_array($values))
228         {
229             foreach ($this->interleaved as $i => $value)
230             {
231                 $url .= ($i % 2) ? urlencode($values[$value[0]]) : $value;
232             }
233         }
234         else
235         {
236             foreach ($this->interleaved as $i => $value)
237             {
238                 $url .= ($i % 2) ? urlencode($values->$value[0]) : $value;
239             }
240         }
241 
242         return $url;
243     }
244 
245     /**
246      * Checks if a pathname matches the pattern.
247      *
248      * @param string $pathname The pathname.
249      * @param array $captured The parameters captured from the pathname.
250      *
251      * @return boolean `true` if the pathname matches the pattern, `false` otherwise.
252      */
253     public function match($pathname, &$captured=null)
254     {
255         #
256         # `params` is empty if the pattern is a plain string,
257         # thus we can simply compare strings.
258         #
259 
260         if (!$this->params)
261         {
262             return $pathname === $this->pattern;
263         }
264 
265         if (!preg_match($this->regex, $pathname, $matches))
266         {
267             return false;
268         }
269 
270         array_shift($matches);
271 
272         $captured = array_combine($this->params, $matches);
273 
274         return true;
275     }
276 }
Autodoc API documentation generated by ApiGen 2.8.0