Completed
Pull Request — master (#23)
by Nikolay
01:33
created

Kohana_Model_Shipping_Item::isFrozen()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php defined('SYSPATH') OR die('No direct script access.');
2
3
use Clippings\Freezable\FreezableInterface;
4
use Clippings\Freezable\FreezableTrait;
5
6
/**
7
 * @package    openbuildings\shipping
8
 * @author     Ivan Kerin <[email protected]>
9
 * @copyright  (c) 2013 OpenBuildings Ltd.
10
 * @license    http://spdx.org/licenses/BSD-3-Clause
11
 */
12
class Kohana_Model_Shipping_Item extends Jam_Model implements FreezableInterface {
13
14
	use FreezableTrait;
15
16
	/**
17
	 * @codeCoverageIgnore
18
	 */
19
	public static function initialize(Jam_Meta $meta)
20
	{
21
		$meta
22
			->associations(array(
23
				'brand_purchase_shipping' => Jam::association('belongsto', array(
24
					'inverse_of' => 'items'
25
				)),
26
				'purchase_item' => Jam::association('belongsto', array(
27
					'inverse_of' => 'shipping_item',
28
					'foreign_key' => 'purchase_item_id',
29
					'foreign_model' => 'purchase_item_product'
30
				)),
31
				'shipping_group' => Jam::association('belongsto', array(
32
					'inverse_of' => 'shipping_items'
33
				)),
34
			))
35
			->fields(array(
36
				'id' => Jam::field('primary'),
37
				'model' => Jam::field('polymorphic'),
38
				'total_delivery_time' => Jam::field('range', array(
39
					'format' => 'Model_Shipping::format_shipping_time'
40
				)),
41
				'is_frozen' => Jam::field('boolean'),
42
			))
43
			->validator('purchase_item', array(
44
				'present' => TRUE
45
			));
46
	}
47
48
	/**
49
	 * Filter out Model_Shipping_Item's of shipping_groups that are discounted,
50
	 * based on the provided total price
51
	 * @param  array     $items array of Model_Shipping_Item objects
52
	 * @param  Jam_Price $total
53
	 * @return array     Model_Shipping_Item objects
54
	 */
55 4
	public static function filter_discounted_items(array $items, Jam_Price $total)
56
	{
57 4
		Array_Util::validate_instance_of($items, 'Model_Shipping_Item');
58
59
		return array_filter($items, function($item) use ($total) {
60 4
			return ! $item->is_discounted($total);
61 4
		});
62
	}
63
64
	/**
65
	 * Sort Model_Shipping_Item by price, biggest price first
66
	 * @param  array  $items
67
	 * @return array
68
	 */
69 3
	public static function sort_by_price(array $items)
70
	{
71 3
		Array_Util::validate_instance_of($items, 'Model_Shipping_Item');
72
73
		// Suppress warnings as usort throws "Array was modified by the user comparison function"
74
		// When price method is being mocked.
75
		// Relevant php bug: https://bugs.php.net/bug.php?id=50688
76
		@ usort($items, function($item1, $item2){
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
77 3
			return $item1->price()->is(Jam_Price::GREATER_THAN, $item2->price()) ? -1 : 1;
78 3
		});
79
80 3
		return $items;
81
	}
82
83
	/**
84
	 * Sort and get all the realtive prices of Model_Shipping_Item object (using relative_price method)
85
	 * @param  array  $items
86
	 * @return array  Jam_Price objects
87
	 */
88 2
	public static function relative_prices(array $items)
89
	{
90 2
		Array_Util::validate_instance_of($items, 'Model_Shipping_Item');
91
92 2
		$items = Model_Shipping_Item::sort_by_price($items);
93
94
		$prices = array_map(function($item, $index) {
95 2
			return $index == 0 ? $item->total_price() : $item->total_additional_item_price();
96 2
		}, $items, array_keys($items));
97
98 2
		return $prices;
99
	}
100
101
	/**
102
	 * Get the shipping object associated with this item
103
	 * @return Model_Shipping
104
	 * @throws Kohana_Exception If shipping_group or its shipping is NULL
105
	 */
106 1
	public function shipping_insist()
107
	{
108 1
		$self = $this;
109
110
		return Jam_Behavior_Paranoid::with_filter(Jam_Behavior_Paranoid::ALL, function() use ($self) {
111 1
			return $self->get_insist('shipping_group')->get_insist('shipping');
112 1
		});
113
	}
114
115 1
	public function purchase_item_shipping()
116
	{
117 1
		return $this->get_insist('purchase_item')->get_insist('reference')->shipping();
118
	}
119
120
	/**
121
	 * Return the date the purchase was paid
122
	 */
123 1
	public function paid_at()
124
	{
125 1
		return $this->get_insist('brand_purchase_shipping')->paid_at();
126
	}
127
128
	/**
129
	 * Get the currency for pricing calculations
130
	 * @return string
131
	 * @throws Kohana_Exception If brand_purchase_shipping is NULL
132
	 */
133 2
	public function currency()
134
	{
135 2
		return $this->get_insist('brand_purchase_shipping')->currency();
136
	}
137
138
	/**
139
	 * Get the monetary object for currency calculations
140
	 * @return Monetary
141
	 * @throws Kohana_Exception If brand_purchase_shipping is NULL
142
	 */
143 2
	public function monetary()
144
	{
145 2
		return $this->get_insist('brand_purchase_shipping')->monetary();
146
	}
147
148
	/**
149
	 * Generate a key based on which shipping groups will be devided.
150
	 * The items in the same group are shipped toggether, allowing us to use
151
	 * additional_item_price instead of price.
152
	 *
153
	 * Groups by method and ships_from
154
	 * @return string
155
	 * @throws Kohana_Exception If shipping_group or shipping is NULL
156
	 */
157 2
	public function group_key()
158
	{
159 2
		$group = $this->shipping_group;
0 ignored issues
show
Documentation introduced by
The property shipping_group does not exist on object<Kohana_Model_Shipping_Item>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
160
161 2
		if ( ! $group OR ! $group->shipping)
162 1
			return NULL;
163
164 2
		return $group->method_id.'-'.$group->shipping->ships_from_id;
165
	}
166
167
	/**
168
	 * Get the price from shipping_group, converted into purchase's currency / monetary
169
	 * @return Jam_Price
170
	 * @throws Kohana_Exception If shipping_group is NULL
171
	 */
172 2
	public function price()
173
	{
174 2
		$price = $this->shipping_group_insist()->price ?: new Jam_Price(0, $this->currency());
175
176
		return $price
177 2
			->monetary($this->monetary())
178 2
				->convert_to($this->currency());
179
	}
180
181
	/**
182
	 * Get the additional_item_price from shipping_group, converted into purchase's currency / monetary
183
	 * If there is no additional_item_price, return price instead
184
	 * @return Jam_Price
185
	 * @throws Kohana_Exception If shipping_group is NULL
186
	 */
187 2
	public function additional_item_price()
188
	{
189 2
		$group = $this->shipping_group_insist();
190
191 2
		$additional_price = $group->additional_item_price ?: $group->price;
192
193
		return $additional_price
194 2
			->monetary($this->monetary())
195 2
				->convert_to($this->currency());
196
	}
197
198
	/**
199
	 * Get shipping_group's is_discounted
200
	 * If there is no additional_item_price, return price instead
201
	 * @return boolean
202
	 * @throws Kohana_Exception If shipping_group is NULL
203
	 */
204 2
	public function is_discounted(Jam_Price $total)
205
	{
206 2
		return $this->shipping_group_insist()->is_discounted($total);
207
	}
208
209
	/**
210
	 * Get purchase_item's quantity
211
	 * @return Jam_Price
212
	 * @throws Kohana_Exception If shipping_group is NULL
213
	 */
214 2
	public function quantity()
215
	{
216 2
		return $this->get_insist('purchase_item')->quantity;
217
	}
218
219
	/**
220
	 * Return price(), if quantity() > 1 the nany additional items are summed using additional_items_price()
221
	 * @return Jam_Price
222
	 * @throws Kohana_Exception If shipping_group is NULL
223
	 */
224 3
	public function total_price()
225
	{
226 3
		$additional_items_price = $this->additional_item_price()->multiply_by($this->quantity() - 1);
227
228 3
		return $this->price()->add($additional_items_price);
229
	}
230
231
	/**
232
	 * Shipping group's delivery_time
233
	 * Freezable
234
	 *
235
	 * @return Jam_Range
236
	 */
237 2
	public function total_delivery_time()
238
	{
239 2
		return $this->isFrozen()
240
			? $this->total_delivery_time
0 ignored issues
show
Documentation introduced by
The property total_delivery_time does not exist on object<Kohana_Model_Shipping_Item>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
241 2
			: $this->shipping_group_insist()->total_delivery_time();
242
	}
243
244
	/**
245
	 * Return the shipping date for this item
246
	 * @return Jam_Range
247
	 */
248 1
	public function shipping_date()
249
	{
250 1
		$paid_at = $this->paid_at();
251 1
		$days = $this->total_delivery_time();
252
253 1
		$from_day = strtotime("{$paid_at} + {$days->min()} weekdays");
254 1
		$to_day = strtotime("{$paid_at} + {$days->max()} weekdays");
255
256 1
		return new Jam_Range(array($from_day, $to_day));
257
	}
258
259
	/**
260
	 * Return additional_items_price() multiplied by quantity()
261
	 * @return Jam_Price
262
	 * @throws Kohana_Exception If shipping_group or purchase_item is NULL
263
	 */
264 3
	public function total_additional_item_price()
265
	{
266 3
		return $this->additional_item_price()->multiply_by($this->quantity());
267
	}
268
269
	/**
270
	 * Use paranoid for shipping group
271
	 */
272 2
	public function shipping_group_insist()
273
	{
274 2
		$self = $this;
275
276
		return Jam_Behavior_Paranoid::with_filter(Jam_Behavior_Paranoid::ALL, function() use ($self) {
277 2
			return $self->get_insist('shipping_group');
278 2
		});
279
	}
280
281 1
	public function shipping_method()
282
	{
283 1
		if ( ! $this->shipping_group)
0 ignored issues
show
Documentation introduced by
The property shipping_group does not exist on object<Kohana_Model_Shipping_Item>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
284 1
			return NULL;
285
286 1
		return $this->shipping_group->method;
0 ignored issues
show
Documentation introduced by
The property shipping_group does not exist on object<Kohana_Model_Shipping_Item>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
287
	}
288
289 4
	public function update_address(Model_Brand_Purchase_Shipping $brand_purchase_shipping)
290
	{
291 4
		$ship_to = $brand_purchase_shipping->ship_to();
292
293 4
		if ( ! $ship_to)
294
			return;
295
296 4
		if (! $this->shipping_group OR ! $this->shipping_group->location OR ! $this->shipping_group->location->contains($ship_to))
0 ignored issues
show
Documentation introduced by
The property shipping_group does not exist on object<Kohana_Model_Shipping_Item>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
297
		{
298 3
			$this->shipping_group = $this->purchase_item_shipping()->cheapest_group_in($ship_to);
0 ignored issues
show
Documentation introduced by
The property shipping_group does not exist on object<Kohana_Model_Shipping_Item>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
299
		}
300 4
	}
301
302 1
	public function isFrozen()
303
	{
304 1
		return $this->is_frozen;
0 ignored issues
show
Documentation introduced by
The property is_frozen does not exist on object<Kohana_Model_Shipping_Item>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
305
	}
306
307 1
	public function setFrozen($frozen)
308
	{
309 1
		$this->is_frozen = (bool) $frozen;
0 ignored issues
show
Documentation introduced by
The property is_frozen does not exist on object<Kohana_Model_Shipping_Item>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
310 1
	}
311
312 2
	public function performFreeze()
313
	{
314 2
		$this->total_delivery_time = $this->total_delivery_time();
0 ignored issues
show
Documentation introduced by
The property total_delivery_time does not exist on object<Kohana_Model_Shipping_Item>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
315 2
	}
316
317 1
	public function performUnfreeze()
318
	{
319 1
		$this->total_delivery_time = NULL;
0 ignored issues
show
Documentation introduced by
The property total_delivery_time does not exist on object<Kohana_Model_Shipping_Item>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
320 1
	}
321
}
322