Completed
Push — master ( b566b5...857ea9 )
by Fran
06:33
created

Router::searchAction()   C

Complexity

Conditions 7
Paths 8

Size

Total Lines 23
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 8
Bugs 1 Features 0
Metric Value
cc 7
eloc 16
c 8
b 1
f 0
nc 8
nop 1
dl 0
loc 23
ccs 0
cts 16
cp 0
crap 56
rs 6.7272
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 7
        public function __construct()
49
        {
50 7
            $this->finder = new Finder();
51 7
            $this->cache = Cache::getInstance();
52 7
            $this->session = Security::getInstance();
53 7
            $this->init();
54 6
        }
55
56
        /**
57
         * Inicializador Router
58
         * @throws ConfigException
59
         */
60 2
        public function init()
61
        {
62 2
            if (!file_exists(CONFIG_DIR . DIRECTORY_SEPARATOR . "urls.json") || Config::getInstance()->getDebugMode()) {
63 2
                $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
         * Método que busca el componente que ejecuta la ruta
178
         *
179
         * @param string $route
180
         *
181
         * @throws \Exception
182
         */
183
        protected function searchAction($route)
184
        {
185
            //Revisamos si tenemos la ruta registrada
186
            $parts = parse_url($route);
187
            $path = (array_key_exists('path', $parts)) ? $parts['path'] : $route;
188
            $httpRequest = Request::getInstance()->getMethod();
189
            foreach ($this->routing as $pattern => $action) {
190
                list($httpMethod, $routePattern) = $this->extractHttpRoute($pattern);
191
                $matched = $this->matchRoutePattern($routePattern, $path);
192
                if ($matched && ($httpMethod === "ALL" || $httpRequest === $httpMethod)) {
193
                    $get = $this->extractComponents($route, $routePattern);
194
                    /** @var $class \PSFS\base\types\Controller */
195
                    $class = $this->getClassToCall($action);
196
                    try {
197
                        return $this->executeCachedRoute($route, $action, $class, $get);
198
                    } catch (\Exception $e) {
199
                        Logger::getInstance()->debugLog($e->getMessage(), array($e->getFile(), $e->getLine()));
200
                        throw new RouterException($e->getMessage(), 404, $e);
201
                    }
202
                }
203
            }
204
            throw new RouterException(_("Ruta no encontrada"));
205
        }
206
207
        /**
208
         * Método que manda las cabeceras de autenticación
209
         * @return string HTML
210
         */
211
        protected function sentAuthHeader()
212
        {
213
            return AdminServices::getInstance()->setAdminHeaders();
214
        }
215
216
        /**
217
         * Método que redirige a la pantalla web del login
218
         *
219
         * @param string $route
220
         *
221
         * @return string HTML
222
         */
223
        public function redirectLogin($route)
224
        {
225
            return Admin::staticAdminLogon($route);
226
        }
227
228
        /**
229
         * Método que chequea el acceso a una zona restringida
230
         *
231
         * @param string $route
232
         *
233
         * @throws AccessDeniedException
234
         */
235
        protected function checkRestrictedAccess($route)
236
        {
237
            //Chequeamos si entramos en el admin
238
            if (preg_match('/^\/admin/i', $route)
239
                || (!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...
240
            ) {
241
                if (!preg_match('/^\/admin\/login/i', $route) && !$this->session->checkAdmin()) {
242
                    throw new AccessDeniedException();
243
                }
244
                Logger::getInstance()->debugLog('Acceso autenticado al admin');
245
            }
246
        }
247
248
        /**
249
         * Método que extrae de la url los parámetros REST
250
         *
251
         * @param string $route
252
         *
253
         * @param string $pattern
254
         *
255
         * @return array
256
         */
257
        protected function extractComponents($route, $pattern)
258
        {
259
            $url = parse_url($route);
260
            $_route = explode("/", $url['path']);
261
            $_pattern = explode("/", $pattern);
262
            $get = array();
263
            if (!empty($_pattern)) foreach ($_pattern as $index => $component) {
264
                $_get = array();
265
                preg_match_all('/^\{(.*)\}$/i', $component, $_get);
266
                if (!empty($_get[1]) && isset($_route[$index])) {
267
                    $get[array_pop($_get[1])] = $_route[$index];
268
                }
269
            }
270
271
            return $get;
272
        }
273
274
        /**
275
         * Método que regenera el fichero de rutas
276
         * @throws ConfigException
277
         */
278 2
        public function hydrateRouting()
279
        {
280 2
            $base = SOURCE_DIR;
281 2
            $modules = realpath(CORE_DIR);
282 2
            $this->routing = $this->inspectDir($base, "PSFS", array());
283 1
            if (file_exists($modules)) {
284
                $this->routing = $this->inspectDir($modules, "", $this->routing);
285
            }
286 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...
287 1
            $home = Config::getInstance()->get('home_action');
288 1
            if (NULL !== $home || $home !== '') {
289 1
                $home_params = NULL;
290 1
                foreach ($this->routing as $pattern => $params) {
291 1
                    list($method, $route) = $this->extractHttpRoute($pattern);
292 1
                    if (preg_match("/" . preg_quote($route, "/") . "$/i", "/" . $home)) {
293
                        $home_params = $params;
294
                    }
295 1
                }
296 1
                if (NULL !== $home_params) {
297
                    $this->routing['/'] = $home_params;
298
                }
299 1
            }
300 1
        }
301
302
        /**
303
         * Método que inspecciona los directorios en busca de clases que registren rutas
304
         *
305
         * @param string $origen
306
         * @param string $namespace
307
         * @param array $routing
308
         *
309
         * @return array
310
         * @throws ConfigException
311
         */
312 2
        private function inspectDir($origen, $namespace = 'PSFS', $routing)
313
        {
314 2
            $files = $this->finder->files()->in($origen)->path('/(controller|api)/i')->name("*.php");
315 2
            foreach ($files as $file) {
316 2
                $filename = str_replace("/", '\\', str_replace($origen, '', $file->getPathname()));
317 2
                $routing = $this->addRouting($namespace . str_replace('.php', '', $filename), $routing);
318 2
            }
319 1
            $this->finder = new Finder();
320
321 1
            return $routing;
322
        }
323
324
        /**
325
         * Método que añade nuevas rutas al array de referencia
326
         *
327
         * @param string $namespace
328
         * @param array $routing
329
         *
330
         * @return array
331
         * @throws ConfigException
332
         */
333 2
        private function addRouting($namespace, $routing)
334
        {
335 2
            if (class_exists($namespace)) {
336 2
                $reflection = new \ReflectionClass($namespace);
337 2
                if (FALSE === $reflection->isAbstract() && FALSE === $reflection->isInterface()) {
338 2
                    $this->extractDomain($reflection);
339 2
                    $classComments = $reflection->getDocComment();
340 2
                    preg_match('/@api\ (.*)\n/im', $classComments, $apiPath);
341 2
                    $api = '';
342 2
                    if (count($apiPath)) {
343
                        $api = array_key_exists(1, $apiPath) ? $apiPath[1] : $api;
344
                    }
345 2
                    foreach ($reflection->getMethods() as $method) {
346 2
                        if ($method->isPublic()) {
347 2
                            $docComments = $method->getDocComment();
348 2
                            preg_match('/@route\ (.*)\n/i', $docComments, $sr);
349 2
                            if (count($sr)) {
350 2
                                list($regex, $default, $params) = $this->extractReflectionParams($sr, $method);
351 2
                                if (strlen($api)) {
352
                                    $regex = str_replace('{__API__}', $api, $regex);
353
                                    $default = str_replace('{__API__}', $api, $default);
354
                                }
355 2
                                $httpMethod = $this->extractReflectionHttpMethod($docComments);
356 2
                                $visible = $this->extractReflectionVisibility($docComments);
357 2
                                $expiration = $this->extractReflectionCacheability($docComments);
358 2
                                $routing[$httpMethod . "#|#" . $regex] = array(
359 2
                                    "class"   => $namespace,
360 2
                                    "method"  => $method->getName(),
361 2
                                    "params"  => $params,
362 2
                                    "default" => $default,
363 2
                                    "visible" => $visible,
364 2
                                    "http"    => $httpMethod,
365 2
                                    "cache"   => $expiration,
366
                                );
367 2
                            }
368 2
                        }
369 2
                    }
370 2
                }
371 2
            }
372
373 2
            return $routing;
374
        }
375
376
        /**
377
         * Método que extrae de la ReflectionClass los datos necesarios para componer los dominios en los templates
378
         *
379
         * @param \ReflectionClass $class
380
         *
381
         * @return Router
382
         * @throws ConfigException
383
         */
384 2
        protected function extractDomain($class)
385
        {
386
            //Calculamos los dominios para las plantillas
387 2
            if ($class->hasConstant("DOMAIN")) {
388 2
                $domain = "@" . $class->getConstant("DOMAIN") . "/";
389 2
                $path = dirname($class->getFileName()) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR;
390 2
                $path = realpath($path) . DIRECTORY_SEPARATOR;
391 2
                $tpl_path = "templates";
392 2
                $public_path = "public";
393 2
                $model_path = "models";
394 2
                if (!preg_match("/ROOT/", $domain)) {
395
                    $tpl_path = ucfirst($tpl_path);
396
                    $public_path = ucfirst($public_path);
397
                    $model_path = ucfirst($model_path);
398
                }
399 2
                if ($class->hasConstant("TPL")) {
400
                    $tpl_path .= DIRECTORY_SEPARATOR . $class->getConstant("TPL");
401
                }
402 2
                $this->domains[$domain] = array(
403 2
                    "template" => $path . $tpl_path,
404 2
                    "model"    => $path . $model_path,
405 2
                    "public"   => $path . $public_path,
406
                );
407 2
            }
408
409 2
            return $this;
410
        }
411
412
        /**
413
         * Método que genera las urls amigables para usar dentro del framework
414
         * @return Router
415
         */
416 1
        public function simpatize()
417
        {
418 1
            $translationFileName = "translations" . DIRECTORY_SEPARATOR . "routes_translations.php";
419 1
            $absoluteTranslationFileName = CACHE_DIR . DIRECTORY_SEPARATOR . $translationFileName;
420 1
            $this->generateSlugs($absoluteTranslationFileName);
421 1
            Config::createDir(CONFIG_DIR);
422 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...
423
424 1
            return $this;
425
        }
426
427
        /**
428
         * Método que devuelve el slug de un string dado
429
         *
430
         * @param string $text
431
         *
432
         * @return string
433
         */
434 1
        private function slugify($text)
435
        {
436
            // replace non letter or digits by -
437 1
            $text = preg_replace('~[^\\pL\d]+~u', '-', $text);
438
439
            // trim
440 1
            $text = trim($text, '-');
441
442
            // transliterate
443 1
            if (function_exists('iconv')) {
444 1
                $text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
445 1
            }
446
447
            // lowercase
448 1
            $text = strtolower($text);
449
450
            // remove unwanted characters
451 1
            $text = preg_replace('~[^-\w]+~', '', $text);
452
453 1
            if (empty($text)) {
454
                return 'n-a';
455
            }
456
457 1
            return $text;
458
        }
459
460
        /**
461
         * Método que devuelve una ruta del framework
462
         *
463
         * @param string $slug
464
         * @param boolean $absolute
465
         * @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...
466
         *
467
         * @return string|null
468
         * @throws RouterException
469
         */
470
        public function getRoute($slug = '', $absolute = FALSE, $params = NULL)
471
        {
472
            if (strlen($slug) === 0) {
473
                return ($absolute) ? Request::getInstance()->getRootUrl() . '/' : '/';
474
            }
475
            if (NULL === $slug || !array_key_exists($slug, $this->slugs)) {
476
                throw new RouterException(_("No existe la ruta especificada"));
477
            }
478
            $url = ($absolute) ? Request::getInstance()->getRootUrl() . $this->slugs[$slug] : $this->slugs[$slug];
479
            if (!empty($params)) foreach ($params as $key => $value) {
480
                $url = str_replace("{" . $key . "}", $value, $url);
481
            } elseif (!empty($this->routing[$this->slugs[$slug]]["default"])) {
482
                $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...
483
            }
484
485
            return preg_replace('/(GET|POST|PUT|DELETE|ALL)\#\|\#/', '', $url);
486
        }
487
488
        /**
489
         * Método que devuelve las rutas de administración
490
         * @return array
491
         */
492 1
        public function getAdminRoutes()
493
        {
494 1
            $routes = array();
495 1
            foreach ($this->routing as $route => $params) {
496 1
                list($httpMethod, $routePattern) = $this->extractHttpRoute($route);
497 1
                if (preg_match('/^\/admin(\/|$)/', $routePattern)) {
498 1
                    if (preg_match('/^PSFS/', $params["class"])) {
499 1
                        $profile = "superadmin";
500 1
                    } else {
501
                        $profile = "admin";
502
                    }
503 1
                    if (!empty($params["default"]) && preg_match('/(GET|ALL)/i', $httpMethod)) {
504 1
                        $_profile = ($params["visible"]) ? $profile : 'adminhidden';
505 1
                        if(!array_key_exists($_profile, $routes)) {
506 1
                            $routes[$_profile] = array();
507 1
                        }
508 1
                        $routes[$_profile][] = $params["slug"];
509 1
                    }
510 1
                }
511 1
            }
512 1
            if (array_key_exists("superadmin", $routes)) {
513 1
                asort($routes["superadmin"]);
514 1
            }
515 1
            if (array_key_exists("adminhidden", $routes)) {
516 1
                asort($routes["adminhidden"]);
517 1
            }
518 1
            if (array_key_exists('admin', $routes)) {
519
                asort($routes["admin"]);
520
            }
521
522 1
            return $routes;
523
        }
524
525
        /**
526
         * Método que devuelve le controlador del admin
527
         * @return Admin
528
         */
529
        public function getAdmin()
530
        {
531
            return Admin::getInstance();
532
        }
533
534
        /**
535
         * Método que extrae los dominios
536
         * @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...
537
         */
538
        public function getDomains()
539
        {
540
            return $this->domains;
541
        }
542
543
        /**
544
         * Método que extrae el controller a invocar
545
         *
546
         * @param string $action
547
         *
548
         * @return Object
549
         */
550
        protected function getClassToCall($action)
551
        {
552
            $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...
553
            if (NULL !== $class && method_exists($class, "init")) {
554
                $class->init();
555
            }
556
557
            return $class;
558
        }
559
560
        /**
561
         * Método que compara la ruta web con la guardada en la cache
562
         *
563
         * @param $routePattern
564
         * @param $path
565
         *
566
         * @return bool
567
         */
568
        protected function matchRoutePattern($routePattern, $path)
569
        {
570
            $expr = preg_replace('/\{(.*)\}/', '###', $routePattern);
571
            $expr = preg_quote($expr, '/');
572
            $expr = str_replace('###', '(.*)', $expr);
573
            $expr2 = preg_replace('/\(\.\*\)$/', '', $expr);
574
            $matched = preg_match('/^' . $expr . '\/?$/i', $path) || preg_match('/^' . $expr2 . '?$/i', $path);
575
576
            return $matched;
577
        }
578
579
        /**
580
         * @param $pattern
581
         *
582
         * @return array
583
         */
584 1
        protected function extractHttpRoute($pattern)
585
        {
586 1
            $httpMethod = "ALL";
587 1
            $routePattern = $pattern;
588 1
            if (FALSE !== strstr($pattern, "#|#")) {
589 1
                list($httpMethod, $routePattern) = explode("#|#", $pattern, 2);
590 1
            }
591
592 1
            return array($httpMethod, $routePattern);
593
        }
594
595
        /**
596
         * Método que extrae los parámetros de una función
597
         *
598
         * @param array $sr
599
         * @param \ReflectionMethod $method
600
         *
601
         * @return array
602
         */
603 2
        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...
604
        {
605 2
            $regex = $sr[1] ?: $sr[0];
606 2
            $default = '';
607 2
            $params = array();
608 2
            $parameters = $method->getParameters();
609 2
            if (count($parameters) > 0) foreach ($parameters as $param) {
610 2
                if ($param->isOptional() && !is_array($param->getDefaultValue())) {
611 2
                    $params[$param->getName()] = $param->getDefaultValue();
612 2
                    $default = str_replace('{' . $param->getName() . '}', $param->getDefaultValue(), $regex);
613 2
                }
614 2
            } else $default = $regex;
615
616 2
            return array($regex, $default, $params);
617
        }
618
619
        /**
620
         * Método que extrae el método http
621
         *
622
         * @param string $docComments
623
         *
624
         * @return string
625
         */
626 2
        private function extractReflectionHttpMethod($docComments)
627
        {
628 2
            preg_match('/@(GET|POST|PUT|DELETE)\n/i', $docComments, $routeMethod);
629
630 2
            return (count($routeMethod) > 0) ? $routeMethod[1] : "ALL";
631
        }
632
633
        /**
634
         * Método que extrae la visibilidad de una ruta
635
         *
636
         * @param string $docComments
637
         *
638
         * @return bool
639
         */
640 2
        private function extractReflectionVisibility($docComments)
641
        {
642 2
            preg_match('/@visible\ (.*)\n/i', $docComments, $visible);
643
644 2
            return (!empty($visible) && isset($visible[1]) && $visible[1] == 'false') ? FALSE : TRUE;
645
        }
646
647
        /**
648
         * Método que extrae el parámetro de caché
649
         *
650
         * @param string $docComments
651
         *
652
         * @return bool
653
         */
654 2
        private function extractReflectionCacheability($docComments)
655
        {
656 2
            preg_match('/@cache\ (.*)\n/i', $docComments, $cache);
657
658 2
            return (count($cache) > 0) ? $cache[1] : "0";
659
        }
660
661
        /**
662
         * Método que ejecuta una acción del framework y revisa si lo tenemos cacheado ya o no
663
         *
664
         * @param string $route
665
         * @param array $action
666
         * @param types\Controller $class
667
         * @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...
668
         */
669
        protected function executeCachedRoute($route, $action, $class, $params = NULL)
670
        {
671
            Logger::getInstance()->debugLog(_('Ruta resuelta para ') . $route);
672
            $this->session->setSessionKey("__CACHE__", $action);
673
            $cache = Cache::needCache();
674
            $execute = TRUE;
675
            if (FALSE !== $cache && Config::getInstance()->getDebugMode() === FALSE) {
676
                $cacheDataName = $this->cache->getRequestCacheHash();
677
                $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...
678
                });
679
                if (NULL !== $cachedData) {
680
                    $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...
681
                    }, Cache::JSON);
682
                    Template::getInstance()->renderCache($cachedData, $headers);
683
                    $execute = FALSE;
684
                }
685
            }
686
            if ($execute) {
687
                call_user_func_array(array($class, $action['method']), $params);
688
            }
689
        }
690
691
        /**
692
         * Parse slugs to create translations
693
         *
694
         * @param string $absoluteTranslationFileName
695
         */
696 1
        private function generateSlugs($absoluteTranslationFileName)
697
        {
698 1
            $translations = $this->generateTranslationsFile($absoluteTranslationFileName);
699 1
            foreach ($this->routing as $key => &$info) {
700 1
                if (preg_match('/(ALL|GET)/i', $key)) {
701 1
                    $keyParts = $key;
702 1
                    if (FALSE === strstr("#|#", $key)) {
703 1
                        $keyParts = explode("#|#", $key);
704 1
                        $keyParts = $keyParts[1];
705 1
                    }
706 1
                    $slug = $this->slugify($keyParts);
707 1
                    if (NULL !== $slug && !array_key_exists($slug, $translations)) {
708 1
                        $translations[$slug] = $key;
709 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...
710 1
                    }
711 1
                    $this->slugs[$slug] = $key;
712 1
                    $info["slug"] = $slug;
713 1
                }
714 1
            }
715 1
        }
716
717
        /**
718
         * Create translation file if not exists
719
         *
720
         * @param string $absoluteTranslationFileName
721
         *
722
         * @return array
723
         */
724 1
        private function generateTranslationsFile($absoluteTranslationFileName)
725
        {
726 1
            $translations = array();
727 1
            if (file_exists($absoluteTranslationFileName)) {
728 1
                include($absoluteTranslationFileName);
729 1
            } else {
730 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...
731
            }
732
733 1
            return $translations;
734
        }
735
    }
736