1 <?php
2
3 4 5 6 7 8
9 class Cart extends Object {
10
11 static $cache = false;
12
13
14 static function add_new_item(OrderItem $item) {
15 $currentItems = self::get_items();
16 foreach($currentItems as $currentItem) {
17 if ($currentItem->hasSameContent($item))
18 return self::add_item($currentItem->ItemIndex);
19 }
20 if ($item->canAddQuantityValue($item->Quantity)) {
21 self::set_item($item->getProductID(), $item);
22 }
23 }
24
25
26 static function add_item($itemIndex, $quantity = 1) {
27 $unserializedItem = self::get_item($itemIndex);
28 $unserializedItem->addQuantityValue($quantity);
29 self::set_item($itemIndex, $unserializedItem);
30 }
31
32
33 static function remove_item($itemIndex, $count = 1) {
34 $unserializedItem = self::get_item($itemIndex);
35 $newQuantity = $unserializedItem->getQuantity() - $count;
36 if ($newQuantity > 0) {
37 $unserializedItem->setQuantityValue($newQuantity);
38 self::set_item($itemIndex, $unserializedItem);
39 } else {
40 self::set_item($itemIndex, false);
41 }
42 }
43
44
45 private static function item_list() {
46 return 'cart_items';
47 }
48
49
50 private static function cart_index() {
51
52 $hash = self::cart_hash();
53 return self::item_list() . '_' . $hash;
54 }
55
56
57 private static function cart_hash() {
58 return (Cookie::get('cart_hash') ? Cookie::get('cart_hash') : self::generate_cart_hash());
59 }
60
61
62 private static function generate_cart_hash() {
63 $sc = SiteConfig::current_site_config();
64 $hash = md5(time() . rand());
65 Cookie::set('cart_hash', $hash, ($sc->CachedCartLifeTime ? $sc->CachedCartLifeTime : 30));
66 return $hash;
67 }
68
69
70 static function clear() {
71 self::clean_cache(self::cart_index());
72 if ($member = Member::currentUser()) {
73 $member->CartData = serialize(array());
74 $member->write();
75 }
76 }
77
78
79 static function remove_all_item($itemIndex) {
80 self::set_item($itemIndex, false);
81 }
82
83
84 static function set_quantity_item($itemIndex, $quantity) {
85 $unserializedItem = self::get_item($itemIndex);
86 $unserializedItem->setQuantityValue($quantity);
87 self::set_item($itemIndex, $unserializedItem);
88 }
89
90
91 static function get_quantity_item($itemIndex) {
92 $unserializedItem = self::get_item($itemIndex);
93 return $unserializedItem->Quantity;
94 }
95
96
97 static function get_items() {
98 $items = array();
99 $currentItems = unserialize(self::get_cached_data(self::cart_index()));
100 if ($currentItems) {
101 foreach ($currentItems as $currentItem) {
102 if ($currentItem != null) {
103 array_push($items, $currentItem);
104 }
105 }
106 }
107 return $items;
108 }
109
110
111 private static function get_item($itemIndex) {
112 $items = self::get_items();
113 if ($items && count($items)) {
114 foreach($items as $item) {
115 if ($item->ItemIndex == $itemIndex) {
116 return $item;
117 }
118 }
119 }
120 return false;
121 }
122
123
124 private static function set_item($index, OrderItem $item) {
125 $allItems = self::get_items();
126 $find = false;
127 if ($allItems) {
128 foreach($allItems as $key=>$oneItem) {
129 if ($oneItem->ItemIndex == $index) {
130 $find = true;
131 if ($item) {
132 $item->ItemIndex = $index;
133 $allItems[$key] = $item;
134 } else {
135 unset($allItems[$key]);
136 }
137 break;
138 }
139 }
140 }
141 if (!$find) {
142 if ($item) {
143 $item->ItemIndex = $index;
144 array_push($allItems, $item);
145 }
146 }
147
148 self::set_cached_data(self::cart_index(), serialize($allItems));
149
150 $order = self::current_order();
151 $order->extend('onAfterSetCart', $allItems);
152
153 if ($member = Member::currentUser()) {
154 $member->CartData = serialize($allItems);
155 $member->write();
156 }
157 return;
158 }
159
160
161 static function has_items() {
162 return self::get_items();
163 }
164
165
166 static function in_cart($itemIndex) {
167 return self::get_item($itemIndex);
168 }
169
170
171 static function current_order() {
172 $order = new Order();
173 $order->IsCart = true;
174 $order->ClearCartLink = Cart_Controller::clear_link();
175 $order->update(self::get_info());
176 return $order;
177 }
178
179 static function get_info($name = null) {
180 $info = Session::get('cart.info');
181 if (!$info) $info = array();
182 if ($name) {
183 return isset($info[$name]) ? $info[$name] : null;
184 }
185 return $info;
186 }
187
188 static function set_info($name, $value) {
189 $info = self::get_info();
190 $info[$name] = $value;
191 Session::set('cart.info', $info);
192 }
193
194 static function get_cached_cart() {
195 if (($member = Member::currentUser()) && ($cartData = unserialize($member->CartData))) {
196 return $cartData;
197 }
198 return false;
199 }
200
201 static function update_cart_from_cache() {
202 if ($cachedCart = self::get_cached_cart()) {
203 foreach($cachedCart as $item) {
204 if ($item->getProduct() && $item->getProduct()->ExistsOnLive) {
205 if ($currentItems = self::get_items()) {
206 $has = false;
207 foreach($currentItems as $currentItem) {
208 if ($currentItem->hasSameContent($item)) {
209 $has = true;
210 }
211 }
212 if (!$has) {
213 self::add_new_item($item);
214 }
215 } else {
216 self::add_new_item($item);
217 }
218 }
219 }
220 }
221 if ($member = Member::currentUser()) {
222 $member->CartData = serialize(self::get_items());
223 $member->write();
224 }
225 return false;
226 }
227
228
229 static function get_cache() {
230 if (!self::$cache) {
231 $sc = SiteConfig::current_site_config();
232 self::$cache = SS_Cache::set_cache_lifetime('cart', ($sc->CachedCartLifeTime ? $sc->CachedCartLifeTime : 30)*24*60*60);
233 self::$cache = SS_Cache::factory('cart');
234 }
235 return self::$cache;
236 }
237
238 static function get_cached_data($key) {
239 if (!$key) return false;
240 return unserialize(self::get_cache()->load($key));
241 }
242
243 static function set_cached_data($key, $data) {
244 if (!$key) return false;
245 return self::get_cache()->save(serialize($data), $key);
246 }
247
248 static function clean_cache($key) {
249 self::get_cache()->remove($key);
250 }
251 }
252
253 class Cart_Controller extends Controller {
254
255 static $allowed_actions = array('add', 'clear', 'additem', 'removeitem', 'removeallitem', 'setquantityitem', 'jsoncart', 'in_cart');
256 static $URLSegment = 'cartaction';
257
258 static $cart_template = 'Cart';
259 static function set_cart_template($v) { self::$cart_template = $v; }
260
261
262 function Link($action = null) {
263 return Controller::join_links(Director::baseURL(), self::$URLSegment, $action);
264 }
265
266 static function clear_link() {
267 return Controller::join_links(Director::baseURL(), self::$URLSegment, 'clear');
268 }
269
270 static function add_item_link($id) {
271 return Controller::join_links(Director::baseURL(), self::$URLSegment, 'additem', $id);
272 }
273
274 static function remove_item_link($id) {
275 return Controller::join_links(Director::baseURL(), self::$URLSegment, 'removeitem', $id);
276 }
277
278 static function remove_all_item_link($id) {
279 return Controller::join_links(Director::baseURL(), self::$URLSegment, 'removeallitem', $id);
280 }
281
282 static function set_quantity_item_link($id) {
283 return Controller::join_links(Director::baseURL(), self::$URLSegment, 'setquantityitem', $id);
284 }
285
286 function init() {
287 parent::init();
288 HTTP::set_cache_age(0);
289 }
290
291 292 293 294 295 296 297
298 function add($data) {
299 if (isset($data['itemId']) && is_numeric($data['itemId'])) {
300 $id = $data['itemId'];
301 $Num = 1;
302 if (isset($data['Num']) && is_numeric($data['Num'])) {
303 $Num = $data['Num'];
304 }
305 $variationId = false;
306 if (isset($data['variationId']) && is_numeric($data['variationId'])) {
307 $variationId = (int)$data['variationId'];
308 $id .= "_{$variationId}";
309 }
310 if (Cart::in_cart($id)) {
311 Cart::add_item($id, $Num);
312 } else {
313 $product = DataObject::get_by_id(singleton('Product')->ClassName, (int)$id);
314 if ($product->hasMethod('Variations') && $product->Variations()->exists()) {
315 if ($variationId) {
316 $product->VariationID = $variationId;
317 } else {
318
319
320
321 return false;
322 }
323 }
324
325 $item = Object::create('OrderItem', $product, $Num);
326 Cart::add_new_item($item);
327 }
328
329 Session::clear('Cart.Process');
330 if (!$this->isAjax())
331 Director::redirectBack();
332 return $this->CartBlock();
333 }
334 }
335
336 337 338 339
340 function clear() {
341 Cart::clear();
342 return ($this->isAjax()) ? $this->renderCart() : Director::redirectBack();
343 }
344
345 346 347 348 349 350
351 function additem() {
352 $itemId = $this->urlParams['ID'];
353 if ($itemId) {
354 Cart::add_item($itemId);
355 return ($this->isAjax()) ? $this->renderCart() : Director::redirectBack();
356 }
357 return false;
358 }
359
360 361 362 363 364 365
366 function removeitem() {
367 $itemId = $this->urlParams['ID'];
368 if ($itemId) {
369 Cart::remove_item($itemId);
370 return ($this->isAjax()) ? $this->renderCart() : Director::redirectBack();
371 }
372 return false;
373 }
374
375 376 377 378 379 380
381 function removeallitem() {
382 $itemId = $this->urlParams['ID'];
383 if ($itemId) {
384 Cart::remove_all_item($itemId);
385 return ($this->isAjax()) ? $this->renderCart() : Director::redirectBack();
386 }
387 return false;
388 }
389
390 391 392 393 394 395
396 function setquantityitem() {
397 $itemId = $this->urlParams['ID'];
398 $quantity = $_REQUEST['quantity'];
399 if ($itemId && is_numeric($quantity) && is_int($quantity + 0) && $quantity > 0) {
400 Cart::set_quantity_item($itemId, $quantity);
401 return ($this->isAjax()) ? $this->renderCart() : Director::redirectBack();
402 }
403 return false;
404 }
405
406 407 408 409 410 411
412 public function jsoncart() {
413 return self::json_code();
414 }
415
416 417 418 419 420 421
422 public function in_cart() {
423 $itemId = $this->urlParams['ID'];
424 if ($itemId && is_numeric($itemId)) {
425 if (Cart::in_cart($itemId)) {
426 $currentOrder = Cart::current_order();
427 $js = array();
428 if ($items = $currentOrder->Items()) {
429 foreach ($items as $item) {
430 if ($item->getProductID() == $itemId) {
431 $item->updateForAjax($js);
432 }
433 }
434 return Convert::array2json($js);
435 }
436 }
437 return false;
438 }
439 return false;
440 }
441
442 443 444 445 446
447 protected function renderCart() {
448 return $this->renderWith(self::$cart_template, Cart::current_order());
449 }
450
451 452 453 454
455 protected static function json_code() {
456 $currentOrder = Cart::current_order();
457 $js = array();
458
459 $items = $currentOrder->Items();
460
461
462 if ($items) {
463 foreach ($items as $item)
464 $item->updateForAjax($js);
465 }
466
467
468 $currentOrder->updateForAjax($js);
469 return Convert::array2json($js);
470 }
471
472
473 function index() {
474 Director::redirect('');
475 }
476
477 }
478
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the
Silverstripe Forums to ask development related questions.
-