Completed
Push — EZP-29891 ( 916cf6...0402ff )
by
unknown
16:53
created

UrlAliasHandler::lookup()   B

Complexity

Conditions 7
Paths 22

Size

Total Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 22
nop 1
dl 0
loc 39
rs 8.3626
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the UrlAlias Handler implementation.
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\Cache;
10
11
use eZ\Publish\API\Repository\Exceptions\NotFoundException as APINotFoundException;
12
use eZ\Publish\Core\Base\Exceptions\NotFoundException;
13
use eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler as UrlAliasHandlerInterface;
14
use eZ\Publish\SPI\Persistence\Content\UrlAlias;
15
16
/**
17
 * @see \eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler
18
 */
19
class UrlAliasHandler extends AbstractHandler implements UrlAliasHandlerInterface
20
{
21
    /**
22
     * Constant used for storing not found results for lookup().
23
     */
24
    const NOT_FOUND = 0;
25
26
    /**
27
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::publishUrlAliasForLocation
28
     */
29
    public function publishUrlAliasForLocation(
30
        $locationId,
31
        $parentLocationId,
32
        $name,
33
        $languageCode,
34
        $alwaysAvailable = false,
35
        $updatePathIdentificationString = false
36
    ) {
37
        $this->logger->logCall(
38
            __METHOD__,
39
            array(
40
                'location' => $locationId,
41
                'parent' => $parentLocationId,
42
                'name' => $name,
43
                'language' => $languageCode,
44
                'alwaysAvailable' => $alwaysAvailable,
45
            )
46
        );
47
48
        // we need to clear all because we are unable to clear cache for children
49
        // locations only based on the locationId
50
        $this->cache->clear('urlAlias');
51
52
        $this->persistenceHandler->urlAliasHandler()->publishUrlAliasForLocation(
53
            $locationId,
54
            $parentLocationId,
55
            $name,
56
            $languageCode,
57
            $alwaysAvailable,
58
            $updatePathIdentificationString
59
        );
60
    }
61
62
    /**
63
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::createCustomUrlAlias
64
     */
65
    public function createCustomUrlAlias($locationId, $path, $forwarding = false, $languageCode = null, $alwaysAvailable = false)
66
    {
67
        $this->logger->logCall(
68
            __METHOD__,
69
            array(
70
                'location' => $locationId,
71
                '$path' => $path,
72
                '$forwarding' => $forwarding,
73
                'language' => $languageCode,
74
                'alwaysAvailable' => $alwaysAvailable,
75
            )
76
        );
77
78
        $urlAlias = $this->persistenceHandler->urlAliasHandler()->createCustomUrlAlias(
79
            $locationId,
80
            $path,
81
            $forwarding,
82
            $languageCode,
83
            $alwaysAvailable
84
        );
85
86
        $this->cache->getItem('urlAlias', $urlAlias->id)->set($urlAlias)->save();
87
        $cache = $this->cache->getItem('urlAlias', 'location', $urlAlias->destination, 'custom');
88
        $urlAliasIds = $cache->get();
89
        if ($cache->isMiss()) {
90
            $urlAliasIds = array();
91
        }
92
93
        $urlAliasIds[] = $urlAlias->id;
94
        $cache->set($urlAliasIds)->save();
95
96
        return $urlAlias;
97
    }
98
99
    /**
100
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::createGlobalUrlAlias
101
     */
102
    public function createGlobalUrlAlias($resource, $path, $forwarding = false, $languageCode = null, $alwaysAvailable = false)
103
    {
104
        $this->logger->logCall(
105
            __METHOD__,
106
            array(
107
                'resource' => $resource,
108
                'path' => $path,
109
                'forwarding' => $forwarding,
110
                'language' => $languageCode,
111
                'alwaysAvailable' => $alwaysAvailable,
112
            )
113
        );
114
115
        $urlAlias = $this->persistenceHandler->urlAliasHandler()->createGlobalUrlAlias(
116
            $resource,
117
            $path,
118
            $forwarding,
119
            $languageCode,
120
            $alwaysAvailable
121
        );
122
123
        $this->cache->getItem('urlAlias', $urlAlias->id)->set($urlAlias)->save();
124
125
        return $urlAlias;
126
    }
127
128
    /**
129
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::listGlobalURLAliases
130
     */
131
    public function listGlobalURLAliases($languageCode = null, $offset = 0, $limit = -1)
132
    {
133
        $this->logger->logCall(__METHOD__, array('language' => $languageCode, 'offset' => $offset, 'limit' => $limit));
134
135
        return $this->persistenceHandler->urlAliasHandler()->listGlobalURLAliases($languageCode, $offset, $limit);
136
    }
137
138
    /**
139
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::listURLAliasesForLocation
140
     */
141 View Code Duplication
    public function listURLAliasesForLocation($locationId, $custom = false)
142
    {
143
        // Look for location to list of url alias id's cache
144
        if ($custom) {
145
            $cache = $this->cache->getItem('urlAlias', 'location', $locationId, 'custom');
146
        } else {
147
            $cache = $this->cache->getItem('urlAlias', 'location', $locationId);
148
        }
149
        $urlAliasIds = $cache->get();
150
        if ($cache->isMiss()) {
151
            $this->logger->logCall(__METHOD__, array('location' => $locationId, 'custom' => $custom));
152
            $urlAliases = $this->persistenceHandler->urlAliasHandler()->listURLAliasesForLocation($locationId, $custom);
153
154
            $urlAliasIds = array();
155
            foreach ($urlAliases as $urlAlias) {
156
                $urlAliasIds[] = $urlAlias->id;
157
            }
158
159
            $cache->set($urlAliasIds)->save();
160
        } else {
161
            // Reuse loadUrlAlias for the url alias object cache
162
            $urlAliases = array();
163
            foreach ($urlAliasIds as $urlAliasId) {
164
                $urlAliases[] = $this->loadUrlAlias($urlAliasId);
165
            }
166
        }
167
168
        return $urlAliases;
169
    }
170
171
    /**
172
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::removeURLAliases
173
     */
174
    public function removeURLAliases(array $urlAliases)
175
    {
176
        $this->logger->logCall(__METHOD__, array('aliases' => $urlAliases));
177
        $return = $this->persistenceHandler->urlAliasHandler()->removeURLAliases($urlAliases);
178
179
        $this->cache->clear('urlAlias', 'url');//TIMBER! (no easy way to do reverse lookup of urls)
180
        foreach ($urlAliases as $urlAlias) {
181
            $this->cache->clear('urlAlias', $urlAlias->id);
182
            if ($urlAlias->type === UrlAlias::LOCATION) {
183
                $this->cache->clear('urlAlias', 'location', $urlAlias->destination);
184
            }
185
            if ($urlAlias->isCustom) {
186
                $this->cache->clear('urlAlias', 'location', $urlAlias->destination, 'custom');
187
            }
188
        }
189
190
        return $return;
191
    }
192
193
    /**
194
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::lookup
195
     */
196
    public function lookup($url)
197
    {
198
        // Look for url to url alias id cache
199
        // Replace slashes by "|" to be sure not to mix cache key combinations in underlying lib.
200
        $cacheKey = $url ?: '/';
201
        $cache = $this->cache->getItem('urlAlias', 'url', $cacheKey);
202
        $urlAliasId = $cache->get();
203
        if ($cache->isMiss()) {
204
            $urlAliasHistoryCache = $this->cache->getItem('urlAlias', 'url', 'history', $cacheKey);
205
            $historyUrlAlias = $urlAliasHistoryCache->get();
206
207
            if (!$urlAliasHistoryCache->isMiss()) {
208
                return $historyUrlAlias;
209
            }
210
211
            // Also cache "not found" as this function is heavliy used and hance should be cached
212
            try {
213
                $this->logger->logCall(__METHOD__, array('url' => $url));
214
                $urlAlias = $this->persistenceHandler->urlAliasHandler()->lookup($url);
215
216
                if ($urlAlias->isHistory) {
217
                    $urlAliasHistoryCache->set($urlAlias)->save();
218
                } else {
219
                    $cache->set($urlAlias->id)->save();
220
                    $urlAliasCache = $this->cache->getItem('urlAlias', $urlAlias->id);
221
                    $urlAliasCache->set($urlAlias)->save();
222
                }
223
            } catch (APINotFoundException $e) {
224
                $cache->set(self::NOT_FOUND)->save();
225
                throw $e;
226
            }
227
        } elseif ($urlAliasId === self::NOT_FOUND) {
228
            throw new NotFoundException('UrlAlias', $url);
229
        } else {
230
            $urlAlias = $this->loadUrlAlias($urlAliasId);
231
        }
232
233
        return $urlAlias;
234
    }
235
236
    /**
237
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::loadUrlAlias
238
     */
239 View Code Duplication
    public function loadUrlAlias($id)
240
    {
241
        // Look for url alias cache
242
        $cache = $this->cache->getItem('urlAlias', $id);
243
        $urlAlias = $cache->get();
244
        if ($cache->isMiss()) {
245
            $this->logger->logCall(__METHOD__, array('alias' => $id));
246
            $urlAlias = $this->persistenceHandler->urlAliasHandler()->loadUrlAlias($id);
247
            $cache->set($urlAlias)->save();
248
        }
249
250
        return $urlAlias;
251
    }
252
253
    /**
254
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::locationMoved
255
     */
256
    public function locationMoved($locationId, $oldParentId, $newParentId)
257
    {
258
        $this->logger->logCall(
259
            __METHOD__,
260
            array(
261
                'location' => $locationId,
262
                'oldParent' => $oldParentId,
263
                'newParent' => $newParentId,
264
            )
265
        );
266
267
        $return = $this->persistenceHandler->urlAliasHandler()->locationMoved($locationId, $oldParentId, $newParentId);
268
        $this->cache->clear('urlAlias', 'url');//TIMBER! (Will have to load url aliases for location to be able to clear specific entries)
269
270
        return $return;
271
    }
272
273
    /**
274
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::locationCopied
275
     */
276
    public function locationCopied($locationId, $newLocationId, $newParentId)
277
    {
278
        $this->logger->logCall(
279
            __METHOD__,
280
            array(
281
                'oldLocation' => $locationId,
282
                'newLocation' => $newLocationId,
283
                'newParent' => $newParentId,
284
            )
285
        );
286
287
        $return = $this->persistenceHandler->urlAliasHandler()->locationCopied(
288
            $locationId,
289
            $newLocationId,
290
            $newParentId
291
        );
292
        $this->cache->clear('urlAlias', 'url'); // required due to caching not found aliases
293
294
        return $return;
295
    }
296
297
    /**
298
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::locationDeleted
299
     */
300 View Code Duplication
    public function locationDeleted($locationId)
301
    {
302
        $this->logger->logCall(__METHOD__, array('location' => $locationId));
303
        $return = $this->persistenceHandler->urlAliasHandler()->locationDeleted($locationId);
304
305
        $this->clearLocation($locationId);
306
307
        return $return;
308
    }
309
310
    /**
311
     * @param $locationId
312
     */
313
    protected function clearLocation($locationId)
314
    {
315
        $locationCache = $this->cache->getItem('urlAlias', 'location', $locationId);
316
317
        if ($locationCache->isMiss()) {
318
            // we need to clear all if we don't have location id in cache
319
            $this->cache->clear('urlAlias');
320
        } else {
321
            $urlAliasIds = $locationCache->get();
322
            foreach ((array) $urlAliasIds as $urlAliasId) {
323
                $this->cache->clear('urlAlias', $urlAliasId);
324
            }
325
            $this->cache->clear('urlAlias', 'url');
326
            $locationCache->clear();
327
        }
328
    }
329
330
    /**
331
     * @see \eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::swap
332
     */
333 View Code Duplication
    public function locationSwapped($location1Id, $location1ParentId, $location2Id, $location2ParentId)
334
    {
335
        $this->logger->logCall(
336
            __METHOD__,
337
            [
338
                'location1Id' => $location1Id,
339
                'location1ParentId' => $location1ParentId,
340
                'location2Id' => $location2Id,
341
                'location2ParentId' => $location2ParentId,
342
            ]
343
        );
344
345
        $return = $this->persistenceHandler->urlAliasHandler()->locationSwapped(
346
            $location1Id,
347
            $location1ParentId,
348
            $location2Id,
349
            $location2ParentId
350
        );
351
352
        $this->clearLocation($location1Id);
353
        $this->clearLocation($location2Id);
354
355
        return $return;
356
    }
357
358
    /**
359
     * {@inheritdoc}
360
     */
361
    public function archiveUrlAliasesForDeletedTranslations($locationId, $parentLocationId, array $languageCodes)
362
    {
363
        $this->logger->logCall(
364
            __METHOD__,
365
            [
366
                'locationId' => $locationId,
367
                'parentLocationId' => $parentLocationId,
368
                'languageCodes' => implode(',', $languageCodes),
369
            ]
370
        );
371
372
        $this->persistenceHandler->urlAliasHandler()->archiveUrlAliasesForDeletedTranslations(
373
            $locationId,
374
            $parentLocationId,
375
            $languageCodes
376
        );
377
378
        $this->clearLocation($locationId);
379
    }
380
381
    /**
382
     * Delete corrupted URL aliases (global, custom and system).
383
     *
384
     * @return int Number of deleted URL aliases
385
     */
386
    public function deleteCorruptedUrlAliases()
387
    {
388
        $this->logger->logCall(__METHOD__);
389
390
        $deletedCount = $this->persistenceHandler->urlAliasHandler()->deleteCorruptedUrlAliases();
391
392
        $this->cache->clear('urlAlias');
393
394
        return $deletedCount;
395
    }
396
397
    /**
398
     * Attempt repairing auto-generated URL aliases for the given Location (including history).
399
     *
400
     * Note: it is assumed that at this point original, working, URL Alias for Location is published.
401
     *
402
     * @param int $locationId
403
     *
404
     * @throws \eZ\Publish\Core\Base\Exceptions\BadStateException
405
     */
406 View Code Duplication
    public function repairBrokenUrlAliasesForLocation($locationId)
407
    {
408
        $this->logger->logCall(__METHOD__, ['locationId' => $locationId]);
409
410
        $this->persistenceHandler->urlAliasHandler()->repairBrokenUrlAliasesForLocation($locationId);
411
412
        $this->clearLocation($locationId);
413
    }
414
}
415