Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.77% covered (success)
96.77%
30 / 31
75.00% covered (warning)
75.00%
3 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
UrlToMvcRouter
96.77% covered (success)
96.77%
30 / 31
75.00% covered (warning)
75.00%
3 / 4
13
0.00% covered (danger)
0.00%
0 / 1
 getRouters
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 requestToMvc
96.15% covered (success)
96.15%
25 / 26
0.00% covered (danger)
0.00%
0 / 1
10
 snakeCaseToUpperCamelCase
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 snakeCaseToLowerCamelCase
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace Miniframe\Middleware;
4
5use Miniframe\Core\AbstractController;
6use Miniframe\Core\AbstractMiddleware;
7
8/**
9 * Load this middleware to use basic routing (GET "/index/main" returns callable App\Controller\Index::main)
10 *
11 * This is the most basic way of routing
12 */
13class UrlToMvcRouter extends AbstractMiddleware
14{
15    /**
16     * Returns a reference to the UrlToMvcRouter::requestToMvc method
17     *
18     * @return callable[]
19     */
20    public function getRouters(): array
21    {
22        return [
23            array($this, 'requestToMvc'),
24        ];
25    }
26
27    /**
28     * Converts a request path to a controller+method (GET "/index/main" returns callable App\Controller\Index::main)
29     *
30     * @return callable
31     */
32    public function requestToMvc(): ?callable
33    {
34        $path = $this->request->getPath();
35
36        // Remove base path, if present
37        $baseHref = $this->config->get('framework', 'base_href');
38        if (!is_string($baseHref)) {
39            $baseHref = '/';
40        }
41        $basePath = explode('/', trim((string)parse_url($baseHref, PHP_URL_PATH), '/'));
42        foreach ($basePath as $prefix) {
43            if (isset($path[0]) && $path[0] == $prefix) {
44                array_shift($path);
45                $path = array_values($path); // Reset indexes
46            }
47        }
48
49        if (count($path) == 0) {
50            $controller = 'Index';
51            $method = 'main';
52        } elseif (count($path) == 1) {
53            $controller = $this->snakeCaseToUpperCamelCase($path[0]);
54            $method = 'main';
55        } else {
56            $controller = $this->snakeCaseToUpperCamelCase($path[0]);
57            $method = $this->snakeCaseToLowerCamelCase($path[1]);
58        }
59
60        // Add Controller namespace
61        $controller = '\\App\\Controller\\' . $controller;
62        if (!class_exists($controller)) {
63            return null;
64        }
65        if (!is_subclass_of($controller, AbstractController::class)) {
66            throw new \RuntimeException('Controller invalid: ' . $controller . ' not a ' . AbstractController::class);
67        }
68        $callable = [new $controller($this->request, $this->config), $method];
69        if (!is_callable($callable)) {
70            return null;
71        }
72
73        return $callable;
74    }
75
76    /**
77     * Converts snake_case_text to UpperCamelCaseText
78     *
79     * @param string $snakeCase Text as snake_case.
80     *
81     * @return string
82     */
83    protected function snakeCaseToUpperCamelCase(string $snakeCase): string
84    {
85        return str_replace(' ', '', ucwords(str_replace(['_', '-'], [' ', ' '], $snakeCase)));
86    }
87
88    /**
89     * Converts snake_case_text to lowerCamelCaseText
90     *
91     * @param string $snakeCase Text as snake_case.
92     *
93     * @return string
94     */
95    protected function snakeCaseToLowerCamelCase(string $snakeCase): string
96    {
97        return lcfirst($this->snakeCaseToUpperCamelCase($snakeCase));
98    }
99}