Completed
Push — 13.x ( aea664...416f31 )
by Tim
02:09
created

ProductWebsiteObserver::setCode()   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
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
            } catch (\RuntimeException $re) {
126
                $this->getSystemLogger()->debug($re->getMessage());
127
            }
128
        }
129
    }
130
131
    /**
132
     * Prepare the attributes of the entity that has to be persisted.
133
     *
134
     * @return array The prepared attributes
135
     */
136
    protected function prepareAttributes()
137
    {
138
139
        // load the ID of the product that has been created recently
140
        $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...
141
142
        // load the website ID to relate the product with
143
        $websiteId = $this->getStoreWebsiteIdByCode($this->getCode());
144
145
        // return the prepared product
146
        return $this->initializeEntity(
147
            array(
148
                MemberNames::PRODUCT_ID => $lastEntityId,
149
                MemberNames::WEBSITE_ID => $websiteId
150
            )
151
        );
152
    }
153
154
    /**
155
     * Initialize the product website with the passed attributes and returns an instance.
156
     *
157
     * @param array $attr The product website attributes
158
     *
159
     * @return array The initialized product website
160
     * @throws \RuntimeException Is thrown, if the attributes can not be initialized
161
     */
162
    protected function initializeProductWebsite(array $attr)
163
    {
164
        return $attr;
165
    }
166
167
    /**
168
     * Persist's the passed product website data and return's the ID.
169
     *
170
     * @param array $productWebsite The product website data to persist
171
     *
172
     * @return void
173
     */
174
    protected function persistProductWebsite($productWebsite)
175
    {
176
        $this->getProductBunchProcessor()->persistProductWebsite($productWebsite);
177
    }
178
179
    /**
180
     * Return's the store website for the passed code.
181
     *
182
     * @param string $code The code of the store website to return the ID for
183
     *
184
     * @return integer The store website ID
185
     */
186
    protected function getStoreWebsiteIdByCode($code)
187
    {
188
        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...
189
    }
190
}
191