Passed
Push — master ( 5e945b...52d6d0 )
by Andreas
20:39
created

resolver::get_handler()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 37
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 24
CRAP Score 5

Importance

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