Completed
Push — master ( 0021de...b72ee8 )
by Andreas
17:13
created

resolver::get_router()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 6
c 0
b 0
f 0
nc 2
nop 2
dl 0
loc 9
ccs 7
cts 7
cp 1
crap 2
rs 10
1
<?php
2
/**
3
 * @package midcom.routing
4
 * @author CONTENT CONTROL http://www.contentcontrol-berlin.de/
5
 * @copyright CONTENT CONTROL http://www.contentcontrol-berlin.de/
6
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License
7
 */
8
9
namespace midcom\routing;
10
11
use Symfony\Component\HttpFoundation\Request;
12
use midcom;
13
use midcom_error_forbidden;
14
use midcom_error_notfound;
15
use midcom_baseclasses_components_viewer;
16
use Symfony\Component\Routing\Router;
17
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
18
19
/**
20
 * @package midcom.routing
21
 */
22
class resolver
23
{
24
    /**
25
     * @var Request
26
     */
27
    private $request;
28
29
    /**
30
     * @var parser
31
     */
32
    private $parser;
33
34
    /**
35
     * @var \midcom_core_context
36
     */
37
    private $context;
38
39
    /**
40
     * @param Request $request
41
     */
42 338
    public function __construct(Request $request)
43
    {
44 338
        $this->request = $request;
45 338
        $this->context = $request->attributes->get('context');
46 338
        $this->parser = new parser($this->context);
47 338
    }
48
49 341
    public static function get_router(string $component, array $request_switch = []) : Router
50
    {
51 341
        $loader = new loader;
52 341
        if (!empty($request_switch)) {
53 120
            return new Router($loader, $request_switch);
54
        }
55 296
        $identifier = str_replace('.', '_', $component);
56 296
        return new Router($loader, $component, [
57 296
            'cache_dir' => midcom::get()->getCacheDir() . '/routing/' . $identifier,
58
        ]);
59
    }
60
61
    /**
62
     * @throws midcom_error_notfound
63
     */
64 338
    public function process_midcom() : bool
65
    {
66 338
        if ($url = $this->parser->find_urlmethod()) {
67
            $router = self::get_router('midcom');
68
            $router->getContext()
69
                ->fromRequest($this->request);
70
71
            try {
72
                $result = $router->match($url);
73
            } catch (ResourceNotFoundException $e) {
74
                throw new midcom_error_notfound('This URL method is unknown.');
75
            }
76
            $this->request->attributes->add($result);
77
78
            return true;
79
        }
80 338
        return false;
81
    }
82
83
    /**
84
     * Basically this method will parse the URL and search for a component that can
85
     * handle the request. If one is found, it will process the request, if not, it
86
     * will report an error, depending on the situation.
87
     *
88
     * Details: The logic will traverse the node tree, and for the last node it will load
89
     * the component that is responsible for it. This component gets the chance to
90
     * accept the request, which is basically a call to can_handle. If the component
91
     * declares to be able to handle the call, its handle function is executed. Depending
92
     * if the handle was successful or not, it will either display an HTTP error page or
93
     * prepares the content handler to display the content later on.
94
     *
95
     * If the parsing process doesn't find any component that declares to be able to
96
     * handle the request, an HTTP 404 - Not Found error is triggered.
97
     *
98
     * @throws midcom_error_forbidden
99
     * @throws midcom_error_notfound
100
     */
101 338
    public function process_component()
102
    {
103 338
        $topic = $this->parser->find_topic();
104 338
        $this->request->attributes->set('argv', $this->parser->argv);
105
106
        // Get component interface class
107 338
        $component_interface = midcom::get()->componentloader->get_interface_class($topic->component);
108 338
        $viewer = $component_interface->get_viewer($topic);
109
110
        // Make can_handle check
111 338
        $parameters = $this->get_parameters($viewer);
112 338
        $viewer->prepare_handler($parameters);
113
114 338
        $this->context->set_key(MIDCOM_CONTEXT_SHOWCALLBACK, [$viewer, 'show']);
115
116 338
        foreach ($parameters as $key => $value) {
117 338
            if ($key === 'handler') {
118 338
                $key = '_controller';
119 338
                $value[1] = '_handler_' . $value[1];
120 338
            } elseif ($key === '_route') {
121 338
                $key = 'handler_id';
122
            }
123 338
            $this->request->attributes->set($key, $value);
124
        }
125 338
        $viewer->handle();
126 338
    }
127
128
    /**
129
     * Checks against all registered handlers if a valid one can be found.
130
     */
131 338
    private function get_parameters(midcom_baseclasses_components_viewer $viewer) : array
132
    {
133 338
        $argv = $this->request->attributes->get('argv', []);
134 338
        $prefix = $this->context->get_key(MIDCOM_CONTEXT_ANCHORPREFIX);
135
136
        // Check if we need to start up a plugin.
137 338
        if (   count($argv) > 1
138 338
            && $config = plugin::get_config($argv[0], $argv[1])) {
139 84
            $namespace = array_shift($argv);
140 84
            $name = array_shift($argv);
141 84
            $prefix .= $namespace . '/' . $name . '/';
142 84
            debug_add("Loading the plugin {$namespace}/{$name}");
143 84
            $viewer->load_plugin($name, new $config['class'], $config);
144
        }
145
146 338
        $url = '/';
147 338
        if (!empty($argv)) {
148 319
            $url .= implode('/', $argv) . '/';
149
        }
150 338
        $router = $viewer->get_router();
151 338
        $router->getContext()
152 338
            ->fromRequest($this->request)
153 338
            ->setBaseUrl(substr($prefix, 0, -1));
154
155
        try {
156 338
            $result = $router->match($url);
157 12
        } catch (ResourceNotFoundException $e) {
158
            // No match
159 12
            debug_add("Component {$viewer->_component} in {$viewer->_topic->name} declared unable to handle request.", MIDCOM_LOG_INFO);
160 12
            throw new midcom_error_notfound("This page is not available on this server.");
161
        }
162
163
        $result['args'] = array_values(array_filter($result, function($name) {
164 338
            return !str_starts_with($name, '_');
165 338
        }, ARRAY_FILTER_USE_KEY));
166
167 338
        return $result;
168
    }
169
}