Completed
Push — master ( 226c3f...287fce )
by Tim
10s
created

ProductWebsiteObserver   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 156
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 17.5%

Importance

Changes 0
Metric Value
wmc 13
lcom 1
cbo 3
dl 0
loc 156
ccs 7
cts 40
cp 0.175
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getProductBunchProcessor() 0 4 1
A setCode() 0 4 1
A getCode() 0 4 1
A initializeProductWebsite() 0 4 1
A persistProductWebsite() 0 4 1
A getStoreWebsiteIdByCode() 0 4 1
B process() 0 31 5
A prepareAttributes() 0 17 1
1
<?php
2
3
/**
4
 * TechDivision\Import\Product\Observers\ProductWebsiteObserver
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\Services\ProductBunchProcessorInterface;
24
use TechDivision\Import\Product\Utils\ColumnKeys;
25
use TechDivision\Import\Product\Utils\MemberNames;
26
27
/**
28
 * Observer that creates/updates the product's website relations.
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
class ProductWebsiteObserver extends AbstractProductImportObserver
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 1
    public function __construct(ProductBunchProcessorInterface $productBunchProcessor)
52
    {
53 1
        $this->productBunchProcessor = $productBunchProcessor;
54 1
    }
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
     * The actual website code that has to be processed.
68
     *
69
     * @var string
70
     */
71
    protected $code;
72
73
    /**
74
     * Set's the actual website code that has to be processed.
75
     *
76
     * @param string $code The website code
77
     *
78
     * @return void
79
     */
80
    protected function setCode($code)
81
    {
82
        $this->code = $code;
83
    }
84
85
    /**
86
     * Return's the webiste code that has to be processed.
87
     *
88
     * @return string The website code
89
     */
90
    protected function getCode()
91
    {
92
        return $this->code;
93
    }
94
95
    /**
96
     * Process the observer's business logic.
97
     *
98
     * @return array The processed row
99
     */
100 1
    protected function process()
101
    {
102
103
        // query whether or not, we've found a new SKU => means we've found a new product
104 1
        if ($this->hasBeenProcessed($this->getValue(ColumnKeys::SKU))) {
105
            return;
106
        }
107
108
        // query whether or not, product => website relations has been specified
109 1
        if (!$this->hasValue(ColumnKeys::PRODUCT_WEBSITES)) {
110 1
            return;
111
        }
112
113
        // append the product => website relations found
114
        $codes = $this->getValue(ColumnKeys::PRODUCT_WEBSITES, array(), array($this, 'explode'));
115
        foreach ($codes as $code) {
116
            // set the code of the website that has to be processed
117
            $this->setCode($code);
118
            // prepare the product website relation attributes
119
            $attr = $this->prepareAttributes();
120
121
            try {
122
                // create the product website relation
123
                $productWebsite = $this->initializeProductWebsite($attr);
124
                $this->persistProductWebsite($productWebsite);
125
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
126
            } catch (\RuntimeException $re) {
127
                $this->getSystemLogger()->debug($re->getMessage());
128
            }
129
        }
130
    }
131
132
    /**
133
     * Prepare the attributes of the entity that has to be persisted.
134
     *
135
     * @return array The prepared attributes
136
     */
137
    protected function prepareAttributes()
138
    {
139
140
        // load the ID of the product that has been created recently
141
        $lastEntityId = $this->getLastEntityId();
0 ignored issues
show
Deprecated Code introduced by
The method TechDivision\Import\Obse...rver::getLastEntityId() has been deprecated with message: Will be removed with version 1.0.0, use subject method instead

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
142
143
        // load the website ID to relate the product with
144
        $websiteId = $this->getStoreWebsiteIdByCode($this->getCode());
145
146
        // return the prepared product
147
        return $this->initializeEntity(
148
            array(
149
                MemberNames::PRODUCT_ID => $lastEntityId,
150
                MemberNames::WEBSITE_ID => $websiteId
151
            )
152
        );
153
    }
154
155
    /**
156
     * Initialize the product website with the passed attributes and returns an instance.
157
     *
158
     * @param array $attr The product website attributes
159
     *
160
     * @return array The initialized product website
161
     * @throws \RuntimeException Is thrown, if the attributes can not be initialized
162
     */
163
    protected function initializeProductWebsite(array $attr)
164
    {
165
        return $attr;
166
    }
167
168
    /**
169
     * Persist's the passed product website data and return's the ID.
170
     *
171
     * @param array $productWebsite The product website data to persist
172
     *
173
     * @return void
174
     */
175
    protected function persistProductWebsite($productWebsite)
176
    {
177
        $this->getProductBunchProcessor()->persistProductWebsite($productWebsite);
178
    }
179
180
    /**
181
     * Return's the store website for the passed code.
182
     *
183
     * @param string $code The code of the store website to return the ID for
184
     *
185
     * @return integer The store website ID
186
     */
187
    protected function getStoreWebsiteIdByCode($code)
188
    {
189
        return $this->getSubject()->getStoreWebsiteIdByCode($code);
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 getStoreWebsiteIdByCode() does only exist in the following implementations of said interface: TechDivision\Import\Prod...\AbstractProductSubject, TechDivision\Import\Product\Subjects\BunchSubject.

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...
190
    }
191
}
192