Completed
Push — master ( 56abb6...e9f23e )
by Tim
9s
created

MediaSubject::persistProductMediaGalleryValue()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

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
eloc 2
nc 1
nop 1
crap 2
1
<?php
2
3
/**
4
 * TechDivision\Import\Product\Media\Subjects\MediaSubject
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\Subjects;
22
23
use TechDivision\Import\Utils\RegistryKeys;
24
use TechDivision\Import\Product\Media\Utils\ConfigurationKeys;
25
use TechDivision\Import\Product\Subjects\AbstractProductSubject;
26
27
/**
28
 * A SLSB that handles the process to import product variants.
29
 *
30
 * @author    Tim Wagner <[email protected]>
31
 * @copyright 2016 TechDivision GmbH <[email protected]>
32
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
33
 * @link      https://github.com/techdivision/import-product-media
34
 * @link      http://www.techdivision.com
35
 */
36
class MediaSubject extends AbstractProductSubject
37
{
38
39
    /**
40
     * The ID of the parent product to relate the variant with.
41
     *
42
     * @var integer
43
     */
44
    protected $parentId;
45
46
    /**
47
     * The value ID of the created media gallery entry.
48
     *
49
     * @var integer
50
     */
51
    protected $parentValueId;
52
53
    /**
54
     * The name of the craeted image.
55
     *
56
     * @var integer
57
     */
58
    protected $parentImage;
59
60
    /**
61
     * The Magento installation directory.
62
     *
63
     * @var string
64
     */
65
    protected $installationDir;
66
67
    /**
68
     * The directory with the Magento media files => target directory for images (relative to the root directory).
69
     *
70
     * @var string
71
     */
72
    protected $mediaDir;
73
74
    /**
75
     * The directory with the images that have to be imported (relative to the root directory).
76
     *
77
     * @var string
78
     */
79
    protected $imagesFileDir;
80
81
    /**
82
     * The position counter, if no position for the product media gallery value has been specified.
83
     *
84
     * @var integer
85
     */
86
    protected $positionCounter = 1;
87
88
    /**
89
     * The available stores.
90
     *
91
     * @var array
92
     */
93
    protected $stores = array();
94
95
    /**
96
     * The mapping for the SKUs to the created entity IDs.
97
     *
98
     * @var array
99
     */
100
    protected $skuEntityIdMapping = array();
101
102
    /**
103
     * Intializes the previously loaded global data for exactly one variants.
104
     *
105
     * @return void
106
     * @see \Importer\Csv\Actions\ProductImportAction::prepare()
107
     */
108
    public function setUp()
109
    {
110
111
        // invoke parent method
112
        parent::setUp();
113
114
        // load the entity manager and the registry processor
115
        $registryProcessor = $this->getRegistryProcessor();
116
117
        // load the status of the actual import process
118
        $status = $registryProcessor->getAttribute($this->getSerial());
119
120
        // load the attribute set we've prepared intially
121
        $this->skuEntityIdMapping = $status[RegistryKeys::SKU_ENTITY_ID_MAPPING];
122
123
        // load the Magento installation directory
124
        $this->setInstallationDir($this->getConfiguration()->getConfiguration()->getInstallationDir());
125
126
        // initialize media/and images directory => can be absolute or relative
127
        $this->setMediaDir($this->resolvePath($this->getConfiguration()->getParam(ConfigurationKeys::MEDIA_DIRECTORY)));
128
        $this->setImagesFileDir($this->resolvePath($this->getConfiguration()->getParam(ConfigurationKeys::IMAGES_FILE__DIRECTORY)));
129
    }
130
131
    /**
132
     * Set's the Magento installation directory.
133
     *
134
     * @param string $installationDir The Magento installation directory
135
     *
136
     * @return void
137
     */
138
    public function setInstallationDir($installationDir)
139
    {
140
        $this->installationDir = $installationDir;
141
    }
142
143
    /**
144
     * Return's the Magento installation directory.
145
     *
146
     * @return string The Magento installation directory
147
     */
148
    public function getInstallationDir()
149
    {
150
        return $this->installationDir;
151
    }
152
153
    /**
154
     * Set's directory with the Magento media files => target directory for images.
155
     *
156
     * @param string $mediaDir The directory with the Magento media files => target directory for images
157
     *
158
     * @return void
159
     */
160
    public function setMediaDir($mediaDir)
161
    {
162
        $this->mediaDir = $mediaDir;
163
    }
164
165
    /**
166
     * Return's the directory with the Magento media files => target directory for images.
167
     *
168
     * @return string The directory with the Magento media files => target directory for images
169
     */
170
    public function getMediaDir()
171
    {
172
        return $this->mediaDir;
173
    }
174
175
    /**
176
     * Set's directory with the images that have to be imported.
177
     *
178
     * @param string $imagesFileDir The directory with the images that have to be imported
179
     *
180
     * @return void
181
     */
182
    public function setImagesFileDir($imagesFileDir)
183
    {
184
        $this->imagesFileDir = $imagesFileDir;
185
    }
186
187
    /**
188
     * Return's the directory with the images that have to be imported.
189
     *
190
     * @return string The directory with the images that have to be imported
191
     */
192
    public function getImagesFileDir()
193
    {
194
        return $this->imagesFileDir;
195
    }
196
197
    /**
198
     * Set's the ID of the parent product to relate the variant with.
199
     *
200
     * @param integer $parentId The ID of the parent product
201
     *
202
     * @return void
203
     */
204
    public function setParentId($parentId)
205
    {
206
        $this->parentId = $parentId;
207
    }
208
209
    /**
210
     * Return's the ID of the parent product to relate the variant with.
211
     *
212
     * @return integer The ID of the parent product
213
     */
214
    public function getParentId()
215
    {
216
        return $this->parentId;
217
    }
218
219
    /**
220
     * Set's the value ID of the created media gallery entry.
221
     *
222
     * @param integer $parentValueId The ID of the created media gallery entry
223
     *
224
     * @return void
225
     */
226
    public function setParentValueId($parentValueId)
227
    {
228
        $this->parentValueId  = $parentValueId;
229
    }
230
231
    /**
232
     * Return's the value ID of the created media gallery entry.
233
     *
234
     * @return integer The ID of the created media gallery entry
235
     */
236
    public function getParentValueId()
237
    {
238
        return $this->parentValueId;
239
    }
240
241
    /**
242
     * Set's the name of the created image.
243
     *
244
     * @param string $parentImage The name of the created image
245
     *
246
     * @return void
247
     */
248
    public function setParentImage($parentImage)
249
    {
250
        $this->parentImage = $parentImage;
0 ignored issues
show
Documentation Bug introduced by
The property $parentImage was declared of type integer, but $parentImage 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...
251
    }
252
253
    /**
254
     * Return's the name of the created image.
255
     *
256
     * @return string The name of the created image
257
     */
258
    public function getParentImage()
259
    {
260
        return $this->parentImage;
261
    }
262
263
    /**
264
     * Reset the position counter to 1.
265
     *
266
     * @return void
267
     */
268
    public function resetPositionCounter()
269
    {
270
        $this->positionCounter = 1;
271
    }
272
273
    /**
274
     * Returns the acutal value of the position counter and raise's it by one.
275
     *
276
     * @return integer The actual value of the position counter
277
     */
278
    public function raisePositionCounter()
279
    {
280
        return $this->positionCounter++;
281
    }
282
283
    /**
284
     * Return the entity ID for the passed SKU.
285
     *
286
     * @param string $sku The SKU to return the entity ID for
287
     *
288
     * @return integer The mapped entity ID
289
     * @throws \Exception Is thrown if the SKU is not mapped yet
290
     */
291
    public function mapSkuToEntityId($sku)
292
    {
293
294
        // query weather or not the SKU has been mapped
295
        if (isset($this->skuEntityIdMapping[$sku])) {
296
            return $this->skuEntityIdMapping[$sku];
297
        }
298
299
        // throw an exception if the SKU has not been mapped yet
300
        throw new \Exception(sprintf('Found not mapped SKU %s', $sku));
301
    }
302
303
    /**
304
     * Return's the store for the passed store code.
305
     *
306
     * @param string $storeCode The store code to return the store for
307
     *
308
     * @return array The requested store
309
     * @throws \Exception Is thrown, if the requested store is not available
310
     */
311
    public function getStoreByStoreCode($storeCode)
312
    {
313
314
        // query whether or not the store with the passed store code exists
315
        if (isset($this->stores[$storeCode])) {
316
            return $this->stores[$storeCode];
317
        }
318
319
        // throw an exception, if not
320
        throw new \Exception(sprintf('Found invalid store code %s', $storeCode));
321
    }
322
323
    /**
324
     * Upload's the file with the passed name to the Magento
325
     * media directory. If the file already exists, the will
326
     * be given a new name that will be returned.
327
     *
328
     * @param string $filename The name of the file to be uploaded
329
     *
330
     * @return string The name of the uploaded file
331
     */
332
    public function uploadFile($filename)
333
    {
334
335
        // trim the leading /, if available
336
        $trimmedFilename = ltrim($filename, '/');
337
338
        // prepare source/target filename
339
        $sourceFilename = sprintf('%s/%s', $this->getImagesFileDir(), $trimmedFilename);
340
        $targetFilename = sprintf('%s/%s', $this->getMediaDir(), $trimmedFilename);
341
342
        // query whether or not the image file to be imported is available
343
        if (!$this->getFilesystem()->has($sourceFilename)) {
344
            $this->getSystemLogger()->info(sprintf('Media file %s not available', $sourceFilename));
345
            return;
346
        }
347
348
        // prepare the target filename, if necessary
349
        $newTargetFilename = $this->getNewFileName($targetFilename);
350
        $targetFilename = str_replace(basename($targetFilename), $newTargetFilename, $targetFilename);
351
352
        // copy the image to the target directory
353
        $this->getFilesystem()->copy($sourceFilename, $targetFilename);
354
355
        // return the new target filename
356
        return str_replace($this->getMediaDir(), '', $targetFilename);
357
    }
358
359
    /**
360
     * Get new file name if the same is already exists.
361
     *
362
     * @param string $targetFilename The name of the exisising files
363
     *
364
     * @return string The new filename
365
     */
366
    public function getNewFileName($targetFilename)
367
    {
368
369
        // load the file information
370
        $fileInfo = pathinfo($targetFilename);
371
372
        // query whether or not, the file exists
373
        if ($this->getFilesystem()->has($targetFilename)) {
374
            // initialize the incex and the basename
375
            $index = 1;
376
            $baseName = $fileInfo['filename'] . '.' . $fileInfo['extension'];
377
378
            // prepare the new filename by raising the index
379
            while ($this->getFilesystem()->has($fileInfo['dirname'] . '/' . $baseName)) {
380
                $baseName = $fileInfo['filename'] . '_' . $index . '.' . $fileInfo['extension'];
381
                $index++;
382
            }
383
384
            // set the new filename
385
            $targetFilename = $baseName;
386
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
387
        } else {
388
            // if not, simply return the filename
389
            return $fileInfo['basename'];
390
        }
391
392
        // return the new filename
393
        return $targetFilename;
394
    }
395
396
    /**
397
     * Load's the product media gallery with the passed attribute ID + value.
398
     *
399
     * @param integer $attributeId The attribute ID of the product media gallery to load
400
     * @param string  $value       The value of the product media gallery to load
401
     *
402
     * @return array The product media gallery
403
     */
404
    public function loadProductMediaGallery($attributeId, $value)
405
    {
406
        return $this->getProductProcessor()->loadProductMediaGallery($attributeId, $value);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface TechDivision\Import\Prod...oductProcessorInterface as the method loadProductMediaGallery() does only exist in the following implementations of said interface: TechDivision\Import\Prod...s\ProductMediaProcessor.

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...
407
    }
408
409
    /**
410
     * Load's the product media gallery with the passed value/entity ID.
411
     *
412
     * @param integer $valueId  The value ID of the product media gallery value to entity to load
413
     * @param integer $entityId The entity ID of the product media gallery value to entity to load
414
     *
415
     * @return array The product media gallery
416
     */
417
    public function loadProductMediaGalleryValueToEntity($valueId, $entityId)
418
    {
419
        return $this->getProductProcessor()->loadProductMediaGalleryValueToEntity($valueId, $entityId);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface TechDivision\Import\Prod...oductProcessorInterface as the method loadProductMediaGalleryValueToEntity() does only exist in the following implementations of said interface: TechDivision\Import\Prod...s\ProductMediaProcessor.

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...
420
    }
421
422
    /**
423
     * Load's the product media gallery value with the passed value/store/parent ID.
424
     *
425
     * @param integer $valueId  The value ID of the product media gallery value to load
426
     * @param string  $storeId  The store ID of the product media gallery value to load
427
     * @param string  $entityId The entity ID of the parent product of the product media gallery value to load
428
     *
429
     * @return array The product media gallery value
430
     */
431
    public function loadProductMediaGalleryValue($valueId, $storeId, $entityId)
432
    {
433
        $this->getProductProcessor()->loadProductMediaGalleryValue($valueId, $storeId, $entityId);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface TechDivision\Import\Prod...oductProcessorInterface as the method loadProductMediaGalleryValue() does only exist in the following implementations of said interface: TechDivision\Import\Prod...s\ProductMediaProcessor.

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...
434
    }
435
436
    /**
437
     * Persist's the passed product media gallery data and return's the ID.
438
     *
439
     * @param array $productMediaGallery The product media gallery data to persist
440
     *
441
     * @return string The ID of the persisted entity
442
     */
443
    public function persistProductMediaGallery($productMediaGallery)
444
    {
445
        return $this->getProductProcessor()->persistProductMediaGallery($productMediaGallery);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface TechDivision\Import\Prod...oductProcessorInterface as the method persistProductMediaGallery() does only exist in the following implementations of said interface: TechDivision\Import\Prod...s\ProductMediaProcessor.

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...
446
    }
447
448
    /**
449
     * Persist's the passed product media gallery value data.
450
     *
451
     * @param array $productMediaGalleryValue The product media gallery value data to persist
452
     *
453
     * @return void
454
     */
455
    public function persistProductMediaGalleryValue($productMediaGalleryValue)
456
    {
457
        $this->getProductProcessor()->persistProductMediaGalleryValue($productMediaGalleryValue);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface TechDivision\Import\Prod...oductProcessorInterface as the method persistProductMediaGalleryValue() does only exist in the following implementations of said interface: TechDivision\Import\Prod...s\ProductMediaProcessor.

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...
458
    }
459
460
    /**
461
     * Persist's the passed product media gallery value to entity data.
462
     *
463
     * @param array $productMediaGalleryValuetoEntity The product media gallery value to entity data to persist
464
     *
465
     * @return void
466
     */
467
    public function persistProductMediaGalleryValueToEntity($productMediaGalleryValuetoEntity)
468
    {
469
        $this->getProductProcessor()->persistProductMediaGalleryValueToEntity($productMediaGalleryValuetoEntity);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface TechDivision\Import\Prod...oductProcessorInterface as the method persistProductMediaGalleryValueToEntity() does only exist in the following implementations of said interface: TechDivision\Import\Prod...s\ProductMediaProcessor.

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...
470
    }
471
472
    /**
473
     * Persist's the passed product media gallery value video data.
474
     *
475
     * @param array $productMediaGalleryValueVideo The product media gallery value video data to persist
476
     *
477
     * @return void
478
     */
479
    public function persistProductMediaGalleryValueVideo($productMediaGalleryValueVideo)
480
    {
481
        $this->getProductProcessor()->persistProductMediaGalleryValueVideo($productMediaGalleryValueVideo);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface TechDivision\Import\Prod...oductProcessorInterface as the method persistProductMediaGalleryValueVideo() does only exist in the following implementations of said interface: TechDivision\Import\Prod...s\ProductMediaProcessor.

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...
482
    }
483
}
484