source: branches/version-2_5-dev/data/class/SC_CartSession.php @ 20487

Revision 20487, 22.0 KB checked in by shutta, 13 years ago (diff)

SC_Productクラスのclass_extends対応

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-httpd-php; charset=UTF-8
Line 
1<?php
2/*
3 * This file is part of EC-CUBE
4 *
5 * Copyright(c) 2000-2010 LOCKON CO.,LTD. All Rights Reserved.
6 *
7 * http://www.lockon.co.jp/
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22 */
23
24/* カートセッション管理クラス */
25class SC_CartSession {
26    /** ユニークIDを指定する. */
27    var $key_tmp;
28
29    /** カートのセッション変数. */
30    var $cartSession;
31
32    /* コンストラクタ */
33    function SC_CartSession($cartKey = "cart") {
34        if (!isset($_SESSION[$cartKey])) {
35            $_SESSION[$cartKey] = array();
36        }
37        $this->cartSession =& $_SESSION[$cartKey];
38    }
39
40    // 商品購入処理中のロック
41    function saveCurrentCart($key_tmp, $productTypeId) {
42        $this->key_tmp = "savecart_" . $key_tmp;
43        // すでに情報がなければ現状のカート情報を記録しておく
44        if(count($_SESSION[$this->key_tmp]) == 0) {
45            $_SESSION[$this->key_tmp] = $this->cartSession[$productTypeId];
46        }
47        // 1世代古いコピー情報は、削除しておく
48        foreach($_SESSION as $k => $val) {
49            if($k != $this->key_tmp && preg_match("/^savecart_/", $k)) {
50                unset($this->cartSession[$productTypeId][$k]);
51            }
52        }
53        $this->registerKey($productTypeId);
54    }
55
56    // 商品購入中の変更があったかをチェックする。
57    function getCancelPurchase($productTypeId) {
58        $ret = isset($this->cartSession[$productTypeId]['cancel_purchase'])
59            ? $this->cartSession[$productTypeId]['cancel_purchase'] : "";
60        $this->cartSession[$productTypeId]['cancel_purchase'] = false;
61        return $ret;
62    }
63
64    // 購入処理中に商品に変更がなかったかを判定
65    function checkChangeCart($productTypeId) {
66        $change = false;
67        $max = $this->getMax($productTypeId);
68        for($i = 1; $i <= $max; $i++) {
69            if ($this->cartSession[$productTypeId][$i]['quantity']
70                != $_SESSION[$this->key_tmp][$i]['quantity']) {
71
72                $change = true;
73                break;
74            }
75            if ($this->cartSession[$productTypeId][$i]['id']
76                != $_SESSION[$this->key_tmp][$i]['id']) {
77
78                $change = true;
79                break;
80            }
81        }
82        if ($change) {
83            // 一時カートのクリア
84            unset($_SESSION[$this->key_tmp]);
85            $this->cartSession[$productTypeId][$key]['cancel_purchase'] = true;
86        } else {
87            $this->cartSession[$productTypeId]['cancel_purchase'] = false;
88        }
89        return $this->cartSession[$productTypeId]['cancel_purchase'];
90    }
91
92    // 次に割り当てるカートのIDを取得する
93    function getNextCartID($productTypeId) {
94        foreach($this->cartSession[$productTypeId] as $key => $val){
95            $arrRet[] = $this->cartSession[$productTypeId][$key]['cart_no'];
96        }
97        return (max($arrRet) + 1);
98    }
99
100    /**
101     * 商品ごとの合計価格
102     * XXX 実際には、「商品」ではなく、「カートの明細行(≒商品規格)」のような気がします。
103     *
104     * @param integer $id
105     * @return string 商品ごとの合計価格(税込み)
106     * @deprecated SC_CartSession::getCartList() を使用してください
107     */
108    function getProductTotal($id, $productTypeId) {
109        $max = $this->getMax($productTypeId);
110        for($i = 0; $i <= $max; $i++) {
111            if(isset($this->cartSession[$productTypeId][$i]['id'])
112               && $this->cartSession[$productTypeId][$i]['id'] == $id) {
113
114                // 税込み合計
115                $price = $this->cartSession[$productTypeId][$i]['price'];
116                $quantity = $this->cartSession[$productTypeId][$i]['quantity'];
117                $incTax = SC_Helper_DB_Ex::sfCalcIncTax($price);
118                $total = $incTax * $quantity;
119                return $total;
120            }
121        }
122        return 0;
123    }
124
125    // 値のセット
126    function setProductValue($id, $key, $val, $productTypeId) {
127        $max = $this->getMax($productTypeId);
128        for($i = 0; $i <= $max; $i++) {
129            if(isset($this->cartSession[$productTypeId][$i]['id'])
130               && $this->cartSession[$productTypeId][$i]['id'] == $id) {
131                $this->cartSession[$productTypeId][$i][$key] = $val;
132            }
133        }
134    }
135
136    // カート内商品の最大要素番号を取得する。
137    function getMax($productTypeId) {
138        $max = 0;
139        if (count($this->cartSession[$productTypeId]) > 0){
140            foreach($this->cartSession[$productTypeId] as $key => $val) {
141                if (is_numeric($key)) {
142                    if($max < $key) {
143                        $max = $key;
144                    }
145                }
146            }
147        }
148        return ($max);
149    }
150
151    // カート内商品数の合計
152    function getTotalQuantity($productTypeId) {
153        $total = 0;
154        $max = $this->getMax($productTypeId);
155        for($i = 0; $i <= $max; $i++) {
156            $total+= $this->cartSession[$productTypeId][$i]['quantity'];
157        }
158        return $total;
159    }
160
161
162    // 全商品の合計価格
163    function getAllProductsTotal($productTypeId) {
164        // 税込み合計
165        $total = 0;
166        $max = $this->getMax($productTypeId);
167        for($i = 0; $i <= $max; $i++) {
168
169            if (!isset($this->cartSession[$productTypeId][$i]['price'])) {
170                $this->cartSession[$productTypeId][$i]['price'] = "";
171            }
172
173            $price = $this->cartSession[$productTypeId][$i]['price'];
174
175            if (!isset($this->cartSession[$productTypeId][$i]['quantity'])) {
176                $this->cartSession[$productTypeId][$i]['quantity'] = "";
177            }
178            $quantity = $this->cartSession[$productTypeId][$i]['quantity'];
179
180            $incTax = SC_Helper_DB_Ex::sfCalcIncTax($price);
181            $total+= ($incTax * $quantity);
182        }
183        return $total;
184    }
185
186    // 全商品の合計税金
187    function getAllProductsTax($productTypeId) {
188        // 税合計
189        $total = 0;
190        $max = $this->getMax($productTypeId);
191        for($i = 0; $i <= $max; $i++) {
192            $price = $this->cartSession[$productTypeId][$i]['price'];
193            $quantity = $this->cartSession[$productTypeId][$i]['quantity'];
194            $tax = SC_Helper_DB_Ex::sfTax($price);
195            $total+= ($tax * $quantity);
196        }
197        return $total;
198    }
199
200    // 全商品の合計ポイント
201    function getAllProductsPoint($productTypeId) {
202        // ポイント合計
203        $total = 0;
204        if (USE_POINT !== false) {
205            $max = $this->getMax($productTypeId);
206            for($i = 0; $i <= $max; $i++) {
207                $price = $this->cartSession[$productTypeId][$i]['price'];
208                $quantity = $this->cartSession[$productTypeId][$i]['quantity'];
209
210                if (!isset($this->cartSession[$productTypeId][$i]['point_rate'])) {
211                    $this->cartSession[$productTypeId][$i]['point_rate'] = "";
212                }
213                $point_rate = $this->cartSession[$productTypeId][$i]['point_rate'];
214
215                if (!isset($this->cartSession[$productTypeId][$i]['id'][0])) {
216                    $this->cartSession[$productTypeId][$i]['id'][0] = "";
217                }
218                $id = $this->cartSession[$productTypeId][$i]['id'][0];
219                $point = SC_Utils_Ex::sfPrePoint($price, $point_rate, POINT_RULE, $id);
220                $total+= ($point * $quantity);
221            }
222        }
223        return $total;
224    }
225
226    // カートへの商品追加
227    function addProduct($product_class_id, $quantity) {
228        $objProduct = new SC_Product_Ex();
229        $arrProduct = $objProduct->getProductsClass($product_class_id);
230        $productTypeId = $arrProduct['product_type_id'];
231        $find = false;
232        $max = $this->getMax($productTypeId);
233        for($i = 0; $i <= $max; $i++) {
234
235            if($this->cartSession[$productTypeId][$i]['id'] == $product_class_id) {
236                $val = $this->cartSession[$productTypeId][$i]['quantity'] + $quantity;
237                if(strlen($val) <= INT_LEN) {
238                    $this->cartSession[$productTypeId][$i]['quantity'] += $quantity;
239                }
240                $find = true;
241            }
242        }
243        if(!$find) {
244            $this->cartSession[$productTypeId][$max+1]['id'] = $product_class_id;
245            $this->cartSession[$productTypeId][$max+1]['quantity'] = $quantity;
246            $this->cartSession[$productTypeId][$max+1]['cart_no'] = $this->getNextCartID($productTypeId);
247        }
248    }
249
250    // 前頁のURLを記録しておく
251    function setPrevURL($url) {
252        // 前頁として記録しないページを指定する。
253        $arrExclude = array(
254            "/shopping/"
255        );
256        $exclude = false;
257        // ページチェックを行う。
258        foreach($arrExclude as $val) {
259            if(preg_match("|" . preg_quote($val) . "|", $url)) {
260                $exclude = true;
261                break;
262            }
263        }
264        // 除外ページでない場合は、前頁として記録する。
265        if(!$exclude) {
266            $_SESSION['prev_url'] = $url;
267        }
268    }
269
270    // 前頁のURLを取得する
271    function getPrevURL() {
272        return isset($_SESSION['prev_url']) ? $_SESSION['prev_url'] : "";
273    }
274
275    // キーが一致した商品の削除
276    function delProductKey($keyname, $val, $productTypeId) {
277        $max = count($this->cartSession[$productTypeId]);
278        for($i = 0; $i < $max; $i++) {
279            if($this->cartSession[$productTypeId][$i][$keyname] == $val) {
280                unset($this->cartSession[$productTypeId][$i]);
281            }
282        }
283    }
284
285    function setValue($key, $val, $productTypeId) {
286        $this->cartSession[$productTypeId][$key] = $val;
287    }
288
289    function getValue($key, $productTypeId) {
290        return $this->cartSession[$productTypeId][$key];
291    }
292
293    function getCartList($productTypeId) {
294        $objProduct = new SC_Product_Ex();
295        $max = $this->getMax($productTypeId);
296        $arrRet = array();
297        for($i = 0; $i <= $max; $i++) {
298            if(isset($this->cartSession[$productTypeId][$i]['cart_no'])
299               && $this->cartSession[$productTypeId][$i]['cart_no'] != "") {
300
301                if (SC_Utils_Ex::isBlank($this->cartSession[$productTypeId][$i]['productsClass'])) {
302                    $this->cartSession[$productTypeId][$i]['productsClass'] =&
303                            $objProduct->getDetailAndProductsClass(
304                                    $this->cartSession[$productTypeId][$i]['id']);
305                }
306
307                $price = $this->cartSession[$productTypeId][$i]['productsClass']['price02'];
308                $this->cartSession[$productTypeId][$i]['price'] = $price;
309
310                $this->cartSession[$productTypeId][$i]['point_rate'] =
311                        $this->cartSession[$productTypeId][$i]['productsClass']['point_rate'];
312
313
314                $quantity = $this->cartSession[$productTypeId][$i]['quantity'];
315                $incTax = SC_Helper_DB_Ex::sfCalcIncTax($price);
316                $total = $incTax * $quantity;
317
318                $this->cartSession[$productTypeId][$i]['total_inctax'] = $total;
319
320                $arrRet[] =& $this->cartSession[$productTypeId][$i];
321            }
322        }
323        return $arrRet;
324    }
325
326    /**
327     * すべてのカートの内容を取得する.
328     *
329     * @return array すべてのカートの内容
330     */
331    function getAllCartList() {
332        $results = array();
333        $cartKeys = $this->getKeys();
334        $i = 0;
335        foreach ($cartKeys as $key) {
336            $cartItems = $this->getCartList($key);
337            foreach (array_keys($cartItems) as $itemKey) {
338                $cartItem =& $cartItems[$itemKey];
339                $results[$key][$i] =& $cartItem;
340                $i++;
341            }
342        }
343        return $results;
344    }
345
346    // カート内にある商品IDを全て取得する
347    function getAllProductID($productTypeId) {
348        $max = $this->getMax($productTypeId);
349        for($i = 0; $i <= $max; $i++) {
350            if($this->cartSession[$productTypeId][$i]['cart_no'] != "") {
351                $arrRet[] = $this->cartSession[$productTypeId][$i]['id'][0];
352            }
353        }
354        return $arrRet;
355    }
356
357    /**
358     * カート内にある商品規格IDを全て取得する.
359     *
360     * @param integer $productTypeId 商品種別ID
361     * @return array 商品規格ID の配列
362     */
363    function getAllProductClassID($productTypeId) {
364        $max = $this->getMax($productTypeId);
365        for($i = 0; $i <= $max; $i++) {
366            if($this->cartSession[$productTypeId][$i]['cart_no'] != "") {
367                $arrRet[] = $this->cartSession[$productTypeId][$i]['id'];
368            }
369        }
370        return $arrRet;
371    }
372
373    function delAllProducts($productTypeId) {
374        $max = $this->getMax($productTypeId);
375        for($i = 0; $i <= $max; $i++) {
376            unset($this->cartSession[$productTypeId][$i]);
377        }
378    }
379
380    // 商品の削除
381    function delProduct($cart_no, $productTypeId) {
382        $max = $this->getMax($productTypeId);
383        for($i = 0; $i <= $max; $i++) {
384            if($this->cartSession[$productTypeId][$i]['cart_no'] == $cart_no) {
385                unset($this->cartSession[$productTypeId][$i]);
386            }
387        }
388    }
389
390    // 数量の増加
391    function upQuantity($cart_no, $productTypeId) {
392        $quantity = $this->getQuantity($cart_no, $productTypeId);
393        if (strlen($quantity + 1) <= INT_LEN) {
394            $this->setQuantity($quantity + 1, $cart_no, $productTypeId);
395        }
396    }
397
398    // 数量の減少
399    function downQuantity($cart_no, $productTypeId) {
400        $quantity = $this->getQuantity($cart_no, $productTypeId);
401        if ($quantity > 1) {
402            $this->setQuantity($quantity - 1, $cart_no, $productTypeId);
403        }
404    }
405
406    function getQuantity($cart_no, $productTypeId) {
407        $max = $this->getMax($productTypeId);
408        for ($i = 0; $i <= $max; $i++) {
409            if ($this->cartSession[$productTypeId][$i]['cart_no'] == $cart_no) {
410                return $this->cartSession[$productTypeId][$i]['quantity'];
411            }
412        }
413    }
414
415    function setQuantity($quantity, $cart_no, $productTypeId) {
416        $max = $this->getMax($productTypeId);
417        for ($i = 0; $i <= $max; $i++) {
418            if ($this->cartSession[$productTypeId][$i]['cart_no'] == $cart_no) {
419                $this->cartSession[$productTypeId][$i]['quantity'] = $quantity;
420            }
421        }
422    }
423
424    function getProductClassId($cart_no, $productTypeId) {
425        for ($i = 0; $i <= $max; $i++) {
426            if ($this->cartSession[$productTypeId][$i]['cart_no'] == $cart_no) {
427                return $this->cartSession[$productTypeId][$i]['id'];
428            }
429        }
430    }
431
432    /**
433     * カート内の商品の妥当性をチェックする.
434     *
435     * エラーが発生した場合は, 商品をカート内から削除又は数量を調整し,
436     * エラーメッセージを返す.
437     *
438     * 1. 商品種別に関連づけられた配送業者の存在チェック
439     * 2. 削除/非表示商品のチェック
440     * 3. 商品購入制限数のチェック
441     * 4. 在庫数チェック
442     *
443     * @param string $key 商品種別ID
444     * @return string エラーが発生した場合はエラーメッセージ
445     */
446    function checkProducts($productTypeId) {
447        $objProduct = new SC_Product_Ex();
448        $tpl_message = "";
449
450        // カート内の情報を取得
451        $items = $this->getCartList($productTypeId);
452        foreach (array_keys($items) as $key) {
453            $item =& $items[$key];
454            $product =& $item['productsClass'];
455
456            /*
457             * 配送業者のチェック
458             */
459            $arrDeliv = SC_Helper_Purchase_Ex::getDeliv($productTypeId);
460            if (SC_Utils_Ex::isBlank($arrDeliv)) {
461                $tpl_message .= "※「" . $product['name'] . "」はまだ配送の準備ができておりません。恐れ入りますがお問い合わせページよりお問い合わせください。\n";
462            }
463
464            /*
465             * 表示/非表示商品のチェック
466             */
467            if (SC_Utils_Ex::isBlank($product)) {
468                $this->delProduct($item['cart_no'], $productTypeId);
469                $tpl_message .= "※ 現時点で販売していない商品が含まれておりました。該当商品をカートから削除しました。\n";
470            }
471
472            /*
473             * 商品購入制限数, 在庫数のチェック
474             */
475            $limit = $objProduct->getBuyLimit($product);
476            if (!is_null($limit) && $item['quantity'] > $limit) {
477                if ($limit > 0) {
478                    $this->setProductValue($item['id'], 'quantity', $limit, $productTypeId);
479                    $tpl_message .= "※「" . $product['name'] . "」は販売制限(または在庫が不足)しております。一度に数量{$limit}以上の購入はできません。\n";
480                } else {
481                    $this->delProduct($item['cart_no'], $productTypeId);
482                    $tpl_message .= "※「" . $product['name'] . "」は売り切れました。\n";
483                    continue;
484                }
485            }
486        }
487        return $tpl_message;
488    }
489
490    /**
491     * カートの内容を計算する.
492     *
493     * カートの内容を計算し, 下記のキーを保持する連想配列を返す.
494     *
495     * - tax: 税額
496     * - subtotal: カート内商品の小計
497     * - deliv_fee: カート内商品の合計送料 FIXME
498     * - total: 合計金額
499     * - payment_total: お支払い合計
500     * - add_point: 加算ポイント
501     *
502     *  TODO ダウンロード商品のみの場合の送料を検討する
503     *  TODO 使用ポイント, 配送都道府県, 支払い方法, 手数料の扱いを検討
504     *
505     * @param integer $productTypeId 商品種別ID
506     * @param SC_Customer $objCustomer ログイン中の SC_Customer インスタンス
507     * @param integer $use_point 今回使用ポイント
508     * @param integer|array $deliv_pref 配送先都道府県ID.
509                                        複数に配送する場合は都道府県IDの配列
510     * @param integer $charge 手数料
511     * @param integer $discount 値引
512     * @return array カートの計算結果の配列
513     */
514    function calculate($productTypeId, &$objCustomer, $use_point = 0,
515                       $deliv_pref = "", $charge = 0, $discount = 0) {
516        $objDb = new SC_Helper_DB_Ex();
517
518        $total_point = $this->getAllProductsPoint($productTypeId);
519        $results['tax'] = $this->getAllProductsTax($productTypeId);
520        $results['subtotal'] = $this->getAllProductsTotal($productTypeId);
521        $results['deliv_fee'] = 0;
522
523        // 商品ごとの送料を加算
524        if (OPTION_PRODUCT_DELIV_FEE == 1) {
525            $cartItems = $this->getCartList($productTypeId);
526            foreach ($cartItems as $item) {
527                $results['deliv_fee'] += $item['deliv_fee'] * $item['quantity'];
528            }
529        }
530
531        // 配送業者の送料を加算
532        if (OPTION_DELIV_FEE == 1) {
533            $results['deliv_fee'] += $objDb->sfGetDelivFee($deliv_pref, $productTypeId);
534        }
535
536        // 送料無料の購入数が設定されている場合
537        if (DELIV_FREE_AMOUNT > 0) {
538            // 商品の合計数量
539            $total_quantity = $this->getTotalQuantity($productTypeId);
540
541            if($total_quantity >= DELIV_FREE_AMOUNT) {
542                $results['deliv_fee'] = 0;
543            }
544        }
545
546        // 送料無料条件が設定されている場合
547        $arrInfo = $objDb->sfGetBasisData();
548        if($arrInfo['free_rule'] > 0) {
549            // 小計が無料条件を超えている場合
550            if($results['subtotal'] >= $arrInfo['free_rule']) {
551                $results['deliv_fee'] = 0;
552            }
553        }
554
555        // 合計を計算
556        $results['total'] = $results['subtotal'];
557        $results['total'] += $results['deliv_fee'];
558        $results['total'] += $charge;
559        $results['total'] -= $discount;
560
561        // お支払い合計
562        $results['payment_total'] = $results['total'] - $use_point * POINT_VALUE;
563
564        // 加算ポイントの計算
565        if (USE_POINT !== false) {
566            $results['add_point'] = SC_Helper_DB_Ex::sfGetAddPoint($total_point,
567                                                                   $use_point);
568            if($objCustomer != "") {
569                // 誕生日月であった場合
570                if($objCustomer->isBirthMonth()) {
571                    $results['birth_point'] = BIRTH_MONTH_POINT;
572                    $results['add_point'] += $results['birth_point'];
573                }
574            }
575            if($results['add_point'] < 0) {
576                $results['add_point'] = 0;
577            }
578        }
579        return $results;
580    }
581
582    function getKeys() {
583        $keys = array_keys($this->cartSession);
584        // 数量が 0 の商品種別は削除する
585        foreach ($keys as $key) {
586            $quantity = $this->getTotalQuantity($key);
587            if ($quantity < 1) {
588                unset($this->cartSession[$key]);
589            }
590        }
591        return array_keys($this->cartSession);
592    }
593
594    function registerKey($key) {
595        $_SESSION['cartKey'] = $key;
596    }
597
598    function unsetKey() {
599        unset($_SESSION['cartKey']);
600    }
601
602    function getKey() {
603        return $_SESSION['cartKey'];
604    }
605
606    function isMultiple() {
607        return count($this->getKeys()) > 1;
608    }
609}
610?>
Note: See TracBrowser for help on using the repository browser.