Completed
Push — 24.x ( 3133ab...f1839c )
by
unknown
01:56 queued 12s
created

BunchSubject   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 339
Duplicated Lines 10.32 %

Coupling/Cohesion

Components 2
Dependencies 8

Test Coverage

Coverage 33.87%

Importance

Changes 0
Metric Value
wmc 24
lcom 2
cbo 8
dl 35
loc 339
ccs 21
cts 62
cp 0.3387
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 16 1
B setUp() 20 46 9
A tearDown() 0 17 1
A getDefaultCallbackMappings() 0 4 1
A getHeaderStockMappings() 0 4 1
A getVisibilityIdByValue() 0 16 2
A preLoadEntityId() 0 4 1
A getEntityType() 15 15 2
A isUrlKeyOf() 0 5 2
A getMediaRoles() 0 4 1
A getCleanUpColumns() 0 14 2
A getEntityTypeCode() 0 4 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/**
4
 * TechDivision\Import\Product\Subjects\BunchSubject
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Tim Wagner <[email protected]>
15
 * @copyright 2016 TechDivision GmbH <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/techdivision/import-product
18
 * @link      http://www.techdivision.com
19
 */
20
21
namespace TechDivision\Import\Product\Subjects;
22
23
use Doctrine\Common\Collections\Collection;
24
use League\Event\EmitterInterface;
25
use TechDivision\Import\Loaders\LoaderInterface;
26
use TechDivision\Import\Services\RegistryProcessorInterface;
27
use TechDivision\Import\Utils\Generators\GeneratorInterface;
28
use TechDivision\Import\Utils\StoreViewCodes;
29
use TechDivision\Import\Utils\Mappings\MapperInterface;
30
use TechDivision\Import\Product\Utils\MemberNames;
31
use TechDivision\Import\Product\Utils\RegistryKeys;
32
use TechDivision\Import\Product\Utils\VisibilityKeys;
33
use TechDivision\Import\Product\Utils\ConfigurationKeys;
34
use TechDivision\Import\Subjects\ExportableTrait;
35
use TechDivision\Import\Subjects\FileUploadTrait;
36
use TechDivision\Import\Subjects\ExportableSubjectInterface;
37
use TechDivision\Import\Subjects\FileUploadSubjectInterface;
38
use TechDivision\Import\Subjects\UrlKeyAwareSubjectInterface;
39
use TechDivision\Import\Subjects\CleanUpColumnsSubjectInterface;
40
use TechDivision\Import\Utils\FileUploadConfigurationKeys;
41
42
/**
43
 * The subject implementation that handles the business logic to persist products.
44
 *
45
 * @author    Tim Wagner <[email protected]>
46
 * @copyright 2016 TechDivision GmbH <[email protected]>
47
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
48
 * @link      https://github.com/techdivision/import-product
49
 * @link      http://www.techdivision.com
50
 */
51
class BunchSubject extends AbstractProductSubject implements ExportableSubjectInterface, FileUploadSubjectInterface, UrlKeyAwareSubjectInterface, CleanUpColumnsSubjectInterface
52
{
53
54
    /**
55
     * The trait that implements the export functionality.
56
     *
57
     * @var \TechDivision\Import\Subjects\ExportableTrait
58
     */
59
    use ExportableTrait;
60
61
    /**
62
     * The trait that provides file upload functionality.
63
     *
64
     * @var \TechDivision\Import\Subjects\FileUploadTrait
65
     */
66
    use FileUploadTrait;
67
68
    /**
69
     * The array with the pre-loaded entity IDs.
70
     *
71
     * @var array
72
     */
73
    protected $preLoadedEntityIds = array();
74
75
    /**
76
     * Mappings for the table column => CSV column header.
77
     *
78
     * @var array
79
     */
80
    protected $headerStockMappings = array(
81
        'qty'                         => array('qty', 'float'),
82
        'min_qty'                     => array('out_of_stock_qty', 'float'),
83
        'use_config_min_qty'          => array('use_config_min_qty', 'int'),
84
        'is_qty_decimal'              => array('is_qty_decimal', 'int'),
85
        'backorders'                  => array('allow_backorders', 'int'),
86
        'use_config_backorders'       => array('use_config_backorders', 'int'),
87
        'min_sale_qty'                => array('min_cart_qty', 'float'),
88
        'use_config_min_sale_qty'     => array('use_config_min_sale_qty', 'int'),
89
        'max_sale_qty'                => array('max_cart_qty', 'float'),
90
        'use_config_max_sale_qty'     => array('use_config_max_sale_qty', 'int'),
91
        'is_in_stock'                 => array('is_in_stock', 'int'),
92
        'notify_stock_qty'            => array('notify_on_stock_below', 'float'),
93
        'use_config_notify_stock_qty' => array('use_config_notify_stock_qty', 'int'),
94
        'manage_stock'                => array('manage_stock', 'int'),
95
        'use_config_manage_stock'     => array('use_config_manage_stock', 'int'),
96
        'use_config_qty_increments'   => array('use_config_qty_increments', 'int'),
97
        'qty_increments'              => array('qty_increments', 'float'),
98
        'use_config_enable_qty_inc'   => array('use_config_enable_qty_inc', 'int'),
99
        'enable_qty_increments'       => array('enable_qty_increments', 'int'),
100
        'is_decimal_divided'          => array('is_decimal_divided', 'int'),
101
    );
102
103
    /**
104
     * The array with the available visibility keys.
105
     *
106
     * @var array
107
     */
108
    protected $availableVisibilities = array(
109
        'Not Visible Individually' => VisibilityKeys::VISIBILITY_NOT_VISIBLE,
110
        'Catalog'                  => VisibilityKeys::VISIBILITY_IN_CATALOG,
111
        'Search'                   => VisibilityKeys::VISIBILITY_IN_SEARCH,
112
        'Catalog, Search'          => VisibilityKeys::VISIBILITY_BOTH
113
    );
114
115
    /**
116
     * The default callback mappings for the Magento standard product attributes.
117
     *
118
     * @var array
119
     */
120
    protected $defaultCallbackMappings = array(
121
        'visibility'           => array('import_product.callback.visibility'),
122
        'tax_class_id'         => array('import_product.callback.tax.class'),
123
        'bundle_price_type'    => array('import_product_bundle.callback.bundle.type'),
124
        'bundle_sku_type'      => array('import_product_bundle.callback.bundle.type'),
125
        'bundle_weight_type'   => array('import_product_bundle.callback.bundle.type'),
126
        'bundle_price_view'    => array('import_product_bundle.callback.bundle.price.view'),
127
        'bundle_shipment_type' => array('import_product_bundle.callback.bundle.shipment.type')
128
    );
129
130
    /**
131
     * The available entity types.
132
     *
133
     * @var array
134
     */
135
    protected $entityTypes = array();
136
137
    /**
138
     * The media roles loader instance.
139
     *
140
     * @var \TechDivision\Import\Loaders\LoaderInterface
141
     */
142
    protected $mediaRolesLoader;
143
144
    /**
145
     * The entity type code mapper instance.
146
     *
147
     * @var \TechDivision\Import\Utils\Mappings\MapperInterface
148
     */
149
    protected $entityTypeCodeMapper;
150
151
    /**
152
     * BunchSubject constructor
153
     *
154
     * @param \TechDivision\Import\Services\RegistryProcessorInterface $registryProcessor          The registry processor instance
155
     * @param \TechDivision\Import\Utils\Generators\GeneratorInterface $coreConfigDataUidGenerator The UID generator for the core config data
156
     * @param \Doctrine\Common\Collections\Collection                  $systemLoggers              The array with the system loggers instances
157
     * @param \League\Event\EmitterInterface                           $emitter                    The event emitter instance
158
     * @param \TechDivision\Import\Loaders\LoaderInterface             $mediaRolesLoader           The media type loader instance
159
     * @param \TechDivision\Import\Utils\Mappings\MapperInterface      $entityTypeCodeMapper       The entity type code mapper instance
160
     */
161 18
    public function __construct(
162
        RegistryProcessorInterface $registryProcessor,
163
        GeneratorInterface $coreConfigDataUidGenerator,
164
        Collection $systemLoggers,
165
        EmitterInterface $emitter,
166
        LoaderInterface $mediaRolesLoader,
167
        MapperInterface $entityTypeCodeMapper
168
    ) {
169
170
        // set the loader for the media roles and the entity type code mapper
171 18
        $this->mediaRolesLoader = $mediaRolesLoader;
172 18
        $this->entityTypeCodeMapper = $entityTypeCodeMapper;
173
174
        // pass the other instances to the parent constructor
175 18
        parent::__construct($registryProcessor, $coreConfigDataUidGenerator, $systemLoggers, $emitter);
176 18
    }
177
178
    /**
179
     * Intializes the previously loaded global data for exactly one bunch.
180
     *
181
     * @param string $serial The serial of the actual import
182
     *
183
     * @return void
184
     */
185 18
    public function setUp($serial)
186
    {
187
188
        // load the status of the actual import
189 18
        $status = $this->getRegistryProcessor()->getAttribute(RegistryKeys::STATUS);
190
191
        // load the global data we've prepared initially
192 18
        $this->entityTypes = $status[RegistryKeys::GLOBAL_DATA][RegistryKeys::ENTITY_TYPES];
193
194
        // initialize the flag whether to copy images or not
195 18
        if ($this->getConfiguration()->hasParam(FileUploadConfigurationKeys::COPY_IMAGES)) {
196
            $this->setCopyImages($this->getConfiguration()->getParam(FileUploadConfigurationKeys::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...
197
        }
198
199
        // initialize the flag whether to override images or not
200 18
        if ($this->getConfiguration()->hasParam(FileUploadConfigurationKeys::OVERRIDE_IMAGES)) {
201
            $this->setOverrideImages($this->getConfiguration()->getParam(FileUploadConfigurationKeys::OVERRIDE_IMAGES));
0 ignored issues
show
Documentation introduced by
$this->getConfiguration(...nKeys::OVERRIDE_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...
202
        }
203
204
        // initialize media directory => can be absolute or relative
205 18 View Code Duplication
        if ($this->getConfiguration()->hasParam(FileUploadConfigurationKeys::MEDIA_DIRECTORY)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
206
            try {
207
                $this->setMediaDir($this->resolvePath($this->getConfiguration()->getParam(FileUploadConfigurationKeys::MEDIA_DIRECTORY)));
208
            } catch (\InvalidArgumentException $iae) {
209
                // only if we wanna copy images we need directories
210
                if ($this->hasCopyImages()) {
211
                    $this->getSystemLogger()->warning($iae->getMessage());
212
                }
213
            }
214
        }
215
216
        // initialize images directory => can be absolute or relative
217 18 View Code Duplication
        if ($this->getConfiguration()->hasParam(FileUploadConfigurationKeys::IMAGES_FILE_DIRECTORY)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
218
            try {
219
                $this->setImagesFileDir($this->resolvePath($this->getConfiguration()->getParam(FileUploadConfigurationKeys::IMAGES_FILE_DIRECTORY)));
220
            } catch (\InvalidArgumentException $iae) {
221
                // only if we wanna copy images we need directories
222
                if ($this->hasCopyImages()) {
223
                    $this->getSystemLogger()->warning($iae->getMessage());
224
                }
225
            }
226
        }
227
228
        // invoke the parent method
229 18
        parent::setUp($serial);
230 18
    }
231
232
    /**
233
     * Clean up the global data after importing the bunch.
234
     *
235
     * @param string $serial The serial of the actual import
236
     *
237
     * @return void
238
     */
239
    public function tearDown($serial)
240
    {
241
242
        // invoke the parent method
243
        parent::tearDown($serial);
244
245
        // load the registry processor
246
        $registryProcessor = $this->getRegistryProcessor();
247
248
        // update the status
249
        $registryProcessor->mergeAttributesRecursive(
250
            RegistryKeys::STATUS,
251
            array(
252
                RegistryKeys::PRE_LOADED_ENTITY_IDS => $this->preLoadedEntityIds,
253
            )
254
        );
255
    }
256
257
    /**
258
     * Return's the default callback mappings.
259
     *
260
     * @return array The default callback mappings
261
     */
262
    public function getDefaultCallbackMappings()
263
    {
264
        return $this->defaultCallbackMappings;
265
    }
266
267
    /**
268
     * Return's the mappings for the table column => CSV column header.
269
     *
270
     * @return array The header stock mappings
271
     */
272 1
    public function getHeaderStockMappings()
273
    {
274 1
        return $this->headerStockMappings;
275
    }
276
277
    /**
278
     * Return's the visibility key for the passed visibility string.
279
     *
280
     * @param string $visibility The visibility string to return the key for
281
     *
282
     * @return integer The requested visibility key
283
     * @throws \Exception Is thrown, if the requested visibility is not available
284
     */
285
    public function getVisibilityIdByValue($visibility)
286
    {
287
288
        // query whether or not, the requested visibility is available
289
        if (isset($this->availableVisibilities[$visibility])) {
290
            // load the visibility ID, add the mapping and return the ID
291
            return $this->availableVisibilities[$visibility];
292
        }
293
294
        // throw an exception, if not
295
        throw new \Exception(
296
            $this->appendExceptionSuffix(
297
                sprintf('Found invalid visibility %s', $visibility)
298
            )
299
        );
300
    }
301
302
    /**
303
     * Pre-load the entity ID for the passed product.
304
     *
305
     * @param array $product The product to be pre-loaded
306
     *
307
     * @return void
308
     */
309
    public function preLoadEntityId(array $product)
310
    {
311
        $this->preLoadedEntityIds[$product[MemberNames::SKU]] = $product[MemberNames::ENTITY_ID];
312
    }
313
314
    /**
315
     * Return's the entity type for the configured entity type code.
316
     *
317
     * @return array The requested entity type
318
     * @throws \Exception Is thrown, if the requested entity type is not available
319
     */
320 1 View Code Duplication
    public function getEntityType()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
321
    {
322
323
        // query whether or not the entity type with the passed code is available
324 1
        if (isset($this->entityTypes[$entityTypeCode = $this->getEntityTypeCode()])) {
325 1
            return $this->entityTypes[$entityTypeCode];
326
        }
327
328
        // throw a new exception
329
        throw new \Exception(
330
            $this->appendExceptionSuffix(
331
                sprintf('Requested entity type "%s" is not available', $entityTypeCode)
332
            )
333
        );
334
    }
335
336
    /**
337
     * Return's TRUE, if the passed URL key varchar value IS related with the actual PK.
338
     *
339
     * @param array $productVarcharAttribute The varchar value to check
340
     *
341
     * @return boolean TRUE if the URL key is related, else FALSE
342
     */
343
    public function isUrlKeyOf(array $productVarcharAttribute)
344
    {
345
        return ((integer) $productVarcharAttribute[MemberNames::ENTITY_ID] === (integer) $this->getLastEntityId()) &&
346
               ((integer) $productVarcharAttribute[MemberNames::STORE_ID] === (integer) $this->getRowStoreId(StoreViewCodes::ADMIN));
347
    }
348
349
    /**
350
     * Loads and returns the media roles.
351
     *
352
     * @return array The array with the media roles
353
     */
354
    public function getMediaRoles(): array
355
    {
356
        return $this->mediaRolesLoader->load();
357
    }
358
359
    /**
360
     * Merge the columns from the configuration with all image type columns to define which
361
     * columns should be cleaned-up.
362
     *
363
     * @return array The columns that has to be cleaned-up
364
     */
365
    public function getCleanUpColumns()
366
    {
367
368
        // initialize the array for the columns that has to be cleaned-up
369
        $cleanUpColumns = array();
370
371
        // query whether or not an array has been specified in the configuration
372
        if ($this->getConfiguration()->hasParam(ConfigurationKeys::CLEAN_UP_EMPTY_COLUMNS)) {
373
            $cleanUpColumns = $this->getConfiguration()->getParam(ConfigurationKeys::CLEAN_UP_EMPTY_COLUMNS);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->getConfiguration(...LEAN_UP_EMPTY_COLUMNS); of type string adds the type string to the return on line 377 which is incompatible with the return type declared by the interface TechDivision\Import\Subj...face::getCleanUpColumns of type array.
Loading history...
374
        }
375
376
        // return the array with the column names
377
        return $cleanUpColumns;
378
    }
379
380
    /**
381
     * Return's the entity type code to be used.
382
     *
383
     * @return string The entity type code to be used
384
     */
385 18
    public function getEntityTypeCode()
386
    {
387 18
        return $this->entityTypeCodeMapper->map(parent::getEntityTypeCode());
388
    }
389
}
390