Completed
Push — 7.5 ( f79096...9972f5 )
by
unknown
27:34
created

Handler::substitute()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 2
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the UrlWildcard Handler.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Publish\Core\Persistence\Legacy\Content\UrlWildcard;
10
11
use eZ\Publish\SPI\Persistence\Content\UrlWildcard;
12
use eZ\Publish\SPI\Persistence\Content\UrlWildcard\Handler as BaseUrlWildcardHandler;
13
use eZ\Publish\Core\Base\Exceptions\NotFoundException;
14
15
/**
16
 * The UrlWildcard Handler provides nice urls with wildcards management.
17
 *
18
 * Its methods operate on a representation of the url alias data structure held
19
 * inside a storage engine.
20
 */
21
class Handler implements BaseUrlWildcardHandler
22
{
23
    private const PLACEHOLDERS_REGEXP = '(\{(\d+)\})';
24
25
    /**
26
     * UrlWildcard Gateway.
27
     *
28
     * @var \eZ\Publish\Core\Persistence\Legacy\Content\UrlWildcard\Gateway
29
     */
30
    protected $gateway;
31
32
    /**
33
     * UrlWildcard Mapper.
34
     *
35
     * @var \eZ\Publish\Core\Persistence\Legacy\Content\UrlWildcard\Mapper
36
     */
37
    protected $mapper;
38
39
    /**
40
     * Creates a new UrlWildcard Handler.
41
     *
42
     * @param \eZ\Publish\Core\Persistence\Legacy\Content\UrlWildcard\Gateway $gateway
43
     * @param \eZ\Publish\Core\Persistence\Legacy\Content\UrlWildcard\Mapper $mapper
44
     */
45
    public function __construct(Gateway $gateway, Mapper $mapper)
46
    {
47
        $this->gateway = $gateway;
48
        $this->mapper = $mapper;
49
    }
50
51
    /**
52
     * Creates a new url wildcard.
53
     *
54
     * @param string $sourceUrl
55
     * @param string $destinationUrl
56
     * @param bool $forward
57
     *
58
     * @return \eZ\Publish\SPI\Persistence\Content\UrlWildcard
59
     */
60
    public function create($sourceUrl, $destinationUrl, $forward = false)
61
    {
62
        $urlWildcard = $this->mapper->createUrlWildcard(
63
            $sourceUrl,
64
            $destinationUrl,
65
            $forward
66
        );
67
68
        $urlWildcard->id = $this->gateway->insertUrlWildcard($urlWildcard);
69
70
        return $urlWildcard;
71
    }
72
73
    /**
74
     * removes an url wildcard.
75
     *
76
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if the url wild card was not found
77
     *
78
     * @param mixed $id
79
     */
80
    public function remove($id)
81
    {
82
        $this->gateway->deleteUrlWildcard($id);
83
    }
84
85
    /**
86
     * Loads a url wild card.
87
     *
88
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if the url wild card was not found
89
     *
90
     * @param mixed $id
91
     *
92
     * @return \eZ\Publish\SPI\Persistence\Content\UrlWildcard
93
     */
94
    public function load($id)
95
    {
96
        $row = $this->gateway->loadUrlWildcardData($id);
97
98
        if (empty($row)) {
99
            throw new NotFoundException('UrlWildcard', $id);
100
        }
101
102
        return $this->mapper->extractUrlWildcardFromRow($row);
103
    }
104
105
    /**
106
     * Loads all url wild card (paged).
107
     *
108
     * @param mixed $offset
109
     * @param mixed $limit
110
     *
111
     * @return \eZ\Publish\SPI\Persistence\Content\UrlWildcard[]
112
     */
113
    public function loadAll($offset = 0, $limit = -1)
114
    {
115
        return $this->mapper->extractUrlWildcardsFromRows(
116
            $this->gateway->loadUrlWildcardsData($offset, $limit)
117
        );
118
    }
119
120
    /**
121
     * Performs lookup for given URL.
122
     *
123
     * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if the url wild card was not found
124
     *
125
     * @param string $sourceUrl
126
     *
127
     * @return \eZ\Publish\SPI\Persistence\Content\UrlWildcard
128
     */
129
    public function translate(string $sourceUrl): UrlWildcard
130
    {
131
        $row = $this->gateway->loadUrlWildcardBySourceUrl($sourceUrl);
132
133
        if (!empty($row)) {
134
            return $this->mapper->extractUrlWildcardFromRow($row);
135
        }
136
137
        // can't find UrlWildcard by simple lookup, continue and try to translate
138
139
        $rows = $this->gateway->loadUrlWildcardsData();
140
        uasort($rows,
141
            static function ($row1, $row2) {
142
                return strlen($row2['source_url']) - strlen($row1['source_url']);
143
            }
144
        );
145
146
        foreach ($rows as $row) {
147
            if ($uri = $this->match($sourceUrl, $row)) {
148
                $row['destination_url'] = $uri;
149
150
                return $this->mapper->extractUrlWildcardFromRow($row);
151
            }
152
        }
153
154
        throw new NotFoundException('URLWildcard', $sourceUrl);
155
    }
156
157
    /**
158
     * Checks whether UrlWildcard with given source url exits.
159
     *
160
     * @param string $sourceUrl
161
     *
162
     * @return bool
163
     */
164
    public function exactSourceUrlExists(string $sourceUrl): bool
165
    {
166
        $row = $this->gateway->loadUrlWildcardBySourceUrl($sourceUrl);
167
168
        return !empty($row);
169
    }
170
171
    /**
172
     * Tests if the given url matches against the given url wildcard.
173
     *
174
     * if the wildcard matches on the given url this method will return a ready
175
     * to use destination url, otherwise this method will return <b>NULL</b>.
176
     *
177
     * @param string $url
178
     * @param array $wildcard
179
     *
180
     * @return string|null
181
     */
182
    private function match(string $url, array $wildcard): ?string
183
    {
184
        if (preg_match($this->compile($wildcard['source_url']), $url, $match)) {
185
            return $this->substitute($wildcard['destination_url'], $match);
186
        }
187
188
        return null;
189
    }
190
191
    /**
192
     * Compiles the given url pattern into a regular expression.
193
     *
194
     * @param string $sourceUrl
195
     *
196
     * @return string
197
     */
198
    private function compile(string $sourceUrl): string
199
    {
200
        return '(^' . str_replace('\\*', '(.*)', preg_quote($sourceUrl)) . '$)U';
201
    }
202
203
    /**
204
     * Substitutes all placeholders ({\d}) in the given <b>$destinationUrl</b> with
205
     * the values from the given <b>$values</b> array.
206
     *
207
     * @param string $destinationUrl
208
     * @param array $values
209
     *
210
     * @return string
211
     */
212
    private function substitute(string $destinationUrl, array $values): string
213
    {
214
        preg_match_all(self::PLACEHOLDERS_REGEXP, $destinationUrl, $matches);
215
216
        foreach ($matches[1] as $match) {
217
            $destinationUrl = str_replace("{{$match}}", $values[$match], $destinationUrl);
218
        }
219
220
        return $destinationUrl;
221
    }
222
}
223