Completed
Push — master ( e9f23e...c329f6 )
by Tim
12s
created

MediaSubject   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 473
Duplicated Lines 0 %

Coupling/Cohesion

Components 4
Dependencies 6

Test Coverage

Coverage 0%

Importance

Changes 2
Bugs 0 Features 1
Metric Value
wmc 33
lcom 4
cbo 6
dl 0
loc 473
ccs 0
cts 147
cp 0
rs 9.3999
c 2
b 0
f 1

28 Methods

Rating   Name   Duplication   Size   Complexity  
B setUp() 0 25 1
A setInstallationDir() 0 4 1
A getInstallationDir() 0 4 1
A setMediaDir() 0 4 1
A getMediaDir() 0 4 1
A setImagesFileDir() 0 4 1
A getImagesFileDir() 0 4 1
A setCopyImages() 0 4 1
A hasCopyImages() 0 4 1
A setParentId() 0 4 1
A getParentId() 0 4 1
A setParentValueId() 0 4 1
A getParentValueId() 0 4 1
A setParentImage() 0 4 1
A getParentImage() 0 4 1
A resetPositionCounter() 0 4 1
A raisePositionCounter() 0 4 1
A mapSkuToEntityId() 0 11 2
A getStoreByStoreCode() 0 11 2
B uploadFile() 0 26 2
B getNewFileName() 0 29 3
A loadProductMediaGallery() 0 4 1
A loadProductMediaGalleryValueToEntity() 0 4 1
A loadProductMediaGalleryValue() 0 4 1
A persistProductMediaGallery() 0 4 1
A persistProductMediaGalleryValue() 0 4 1
A persistProductMediaGalleryValueToEntity() 0 4 1
A persistProductMediaGalleryValueVideo() 0 4 1
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 the flag to decide copy images or not
127
        $this->setCopyImages($this->getConfiguration()->getParam(ConfigurationKeys::COPY_IMAGES));
0 ignored issues
show
Documentation introduced by
$this->getConfiguration(...ationKeys::COPY_IMAGES) is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
128
129
        // initialize media/and images directory => can be absolute or relative
130
        $this->setMediaDir($this->resolvePath($this->getConfiguration()->getParam(ConfigurationKeys::MEDIA_DIRECTORY)));
131
        $this->setImagesFileDir($this->resolvePath($this->getConfiguration()->getParam(ConfigurationKeys::IMAGES_FILE_DIRECTORY)));
132
    }
133
134
    /**
135
     * Set's the Magento installation directory.
136
     *
137
     * @param string $installationDir The Magento installation directory
138
     *
139
     * @return void
140
     */
141
    public function setInstallationDir($installationDir)
142
    {
143
        $this->installationDir = $installationDir;
144
    }
145
146
    /**
147
     * Return's the Magento installation directory.
148
     *
149
     * @return string The Magento installation directory
150
     */
151
    public function getInstallationDir()
152
    {
153
        return $this->installationDir;
154
    }
155
156
    /**
157
     * Set's directory with the Magento media files => target directory for images.
158
     *
159
     * @param string $mediaDir The directory with the Magento media files => target directory for images
160
     *
161
     * @return void
162
     */
163
    public function setMediaDir($mediaDir)
164
    {
165
        $this->mediaDir = $mediaDir;
166
    }
167
168
    /**
169
     * Return's the directory with the Magento media files => target directory for images.
170
     *
171
     * @return string The directory with the Magento media files => target directory for images
172
     */
173
    public function getMediaDir()
174
    {
175
        return $this->mediaDir;
176
    }
177
178
    /**
179
     * Set's directory with the images that have to be imported.
180
     *
181
     * @param string $imagesFileDir The directory with the images that have to be imported
182
     *
183
     * @return void
184
     */
185
    public function setImagesFileDir($imagesFileDir)
186
    {
187
        $this->imagesFileDir = $imagesFileDir;
188
    }
189
190
    /**
191
     * Return's the directory with the images that have to be imported.
192
     *
193
     * @return string The directory with the images that have to be imported
194
     */
195
    public function getImagesFileDir()
196
    {
197
        return $this->imagesFileDir;
198
    }
199
200
    /**
201
     * Set's the flag to copy the images or not.
202
     *
203
     * @param boolean $copyImages The flag
204
     *
205
     * @return void
206
     */
207
    public function setCopyImages($copyImages)
208
    {
209
        $this->copyImages = $copyImages;
0 ignored issues
show
Bug introduced by
The property copyImages does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
210
    }
211
212
    /**
213
     * Return's the flag to copy images or not.
214
     *
215
     * @return boolean The flag
216
     */
217
    public function hasCopyImages()
218
    {
219
        return $this->copyImages;
220
    }
221
222
    /**
223
     * Set's the ID of the parent product to relate the variant with.
224
     *
225
     * @param integer $parentId The ID of the parent product
226
     *
227
     * @return void
228
     */
229
    public function setParentId($parentId)
230
    {
231
        $this->parentId = $parentId;
232
    }
233
234
    /**
235
     * Return's the ID of the parent product to relate the variant with.
236
     *
237
     * @return integer The ID of the parent product
238
     */
239
    public function getParentId()
240
    {
241
        return $this->parentId;
242
    }
243
244
    /**
245
     * Set's the value ID of the created media gallery entry.
246
     *
247
     * @param integer $parentValueId The ID of the created media gallery entry
248
     *
249
     * @return void
250
     */
251
    public function setParentValueId($parentValueId)
252
    {
253
        $this->parentValueId  = $parentValueId;
254
    }
255
256
    /**
257
     * Return's the value ID of the created media gallery entry.
258
     *
259
     * @return integer The ID of the created media gallery entry
260
     */
261
    public function getParentValueId()
262
    {
263
        return $this->parentValueId;
264
    }
265
266
    /**
267
     * Set's the name of the created image.
268
     *
269
     * @param string $parentImage The name of the created image
270
     *
271
     * @return void
272
     */
273
    public function setParentImage($parentImage)
274
    {
275
        $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...
276
    }
277
278
    /**
279
     * Return's the name of the created image.
280
     *
281
     * @return string The name of the created image
282
     */
283
    public function getParentImage()
284
    {
285
        return $this->parentImage;
286
    }
287
288
    /**
289
     * Reset the position counter to 1.
290
     *
291
     * @return void
292
     */
293
    public function resetPositionCounter()
294
    {
295
        $this->positionCounter = 1;
296
    }
297
298
    /**
299
     * Returns the acutal value of the position counter and raise's it by one.
300
     *
301
     * @return integer The actual value of the position counter
302
     */
303
    public function raisePositionCounter()
304
    {
305
        return $this->positionCounter++;
306
    }
307
308
    /**
309
     * Return the entity ID for the passed SKU.
310
     *
311
     * @param string $sku The SKU to return the entity ID for
312
     *
313
     * @return integer The mapped entity ID
314
     * @throws \Exception Is thrown if the SKU is not mapped yet
315
     */
316
    public function mapSkuToEntityId($sku)
317
    {
318
319
        // query weather or not the SKU has been mapped
320
        if (isset($this->skuEntityIdMapping[$sku])) {
321
            return $this->skuEntityIdMapping[$sku];
322
        }
323
324
        // throw an exception if the SKU has not been mapped yet
325
        throw new \Exception(sprintf('Found not mapped SKU %s', $sku));
326
    }
327
328
    /**
329
     * Return's the store for the passed store code.
330
     *
331
     * @param string $storeCode The store code to return the store for
332
     *
333
     * @return array The requested store
334
     * @throws \Exception Is thrown, if the requested store is not available
335
     */
336
    public function getStoreByStoreCode($storeCode)
337
    {
338
339
        // query whether or not the store with the passed store code exists
340
        if (isset($this->stores[$storeCode])) {
341
            return $this->stores[$storeCode];
342
        }
343
344
        // throw an exception, if not
345
        throw new \Exception(sprintf('Found invalid store code %s', $storeCode));
346
    }
347
348
    /**
349
     * Upload's the file with the passed name to the Magento
350
     * media directory. If the file already exists, the will
351
     * be given a new name that will be returned.
352
     *
353
     * @param string $filename The name of the file to be uploaded
354
     *
355
     * @return string The name of the uploaded file
356
     */
357
    public function uploadFile($filename)
358
    {
359
360
        // trim the leading /, if available
361
        $trimmedFilename = ltrim($filename, '/');
362
363
        // prepare source/target filename
364
        $sourceFilename = sprintf('%s/%s', $this->getImagesFileDir(), $trimmedFilename);
365
        $targetFilename = sprintf('%s/%s', $this->getMediaDir(), $trimmedFilename);
366
367
        // query whether or not the image file to be imported is available
368
        if (!$this->getFilesystem()->has($sourceFilename)) {
369
            $this->getSystemLogger()->info(sprintf('Media file %s not available', $sourceFilename));
370
            return;
371
        }
372
373
        // prepare the target filename, if necessary
374
        $newTargetFilename = $this->getNewFileName($targetFilename);
375
        $targetFilename = str_replace(basename($targetFilename), $newTargetFilename, $targetFilename);
376
377
        // copy the image to the target directory
378
        $this->getFilesystem()->copy($sourceFilename, $targetFilename);
379
380
        // return the new target filename
381
        return str_replace($this->getMediaDir(), '', $targetFilename);
382
    }
383
384
    /**
385
     * Get new file name if the same is already exists.
386
     *
387
     * @param string $targetFilename The name of the exisising files
388
     *
389
     * @return string The new filename
390
     */
391
    public function getNewFileName($targetFilename)
392
    {
393
394
        // load the file information
395
        $fileInfo = pathinfo($targetFilename);
396
397
        // query whether or not, the file exists
398
        if ($this->getFilesystem()->has($targetFilename)) {
399
            // initialize the incex and the basename
400
            $index = 1;
401
            $baseName = $fileInfo['filename'] . '.' . $fileInfo['extension'];
402
403
            // prepare the new filename by raising the index
404
            while ($this->getFilesystem()->has($fileInfo['dirname'] . '/' . $baseName)) {
405
                $baseName = $fileInfo['filename'] . '_' . $index . '.' . $fileInfo['extension'];
406
                $index++;
407
            }
408
409
            // set the new filename
410
            $targetFilename = $baseName;
411
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
412
        } else {
413
            // if not, simply return the filename
414
            return $fileInfo['basename'];
415
        }
416
417
        // return the new filename
418
        return $targetFilename;
419
    }
420
421
    /**
422
     * Load's the product media gallery with the passed attribute ID + value.
423
     *
424
     * @param integer $attributeId The attribute ID of the product media gallery to load
425
     * @param string  $value       The value of the product media gallery to load
426
     *
427
     * @return array The product media gallery
428
     */
429
    public function loadProductMediaGallery($attributeId, $value)
430
    {
431
        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...
432
    }
433
434
    /**
435
     * Load's the product media gallery with the passed value/entity ID.
436
     *
437
     * @param integer $valueId  The value ID of the product media gallery value to entity to load
438
     * @param integer $entityId The entity ID of the product media gallery value to entity to load
439
     *
440
     * @return array The product media gallery
441
     */
442
    public function loadProductMediaGalleryValueToEntity($valueId, $entityId)
443
    {
444
        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...
445
    }
446
447
    /**
448
     * Load's the product media gallery value with the passed value/store/parent ID.
449
     *
450
     * @param integer $valueId  The value ID of the product media gallery value to load
451
     * @param string  $storeId  The store ID of the product media gallery value to load
452
     * @param string  $entityId The entity ID of the parent product of the product media gallery value to load
453
     *
454
     * @return array The product media gallery value
455
     */
456
    public function loadProductMediaGalleryValue($valueId, $storeId, $entityId)
457
    {
458
        $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...
459
    }
460
461
    /**
462
     * Persist's the passed product media gallery data and return's the ID.
463
     *
464
     * @param array $productMediaGallery The product media gallery data to persist
465
     *
466
     * @return string The ID of the persisted entity
467
     */
468
    public function persistProductMediaGallery($productMediaGallery)
469
    {
470
        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...
471
    }
472
473
    /**
474
     * Persist's the passed product media gallery value data.
475
     *
476
     * @param array $productMediaGalleryValue The product media gallery value data to persist
477
     *
478
     * @return void
479
     */
480
    public function persistProductMediaGalleryValue($productMediaGalleryValue)
481
    {
482
        $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...
483
    }
484
485
    /**
486
     * Persist's the passed product media gallery value to entity data.
487
     *
488
     * @param array $productMediaGalleryValuetoEntity The product media gallery value to entity data to persist
489
     *
490
     * @return void
491
     */
492
    public function persistProductMediaGalleryValueToEntity($productMediaGalleryValuetoEntity)
493
    {
494
        $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...
495
    }
496
497
    /**
498
     * Persist's the passed product media gallery value video data.
499
     *
500
     * @param array $productMediaGalleryValueVideo The product media gallery value video data to persist
501
     *
502
     * @return void
503
     */
504
    public function persistProductMediaGalleryValueVideo($productMediaGalleryValueVideo)
505
    {
506
        $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...
507
    }
508
}
509