Issues (808)

src/midcom/routing/parser.php (4 issues)

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 midcom_connection;
12
use midcom_core_context;
13
use midcom_db_topic;
14
15
/**
16
 * URL name parser that uses the topic structure
17
 *
18
 * @package midcom.routing
19
 */
20
class parser
21
{
22
    public array $argv = [];
23
24
    private ?midcom_db_topic $current = null;
25
26
    private string $url = '';
27
28
    /**
29
     * Objects by URL
30
     *
31
     * @var midcom_db_topic[]
32
     */
33
    private array $objects = [];
34
35
    private midcom_core_context $context;
36
37 354
    public function __construct(midcom_core_context $context)
38
    {
39 354
        $this->context = $context;
40 354
        $url = $this->context->get_key(MIDCOM_CONTEXT_URI);
41
42 354
        $prefix_length = strlen(midcom_connection::get_url('prefix'));
0 ignored issues
show
It seems like midcom_connection::get_url('prefix') can also be of type null; however, parameter $string of strlen() 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

42
        $prefix_length = strlen(/** @scrutinizer ignore-type */ midcom_connection::get_url('prefix'));
Loading history...
43 354
        if (   $prefix_length > 1
44 354
            && str_starts_with($url, midcom_connection::get_url('prefix'))) {
0 ignored issues
show
It seems like midcom_connection::get_url('prefix') can also be of type null; however, parameter $needle of str_starts_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

44
            && str_starts_with($url, /** @scrutinizer ignore-type */ midcom_connection::get_url('prefix'))) {
Loading history...
It seems like $url can also be of type false; however, parameter $haystack of str_starts_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

44
            && str_starts_with(/** @scrutinizer ignore-type */ $url, midcom_connection::get_url('prefix'))) {
Loading history...
45
            $url = substr($url, $prefix_length);
0 ignored issues
show
It seems like $url can also be of type false; however, parameter $string of substr() 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

45
            $url = substr(/** @scrutinizer ignore-type */ $url, $prefix_length);
Loading history...
46
        }
47 354
        $url = trim($url, '/');
48 354
        if ($url != '') {
49 338
            $argv = explode('/', $url);
50 338
            foreach ($argv as $val) {
51 338
                if ($val !== '') {
52 338
                    $this->argv[] = $val;
53
                }
54
            }
55
        }
56
    }
57
58
    /**
59
     * Try to fetch a URL variable.
60
     *
61
     * Try to decode an midcom-<key>-<value> pair at the current URL
62
     * position.
63
     *
64
     * On success it returns the command it found.
65
     */
66 353
    public function find_urlmethod() : ?string
67
    {
68 353
        if (   empty($this->argv)
69 353
            || !str_starts_with($this->argv[0], 'midcom-')) {
70 352
            return null;
71
        }
72 1
        return $this->context->get_key(MIDCOM_CONTEXT_URI);
73
    }
74
75
    /**
76
     * @throws \midcom_error
77
     */
78 352
    public function find_topic() : midcom_db_topic
79
    {
80 352
        $this->current = $this->context->get_key(MIDCOM_CONTEXT_ROOTTOPIC);
81 352
        if (!$this->current) {
82
            throw new \midcom_error('Root node missing.');
83
        }
84 352
        $this->walk_topics();
85
86
        // Initialize context
87 352
        $this->context->set_key(MIDCOM_CONTEXT_ANCHORPREFIX, midcom_connection::get_url('self') . $this->url);
88 352
        $this->context->set_key(MIDCOM_CONTEXT_COMPONENT, $this->current->component);
89 352
        $this->context->set_key(MIDCOM_CONTEXT_CONTENTTOPIC, $this->current);
90 352
        $this->context->set_key(MIDCOM_CONTEXT_URLTOPICS, $this->objects);
91
92 352
        return $this->current;
93
    }
94
95
    /**
96
     * Load topics recursively from argv
97
     */
98 352
    private function walk_topics()
99
    {
100 352
        if (empty($this->argv)) {
101
            // No arguments left
102 20
            return;
103
        }
104
105 336
        $object_url = $this->argv[0] . '/';
106 336
        if (!empty($this->url)) {
107 3
            $object_url = $this->url . $object_url;
108
        }
109 336
        if (!array_key_exists($object_url, $this->objects)) {
110 336
            $qb = midcom_db_topic::new_query_builder();
111 336
            $qb->add_constraint('name', '=', $this->argv[0]);
112 336
            $qb->add_constraint('up', '=', $this->current->id);
113
114 336
            if ($qb->count() == 0) {
115
                // last load returned ACCESS DENIED, no sense to dig deeper
116 336
                if ($qb->denied > 0) {
117
                    throw new \midcom_error_forbidden;
118
                }
119
                // allow for handler switches to work
120 336
                return;
121
            }
122
            // Set to current topic
123 3
            $this->objects[$object_url] = $qb->get_result(0);
124
        }
125
        // Remove this component from path
126 3
        array_shift($this->argv);
127
128
        // Set as current object
129 3
        $this->url = $object_url;
130 3
        $this->current = $this->objects[$object_url];
131 3
        $this->walk_topics();
132
    }
133
}
134