Passed
Push — master ( 4751e9...ec72de )
by Rafael
38:16
created

CachedPathVariableModifier::__invoke()   B

Complexity

Conditions 10
Paths 7

Size

Total Lines 74
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 110

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 45
c 2
b 0
f 0
dl 0
loc 74
ccs 0
cts 61
cp 0
rs 7.3333
cc 10
nc 7
nop 1
crap 110

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
declare(strict_types=1);
3
4
/*
5
 * This file is part of the TYPO3 CMS project.
6
 *
7
 * It is free software; you can redistribute it and/or modify it under
8
 * the terms of the GNU General Public License, either version 2
9
 * of the License, or any later version.
10
 *
11
 * For the full copyright and license information, please read the
12
 * LICENSE.txt file that was distributed with this source code.
13
 *
14
 * The TYPO3 project - inspiring people to share!
15
 */
16
17
namespace ApacheSolrForTypo3\Solr\EventListener\EnhancedRouting;
18
19
use ApacheSolrForTypo3\Solr\Event\Routing\BeforeProcessCachedVariablesEvent;
20
use ApacheSolrForTypo3\Solr\Routing\RoutingService;
21
use Psr\Http\Message\UriInterface;
22
use TYPO3\CMS\Core\Utility\GeneralUtility;
23
24
/**
25
 * Event listener to handle path elements containing placeholder
26
 *
27
 * @author Lars Tode <[email protected]>
28
 */
29
class CachedPathVariableModifier
30
{
31
    /**
32
     * @var RoutingService
33
     */
34
    protected $routingService;
35
36
    public function __invoke(BeforeProcessCachedVariablesEvent $event): void
37
    {
38
        if (!$event->hasRouting()) {
39
            return;
40
        }
41
        $pathVariables = $this->getPathVariablesFromUri($event->getUri());
42
43
        // No path variables exists .. skip processing
44
        if (empty($pathVariables)) {
45
            return;
46
        }
47
48
        $variableKeys = $event->getVariableKeys();
49
        $variableValues = $event->getVariableValues();
50
        $enhancerConfiguration = $event->getRouterConfiguration();
51
52
        $this->routingService = GeneralUtility::makeInstance(
53
            RoutingService::class,
54
            $enhancerConfiguration['solr'],
55
            (string)$enhancerConfiguration['extensionKey']
56
        );
57
58
        if (!$this->routingService->isRouteEnhancerForSolr((string)$enhancerConfiguration['type'])) {
59
            return;
60
        }
61
62
        // TODO: Detect multiValue? Could be removed?
63
        $multiValue = false;
64
65
        $standardizedKeys = $variableKeys;
66
67
        $variableKeysCount = count($variableKeys);
68
        for ($i = 0; $i < $variableKeysCount; $i++) {
69
            $standardizedKey = $this->standardizeKey($variableKeys[$i]);
70
            if (!$this->containsPathVariable($standardizedKey, $pathVariables) || empty($variableValues[$standardizedKey])) {
71
                continue;
72
            }
73
            $value = '';
74
            // Note: Some values contain the multi value separator
75
            if ($multiValue) {
76
                // Note: if the customer configured a + as separator an additional check on the facet value is required!
77
                $facets = $this->routingService->pathFacetStringToArray(
78
                    $this->standardizeKey((string)$variableValues[$standardizedKey])
79
                );
80
81
                $singleValues = [];
82
                $index = 0;
83
                foreach ($facets as $facet) {
84
                    if (mb_strpos($facet, ':') !== false) {
85
                        [$prefix, $value] = explode(
86
                            ':',
87
                            $facet,
88
                            2
89
                        );
90
                        $singleValues[] = $value;
91
                        $index++;
92
                    } else {
93
                        $singleValues[$index - 1] .= ' ' . $facet;
94
                    }
95
                }
96
                $value = $this->routingService->pathFacetsToString($singleValues);
97
            } else {
98
                [$prefix, $value] = explode(
99
                    ':',
100
                    $this->standardizeKey((string)$variableValues[$standardizedKey]),
101
                    2
102
                );
103
            }
104
            $standardizedKeys[$i] = $standardizedKey;
105
            $variableValues[$standardizedKey] = $value;
106
        }
107
108
        $event->setVariableValues($variableValues);
109
        $event->setVariableKeys($standardizedKeys);
110
    }
111
112
    /**
113
     * Extract path variables from URI
114
     *
115
     * @param UriInterface $uri
116
     * @return array
117
     */
118
    protected function getPathVariablesFromUri(UriInterface $uri): array
119
    {
120
        $elements = explode('/', $uri->getPath());
121
        $variables = [];
122
123
        foreach ($elements as $element) {
124
            if (empty($element)) {
125
                continue;
126
            }
127
            $element = $this->standardizeKey($element);
128
            if (substr($element, 0, 3) !== '###') {
129
                continue;
130
            }
131
132
            $variables[] = $element;
133
        }
134
135
        return $variables;
136
    }
137
138
    /**
139
     * Standardize a given string in order to reduce the amount of if blocks
140
     *
141
     * @param string $key
142
     * @return string
143
     */
144
    protected function standardizeKey(string $key): string
145
    {
146
        $map = [
147
            '%23' => '#',
148
            '%3A' => ':',
149
        ];
150
        return str_replace(array_keys($map), array_values($map), $key);
151
    }
152
153
    /**
154
     * Check if the variable is includes within the path variables
155
     *
156
     * @param string $variableName
157
     * @param array $pathVariables
158
     * @return bool
159
     */
160
    protected function containsPathVariable(string $variableName, array $pathVariables): bool
161
    {
162
        if (in_array($variableName, $pathVariables)) {
163
            return true;
164
        }
165
        foreach ($pathVariables as $keyName => $value) {
166
            $segments = explode($this->routingService->getUrlFacetPathService()->getMultiValueSeparator(), $value);
167
            if (in_array($variableName, $segments)) {
168
                return true;
169
            }
170
        }
171
172
        return false;
173
    }
174
}
175