Completed
Push — master ( c65989...5a81e9 )
by Fran
03:41
created

Router::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 5
Bugs 0 Features 0
Metric Value
cc 1
eloc 5
c 5
b 0
f 0
nc 1
nop 0
dl 0
loc 7
ccs 6
cts 6
cp 1
crap 1
rs 9.4285
1
<?php
2
3
    namespace PSFS\base;
4
5
    use PSFS\base\config\Config;
6
    use PSFS\base\exception\AccessDeniedException;
7
    use PSFS\base\exception\ConfigException;
8
    use PSFS\base\exception\RouterException;
9
    use PSFS\base\types\SingletonTrait;
10
    use PSFS\controller\Admin;
11
    use PSFS\services\AdminServices;
12
    use Symfony\Component\Finder\Finder;
13
14
15
    /**
16
     * Class Router
17
     * @package PSFS
18
     */
19
    class Router
20
    {
21
22
        use SingletonTrait;
23
24
        protected $routing;
25
        protected $slugs;
26
        private $domains;
27
        /**
28
         * @var Finder $finder
29
         */
30
        private $finder;
31
        /**
32
         * @var \PSFS\base\Cache $cache
33
         */
34
        private $cache;
35
        /**
36
         * @var \PSFS\base\Security $session
37
         */
38
        private $session;
39
        /**
40
         * @var bool headersSent
41
         */
42
        protected $headersSent = false;
43
44
        /**
45
         * Constructor Router
46
         * @throws ConfigException
47
         */
48 6
        public function __construct()
49
        {
50 6
            $this->finder = new Finder();
51 6
            $this->cache = Cache::getInstance();
52 6
            $this->session = Security::getInstance();
53 6
            $this->init();
54 6
        }
55
56
        /**
57
         * Inicializador Router
58
         * @throws ConfigException
59
         */
60 1
        public function init()
61
        {
62 1
            if (!file_exists(CONFIG_DIR . DIRECTORY_SEPARATOR . "urls.json") || Config::getInstance()->getDebugMode()) {
63 1
                $this->hydrateRouting();
64 1
                $this->simpatize();
65 1
            } else {
66
                list($this->routing, $this->slugs) = $this->cache->getDataFromFile(CONFIG_DIR . DIRECTORY_SEPARATOR . "urls.json", Cache::JSON, TRUE);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 150 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
67
                $this->domains = $this->cache->getDataFromFile(CONFIG_DIR . DIRECTORY_SEPARATOR . "domains.json", Cache::JSON, TRUE);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 133 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
68
            }
69 1
        }
70
71
        /**
72
         * Método que deriva un error HTTP de página no encontrada
73
         *
74
         * @param \Exception $e
75
         *
76
         * @return string HTML
77
         */
78
        public function httpNotFound(\Exception $e = NULL)
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $e. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
79
        {
80
            $template = Template::getInstance()
81
                ->setStatus($e->getCode());
82
            if (preg_match('/json/i', Request::getInstance()->getServer('CONTENT_TYPE'))) {
83
                return $template->output(json_encode(array(
84
                    "success" => FALSE,
85
                    "error"   => $e->getMessage(),
86
                )), 'application/json');
87
            } else {
88
                if (NULL === $e) {
89
                    $e = new \Exception(_('Página no encontrada'), 404);
90
                }
91
92
                return $template->render('error.html.twig', array(
93
                    'exception'  => $e,
94
                    'trace'      => $e->getTraceAsString(),
95
                    'error_page' => TRUE,
96
                ));
97
            }
98
        }
99
100
        /**
101
         * Método que devuelve las rutas
102
         * @return string|null
103
         */
104
        public function getSlugs()
105
        {
106
            return $this->slugs;
107
        }
108
109
        /**
110
         * Método que calcula el objeto a enrutar
111
         *
112
         * @param string $route
113
         *
114
         * @throws \Exception
115
         * @return string HTML
116
         */
117
        public function execute($route)
118
        {
119
            try {
120
                //Check CORS for requests
121
                $this->checkCORS();
122
                // Checks restricted access
123
                $this->checkRestrictedAccess($route);
124
125
                //Search action and execute
126
                return $this->searchAction($route);
127
            } catch (AccessDeniedException $e) {
128
                Logger::getInstance()->debugLog(_('Solicitamos credenciales de acceso a zona restringida'));
129
                if ('login' === Config::getInstance()->get('admin_login')) {
130
                    return $this->redirectLogin($route);
131
                } else {
132
                    return $this->sentAuthHeader();
133
                }
134
            } catch (RouterException $r) {
135
                if (FALSE !== preg_match('/\/$/', $route)) {
136
                    if (preg_match('/admin/', $route)) {
137
                        $default = Config::getInstance()->get('admin_action');
138
                    } else {
139
                        $default = Config::getInstance()->get('home_action');
140
                    }
141
142
                    return $this->execute($this->getRoute($default));
143
                }
144
            } catch (\Exception $e) {
145
                Logger::getInstance()->errorLog($e->getMessage());
146
                throw $e;
147
            }
148
149
            return $this->httpNotFound();
150
        }
151
152
        /**
153
         * Check CROS requests
154
         */
155
        private function checkCORS()
156
        {
157
            $corsEnabled = Config::getInstance()->get('cors.enabled');
158
            $request = Request::getInstance();
159
            if (NULL !== $corsEnabled && null !== $request->getServer('HTTP_REFERER')) {
160
                if($corsEnabled == '*' || preg_match($corsEnabled, $request->getServer('HTTP_REFERER'))) {
161
                    if (!$this->headersSent) {
162
                        header("Access-Control-Allow-Credentials: true");
163
                        header("Access-Control-Allow-Origin: *");
164
                        header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
165
                        header("Access-Control-Allow-Headers: Access-Control-Allow-Methods, Access-Control-Allow-Headers, Access-Control-Allow-Origin, Origin, X-Requested-With, Content-Type, Accept, Authorization, X-API-SEC-TOKEN, X-API-USER-TOKEN");
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 250 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
166
                        $this->headersSent = true;
167
                    }
168
                    if(Request::getInstance()->getMethod() == 'OPTIONS') {
169
                        header( "HTTP/1.1 200 OK" );
170
                        exit();
171
                    }
172
                }
173
            }
174
        }
175
176
        /**
177
         * Function that checks if the long of the patterns match
178
         * @param $routePattern
179
         * @param $path
180
         * @return bool
181
         */
182
        private function compareSlashes($routePattern, $path) {
183
            $pattern_sep = count(explode('/', $routePattern));
184
            if(preg_match('/\/$/', $routePattern)) {
185
                $pattern_sep--;
186
            }
187
            $path_sep = count(explode('/', $path));
188
            if(preg_match('/\/$/', $path)) {
189
                $path_sep--;
190
            }
191
            return abs($pattern_sep - $path_sep) < 1;
192
        }
193
194
        /**
195
         * Método que busca el componente que ejecuta la ruta
196
         *
197
         * @param string $route
198
         *
199
         * @throws \Exception
200
         */
201
        protected function searchAction($route)
202
        {
203
            //Revisamos si tenemos la ruta registrada
204
            $parts = parse_url($route);
205
            $path = (array_key_exists('path', $parts)) ? $parts['path'] : $route;
206
            $httpRequest = Request::getInstance()->getMethod();
207
            foreach ($this->routing as $pattern => $action) {
208
                list($httpMethod, $routePattern) = $this->extractHttpRoute($pattern);
209
                $matched = $this->matchRoutePattern($routePattern, $path);
210
                if ($matched && ($httpMethod === "ALL" || $httpRequest === $httpMethod) && $this->compareSlashes($routePattern, $path)) {
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 137 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
211
                    $get = $this->extractComponents($route, $routePattern);
212
                    /** @var $class \PSFS\base\types\Controller */
213
                    $class = $this->getClassToCall($action);
214
                    try {
215
                        return $this->executeCachedRoute($route, $action, $class, $get);
216
                    } catch (\Exception $e) {
217
                        Logger::getInstance()->debugLog($e->getMessage(), array($e->getFile(), $e->getLine()));
218
                        throw new RouterException($e->getMessage(), 404, $e);
219
                    }
220
                }
221
            }
222
            throw new RouterException(_("Ruta no encontrada"));
223
        }
224
225
        /**
226
         * Método que manda las cabeceras de autenticación
227
         * @return string HTML
228
         */
229
        protected function sentAuthHeader()
230
        {
231
            return AdminServices::getInstance()->setAdminHeaders();
232
        }
233
234
        /**
235
         * Método que redirige a la pantalla web del login
236
         *
237
         * @param string $route
238
         *
239
         * @return string HTML
240
         */
241
        public function redirectLogin($route)
242
        {
243
            return Admin::staticAdminLogon($route);
244
        }
245
246
        /**
247
         * Método que chequea el acceso a una zona restringida
248
         *
249
         * @param string $route
250
         *
251
         * @throws AccessDeniedException
252
         */
253
        protected function checkRestrictedAccess($route)
254
        {
255
            //Chequeamos si entramos en el admin
256
            if (!Config::getInstance()->checkTryToSaveConfig() && preg_match('/^\/admin/i', $route)
257
                || (!preg_match('/^\/(admin|setup\-admin)/i', $route) && NULL !== Config::getInstance()->get('restricted'))
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 123 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
258
            ) {
259
                if (!preg_match('/^\/admin\/login/i', $route) && !$this->session->checkAdmin()) {
260
                    throw new AccessDeniedException();
261
                }
262
                Logger::getInstance()->debugLog('Acceso autenticado al admin');
263
            }
264
        }
265
266
        /**
267
         * Método que extrae de la url los parámetros REST
268
         *
269
         * @param string $route
270
         *
271
         * @param string $pattern
272
         *
273
         * @return array
274
         */
275
        protected function extractComponents($route, $pattern)
276
        {
277
            $url = parse_url($route);
278
            $_route = explode("/", $url['path']);
279
            $_pattern = explode("/", $pattern);
280
            $get = array();
281
            if (!empty($_pattern)) foreach ($_pattern as $index => $component) {
282
                $_get = array();
283
                preg_match_all('/^\{(.*)\}$/i', $component, $_get);
284
                if (!empty($_get[1]) && isset($_route[$index])) {
285
                    $get[array_pop($_get[1])] = $_route[$index];
286
                }
287
            }
288
289
            return $get;
290
        }
291
292
        /**
293
         * Método que regenera el fichero de rutas
294
         * @throws ConfigException
295
         */
296 1
        public function hydrateRouting()
297
        {
298 1
            $base = SOURCE_DIR;
299 1
            $modules = realpath(CORE_DIR);
300 1
            $this->routing = $this->inspectDir($base, "PSFS", array());
301 1
            if (file_exists($modules)) {
302
                $this->routing = $this->inspectDir($modules, "", $this->routing);
303
            }
304 1
            $this->cache->storeData(CONFIG_DIR . DIRECTORY_SEPARATOR . "domains.json", $this->domains, Cache::JSON, TRUE);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 122 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
305 1
            $home = Config::getInstance()->get('home_action');
306 1
            if (NULL !== $home || $home !== '') {
307 1
                $home_params = NULL;
308 1
                foreach ($this->routing as $pattern => $params) {
309 1
                    list($method, $route) = $this->extractHttpRoute($pattern);
310 1
                    if (preg_match("/" . preg_quote($route, "/") . "$/i", "/" . $home)) {
311
                        $home_params = $params;
312
                    }
313 1
                }
314 1
                if (NULL !== $home_params) {
315
                    $this->routing['/'] = $home_params;
316
                }
317 1
            }
318 1
        }
319
320
        /**
321
         * Método que inspecciona los directorios en busca de clases que registren rutas
322
         *
323
         * @param string $origen
324
         * @param string $namespace
325
         * @param array $routing
326
         *
327
         * @return array
328
         * @throws ConfigException
329
         */
330 1
        private function inspectDir($origen, $namespace = 'PSFS', $routing)
331
        {
332 1
            $files = $this->finder->files()->in($origen)->path('/(controller|api)/i')->name("*.php");
333 1
            foreach ($files as $file) {
334 1
                $filename = str_replace("/", '\\', str_replace($origen, '', $file->getPathname()));
335 1
                $routing = $this->addRouting($namespace . str_replace('.php', '', $filename), $routing);
336 1
            }
337 1
            $this->finder = new Finder();
338
339 1
            return $routing;
340
        }
341
342
        /**
343
         * Método que añade nuevas rutas al array de referencia
344
         *
345
         * @param string $namespace
346
         * @param array $routing
347
         *
348
         * @return array
349
         * @throws ConfigException
350
         */
351 1
        private function addRouting($namespace, $routing)
352
        {
353 1
            if (class_exists($namespace)) {
354 1
                $reflection = new \ReflectionClass($namespace);
355 1
                if (FALSE === $reflection->isAbstract() && FALSE === $reflection->isInterface()) {
356 1
                    $this->extractDomain($reflection);
357 1
                    $classComments = $reflection->getDocComment();
358 1
                    preg_match('/@api\ (.*)\n/im', $classComments, $apiPath);
359 1
                    $api = '';
360 1
                    if (count($apiPath)) {
361
                        $api = array_key_exists(1, $apiPath) ? $apiPath[1] : $api;
362
                    }
363 1
                    foreach ($reflection->getMethods() as $method) {
364 1
                        if ($method->isPublic()) {
365 1
                            $docComments = $method->getDocComment();
366 1
                            preg_match('/@route\ (.*)\n/i', $docComments, $sr);
367 1
                            if (count($sr)) {
368 1
                                list($regex, $default, $params) = $this->extractReflectionParams($sr, $method);
369 1
                                if (strlen($api)) {
370
                                    $regex = str_replace('{__API__}', $api, $regex);
371
                                    $default = str_replace('{__API__}', $api, $default);
372
                                }
373 1
                                $httpMethod = $this->extractReflectionHttpMethod($docComments);
374 1
                                $visible = $this->extractReflectionVisibility($docComments);
375 1
                                $expiration = $this->extractReflectionCacheability($docComments);
376 1
                                $routing[$httpMethod . "#|#" . $regex] = array(
377 1
                                    "class"   => $namespace,
378 1
                                    "method"  => $method->getName(),
379 1
                                    "params"  => $params,
380 1
                                    "default" => $default,
381 1
                                    "visible" => $visible,
382 1
                                    "http"    => $httpMethod,
383 1
                                    "cache"   => $expiration,
384
                                );
385 1
                            }
386 1
                        }
387 1
                    }
388 1
                }
389 1
            }
390
391 1
            return $routing;
392
        }
393
394
        /**
395
         * Método que extrae de la ReflectionClass los datos necesarios para componer los dominios en los templates
396
         *
397
         * @param \ReflectionClass $class
398
         *
399
         * @return Router
400
         * @throws ConfigException
401
         */
402 1
        protected function extractDomain($class)
403
        {
404
            //Calculamos los dominios para las plantillas
405 1
            if ($class->hasConstant("DOMAIN")) {
406 1
                $domain = "@" . $class->getConstant("DOMAIN") . "/";
407 1
                $path = dirname($class->getFileName()) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR;
408 1
                $path = realpath($path) . DIRECTORY_SEPARATOR;
409 1
                $tpl_path = "templates";
410 1
                $public_path = "public";
411 1
                $model_path = "models";
412 1
                if (!preg_match("/ROOT/", $domain)) {
413
                    $tpl_path = ucfirst($tpl_path);
414
                    $public_path = ucfirst($public_path);
415
                    $model_path = ucfirst($model_path);
416
                }
417 1
                if ($class->hasConstant("TPL")) {
418
                    $tpl_path .= DIRECTORY_SEPARATOR . $class->getConstant("TPL");
419
                }
420 1
                $this->domains[$domain] = array(
421 1
                    "template" => $path . $tpl_path,
422 1
                    "model"    => $path . $model_path,
423 1
                    "public"   => $path . $public_path,
424
                );
425 1
            }
426
427 1
            return $this;
428
        }
429
430
        /**
431
         * Método que genera las urls amigables para usar dentro del framework
432
         * @return Router
433
         */
434 1
        public function simpatize()
435
        {
436 1
            $translationFileName = "translations" . DIRECTORY_SEPARATOR . "routes_translations.php";
437 1
            $absoluteTranslationFileName = CACHE_DIR . DIRECTORY_SEPARATOR . $translationFileName;
438 1
            $this->generateSlugs($absoluteTranslationFileName);
439 1
            Config::createDir(CONFIG_DIR);
440 1
            Cache::getInstance()->storeData(CONFIG_DIR . DIRECTORY_SEPARATOR . "urls.json", array($this->routing, $this->slugs), Cache::JSON, TRUE);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 148 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
441
442 1
            return $this;
443
        }
444
445
        /**
446
         * Método que devuelve el slug de un string dado
447
         *
448
         * @param string $text
449
         *
450
         * @return string
451
         */
452 1
        private function slugify($text)
453
        {
454
            // replace non letter or digits by -
455 1
            $text = preg_replace('~[^\\pL\d]+~u', '-', $text);
456
457
            // trim
458 1
            $text = trim($text, '-');
459
460
            // transliterate
461 1
            if (function_exists('iconv')) {
462 1
                $text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
463 1
            }
464
465
            // lowercase
466 1
            $text = strtolower($text);
467
468
            // remove unwanted characters
469 1
            $text = preg_replace('~[^-\w]+~', '', $text);
470
471 1
            if (empty($text)) {
472
                return 'n-a';
473
            }
474
475 1
            return $text;
476
        }
477
478
        /**
479
         * Método que devuelve una ruta del framework
480
         *
481
         * @param string $slug
482
         * @param boolean $absolute
483
         * @param array $params
0 ignored issues
show
Documentation introduced by
Should the type for parameter $params not be array|null? Also, consider making the array more specific, something like array<String>, or String[].

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
484
         *
485
         * @return string|null
486
         * @throws RouterException
487
         */
488
        public function getRoute($slug = '', $absolute = FALSE, $params = NULL)
489
        {
490
            if (strlen($slug) === 0) {
491
                return ($absolute) ? Request::getInstance()->getRootUrl() . '/' : '/';
492
            }
493
            if (NULL === $slug || !array_key_exists($slug, $this->slugs)) {
494
                throw new RouterException(_("No existe la ruta especificada"));
495
            }
496
            $url = ($absolute) ? Request::getInstance()->getRootUrl() . $this->slugs[$slug] : $this->slugs[$slug];
497
            if (!empty($params)) foreach ($params as $key => $value) {
498
                $url = str_replace("{" . $key . "}", $value, $url);
499
            } elseif (!empty($this->routing[$this->slugs[$slug]]["default"])) {
500
                $url = ($absolute) ? Request::getInstance()->getRootUrl() . $this->routing[$this->slugs[$slug]]["default"] : $this->routing[$this->slugs[$slug]]["default"];
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 172 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
501
            }
502
503
            return preg_replace('/(GET|POST|PUT|DELETE|ALL)\#\|\#/', '', $url);
504
        }
505
506
        /**
507
         * Método que devuelve las rutas de administración
508
         * @return array
509
         */
510 1
        public function getAdminRoutes()
511
        {
512 1
            $routes = array();
513 1
            foreach ($this->routing as $route => $params) {
514 1
                list($httpMethod, $routePattern) = $this->extractHttpRoute($route);
515 1
                if (preg_match('/^\/admin(\/|$)/', $routePattern)) {
516 1
                    if (preg_match('/^PSFS/', $params["class"])) {
517 1
                        $profile = "superadmin";
518 1
                    } else {
519
                        $profile = "admin";
520
                    }
521 1
                    if (!empty($params["default"]) && preg_match('/(GET|ALL)/i', $httpMethod)) {
522 1
                        $_profile = ($params["visible"]) ? $profile : 'adminhidden';
523 1
                        if(!array_key_exists($_profile, $routes)) {
524 1
                            $routes[$_profile] = array();
525 1
                        }
526 1
                        $routes[$_profile][] = $params["slug"];
527 1
                    }
528 1
                }
529 1
            }
530 1
            if (array_key_exists("superadmin", $routes)) {
531 1
                asort($routes["superadmin"]);
532 1
            }
533 1
            if (array_key_exists("adminhidden", $routes)) {
534 1
                asort($routes["adminhidden"]);
535 1
            }
536 1
            if (array_key_exists('admin', $routes)) {
537
                asort($routes["admin"]);
538
            }
539
540 1
            return $routes;
541
        }
542
543
        /**
544
         * Método que devuelve le controlador del admin
545
         * @return Admin
546
         */
547
        public function getAdmin()
548
        {
549
            return Admin::getInstance();
550
        }
551
552
        /**
553
         * Método que extrae los dominios
554
         * @return array|null
0 ignored issues
show
Documentation introduced by
Should the return type not be array|string? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
555
         */
556
        public function getDomains()
557
        {
558
            return $this->domains;
559
        }
560
561
        /**
562
         * Método que extrae el controller a invocar
563
         *
564
         * @param string $action
565
         *
566
         * @return Object
567
         */
568
        protected function getClassToCall($action)
569
        {
570
            $class = (method_exists($action["class"], "getInstance")) ? $action["class"]::getInstance() : new $action["class"];
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 127 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
571
            if (NULL !== $class && method_exists($class, "init")) {
572
                $class->init();
573
            }
574
575
            return $class;
576
        }
577
578
        /**
579
         * Método que compara la ruta web con la guardada en la cache
580
         *
581
         * @param $routePattern
582
         * @param $path
583
         *
584
         * @return bool
585
         */
586
        protected function matchRoutePattern($routePattern, $path)
587
        {
588
            $expr = preg_replace('/\{(.*)\}/', '###', $routePattern);
589
            $expr = preg_quote($expr, '/');
590
            $expr = str_replace('###', '(.*)', $expr);
591
            $expr2 = preg_replace('/\(\.\*\)$/', '', $expr);
592
            $matched = preg_match('/^' . $expr . '\/?$/i', $path) || preg_match('/^' . $expr2 . '?$/i', $path);
593
            return $matched;
594
        }
595
596
        /**
597
         * @param $pattern
598
         *
599
         * @return array
600
         */
601 2
        protected function extractHttpRoute($pattern)
602
        {
603 2
            $httpMethod = "ALL";
604 2
            $routePattern = $pattern;
605 2
            if (FALSE !== strstr($pattern, "#|#")) {
606 2
                list($httpMethod, $routePattern) = explode("#|#", $pattern, 2);
607 2
            }
608
609 2
            return array(strtoupper($httpMethod), $routePattern);
610
        }
611
612
        /**
613
         * Método que extrae los parámetros de una función
614
         *
615
         * @param array $sr
616
         * @param \ReflectionMethod $method
617
         *
618
         * @return array
619
         */
620 1
        private function extractReflectionParams($sr, $method)
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $sr. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
621
        {
622 1
            $regex = $sr[1] ?: $sr[0];
623 1
            $default = '';
624 1
            $params = array();
625 1
            $parameters = $method->getParameters();
626 1
            if (count($parameters) > 0) foreach ($parameters as $param) {
627 1
                if ($param->isOptional() && !is_array($param->getDefaultValue())) {
628 1
                    $params[$param->getName()] = $param->getDefaultValue();
629 1
                    $default = str_replace('{' . $param->getName() . '}', $param->getDefaultValue(), $regex);
630 1
                }
631 1
            } else $default = $regex;
632
633 1
            return array($regex, $default, $params);
634
        }
635
636
        /**
637
         * Método que extrae el método http
638
         *
639
         * @param string $docComments
640
         *
641
         * @return string
642
         */
643 1
        private function extractReflectionHttpMethod($docComments)
644
        {
645 1
            preg_match('/@(GET|POST|PUT|DELETE)\n/i', $docComments, $routeMethod);
646
647 1
            return (count($routeMethod) > 0) ? $routeMethod[1] : "ALL";
648
        }
649
650
        /**
651
         * Método que extrae la visibilidad de una ruta
652
         *
653
         * @param string $docComments
654
         *
655
         * @return bool
656
         */
657 1
        private function extractReflectionVisibility($docComments)
658
        {
659 1
            preg_match('/@visible\ (.*)\n/i', $docComments, $visible);
660
661 1
            return (!empty($visible) && isset($visible[1]) && $visible[1] == 'false') ? FALSE : TRUE;
662
        }
663
664
        /**
665
         * Método que extrae el parámetro de caché
666
         *
667
         * @param string $docComments
668
         *
669
         * @return bool
670
         */
671 1
        private function extractReflectionCacheability($docComments)
672
        {
673 1
            preg_match('/@cache\ (.*)\n/i', $docComments, $cache);
674
675 1
            return (count($cache) > 0) ? $cache[1] : "0";
676
        }
677
678
        /**
679
         * Método que ejecuta una acción del framework y revisa si lo tenemos cacheado ya o no
680
         *
681
         * @param string $route
682
         * @param array $action
683
         * @param types\Controller $class
684
         * @param array $params
0 ignored issues
show
Documentation introduced by
Should the type for parameter $params not be array|null? Also, consider making the array more specific, something like array<String>, or String[].

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive. In addition it looks for parameters that have the generic type array and suggests a stricter type like array<String>.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
685
         */
686
        protected function executeCachedRoute($route, $action, $class, $params = NULL)
687
        {
688
            Logger::getInstance()->debugLog(_('Ruta resuelta para ') . $route);
689
            $this->session->setSessionKey("__CACHE__", $action);
690
            $cache = Cache::needCache();
691
            $execute = TRUE;
692
            if (FALSE !== $cache && Config::getInstance()->getDebugMode() === FALSE) {
693
                $cacheDataName = $this->cache->getRequestCacheHash();
694
                $cachedData = $this->cache->readFromCache("templates" . DIRECTORY_SEPARATOR . $cacheDataName, $cache, function () {
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 131 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
695
                });
696
                if (NULL !== $cachedData) {
697
                    $headers = $this->cache->readFromCache("templates" . DIRECTORY_SEPARATOR . $cacheDataName . ".headers", $cache, function () {
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 145 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
698
                    }, Cache::JSON);
699
                    Template::getInstance()->renderCache($cachedData, $headers);
700
                    $execute = FALSE;
701
                }
702
            }
703
            if ($execute) {
704
                call_user_func_array(array($class, $action['method']), $params);
705
            }
706
        }
707
708
        /**
709
         * Parse slugs to create translations
710
         *
711
         * @param string $absoluteTranslationFileName
712
         */
713 1
        private function generateSlugs($absoluteTranslationFileName)
714
        {
715 1
            $translations = $this->generateTranslationsFile($absoluteTranslationFileName);
716 1
            foreach ($this->routing as $key => &$info) {
717 1
                if (preg_match('/(ALL|GET)/i', $key)) {
718 1
                    $keyParts = $key;
719 1
                    if (FALSE === strstr("#|#", $key)) {
720 1
                        $keyParts = explode("#|#", $key);
721 1
                        $keyParts = $keyParts[1];
722 1
                    }
723 1
                    $slug = $this->slugify($keyParts);
724 1
                    if (NULL !== $slug && !array_key_exists($slug, $translations)) {
725 1
                        $translations[$slug] = $key;
726 1
                        file_put_contents($absoluteTranslationFileName, "\$translations[\"{$slug}\"] = _(\"{$slug}\");\n", FILE_APPEND);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 136 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
727 1
                    }
728 1
                    $this->slugs[$slug] = $key;
729 1
                    $info["slug"] = $slug;
730 1
                }
731 1
            }
732 1
        }
733
734
        /**
735
         * Create translation file if not exists
736
         *
737
         * @param string $absoluteTranslationFileName
738
         *
739
         * @return array
740
         */
741 1
        private function generateTranslationsFile($absoluteTranslationFileName)
742
        {
743 1
            $translations = array();
744 1
            if (file_exists($absoluteTranslationFileName)) {
745 1
                include($absoluteTranslationFileName);
746 1
            } else {
747 1
                Cache::getInstance()->storeData($absoluteTranslationFileName, "<?php \$translations = array();\n", Cache::TEXT, TRUE);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 134 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
748
            }
749
750 1
            return $translations;
751
        }
752
        
753
    }
754