Rewriter::rewrite()   F
last analyzed

Complexity

Conditions 16
Paths 278

Size

Total Lines 72
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 39
CRAP Score 16.0931

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 16
eloc 42
c 2
b 0
f 0
nc 278
nop 2
dl 0
loc 72
ccs 39
cts 42
cp 0.9286
crap 16.0931
rs 3.7583

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
/**
3
 * @author Gerard van Helden <[email protected]>
4
 * @copyright Zicht Online <http://zicht.nl>
5
 */
6
7
namespace Zicht\Bundle\UrlBundle\Url;
8
9
use Zicht\Bundle\UrlBundle\Aliasing\Aliasing;
10
11
/**
12
 * Class Rewriter
13
 */
14
class Rewriter
15
{
16
    private $localDomains = [];
17
18
    /**
19
     * Constructor
20
     *
21
     * @param Aliasing $aliasing
22
     */
23 26
    public function __construct(Aliasing $aliasing)
24
    {
25 26
        $this->aliasing = $aliasing;
0 ignored issues
show
Bug Best Practice introduced by
The property aliasing does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
26 26
    }
27
28
    /**
29
     * Set a list of domains in urls to consider 'local', i.e. process the 'path' while keeping the domain in tact.
30
     *
31
     * @param string[] $localDomains
32
     */
33 9
    public function setLocalDomains($localDomains)
34
    {
35 9
        $this->localDomains = $localDomains;
36 9
    }
37
38
    /**
39
     * Rewrite all $urls, given the $mappings map of mappings (from => to), within the context of
40
     * host names $localDomains.
41
     *
42
     * Example:
43
     *
44
     *     rewrite(['http://example.org/foo?x=y'], ['/foo' => '/bar'], ['example.org']);
45
     *
46
     *
47
     * Would return the following mapping:
48
     *
49
     * ['http://example.org/foo?x=y' => 'http://example.org/bar?x=y']
50
     *
51
     * @param string[] $urls
52
     * @param string $mode
53
     * @return array
54
     */
55 23
    public function rewrite(array $urls, $mode)
56
    {
57 23
        $mappings = $this->aliasing->getAliasingMap(
58 23
            array_map(
59 23
                [$this, 'extractPath'],
60 23
                $urls
61
            ),
62 23
            $mode
63
        );
64
65 23
        $ret = [];
66 23
        foreach ($urls as $url) {
67 22
            if (isset($mappings[$url])) {
68
                // early match, if the value can be mapping directly, used that.
69 11
                $ret[$url] = $mappings[$url];
70 11
                continue;
71
            }
72
73 11
            $parts = $this->parseUrl($url);
74
75 11
            if (!isset($parts['path'])) {
76
                // no path, nothing to map.
77 1
                $ret[$url] = $url;
78 1
                continue;
79
            }
80
81 11
            if (isset($parts['host'])) {
82 8
                if (!in_array($parts['host'], $this->localDomains)) {
83
                    // external url, don't do mapping.
84 3
                    $ret[$url] = $url;
85 3
                    continue;
86
                }
87
            }
88
89
            // don't rewrite this.
90 8
            if (isset($parts['user']) || isset($parts['password'])) {
91
                $ret[$url]=  $url;
92
                continue;
93
            }
94
95 8
            $rewritten = '';
96 8
            if (isset($parts['scheme'])) {
97 5
                $rewritten .= $parts['scheme'] . ':';
98
            }
99 8
            if (isset($parts['host'])) {
100 5
                $rewritten .= '//' . $parts['host'];
101
            }
102 8
            if (isset($parts['port'])) {
103
                $rewritten .= ':' . $parts['port'];
104
            }
105 8
            if (isset($parts['path'])) {
106 8
                if (isset($mappings[$parts['path']])) {
107 6
                    $rewritten .= $mappings[$parts['path']];
108
                } else {
109
                    // no match on path level, keep as-is
110 3
                    $ret[$url] = $url;
111 3
                    continue;
112
                }
113
            }
114 6
            if (isset($parts['params'])) {
115 3
                $rewritten .= '/' . $parts['params'];
116
            }
117 6
            if (isset($parts['query'])) {
118 3
                $rewritten .= '?' . $parts['query'];
119
            }
120 6
            if (isset($parts['fragment'])) {
121 1
                $rewritten .= '#' . $parts['fragment'];
122
            }
123
124 6
            $ret[$url] = $rewritten;
125
        }
126 23
        return $ret;
127
    }
128
129
130
    /**
131
     * Extract the path of the URL which is considered for aliasing.
132
     *
133
     * @param string $url
134
     * @return string|null
135
     */
136 25
    public function extractPath($url)
137
    {
138 25
        $parts = $this->parseUrl($url);
139
140 25
        if (!isset($parts['path'])) {
141 1
            return null;
142
        }
143
        // ignore non-http schemes
144 25
        if (isset($parts['scheme']) && !in_array($parts['scheme'], ['http', 'https'])) {
145 1
            return null;
146
        }
147
148 24
        return $parts['path'];
149
    }
150
151
152
    /**
153
     * Parse the url, and additionally add a 'parameters' part which is defined as follows:
154
     *
155
     * The parameters may occur after the path, separated by slashes, where each of the key value pairs are
156
     * separated by '='.
157
     *
158
     * e.g.:
159
     *      /this/is/the/path/while=these/are=paremeters
160
     *      ^----- path ----^ ^------- params ---------^
161
     *
162
     * @param string $url
163
     * @return mixed
164
     */
165 25
    public function parseUrl($url)
166
    {
167 25
        $ret = parse_url($url);
168
169 25
        if (isset($ret['path'])) {
170 25
            $parts = explode('/', $ret['path']);
171 25
            $params = [];
172 25
            while (false !== strpos(end($parts), '=')) {
173 5
                array_push($params, array_pop($parts));
174
            }
175 25
            if (count($params)) {
176 5
                $ret['path'] = join('/', $parts);
177 5
                $ret['params'] = join('/', $params);
178
            }
179
        }
180
181 25
        return $ret;
182
    }
183
184
185
    /**
186
     * This convenenience method processes the urls in the content with a structure matching the following:
187
     *
188
     * ['the url' => ['total string that should be replaced', 'the prefix', 'the url', 'the suffix']]
189
     *
190
     * e.g.:
191
     * 'http://example.org/' => ['<a href="http://example.org/"', '<a href="', 'http://example.org/', '"']
192
     *
193
     * It replaces contents by replacing all occurrences of the 0 index with the 1 index, concatenated with the
194
     * rewritten url, and the suffix.
195
     *
196
     * @param string $content
197
     * @param string $mode
198
     * @param mixed $matchedGroups
199
     * @return string
200
     */
201 14
    public function rewriteMatches($content, $mode, $matchedGroups)
202
    {
203 14
        $replacements = [];
204 14
        foreach ($this->rewrite(array_keys($matchedGroups), $mode) as $from => $to) {
205 13
            if (isset($matchedGroups[$from]) && $from !== $to) {
206 10
                foreach ($matchedGroups[$from] as list($source, $prefix, $oldUrl, $suffix)) {
207 13
                    $replacements[$source] = $prefix . $to . $suffix;
208
                }
209
            }
210
        }
211
212 14
        return strtr($content, $replacements);
213
    }
214
}
215