Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
 
3
/*
4
 * This file is part of the symfony package.
5
 * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
 
11
/**
12
 * sfRoute represents a route.
13
 *
14
 * @package    symfony
15
 * @subpackage routing
16
 * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
17
 * @version    SVN: $Id: sfRoute.class.php 32652 2011-06-15 17:44:19Z fabien $
18
 */
19
class sfRoute implements Serializable
20
{
21
  protected
22
    $isBound           = false,
23
    $context           = null,
24
    $parameters        = null,
25
    $suffix            = null,
26
    $defaultParameters = array(),
27
    $defaultOptions    = array(),
28
    $compiled          = false,
29
    $options           = array(),
30
    $pattern           = null,
31
    $staticPrefix      = null,
32
    $regex             = null,
33
    $variables         = array(),
34
    $defaults          = array(),
35
    $requirements      = array(),
36
    $tokens            = array(),
37
    $customToken       = false;
38
 
39
  /**
40
   * Constructor.
41
   *
42
   * Available options:
43
   *
44
   *  * variable_prefixes:                An array of characters that starts a variable name (: by default)
45
   *  * segment_separators:               An array of allowed characters for segment separators (/ and . by default)
46
   *  * variable_regex:                   A regex that match a valid variable name ([\w\d_]+ by default)
47
   *  * generate_shortest_url:            Whether to generate the shortest URL possible (true by default)
48
   *  * extra_parameters_as_query_string: Whether to generate extra parameters as a query string
49
   *
50
   * @param string $pattern       The pattern to match
51
   * @param array  $defaults      An array of default parameter values
52
   * @param array  $requirements  An array of requirements for parameters (regexes)
53
   * @param array  $options       An array of options
54
   */
55
  public function __construct($pattern, array $defaults = array(), array $requirements = array(), array $options = array())
56
  {
57
    $this->pattern      = trim($pattern);
58
    $this->defaults     = $defaults;
59
    $this->requirements = $requirements;
60
    $this->options      = $options;
61
  }
62
 
63
  /**
64
   * Binds the current route for a given context and parameters.
65
   *
66
   * @param array $context    The context
67
   * @param array $parameters The parameters
68
   */
69
  public function bind($context, $parameters)
70
  {
71
    $this->isBound    = true;
72
    $this->context    = $context;
73
    $this->parameters = $parameters;
74
  }
75
 
76
  /**
77
   * Returns true if the route is bound to context and parameters.
78
   *
79
   * @return Boolean true if theroute is bound to context and parameters, false otherwise
80
   */
81
  public function isBound()
82
  {
83
    return $this->isBound;
84
  }
85
 
86
  /**
87
   * Returns an array of parameters if the URL matches this route, false otherwise.
88
   *
89
   * @param  string  $url     The URL
90
   * @param  array   $context The context
91
   *
92
   * @return array   An array of parameters
93
   */
94
  public function matchesUrl($url, $context = array())
95
  {
96
    if (!$this->compiled)
97
    {
98
      $this->compile();
99
    }
100
 
101
    // check the static prefix uf the URL first. Only use the more expensive preg_match when it matches
102
    if ('' !== $this->staticPrefix  && 0 !== strpos($url, $this->staticPrefix))
103
    {
104
      return false;
105
    }
106
    if (!preg_match($this->regex, $url, $matches))
107
    {
108
      return false;
109
    }
110
 
111
    $defaults   = array_merge($this->getDefaultParameters(), $this->defaults);
112
    $parameters = array();
113
 
114
    // *
115
    if (isset($matches['_star']))
116
    {
117
      $parameters = $this->parseStarParameter($matches['_star']);
118
      unset($matches['_star'], $parameters['module'], $parameters['action']);
119
    }
120
 
121
    // defaults
122
    $parameters = $this->mergeArrays($defaults, $parameters);
123
 
124
    // variables
125
    foreach ($matches as $key => $value)
126
    {
127
      if (!is_int($key))
128
      {
129
        $parameters[$key] = urldecode($value);
130
      }
131
    }
132
 
133
    return $parameters;
134
  }
135
 
136
  /**
137
   * Returns true if the parameters matches this route, false otherwise.
138
   *
139
   * @param  mixed  $params  The parameters
140
   * @param  array  $context The context
141
   *
142
   * @return Boolean         true if the parameters matches this route, false otherwise.
143
   */
144
  public function matchesParameters($params, $context = array())
145
  {
146
    if (!$this->compiled)
147
    {
148
      $this->compile();
149
    }
150
 
151
    if (!is_array($params))
152
    {
153
      return false;
154
    }
155
 
156
    $defaults = $this->mergeArrays($this->getDefaultParameters(), $this->defaults);
157
    $tparams = $this->mergeArrays($defaults, $params);
158
 
159
    // all $variables must be defined in the $tparams array
160
    if (array_diff_key($this->variables, $tparams))
161
    {
162
      return false;
163
    }
164
 
165
    // check requirements
166
    foreach (array_keys($this->variables) as $variable)
167
    {
168
      if (!$tparams[$variable])
169
      {
170
        continue;
171
      }
172
 
173
      if (!preg_match('#'.$this->requirements[$variable].'#', $tparams[$variable]))
174
      {
175
        return false;
176
      }
177
    }
178
 
179
    // all $params must be in $variables or $defaults if there is no * in route
180
    if (!$this->options['extra_parameters_as_query_string'])
181
    {
182
      if (false === strpos($this->regex, '<_star>') && array_diff_key($params, $this->variables, $defaults))
183
      {
184
        return false;
185
      }
186
    }
187
 
188
    // check that $params does not override a default value that is not a variable
189
    foreach ($defaults as $key => $value)
190
    {
191
      if (!isset($this->variables[$key]) && $tparams[$key] != $value)
192
      {
193
        return false;
194
      }
195
    }
196
 
197
    return true;
198
  }
199
 
200
  /**
201
   * Generates a URL from the given parameters.
202
   *
203
   * @param  mixed   $params    The parameter values
204
   * @param  array   $context   The context
205
   * @param  Boolean $absolute  Whether to generate an absolute URL
206
   *
207
   * @return string The generated URL
208
   */
209
  public function generate($params, $context = array(), $absolute = false)
210
  {
211
    if (!$this->compiled)
212
    {
213
      $this->compile();
214
    }
215
 
216
    $url = $this->pattern;
217
 
218
    $defaults = $this->mergeArrays($this->getDefaultParameters(), $this->defaults);
219
    $tparams = $this->mergeArrays($defaults, $params);
220
 
221
    // all params must be given
222
    if ($diff = array_diff_key($this->variables, $tparams))
223
    {
224
      throw new InvalidArgumentException(sprintf('The "%s" route has some missing mandatory parameters (%s).', $this->pattern, implode(', ', $diff)));
225
    }
226
 
227
    if ($this->options['generate_shortest_url'] || $this->customToken)
228
    {
229
      $url = $this->generateWithTokens($tparams);
230
    }
231
    else
232
    {
233
      // replace variables
234
      $variables = $this->variables;
235
      uasort($variables, create_function('$a, $b', 'return strlen($a) < strlen($b);'));
236
      foreach ($variables as $variable => $value)
237
      {
238
        $url = str_replace($value, urlencode($tparams[$variable]), $url);
239
      }
240
 
241
      if(!in_array($this->suffix, $this->options['segment_separators']))
242
      {
243
        $url .= $this->suffix;
244
      }
245
    }
246
 
247
    // replace extra parameters if the route contains *
248
    $url = $this->generateStarParameter($url, $defaults, $tparams);
249
 
250
    if ($this->options['extra_parameters_as_query_string'] && !$this->hasStarParameter())
251
    {
252
      // add a query string if needed
253
      if ($extra = array_diff_key($params, $this->variables, $defaults))
254
      {
255
        $url .= '?'.http_build_query($extra);
256
      }
257
    }
258
 
259
    return $url;
260
  }
261
 
262
  /**
263
   * Generates a URL for the given parameters by using the route tokens.
264
   *
265
   * @param array $parameters An array of parameters
266
   */
267
  protected function generateWithTokens($parameters)
268
  {
269
    $url = array();
270
    $optional = $this->options['generate_shortest_url'];
271
    $first = true;
272
    $tokens = array_reverse($this->tokens);
273
    foreach ($tokens as $token)
274
    {
275
      switch ($token[0])
276
      {
277
        case 'variable':
278
          if (!$optional || !isset($this->defaults[$token[3]]) || $parameters[$token[3]] != $this->defaults[$token[3]])
279
          {
280
            $url[] = urlencode($parameters[$token[3]]);
281
            $optional = false;
282
          }
283
          break;
284
        case 'text':
285
          $url[] = $token[2];
286
          $optional = false;
287
          break;
288
        case 'separator':
289
          if (false === $optional || $first)
290
          {
291
            $url[] = $token[2];
292
          }
293
          break;
294
        default:
295
          // handle custom tokens
296
          if ($segment = call_user_func_array(array($this, 'generateFor'.ucfirst(array_shift($token))), array_merge(array($optional, $parameters), $token)))
297
          {
298
            $url[] = $segment;
299
            $optional = false;
300
          }
301
          break;
302
      }
303
 
304
      $first = false;
305
    }
306
 
307
    $url = implode('', array_reverse($url));
308
    if (!$url)
309
    {
310
      $url = '/';
311
    }
312
 
313
    return $url;
314
  }
315
 
316
  /**
317
   * Returns the route parameters.
318
   *
319
   * @return array The route parameters
320
   */
321
  public function getParameters()
322
  {
323
    if (!$this->compiled)
324
    {
325
      $this->compile();
326
    }
327
 
328
    return $this->parameters;
329
  }
330
 
331
  /**
332
   * Returns the compiled pattern.
333
   *
334
   * @return string The compiled pattern
335
   */
336
  public function getPattern()
337
  {
338
    if (!$this->compiled)
339
    {
340
      $this->compile();
341
    }
342
 
343
    return $this->pattern;
344
  }
345
 
346
  /**
347
   * Returns the compiled regex.
348
   *
349
   * @return string The compiled regex
350
   */
351
  public function getRegex()
352
  {
353
    if (!$this->compiled)
354
    {
355
      $this->compile();
356
    }
357
 
358
    return $this->regex;
359
  }
360
 
361
  /**
362
   * Returns the compiled tokens.
363
   *
364
   * @return array The compiled tokens
365
   */
366
  public function getTokens()
367
  {
368
    if (!$this->compiled)
369
    {
370
      $this->compile();
371
    }
372
 
373
    return $this->tokens;
374
  }
375
 
376
  /**
377
   * Returns the compiled options.
378
   *
379
   * @return array The compiled options
380
   */
381
  public function getOptions()
382
  {
383
    if (!$this->compiled)
384
    {
385
      $this->compile();
386
    }
387
 
388
    return $this->options;
389
  }
390
 
391
  /**
392
   * Returns the compiled variables.
393
   *
394
   * @return array The compiled variables
395
   */
396
  public function getVariables()
397
  {
398
    if (!$this->compiled)
399
    {
400
      $this->compile();
401
    }
402
 
403
    return $this->variables;
404
  }
405
 
406
  /**
407
   * Returns the compiled defaults.
408
   *
409
   * @return array The compiled defaults
410
   */
411
  public function getDefaults()
412
  {
413
    if (!$this->compiled)
414
    {
415
      $this->compile();
416
    }
417
 
418
    return $this->defaults;
419
  }
420
 
421
  /**
422
   * Returns the compiled requirements.
423
   *
424
   * @return array The compiled requirements
425
   */
426
  public function getRequirements()
427
  {
428
    if (!$this->compiled)
429
    {
430
      $this->compile();
431
    }
432
 
433
    return $this->requirements;
434
  }
435
 
436
  /**
437
   * Compiles the current route instance.
438
   */
439
  public function compile()
440
  {
441
    if ($this->compiled)
442
    {
443
      return;
444
    }
445
 
446
    $this->initializeOptions();
447
    $this->fixRequirements();
448
    $this->fixDefaults();
449
    $this->fixSuffix();
450
 
451
    $this->compiled = true;
452
    $this->firstOptional = 0;
453
    $this->segments = array();
454
 
455
    $this->preCompile();
456
 
457
    $this->tokenize();
458
 
459
    // parse
460
    foreach ($this->tokens as $token)
461
    {
462
      call_user_func_array(array($this, 'compileFor'.ucfirst(array_shift($token))), $token);
463
    }
464
 
465
    $this->postCompile();
466
 
467
    $separator = '';
468
    if (count($this->tokens))
469
    {
470
      $lastToken = $this->tokens[count($this->tokens) - 1];
471
      $separator = 'separator' == $lastToken[0] ? $lastToken[2] : '';
472
    }
473
 
474
    $this->regex = "#^".implode("", $this->segments)."".preg_quote($separator, '#')."$#x";
475
  }
476
 
477
  /**
478
   * Pre-compiles a route.
479
   */
480
  protected function preCompile()
481
  {
482
    // a route must start with a slash
483
    if (empty($this->pattern) || '/' != $this->pattern[0])
484
    {
485
      $this->pattern = '/'.$this->pattern;
486
    }
487
  }
488
 
489
  /**
490
   * Post-compiles a route.
491
   */
492
  protected function postCompile()
493
  {
494
    // all segments after the last static segment are optional
495
    // be careful, the n-1 is optional only if n is empty
496
    for ($i = $this->firstOptional, $max = count($this->segments); $i < $max; $i++)
497
    {
498
      $this->segments[$i] = (0 == $i ? '/?' : '').str_repeat(' ', $i - $this->firstOptional).'(?:'.$this->segments[$i];
499
      $this->segments[] = str_repeat(' ', $max - $i - 1).')?';
500
    }
501
 
502
    $this->staticPrefix = '';
503
    foreach ($this->tokens as $token)
504
    {
505
      switch ($token[0])
506
      {
507
        case 'separator':
508
          break;
509
        case 'text':
510
          if ($token[2] !== '*')
511
          {
512
            // non-star text is static
513
            $this->staticPrefix .= $token[1].$token[2];
514
            break;
515
          }
516
        default:
517
          // everything else indicates variable parts. break switch and for loop
518
          break 2;
519
      }
520
    }
521
  }
522
 
523
  /**
524
   * Tokenizes the route.
525
   */
526
  protected function tokenize()
527
  {
528
    $this->tokens = array();
529
    $buffer = $this->pattern;
530
    $afterASeparator = false;
531
    $currentSeparator = '';
532
 
533
    // a route is an array of (separator + variable) or (separator + text) segments
534
    while (strlen($buffer))
535
    {
536
      if (false !== $this->tokenizeBufferBefore($buffer, $this->tokens, $afterASeparator, $currentSeparator))
537
      {
538
        // a custom token
539
        $this->customToken = true;
540
      }
541
      else if ($afterASeparator && preg_match('#^'.$this->options['variable_prefix_regex'].'('.$this->options['variable_regex'].')#', $buffer, $match))
542
      {
543
        // a variable
544
        $this->tokens[] = array('variable', $currentSeparator, $match[0], $match[1]);
545
 
546
        $currentSeparator = '';
547
        $buffer = substr($buffer, strlen($match[0]));
548
        $afterASeparator = false;
549
      }
550
      else if ($afterASeparator && preg_match('#^('.$this->options['text_regex'].')(?:'.$this->options['segment_separators_regex'].'|$)#', $buffer, $match))
551
      {
552
        // a text
553
        $this->tokens[] = array('text', $currentSeparator, $match[1], null);
554
 
555
        $currentSeparator = '';
556
        $buffer = substr($buffer, strlen($match[1]));
557
        $afterASeparator = false;
558
      }
559
      else if (!$afterASeparator && preg_match('#^/|^'.$this->options['segment_separators_regex'].'#', $buffer, $match))
560
      {
561
        // beginning of URL (^/) or a separator
562
        $this->tokens[] = array('separator', $currentSeparator, $match[0], null);
563
 
564
        $currentSeparator = $match[0];
565
        $buffer = substr($buffer, strlen($match[0]));
566
        $afterASeparator = true;
567
      }
568
      else if (false !== $this->tokenizeBufferAfter($buffer, $this->tokens, $afterASeparator, $currentSeparator))
569
      {
570
        // a custom token
571
        $this->customToken = true;
572
      }
573
      else
574
      {
575
        // parsing problem
576
        throw new InvalidArgumentException(sprintf('Unable to parse "%s" route near "%s".', $this->pattern, $buffer));
577
      }
578
    }
579
 
580
    // check for suffix
581
    if ($this->suffix)
582
    {
583
      // treat as a separator
584
      $this->tokens[] = array('separator', $currentSeparator, $this->suffix);
585
    }
586
 
587
  }
588
 
589
  /**
590
   * Tokenizes the buffer before default logic is applied.
591
   *
592
   * This method must return false if the buffer has not been parsed.
593
   *
594
   * @param string   $buffer           The current route buffer
595
   * @param array    $tokens           An array of current tokens
596
   * @param Boolean  $afterASeparator  Whether the buffer is just after a separator
597
   * @param string   $currentSeparator The last matched separator
598
   *
599
   * @return Boolean true if a token has been generated, false otherwise
600
   */
601
  protected function tokenizeBufferBefore(&$buffer, &$tokens, &$afterASeparator, &$currentSeparator)
602
  {
603
    return false;
604
  }
605
 
606
  /**
607
   * Tokenizes the buffer after default logic is applied.
608
   *
609
   * This method must return false if the buffer has not been parsed.
610
   *
611
   * @param string   $buffer           The current route buffer
612
   * @param array    $tokens           An array of current tokens
613
   * @param Boolean  $afterASeparator  Whether the buffer is just after a separator
614
   * @param string   $currentSeparator The last matched separator
615
   *
616
   * @return Boolean true if a token has been generated, false otherwise
617
   */
618
  protected function tokenizeBufferAfter(&$buffer, &$tokens, &$afterASeparator, &$currentSeparator)
619
  {
620
    return false;
621
  }
622
 
623
  protected function compileForText($separator, $text)
624
  {
625
    if ('*' == $text)
626
    {
627
      $this->segments[] = '(?:'.preg_quote($separator, '#').'(?P<_star>.*))?';
628
    }
629
    else
630
    {
631
      $this->firstOptional = count($this->segments) + 1;
632
 
633
      $this->segments[] = preg_quote($separator, '#').preg_quote($text, '#');
634
    }
635
  }
636
 
637
  protected function compileForVariable($separator, $name, $variable)
638
  {
639
    if (!isset($this->requirements[$variable]))
640
    {
641
      $this->requirements[$variable] = $this->options['variable_content_regex'];
642
    }
643
 
644
    $this->segments[] = preg_quote($separator, '#').'(?P<'.$variable.'>'.$this->requirements[$variable].')';
645
    $this->variables[$variable] = $name;
646
 
647
    if (!isset($this->defaults[$variable]))
648
    {
649
      $this->firstOptional = count($this->segments);
650
    }
651
  }
652
 
653
  protected function compileForSeparator($separator, $regexSeparator)
654
  {
655
  }
656
 
657
  public function getDefaultParameters()
658
  {
659
    return $this->defaultParameters;
660
  }
661
 
662
  public function setDefaultParameters($parameters)
663
  {
664
    $this->defaultParameters = $parameters;
665
  }
666
 
667
  public function getDefaultOptions()
668
  {
669
    return $this->defaultOptions;
670
  }
671
 
672
  public function setDefaultOptions($options)
673
  {
674
    $this->defaultOptions = $options;
675
  }
676
 
677
  protected function initializeOptions()
678
  {
679
    $this->options = array_merge(array(
680
      'suffix'                           => '',
681
      'variable_prefixes'                => array(':'),
682
      'segment_separators'               => array('/', '.'),
683
      'variable_regex'                   => '[\w\d_]+',
684
      'text_regex'                       => '.+?',
685
      'generate_shortest_url'            => true,
686
      'extra_parameters_as_query_string' => true,
687
    ), $this->getDefaultOptions(), $this->options);
688
 
689
    $preg_quote_hash = create_function('$a', 'return preg_quote($a, \'#\');');
690
 
691
    // compute some regexes
692
    $this->options['variable_prefix_regex'] = '(?:'.implode('|', array_map($preg_quote_hash, $this->options['variable_prefixes'])).')';
693
 
694
    if (count($this->options['segment_separators']))
695
    {
696
      $this->options['segment_separators_regex'] = '(?:'.implode('|', array_map($preg_quote_hash, $this->options['segment_separators'])).')';
697
 
698
      // as of PHP 5.3.0, preg_quote automatically quotes dashes "-" (see http://bugs.php.net/bug.php?id=47229)
699
      $preg_quote_hash_53 = create_function('$a', 'return str_replace(\'-\', \'\-\', preg_quote($a, \'#\'));');
700
      $this->options['variable_content_regex'] = '[^'.implode('',
701
          array_map(version_compare(PHP_VERSION, '5.3.0RC4', '>=') ? $preg_quote_hash : $preg_quote_hash_53, $this->options['segment_separators'])
702
        ).']+';
703
    }
704
    else
705
    {
706
      // use simplified regexes for case where no separators are used
707
      $this->options['segment_separators_regex'] = '()';
708
      $this->options['variable_content_regex']   = '.+';
709
    }
710
  }
711
 
712
  protected function parseStarParameter($star)
713
  {
714
    $parameters = array();
715
    $tmp = explode('/', $star);
716
    for ($i = 0, $max = count($tmp); $i < $max; $i += 2)
717
    {
718
      //dont allow a param name to be empty - #4173
719
      if (!empty($tmp[$i]))
720
      {
721
        $parameters[$tmp[$i]] = isset($tmp[$i + 1]) ? urldecode($tmp[$i + 1]) : true;
722
      }
723
    }
724
 
725
    return $parameters;
726
  }
727
 
728
  protected function hasStarParameter()
729
  {
730
    return false !== strpos($this->regex, '<_star>');
731
  }
732
 
733
  protected function generateStarParameter($url, $defaults, $parameters)
734
  {
735
    if (false === strpos($this->regex, '<_star>'))
736
    {
737
      return $url;
738
    }
739
 
740
    $tmp = array();
741
    foreach (array_diff_key($parameters, $this->variables, $defaults) as $key => $value)
742
    {
743
      if (is_array($value))
744
      {
745
        foreach ($value as $v)
746
        {
747
          $tmp[] = $key.'='.urlencode($v);
748
        }
749
      }
750
      else
751
      {
752
        $tmp[] = urlencode($key).'/'.urlencode($value);
753
      }
754
    }
755
    $tmp = implode('/', $tmp);
756
    if ($tmp)
757
    {
758
      $tmp = '/'.$tmp;
759
    }
760
 
761
    return preg_replace('#'.$this->options['segment_separators_regex'].'\*('.$this->options['segment_separators_regex'].'|$)#', "$tmp$1", $url);
762
  }
763
 
764
  protected function mergeArrays($arr1, $arr2)
765
  {
766
    foreach ($arr2 as $key => $value)
767
    {
768
      $arr1[$key] = $value;
769
    }
770
 
771
    return $arr1;
772
  }
773
 
774
  protected function fixDefaults()
775
  {
776
    foreach ($this->defaults as $key => $value)
777
    {
778
      if (ctype_digit($key))
779
      {
780
        $this->defaults[$value] = true;
781
      }
782
      else
783
      {
784
        $this->defaults[$key] = urldecode($value);
785
      }
786
    }
787
  }
788
 
789
  protected function fixRequirements()
790
  {
791
    foreach ($this->requirements as $key => $regex)
792
    {
793
      if (!is_string($regex))
794
      {
795
        continue;
796
      }
797
 
798
      if ('^' == $regex[0])
799
      {
800
        $regex = substr($regex, 1);
801
      }
802
      if ('$' == substr($regex, -1))
803
      {
804
        $regex = substr($regex, 0, -1);
805
      }
806
 
807
      $this->requirements[$key] = $regex;
808
    }
809
  }
810
 
811
  protected function fixSuffix()
812
  {
813
    $length = strlen($this->pattern);
814
 
815
    if ($length > 0 && '/' == $this->pattern[$length - 1])
816
    {
817
      // route ends by / (directory)
818
      $this->suffix = '/';
819
    }
820
    else if ($length > 0 && '.' == $this->pattern[$length - 1])
821
    {
822
      // route ends by . (no suffix)
823
      $this->suffix = '';
824
      $this->pattern = substr($this->pattern, 0, $length - 1);
825
    }
826
    else if (preg_match('#\.(?:'.$this->options['variable_prefix_regex'].$this->options['variable_regex'].'|'.$this->options['variable_content_regex'].')$#i', $this->pattern))
827
    {
828
      // specific suffix for this route
829
      // a . with a variable after or some chars without any separators
830
      $this->suffix = '';
831
    }
832
    else
833
    {
834
      $this->suffix = $this->options['suffix'];
835
    }
836
  }
837
 
838
  public function serialize()
839
  {
840
    // always serialize compiled routes
841
    $this->compile();
842
    // sfPatternRouting will always re-set defaultParameters, so no need to serialize them
843
    return serialize(array($this->tokens, $this->defaultOptions, $this->options, $this->pattern, $this->staticPrefix, $this->regex, $this->variables, $this->defaults, $this->requirements, $this->suffix, $this->customToken));
844
  }
845
 
846
  public function unserialize($data)
847
  {
848
    list($this->tokens, $this->defaultOptions, $this->options, $this->pattern, $this->staticPrefix, $this->regex, $this->variables, $this->defaults, $this->requirements, $this->suffix, $this->customToken) = unserialize($data);
849
    $this->compiled = true;
850
  }
851
}