source: branches/version-2_5-dev/data/class/SC_Product.php @ 18852

Revision 18852, 22.8 KB checked in by nanasess, 10 years ago (diff)

商品種別によってカートを分ける(#823)

  • SC_CartSession をリファクタリング
  • 商品情報を SC_CartSession で取得するように変更
  • SC_Helper_DB::sfTotalCart() の実装を SC_CartSession へ移動
  • SC_Product で, 規格分類名を name に格納していたのを classcategory_name へ変更
  • カート関連の処理を修正
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/*  [名称] SC_Product
25 *  [概要] 商品クラス
26 */
27class SC_Product {
28
29    /** 規格名一覧 */
30    var $arrClassName;
31    /** 規格分類名一覧 */
32    var $arrClassCatName;
33    var $classCategories = array();
34    var $stock_find;
35    /** 規格1クラス名 */
36    var $className1 = '';
37    /** 規格2クラス名 */
38    var $className2 = '';
39    /** 規格1が設定されている */
40    var $classCat1_find;
41    /** 規格2が設定されている */
42    var $classCat2_find;
43    var $classCats1;
44
45    /**
46     * SC_Queryインスタンスに設定された検索条件をもとに商品IDの配列を取得する.
47     *
48     * 検索条件は, SC_Query::getWhere() 関数で設定しておく必要があります.
49     *
50     * @param SC_Query $objQuery SC_Query インスタンス
51     * @param array $arrVal 検索パラメータの配列
52     * @return array 商品IDの配列
53     */
54    function findProductIds(&$objQuery, $arrVal = array()) {
55        $table = <<< __EOS__
56                 dtb_products AS alldtl
57            JOIN dtb_product_categories AS T2
58              ON alldtl.product_id = T2.product_id
59            JOIN dtb_category
60              ON T2.category_id = dtb_category.category_id
61__EOS__;
62        // SC_Query::getCol() ではパフォーマンスが出ない
63        $results = $objQuery->select('alldtl.product_id', $table, "", $arrVal,
64                                     MDB2_FETCHMODE_ORDERED);
65        foreach ($results as $val) {
66            $resultValues[] = $val[0];
67        }
68        return array_unique($resultValues);
69    }
70
71    /**
72     * SC_Queryインスタンスに設定された検索条件をもとに商品一覧の配列を取得する.
73     *
74     * 主に SC_Product::findProductIds() で取得した商品IDを検索条件にし,
75     * SC_Query::setOrder() や SC_Query::setLimitOffset() を設定して, 商品一覧
76     * の配列を取得する.
77     *
78     * @param SC_Query $objQuery SC_Query インスタンス
79     * @param array $arrVal 検索パラメータ(ソート条件)の配列
80     * @return array 商品一覧の配列
81     */
82    function lists(&$objQuery, $arrVal = array()) {
83        $col = <<< __EOS__
84             product_id
85            ,product_code_min
86            ,product_code_max
87            ,name
88            ,comment1
89            ,comment2
90            ,comment3
91            ,main_list_comment
92            ,main_image
93            ,main_list_image
94            ,price01_min
95            ,price01_max
96            ,price02_min
97            ,price02_max
98            ,stock_min
99            ,stock_max
100            ,stock_unlimited_min
101            ,stock_unlimited_max
102            ,deliv_date_id
103            ,status
104            ,del_flg
105            ,update_date
106__EOS__;
107        return $objQuery->select($col, $this->alldtlSQL($objQuery->where),
108                                 "", $arrVal);
109    }
110
111    /**
112     * 商品詳細を取得する.
113     *
114     * @param integer $productId 商品ID
115     * @return array 商品詳細情報の配列
116     */
117    function getDetail($productId) {
118        $objQuery =& SC_Query::getSingletonInstance();
119        $result = $objQuery->select("*", $this->alldtlSQL("product_id = ?"),
120                                    "product_id = ?",
121                                    array($productId, $productId));
122        return $result[0];
123    }
124
125    /**
126     * 商品詳細情報と商品規格を取得する.
127     *
128     * @param integer $productClassId 商品規格ID
129     * @return array 商品詳細情報と商品規格の配列
130     */
131    function getDetailAndProductsClass($productClassId) {
132        $result = $this->getProductsClass($productClassId);
133        $result = array_merge($result, $this->getDetail($result['product_id']));
134        return $result;
135    }
136
137    /**
138     * 商品IDに紐づく商品規格を自分自身に設定する.
139     *
140     * 引数の商品IDの配列に紐づく商品規格を取得し, 自分自身のフィールドに
141     * 設定する.
142     *
143     * @param array $arrProductId 商品ID の配列
144     * @return void
145     */
146    function setProductsClassByProductIds($arrProductId) {
147
148        foreach ($arrProductId as $productId) {
149            $rows[$productId] = $this->getProductsClassFullByProductId($productId);
150        }
151
152        $arrProductsClass = array();
153        foreach ($rows as $productId => $arrProductClass) {
154            $classCats1 = array();
155            $classCats1[''] = '選択してください';
156
157            // 規格1クラス名
158            $this->className1[$productId] =
159                isset($arrProductClass[0]['class_name1'])
160                ? $arrProductClass[0]['class_name1']
161                : '';
162
163            // 規格2クラス名
164            $this->className2[$productId] =
165                isset($arrProductClass[0]['class_name2'])
166                ? $arrProductClass[0]['class_name2']
167                : '';
168
169            // 規格1が設定されている
170            $this->classCat1_find[$productId] = (!SC_Utils_Ex::isBlank($arrProductClass[0]['classcategory_id1']));
171            // 規格2が設定されている
172            $this->classCat2_find[$productId] = (!SC_Utils_Ex::isBlank($arrProductClass[0]['classcategory_id2']));
173
174            $this->stock_find[$productId] = false;
175            $classCategories = array();
176            $classCategories['']['']['name'] = '選択してください';
177            $classCategories['']['']['product_class_id'] = $arrProductClass[0]['product_class_id'];
178            // 商品種別 TODO 暫定的に down を使用する
179            $classCategories['']['']['product_type'] = $arrProductClass[0]['down'];
180            $this->product_class_id[$productId] = $arrProductClass[0]['product_class_id'];
181            // 商品種別 TODO 暫定的に down を使用する
182            $this->product_type[$productId] = $arrProductClass[0]['down'];
183            foreach ($arrProductClass as $productsClass) {
184                $productsClass1 = $productsClass['classcategory_id1'];
185                $productsClass2 = $productsClass['classcategory_id2'];
186                $classCategories[$productsClass1]['']['name'] = '選択してください';
187                // 在庫
188                $stock_find_class = ($productsClass['stock_unlimited'] || $productsClass['stock'] > 0);
189
190                $classCategories[$productsClass1][$productsClass2]['name'] = $productsClass['classcategory_name2'] . ($stock_find_class ? '' : ' (品切れ中)');
191
192                $classCategories[$productsClass1][$productsClass2]['stock_find'] = $stock_find_class;
193
194                if ($stock_find_class) {
195                    $this->stock_find[$productId] = true;
196                }
197
198                if (!in_array($classcat_id1, $classCats1)) {
199                    $classCats1[$productsClass1] = $productsClass['classcategory_name1']
200                        . ($productsClass2 == 0 && !$stock_find_class ? ' (品切れ中)' : '');
201                }
202
203                // 価格
204                $classCategories[$productsClass1][$productsClass2]['price01']
205                    = strlen($productsClass['price01'])
206                    ? number_format(SC_Helper_DB_Ex::sfPreTax($productsClass['price01']))
207                    : '';
208
209                $classCategories[$productsClass1][$productsClass2]['price02']
210                    = strlen($productsClass['price02'])
211                    ? number_format(SC_Helper_DB_Ex::sfPreTax($productsClass['price02']))
212                    : '';
213
214                // ポイント
215                // XXX sfPrePoint() の第4パラメータは、処理にバグがあるため現状省略している。(http://xoops.ec-cube.net/modules/newbb/viewtopic.php?topic_id=3540&forum=1&post_id=13853#forumpost13853)
216                $classCategories[$productsClass1][$productsClass2]['point']
217                    = SC_Utils_Ex::sfPrePoint($productsClass['price02'], $productsClass['point_rate']);
218
219                // 商品コード
220                $classCategories[$productsClass1][$productsClass2]['product_code'] = $productsClass['product_code'];
221                // 商品規格ID
222                $classCategories[$productsClass1][$productsClass2]['product_class_id'] = $productsClass['product_class_id'];
223                // 商品種別 TODO 暫定的に down を使用する
224                $classCategories[$productsClass1][$productsClass2]['product_type'] = $productsClass['down'];
225            }
226
227            $this->classCategories[$productId] = $classCategories;
228
229            // 規格1
230            $this->classCats1[$productId] = $classCats1;
231        }
232    }
233
234    /**
235     * SC_Query インスタンスに設定された検索条件を使用して商品規格を取得する.
236     *
237     * @param SC_Query $objQuery SC_Queryインスタンス
238     * @param array $params 検索パラメータの配列
239     * @return array 商品規格の配列
240     */
241    function getProductsClassByQuery(&$objQuery, $params) {
242        // 末端の規格を取得
243        $col = <<< __EOS__
244            T1.product_id,
245            T1.stock,
246            T1.stock_unlimited,
247            T1.price01,
248            T1.price02,
249            T1.point_rate,
250            T1.product_code,
251            T1.product_class_id,
252            T1.del_flg,
253            T1.down,
254            T1.down_filename,
255            T1.down_realfilename,
256            T2.class_combination_id,
257            T2.parent_class_combination_id,
258            T2.classcategory_id,
259            T2.level,
260            T3.name AS classcategory_name,
261            T4.name AS class_name,
262            T4.class_id
263__EOS__;
264        $table = <<< __EOS__
265                      dtb_products_class T1
266            LEFT JOIN dtb_class_combination T2
267                   ON T1.class_combination_id = T2.class_combination_id
268            LEFT JOIN dtb_classcategory T3
269                   ON T2.classcategory_id = T3.classcategory_id
270            LEFT JOIN dtb_class T4
271                   ON T3.class_id = T4.class_id
272__EOS__;
273        $arrRet = $objQuery->select($col, $table, "", $params);
274        $levels = array();
275        $parents = array();
276        foreach ($arrRet as $rows) {
277            $levels[] = $rows['level'];
278            $parents[] = $rows['parent_class_combination_id'];
279        }
280        $level = max($levels);
281        $parentsClass = array();
282        // 階層分の親を取得
283        for ($i = 0; $i < $level -1; $i++) {
284            $objQuery =& SC_Query::getSingletonInstance();
285            $objQuery->setWhere('T1.class_combination_id IN (' . implode(', ', array_pad(array(), count($parents), '?')) . ')');
286
287            $col = <<< __EOS__
288                T1.class_combination_id,
289                T1.classcategory_id,
290                T1.parent_class_combination_id,
291                T1.level,
292                T2.name AS classcategory_name,
293                T3.name AS class_name,
294                T3.class_id
295__EOS__;
296            $table = <<< __EOS__
297                          dtb_class_combination T1
298                LEFT JOIN dtb_classcategory T2
299                       ON T1.classcategory_id = T2.classcategory_id
300                LEFT JOIN dtb_class T3
301                       ON T2.class_id = T3.class_id
302__EOS__;
303
304            $arrParents = $objQuery->select($col, $table, "", $parents);
305
306            unset($parents);
307            foreach ($arrParents as $rows) {
308                $parents[] = $rows['parent_class_combination_id'];
309
310                foreach ($arrRet as $child) {
311                    if ($child['parent_class_combination_id']
312                        == $rows['class_combination_id']) {
313                        $rows['product_id'] = $child['product_id'];
314                    }
315                }
316                $tmpParents[] = $rows;
317            }
318            $parentsClass = array_merge($parentsClass, $tmpParents);
319        }
320
321        // 末端から枝を作成
322        $tmpClass = array_merge($arrRet, $parentsClass);
323
324        foreach ($tmpClass as $val) {
325            $val['class_id' . $val['level']] = $val['class_id'];
326            $val['class_name' . $val['level']] = $val['class_name'];
327            $val['classcategory_name' . $val['level']] = $val['classcategory_name'];
328            $val['classcategory_id' . $val['level']] = $val['classcategory_id'];
329            $arrProductsClass[] = $val;
330        }
331
332        return $arrProductsClass;
333    }
334
335    /**
336     * 商品規格IDから商品規格を取得する.
337     */
338    function getProductsClass($productClassId) {
339        $objQuery =& SC_Query::getSingletonInstance();
340        $objQuery->setWhere('product_class_id = ?');
341        $objQuery->setOrder("T2.level DESC");
342        $results = $this->getProductsClassByQuery($objQuery, $productClassId);
343        $productsClass = $this->getProductsClassFull($results);
344        return $productsClass[0];
345    }
346
347    /**
348     * 複数の商品IDに紐づいた, 商品規格を取得する.
349     *
350     * @param array $productIds 商品IDの配列
351     * @return array 商品規格の配列
352     */
353    function getProductsClassByProductIds($productIds = array()) {
354        if (empty($productIds)) {
355            return array();
356        }
357        $objQuery =& SC_Query::getSingletonInstance();
358        $objQuery->setWhere('product_id IN (' . implode(', ', array_pad(array(), count($productIds), '?')) . ')');
359        $objQuery->setOrder("T2.level DESC");
360        return $this->getProductsClassByQuery($objQuery, $productIds);
361    }
362
363    /**
364     * 商品IDに紐づいた, 商品規格を階層ごとに取得する.
365     *
366     * @param array $productId 商品ID
367     * @return array 階層ごとの商品規格の配列
368     */
369    function getProductsClassLevelByProductId($productId) {
370        $results = $this->getProductsClassByProductIds(array($productId));
371        return $this->getProductsClassLevel($results);
372    }
373
374    /**
375     * 商品IDに紐づいた, 商品規格をすべての組み合わせごとに取得する.
376     *
377     * @param array $productId 商品ID
378     * @return array すべての組み合わせの商品規格の配列
379     */
380    function getProductsClassFullByProductId($productId) {
381        $results = $this->getProductsClassByProductIds(array($productId));
382        return $this->getProductsClassFull($results);
383    }
384
385    /**
386     * 商品規格の配列から, 商品規格を階層ごとに取得する.
387     *
388     * @access private
389     * @param array $productsClassResults 商品規格の結果の配列
390     * @return array 階層ごとの商品規格の配列
391     */
392    function getProductsClassLevel($productsClassResults) {
393        foreach ($productsClassResults as $row) {
394            $productsClassLevel["level" . $row['level']][] = $row;
395        }
396        return $productsClassLevel;
397    }
398
399    /**
400     * 商品規格の配列から, 商品規格のすべての組み合わせを取得する.
401     *
402     * @access private
403     * @param array $productsClassResults 商品規格の結果の配列
404     * @ array 階層ごとの商品規格の配列
405     */
406    function getProductsClassFull($productsClassResults) {
407        $results = $this->getProductsClassLevel($productsClassResults);
408        $productsClass = array();
409        if (SC_Utils_Ex::isBlank($results["level1"])
410            && SC_Utils_Ex::isBlank($results["level2"])) {
411            return $results["level"];
412        }
413
414        foreach ($results["level1"] as $level1) {
415            foreach ($results["level2"] as $level2) {
416                if ($level2['parent_class_combination_id'] == $level1['class_combination_id']) {
417                    $level1 = array_merge($level1, $level2);
418                }
419            }
420            $productsClass[] = $level1;
421        }
422        return $productsClass;
423    }
424
425    /**
426     * 商品詳細の結果から, 購入制限数を取得する.
427     *
428     * getDetailAndProductsClass() の結果から, 購入制限数を取得する.
429     *
430     * @param array $p 商品詳細の検索結果の配列
431     * @return integer 商品詳細の結果から求めた購入制限数.
432     * @see getDetailAndProductsClass()
433     */
434    function getBuyLimit($p) {
435        $limit = null;
436        if ($p['stock_unlimited'] != '1' && is_numeric($p['sale_limit'])) {
437            $limit = min($p['sale_limit'], $p['stock']);
438        } elseif (is_numeric($p['sale_limit'])) {
439            $limit = $p['sale_limit'];
440        } elseif ($p['stock_unlimited'] != '1') {
441            $limit = $p['stock'];
442        }
443        return $limit;
444    }
445
446    /**
447     * 商品詳細の SQL を取得する.
448     *
449     * @param string $where 商品詳細の WHERE 句
450     * @return string 商品詳細の SQL
451     */
452    function alldtlSQL($where = "") {
453        $whereCause = "";
454        if (!SC_Utils_Ex::isBlank($where)) {
455            $whereCause = " WHERE " . $where;
456        }
457        /*
458         * point_rate は商品規格(dtb_products_class)ごとに保持しているが,
459         * 商品(dtb_products)ごとの設定なので MAX のみを取得する.
460         */
461        $sql = <<< __EOS__
462            (
463             SELECT dtb_products.product_id,
464                    dtb_products.name,
465                    dtb_products.maker_id,
466                    dtb_products.rank,
467                    dtb_products.status,
468                    dtb_products.comment1,
469                    dtb_products.comment2,
470                    dtb_products.comment3,
471                    dtb_products.comment4,
472                    dtb_products.comment5,
473                    dtb_products.comment6,
474                    dtb_products.note,
475                    dtb_products.file1,
476                    dtb_products.file2,
477                    dtb_products.file3,
478                    dtb_products.file4,
479                    dtb_products.file5,
480                    dtb_products.file6,
481                    dtb_products.main_list_comment,
482                    dtb_products.main_list_image,
483                    dtb_products.main_comment,
484                    dtb_products.main_image,
485                    dtb_products.main_large_image,
486                    dtb_products.sub_title1,
487                    dtb_products.sub_comment1,
488                    dtb_products.sub_image1,
489                    dtb_products.sub_large_image1,
490                    dtb_products.sub_title2,
491                    dtb_products.sub_comment2,
492                    dtb_products.sub_image2,
493                    dtb_products.sub_large_image2,
494                    dtb_products.sub_title3,
495                    dtb_products.sub_comment3,
496                    dtb_products.sub_image3,
497                    dtb_products.sub_large_image3,
498                    dtb_products.sub_title4,
499                    dtb_products.sub_comment4,
500                    dtb_products.sub_image4,
501                    dtb_products.sub_large_image4,
502                    dtb_products.sub_title5,
503                    dtb_products.sub_comment5,
504                    dtb_products.sub_image5,
505                    dtb_products.sub_large_image5,
506                    dtb_products.sub_title6,
507                    dtb_products.sub_comment6,
508                    dtb_products.sub_image6,
509                    dtb_products.sub_large_image6,
510                    dtb_products.del_flg,
511                    dtb_products.creator_id,
512                    dtb_products.create_date,
513                    dtb_products.update_date,
514                    dtb_products.deliv_date_id,
515                    T4.product_code_min,
516                    T4.product_code_max,
517                    T4.price01_min,
518                    T4.price01_max,
519                    T4.price02_min,
520                    T4.price02_max,
521                    T4.stock_min,
522                    T4.stock_max,
523                    T4.stock_unlimited_min,
524                    T4.stock_unlimited_max,
525                    T4.point_rate,
526                    T4.class_count
527               FROM dtb_products
528               JOIN (
529                       SELECT product_id,
530                              MIN(product_code) AS product_code_min,
531                              MAX(product_code) AS product_code_max,
532                              MIN(price01) AS price01_min,
533                              MAX(price01) AS price01_max,
534                              MIN(price02) AS price02_min,
535                              MAX(price02) AS price02_max,
536                              MIN(stock) AS stock_min,
537                              MAX(stock) AS stock_max,
538                              MIN(stock_unlimited) AS stock_unlimited_min,
539                              MAX(stock_unlimited) AS stock_unlimited_max,
540                              MAX(point_rate) AS point_rate,
541                              COUNT(*) as class_count
542                         FROM dtb_products_class
543                       $whereCause
544                     GROUP BY product_id
545                     ) AS T4
546                 ON dtb_products.product_id = T4.product_id
547        ) AS alldtl
548__EOS__;
549        return $sql;
550    }
551
552    /**
553     * 商品規格ID1、2に紐づいた,product_class_idを取得する.
554     *
555     * @param int $productId 商品ID
556     * @param int $classcategory_id1 商品規格ID1
557     * @param int $classcategory_id2 商品規格ID2
558     * @return string product_class_id
559     */
560    function getClasscategoryIdsByProductClassId($productId, $classcategory_id1, $classcategory_id2) {
561        $objQuery = new SC_Query();
562        $col = "T1.product_id AS product_id,T1.product_class_id AS product_class_id,T1.classcategory_id1 AS classcategory_id1,T1.classcategory_id2 AS classcategory_id2";
563        $table = <<< __EOS__
564            (SELECT
565                pc.product_code AS product_code,
566                pc.product_id AS product_id,
567                pc.product_class_id AS product_class_id,
568                pc.class_combination_id AS class_combination_id,
569                COALESCE(cc2.classcategory_id,0) AS classcategory_id1,
570                COALESCE(cc1.classcategory_id,0) AS classcategory_id2
571            FROM
572                dtb_products_class pc LEFT JOIN dtb_class_combination cc1 ON pc.class_combination_id = cc1.class_combination_id
573                LEFT JOIN dtb_class_combination cc2 ON cc1.parent_class_combination_id = cc2.class_combination_id) T1
574__EOS__;
575        $where = "T1.product_id = ? AND T1.classcategory_id1 = ? AND T1.classcategory_id2 = ?";
576        $arrRet = $objQuery->select($col, $table, $where,
577                                    array($productId, $classcategory_id1, $classcategory_id2));
578        return $arrRet[0]['product_class_id'];
579    }
580
581}
582?>
Note: See TracBrowser for help on using the repository browser.