Completed
Push — master ( 970228...838402 )
by Paweł
29s
created

Product::hasTaxon()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sylius\Component\Core\Model;
13
14
use Doctrine\Common\Collections\ArrayCollection;
15
use Doctrine\Common\Collections\Collection;
16
use Doctrine\Common\Collections\Criteria;
17
use Sylius\Component\Channel\Model\ChannelInterface as BaseChannelInterface;
18
use Sylius\Component\Product\Model\Product as BaseProduct;
19
use Sylius\Component\Review\Model\ReviewInterface;
20
use Sylius\Component\Taxonomy\Model\TaxonInterface as BaseTaxonInterface;
21
22
/**
23
 * @author Paweł Jędrzejewski <[email protected]>
24
 * @author Gonzalo Vilaseca <[email protected]>
25
 * @author Anna Walasek <[email protected]>
26
 */
27
class Product extends BaseProduct implements ProductInterface, ReviewableProductInterface
28
{
29
    /**
30
     * @var string
31
     */
32
    protected $variantSelectionMethod = self::VARIANT_SELECTION_CHOICE;
33
34
    /**
35
     * @var Collection|ProductTaxonInterface[]
36
     */
37
    protected $productTaxons;
38
39
    /**
40
     * @var Collection|ChannelInterface[]
41
     */
42
    protected $channels;
43
44
    /**
45
     * @var BaseTaxonInterface
46
     */
47
    protected $mainTaxon;
48
49
    /**
50
     * @var Collection|ReviewInterface[]
51
     */
52
    protected $reviews;
53
54
    /**
55
     * @var float
56
     */
57
    protected $averageRating = 0;
58
59
    /**
60
     * @var Collection|ImageInterface[]
61
     */
62
    protected $images;
63
64
    public function __construct()
65
    {
66
        parent::__construct();
67
68
        $this->productTaxons = new ArrayCollection();
69
        $this->channels = new ArrayCollection();
70
        $this->reviews = new ArrayCollection();
71
        $this->images = new ArrayCollection();
72
    }
73
74
    /**
75
     * {@inheritdoc}
76
     */
77
    public function getVariantSelectionMethod()
78
    {
79
        return $this->variantSelectionMethod;
80
    }
81
82
    /**
83
     * {@inheritdoc}
84
     */
85
    public function setVariantSelectionMethod($variantSelectionMethod)
86
    {
87
        if (!in_array($variantSelectionMethod, [self::VARIANT_SELECTION_CHOICE, self::VARIANT_SELECTION_MATCH])) {
88
            throw new \InvalidArgumentException(sprintf('Wrong variant selection method "%s" given.', $variantSelectionMethod));
89
        }
90
91
        $this->variantSelectionMethod = $variantSelectionMethod;
92
    }
93
94
    /**
95
     * {@inheritdoc}
96
     */
97
    public function isVariantSelectionMethodChoice()
98
    {
99
        return self::VARIANT_SELECTION_CHOICE === $this->variantSelectionMethod;
100
    }
101
102
    /**
103
     * {@inheritdoc}
104
     */
105
    public function getVariantSelectionMethodLabel()
106
    {
107
        $labels = self::getVariantSelectionMethodLabels();
108
109
        return $labels[$this->variantSelectionMethod];
110
    }
111
112
    /**
113
     * {@inheritdoc}
114
     */
115
    public function getProductTaxons()
116
    {
117
        return $this->productTaxons;
118
    }
119
120
    /**
121
     * {@inheritdoc}
122
     */
123
    public function addProductTaxon(ProductTaxonInterface $productTaxon)
124
    {
125
        if (!$this->hasProductTaxon($productTaxon)) {
126
            $this->productTaxons->add($productTaxon);
127
            $productTaxon->setProduct($this);
128
        }
129
    }
130
131
    /**
132
     * {@inheritdoc}
133
     */
134
    public function removeProductTaxon(ProductTaxonInterface $productTaxon)
135
    {
136
        if ($this->hasProductTaxon($productTaxon)) {
137
            $this->productTaxons->removeElement($productTaxon);
138
        }
139
    }
140
141
    /**
142
     * {@inheritdoc}
143
     */
144
    public function hasProductTaxon(ProductTaxonInterface $productTaxon)
145
    {
146
        return $this->productTaxons->contains($productTaxon);
147
    }
148
149
    /**
150
     * {@inheritdoc}
151
     */
152
    public function getTaxons()
153
    {
154
        return $this->productTaxons->map(function (ProductTaxonInterface $productTaxon) {
155
            return $productTaxon->getTaxon();
156
        });
157
    }
158
159
    /**
160
     * {@inheritdoc}
161
     */
162
    public function hasTaxon(TaxonInterface $taxon)
163
    {
164
        return $this->getTaxons()->contains($taxon);
165
    }
166
167
    /**
168
     * {@inheritdoc}
169
     */
170
    public function getChannels()
171
    {
172
        return $this->channels;
173
    }
174
175
    /**
176
     * {@inheritdoc}
177
     */
178
    public function addChannel(BaseChannelInterface $channel)
179
    {
180
        if (!$this->hasChannel($channel)) {
181
            $this->channels->add($channel);
182
        }
183
    }
184
185
    /**
186
     * {@inheritdoc}
187
     */
188
    public function removeChannel(BaseChannelInterface $channel)
189
    {
190
        if ($this->hasChannel($channel)) {
191
            $this->channels->removeElement($channel);
192
        }
193
    }
194
195
    /**
196
     * {@inheritdoc}
197
     */
198
    public function hasChannel(BaseChannelInterface $channel)
199
    {
200
        return $this->channels->contains($channel);
201
    }
202
203
    /**
204
     * {@inheritdoc}
205
     */
206
    public static function getVariantSelectionMethodLabels()
207
    {
208
        return [
209
            self::VARIANT_SELECTION_CHOICE => 'sylius.ui.variant_choice',
210
            self::VARIANT_SELECTION_MATCH => 'sylius.ui.options_matching',
211
        ];
212
    }
213
214
    /**
215
     * {@inheritdoc}
216
     */
217
    public function getShortDescription()
218
    {
219
        return $this->getTranslation()->getShortDescription();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Sylius\Component\Resourc...el\TranslationInterface as the method getShortDescription() does only exist in the following implementations of said interface: Sylius\Component\Core\Model\ProductTranslation.

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...
220
    }
221
222
    /**
223
     * {@inheritdoc}
224
     */
225
    public function setShortDescription($shortDescription)
226
    {
227
        $this->getTranslation()->setShortDescription($shortDescription);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Sylius\Component\Resourc...el\TranslationInterface as the method setShortDescription() does only exist in the following implementations of said interface: Sylius\Component\Core\Model\ProductTranslation.

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...
228
    }
229
230
    /**
231
     * {@inheritdoc}
232
     */
233
    public function getMainTaxon()
234
    {
235
        return $this->mainTaxon;
236
    }
237
238
    /**
239
     * {@inheritdoc}
240
     */
241
    public function setMainTaxon(TaxonInterface $mainTaxon = null)
242
    {
243
        $this->mainTaxon = $mainTaxon;
244
    }
245
246
    /**
247
     * {@inheritdoc}
248
     */
249
    public function getReviews()
250
    {
251
        return $this->reviews;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->reviews; of type Doctrine\Common\Collecti...Model\ReviewInterface[] adds the type Doctrine\Common\Collections\Collection to the return on line 251 which is incompatible with the return type declared by the interface Sylius\Component\Review\...leInterface::getReviews of type Sylius\Component\Review\Model\ReviewInterface[].
Loading history...
252
    }
253
254
    /**
255
     * {@inheritdoc}
256
     */
257
    public function getAcceptedReviews()
258
    {
259
        $criteria = Criteria::create()
260
            ->where(Criteria::expr()->eq('status', ReviewInterface::STATUS_ACCEPTED))
261
        ;
262
263
        return $this->reviews->matching($criteria);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Doctrine\Common\Collections\Collection as the method matching() does only exist in the following implementations of said interface: Doctrine\Common\Collections\ArrayCollection, Doctrine\ORM\LazyCriteriaCollection, Doctrine\ORM\PersistentCollection.

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...
264
    }
265
266
    /**
267
     * {@inheritdoc}
268
     */
269
    public function addReview(ReviewInterface $review)
270
    {
271
        $this->reviews->add($review);
272
    }
273
274
    /**
275
     * {@inheritdoc}
276
     */
277
    public function removeReview(ReviewInterface $review)
278
    {
279
        $this->reviews->remove($review);
0 ignored issues
show
Documentation introduced by
$review is of type object<Sylius\Component\...\Model\ReviewInterface>, but the function expects a string|integer.

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...
280
    }
281
282
    /**
283
     * {@inheritdoc}
284
     */
285
    public function getAverageRating()
286
    {
287
        return $this->averageRating;
288
    }
289
290
    /**
291
     * {@inheritdoc}
292
     */
293
    public function setAverageRating($averageRating)
294
    {
295
        $this->averageRating = $averageRating;
296
    }
297
298
    /**
299
     * {@inheritdoc}
300
     */
301
    public function getImages()
302
    {
303
        return $this->images;
304
    }
305
306
    /**
307
     * {@inheritdoc}
308
     */
309
    public function getImagesByType($type)
310
    {
311
        return $this->images->filter(function (ImageInterface $image) use ($type) {
312
            return $type === $image->getType();
313
        });
314
    }
315
316
    /**
317
     * {@inheritdoc}
318
     */
319
    public function hasImages()
320
    {
321
        return !$this->images->isEmpty();
322
    }
323
324
    /**
325
     * {@inheritdoc}
326
     */
327
    public function hasImage(ImageInterface $image)
328
    {
329
        return $this->images->contains($image);
330
    }
331
332
    /**
333
     * {@inheritdoc}
334
     */
335
    public function addImage(ImageInterface $image)
336
    {
337
        $image->setOwner($this);
338
        $this->images->add($image);
339
    }
340
341
    /**
342
     * {@inheritdoc}
343
     */
344
    public function removeImage(ImageInterface $image)
345
    {
346
        if ($this->hasImage($image)) {
347
            $image->setOwner(null);
348
            $this->images->removeElement($image);
349
        }
350
    }
351
352
    /**
353
     * {@inheritdoc}
354
     */
355
    protected function createTranslation()
356
    {
357
        return new ProductTranslation();
358
    }
359
}
360