Completed
Pull Request — master (#76)
by Tim
05:58 queued 03:58
created

LastEntityIdObserver::getProductBunchProcessor()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 4
Ratio 100 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 4
loc 4
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
3
/**
4
 * TechDivision\Import\Product\Observers\LastEntityIdObserver
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\Observers;
22
23
use TechDivision\Import\Product\Utils\ColumnKeys;
24
use TechDivision\Import\Product\Utils\MemberNames;
25
use TechDivision\Import\Product\Services\ProductBunchProcessorInterface;
26
27
/**
28
 * Observer that pre-loads the entity ID of the product with the SKU found in the CSV file.
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
34
 * @link      http://www.techdivision.com
35
 */
36 View Code Duplication
class LastEntityIdObserver extends AbstractProductImportObserver
0 ignored issues
show
Duplication introduced by
This class 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...
37
{
38
39
    /**
40
     * The product bunch processor instance.
41
     *
42
     * @var \TechDivision\Import\Product\Services\ProductBunchProcessorInterface
43
     */
44
    protected $productBunchProcessor;
45
46
    /**
47
     * Initialize the observer with the passed product bunch processor instance.
48
     *
49
     * @param \TechDivision\Import\Product\Services\ProductBunchProcessorInterface $productBunchProcessor The product bunch processor instance
50
     */
51
    public function __construct(ProductBunchProcessorInterface $productBunchProcessor)
52
    {
53
        $this->productBunchProcessor = $productBunchProcessor;
54
    }
55
56
    /**
57
     * Return's the product bunch processor instance.
58
     *
59
     * @return \TechDivision\Import\Product\Services\ProductBunchProcessorInterface The product bunch processor instance
60
     */
61
    protected function getProductBunchProcessor()
62
    {
63
        return $this->productBunchProcessor;
64
    }
65
66
    /**
67
     * Process the observer's business logic.
68
     *
69
     * @return array The processed row
70
     * @throws \Exception Is thrown, if the product with the SKU can not be loaded
71
     */
72
    protected function process()
73
    {
74
75
        // query whether or not, we've found a new SKU => means we've found a new product
76
        if ($this->isLastSku($sku = $this->getValue(ColumnKeys::SKU))) {
77
            return;
78
        }
79
80
        // set the entity ID for the product with the passed SKU
81
        if ($product = $this->loadProduct($sku)) {
82
            $this->setIds($product);
83
        } else {
84
            // initialize the error message
85
            $message = sprintf('Can\'t load entity ID for product with SKU %s', $sku);
86
            // load the subject
87
            $subject = $this->getSubject();
88
            // query whether or not debug mode has been enabled
89
            if ($subject->isDebugMode()) {
90
                $subject->getSystemLogger()->warning($subject->appendExceptionSuffix($message));
91
            } else {
92
                throw new \Exception($message);
93
            }
94
        }
95
    }
96
97
    /**
98
     * Temporarily persist's the IDs of the passed product.
99
     *
100
     * @param array $product The product to temporarily persist the IDs for
101
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
102
    protected function setIds(array $product)
103
    {
104
        $this->setLastEntityId($product[MemberNames::ENTITY_ID]);
105
    }
106
107
    /**
108
     * Set's the ID of the product that has been created recently.
109
     *
110
     * @param string $lastEntityId The entity ID
111
     *
112
     * @return void
113
     */
114
    protected function setLastEntityId($lastEntityId)
115
    {
116
        $this->getSubject()->setLastEntityId($lastEntityId);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface TechDivision\Import\Subjects\SubjectInterface as the method setLastEntityId() does only exist in the following implementations of said interface: TechDivision\Import\Plugins\ExportableSubjectImpl, TechDivision\Import\Prod...\AbstractProductSubject, TechDivision\Import\Product\Subjects\BunchSubject, TechDivision\Import\Subjects\ExportableTraitImpl.

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...
117
    }
118
119
    /**
120
     * Load's and return's the product with the passed SKU.
121
     *
122
     * @param string $sku The SKU of the product to load
123
     *
124
     * @return array The product
125
     */
126
    protected function loadProduct($sku)
127
    {
128
        return $this->getProductBunchProcessor()->loadProduct($sku);
129
    }
130
}
131