Passed
Push — master ( 44cbe3...1a2823 )
by Jason
01:49
created

AddToCartForm::getProductOptionSet()   A

Complexity

Conditions 5
Paths 7

Size

Total Lines 42
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 24
nc 7
nop 0
dl 0
loc 42
rs 9.2248
c 0
b 0
f 0
1
<?php
2
3
namespace Dynamic\Foxy\Form;
4
5
use Dynamic\Foxy\Extension\Purchasable;
6
use Dynamic\Foxy\Extension\Shippable;
7
use Dynamic\Foxy\Model\Foxy;
8
use Dynamic\Foxy\Model\FoxyHelper;
9
use Dynamic\Foxy\Model\ProductOption;
10
use Dynamic\Foxy\Model\Setting;
11
use SilverStripe\Forms\CompositeField;
12
use SilverStripe\Forms\DropdownField;
13
use SilverStripe\Forms\FieldList;
14
use SilverStripe\Forms\Form;
15
use SilverStripe\Forms\FormAction;
16
use SilverStripe\Forms\HeaderField;
17
use SilverStripe\Forms\HiddenField;
18
use SilverStripe\Forms\RequiredFields;
19
20
class AddToCartForm extends Form
21
{
22
    /**
23
     * @var
24
     */
25
    protected $foxy_setting;
26
27
    /**
28
     * @var
29
     */
30
    private $product;
31
32
    /**
33
     * @param $foxySetting
34
     *
35
     * @return $this
36
     */
37
    public function setFoxySetting($foxySetting)
38
    {
39
        $foxySetting = $foxySetting === null ? Setting::current_foxy_setting() : $foxySetting;
40
        if ($foxySetting instanceof Setting) {
41
            $this->foxy_setting = $foxySetting;
42
            return $this;
43
        }
44
        throw new \InvalidArgumentException('$foxySetting needs to be an instance of Foxy Setting.');
45
    }
46
47
    /**
48
     * @return FoxyStripeSetting
0 ignored issues
show
Bug introduced by
The type Dynamic\Foxy\Form\FoxyStripeSetting was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
49
     */
50
    public function getFoxySetting()
51
    {
52
        if (!$this->foxy_setting) {
53
            $this->setFoxySetting(Setting::current_foxy_setting());
54
        }
55
        return $this->foxy_setting;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->foxy_setting returns the type Dynamic\Foxy\Model\Setting which is incompatible with the documented return type Dynamic\Foxy\Form\FoxyStripeSetting.
Loading history...
56
    }
57
58
    /**
59
     * @param $product
60
     *
61
     * @return $this
62
     */
63
    public function setProduct($product)
64
    {
65
        if ($product->isProduct()) {
66
            $this->product = $product;
67
            return $this;
68
        }
69
        throw new \InvalidArgumentException('$product needs to implement a Foxy DataExtension.');
70
    }
71
72
    /**
73
     * @return ProductPage
0 ignored issues
show
Bug introduced by
The type Dynamic\Foxy\Form\ProductPage was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
74
     */
75
    public function getProduct()
76
    {
77
        return $this->product;
78
    }
79
80
    /**
81
     * AddToCartForm constructor.
82
     *
83
     * @param ContentController $controller
0 ignored issues
show
Bug introduced by
The type Dynamic\Foxy\Form\ContentController was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
84
     * @param string $name
85
     * @param FieldList|null $fields
86
     * @param FieldList|null $actions
87
     * @param null $validator
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $validator is correct as it would always require null to be passed?
Loading history...
88
     * @param null $product
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $product is correct as it would always require null to be passed?
Loading history...
89
     * @param null $foxySetting
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $foxySetting is correct as it would always require null to be passed?
Loading history...
90
     *
91
     */
92
    public function __construct(
93
        $controller,
94
        $name,
95
        FieldList $fields = null,
96
        FieldList $actions = null,
97
        $validator = null,
98
        $product = null,
99
        $foxySetting = null
100
    ) {
101
        $this->setProduct($product);
102
        $this->setFoxySetting($foxySetting);
103
104
        $fields = ($fields != null && $fields->exists()) ?
105
            $this->getProductFields($fields) :
106
            $this->getProductFields(FieldList::create());
107
108
        $actions = ($actions != null && $actions->exists()) ?
109
            $this->getProductActions($actions) :
110
            $this->getProductActions(FieldList::create());
111
112
        $validator = (!empty($validator) || $validator != null) ? $validator : RequiredFields::create();
113
114
        parent::__construct($controller, $name, $fields, $actions, $validator);
115
116
        //have to call after parent::__construct()
117
        $this->setAttribute('action', FoxyHelper::FormActionURL());
118
        $this->disableSecurityToken();
119
        $this->setHTMLID($this->getTemplateHelper()->generateFormID($this) . "_{$product->ID}");
120
    }
121
122
    /**
123
     * @param FieldList $fields
124
     *
125
     * @return FieldList
126
     */
127
    protected function getProductFields(FieldList $fields)
128
    {
129
        $hiddenTitle = ($this->product->ReceiptTitle) ?
130
            htmlspecialchars($this->product->ReceiptTitle) :
131
            htmlspecialchars($this->product->Title);
132
        $code = $this->product->Code;
133
134
        if ($this->product->isAvailable()) {
135
            $fields->push(
136
                HiddenField::create('name')
137
                    ->setValue(
138
                        self::getGeneratedValue($code, 'name', $hiddenTitle, 'value')
139
                    )
140
            );
141
142
            $fields->push(
143
                HiddenField::create('category')
144
                    ->setValue(
145
                        self::getGeneratedValue($code, 'category', $this->product->FoxyCategory()->Code, 'value')
146
                    )
147
            );
148
149
            $fields->push(
150
                HiddenField::create('code')
151
                    ->setValue(
152
                        self::getGeneratedValue($code, 'code', $this->product->Code, 'value')
153
                    )
154
            );
155
156
            $fields->push(
157
                HiddenField::create('product_id')
158
                    ->setValue(
159
                        self::getGeneratedValue($code, 'product_id', $this->product->ID, 'value')
160
                    )
161
                    ->setName('h:product_id')
162
            );
163
164
            $fields->push(
165
                HiddenField::create('price')
166
                    ->setValue(
167
                        self::getGeneratedValue($code, 'price', $this->product->Price, 'value')
168
                    )
169
            );
170
171
            if ($this->product->hasExtension(Shippable::class)) {
172
                if ($this->product->Weight > 0) {
173
                    $fields->push(
174
                        HiddenField::create('weight')
175
                            ->setValue(
176
                                self::getGeneratedValue($code, 'weight', $this->product->Weight, 'value')
177
                            )
178
                    );
179
                }
180
            }
181
182
            $image = null;
183
            if ($this->product->hasMethod('getImage')) {
184
                if ($this->product->getImage()) {
185
                    $image = $this->product->getImage()->CMSThumbnail()->absoluteURL;
186
                }
187
                if ($image) {
188
                    $fields->push(
189
                        HiddenField::create('image')
190
                            ->setValue(
191
                                self::getGeneratedValue($code, 'image', $image, 'value')
192
                            )
193
                    );
194
                }
195
            }
196
197
            $optionsSet = $this->getProductOptionSet();
198
            $fields->push($optionsSet);
199
            $quantityMax = (FoxyHelper::config()->get('max_quantity' != null)) ?
0 ignored issues
show
Unused Code introduced by
The assignment to $quantityMax is dead and can be removed.
Loading history...
200
                FoxyHelper::config()->get('MaxQuantity') :
201
                10;
202
            $fields->push(QuantityField::create('x:visibleQuantity')->setTitle('Quantity')->setValue(1));
203
            $fields->push(
204
                HiddenField::create('quantity')
205
                    ->setValue(
206
                        self::getGeneratedValue($code, 'quantity', 1, 'value')
207
                    )
208
            );
209
210
            $fields->push(
211
                HeaderField::create('submitPrice', '$' . $this->product->Price, 4)
212
                    ->addExtraClass('submit-price')
213
            );
214
            $fields->push(
215
                $unavailable = HeaderField::create('unavailableText', 'Selection unavailable', 4)
216
                    ->addExtraClass('unavailable-text')
217
            );
218
            if (!empty(trim($this->foxy_setting->StoreDomain)) && $this->product->isAvailable()) {
219
                $unavailable->addExtraClass('hidden');
220
            }
221
        } else {
222
            $fields->push(HeaderField::create('unavailableText', 'currently unavaiable', 4));
223
        }
224
225
        $this->extend('updateProductFields', $fields);
226
227
        return $fields;
228
    }
229
230
    /**
231
     * @param FieldList $actions
232
     *
233
     * @return FieldList
234
     */
235
    protected function getProductActions(FieldList $actions)
236
    {
237
        if (!empty(trim($this->foxy_setting->StoreDomain)) && $this->product->isAvailable()) {
238
            $actions->push(
239
                FormAction::create(
240
                    'x:submit',
241
                    _t(__CLASS__ . '.AddToCart', 'Add to Cart')
242
                )
243
                    ->addExtraClass('fs-add-to-cart-button')
244
                    ->setName('x:submit')
245
            );
246
        }
247
248
        $this->extend('updateProductActions', $actions);
249
250
        return $actions;
251
    }
252
253
    /**
254
     * @param null $productCode
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $productCode is correct as it would always require null to be passed?
Loading history...
255
     * @param null $optionName
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $optionName is correct as it would always require null to be passed?
Loading history...
256
     * @param null $optionValue
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $optionValue is correct as it would always require null to be passed?
Loading history...
257
     * @param string $method
258
     * @param bool $output
259
     * @param bool $urlEncode
260
     *
261
     * @return null|string
262
     */
263
    // todo - Purchasable Extension or AddToCartForm? protected in Form
264
    public static function getGeneratedValue(
265
        $productCode = null,
266
        $optionName = null,
267
        $optionValue = null,
268
        $method = 'name',
269
        $output = false,
270
        $urlEncode = false
271
    ) {
272
        $optionName = ($optionName !== null) ? preg_replace('/\s/', '_', $optionName) : $optionName;
0 ignored issues
show
introduced by
The condition $optionName !== null is always false.
Loading history...
273
        $helper = FoxyHelper::create();
274
275
        return $helper::fc_hash_value($productCode, $optionName, $optionValue, $method, $output, $urlEncode);
276
    }
277
278
    /**
279
     * @return CompositeField
280
     */
281
    protected function getProductOptionSet()
282
    {
283
        /** @var CompositeField $optionsSet */
284
        $optionsSet = CompositeField::create();
285
286
        $types = $this->product->OptionTypes();
287
288
        foreach ($types as $type) {
289
            $title = $type->Title;
290
            $fieldName = preg_replace('/\s/', '_', $title);
291
            $disabled = [];
292
            $fullOptions = [];
293
294
            foreach ($type->Options() as $option) {
295
                $option = $this->setAvailability($option);
296
                $name = self::getGeneratedValue(
297
                    $this->product->Code,
298
                    $type->Title,
299
                    $option->getGeneratedValue(),
300
                    'value'
301
                );
302
303
                $fullOptions[$name] = $option->getGeneratedTitle();
304
                if (!$option->Availability) {
305
                    array_push($disabled, $name);
306
                }
307
            }
308
309
            $optionsSet->push(
310
                $dropdown = DropdownField::create($fieldName, $title, $fullOptions)->setTitle($title)
311
            );
312
313
            if (!empty($disabled)) {
314
                $dropdown->setDisabledItems($disabled);
315
            }
316
317
            $dropdown->addExtraClass("product-options");
318
        }
319
320
        $optionsSet->addExtraClass('foxycartOptionsContainer');
321
322
        return $optionsSet;
323
    }
324
325
    /**
326
     * @param OptionItem $option
0 ignored issues
show
Bug introduced by
The type Dynamic\Foxy\Form\OptionItem was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
327
     * @return OptionItem
328
     */
329
    protected function setAvailability(ProductOption $option)
330
    {
331
        $option->Available = ($option->getAvailability()) ? true : false;
0 ignored issues
show
Bug Best Practice introduced by
The property Available does not exist on Dynamic\Foxy\Model\ProductOption. Since you implemented __set, consider adding a @property annotation.
Loading history...
332
        return $option;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $option returns the type Dynamic\Foxy\Model\ProductOption which is incompatible with the documented return type Dynamic\Foxy\Form\OptionItem.
Loading history...
333
    }
334
}
335