Issues (808)

src/midcom/routing/resolver.php (1 issue)

Labels
Severity
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 Symfony\Component\Routing\Router;
16
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
17
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
18
use Symfony\Component\HttpFoundation\Response;
19
20
/**
21
 * @package midcom.routing
22
 */
23
class resolver
24
{
25
    private Request $request;
26
27
    private parser $parser;
28
29
    private \midcom_core_context $context;
30
31 353
    public function __construct(Request $request)
32
    {
33 353
        $this->request = $request;
34 353
        $this->context = $request->attributes->get('context');
35 353
        $this->parser = new parser($this->context);
36
    }
37
38 356
    public static function get_router(string $component, array $request_switch = []) : Router
39
    {
40 356
        $loader = new loader;
41 356
        if (!empty($request_switch)) {
42
            return new Router($loader, $request_switch);
43
        }
44 356
        $identifier = str_replace('.', '_', $component);
45 356
        return new Router($loader, $component, [
46 356
            'cache_dir' => midcom::get()->getCacheDir() . '/routing/' . $identifier,
47 356
        ]);
48
    }
49
50
    /**
51
     * @throws midcom_error_notfound
52
     */
53 353
    public function process_midcom() : bool
54
    {
55 353
        if ($url = $this->parser->find_urlmethod()) {
56 1
            $router = self::get_router('midcom');
57 1
            $router->getContext()
58 1
                ->fromRequest($this->request);
59
60
            try {
61 1
                $result = $router->match($url);
62
            } catch (ResourceNotFoundException) {
63
                throw new midcom_error_notfound('This URL method is unknown.');
64
            }
65 1
            $this->request->attributes->add($result);
66
67 1
            return true;
68
        }
69 352
        return false;
70
    }
71
72
    /**
73
     * Basically this method will parse the URL and search for a component that can
74
     * handle the request. If one is found, it will process the request, if not, it
75
     * will report an error, depending on the situation.
76
     *
77
     * Details: The logic will traverse the node tree, and for the last node it will load
78
     * the component that is responsible for it. If the component
79
     * declares to be able to handle the call, its handle function is executed. Depending
80
     * if the handle was successful or not, it will either display an HTTP error page or
81
     * prepares the content handler to display the content later on.
82
     *
83
     * If the parsing process doesn't find any component that declares to be able to
84
     * handle the request, an HTTP 404 - Not Found error is triggered.
85
     *
86
     * @throws midcom_error_forbidden
87
     * @throws midcom_error_notfound
88
     */
89 352
    public function process_component()
90
    {
91 352
        $topic = $this->parser->find_topic();
92 352
        $argv = $this->parser->argv;
93
94
        // Get component interface class
95 352
        $component_interface = midcom::get()->componentloader->get_interface_class($topic->component);
96 352
        $viewer = $component_interface->get_viewer($topic);
97
98 352
        $prefix = $this->context->get_key(MIDCOM_CONTEXT_ANCHORPREFIX);
99
100
        // Check if we need to start up a plugin.
101 352
        if (   count($argv) > 1
102 352
            && $config = plugin::get_config($argv[0], $argv[1])) {
103 88
            $namespace = array_shift($argv);
104 88
            $name = array_shift($argv);
105 88
            $prefix .= $namespace . '/' . $name . '/';
106 88
            debug_add("Loading the plugin {$namespace}/{$name}");
107 88
            $viewer->load_plugin($name, new $config['class'], $config);
108
        }
109
110 352
        $url = '/';
111 352
        if (!empty($argv)) {
112 332
            $url .= implode('/', $argv);
113 332
            $uri = $this->context->get_key(MIDCOM_CONTEXT_URI);
114 332
            if ($uri !== '/' && str_ends_with($uri, '/')) {
0 ignored issues
show
It seems like $uri can also be of type false; however, parameter $haystack of str_ends_with() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

114
            if ($uri !== '/' && str_ends_with(/** @scrutinizer ignore-type */ $uri, '/')) {
Loading history...
115 327
                $url .= '/';
116
            }
117
        }
118 352
        $router = $viewer->get_router();
119 352
        $router->getContext()
120 352
            ->fromRequest($this->request)
121 352
            ->setBaseUrl(substr($prefix, 0, -1));
122
123
        try {
124 352
            $result = $router->match($url);
125 15
        } catch (ResourceNotFoundException) {
126
            // No match
127 15
            debug_add("Component {$viewer->_component} in {$viewer->_topic->name} declared unable to handle request.", MIDCOM_LOG_INFO);
128 15
            throw new midcom_error_notfound("This page is not available on this server.");
129
        } catch (MethodNotAllowedException $e) {
130
            debug_add("Component {$viewer->_component} in {$viewer->_topic->name} declared unable to handle request (method not allowed).", MIDCOM_LOG_INFO);
131
            throw new midcom_error_forbidden($e->getMessage(), Response::HTTP_METHOD_NOT_ALLOWED);
132
        }
133
134 352
        $result['args'] = array_values(array_filter($result, function(string $name) {
135 352
            return !str_starts_with($name, '_');
136 352
        }, ARRAY_FILTER_USE_KEY));
137
138 352
        $result['__viewer'] = $viewer;
139 352
        $result['_controller'] = str_replace('::', '::_handler_', $result['_controller']);
140
141 352
        if (!empty($result['component'])) {
142 6
            $this->context->set_key(MIDCOM_CONTEXT_COMPONENT, $result['component']);
143 6
            $topic = new \midcom_db_topic();
144 6
            $topic->component = $result['component'];
145 6
            $this->context->set_key(MIDCOM_CONTEXT_CONTENTTOPIC, $topic);
146
        }
147
148 352
        $this->request->attributes->add($result);
149 352
        $this->context->set_key(MIDCOM_CONTEXT_SHOWCALLBACK, $viewer->show(...));
150
    }
151
}