Completed
Pull Request — master (#3)
by Tim
03:55
created

MediaSubject::setUp()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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