Completed
Pull Request — master (#65)
by
unknown
09:03
created

CartCondition::applyCondition()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php namespace Darryldecode\Cart;
2
use Darryldecode\Cart\Exceptions\InvalidConditionException;
3
use Darryldecode\Cart\Helpers\Helpers;
4
use Darryldecode\Cart\Validators\CartConditionValidator;
5
6
/**
7
 * Created by PhpStorm.
8
 * User: darryl
9
 * Date: 1/15/2015
10
 * Time: 9:02 PM
11
 */
12
13
class CartCondition {
14
15
    /**
16
     * @var array
17
     */
18
    private $args;
19
20
    /**
21
     * the parsed raw value of the condition
22
     *
23
     * @var
24
     */
25
    private $parsedRawValue;
26
27
    /**
28
     * @param array $args (name, type, target, value)
29
     * @throws InvalidConditionException
30
     */
31
    public function __construct(array $args)
32
    {
33
        $this->args = $args;
34
35
        if( Helpers::isMultiArray($args) )
36
        {
37
            Throw new InvalidConditionException('Multi dimensional array is not supported.');
38
        }
39
        else
40
        {
41
            $this->validate($this->args);
42
        }
43
    }
44
45
    /**
46
     * the target of where the condition is applied
47
     *
48
     * @return mixed
49
     */
50
    public function getTarget()
51
    {
52
        return $this->args['target'];
53
    }
54
55
    /**
56
     * the name of the condition
57
     *
58
     * @return mixed
59
     */
60
    public function getName()
61
    {
62
        return $this->args['name'];
63
    }
64
65
    /**
66
     * the type of the condition
67
     *
68
     * @return mixed
69
     */
70
    public function getType()
71
    {
72
        return $this->args['type'];
73
    }
74
75
    /**
76
     * get the additional attributes of a condition
77
     *
78
     * @return array
79
     */
80
    public function getAttributes()
81
    {
82
        return (isset($this->args['attributes'])) ? $this->args['attributes'] : array();
83
    }
84
85
    /**
86
     * the value of this the condition
87
     *
88
     * @return mixed
89
     */
90
    public function getValue()
91
    {
92
        return $this->args['value'];
93
    }
94
95
    /**
96
     * the order to apply this condition. If no argument order is applied defaults to 0
97
     *
98
     * @return Integer
99
     */
100
    public function getOrder()
101
    {
102
        return isset($this->args['order']) && is_numeric($this->args['order']) ? (int)$this->args['order'] : 0;
103
    }
104
105
    /**
106
     * apply condition to total or subtotal
107
     *
108
     * @param $totalOrSubTotalOrPrice
109
     * @return float
110
     */
111
    public function applyCondition($totalOrSubTotalOrPrice)
112
    {
113
        return $this->apply($totalOrSubTotalOrPrice, $this->getValue());
114
    }
115
116
    /**
117
     * get the calculated value of this condition supplied by the subtotal|price
118
     *
119
     * @param $totalOrSubTotalOrPrice
120
     * @return mixed
121
     */
122
    public function getCalculatedValue($totalOrSubTotalOrPrice)
123
    {
124
        $this->apply($totalOrSubTotalOrPrice, $this->getValue());
125
126
        return $this->parsedRawValue;
127
    }
128
129
    /**
130
     * apply condition
131
     *
132
     * @param $totalOrSubTotalOrPrice
133
     * @param $conditionValue
134
     * @return float
135
     */
136
    protected function apply($totalOrSubTotalOrPrice, $conditionValue)
137
    {
138
        // if value has a percentage sign on it, we will get first
139
        // its percentage then we will evaluate again if the value
140
        // has a minus or plus sign so we can decide what to do with the
141
        // percentage, whether to add or subtract it to the total/subtotal/price
142
        // if we can't find any plus/minus sign, we will assume it as plus sign
143
        if( $this->valueIsPercentage($conditionValue) )
144
        {
145
            if( $this->valueIsToBeSubtracted($conditionValue) )
146
            {
147
                $value = Helpers::normalizePrice( $this->cleanValue($conditionValue) );
148
149
                $this->parsedRawValue = $totalOrSubTotalOrPrice * ($value / 100);
150
151
                $result = floatval($totalOrSubTotalOrPrice - $this->parsedRawValue);
152
            }
153
            else if ( $this->valueIsToBeAdded($conditionValue) )
154
            {
155
                $value = Helpers::normalizePrice( $this->cleanValue($conditionValue) );
156
157
                $this->parsedRawValue = $totalOrSubTotalOrPrice * ($value / 100);
158
159
                $result = floatval($totalOrSubTotalOrPrice + $this->parsedRawValue);
160
            }
161
            else
162
            {
163
                $value = Helpers::normalizePrice($conditionValue);
164
165
                $this->parsedRawValue = $totalOrSubTotalOrPrice * ($value / 100);
166
167
                $result = floatval($totalOrSubTotalOrPrice + $this->parsedRawValue);
168
            }
169
        }
170
171
        // if the value has no percent sign on it, the operation will not be a percentage
172
        // next is we will check if it has a minus/plus sign so then we can just deduct it to total/subtotal/price
173
        else
174
        {
175
            if( $this->valueIsToBeSubtracted($conditionValue) )
176
            {
177
                $this->parsedRawValue = Helpers::normalizePrice( $this->cleanValue($conditionValue) );
178
179
                $result = floatval($totalOrSubTotalOrPrice - $this->parsedRawValue);
180
            }
181
            else if ( $this->valueIsToBeAdded($conditionValue) )
182
            {
183
                $this->parsedRawValue = Helpers::normalizePrice( $this->cleanValue($conditionValue) );
184
185
                $result = floatval($totalOrSubTotalOrPrice + $this->parsedRawValue);
186
            }
187
            else
188
            {
189
                $this->parsedRawValue = Helpers::normalizePrice($conditionValue);
190
191
                $result = floatval($totalOrSubTotalOrPrice + $this->parsedRawValue);
192
            }
193
        }
194
195
        // Do not allow items with negative prices.
196
        return $result < 0 ? 0.00 : $result;
197
    }
198
199
    /**
200
     * check if value is a percentage
201
     *
202
     * @param $value
203
     * @return bool
204
     */
205
    protected function valueIsPercentage($value)
206
    {
207
        return (preg_match('/%/', $value) == 1);
208
    }
209
210
    /**
211
     * check if value is a subtract
212
     *
213
     * @param $value
214
     * @return bool
215
     */
216
    protected function valueIsToBeSubtracted($value)
217
    {
218
        return (preg_match('/\-/', $value) == 1);
219
    }
220
221
    /**
222
     * check if value is to be added
223
     *
224
     * @param $value
225
     * @return bool
226
     */
227
    protected function valueIsToBeAdded($value)
228
    {
229
        return (preg_match('/\+/', $value) == 1);
230
    }
231
232
    /**
233
     * removes some arithmetic signs (%,+,-) only
234
     *
235
     * @param $value
236
     * @return mixed
237
     */
238
    protected function cleanValue($value)
239
    {
240
        return str_replace(array('%','-','+'),'',$value);
241
    }
242
243
    /**
244
     * validates condition arguments
245
     *
246
     * @param $args
247
     * @throws InvalidConditionException
248
     */
249 View Code Duplication
    protected function validate($args)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
250
    {
251
        $rules = array(
252
            'name' => 'required',
253
            'type' => 'required',
254
            'target' => 'required',
255
            'value' => 'required',
256
        );
257
258
        $validator = CartConditionValidator::make($args, $rules);
259
260
        if( $validator->fails() )
261
        {
262
            throw new InvalidConditionException($validator->messages()->first());
263
        }
264
    }
265
}