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

Revision 18820, 17.4 KB checked in by nanasess, 14 years ago (diff)

#781(規格のデータベースを木構造に)

  • 規格の無い商品が品切れになってしまう不具合修正
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     * 商品IDに紐づく商品規格を自分自身に設定する.
127     *
128     * 引数の商品IDの配列に紐づく商品規格を取得し, 自分自身のフィールドに
129     * 設定する.
130     *
131     * @param array $arrProductId 商品ID の配列
132     * @return void
133     */
134    function setProductsClassByProductIds($arrProductId) {
135
136        foreach ($arrProductId as $productId) {
137            $rows[$productId] = $this->getProductsClassFullByProductId($productId);
138        }
139
140        $arrProductsClass = array();
141        foreach ($rows as $productId => $arrProductClass) {
142            $classCats1 = array();
143            $classCats1[''] = '選択してください';
144
145            // 規格1クラス名
146            $this->className1[$productId] =
147                isset($arrProductClass[0]['class_name1'])
148                ? $arrProductClass[0]['class_name1']
149                : '';
150
151            // 規格2クラス名
152            $this->className2[$productId] =
153                isset($arrProductClass[0]['class_name2'])
154                ? $arrProductClass[0]['class_name2']
155                : '';
156
157            // 規格1が設定されている
158            $this->classCat1_find[$productId] = (!SC_Utils_Ex::isBlank($arrProductClass[0]['classcategory_id1']));
159            // 規格2が設定されている
160            $this->classCat2_find[$productId] = (!SC_Utils_Ex::isBlank($arrProductClass[0]['classcategory_id2']));
161
162            $this->stock_find[$productId] = false;
163            $classCategories = array();
164            $classCategories['']['']['name'] = '選択してください';
165            foreach ($arrProductClass as $productsClass) {
166                $productsClass1 = $productsClass['classcategory_id1'];
167                $productsClass2 = $productsClass['classcategory_id2'];
168                $classCategories[$productsClass1]['']['name'] = '選択してください';
169                // 在庫
170                $stock_find_class = ($productsClass['stock_unlimited'] || $productsClass['stock'] > 0);
171
172                $classCategories[$productsClass1][$productsClass2]['name'] = $productsClass['name2'] . ($stock_find_class ? '' : ' (品切れ中)');
173
174                $classCategories[$productsClass1][$productsClass2]['stock_find'] = $stock_find_class;
175
176                if ($stock_find_class) {
177                    $this->stock_find[$productId] = true;
178                }
179
180                if (!in_array($classcat_id1, $classCats1)) {
181                    $classCats1[$productsClass1] = $productsClass['name1']
182                        . ($productsClass2 == 0 && !$stock_find_class ? ' (品切れ中)' : '');
183                }
184
185                // 価格
186                $classCategories[$productsClass1][$productsClass2]['price01']
187                    = strlen($productsClass['price01'])
188                    ? number_format(SC_Helper_DB_Ex::sfPreTax($productsClass['price01']))
189                    : '';
190
191                $classCategories[$productsClass1][$productsClass2]['price02']
192                    = strlen($productsClass['price02'])
193                    ? number_format(SC_Helper_DB_Ex::sfPreTax($productsClass['price02']))
194                    : '';
195
196                // ポイント
197                // XXX sfPrePoint() の第4パラメータは、処理にバグがあるため現状省略している。(http://xoops.ec-cube.net/modules/newbb/viewtopic.php?topic_id=3540&forum=1&post_id=13853#forumpost13853)
198                $classCategories[$productsClass1][$productsClass2]['point']
199                    = SC_Utils_Ex::sfPrePoint($productsClass['price02'], $productsClass['point_rate']);
200
201                // 商品コード
202                $classCategories[$productsClass1][$productsClass2]['product_code'] = $productsClass['product_code'];
203            }
204
205            $this->classCategories[$productId] = $classCategories;
206
207            // 規格1
208            $this->classCats1[$productId] = $classCats1;
209        }
210    }
211
212    /**
213     * 複数の商品IDに紐づいた, 商品規格を取得する.
214     *
215     * @param array $productIds 商品IDの配列
216     * @return array 商品規格の配列
217     */
218    function getProductsClassByProductIds($productIds = array()) {
219        if (empty($productIds)) {
220            return array();
221        }
222        $objQuery =& SC_Query::getSingletonInstance();
223        $objQuery->setWhere('product_id IN (' . implode(', ', array_pad(array(), count($productIds), '?')) . ')');
224        $objQuery->setOrder("T2.level DESC");
225        // 末端の規格を取得
226        $col = <<< __EOS__
227            T1.product_id,
228            T1.stock,
229            T1.stock_unlimited,
230            T1.price01,
231            T1.price02,
232            T1.point_rate,
233            T1.product_code,
234            T1.product_class_id,
235            T1.del_flg,
236            T1.down,
237            T1.down_filename,
238            T1.down_realfilename,
239            T2.class_combination_id,
240            T2.parent_class_combination_id,
241            T2.classcategory_id,
242            T2.level,
243            T3.name,
244            T4.name AS class_name,
245            T4.class_id
246__EOS__;
247        $table = <<< __EOS__
248                      dtb_products_class T1
249            LEFT JOIN dtb_class_combination T2
250                   ON T1.class_combination_id = T2.class_combination_id
251            LEFT JOIN dtb_classcategory T3
252                   ON T2.classcategory_id = T3.classcategory_id
253            LEFT JOIN dtb_class T4
254                   ON T3.class_id = T4.class_id
255__EOS__;
256        $arrRet = $objQuery->select($col, $table, "", $productIds);
257        $levels = array();
258        $parents = array();
259        $i = 0;
260        foreach ($arrRet as $rows) {
261            if($rows['level']==""){
262                $rows['level']="1";
263                $arrRet[$i]['level'] = $rows['level'];
264
265            }
266            $levels[] = $rows['level'];
267            $parents[] = $rows['parent_class_combination_id'];
268        }
269        $level = max($levels);
270        $parentsClass = array();
271        // 階層分の親を取得
272        for ($i = 0; $i < $level -1; $i++) {
273            $objQuery =& SC_Query::getSingletonInstance();
274            $objQuery->setWhere('T1.class_combination_id IN (' . implode(', ', array_pad(array(), count($parents), '?')) . ')');
275
276            $col = <<< __EOS__
277                T1.class_combination_id,
278                T1.classcategory_id,
279                T1.parent_class_combination_id,
280                T1.level,
281                T2.name,
282                T3.name AS class_name,
283                T3.class_id
284__EOS__;
285            $table = <<< __EOS__
286                          dtb_class_combination T1
287                LEFT JOIN dtb_classcategory T2
288                       ON T1.classcategory_id = T2.classcategory_id
289                LEFT JOIN dtb_class T3
290                       ON T2.class_id = T3.class_id
291__EOS__;
292
293            $arrParents = $objQuery->select($col, $table, "", $parents);
294
295            unset($parents);
296            foreach ($arrParents as $rows) {
297                $parents[] = $rows['parent_class_combination_id'];
298
299                foreach ($arrRet as $child) {
300                    if ($child['parent_class_combination_id']
301                        == $rows['class_combination_id']) {
302                        $rows['product_id'] = $child['product_id'];
303                    }
304                }
305                $tmpParents[] = $rows;
306            }
307            $parentsClass = array_merge($parentsClass, $tmpParents);
308        }
309
310        // 末端から枝を作成
311        $tmpClass = array_merge($arrRet, $parentsClass);
312
313        foreach ($tmpClass as $val) {
314            $val['class_id' . $val['level']] = $val['class_id'];
315            $val['class_name' . $val['level']] = $val['class_name'];
316            $val['name' . $val['level']] = $val['name'];
317            $val['classcategory_id' . $val['level']] = $val['classcategory_id'];
318            $arrProductsClass[] = $val;
319        }
320
321        return $arrProductsClass;
322    }
323
324    /**
325     * 商品IDに紐づいた, 商品規格を階層ごとに取得する.
326     *
327     * @param array $productId 商品IDの配列
328     * @return array 階層ごとの商品規格の配列
329     */
330    function getProductsClassLevelByProductId($productId) {
331        $results = $this->getProductsClassByProductIds(array($productId));
332        foreach ($results as $row) {
333            $productsClassLevel["level" . $row['level']][] = $row;
334        }
335        return $productsClassLevel;
336    }
337
338    /**
339     * 商品IDに紐づいた, 商品規格をすべての組み合わせごとに取得する.
340     *
341     * @param array $productId 商品IDの配列
342     * @return array すべての組み合わせの商品規格の配列
343     */
344    function getProductsClassFullByProductId($productId) {
345        $results = $this->getProductsClassLevelByProductId($productId);
346        $productsClass = array();
347        if (SC_Utils_Ex::isBlank($results["level1"]) && SC_Utils_Ex::isBlank($results["level2"])) {
348            return $results["level"];
349        }
350
351        foreach ($results["level1"] as $level1) {
352            foreach ($results["level2"] as $level2) {
353                if ($level2['parent_class_combination_id'] == $level1['class_combination_id']) {
354                    $level1 = array_merge($level1, $level2);
355                }
356            }
357            $productsClass[] = $level1;
358        }
359        return $productsClass;
360    }
361
362    /**
363     * 商品詳細の SQL を取得する.
364     *
365     * @param string $where 商品詳細の WHERE 句
366     * @return string 商品詳細の SQL
367     */
368    function alldtlSQL($where = "") {
369        $whereCause = "";
370        if (!SC_Utils_Ex::isBlank($where)) {
371            $whereCause = " WHERE " . $where;
372        }
373
374        $sql = <<< __EOS__
375            (
376             SELECT dtb_products.product_id,
377                    dtb_products.name,
378                    dtb_products.maker_id,
379                    dtb_products.rank,
380                    dtb_products.status,
381                    dtb_products.comment1,
382                    dtb_products.comment2,
383                    dtb_products.comment3,
384                    dtb_products.comment4,
385                    dtb_products.comment5,
386                    dtb_products.comment6,
387                    dtb_products.note,
388                    dtb_products.file1,
389                    dtb_products.file2,
390                    dtb_products.file3,
391                    dtb_products.file4,
392                    dtb_products.file5,
393                    dtb_products.file6,
394                    dtb_products.main_list_comment,
395                    dtb_products.main_list_image,
396                    dtb_products.main_comment,
397                    dtb_products.main_image,
398                    dtb_products.main_large_image,
399                    dtb_products.sub_title1,
400                    dtb_products.sub_comment1,
401                    dtb_products.sub_image1,
402                    dtb_products.sub_large_image1,
403                    dtb_products.sub_title2,
404                    dtb_products.sub_comment2,
405                    dtb_products.sub_image2,
406                    dtb_products.sub_large_image2,
407                    dtb_products.sub_title3,
408                    dtb_products.sub_comment3,
409                    dtb_products.sub_image3,
410                    dtb_products.sub_large_image3,
411                    dtb_products.sub_title4,
412                    dtb_products.sub_comment4,
413                    dtb_products.sub_image4,
414                    dtb_products.sub_large_image4,
415                    dtb_products.sub_title5,
416                    dtb_products.sub_comment5,
417                    dtb_products.sub_image5,
418                    dtb_products.sub_large_image5,
419                    dtb_products.sub_title6,
420                    dtb_products.sub_comment6,
421                    dtb_products.sub_image6,
422                    dtb_products.sub_large_image6,
423                    dtb_products.del_flg,
424                    dtb_products.creator_id,
425                    dtb_products.create_date,
426                    dtb_products.update_date,
427                    dtb_products.deliv_date_id,
428                    T4.product_code_min,
429                    T4.product_code_max,
430                    T4.price01_min,
431                    T4.price01_max,
432                    T4.price02_min,
433                    T4.price02_max,
434                    T4.stock_min,
435                    T4.stock_max,
436                    T4.stock_unlimited_min,
437                    T4.stock_unlimited_max,
438                    T4.class_count
439               FROM dtb_products
440               JOIN (
441                       SELECT product_id,
442                              MIN(product_code) AS product_code_min,
443                              MAX(product_code) AS product_code_max,
444                              MIN(price01) AS price01_min,
445                              MAX(price01) AS price01_max,
446                              MIN(price02) AS price02_min,
447                              MAX(price02) AS price02_max,
448                              MIN(stock) AS stock_min,
449                              MAX(stock) AS stock_max,
450                              MIN(stock_unlimited) AS stock_unlimited_min,
451                              MAX(stock_unlimited) AS stock_unlimited_max,
452                              COUNT(*) as class_count
453                         FROM dtb_products_class
454                       $whereCause
455                     GROUP BY product_id
456                     ) AS T4
457                 ON dtb_products.product_id = T4.product_id
458        ) AS alldtl
459__EOS__;
460        return $sql;
461    }
462}
463?>
Note: See TracBrowser for help on using the repository browser.