Completed
Push — master ( 8f8233...93b489 )
by Lawrence
02:09
created

Combination::getAttributePricing()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 9
rs 9.6666
cc 1
eloc 6
nc 1
nop 1
1
<?php
2
3
namespace ABM\Wasabi;
4
5
use Analog\Analog;
6
7
class Combination extends Prestashop
8
{
9
     /**
10
     * @param string $data
11
     */
12
    private function getCombinationData($data)
13
    {
14
        $product = substr($data, 0, strpos($data, ','));
15
        $combinations = [];
16
        $vars = explode(',', $data);
17
        Analog::log("Product variables: $data");
18
        $choices = array_slice($vars, 1);
19
        $id_product_attribute = $this->getAttribute($product, $choices);
20
        Analog::log("Product combination: $id_product_attribute");
21
        $combo_groups = $this->getCombination($product, $id_product_attribute);
22
        if (!empty($combo_groups) && is_array($combo_groups) && $combo_groups) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $combo_groups of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
23
            foreach ($combo_groups as $k => $row) {
24
                $combinations = $this->buildAttributes($combinations, $id_product_attribute, $row);
25
            }
26
        }
27
28
        return $combinations;
29
    }
30
31
  
32
    /**
33
     * @param string $product
34
     */
35
    private function getAttribute($product, $choices)
36
    {
37
        $sql = 'SELECT pac.id_product_attribute from '._DB_PREFIX_.'product_attribute_combination as pac
38
                LEFT JOIN  '._DB_PREFIX_.'product_attribute as ppa on ppa.id_product_attribute = pac.id_product_attribute
39
                LEFT JOIN '._DB_PREFIX_.'attribute a ON (a.id_attribute = pac.id_attribute)
40
                WHERE ppa.id_product = '.$product;
41
        foreach ($choices as $value) {
42
            $sql .= ' AND pac.id_product_attribute IN
43
                    ( SELECT pac.id_product_attribute from '._DB_PREFIX_.'product_attribute_combination as pac
44
                    WHERE pac.id_attribute = '.(int) $value.')  ';
45
        }
46
        $sql .= ' GROUP BY pac.id_product_attribute';
47
        $id_product_attribute = $this->dbConn->fetchColumn($sql);
48
49
        return $id_product_attribute;
50
    }
51
52
    /**
53
     * @param null|string $id_product_attribute
54
     */
55
    private function buildAttributes($combinations, $id_product_attribute, $row)
56
    {
57
        $combinationSet = [];
58
        $specific_price = null;
59
60
        $combinations['name'] = $row['product_name'];
61
        $typcheck = ['id_product', 'price', 'base_price', 'price', 'ecotax', 'weight', 'quantity', 'unit_impact', 'minimal_quantity'];
62
63
        foreach ($typcheck as $key => $value) {
64
            ((strpos($value, 'price') !== false) || (strpos($value, 'weight') !== false) || (strpos($value, 'ecotax') !== false) || (strpos($value, 'impact') !== false)) ? $combinations[$value] = (float) $row[$value] : $combinations[$value] = (int) $row[$value];
65
        }
66
        $combinations['attributes_values'][$row['id_attribute_group']] = $row['attribute_name'];
67
        $combinations['attributes'][] = (int) $row['id_attribute'];
68
69
        list($combinationSet[(int) $row['id_product_attribute']], $combinations['specific_price']) = $this->getCombinationSpecificPrice($combinationSet, $row, $id_product_attribute);
70
71
        $combinations['reference'] = $row['reference'];
72
        $combinations['available_date'] = $this->getAvailableDate($row);
73
        $combinations['image'] = $this->getComboImage($id_product_attribute);
74
        $combinations['final_price'] = $this->getFinalPrice($row, $specific_price);
75
76
        return $combinations;
77
    }
78
79
    private function getFinalPrice($row, $specific_price)
80
    {
81
        $specific_price['price'] != 0 ? $final_price = (((float) $row['base_price'] + (float) $row['price']) * (((int) 100 - $specific_price['reduction_percent']) / 100)) : $final_price = (float) $row['base_price'] + (float) $row['price'];
82
83
        return $final_price;
84
    }
85
86
    private function getAvailableDate($row)
87
    {
88
        ($row['available_date'] != '0000-00-00') ? $dater = $row['available_date'] : $dater = '';
89
90
        return $dater;
91
    }
92
93
    /**
94
     * @param null|string $id_product_attribute
95
     */
96
    private function getCombinationSpecificPrice($combinationSet, $row, $id_product_attribute)
97
    {
98
        // Call getSpecificPrice in order to set $combination_specific_price
99
                if (!isset($combinationSet[(int) $row['id_product_attribute']])) {
100
                    $specific_price = $this->getSpecificPrice($id_product_attribute, $row['id_product']);
101
                    $combinationSet[(int) $row['id_product_attribute']] = true;
102
103
                    return [$combinationSet, $specific_price];
104
                } else {
105
                    return [false, null];
106
                }
107
    }
108
109
    /**
110
     * @param null|string $id_product_attribute
111
     * @param string      $product
112
     */
113
    private function getCombination($product, $id_product_attribute)
114
    {
115
        $combo = $this->getAttributeBase($id_product_attribute);
116
117
        if (is_array($combo)) {
118
            foreach ($combo as $key => $value) {
119
                $combo['base_price'] = (float) Product::getOrderPrice($product);
0 ignored issues
show
Bug introduced by
The method getOrderPrice() cannot be called from this context as it is declared private in class ABM\Wasabi\Product.

This check looks for access to methods that are not accessible from the current context.

If you need to make a method accessible to another context you can raise its visibility level in the defining class.

Loading history...
120
                $combo['quantity'] = (int) $this->getStockQuantity($product, $id_product_attribute);
121
                $combo['id_product'] = (int) $product;
122
                $combo['product_name'] = (int) Product::getProductName($product);
0 ignored issues
show
Bug introduced by
The method getProductName() cannot be called from this context as it is declared private in class ABM\Wasabi\Product.

This check looks for access to methods that are not accessible from the current context.

If you need to make a method accessible to another context you can raise its visibility level in the defining class.

Loading history...
123
                $pricing = $this->getAttributePricing($id_product_attribute);
124
                foreach ($pricing as $ki => $val) {
0 ignored issues
show
Bug introduced by
The expression $pricing of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
125
                    $combo[$ki] = $val;
126
                }
127
            }
128
        }
129
130
        return $combo;
131
    }
132
133
    /**
134
     * @param null|string $attribute
135
     */
136
    private function getAttributeBase($attribute)
137
    {
138
        $sql = 'SELECT ag.id_attribute_group, ag.is_color_group, agl.name AS group_name, agl.public_name AS public_group_name,
139
                    a.id_attribute, al.name AS attribute_name, a.color AS attribute_color, ag.group_type, pac.id_product_attribute
140
            FROM '._DB_PREFIX_.'product_attribute_combination pac
141
            LEFT JOIN '._DB_PREFIX_.'attribute a ON (a.id_attribute = pac.id_attribute)
142
            LEFT JOIN  '._DB_PREFIX_.'attribute_group ag ON (ag.id_attribute_group = a.id_attribute_group)
143
            LEFT JOIN '._DB_PREFIX_.'attribute_lang al ON (a.id_attribute = al.id_attribute)
144
            LEFT JOIN '._DB_PREFIX_.'attribute_group_lang agl ON (ag.id_attribute_group = agl.id_attribute_group)
145
            WHERE pac.id_product_attribute='.(int) $attribute;
146
        $result = $this->dbConn->fetchRowMany($sql);
147
148
        return $result;
149
    }
150
151
    /**
152
     * @param null|string $attribute
153
     * @param string      $product
154
     */
155
    private function getStockQuantity($product, $attribute)
156
    {
157
        $sql = 'SELECT stock.quantity from '._DB_PREFIX_.'stock_available as stock WHERE stock.id_product = '.(int) $product.'AND stock.id_product_attribute = '.(int) $attribute;
158
        $result = $this->dbConn->fetchColumn($sql);
159
160
        return $result;
161
    }
162
163
    /**
164
     * @param null|string $attribute
165
     */
166
    private function getAttributePricing($attribute)
167
    {
168
        $sql = 'SELECT pas.price, pas.ecotax, pas.weight, pas.default_on, pa.reference, pas.unit_price_impact, 
169
                pas.minimal_quantity, pas.available_date FROM '._DB_PREFIX_.'product_attribute_shop pas 
170
                WHERE pas.id_product_attribute = '.(int) $attribute;
171
        $result = $this->dbConn->fetchRowMany($sql);
172
173
        return $result;
174
    }
175
176
    /**
177
     * @param null|string $id_product_attribute
178
     * @param string      $id_product
179
     */
180
    private function getSpecificPrice($id_product_attribute, $id_product)
181
    {
182
        $specific_price = [];
183
        if ($this->getNumberSpecificPrice($id_product_attribute, $id_product) > 0) {
184
            $result = $this->getSpecificPriceData($id_product_attribute, $id_product, date('Y-m-d H:i:s'));
185
            $specific_price['price'] = $result['price'];
186
            $specific_price['id_product_attribute'] = $result['id_product_attribute'];
187
            $specific_price['reduction_percent'] = (int) 100 * $result['reduction'];
188
            $specific_price['reduction_price'] = 0;
189
            $specific_price['reduction_type'] = $result['reduction_type'];
190
191
            return $specific_price;
192
        }
193
    }
194
195
    /**
196
     * @param string      $now
197
     * @param null|string $id_product_attribute
198
     * @param string      $id_product
199
     */
200
    private function getSpecificPriceData($id_product_attribute, $id_product, $now)
201
    {
202
        $sql = 'SELECT * FROM '._DB_PREFIX_.'specific_price
203
                            WWHERE id_product = '.(int) $id_product.'
204
                            AND id_product_attribute IN (0, '.(int) $id_product_attribute.')
205
                            AND (
206
                                   (from = \'0000-00-00 00:00:00\' OR \''.$now.'\' >= from)
207
                            AND
208
                                     (to = \'0000-00-00 00:00:00\' OR \''.$now.'\' <= to)
209
                            ) ';
210
211
        $sql .= ' ORDER BY id_product_attribute DESC, from_quantity DESC, id_specific_price_rule ASC';
212
213
        $result = $this->dbConn->fetchRow($sql);
214
215
        return $result;
216
    }
217
218
    /**
219
     * @param null|string $id_product_attribute
220
     * @param string      $id_product
221
     */
222
    private function getNumberSpecificPrice($id_product_attribute, $id_product)
223
    {
224
        $sql = 'SELECT COUNT(*) FROM '._DB_PREFIX_.'specific_price WHERE id_product = '.(int) $id_product.' AND id_product_attribute = 0';
225
        $spec = $this->dbConn->fetchColumn($sql);
226
        if ($spec == 0) {
227
            $sql = 'SELECT COUNT(*) FROM '._DB_PREFIX_.'specific_price WHERE id_product_attribute = '.(int) $id_product_attribute;
228
            $spec = $this->dbConn->fetchColumn($sql);
229
        }
230
231
        return $spec;
232
    }
233
234
    /**
235
     * @param null|string $id_product_attribute
236
     */
237
    private function getComboImage($id_product_attribute)
238
    {
239
        $sql = 'SELECT pai.id_imageas image
240
                        FROM '._DB_PREFIX_.'product_attribute_image pai
241
                        LEFT JOIN '._DB_PREFIX_.'image_lang il ON (il.id_image = pai.id_image)
242
                        LEFT JOIN '._DB_PREFIX_.'image i ON (i.id_image = pai.id_image)
243
                        WHERE pai.id_product_attribute = '.(int) $id_product_attribute.' ORDER by i.position';
244
        $image = $this->dbConn->fetchColumn($sql);
245
        ($image !== false) ? $imager = (int) $image : $imager = -1;
246
247
        return $imager;
248
    }
249
250
}
251