Test Failed
Push — master ( 4d2954...a25839 )
by Andreas
23:42
created

resolver::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

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