Completed
Push — sf_cache ( 94d0e5...42a66b )
by André
12:53
created

UrlAliasHandler::locationCopied()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 13

Duplication

Lines 20
Ratio 100 %

Importance

Changes 0
Metric Value
cc 1
eloc 13
nc 1
nop 3
dl 20
loc 20
rs 9.4285
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
        $this->clearLocation($locationId);
0 ignored issues
show
Bug introduced by
The method clearLocation() does not seem to exist on object<eZ\Publish\Core\P...\Cache\UrlAliasHandler>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
48
49
        $this->persistenceHandler->urlAliasHandler()->publishUrlAliasForLocation(
50
            $locationId,
51
            $parentLocationId,
52
            $name,
53
            $languageCode,
54
            $alwaysAvailable,
55
            $updatePathIdentificationString
56
        );
57
    }
58
59
    /**
60
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::createCustomUrlAlias
61
     */
62
    public function createCustomUrlAlias($locationId, $path, $forwarding = false, $languageCode = null, $alwaysAvailable = false)
63
    {
64
        $this->logger->logCall(
65
            __METHOD__,
66
            array(
67
                'location' => $locationId,
68
                '$path' => $path,
69
                '$forwarding' => $forwarding,
70
                'language' => $languageCode,
71
                'alwaysAvailable' => $alwaysAvailable,
72
            )
73
        );
74
75
        $urlAlias = $this->persistenceHandler->urlAliasHandler()->createCustomUrlAlias(
76
            $locationId,
77
            $path,
78
            $forwarding,
79
            $languageCode,
80
            $alwaysAvailable
81
        );
82
83
        $this->cache->getItem('urlAlias', $urlAlias->id)->set($urlAlias)->save();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Psr\Cache\CacheItemInterface as the method save() does only exist in the following implementations of said interface: Stash\Item, Tedivm\StashBundle\Service\CacheItem.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
84
        $cache = $this->cache->getItem('urlAlias', 'location', $urlAlias->destination, 'custom');
85
        $urlAliasIds = $cache->get();
86
        if ($cache->isMiss()) {
87
            $urlAliasIds = array();
88
        }
89
90
        $urlAliasIds[] = $urlAlias->id;
91
        $cache->set($urlAliasIds)->save();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Psr\Cache\CacheItemInterface as the method save() does only exist in the following implementations of said interface: Stash\Item, Tedivm\StashBundle\Service\CacheItem.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
92
93
        return $urlAlias;
94
    }
95
96
    /**
97
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::createGlobalUrlAlias
98
     */
99
    public function createGlobalUrlAlias($resource, $path, $forwarding = false, $languageCode = null, $alwaysAvailable = false)
100
    {
101
        $this->logger->logCall(
102
            __METHOD__,
103
            array(
104
                'resource' => $resource,
105
                'path' => $path,
106
                'forwarding' => $forwarding,
107
                'language' => $languageCode,
108
                'alwaysAvailable' => $alwaysAvailable,
109
            )
110
        );
111
112
        $urlAlias = $this->persistenceHandler->urlAliasHandler()->createGlobalUrlAlias(
113
            $resource,
114
            $path,
115
            $forwarding,
116
            $languageCode,
117
            $alwaysAvailable
118
        );
119
120
        $this->cache->getItem('urlAlias', $urlAlias->id)->set($urlAlias)->save();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Psr\Cache\CacheItemInterface as the method save() does only exist in the following implementations of said interface: Stash\Item, Tedivm\StashBundle\Service\CacheItem.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
121
122
        return $urlAlias;
123
    }
124
125
    /**
126
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::listGlobalURLAliases
127
     */
128
    public function listGlobalURLAliases($languageCode = null, $offset = 0, $limit = -1)
129
    {
130
        $this->logger->logCall(__METHOD__, array('language' => $languageCode, 'offset' => $offset, 'limit' => $limit));
131
132
        return $this->persistenceHandler->urlAliasHandler()->listGlobalURLAliases($languageCode, $offset, $limit);
133
    }
134
135
    /**
136
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::listURLAliasesForLocation
137
     */
138
    public function listURLAliasesForLocation($locationId, $custom = false)
139
    {
140
        // Look for location to list of url alias id's cache
141
        if ($custom) {
142
            $cache = $this->cache->getItem('urlAlias', 'location', $locationId, 'custom');
143
        } else {
144
            $cache = $this->cache->getItem('urlAlias', 'location', $locationId);
145
        }
146
        $urlAliasIds = $cache->get();
147
        if ($cache->isMiss()) {
148
            $this->logger->logCall(__METHOD__, array('location' => $locationId, 'custom' => $custom));
149
            $urlAliases = $this->persistenceHandler->urlAliasHandler()->listURLAliasesForLocation($locationId, $custom);
150
151
            $urlAliasIds = array();
152
            foreach ($urlAliases as $urlAlias) {
153
                $urlAliasIds[] = $urlAlias->id;
154
            }
155
156
            $cache->set($urlAliasIds)->save();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Psr\Cache\CacheItemInterface as the method save() does only exist in the following implementations of said interface: Stash\Item, Tedivm\StashBundle\Service\CacheItem.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
157
        } else {
158
            // Reuse loadUrlAlias for the url alias object cache
159
            $urlAliases = array();
160
            foreach ($urlAliasIds as $urlAliasId) {
161
                $urlAliases[] = $this->loadUrlAlias($urlAliasId);
162
            }
163
        }
164
165
        return $urlAliases;
166
    }
167
168
    /**
169
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::removeURLAliases
170
     */
171
    public function removeURLAliases(array $urlAliases)
172
    {
173
        $this->logger->logCall(__METHOD__, array('aliases' => $urlAliases));
174
        $return = $this->persistenceHandler->urlAliasHandler()->removeURLAliases($urlAliases);
175
176
        $this->cache->clear('urlAlias', 'url');//TIMBER! (no easy way to do reverse lookup of urls)
177
        foreach ($urlAliases as $urlAlias) {
178
            $this->cache->clear('urlAlias', $urlAlias->id);
179
            if ($urlAlias->type === UrlAlias::LOCATION) {
180
                $this->cache->clear('urlAlias', 'location', $urlAlias->destination);
181
            }
182
            if ($urlAlias->isCustom) {
183
                $this->cache->clear('urlAlias', 'location', $urlAlias->destination, 'custom');
184
            }
185
        }
186
187
        return $return;
188
    }
189
190
    /**
191
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::lookup
192
     */
193
    public function lookup($url)
194
    {
195
        $cacheItem = $this->cache->getItem('ez-urlAlias-url-', $url);
196
        if ($cacheItem->isHit()) {
197
            if (($return = $cacheItem->get()) === self::NOT_FOUND) {
198
                throw new NotFoundException('UrlAlias', $url);
199
            }
200
201
            return $return;
202
        }
203
204
        $this->logger->logCall(__METHOD__, array('url' => $url));
205
        try {
206
            $urlAlias = $this->persistenceHandler->urlAliasHandler()->lookup($url);
207
        } catch (APINotFoundException $e) {
208
            $cacheItem->set(self::NOT_FOUND)
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Psr\Cache\CacheItemInterface as the method tag() does only exist in the following implementations of said interface: Symfony\Component\Cache\CacheItem.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
209
                ->expiresAfter(30)
210
                ->tag(['urlAlias-notFound']);
211
            $this->cache->save($cacheItem);
212
            throw $e;
213
        }
214
215
        $cacheItem->set($urlAlias);
216
        $cachTags = ['urlAlias-'.$urlAlias->id];
217
        if ($urlAlias->type === UrlAlias::LOCATION) {
218
            $cachTags[] = 'urlAlias-location-'.$urlAlias->destination;
219
        }
220
        $cacheItem->tag($cachTags);
221
        $this->cache->save($cacheItem);
222
223
224
        return $urlAlias;
225
    }
226
227
    /**
228
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::loadUrlAlias
229
     */
230 View Code Duplication
    public function loadUrlAlias($id)
231
    {
232
        $cacheItem = $this->cache->getItem('ez-urlAlias-', $id);
233
        if ($cacheItem->isHit()) {
234
            return $cacheItem->get();
235
        }
236
237
        $this->logger->logCall(__METHOD__, array('alias' => $id));
238
        $urlAlias = $this->persistenceHandler->urlAliasHandler()->loadUrlAlias($id);
239
240
        $cacheItem->set($urlAlias);
241
        if ($urlAlias->type === UrlAlias::LOCATION) {
242
            $cacheItem->tag(['urlAlias-location-'.$urlAlias->destination]);
243
        }
244
        $this->cache->save($cacheItem);
245
246
247
        return $urlAlias;
248
    }
249
250
    /**
251
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::locationMoved
252
     */
253
    public function locationMoved($locationId, $oldParentId, $newParentId)
254
    {
255
        $this->logger->logCall(
256
            __METHOD__,
257
            array(
258
                'location' => $locationId,
259
                'oldParent' => $oldParentId,
260
                'newParent' => $newParentId,
261
            )
262
        );
263
264
        $return = $this->persistenceHandler->urlAliasHandler()->locationMoved($locationId, $oldParentId, $newParentId);
265
266
        $this->cache->invalidateTags(['urlAlias-location-'.$locationId]);
267
268
        return $return;
269
    }
270
271
    /**
272
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::locationCopied
273
     */
274 View Code Duplication
    public function locationCopied($locationId, $newLocationId, $newParentId)
275
    {
276
        $this->logger->logCall(
277
            __METHOD__,
278
            array(
279
                'oldLocation' => $locationId,
280
                'newLocation' => $newLocationId,
281
                'newParent' => $newParentId,
282
            )
283
        );
284
285
        $return = $this->persistenceHandler->urlAliasHandler()->locationCopied(
286
            $locationId,
287
            $newLocationId,
288
            $newParentId
289
        );
290
        $this->cache->invalidateTags(['urlAlias-location-'.$locationId, 'urlAlias-location-'.$newLocationId]);
291
292
        return $return;
293
    }
294
295
    /**
296
     * @see eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::locationDeleted
297
     */
298
    public function locationDeleted($locationId)
299
    {
300
        $this->logger->logCall(__METHOD__, array('location' => $locationId));
301
        $return = $this->persistenceHandler->urlAliasHandler()->locationDeleted($locationId);
302
303
        $this->cache->invalidateTags(['urlAlias-location-'.$locationId]);
304
305
        return $return;
306
    }
307
308
    /**
309
     * @see \eZ\Publish\SPI\Persistence\Content\UrlAlias\Handler::swap
310
     */
311
    public function locationSwapped($location1ParentId, $location1Id, $location2ParentId, $location2Id)
312
    {
313
        $this->logger->logCall(
314
            __METHOD__,
315
            [
316
                'location1ParentId' => $location1ParentId,
317
                'location1Id' => $location1Id,
318
                'location2ParentId' => $location2ParentId,
319
                'location2Id' => $location2Id,
320
            ]
321
        );
322
323
        $return = $this->persistenceHandler->urlAliasHandler()->locationSwapped(
324
            $location1ParentId,
325
            $location1Id,
326
            $location2ParentId,
327
            $location2Id
328
        );
329
330
        $this->cache->invalidateTags(['urlAlias-location-'.$location1Id, 'urlAlias-location-'.$location2Id]);
331
332
        return $return;
333
    }
334
}
335