CartCondition::applyCondition()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
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
    public $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
     * NOTE: On conditions added to per item bases, target is not needed.
48
     *
49
     * @return mixed
50
     */
51
    public function getTarget()
52
    {
53
        return (isset($this->args['target'])) ? $this->args['target'] : '';
54
    }
55
56
    /**
57
     * the name of the condition
58
     *
59
     * @return mixed
60
     */
61
    public function getName()
62
    {
63
        return $this->args['name'];
64
    }
65
66
    /**
67
     * the type of the condition
68
     *
69
     * @return mixed
70
     */
71
    public function getType()
72
    {
73
        return $this->args['type'];
74
    }
75
76
    /**
77
     * get the additional attributes of a condition
78
     *
79
     * @return array
80
     */
81
    public function getAttributes()
82
    {
83
        return (isset($this->args['attributes'])) ? $this->args['attributes'] : array();
84
    }
85
86
    /**
87
     * the value of this the condition
88
     *
89
     * @return mixed
90
     */
91
    public function getValue()
92
    {
93
        return $this->args['value'];
94
    }
95
96
    /**
97
     * Set the order to apply this condition. If no argument order is applied we return 0 as
98
     * indicator that no assignment has been made
99
     * @param int $order
100
     * @return Integer
101
     */
102
    public function setOrder($order = 1)
103
    {
104
        $this->args['order'] = $order;
105
    }
106
107
    /**
108
     * the order to apply this condition. If no argument order is applied we return 0 as
109
     * indicator that no assignment has been made
110
     *
111
     * @return Integer
112
     */
113
    public function getOrder()
114
    {
115
        return isset($this->args['order']) && is_numeric($this->args['order']) ? (int)$this->args['order'] : 0;
116
    }
117
118
    /**
119
     * apply condition to total or subtotal
120
     *
121
     * @param $totalOrSubTotalOrPrice
122
     * @return float
123
     */
124
    public function applyCondition($totalOrSubTotalOrPrice)
125
    {
126
        return $this->apply($totalOrSubTotalOrPrice, $this->getValue());
127
    }
128
129
    /**
130
     * get the calculated value of this condition supplied by the subtotal|price
131
     *
132
     * @param $totalOrSubTotalOrPrice
133
     * @return mixed
134
     */
135
    public function getCalculatedValue($totalOrSubTotalOrPrice)
136
    {
137
        $this->apply($totalOrSubTotalOrPrice, $this->getValue());
138
139
        return $this->parsedRawValue;
140
    }
141
142
    /**
143
     * apply condition
144
     *
145
     * @param $totalOrSubTotalOrPrice
146
     * @param $conditionValue
147
     * @return float
148
     */
149
    protected function apply($totalOrSubTotalOrPrice, $conditionValue)
150
    {
151
        // if value has a percentage sign on it, we will get first
152
        // its percentage then we will evaluate again if the value
153
        // has a minus or plus sign so we can decide what to do with the
154
        // percentage, whether to add or subtract it to the total/subtotal/price
155
        // if we can't find any plus/minus sign, we will assume it as plus sign
156
        if( $this->valueIsPercentage($conditionValue) )
157
        {
158
            if( $this->valueIsToBeSubtracted($conditionValue) )
159
            {
160
                $value = Helpers::normalizePrice( $this->cleanValue($conditionValue) );
161
162
                $this->parsedRawValue = $totalOrSubTotalOrPrice * ($value / 100);
163
164
                $result = floatval($totalOrSubTotalOrPrice - $this->parsedRawValue);
165
            }
166
            else if ( $this->valueIsToBeAdded($conditionValue) )
167
            {
168
                $value = Helpers::normalizePrice( $this->cleanValue($conditionValue) );
169
170
                $this->parsedRawValue = $totalOrSubTotalOrPrice * ($value / 100);
171
172
                $result = floatval($totalOrSubTotalOrPrice + $this->parsedRawValue);
173
            }
174
            else
175
            {
176
                $value = Helpers::normalizePrice($conditionValue);
177
178
                $this->parsedRawValue = $totalOrSubTotalOrPrice * ($value / 100);
179
180
                $result = floatval($totalOrSubTotalOrPrice + $this->parsedRawValue);
181
            }
182
        }
183
184
        // if the value has no percent sign on it, the operation will not be a percentage
185
        // next is we will check if it has a minus/plus sign so then we can just deduct it to total/subtotal/price
186
        else
187
        {
188
            if( $this->valueIsToBeSubtracted($conditionValue) )
189
            {
190
                $this->parsedRawValue = Helpers::normalizePrice( $this->cleanValue($conditionValue) );
191
192
                $result = floatval($totalOrSubTotalOrPrice - $this->parsedRawValue);
193
            }
194
            else if ( $this->valueIsToBeAdded($conditionValue) )
195
            {
196
                $this->parsedRawValue = Helpers::normalizePrice( $this->cleanValue($conditionValue) );
197
198
                $result = floatval($totalOrSubTotalOrPrice + $this->parsedRawValue);
199
            }
200
            else
201
            {
202
                $this->parsedRawValue = Helpers::normalizePrice($conditionValue);
203
204
                $result = floatval($totalOrSubTotalOrPrice + $this->parsedRawValue);
205
            }
206
        }
207
208
        // Do not allow items with negative prices.
209
        return $result < 0 ? 0.00 : $result;
210
    }
211
212
    /**
213
     * check if value is a percentage
214
     *
215
     * @param $value
216
     * @return bool
217
     */
218
    protected function valueIsPercentage($value)
219
    {
220
        return (preg_match('/%/', $value) == 1);
221
    }
222
223
    /**
224
     * check if value is a subtract
225
     *
226
     * @param $value
227
     * @return bool
228
     */
229
    protected function valueIsToBeSubtracted($value)
230
    {
231
        return (preg_match('/\-/', $value) == 1);
232
    }
233
234
    /**
235
     * check if value is to be added
236
     *
237
     * @param $value
238
     * @return bool
239
     */
240
    protected function valueIsToBeAdded($value)
241
    {
242
        return (preg_match('/\+/', $value) == 1);
243
    }
244
245
    /**
246
     * removes some arithmetic signs (%,+,-) only
247
     *
248
     * @param $value
249
     * @return mixed
250
     */
251
    protected function cleanValue($value)
252
    {
253
        return str_replace(array('%','-','+'),'',$value);
254
    }
255
256
    /**
257
     * validates condition arguments
258
     *
259
     * @param $args
260
     * @throws InvalidConditionException
261
     */
262 View Code Duplication
    protected function validate($args)
263
    {
264
        $rules = array(
265
            'name' => 'required',
266
            'type' => 'required',
267
            'value' => 'required',
268
        );
269
270
        $validator = CartConditionValidator::make($args, $rules);
271
272
        if( $validator->fails() )
273
        {
274
            throw new InvalidConditionException($validator->messages()->first());
275
        }
276
    }
277
}
278