Completed
Push — master ( 404f67...9bc8e3 )
by Tim
10s
created

UrlRewriteUpdateObserver::process()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 55
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 6.031

Importance

Changes 0
Metric Value
dl 0
loc 55
c 0
b 0
f 0
ccs 19
cts 21
cp 0.9048
rs 8.7752
cc 6
eloc 21
nc 6
nop 0
crap 6.031

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * TechDivision\Import\Product\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-product
18
 * @link      http://www.techdivision.com
19
 */
20
21
namespace TechDivision\Import\Product\Observers;
22
23
use TechDivision\Import\Product\Utils\MemberNames;
24
25
/**
26
 * Observer that creates/updates the product'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-product
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 product.
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 1
    protected function getExistingUrlRewrite($storeId, $requestPath)
53
    {
54 1
        if (isset($this->existingUrlRewrites[$storeId][$requestPath])) {
55
            return $this->existingUrlRewrites[$storeId][$requestPath];
56
        }
57 1
    }
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
     * @see \TechDivision\Import\Product\Observers\UrlRewriteObserver::process()
84
     */
85 1
    protected function process()
86
    {
87
88
        // process the new URL rewrites first
89 1
        parent::process();
90
91
        // load the root category
92 1
        $rootCategory = $this->getRootCategory();
93
94
        // create redirect URL rewrites for the existing URL rewrites
95 1
        foreach ($this->existingUrlRewrites as $existingUrlRewrites) {
96 1
            foreach ($existingUrlRewrites as $existingUrlRewrite) {
97
                // if the URL rewrite has been created manually
98 1
                if ((integer) $existingUrlRewrite[MemberNames::IS_AUTOGENERATED] === 0) {
99
                    // do NOT create another redirect
100
                    continue;
101
                }
102
103
                // if the URL rewrite already IS a redirect
104 1
                if ((integer) $existingUrlRewrite[MemberNames::REDIRECT_TYPE] !== 0) {
105
                    // do NOT create another redirect
106
                    continue;
107
                }
108
109
                // load the metadata from the existing URL rewrite
110 1
                $metadata = $this->getMetadata($existingUrlRewrite);
111
112
                // initialize the category with the root category
113 1
                $category = $rootCategory;
114
115
                // query whether or not, the existing URL rewrite has been replaced
116 1
                if (isset($this->urlRewrites[$metadata['category_id']])) {
117
                    // if yes, load the category of the original one
118 1
                    $category = $this->getCategory($metadata['category_id']);
119
                }
120
121
                // load target path/metadata for the actual category
122 1
                $targetPath = $this->prepareRequestPath($category);
123 1
                $metadata = serialize($this->prepareMetadata($category));
124
125
                // override data witht rhe root category information
126
                $attr = array(
127 1
                    MemberNames::REDIRECT_TYPE    => 301,
128 1
                    MemberNames::METADATA         => $metadata,
129 1
                    MemberNames::TARGET_PATH      => $targetPath,
130
                );
131
132
                // merge and return the prepared URL rewrite
133 1
                $existingUrlRewrite = $this->mergeEntity($existingUrlRewrite, $attr);
134
135
                // create the URL rewrite
136 1
                $this->persistUrlRewrite($existingUrlRewrite);
137
            }
138
        }
139 1
    }
140
141
    /**
142
     * Prepare's the URL rewrites that has to be created/updated.
143
     *
144
     * @return void
145
     * @see \TechDivision\Import\Product\Observers\UrlRewriteObserver::prepareUrlRewrites()
146
     */
147 1
    protected function prepareUrlRewrites()
148
    {
149
150
        // prepare the new URL rewrites first
151 1
        parent::prepareUrlRewrites();
152
153
        // (re-)initialize the array for the existing URL rewrites
154 1
        $this->existingUrlRewrites = array();
155
156
        // load primary key and entity type
157 1
        $pk = $this->getPrimaryKey();
158 1
        $entityType = UrlRewriteObserver::ENTITY_TYPE;
159
160
        // load the existing URL rewrites of the actual entity
161 1
        $existingUrlRewrites = $this->getUrlRewritesByEntityTypeAndEntityId($entityType, $pk);
162
163
        // prepare the existing URL rewrites to improve searching them by store ID/request path
164 1
        foreach ($existingUrlRewrites as $existingUrlRewrite) {
165
            // load store ID and request path from the existing URL rewrite
166 1
            $storeId = (integer) $existingUrlRewrite[MemberNames::STORE_ID];
167 1
            $requestPath = $existingUrlRewrite[MemberNames::REQUEST_PATH];
168
169
            // append the URL rewrite with its store ID/request path
170 1
            $this->existingUrlRewrites[$storeId][$requestPath] = $existingUrlRewrite;
171
        }
172 1
    }
173
174
    /**
175
     * Initialize the category product with the passed attributes and returns an instance.
176
     *
177
     * @param array $attr The category product attributes
178
     *
179
     * @return array The initialized category product
180
     */
181 1
    protected function initializeUrlRewrite(array $attr)
182
    {
183
184
        // load store ID and request path
185 1
        $storeId = $attr[MemberNames::STORE_ID];
186 1
        $requestPath = $attr[MemberNames::REQUEST_PATH];
187
188
        // try to load the URL rewrite for the store ID and request path
189 1
        if ($urlRewrite = $this->getExistingUrlRewrite($storeId, $requestPath)) {
190
            // if a URL rewrite has been found, do NOT create a redirect
191
            $this->removeExistingUrlRewrite($urlRewrite);
192
193
            // if the found URL rewrite has been created manually
194
            if ((integer) $urlRewrite[MemberNames::IS_AUTOGENERATED] === 0) {
195
                // do NOT update it nor create a another redirect
196
                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\Prod...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...
197
            }
198
199
            // if the found URL rewrite has been autogenerated, then update it
200
            return $this->mergeEntity($urlRewrite, $attr);
201
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
202
        }
203
204
        // simple return the attributes
205 1
        return $attr;
206
    }
207
208
    /**
209
     * Return's the unserialized metadata of the passed URL rewrite. If the
210
     * metadata doesn't contain a category ID, the category ID of the root
211
     * category will be added.
212
     *
213
     * @param array $urlRewrite The URL rewrite to return the metadata for
214
     *
215
     * @return array The metadata of the passed URL rewrite
216
     */
217 1
    protected function getMetadata($urlRewrite)
218
    {
219
220
        // initialize the array with the metaddata
221 1
        $metadata = array();
222
223
        // try to unserialize the metadata from the passed URL rewrite
224 1
        if (isset($urlRewrite[MemberNames::METADATA])) {
225 1
            $metadata = unserialize($urlRewrite[MemberNames::METADATA]);
226
        }
227
228
        // query whether or not a category ID has been found
229 1
        if (isset($metadata['category_id'])) {
230
            // if yes, return the metadata
231 1
            return $metadata;
232
        }
233
234
        // if not, append the ID of the root category
235 1
        $rootCategory = $this->getRootCategory();
236 1
        $metadata['category_id'] = $rootCategory[MemberNames::ENTITY_ID];
237
238
        // and return the metadata
239 1
        return $metadata;
240
    }
241
242
    /**
243
     * Return's the URL rewrites for the passed URL entity type and ID.
244
     *
245
     * @param string  $entityType The entity type to load the URL rewrites for
246
     * @param integer $entityId   The entity ID to laod the rewrites for
247
     *
248
     * @return array The URL rewrites
249
     */
250 1
    protected function getUrlRewritesByEntityTypeAndEntityId($entityType, $entityId)
251
    {
252 1
        return $this->getSubject()->getUrlRewritesByEntityTypeAndEntityId($entityType, $entityId);
253
    }
254
}
255