Completed
Push — master ( ca539c...a89354 )
by Tim
10s queued 10s
created

UrlRewriteUpdateObserver::initializeUrlRewrite()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 25
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 25
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 9
nc 3
nop 1
1
<?php
2
3
/**
4
 * TechDivision\Import\Category\Observers\UrlRewriteUpdateObserver
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Tim Wagner <[email protected]>
15
 * @copyright 2016 TechDivision GmbH <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/techdivision/import-category
18
 * @link      http://www.techdivision.com
19
 */
20
21
namespace TechDivision\Import\Category\Observers;
22
23
use TechDivision\Import\Category\Utils\MemberNames;
24
25
/**
26
 * Observer that creates/updates the category's URL rewrites.
27
 *
28
 * @author    Tim Wagner <[email protected]>
29
 * @copyright 2016 TechDivision GmbH <[email protected]>
30
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
31
 * @link      https://github.com/techdivision/import-category
32
 * @link      http://www.techdivision.com
33
 */
34
class UrlRewriteUpdateObserver extends UrlRewriteObserver
35
{
36
37
    /**
38
     * Array with the existing URL rewrites of the actual category.
39
     *
40
     * @var array
41
     */
42
    protected $existingUrlRewrites = array();
43
44
    /**
45
     * Return's the URL rewrite for the passed store ID and request path.
46
     *
47
     * @param integer $storeId     The store ID to return the URL rewrite for
48
     * @param string  $requestPath The request path to return the URL rewrite for
49
     *
50
     * @return array|null The URL rewrite
51
     */
52
    protected function getExistingUrlRewrite($storeId, $requestPath)
53
    {
54
        if (isset($this->existingUrlRewrites[$storeId][$requestPath])) {
55
            return $this->existingUrlRewrites[$storeId][$requestPath];
56
        }
57
    }
58
59
    /**
60
     * Remove's the passed URL rewrite from the existing one's.
61
     *
62
     * @param array $urlRewrite The URL rewrite to remove
63
     *
64
     * @return void
65
     */
66
    protected function removeExistingUrlRewrite(array $urlRewrite)
67
    {
68
69
        // load store ID and request path
70
        $storeId = (integer) $urlRewrite[MemberNames::STORE_ID];
71
        $requestPath = $urlRewrite[MemberNames::REQUEST_PATH];
72
73
        // query whether or not the URL rewrite exists and remove it, if available
74
        if (isset($this->existingUrlRewrites[$storeId][$requestPath])) {
75
            unset($this->existingUrlRewrites[$storeId][$requestPath]);
76
        }
77
    }
78
79
    /**
80
     * Process the observer's business logic.
81
     *
82
     * @return void
83
     */
84
    protected function process()
85
    {
86
87
        // prepare the existing URL rewrites for the categoy
88
        $this->prepareUrlRewrites();
89
90
        // process the new URL rewrites first
91
        parent::process();
92
93
        // create redirect URL rewrites for the existing URL rewrites
94
        foreach ($this->existingUrlRewrites as $existingUrlRewrites) {
95
            foreach ($existingUrlRewrites as $existingUrlRewrite) {
96
                // if the URL rewrite has been created manually
97
                if ((integer) $existingUrlRewrite[MemberNames::IS_AUTOGENERATED] === 0) {
98
                    // do NOT create another redirect
99
                    continue;
100
                }
101
102
                // if the URL rewrite already IS a redirect
103
                if ((integer) $existingUrlRewrite[MemberNames::REDIRECT_TYPE] !== 0) {
104
                    // do NOT create another redirect
105
                    continue;
106
                }
107
108
                // if yes, load the category of the original one
109
                $category = $this->getCategory($existingUrlRewrite[MemberNames::ENTITY_ID]);
0 ignored issues
show
Bug introduced by
The method getCategory() does not seem to exist on object<TechDivision\Impo...lRewriteUpdateObserver>.

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...
110
111
                // load target path/metadata for the actual category
112
                $targetPath = $this->prepareRequestPath($category);
0 ignored issues
show
Unused Code introduced by
The call to UrlRewriteUpdateObserver::prepareRequestPath() has too many arguments starting with $category.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
113
114
                // override data with the 301 configuration
115
                $attr = array(
116
                    MemberNames::IS_AUTOGENERATED => 0,
117
                    MemberNames::REDIRECT_TYPE    => 301,
118
                    MemberNames::TARGET_PATH      => $targetPath,
119
                );
120
121
                // merge and return the prepared URL rewrite
122
                $existingUrlRewrite = $this->mergeEntity($existingUrlRewrite, $attr);
123
124
                // create the URL rewrite
125
                $this->persistUrlRewrite($existingUrlRewrite);
126
            }
127
        }
128
    }
129
130
    /**
131
     * Prepare's the URL rewrites that has to be created/updated.
132
     *
133
     * @return void
134
     * @see \TechDivision\Import\Product\Observers\UrlRewriteObserver::prepareUrlRewrites()
135
     */
136
    protected function prepareUrlRewrites()
137
    {
138
139
        // (re-)initialize the array for the existing URL rewrites
140
        $this->existingUrlRewrites = array();
141
142
        // load primary key and entity type
143
        $pk = $this->getPrimaryKey();
144
        $entityType = UrlRewriteObserver::ENTITY_TYPE;
145
146
        // load the existing URL rewrites of the actual entity
147
        $existingUrlRewrites = $this->getUrlRewritesByEntityTypeAndEntityId($entityType, $pk);
148
149
        // prepare the existing URL rewrites to improve searching them by store ID/request path
150
        foreach ($existingUrlRewrites as $existingUrlRewrite) {
151
            // load store ID and request path from the existing URL rewrite
152
            $storeId = (integer) $existingUrlRewrite[MemberNames::STORE_ID];
153
            $requestPath = $existingUrlRewrite[MemberNames::REQUEST_PATH];
154
155
            // append the URL rewrite with its store ID/request path
156
            $this->existingUrlRewrites[$storeId][$requestPath] = $existingUrlRewrite;
157
        }
158
    }
159
160
    /**
161
     * Initialize the URL rewrite with the passed attributes and returns an instance.
162
     *
163
     * @param array $attr The URL rewrite attributes
164
     *
165
     * @return array The initialized URL rewrite
166
     */
167
    protected function initializeUrlRewrite(array $attr)
168
    {
169
170
        // load store ID and request path
171
        $storeId = $attr[MemberNames::STORE_ID];
172
        $requestPath = $attr[MemberNames::REQUEST_PATH];
173
174
        // try to load the URL rewrite for the store ID and request path
175
        if ($urlRewrite = $this->getExistingUrlRewrite($storeId, $requestPath)) {
176
            // if a URL rewrite has been found, do NOT create a redirect
177
            $this->removeExistingUrlRewrite($urlRewrite);
178
179
            // if the found URL rewrite has been created manually
180
            if ((integer) $urlRewrite[MemberNames::IS_AUTOGENERATED] === 0) {
181
                // do NOT update it nor create a another redirect
182
                return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type of the parent method TechDivision\Import\Cate...r::initializeUrlRewrite of type array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
183
            }
184
185
            // if the found URL rewrite has been autogenerated, then update it
186
            return $this->mergeEntity($urlRewrite, $attr);
187
        }
188
189
        // simple return the attributes
190
        return $attr;
191
    }
192
193
    /**
194
     * Return's the URL rewrites for the passed URL entity type and ID.
195
     *
196
     * @param string  $entityType The entity type to load the URL rewrites for
197
     * @param integer $entityId   The entity ID to laod the rewrites for
198
     *
199
     * @return array The URL rewrites
200
     */
201
    protected function getUrlRewritesByEntityTypeAndEntityId($entityType, $entityId)
202
    {
203
        return $this->getSubject()->getUrlRewritesByEntityTypeAndEntityId($entityType, $entityId);
204
    }
205
}
206