Completed
Push — master ( ae9952...b2a7f6 )
by
unknown
137:19 queued 113:13
created

repairBrokenUrlAliasesForLocation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 13
rs 9.8333
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
     * {@inheritdoc}
28
     */
29 View Code Duplication
    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
        $this->persistenceHandler->urlAliasHandler()->publishUrlAliasForLocation(
49
            $locationId,
50
            $parentLocationId,
51
            $name,
52
            $languageCode,
53
            $alwaysAvailable,
54
            $updatePathIdentificationString
55
        );
56
57
        $this->cache->invalidateTags(['urlAlias-location-' . $locationId, 'urlAlias-location-path-' . $locationId, 'urlAlias-notFound']);
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63 View Code Duplication
    public function createCustomUrlAlias($locationId, $path, $forwarding = false, $languageCode = null, $alwaysAvailable = false)
64
    {
65
        $this->logger->logCall(
66
            __METHOD__,
67
            array(
68
                'location' => $locationId,
69
                '$path' => $path,
70
                '$forwarding' => $forwarding,
71
                'language' => $languageCode,
72
                'alwaysAvailable' => $alwaysAvailable,
73
            )
74
        );
75
76
        $urlAlias = $this->persistenceHandler->urlAliasHandler()->createCustomUrlAlias(
77
            $locationId,
78
            $path,
79
            $forwarding,
80
            $languageCode,
81
            $alwaysAvailable
82
        );
83
84
        $this->cache->invalidateTags(['urlAlias-location-' . $locationId, 'urlAlias-location-path-' . $locationId, 'urlAlias-notFound']);
85
86
        return $urlAlias;
87
    }
88
89
    /**
90
     * {@inheritdoc}
91
     */
92
    public function createGlobalUrlAlias($resource, $path, $forwarding = false, $languageCode = null, $alwaysAvailable = false)
93
    {
94
        $this->logger->logCall(
95
            __METHOD__,
96
            array(
97
                'resource' => $resource,
98
                'path' => $path,
99
                'forwarding' => $forwarding,
100
                'language' => $languageCode,
101
                'alwaysAvailable' => $alwaysAvailable,
102
            )
103
        );
104
105
        $urlAlias = $this->persistenceHandler->urlAliasHandler()->createGlobalUrlAlias(
106
            $resource,
107
            $path,
108
            $forwarding,
109
            $languageCode,
110
            $alwaysAvailable
111
        );
112
113
        $this->cache->invalidateTags(['urlAlias-notFound']);
114
115
        return $urlAlias;
116
    }
117
118
    /**
119
     * {@inheritdoc}
120
     */
121
    public function listGlobalURLAliases($languageCode = null, $offset = 0, $limit = -1)
122
    {
123
        $this->logger->logCall(__METHOD__, array('language' => $languageCode, 'offset' => $offset, 'limit' => $limit));
124
125
        return $this->persistenceHandler->urlAliasHandler()->listGlobalURLAliases($languageCode, $offset, $limit);
126
    }
127
128
    /**
129
     * {@inheritdoc}
130
     */
131
    public function listURLAliasesForLocation($locationId, $custom = false)
132
    {
133
        $cacheItem = $this->cache->getItem('ez-urlAlias-location-list-' . $locationId . ($custom ? '-custom' : ''));
134
        if ($cacheItem->isHit()) {
135
            return $cacheItem->get();
136
        }
137
138
        $this->logger->logCall(__METHOD__, array('location' => $locationId, 'custom' => $custom));
139
        $urlAliases = $this->persistenceHandler->urlAliasHandler()->listURLAliasesForLocation($locationId, $custom);
140
141
        $cacheItem->set($urlAliases);
142
        $cacheTags = ['urlAlias-location-' . $locationId];
143
        foreach ($urlAliases as $urlAlias) {
144
            $cacheTags = $this->getCacheTags($urlAlias, $cacheTags);
145
        }
146
        $cacheItem->tag($cacheTags);
147
        $this->cache->save($cacheItem);
148
149
        return $urlAliases;
150
    }
151
152
    /**
153
     * {@inheritdoc}
154
     */
155
    public function removeURLAliases(array $urlAliases)
156
    {
157
        $this->logger->logCall(__METHOD__, array('aliases' => $urlAliases));
158
        $return = $this->persistenceHandler->urlAliasHandler()->removeURLAliases($urlAliases);
159
160
        $cacheTags = [];
161
        foreach ($urlAliases as $urlAlias) {
162
            $cacheTags[] = 'urlAlias-' . $urlAlias->id;
163
            if ($urlAlias->type === UrlAlias::LOCATION) {
164
                $cacheTags[] = 'urlAlias-location-' . $urlAlias->destination;
165
                $cacheTags[] = 'urlAlias-location-path-' . $urlAlias->destination;
166
            }
167
            if ($urlAlias->isCustom) {
168
                $cacheTags[] = 'urlAlias-custom-' . $urlAlias->destination;
169
            }
170
        }
171
        $this->cache->invalidateTags($cacheTags);
172
173
        return $return;
174
    }
175
176
    /**
177
     * {@inheritdoc}
178
     */
179
    public function lookup($url)
180
    {
181
        $cacheItem = $this->cache->getItem(
182
            'ez-urlAlias-url-' . str_replace(['/', ':', '(', ')', '@'], ['_S', '_C', '_B', '_B', '_A'], $url)
183
        );
184
        if ($cacheItem->isHit()) {
185
            if (($return = $cacheItem->get()) === self::NOT_FOUND) {
186
                throw new NotFoundException('UrlAlias', $url);
187
            }
188
189
            return $return;
190
        }
191
192
        $this->logger->logCall(__METHOD__, array('url' => $url));
193
        try {
194
            $urlAlias = $this->persistenceHandler->urlAliasHandler()->lookup($url);
195
        } catch (APINotFoundException $e) {
196
            $cacheItem->set(self::NOT_FOUND)
197
                ->expiresAfter(30)
198
                ->tag(['urlAlias-notFound']);
199
            $this->cache->save($cacheItem);
200
            throw $e;
201
        }
202
203
        $cacheItem->set($urlAlias);
204
        $cacheItem->tag($this->getCacheTags($urlAlias));
205
        $this->cache->save($cacheItem);
206
207
        return $urlAlias;
208
    }
209
210
    /**
211
     * {@inheritdoc}
212
     */
213
    public function loadUrlAlias($id)
214
    {
215
        $cacheItem = $this->cache->getItem('ez-urlAlias-' . $id);
216
        if ($cacheItem->isHit()) {
217
            return $cacheItem->get();
218
        }
219
220
        $this->logger->logCall(__METHOD__, array('alias' => $id));
221
        $urlAlias = $this->persistenceHandler->urlAliasHandler()->loadUrlAlias($id);
222
223
        $cacheItem->set($urlAlias);
224
        $cacheItem->tag($this->getCacheTags($urlAlias));
225
        $this->cache->save($cacheItem);
226
227
        return $urlAlias;
228
    }
229
230
    /**
231
     * {@inheritdoc}
232
     */
233 View Code Duplication
    public function locationMoved($locationId, $oldParentId, $newParentId)
234
    {
235
        $this->logger->logCall(
236
            __METHOD__,
237
            array(
238
                'location' => $locationId,
239
                'oldParent' => $oldParentId,
240
                'newParent' => $newParentId,
241
            )
242
        );
243
244
        $return = $this->persistenceHandler->urlAliasHandler()->locationMoved($locationId, $oldParentId, $newParentId);
245
246
        $this->cache->invalidateTags(['urlAlias-location-' . $locationId, 'urlAlias-location-path-' . $locationId]);
247
248
        return $return;
249
    }
250
251
    /**
252
     * {@inheritdoc}
253
     */
254 View Code Duplication
    public function locationCopied($locationId, $newLocationId, $newParentId)
255
    {
256
        $this->logger->logCall(
257
            __METHOD__,
258
            array(
259
                'oldLocation' => $locationId,
260
                'newLocation' => $newLocationId,
261
                'newParent' => $newParentId,
262
            )
263
        );
264
265
        $return = $this->persistenceHandler->urlAliasHandler()->locationCopied(
266
            $locationId,
267
            $newLocationId,
268
            $newParentId
269
        );
270
        $this->cache->invalidateTags(['urlAlias-location-' . $locationId, 'urlAlias-location-' . $newLocationId]);
271
272
        return $return;
273
    }
274
275
    /**
276
     * {@inheritdoc}
277
     */
278
    public function locationDeleted($locationId)
279
    {
280
        $this->logger->logCall(__METHOD__, array('location' => $locationId));
281
        $return = $this->persistenceHandler->urlAliasHandler()->locationDeleted($locationId);
282
283
        $this->cache->invalidateTags(['urlAlias-location-' . $locationId, 'urlAlias-location-path-' . $locationId]);
284
285
        return $return;
286
    }
287
288
    /**
289
     * {@inheritdoc}
290
     */
291
    public function locationSwapped($location1Id, $location1ParentId, $location2Id, $location2ParentId)
292
    {
293
        $this->logger->logCall(
294
            __METHOD__,
295
            [
296
                'location1Id' => $location1Id,
297
                'location1ParentId' => $location1ParentId,
298
                'location2Id' => $location2Id,
299
                'location2ParentId' => $location2ParentId,
300
            ]
301
        );
302
303
        $return = $this->persistenceHandler->urlAliasHandler()->locationSwapped(
304
            $location1Id,
305
            $location1ParentId,
306
            $location2Id,
307
            $location2ParentId
308
        );
309
310
        $this->cache->invalidateTags(
311
            [
312
                'urlAlias-location-' . $location1Id,
313
                'urlAlias-location-path-' . $location1Id,
314
                'urlAlias-location-' . $location2Id,
315
                'urlAlias-location-path-' . $location2Id,
316
            ]
317
        );
318
319
        return $return;
320
    }
321
322
    /**
323
     * {@inheritdoc}
324
     */
325
    public function translationRemoved(array $locationIds, $languageCode)
326
    {
327
        $this->logger->logCall(
328
            __METHOD__,
329
            ['locations' => implode(',', $locationIds), 'language' => $languageCode]
330
        );
331
332
        $this->persistenceHandler->urlAliasHandler()->translationRemoved($locationIds, $languageCode);
333
334
        $locationTags = [];
335
        foreach ($locationIds as $locationId) {
336
            $locationTags[] = 'urlAlias-location-' . $locationId;
337
            $locationTags[] = 'urlAlias-location-path-' . $locationId;
338
        }
339
340
        $this->cache->invalidateTags($locationTags);
341
    }
342
343
    /**
344
     * {@inheritdoc}
345
     */
346 View Code Duplication
    public function archiveUrlAliasesForDeletedTranslations($locationId, $parentLocationId, array $languageCodes)
347
    {
348
        $this->logger->logCall(
349
            __METHOD__,
350
            [
351
                'locationId' => $locationId,
352
                'parentLocationId' => $parentLocationId,
353
                'languageCodes' => implode(',', $languageCodes),
354
            ]
355
        );
356
357
        $this->persistenceHandler->urlAliasHandler()->archiveUrlAliasesForDeletedTranslations(
358
            $locationId,
359
            $parentLocationId,
360
            $languageCodes
361
        );
362
363
        $this->cache->invalidateTags(['urlAlias-location-' . $locationId, 'urlAlias-location-path-' . $locationId]);
364
    }
365
366
    /**
367
     * Return relevant UrlAlias and optionally UrlAlias location tags so cache can be purged reliably.
368
     *
369
     * For use when generating cache, not on invalidation.
370
     *
371
     * @param \eZ\Publish\SPI\Persistence\Content\UrlAlias $urlAlias
372
     * @param array $tags Optional, can be used to specify other tags.
373
     *
374
     * @return array
375
     */
376 View Code Duplication
    private function getCacheTags(UrlAlias $urlAlias, array $tags = [])
377
    {
378
        $tags[] = 'urlAlias-' . $urlAlias->id;
379
380
        if ($urlAlias->type === UrlAlias::LOCATION) {
381
            $cacheTags[] = 'urlAlias-location-' . $urlAlias->destination;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$cacheTags was never initialized. Although not strictly required by PHP, it is generally a good practice to add $cacheTags = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
382
            $location = $this->persistenceHandler->locationHandler()->load($urlAlias->destination);
383
            foreach (explode('/', trim($location->pathString, '/')) as $pathId) {
384
                $tags[] = 'urlAlias-location-path-' . $pathId;
385
            }
386
        }
387
388
        return array_unique($tags);
389
    }
390
391
    /**
392
     * Delete corrupted URL aliases (global, custom and system).
393
     *
394
     * @return int Number of deleted URL aliases
395
     */
396
    public function deleteCorruptedUrlAliases()
397
    {
398
        $this->logger->logCall(__METHOD__);
399
400
        $deletedCount = $this->persistenceHandler->urlAliasHandler()->deleteCorruptedUrlAliases();
401
402
        $this->cache->clear('urlAlias');
403
404
        return $deletedCount;
405
    }
406
407
    /**
408
     * Attempt repairing auto-generated URL aliases for the given Location (including history).
409
     *
410
     * Note: it is assumed that at this point original, working, URL Alias for Location is published.
411
     *
412
     * @param int $locationId
413
     *
414
     * @throws \eZ\Publish\Core\Base\Exceptions\BadStateException
415
     * @throws \Psr\Cache\InvalidArgumentException
416
     */
417
    public function repairBrokenUrlAliasesForLocation(int $locationId)
418
    {
419
        $this->logger->logCall(__METHOD__, ['locationId' => $locationId]);
420
421
        $this->persistenceHandler->urlAliasHandler()->repairBrokenUrlAliasesForLocation($locationId);
422
423
        $this->cache->invalidateTags(
424
            [
425
                'urlAlias-location-' . $locationId,
426
                'urlAlias-location-path-' . $locationId,
427
            ]
428
        );
429
    }
430
}
431