Completed
Push — master ( 8971e9...2784a4 )
by
unknown
12:30
created

Relational::getManufacturer()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 6
ccs 1
cts 1
cp 1
rs 9.4285
cc 2
eloc 3
nc 2
nop 0
crap 2
1
<?php
2
3
namespace SpeckCatalog\Model\Choice;
4
5
use SpeckCatalog\Model\AbstractModel;
6
use SpeckCatalog\Model\Choice as Base;
7
8
class Relational extends Base
9
{
10
    protected $parent;
11
    protected $product;
12
    protected $options;
13
    protected $parentOptions;
14
    protected $addPrice;
15
16
    public function getKey()
17
    {
18
        return $this->choiceId;
19
    }
20
21
    public function getPrice()
22
    {
23
        if ($this->has('product')) {
24
            return $this->getProduct()->getPrice();
25
        }
26
        return 0;
27
    }
28
29 4
    public function getRecursivePrice($parentProductPrice = 0, $retailPrice = false)
30
    {
31 4
        if ($this->has('product')) {
32 1
            $productPrice = $this->getProduct()->getRecursivePrice($retailPrice);
33 1
            return $productPrice + $this->getAdjustmentPrice($productPrice);
34
        } else {
35 3
            $adjustedPrice = $this->getAdjustedPrice($retailPrice);
36 3
            $adjustmentPrice = $adjustedPrice - $parentProductPrice;
37
38 3
            $price = 0;
39 3
            if ($this->has('options')) {
40 3
                foreach ($this->getOptions() as $option) {
41 3
                    $price += $option->getRecursivePrice($adjustedPrice, $retailPrice);
42 3
                }
43 3
            }
44
45 3
            return ($adjustmentPrice + $price) >= -$parentProductPrice
46 3
                ? $adjustmentPrice + $price
47 4
                : -$parentProductPrice;
48
        }
49
    }
50
51 6
    public function getAdjustedPrice($retailPrice = false)
52
    {
53 6
        $parentProductPrice = $this->getParentProductPrice($retailPrice);
54 6
        return $parentProductPrice + $this->getAdjustmentPrice($parentProductPrice);
55
    }
56
57 6
    public function getParentProductPrice($retailPrice = false)
58
    {
59 6
        if ($this->has('parent')) {
60 6
            return $this->getParent()->getAdjustedPrice($retailPrice);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class SpeckCatalog\Model\AbstractModel as the method getAdjustedPrice() does only exist in the following sub-classes of SpeckCatalog\Model\AbstractModel: SpeckCatalog\Model\Choice\Relational, SpeckCatalog\Model\Option\Relational. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
61
        }
62
        return 0;
63
    }
64
65
66 8
    public function getAdjustmentPrice($parentPrice)
67
    {
68 8
        if ($this->getPriceDiscountFixed()) {
69 8
            return -$this->getPriceDiscountFixed();
70 8
        } elseif ($this->getPriceDiscountPercent()) {
71 8
            return $parentPrice * -($this->getPriceDiscountPercent()/100);
72 8
        } elseif ($this->getPriceNoCharge()) {
73 8
            return -$parentPrice;
74 8
        } elseif ($this->getPriceOverrideFixed()) {
75 8
            return $this->getPriceOverrideFixed() - $parentPrice;
76
        } else {
77 8
            return 0;
78
        }
79
    }
80
81
82
    public function getItemNumber()
83
    {
84
        if ($this->getProduct()) {
85
            return $this->getProduct()->getItemNumber();
86
        }
87
    }
88
89
90
    public function getProductTypeId()
91
    {
92
        if ($this->getProduct()) {
93
            return $this->getProduct()->getProductTypeId();
94
        }
95
    }
96
97
    public function getManufacturer()
98
    {
99
        if ($this->getProduct()) {
100
            return $this->getProduct()->getManufacturer();
101 7
        }
102
    }
103 7
104
105
    /**
106
     * @return product
107
     */
108
    public function getProduct()
109
    {
110 3
        return $this->product;
111
    }
112 3
113 3
    /**
114
     * @param $product
115
     * @return self
116
     */
117
    public function setProduct($product)
118
    {
119 3
        $this->product = $product;
120
        return $this;
121 3
    }
122
123
    /**
124 4
     * @return options
125
     */
126 4
    public function getOptions()
127 4
    {
128 4
        return $this->options;
129
    }
130
131
    public function addOption($option)
132
    {
133
        $option->setParent($this);
134
        $this->options[] = $option;
135
        return $this;
136
    }
137
138
    /**
139
     * @param $options
140
     * @return self
141
     */
142
    public function setOptions($options)
143
    {
144
        $this->options = array();
145
146
        foreach ($options as $option) {
147
            $this->addOption($option);
148
        }
149
150
        return $this;
151
    }
152
153
    /**
154
     * @return parentOptions
155
     */
156
    public function getParentOptions()
157
    {
158
        return $this->parentOptions;
159
    }
160
161
    /**
162
     * @param $parentOptions
163
     * @return self
164 3
     */
165
    public function setParentOptions($parentOptions)
166 3
    {
167
        $this->parentOptions = $parentOptions;
168 3
        return $this;
169 2
    }
170 2
171
    public function getAddPrice($retailPrice = false)
172 3
    {
173
        if ($this->addPrice) {
174
            return $this->addPrice;
175
        } elseif ($this->has('product')) {
176
            $productPrice = $this->getProduct()->getPrice($retailPrice);
177
            return $productPrice + $this->getAdjustmentPrice($productPrice);
178
        } else {
179
            return $this->getAdjustedPrice($retailPrice) - $this->getParentProductPrice($retailPrice);
180
        }
181
    }
182
183
    /**
184
     * @param $addPrice
185
     * @return self
186
     */
187
    public function setAddPrice($addPrice)
188
    {
189 6
        $this->addPrice = $addPrice;
190
        return $this;
191 6
    }
192
193
    /**
194
     * @return parent
195
     */
196
    public function getParent()
197
    {
198 6
        return $this->parent;
199
    }
200 6
201 6
    /**
202 6
     * @param $parent
203
     * @return self
204
     */
205
    public function setParent(AbstractModel $parent)
206
    {
207
        $this->parent = $parent;
208
        $this->setOptionId($parent->getOptionId());
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class SpeckCatalog\Model\AbstractModel as the method getOptionId() does only exist in the following sub-classes of SpeckCatalog\Model\AbstractModel: SpeckCatalog\Model\Choice, SpeckCatalog\Model\Choice\Relational, SpeckCatalog\Model\Option, SpeckCatalog\Model\OptionImage, SpeckCatalog\Model\OptionImage\Relational, SpeckCatalog\Model\Option\Relational. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
209
        return $this;
210
    }
211
212
    public function __toString()
213
    {
214
        if ($this->getOverrideName()) {
215
            $str = $this->getOverrideName();
216
        } elseif ($this->has('product')) {
217
            $str = $this->getProduct()->getName();
218
        } else {
219
            $str = 'Unnamed Choice';
220
        }
221
        return $str;
222
    }
223
}
224