Completed
Push — 13.x ( 6ef6a1...0de302 )
by Tim
04:41
created

MediaGalleryObserver::isParentStoreViewCode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
1
<?php
2
3
/**
4
 * TechDivision\Import\Product\Media\Observers\MediaGalleryObserver
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-media
18
 * @link      http://www.techdivision.com
19
 */
20
21
namespace TechDivision\Import\Product\Media\Observers;
22
23
use TechDivision\Import\Product\Media\Utils\ColumnKeys;
24
use TechDivision\Import\Product\Media\Utils\MemberNames;
25
use TechDivision\Import\Product\Observers\AbstractProductImportObserver;
26
use TechDivision\Import\Product\Media\Services\ProductMediaProcessorInterface;
27
28
/**
29
 * Observer that creates/updates the product's media gallery information.
30
 *
31
 * @author    Tim Wagner <[email protected]>
32
 * @copyright 2016 TechDivision GmbH <[email protected]>
33
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
34
 * @link      https://github.com/techdivision/import-product-media
35
 * @link      http://www.techdivision.com
36
 */
37
class MediaGalleryObserver extends AbstractProductImportObserver
38
{
39
40
    /**
41
     * The media gallery attribute code.
42
     *
43
     * @var string
44
     */
45
    const ATTRIBUTE_CODE = 'media_gallery';
46
47
    /**
48
     * The ID of the parent product the media is related to.
49
     *
50
     * @var integer
51
     */
52
    protected $parentId;
53
54
    /**
55
     * The ID of the persisted media gallery entity.
56
     *
57
     * @var integer
58
     */
59
    protected $valueId;
60
61
    /**
62
     * The product media processor instance.
63
     *
64
     * @var \TechDivision\Import\Product\Media\Services\ProductMediaProcessorInterface
65
     */
66
    protected $productMediaProcessor;
67
68
    /**
69
     * Initialize the observer with the passed product media processor instance.
70
     *
71
     * @param \TechDivision\Import\Product\Media\Services\ProductMediaProcessorInterface $productMediaProcessor The product media processor instance
72
     */
73
    public function __construct(ProductMediaProcessorInterface $productMediaProcessor)
74
    {
75
        $this->productMediaProcessor = $productMediaProcessor;
76
    }
77
78
    /**
79
     * Return's the product media processor instance.
80
     *
81
     * @return \TechDivision\Import\Product\Media\Services\ProductMediaProcessorInterface The product media processor instance
82
     */
83
    protected function getProductMediaProcessor()
84
    {
85
        return $this->productMediaProcessor;
86
    }
87
88
    /**
89
     * Process the observer's business logic.
90
     *
91
     * @return array The processed row
92
     */
93
    protected function process()
94
    {
95
96
        // try to load the product SKU and map it the entity ID and
97
        $this->parentId = $this->getValue(ColumnKeys::IMAGE_PARENT_SKU, null, array($this, 'mapParentSku'));
98
99
        // reset the position counter, if either a new PK or store view code has been found
100
        if (!$this->isParentStoreViewCode($this->getValue(ColumnKeys::STORE_VIEW_CODE, $this->getDefaultStoreViewCode())) ||
101
            !$this->isParentId($this->parentId)
102
        ) {
103
            $this->resetPositionCounter();
104
        }
105
106
        // prepare the actual store view code
107
        $this->prepareStoreViewCode($this->getRow());
0 ignored issues
show
Unused Code introduced by
The call to MediaGalleryObserver::prepareStoreViewCode() has too many arguments starting with $this->getRow().

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...
Deprecated Code introduced by
The method TechDivision\Import\Obse...:prepareStoreViewCode() has been deprecated with message: Will be removed with version 1.0.0, use subject method instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
108
109
        // initialize and persist the product media gallery
110
        $productMediaGallery = $this->initializeProductMediaGallery($this->prepareProductMediaGalleryAttributes());
111
        $this->valueId = $this->persistProductMediaGallery($productMediaGallery);
0 ignored issues
show
Documentation Bug introduced by
The property $valueId was declared of type integer, but $this->persistProductMed...y($productMediaGallery) is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
112
113
        // persist the product media gallery to entity data
114
        if ($productMediaGalleryValueToEntity = $this->initializeProductMediaGalleryValueToEntity($this->prepareProductMediaGalleryValueToEntityAttributes())) {
115
            $this->persistProductMediaGalleryValueToEntity($productMediaGalleryValueToEntity);
116
        }
117
118
        // temporarily persist parent/value ID
119
        $this->setParentId($this->parentId);
120
        $this->setParentValueId($this->valueId);
121
    }
122
123
    /**
124
     * Prepare the product media gallery that has to be persisted.
125
     *
126
     * @return array The prepared product media gallery attributes
127
     */
128
    protected function prepareProductMediaGalleryAttributes()
129
    {
130
131
        // load the attribute ID of the media gallery EAV attribute
132
        $mediaGalleryAttribute = $this->getEavAttributeByAttributeCode(MediaGalleryObserver::ATTRIBUTE_CODE);
133
        $attributeId = $mediaGalleryAttribute[MemberNames::ATTRIBUTE_ID];
134
135
        // initialize the gallery data
136
        $disabled = 0;
137
        $mediaType = 'image';
138
        $image = $this->getValue(ColumnKeys::IMAGE_PATH_NEW);
139
140
        // initialize and return the entity
141
        return $this->initializeEntity(
142
            array(
143
                MemberNames::ATTRIBUTE_ID => $attributeId,
144
                MemberNames::VALUE        => $image,
145
                MemberNames::MEDIA_TYPE   => $mediaType,
146
                MemberNames::DISABLED     => $disabled
147
            )
148
        );
149
    }
150
151
    /**
152
     * Prepare the product media gallery value to entity that has to be persisted.
153
     *
154
     * @return array The prepared product media gallery value to entity attributes
155
     */
156
    protected function prepareProductMediaGalleryValueToEntityAttributes()
157
    {
158
159
        // initialize and return the entity
160
        return $this->initializeEntity(
161
            array(
162
                MemberNames::VALUE_ID  => $this->valueId,
163
                MemberNames::ENTITY_ID => $this->parentId
164
            )
165
        );
166
    }
167
168
    /**
169
     * Initialize the product media gallery with the passed attributes and returns an instance.
170
     *
171
     * @param array $attr The product media gallery attributes
172
     *
173
     * @return array The initialized product media gallery
174
     */
175
    protected function initializeProductMediaGallery(array $attr)
176
    {
177
        return $attr;
178
    }
179
180
    /**
181
     * Initialize the product media gallery value to entity with the passed attributes and returns an instance.
182
     *
183
     * @param array $attr The product media gallery value to entity attributes
184
     *
185
     * @return array|null The initialized product media gallery value to entity, or NULL if the product media gallery value to entity already exists
186
     */
187
    protected function initializeProductMediaGalleryValueToEntity(array $attr)
188
    {
189
        return $attr;
190
    }
191
192
    /**
193
     * Map's the passed SKU of the parent product to it's PK.
194
     *
195
     * @param string $parentSku The SKU of the parent product
196
     *
197
     * @return integer The primary key used to create relations
198
     */
199
    protected function mapParentSku($parentSku)
200
    {
201
        return $this->mapSkuToEntityId($parentSku);
202
    }
203
204
    /**
205
     * Set's the value ID of the created media gallery entry.
206
     *
207
     * @param integer $parentValueId The ID of the created media gallery entry
208
     *
209
     * @return void
210
     */
211
    protected function setParentValueId($parentValueId)
212
    {
213
        $this->getSubject()->setParentValueId($parentValueId);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface TechDivision\Import\Subjects\SubjectInterface as the method setParentValueId() does only exist in the following implementations of said interface: TechDivision\Import\Prod...a\Subjects\MediaSubject.

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...
214
    }
215
216
    /**
217
     * Return the entity ID for the passed SKU.
218
     *
219
     * @param string $sku The SKU to return the entity ID for
220
     *
221
     * @return integer The mapped entity ID
222
     * @throws \Exception Is thrown if the SKU is not mapped yet
223
     */
224
    protected function mapSkuToEntityId($sku)
225
    {
226
        return $this->getSubject()->mapSkuToEntityId($sku);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface TechDivision\Import\Subjects\SubjectInterface as the method mapSkuToEntityId() does only exist in the following implementations of said interface: TechDivision\Import\Prod...a\Subjects\MediaSubject.

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...
227
    }
228
229
    /**
230
     * Set's the ID of the parent product to relate the variant with.
231
     *
232
     * @param integer $parentId The ID of the parent product
233
     *
234
     * @return void
235
     */
236
    protected function setParentId($parentId)
237
    {
238
        $this->getSubject()->setParentId($parentId);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface TechDivision\Import\Subjects\SubjectInterface as the method setParentId() does only exist in the following implementations of said interface: TechDivision\Import\Prod...a\Subjects\MediaSubject.

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...
239
    }
240
241
    /**
242
     * Return's the ID of the parent product to relate the variant with.
243
     *
244
     * @return integer The ID of the parent product
245
     */
246
    protected function getParentId()
247
    {
248
        return $this->getSubject()->getParentId();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface TechDivision\Import\Subjects\SubjectInterface as the method getParentId() does only exist in the following implementations of said interface: TechDivision\Import\Prod...a\Subjects\MediaSubject.

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...
249
    }
250
251
    /**
252
     * Query whether or not this is the parent ID.
253
     *
254
     * @param integer $parentId The PK of the parent image
255
     *
256
     * @return boolean TRUE if the PK euqals, else FALSE
257
     */
258
    protected function isParentId($parentId)
259
    {
260
        return $this->getParentId() === $parentId;
261
    }
262
263
    /**
264
     * Query whether or not this is the parent store view code.
265
     *
266
     * @param string $storeViewCode The actual store view code
267
     *
268
     * @return boolean TRUE if the store view code equals, else FALSE
269
     */
270
    protected function isParentStoreViewCode($storeViewCode)
271
    {
272
        return $this->getStoreViewCode() === $storeViewCode;
0 ignored issues
show
Deprecated Code introduced by
The method TechDivision\Import\Obse...ver::getStoreViewCode() has been deprecated with message: Will be removed with version 1.0.0, use subject method instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
273
    }
274
275
    /**
276
     * Return's the default store view code.
277
     *
278
     * @return array The default store view code
279
     */
280
    protected function getDefaultStoreViewCode()
281
    {
282
        return $this->getSubject()->getDefaultStoreViewCode();
283
    }
284
285
    /**
286
     * Reset the position counter to 1.
287
     *
288
     * @return void
289
     */
290
    protected function resetPositionCounter()
291
    {
292
        $this->getSubject()->resetPositionCounter();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface TechDivision\Import\Subjects\SubjectInterface as the method resetPositionCounter() does only exist in the following implementations of said interface: TechDivision\Import\Prod...a\Subjects\MediaSubject.

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...
293
    }
294
295
    /**
296
     * Return's the EAV attribute with the passed attribute code.
297
     *
298
     * @param string $attributeCode The attribute code
299
     *
300
     * @return array The array with the EAV attribute
301
     * @throws \Exception Is thrown if the attribute with the passed code is not available
302
     */
303
    protected function getEavAttributeByAttributeCode($attributeCode)
304
    {
305
        return $this->getSubject()->getEavAttributeByAttributeCode($attributeCode);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface TechDivision\Import\Subjects\SubjectInterface as the method getEavAttributeByAttributeCode() does only exist in the following implementations of said interface: TechDivision\Import\Observers\EntitySubjectImpl, TechDivision\Import\Prod...a\Subjects\MediaSubject, TechDivision\Import\Prod...\AbstractProductSubject, TechDivision\Import\Product\Subjects\BunchSubject, TechDivision\Import\Subjects\AbstractEavSubject.

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...
306
    }
307
308
    /**
309
     * Persist's the passed product media gallery data and return's the ID.
310
     *
311
     * @param array $productMediaGallery The product media gallery data to persist
312
     *
313
     * @return string The ID of the persisted entity
314
     */
315
    protected function persistProductMediaGallery($productMediaGallery)
316
    {
317
        return $this->getProductMediaProcessor()->persistProductMediaGallery($productMediaGallery);
318
    }
319
320
    /**
321
     * Persist's the passed product media gallery value to entity data.
322
     *
323
     * @param array $productMediaGalleryValueToEntity The product media gallery value to entity data to persist
324
     *
325
     * @return void
326
     */
327
    protected function persistProductMediaGalleryValueToEntity($productMediaGalleryValueToEntity)
328
    {
329
        $this->getProductMediaProcessor()->persistProductMediaGalleryValueToEntity($productMediaGalleryValueToEntity);
330
    }
331
}
332