Completed
Push — 19.x ( 82277b...b16137 )
by Tim
02:28
created

ProductWebsiteObserver::deleteProductWebsite()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 3
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
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
use TechDivision\Import\Product\Utils\ConfigurationKeys;
27
28
/**
29
 * Observer that creates/updates the product's website relations.
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
35
 * @link      http://www.techdivision.com
36
 */
37
class ProductWebsiteObserver extends AbstractProductImportObserver
38
{
39
40
    /**
41
     * The product bunch processor instance.
42
     *
43
     * @var \TechDivision\Import\Product\Services\ProductBunchProcessorInterface
44
     */
45
    protected $productBunchProcessor;
46
47
    /**
48
     * Initialize the observer with the passed product bunch processor instance.
49
     *
50
     * @param \TechDivision\Import\Product\Services\ProductBunchProcessorInterface $productBunchProcessor The product bunch processor instance
51
     */
52 1
    public function __construct(ProductBunchProcessorInterface $productBunchProcessor)
53
    {
54 1
        $this->productBunchProcessor = $productBunchProcessor;
55 1
    }
56
57
    /**
58
     * Return's the product bunch processor instance.
59
     *
60
     * @return \TechDivision\Import\Product\Services\ProductBunchProcessorInterface The product bunch processor instance
61
     */
62
    protected function getProductBunchProcessor()
63
    {
64
        return $this->productBunchProcessor;
65
    }
66
67
    /**
68
     * The actual website code that has to be processed.
69
     *
70
     * @var string
71
     */
72
    protected $code;
73
74
    /**
75
     * Set's the actual website code that has to be processed.
76
     *
77
     * @param string $code The website code
78
     *
79
     * @return void
80
     */
81
    protected function setCode($code)
82
    {
83
        $this->code = $code;
84
    }
85
86
    /**
87
     * Return's the webiste code that has to be processed.
88
     *
89
     * @return string The website code
90
     */
91
    protected function getCode()
92
    {
93
        return $this->code;
94
    }
95
96
    /**
97
     * Process the observer's business logic.
98
     *
99
     * @return array The processed row
100
     */
101 1
    protected function process()
102
    {
103
104
        // query whether or not, we've found a new SKU => means we've found a new product
105 1
        if ($this->hasBeenProcessed($sku = $this->getValue(ColumnKeys::SKU))) {
106
            return;
107
        }
108
109
        // load the product => website relations
110 1
        $codes = $this->getValue(ColumnKeys::PRODUCT_WEBSITES, array(), array($this, 'explode'));
111
112
        // query whether or not we've to clean up existing website product relations
113 1
        if ($this->getSubject()->getConfiguration()->hasParam(ConfigurationKeys::CLEAN_UP_WEBSITE_PRODUCT_RELATIONS) &&
114
            $this->getSubject()->getConfiguration()->getParam(ConfigurationKeys::CLEAN_UP_WEBSITE_PRODUCT_RELATIONS)
115
        ) {
116
117
            // initialize the array for the website IDs
118
            $websiteIds = array();
119
120
            // prepare the website IDs
121
            foreach ($codes as $code) {
122
                $websiteIds[$code] = $this->getStoreWebsiteIdByCode($code);
123
            }
124
125
            // load the available product websites
126
            if ($productWebsites = $this->loadProductWebsitesBySku($sku)) {
127
                // iterate over the products websites
128
                foreach ($productWebsites as $productWebsite) {
129
                    // if the product websit relation is in the CSV file, do nothing
130
                    if (in_array($productWebsite[MemberNames::WEBSITE_ID], $websiteIds)) {
131
                        continue;
132
                    }
133
134
                    // delete it, because we don't need it any longer
135
                    $this->deleteProductWebsite(
136
                        array(
137
                            MemberNames::PRODUCT_ID => $productWebsite[MemberNames::PRODUCT_ID],
138
                            MemberNames::WEBSITE_ID => $productWebsite[MemberNames::WEBSITE_ID]
139
                        )
140
                    );
141
                }
142
            }
143
        }
144
145
        // append the product => website relations found
146
        foreach ($codes as $code) {
147
            // set the code of the website that has to be processed
148
            $this->setCode($code);
149
            // prepare the product website relation attributes
150
            $attr = $this->prepareAttributes();
151
152
            try {
153
                // create the product website relation
154
                $productWebsite = $this->initializeProductWebsite($attr);
155
                $this->persistProductWebsite($productWebsite);
156
            } catch (\RuntimeException $re) {
157
                $this->getSystemLogger()->debug($re->getMessage());
158
            }
159
        }
160
    }
161
162
    /**
163
     * Prepare the attributes of the entity that has to be persisted.
164
     *
165
     * @return array The prepared attributes
166
     */
167
    protected function prepareAttributes()
168
    {
169
170
        // load the ID of the product that has been created recently
171
        $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...
172
173
        // load the website ID to relate the product with
174
        $websiteId = $this->getStoreWebsiteIdByCode($this->getCode());
175
176
        // return the prepared product
177
        return $this->initializeEntity(
178
            array(
179
                MemberNames::PRODUCT_ID => $lastEntityId,
180
                MemberNames::WEBSITE_ID => $websiteId
181
            )
182
        );
183
    }
184
185
    /**
186
     * Initialize the product website with the passed attributes and returns an instance.
187
     *
188
     * @param array $attr The product website attributes
189
     *
190
     * @return array The initialized product website
191
     * @throws \RuntimeException Is thrown, if the attributes can not be initialized
192
     */
193
    protected function initializeProductWebsite(array $attr)
194
    {
195
        return $attr;
196
    }
197
198
    /**
199
     * Load's and return's the product website relations for the product with the passed SKU.
200
     *
201
     * @param string $sku The SKU to of the product to load the product website relations for
202
     *
203
     * @return array The product website relations
204
     */
205
    protected function loadProductWebsitesBySku($sku)
206
    {
207
        return $this->getProductBunchProcessor()->loadProductWebsitesBySku($sku);
208
    }
209
210
    /**
211
     * Persist's the passed product website data.
212
     *
213
     * @param array $productWebsite The product website data to persist
214
     *
215
     * @return void
216
     */
217
    protected function persistProductWebsite(array $productWebsite)
218
    {
219
        $this->getProductBunchProcessor()->persistProductWebsite($productWebsite);
220
    }
221
222
    /**
223
     * Delete's the passed product website data.
224
     *
225
     * @param array $productWebsite The product website data to delete
226
     *
227
     * @return void
228
     */
229
    protected function deleteProductWebsite(array $productWebsite)
230
    {
231
        $this->getProductBunchProcessor()->deleteProductWebsite($productWebsite);
232
    }
233
234
    /**
235
     * Return's the store website for the passed code.
236
     *
237
     * @param string $code The code of the store website to return the ID for
238
     *
239
     * @return integer The store website ID
240
     */
241
    protected function getStoreWebsiteIdByCode($code)
242
    {
243
        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...
244
    }
245
}
246