Item.php 5.07 KB
Newer Older
1
<?php namespace Bnet\Cart;
2 3 4 5 6 7 8 9 10 11

/**
 * Created by PhpStorm.
 * User: darryl
 * Date: 1/17/2015
 * Time: 11:03 AM
 */

use Illuminate\Support\Collection;

12 13 14 15 16 17 18 19 20
/**
 * @property int id
 * @property int quantity
 * @property string name
 * @property mixed|null price
 * @property Attribute attributes
 * @property Conditions conditions
 */
class Item extends Collection {
21

22 23 24 25 26 27 28 29

	/**
	 * Create a new Item with the given attributes.
	 *
	 * @param mixed $attributes
	 * @return void
	 */
	public function __construct($attributes) {
30 31
		$attributes['conditions'] = $this->prepareConditionCollection($attributes);

32 33 34 35
		parent::__construct($attributes);
	}


Thorsten Buss's avatar
Thorsten Buss committed
36 37 38 39 40
	/**
	 * get the sum of price
	 *
	 * @return mixed|null
	 */
41
	public function priceSum() {
42
		return $this->price() * $this->quantity;
Thorsten Buss's avatar
Thorsten Buss committed
43
	}
darrylcoder's avatar
darrylcoder committed
44

45 46 47 48 49
	/**
	 * return property
	 * @param $name
	 * @return mixed|null
	 */
Thorsten Buss's avatar
Thorsten Buss committed
50 51 52 53
	public function __get($name) {
		if ($this->has($name)) return $this->get($name);
		return null;
	}
54

55 56 57 58
	public function __isset($name) {
		return $this->has($name);
	}

Thorsten Buss's avatar
Thorsten Buss committed
59 60 61 62 63 64
	/**
	 * check if item has conditions
	 *
	 * @return bool
	 */
	public function hasConditions() {
65
		return !$this->conditions || !$this->conditions->isEmpty();
Thorsten Buss's avatar
Thorsten Buss committed
66
	}
67

68 69 70 71 72 73 74 75
	/**
	 * return the price amount for this item
	 * @return int
	 */
	public function price() {
		return $this->price;
	}

Thorsten Buss's avatar
Thorsten Buss committed
76 77 78
	/**
	 * get the single price in which conditions are already applied
	 *
79
	 * @param null|string $type only sum with conditions for this $type
Thorsten Buss's avatar
Thorsten Buss committed
80 81
	 * @return mixed|null
	 */
82
	public function priceWithConditions($type = null) {
83
		$originalPrice = $this->price();
84

85 86
		$condition_price = $this->conditions->sum(function ($condition) use ($originalPrice, $type) {
			/** @var Condition $condition */
87
			return ($condition && $condition->getTarget() === Condition::TARGET_ITEM
88
				&& (is_null($type) || $type == $condition->getType()))
89 90 91
				? $condition->applyCondition($originalPrice)
				: 0;
		});
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
		return $this->returnPriceAboveZero($condition_price + $originalPrice);
	}

	/**
	 * return the price of the conditions without the item price
	 * @param null|string $type only sum with conditions for this $type
	 * @return mixed|null
	 */
	public function priceOnlyConditions($type = null) {
		return $this->priceWithConditions($type) - $this->price();
	}

	/**
	 * return the price of the conditions SUM without the item priceSUM
	 * @param null|string $type only sum with conditions for this $type
	 * @return mixed|null
	 */
	public function priceSumOnlyConditions($type = null) {
		return $this->priceSumWithConditions($type) - $this->priceSum();
Thorsten Buss's avatar
Thorsten Buss committed
111
	}
112

Thorsten Buss's avatar
Thorsten Buss committed
113 114 115
	/**
	 * get the sum of price in which conditions are already applied
	 *
116
	 * @param null|string $type only sum with conditions for this $type
Thorsten Buss's avatar
Thorsten Buss committed
117 118
	 * @return mixed|null
	 */
119
	public function priceSumWithConditions($type = null) {
Thorsten Buss's avatar
Thorsten Buss committed
120 121
		$originalPrice = $this->price();

122 123
		$condition_price = $this->conditions->sum(function ($condition) use ($originalPrice, $type) {
			/** @var Condition $condition */
124
			return ($condition && $condition->getTarget() === Condition::TARGET_ITEM
125
				&& (is_null($type) || $type == $condition->getType()))
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
				? $condition->applyConditionWithQuantity($originalPrice, $this->quantity)
				: 0;
		});
		return $this->returnPriceAboveZero($condition_price + ($this->quantity * $originalPrice));
	}

	/**
	 * assert that the price is > 0
	 * @param $price
	 * @return int
	 */
	protected function returnPriceAboveZero($price) {
		return $price > 0
			? $price
			: 0;
Thorsten Buss's avatar
Thorsten Buss committed
141
	}
142 143 144 145 146 147 148 149 150

	/**
	 * Get the collection of items as a plain array.
	 *
	 * @return array
	 */
	public function toArray() {
		$arr = parent::toArray();
		if (!empty($arr['conditions'])) {
151 152 153
			/** @var Collection $cond */
			$cond = $this['conditions'];
			$arr['conditions'] = $cond->keyBy('name')->toArray();
154 155 156 157
		}
		return $arr;
	}

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
	/**
	 * make conditions as array and set target to item if not set
	 * @param $attributes
	 * @return mixed
	 */
	protected function prepareConditionCollection($attributes) {
		if (!isset($attributes['conditions']))
			$conditions = collect([]);
		elseif ($attributes['conditions'] instanceOf Condition || !is_array($attributes['conditions']))
			$conditions = collect([$attributes['conditions']]);
		else
			$conditions = collect($attributes['conditions']);

		$uniqueKeys = collect(); //list of keys to garantie uniquness
		// check/set the target
		$conditions = $conditions->map(function ($condition) {
			if (!$condition instanceof Condition)
				$condition = new Condition($condition);

			// ignore target==cart conditions
178
			if ($condition->getTarget() == Condition::TARGET_CART)
179
				return false;
180
			$condition->setTarget(Condition::TARGET_ITEM); // set item as default it not set
181 182

			return $condition;
183 184 185 186 187 188
		})
		->filter(function($condition) {
			// remove conditions which are invalid or for cart instead of item
			return $condition !== false;
		})
		->keyBy(function ($cond) use (&$uniqueKeys) {
189
			// use name as key and verify that the key is unique
190
			$key = @$cond->name ?: 'unknown';
191 192 193 194 195 196 197 198 199 200 201
			$postfix = '';
			while ($uniqueKeys->contains($key . $postfix)) {
				$postfix = empty($postfix) ? 1 : ($postfix + 1);
			}
			$uniqueKeys->push($key . $postfix);
			return $key . $postfix;
		});

		return $conditions;
	}

202
}