GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — develop ( a7c8b8...eba62c )
by Lonnie
09:12
created
myth/Route.php 1 patch
Indentation   +639 added lines, -639 removed lines patch added patch discarded remove patch
@@ -43,644 +43,644 @@
 block discarded – undo
43 43
 class Route
44 44
 {
45 45
 
46
-    // Our routes, ripe for the picking.
47
-    public $routes = array();
48
-
49
-    // Holds key/value pairs of named routes
50
-    public static $names = array();
51
-
52
-    // Used for grouping routes together.
53
-    public $group = null;
54
-
55
-    // Holds the 'areas' of the site.
56
-    public static $areas = array();
57
-
58
-    // The default controller to use in case
59
-    // 'default_controller' is not in the routes file.
60
-    protected $default_home = 'home';
61
-
62
-    // The default constraint to use in route building
63
-    protected $default_constraint = 'any';
64
-
65
-    protected $constraints = [
66
-        'any'  => '(:any)',
67
-        'num'  => '(:num)',
68
-        'id'   => '(:num)',
69
-        'name' => "([a-zA-Z']+)"
70
-    ];
71
-
72
-    protected $current_subdomain = null;
73
-
74
-    //--------------------------------------------------------------------
75
-
76
-    /**
77
-     * Combines the routes that we've defined with the Route class with the
78
-     * routes passed in. This is intended to be used  after all routes have been
79
-     * defined to merge CI's default $route array with our routes.
80
-     *
81
-     * Example:
82
-     *     $route['default_controller'] = 'home';
83
-     *     Route::resource('posts');
84
-     *     $route = Route::map($route);
85
-     *
86
-     * @param array $routes
87
-     * @internal param array $route The array to merge
88
-     * @return array         The merge route array.
89
-     */
90
-    public function map($routes = array())
91
-    {
92
-        $controller = isset($routes['default_controller']) ? $routes['default_controller'] : $this->default_home;
93
-
94
-        $routes = array_merge($routes, $this->routes);
95
-
96
-        foreach ($routes as $from => $to) {
97
-            $routes[$from] = str_ireplace('{default_controller}', $controller, $to);
98
-        }
99
-
100
-        return $routes;
101
-    }
102
-
103
-    //--------------------------------------------------------------------
104
-
105
-    /**
106
-     * A single point to the basic routing. Can be used in place of CI's $route
107
-     * array if desired. Used internally by many of the methods.
108
-     *
109
-     * Available options are currently:
110
-     *      'as'        - remembers the route via a name that can be called outside of it.
111
-     *      'offset'    - Offsets and parameters ($1, $2, etc) in routes by the specified amount.
112
-     *                    Useful while doing versioning of API's, etc.
113
-     *
114
-     * Example:
115
-     *      $route->any('news', 'posts/index');
116
-     *
117
-     * @param string $from
118
-     * @param string $to
119
-     * @param array  $options
120
-     * @return void
121
-     */
122
-    public function any($from, $to, $options = array())
123
-    {
124
-        $this->create($from, $to, $options);
125
-    }
126
-
127
-    //--------------------------------------------------------------------
128
-
129
-    /**
130
-     * Sets the default constraint to be used in the system. Typically
131
-     * for use with the 'resources' method.
132
-     *
133
-     * @param $constraint
134
-     */
135
-    public function setDefaultConstraint($constraint)
136
-    {
137
-        if (array_key_exists($constraint, $this->constraints)) {
138
-            $this->default_constraint = $constraint;
139
-        }
140
-    }
141
-
142
-    //--------------------------------------------------------------------
143
-
144
-    /**
145
-     * Registers a new constraint to be used internally. Useful for creating
146
-     * very specific regex patterns, or simply to allow your routes to be
147
-     * a tad more readable.
148
-     *
149
-     * Example:
150
-     *      $route->registerConstraint('hero', '(^.*)');
151
-     *
152
-     *      $route->any('home/{hero}', 'heroes/journey');
153
-     *
154
-     *      // Route then looks like:
155
-     *      $route['home/(^.*)'] = 'heroes/journey';
156
-     *
157
-     * @param      $name
158
-     * @param      $pattern
159
-     * @param bool $overwrite
160
-     */
161
-    public function registerConstraint($name, $pattern, $overwrite = false)
162
-    {
163
-        // Ensure consistency
164
-        $name    = trim($name, '{} ');
165
-        $pattern = '(' . trim($pattern, '() ') . ')';
166
-
167
-        // Not here? Add it and leave...
168
-        if (! array_key_exists($name, $this->constraints)) {
169
-            $this->constraints[$name] = $pattern;
170
-
171
-            return;
172
-        }
173
-
174
-        // Here? Then it exists. Should we overwrite it?
175
-        if ($overwrite) {
176
-            $this->constraints[$name] = $pattern;
177
-        }
178
-    }
179
-
180
-    //--------------------------------------------------------------------
181
-
182
-    //--------------------------------------------------------------------
183
-    // Named Routes
184
-    //--------------------------------------------------------------------
185
-
186
-    /**
187
-     * Returns the value of a named route. Useful for getting named
188
-     * routes for use while building with site_url() or in templates
189
-     * where you don't need to instantiate the route class.
190
-     *
191
-     * Example:
192
-     *      $route->any('news', 'posts/index', ['as' => 'blog']);
193
-     *
194
-     *      // Returns http://mysite.com/news
195
-     *      site_url( Route::named('blog') );
196
-     *
197
-     * @param  [type] $name [description]
198
-     * @return [type]       [description]
199
-     */
200
-    public static function named($name)
201
-    {
202
-        if (isset(self::$names[$name])) {
203
-            return self::$names[$name];
204
-        }
205
-
206
-        return null;
207
-    }
208
-
209
-    //--------------------------------------------------------------------
210
-
211
-    //--------------------------------------------------------------------
212
-    // Grouping Routes
213
-    //--------------------------------------------------------------------
214
-
215
-    /**
216
-     * Group a series of routes under a single URL segment. This is handy
217
-     * for grouping items into an admin area, like:
218
-     *
219
-     * Example:
220
-     *     $route->group('admin', function() {
221
-     *            $route->resources('users');
222
-     *     });
223
-     *
224
-     * @param  string   $name     The name to group/prefix the routes with.
225
-     * @param  \Closure $callback An anonymous function that allows you route inside of this group.
226
-     * @return void
227
-     */
228
-    public function group($name, \Closure $callback)
229
-    {
230
-        $old_group = $this->group;
231
-
232
-        // To register a route, we'll set a flag so that our router
233
-        // so it will see the groupname.
234
-        $this->group = ltrim($old_group . '/' . $name, '/');
235
-
236
-        call_user_func($callback);
237
-
238
-        // Make sure to clear the group name so we don't accidentally
239
-        // group any ones we didn't want to.
240
-        $this->group = $old_group;
241
-    }
242
-
243
-    //--------------------------------------------------------------------
244
-
245
-    //--------------------------------------------------------------------
246
-    // HTTP Verb-based routing
247
-    //--------------------------------------------------------------------
248
-    // Routing works here because, as the routes config file is read in,
249
-    // the various HTTP verb-based routes will only be added to the in-memory
250
-    // routes if it is a call that should respond to that verb.
251
-    //
252
-    // The options array is typically used to pass in an 'as' or var, but may
253
-    // be expanded in the future. See the docblock for 'any' method above for
254
-    // current list of globally available options.
255
-    //
256
-
257
-    /**
258
-     * Specifies a single route to match for multiple HTTP Verbs.
259
-     *
260
-     * Example:
261
-     *  $route->match( ['get', 'post'], 'users/(:num)', 'users/$1);
262
-     *
263
-     * @param array $verbs
264
-     * @param       $from
265
-     * @param       $to
266
-     * @param array $options
267
-     */
268
-    public function match($verbs = [], $from, $to, $options = [])
269
-    {
270
-        foreach ($verbs as $verb) {
271
-            $verb = strtolower($verb);
272
-
273
-            $this->{$verb}($from, $to, $options);
274
-        }
275
-    }
276
-
277
-    //--------------------------------------------------------------------
278
-
279
-    /**
280
-     * Specifies a route that is only available to GET requests.
281
-     *
282
-     * @param       $from
283
-     * @param       $to
284
-     * @param array $options
285
-     */
286
-    public function get($from, $to, $options = [])
287
-    {
288
-        if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'GET') {
289
-            $this->create($from, $to, $options);
290
-        }
291
-    }
292
-
293
-    //--------------------------------------------------------------------
294
-
295
-    /**
296
-     * Specifies a route that is only available to POST requests.
297
-     *
298
-     * @param       $from
299
-     * @param       $to
300
-     * @param array $options
301
-     */
302
-    public function post($from, $to, $options = [])
303
-    {
304
-        if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') {
305
-            $this->create($from, $to, $options);
306
-        }
307
-    }
308
-
309
-    //--------------------------------------------------------------------
310
-
311
-    /**
312
-     * Specifies a route that is only available to PUT requests.
313
-     *
314
-     * @param       $from
315
-     * @param       $to
316
-     * @param array $options
317
-     */
318
-    public function put($from, $to, $options = [])
319
-    {
320
-        if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'PUT') {
321
-            $this->create($from, $to, $options);
322
-        }
323
-    }
324
-
325
-    //--------------------------------------------------------------------
326
-
327
-    /**
328
-     * Specifies a route that is only available to DELETE requests.
329
-     *
330
-     * @param       $from
331
-     * @param       $to
332
-     * @param array $options
333
-     */
334
-    public function delete($from, $to, $options = [])
335
-    {
336
-        if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'DELETE') {
337
-            $this->create($from, $to, $options);
338
-        }
339
-    }
340
-
341
-    //--------------------------------------------------------------------
342
-
343
-    /**
344
-     * Specifies a route that is only available to HEAD requests.
345
-     *
346
-     * @param       $from
347
-     * @param       $to
348
-     * @param array $options
349
-     */
350
-    public function head($from, $to, $options = [])
351
-    {
352
-        if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'HEAD') {
353
-            $this->create($from, $to, $options);
354
-        }
355
-    }
356
-
357
-    //--------------------------------------------------------------------
358
-
359
-    /**
360
-     * Specifies a route that is only available to PATCH requests.
361
-     *
362
-     * @param       $from
363
-     * @param       $to
364
-     * @param array $options
365
-     */
366
-    public function patch($from, $to, $options = [])
367
-    {
368
-        if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'PATCH') {
369
-            $this->create($from, $to, $options);
370
-        }
371
-    }
372
-
373
-    //--------------------------------------------------------------------
374
-
375
-    /**
376
-     * Specifies a route that is only available to OPTIONS requests.
377
-     *
378
-     * @param       $from
379
-     * @param       $to
380
-     * @param array $options
381
-     */
382
-    public function options($from, $to, $options = [])
383
-    {
384
-        if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
385
-            $this->create($from, $to, $options);
386
-        }
387
-    }
388
-
389
-    //--------------------------------------------------------------------
390
-
391
-    /**
392
-     * Creates a collections of HTTP-verb based routes for a controller.
393
-     *
394
-     * Possible Options:
395
-     *      'controller'    - Customize the name of the controller used in the 'to' route
396
-     *      'module'        - Prepend a module name to the generate 'to' routes
397
-     *      'constraint'    - The regex used by the Router. Defaults to '(:any)'
398
-     *
399
-     * Example:
400
-     *      $route->resources('photos');
401
-     *
402
-     *      // Generates the following routes:
403
-     *      HTTP Verb | Path        | Action        | Used for...
404
-     *      ----------+-------------+---------------+-----------------
405
-     *      GET         /photos             index           display a list of photos
406
-     *      GET         /photos/new         creation_form   return an HTML form for creating a new photo
407
-     *      GET         /photos/{id}        show            display a specific photo
408
-     *      GET         /photos/{id}/edit   editing_form    return an HTML form for editing the photo
409
-     *      POST        /photos             create          create a new photo
410
-     *      PUT         /photos/{id}        update          update an existing photo
411
-     *      DELETE      /photos/{id}/delete delete          delete an existing photo
412
-     *
413
-     * @param  string $name    The name of the controller to route to.
414
-     * @param  array  $options An list of possible ways to customize the routing.
415
-     */
416
-    public function resources($name, $options = [])
417
-    {
418
-        // In order to allow customization of the route the
419
-        // resources are sent to, we need to have a new name
420
-        // to store the values in.
421
-        $new_name = $name;
422
-
423
-        // If a new controller is specified, then we replace the
424
-        // $name value with the name of the new controller.
425
-        if (isset($options['controller'])) {
426
-            $new_name = $options['controller'];
427
-        }
428
-
429
-        // If a new module was specified, simply put that path
430
-        // in front of the controller.
431
-        if (isset($options['module'])) {
432
-            $new_name = $options['module'] . '/' . $new_name;
433
-        }
434
-
435
-        // In order to allow customization of allowed id values
436
-        // we need someplace to store them.
437
-        $id = isset($this->constraints[$this->default_constraint]) ? $this->constraints[$this->default_constraint] :
438
-            '(:any)';
439
-
440
-        if (isset($options['constraint'])) {
441
-            $id = $options['constraint'];
442
-        }
443
-
444
-        $this->get($name, $new_name . '/list_all', $options);
445
-        $this->get($name . '/' . $id, $new_name . '/show/$1', $options);
446
-        $this->post($name, $new_name . '/create', $options);
447
-        $this->put($name . '/' . $id, $new_name . '/update/$1', $options);
448
-        $this->delete($name . '/' . $id, $new_name . '/delete/$1', $options);
449
-        $this->options($name, $new_name . '/index', $options);
450
-    }
451
-
452
-    //--------------------------------------------------------------------
453
-
454
-    /**
455
-     * Lets the system know about different 'areas' within the site, like
456
-     * the admin area, that maps to certain controllers.
457
-     *
458
-     * @param  string $area       The name of the area.
459
-     * @param  string $controller The controller name to look for.
460
-     * @param         $options
461
-     */
462
-    public function area($area, $controller = null, $options = [])
463
-    {
464
-        // No controller? Match the area name.
465
-        $controller = is_null($controller) ? $area : $controller;
466
-
467
-        // Save the area so we can recognize it later.
468
-        self::$areas[$area] = $controller;
469
-
470
-        // Create routes for this area.
471
-        $this->create($area . '/(:any)/(:any)/(:any)/(:any)/(:any)', '$1/' . $controller . '/$2/$3/$4/$5', $options);
472
-        $this->create($area . '/(:any)/(:any)/(:any)/(:any)', '$1/' . $controller . '/$2/$3/$4', $options);
473
-        $this->create($area . '/(:any)/(:any)/(:any)', '$1/' . $controller . '/$2/$3', $options);
474
-        $this->create($area . '/(:any)/(:any)', '$1/' . $controller . '/$2', $options);
475
-        $this->create($area . '/(:any)', '$1/' . $controller, $options);
476
-    }
477
-
478
-    //--------------------------------------------------------------------
479
-
480
-    /**
481
-     * Returns the name of the area based on the controller name.
482
-     *
483
-     * @param  string $controller The name of the controller
484
-     * @return string             The name of the corresponding area
485
-     */
486
-    public static function getAreaName($controller)
487
-    {
488
-        foreach (self::$areas as $area => $cont) {
489
-            if ($controller == $cont) {
490
-                return $area;
491
-            }
492
-        }
493
-
494
-        return null;
495
-    }
496
-
497
-    //--------------------------------------------------------------------
498
-
499
-    /**
500
-     * Limits the routes to a specified ENVIRONMENT or they won't run.
501
-     *
502
-     * @param $env
503
-     * @param callable $callback
504
-     *
505
-     * @return bool|null
506
-     */
507
-    public function environment($env, \Closure $callback)
508
-    {
509
-        if (ENVIRONMENT == $env)
510
-        {
511
-            call_user_func($callback);
512
-            return true;
513
-        }
514
-
515
-        return null;
516
-    }
517
-
518
-    //--------------------------------------------------------------------
519
-
520
-
521
-
522
-    /**
523
-     * Allows you to easily block access to any number of routes by setting
524
-     * that route to an empty path ('').
525
-     *
526
-     * Example:
527
-     *     Route::block('posts', 'photos/(:num)');
528
-     *
529
-     *     // Same as...
530
-     *     $route['posts']          = '';
531
-     *     $route['photos/(:num)']  = '';
532
-     */
533
-    public function block()
534
-    {
535
-        $paths = func_get_args();
536
-
537
-        if (! is_array($paths) || ! count($paths)) {
538
-            return;
539
-        }
540
-
541
-        foreach ($paths as $path) {
542
-            $this->create($path, '');
543
-        }
544
-    }
545
-
546
-    //--------------------------------------------------------------------
547
-
548
-    /**
549
-     * Empties all named and un-named routes from the system.
550
-     *
551
-     * @return void
552
-     */
553
-    public function reset()
554
-    {
555
-        $this->routes = array();
556
-        $this->group  = null;
557
-        self::$names  = array();
558
-        self::$areas  = array();
559
-    }
560
-
561
-    //--------------------------------------------------------------------
562
-
563
-    //--------------------------------------------------------------------
564
-    // Private Methods
565
-    //--------------------------------------------------------------------
566
-
567
-    /**
568
-     * Does the heavy lifting of creating an actual route. You must specify
569
-     * the request method(s) that this route will work for. They can be separated
570
-     * by a pipe character "|" if there is more than one.
571
-     *
572
-     * @param  string $from
573
-     * @param  array  $to
574
-     * @param array   $options
575
-     *
576
-     * @return array          The built route.
577
-     */
578
-    private function create($from, $to, $options = array())
579
-    {
580
-        $prefix = is_null($this->group) ? '' : $this->group . '/';
581
-
582
-        $from = $prefix . $from;
583
-
584
-        // Are we saving the name for this one?
585
-        if (isset($options['as']) && !empty($options['as'])) {
586
-            self::$names[$options['as']] = $from;
587
-        }
588
-
589
-        // Limiting to subdomains?
590
-        if (isset($options['subdomain']) && !empty($options['subdomain'])) {
591
-            // If we don't match the current subdomain, then
592
-            // we don't need to add the route.
593
-            if (!$this->checkSubdomains($options['subdomain'])) {
594
-                return;
595
-            }
596
-        }
597
-
598
-        // Are we offsetting the parameters?
599
-        // If so, take care of them here in one
600
-        // fell swoop.
601
-        if (isset($options['offset'])) {
602
-            // Get a constant string to work with.
603
-            $to = preg_replace('/(\$\d+)/', '$X', $to);
604
-
605
-            for ($i = (int)$options['offset'] + 1; $i < (int)$options['offset'] + 7; $i ++) {
606
-                $to = preg_replace_callback(
607
-                    '/\$X/',
608
-                    function ($m) use ($i) {
609
-                        return '$' . $i;
610
-                    },
611
-                    $to,
612
-                    1
613
-                );
614
-            }
615
-        }
616
-
617
-        // Convert any custom constraints to the CI/pattern equivalent
618
-        foreach ($this->constraints as $name => $pattern) {
619
-            $from = str_replace('{' . $name . '}', $pattern, $from);
620
-        }
621
-
622
-        $this->routes[$from] = $to;
623
-    }
624
-
625
-    //--------------------------------------------------------------------
626
-
627
-    /**
628
-     * Compares the subdomain(s) passed in against the current subdomain
629
-     * on this page request.
630
-     *
631
-     * @param $subdomains
632
-     * @return bool
633
-     */
634
-    private function checkSubdomains($subdomains)
635
-    {
636
-        if (is_null($this->current_subdomain)) {
637
-            $this->determineCurrentSubdomain();
638
-        }
639
-
640
-        if (!is_array($subdomains)) {
641
-            $subdomains = array($subdomains);
642
-        }
643
-
644
-        $matched = false;
645
-
646
-        array_walk(
647
-            $subdomains,
648
-            function ($subdomain) use (&$matched) {
649
-                if ($subdomain == $this->current_subdomain || $subdomain == '*') {
650
-                    $matched = true;
651
-                }
652
-            }
653
-        );
654
-
655
-        return $matched;
656
-    }
657
-
658
-    //--------------------------------------------------------------------
659
-
660
-    /**
661
-     * Examines the HTTP_HOST to get a best match for the subdomain. It
662
-     * won't be perfect, but should work for our needs.
663
-     */
664
-    private function determineCurrentSubdomain()
665
-    {
666
-        $parsedUrl = parse_url($_SERVER['HTTP_HOST']);
667
-
668
-        $host = explode('.', $parsedUrl['host']);
669
-
670
-        // If we only have 2 parts, then we don't have a subdomain.
671
-        // This won't be totally accurate, since URL's like example.co.uk
672
-        // would still pass, but it helps to separate the chaff...
673
-        if (!is_array($host) || count($host) == 2) {
674
-            // Set it to false so we don't make it back here again.
675
-            $this->current_subdomain = false;
676
-            return;
677
-        }
678
-
679
-        // Now, we'll simply take the first element of the array. This should
680
-        // be fine even in cases like example.co.uk, since they won't be looking
681
-        // for 'example' when they try to match the subdomain, in most all cases.
682
-        $this->current_subdomain = array_shift($host);
683
-    }
684
-    //--------------------------------------------------------------------
46
+	// Our routes, ripe for the picking.
47
+	public $routes = array();
48
+
49
+	// Holds key/value pairs of named routes
50
+	public static $names = array();
51
+
52
+	// Used for grouping routes together.
53
+	public $group = null;
54
+
55
+	// Holds the 'areas' of the site.
56
+	public static $areas = array();
57
+
58
+	// The default controller to use in case
59
+	// 'default_controller' is not in the routes file.
60
+	protected $default_home = 'home';
61
+
62
+	// The default constraint to use in route building
63
+	protected $default_constraint = 'any';
64
+
65
+	protected $constraints = [
66
+		'any'  => '(:any)',
67
+		'num'  => '(:num)',
68
+		'id'   => '(:num)',
69
+		'name' => "([a-zA-Z']+)"
70
+	];
71
+
72
+	protected $current_subdomain = null;
73
+
74
+	//--------------------------------------------------------------------
75
+
76
+	/**
77
+	 * Combines the routes that we've defined with the Route class with the
78
+	 * routes passed in. This is intended to be used  after all routes have been
79
+	 * defined to merge CI's default $route array with our routes.
80
+	 *
81
+	 * Example:
82
+	 *     $route['default_controller'] = 'home';
83
+	 *     Route::resource('posts');
84
+	 *     $route = Route::map($route);
85
+	 *
86
+	 * @param array $routes
87
+	 * @internal param array $route The array to merge
88
+	 * @return array         The merge route array.
89
+	 */
90
+	public function map($routes = array())
91
+	{
92
+		$controller = isset($routes['default_controller']) ? $routes['default_controller'] : $this->default_home;
93
+
94
+		$routes = array_merge($routes, $this->routes);
95
+
96
+		foreach ($routes as $from => $to) {
97
+			$routes[$from] = str_ireplace('{default_controller}', $controller, $to);
98
+		}
99
+
100
+		return $routes;
101
+	}
102
+
103
+	//--------------------------------------------------------------------
104
+
105
+	/**
106
+	 * A single point to the basic routing. Can be used in place of CI's $route
107
+	 * array if desired. Used internally by many of the methods.
108
+	 *
109
+	 * Available options are currently:
110
+	 *      'as'        - remembers the route via a name that can be called outside of it.
111
+	 *      'offset'    - Offsets and parameters ($1, $2, etc) in routes by the specified amount.
112
+	 *                    Useful while doing versioning of API's, etc.
113
+	 *
114
+	 * Example:
115
+	 *      $route->any('news', 'posts/index');
116
+	 *
117
+	 * @param string $from
118
+	 * @param string $to
119
+	 * @param array  $options
120
+	 * @return void
121
+	 */
122
+	public function any($from, $to, $options = array())
123
+	{
124
+		$this->create($from, $to, $options);
125
+	}
126
+
127
+	//--------------------------------------------------------------------
128
+
129
+	/**
130
+	 * Sets the default constraint to be used in the system. Typically
131
+	 * for use with the 'resources' method.
132
+	 *
133
+	 * @param $constraint
134
+	 */
135
+	public function setDefaultConstraint($constraint)
136
+	{
137
+		if (array_key_exists($constraint, $this->constraints)) {
138
+			$this->default_constraint = $constraint;
139
+		}
140
+	}
141
+
142
+	//--------------------------------------------------------------------
143
+
144
+	/**
145
+	 * Registers a new constraint to be used internally. Useful for creating
146
+	 * very specific regex patterns, or simply to allow your routes to be
147
+	 * a tad more readable.
148
+	 *
149
+	 * Example:
150
+	 *      $route->registerConstraint('hero', '(^.*)');
151
+	 *
152
+	 *      $route->any('home/{hero}', 'heroes/journey');
153
+	 *
154
+	 *      // Route then looks like:
155
+	 *      $route['home/(^.*)'] = 'heroes/journey';
156
+	 *
157
+	 * @param      $name
158
+	 * @param      $pattern
159
+	 * @param bool $overwrite
160
+	 */
161
+	public function registerConstraint($name, $pattern, $overwrite = false)
162
+	{
163
+		// Ensure consistency
164
+		$name    = trim($name, '{} ');
165
+		$pattern = '(' . trim($pattern, '() ') . ')';
166
+
167
+		// Not here? Add it and leave...
168
+		if (! array_key_exists($name, $this->constraints)) {
169
+			$this->constraints[$name] = $pattern;
170
+
171
+			return;
172
+		}
173
+
174
+		// Here? Then it exists. Should we overwrite it?
175
+		if ($overwrite) {
176
+			$this->constraints[$name] = $pattern;
177
+		}
178
+	}
179
+
180
+	//--------------------------------------------------------------------
181
+
182
+	//--------------------------------------------------------------------
183
+	// Named Routes
184
+	//--------------------------------------------------------------------
185
+
186
+	/**
187
+	 * Returns the value of a named route. Useful for getting named
188
+	 * routes for use while building with site_url() or in templates
189
+	 * where you don't need to instantiate the route class.
190
+	 *
191
+	 * Example:
192
+	 *      $route->any('news', 'posts/index', ['as' => 'blog']);
193
+	 *
194
+	 *      // Returns http://mysite.com/news
195
+	 *      site_url( Route::named('blog') );
196
+	 *
197
+	 * @param  [type] $name [description]
198
+	 * @return [type]       [description]
199
+	 */
200
+	public static function named($name)
201
+	{
202
+		if (isset(self::$names[$name])) {
203
+			return self::$names[$name];
204
+		}
205
+
206
+		return null;
207
+	}
208
+
209
+	//--------------------------------------------------------------------
210
+
211
+	//--------------------------------------------------------------------
212
+	// Grouping Routes
213
+	//--------------------------------------------------------------------
214
+
215
+	/**
216
+	 * Group a series of routes under a single URL segment. This is handy
217
+	 * for grouping items into an admin area, like:
218
+	 *
219
+	 * Example:
220
+	 *     $route->group('admin', function() {
221
+	 *            $route->resources('users');
222
+	 *     });
223
+	 *
224
+	 * @param  string   $name     The name to group/prefix the routes with.
225
+	 * @param  \Closure $callback An anonymous function that allows you route inside of this group.
226
+	 * @return void
227
+	 */
228
+	public function group($name, \Closure $callback)
229
+	{
230
+		$old_group = $this->group;
231
+
232
+		// To register a route, we'll set a flag so that our router
233
+		// so it will see the groupname.
234
+		$this->group = ltrim($old_group . '/' . $name, '/');
235
+
236
+		call_user_func($callback);
237
+
238
+		// Make sure to clear the group name so we don't accidentally
239
+		// group any ones we didn't want to.
240
+		$this->group = $old_group;
241
+	}
242
+
243
+	//--------------------------------------------------------------------
244
+
245
+	//--------------------------------------------------------------------
246
+	// HTTP Verb-based routing
247
+	//--------------------------------------------------------------------
248
+	// Routing works here because, as the routes config file is read in,
249
+	// the various HTTP verb-based routes will only be added to the in-memory
250
+	// routes if it is a call that should respond to that verb.
251
+	//
252
+	// The options array is typically used to pass in an 'as' or var, but may
253
+	// be expanded in the future. See the docblock for 'any' method above for
254
+	// current list of globally available options.
255
+	//
256
+
257
+	/**
258
+	 * Specifies a single route to match for multiple HTTP Verbs.
259
+	 *
260
+	 * Example:
261
+	 *  $route->match( ['get', 'post'], 'users/(:num)', 'users/$1);
262
+	 *
263
+	 * @param array $verbs
264
+	 * @param       $from
265
+	 * @param       $to
266
+	 * @param array $options
267
+	 */
268
+	public function match($verbs = [], $from, $to, $options = [])
269
+	{
270
+		foreach ($verbs as $verb) {
271
+			$verb = strtolower($verb);
272
+
273
+			$this->{$verb}($from, $to, $options);
274
+		}
275
+	}
276
+
277
+	//--------------------------------------------------------------------
278
+
279
+	/**
280
+	 * Specifies a route that is only available to GET requests.
281
+	 *
282
+	 * @param       $from
283
+	 * @param       $to
284
+	 * @param array $options
285
+	 */
286
+	public function get($from, $to, $options = [])
287
+	{
288
+		if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'GET') {
289
+			$this->create($from, $to, $options);
290
+		}
291
+	}
292
+
293
+	//--------------------------------------------------------------------
294
+
295
+	/**
296
+	 * Specifies a route that is only available to POST requests.
297
+	 *
298
+	 * @param       $from
299
+	 * @param       $to
300
+	 * @param array $options
301
+	 */
302
+	public function post($from, $to, $options = [])
303
+	{
304
+		if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') {
305
+			$this->create($from, $to, $options);
306
+		}
307
+	}
308
+
309
+	//--------------------------------------------------------------------
310
+
311
+	/**
312
+	 * Specifies a route that is only available to PUT requests.
313
+	 *
314
+	 * @param       $from
315
+	 * @param       $to
316
+	 * @param array $options
317
+	 */
318
+	public function put($from, $to, $options = [])
319
+	{
320
+		if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'PUT') {
321
+			$this->create($from, $to, $options);
322
+		}
323
+	}
324
+
325
+	//--------------------------------------------------------------------
326
+
327
+	/**
328
+	 * Specifies a route that is only available to DELETE requests.
329
+	 *
330
+	 * @param       $from
331
+	 * @param       $to
332
+	 * @param array $options
333
+	 */
334
+	public function delete($from, $to, $options = [])
335
+	{
336
+		if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'DELETE') {
337
+			$this->create($from, $to, $options);
338
+		}
339
+	}
340
+
341
+	//--------------------------------------------------------------------
342
+
343
+	/**
344
+	 * Specifies a route that is only available to HEAD requests.
345
+	 *
346
+	 * @param       $from
347
+	 * @param       $to
348
+	 * @param array $options
349
+	 */
350
+	public function head($from, $to, $options = [])
351
+	{
352
+		if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'HEAD') {
353
+			$this->create($from, $to, $options);
354
+		}
355
+	}
356
+
357
+	//--------------------------------------------------------------------
358
+
359
+	/**
360
+	 * Specifies a route that is only available to PATCH requests.
361
+	 *
362
+	 * @param       $from
363
+	 * @param       $to
364
+	 * @param array $options
365
+	 */
366
+	public function patch($from, $to, $options = [])
367
+	{
368
+		if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'PATCH') {
369
+			$this->create($from, $to, $options);
370
+		}
371
+	}
372
+
373
+	//--------------------------------------------------------------------
374
+
375
+	/**
376
+	 * Specifies a route that is only available to OPTIONS requests.
377
+	 *
378
+	 * @param       $from
379
+	 * @param       $to
380
+	 * @param array $options
381
+	 */
382
+	public function options($from, $to, $options = [])
383
+	{
384
+		if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
385
+			$this->create($from, $to, $options);
386
+		}
387
+	}
388
+
389
+	//--------------------------------------------------------------------
390
+
391
+	/**
392
+	 * Creates a collections of HTTP-verb based routes for a controller.
393
+	 *
394
+	 * Possible Options:
395
+	 *      'controller'    - Customize the name of the controller used in the 'to' route
396
+	 *      'module'        - Prepend a module name to the generate 'to' routes
397
+	 *      'constraint'    - The regex used by the Router. Defaults to '(:any)'
398
+	 *
399
+	 * Example:
400
+	 *      $route->resources('photos');
401
+	 *
402
+	 *      // Generates the following routes:
403
+	 *      HTTP Verb | Path        | Action        | Used for...
404
+	 *      ----------+-------------+---------------+-----------------
405
+	 *      GET         /photos             index           display a list of photos
406
+	 *      GET         /photos/new         creation_form   return an HTML form for creating a new photo
407
+	 *      GET         /photos/{id}        show            display a specific photo
408
+	 *      GET         /photos/{id}/edit   editing_form    return an HTML form for editing the photo
409
+	 *      POST        /photos             create          create a new photo
410
+	 *      PUT         /photos/{id}        update          update an existing photo
411
+	 *      DELETE      /photos/{id}/delete delete          delete an existing photo
412
+	 *
413
+	 * @param  string $name    The name of the controller to route to.
414
+	 * @param  array  $options An list of possible ways to customize the routing.
415
+	 */
416
+	public function resources($name, $options = [])
417
+	{
418
+		// In order to allow customization of the route the
419
+		// resources are sent to, we need to have a new name
420
+		// to store the values in.
421
+		$new_name = $name;
422
+
423
+		// If a new controller is specified, then we replace the
424
+		// $name value with the name of the new controller.
425
+		if (isset($options['controller'])) {
426
+			$new_name = $options['controller'];
427
+		}
428
+
429
+		// If a new module was specified, simply put that path
430
+		// in front of the controller.
431
+		if (isset($options['module'])) {
432
+			$new_name = $options['module'] . '/' . $new_name;
433
+		}
434
+
435
+		// In order to allow customization of allowed id values
436
+		// we need someplace to store them.
437
+		$id = isset($this->constraints[$this->default_constraint]) ? $this->constraints[$this->default_constraint] :
438
+			'(:any)';
439
+
440
+		if (isset($options['constraint'])) {
441
+			$id = $options['constraint'];
442
+		}
443
+
444
+		$this->get($name, $new_name . '/list_all', $options);
445
+		$this->get($name . '/' . $id, $new_name . '/show/$1', $options);
446
+		$this->post($name, $new_name . '/create', $options);
447
+		$this->put($name . '/' . $id, $new_name . '/update/$1', $options);
448
+		$this->delete($name . '/' . $id, $new_name . '/delete/$1', $options);
449
+		$this->options($name, $new_name . '/index', $options);
450
+	}
451
+
452
+	//--------------------------------------------------------------------
453
+
454
+	/**
455
+	 * Lets the system know about different 'areas' within the site, like
456
+	 * the admin area, that maps to certain controllers.
457
+	 *
458
+	 * @param  string $area       The name of the area.
459
+	 * @param  string $controller The controller name to look for.
460
+	 * @param         $options
461
+	 */
462
+	public function area($area, $controller = null, $options = [])
463
+	{
464
+		// No controller? Match the area name.
465
+		$controller = is_null($controller) ? $area : $controller;
466
+
467
+		// Save the area so we can recognize it later.
468
+		self::$areas[$area] = $controller;
469
+
470
+		// Create routes for this area.
471
+		$this->create($area . '/(:any)/(:any)/(:any)/(:any)/(:any)', '$1/' . $controller . '/$2/$3/$4/$5', $options);
472
+		$this->create($area . '/(:any)/(:any)/(:any)/(:any)', '$1/' . $controller . '/$2/$3/$4', $options);
473
+		$this->create($area . '/(:any)/(:any)/(:any)', '$1/' . $controller . '/$2/$3', $options);
474
+		$this->create($area . '/(:any)/(:any)', '$1/' . $controller . '/$2', $options);
475
+		$this->create($area . '/(:any)', '$1/' . $controller, $options);
476
+	}
477
+
478
+	//--------------------------------------------------------------------
479
+
480
+	/**
481
+	 * Returns the name of the area based on the controller name.
482
+	 *
483
+	 * @param  string $controller The name of the controller
484
+	 * @return string             The name of the corresponding area
485
+	 */
486
+	public static function getAreaName($controller)
487
+	{
488
+		foreach (self::$areas as $area => $cont) {
489
+			if ($controller == $cont) {
490
+				return $area;
491
+			}
492
+		}
493
+
494
+		return null;
495
+	}
496
+
497
+	//--------------------------------------------------------------------
498
+
499
+	/**
500
+	 * Limits the routes to a specified ENVIRONMENT or they won't run.
501
+	 *
502
+	 * @param $env
503
+	 * @param callable $callback
504
+	 *
505
+	 * @return bool|null
506
+	 */
507
+	public function environment($env, \Closure $callback)
508
+	{
509
+		if (ENVIRONMENT == $env)
510
+		{
511
+			call_user_func($callback);
512
+			return true;
513
+		}
514
+
515
+		return null;
516
+	}
517
+
518
+	//--------------------------------------------------------------------
519
+
520
+
521
+
522
+	/**
523
+	 * Allows you to easily block access to any number of routes by setting
524
+	 * that route to an empty path ('').
525
+	 *
526
+	 * Example:
527
+	 *     Route::block('posts', 'photos/(:num)');
528
+	 *
529
+	 *     // Same as...
530
+	 *     $route['posts']          = '';
531
+	 *     $route['photos/(:num)']  = '';
532
+	 */
533
+	public function block()
534
+	{
535
+		$paths = func_get_args();
536
+
537
+		if (! is_array($paths) || ! count($paths)) {
538
+			return;
539
+		}
540
+
541
+		foreach ($paths as $path) {
542
+			$this->create($path, '');
543
+		}
544
+	}
545
+
546
+	//--------------------------------------------------------------------
547
+
548
+	/**
549
+	 * Empties all named and un-named routes from the system.
550
+	 *
551
+	 * @return void
552
+	 */
553
+	public function reset()
554
+	{
555
+		$this->routes = array();
556
+		$this->group  = null;
557
+		self::$names  = array();
558
+		self::$areas  = array();
559
+	}
560
+
561
+	//--------------------------------------------------------------------
562
+
563
+	//--------------------------------------------------------------------
564
+	// Private Methods
565
+	//--------------------------------------------------------------------
566
+
567
+	/**
568
+	 * Does the heavy lifting of creating an actual route. You must specify
569
+	 * the request method(s) that this route will work for. They can be separated
570
+	 * by a pipe character "|" if there is more than one.
571
+	 *
572
+	 * @param  string $from
573
+	 * @param  array  $to
574
+	 * @param array   $options
575
+	 *
576
+	 * @return array          The built route.
577
+	 */
578
+	private function create($from, $to, $options = array())
579
+	{
580
+		$prefix = is_null($this->group) ? '' : $this->group . '/';
581
+
582
+		$from = $prefix . $from;
583
+
584
+		// Are we saving the name for this one?
585
+		if (isset($options['as']) && !empty($options['as'])) {
586
+			self::$names[$options['as']] = $from;
587
+		}
588
+
589
+		// Limiting to subdomains?
590
+		if (isset($options['subdomain']) && !empty($options['subdomain'])) {
591
+			// If we don't match the current subdomain, then
592
+			// we don't need to add the route.
593
+			if (!$this->checkSubdomains($options['subdomain'])) {
594
+				return;
595
+			}
596
+		}
597
+
598
+		// Are we offsetting the parameters?
599
+		// If so, take care of them here in one
600
+		// fell swoop.
601
+		if (isset($options['offset'])) {
602
+			// Get a constant string to work with.
603
+			$to = preg_replace('/(\$\d+)/', '$X', $to);
604
+
605
+			for ($i = (int)$options['offset'] + 1; $i < (int)$options['offset'] + 7; $i ++) {
606
+				$to = preg_replace_callback(
607
+					'/\$X/',
608
+					function ($m) use ($i) {
609
+						return '$' . $i;
610
+					},
611
+					$to,
612
+					1
613
+				);
614
+			}
615
+		}
616
+
617
+		// Convert any custom constraints to the CI/pattern equivalent
618
+		foreach ($this->constraints as $name => $pattern) {
619
+			$from = str_replace('{' . $name . '}', $pattern, $from);
620
+		}
621
+
622
+		$this->routes[$from] = $to;
623
+	}
624
+
625
+	//--------------------------------------------------------------------
626
+
627
+	/**
628
+	 * Compares the subdomain(s) passed in against the current subdomain
629
+	 * on this page request.
630
+	 *
631
+	 * @param $subdomains
632
+	 * @return bool
633
+	 */
634
+	private function checkSubdomains($subdomains)
635
+	{
636
+		if (is_null($this->current_subdomain)) {
637
+			$this->determineCurrentSubdomain();
638
+		}
639
+
640
+		if (!is_array($subdomains)) {
641
+			$subdomains = array($subdomains);
642
+		}
643
+
644
+		$matched = false;
645
+
646
+		array_walk(
647
+			$subdomains,
648
+			function ($subdomain) use (&$matched) {
649
+				if ($subdomain == $this->current_subdomain || $subdomain == '*') {
650
+					$matched = true;
651
+				}
652
+			}
653
+		);
654
+
655
+		return $matched;
656
+	}
657
+
658
+	//--------------------------------------------------------------------
659
+
660
+	/**
661
+	 * Examines the HTTP_HOST to get a best match for the subdomain. It
662
+	 * won't be perfect, but should work for our needs.
663
+	 */
664
+	private function determineCurrentSubdomain()
665
+	{
666
+		$parsedUrl = parse_url($_SERVER['HTTP_HOST']);
667
+
668
+		$host = explode('.', $parsedUrl['host']);
669
+
670
+		// If we only have 2 parts, then we don't have a subdomain.
671
+		// This won't be totally accurate, since URL's like example.co.uk
672
+		// would still pass, but it helps to separate the chaff...
673
+		if (!is_array($host) || count($host) == 2) {
674
+			// Set it to false so we don't make it back here again.
675
+			$this->current_subdomain = false;
676
+			return;
677
+		}
678
+
679
+		// Now, we'll simply take the first element of the array. This should
680
+		// be fine even in cases like example.co.uk, since they won't be looking
681
+		// for 'example' when they try to match the subdomain, in most all cases.
682
+		$this->current_subdomain = array_shift($host);
683
+	}
684
+	//--------------------------------------------------------------------
685 685
 
686 686
 }
Please login to merge, or discard this patch.