Passed
Pull Request — master (#30)
by Jason
01:48
created

AddToCartForm::setFoxyHelper()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 4
nop 1
dl 0
loc 8
rs 10
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 SilverStripe\Forms\CompositeField;
11
use SilverStripe\Forms\DropdownField;
12
use SilverStripe\Forms\FieldList;
13
use SilverStripe\Forms\Form;
14
use SilverStripe\Forms\FormAction;
15
use SilverStripe\Forms\HeaderField;
16
use SilverStripe\Forms\HiddenField;
17
use SilverStripe\Forms\RequiredFields;
18
19
class AddToCartForm extends Form
20
{
21
    /**
22
     * @var
23
     */
24
    protected $helper;
25
26
    /**
27
     * @var
28
     */
29
    private $product;
30
31
    /**
32
     * @param $helper
33
     *
34
     * @return $this
35
     */
36
    public function setFoxyHelper($helper)
37
    {
38
        $helper = $helper === null ? FoxyHelper::create() : $helper;
39
        if ($helper instanceof FoxyHelper) {
40
            $this->helper = $helper;
41
            return $this;
42
        }
43
        throw new \InvalidArgumentException('$helper needs to be an instance of FoxyHelper.');
44
    }
45
46
    /**
47
     * @return FoxyHelper
48
     */
49
    public function getFoxyHelper()
50
    {
51
        if (!$this->helper) {
52
            $this->setFoxyHelper(FoxyHelper::create());
53
        }
54
        return $this->helper;
55
    }
56
57
    /**
58
     * @param $product
59
     *
60
     * @return $this
61
     */
62
    public function setProduct($product)
63
    {
64
        if ($product->isProduct()) {
65
            $this->product = $product;
66
            return $this;
67
        }
68
        throw new \InvalidArgumentException('$product needs to implement a Foxy DataExtension.');
69
    }
70
71
    /**
72
     * @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...
73
     */
74
    public function getProduct()
75
    {
76
        return $this->product;
77
    }
78
79
    /**
80
     * AddToCartForm constructor.
81
     *
82
     * @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...
83
     * @param string $name
84
     * @param FieldList|null $fields
85
     * @param FieldList|null $actions
86
     * @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...
87
     * @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...
88
     * @param null $helper
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $helper is correct as it would always require null to be passed?
Loading history...
89
     *
90
     */
91
    public function __construct(
92
        $controller,
93
        $name,
94
        FieldList $fields = null,
95
        FieldList $actions = null,
96
        $validator = null,
97
        $product = null,
98
        $helper = null
99
    ) {
100
        $this->setProduct($product);
101
        $this->setFoxyHelper($helper);
102
103
        $fields = ($fields != null && $fields->exists()) ?
104
            $this->getProductFields($fields) :
105
            $this->getProductFields(FieldList::create());
106
107
        $actions = ($actions != null && $actions->exists()) ?
108
            $this->getProductActions($actions) :
109
            $this->getProductActions(FieldList::create());
110
111
        $validator = (!empty($validator) || $validator != null) ? $validator : RequiredFields::create();
112
113
        parent::__construct($controller, $name, $fields, $actions, $validator);
114
115
        //have to call after parent::__construct()
116
        $this->setAttribute('action', FoxyHelper::FormActionURL());
117
        $this->disableSecurityToken();
118
        $this->setHTMLID($this->getTemplateHelper()->generateFormID($this) . "_{$product->ID}");
119
    }
120
121
    /**
122
     * @param FieldList $fields
123
     *
124
     * @return FieldList
125
     */
126
    protected function getProductFields(FieldList $fields)
127
    {
128
        $hiddenTitle = ($this->product->ReceiptTitle) ?
129
            htmlspecialchars($this->product->ReceiptTitle) :
130
            htmlspecialchars($this->product->Title);
131
        $code = $this->product->Code;
132
133
        if ($this->product->isAvailable()) {
134
            $fields->push(
135
                HiddenField::create('name')
136
                    ->setValue(
137
                        self::getGeneratedValue($code, 'name', $hiddenTitle, 'value')
138
                    )
139
            );
140
141
            $fields->push(
142
                HiddenField::create('category')
143
                    ->setValue(
144
                        self::getGeneratedValue($code, 'category', $this->product->FoxyCategory()->Code, 'value')
145
                    )
146
            );
147
148
            $fields->push(
149
                HiddenField::create('code')
150
                    ->setValue(
151
                        self::getGeneratedValue($code, 'code', $this->product->Code, 'value')
152
                    )
153
            );
154
155
            $fields->push(
156
                HiddenField::create('product_id')
157
                    ->setValue(
158
                        self::getGeneratedValue($code, 'product_id', $this->product->ID, 'value')
159
                    )
160
                    ->setName('h:product_id')
161
            );
162
163
            $fields->push(
164
                HiddenField::create('price')
165
                    ->setValue(
166
                        self::getGeneratedValue($code, 'price', $this->product->Price, 'value')
167
                    )
168
            );
169
170
            if ($this->product->hasExtension(Shippable::class)) {
171
                if ($this->product->Weight > 0) {
172
                    $fields->push(
173
                        HiddenField::create('weight')
174
                            ->setValue(
175
                                self::getGeneratedValue($code, 'weight', $this->product->Weight, 'value')
176
                            )
177
                    );
178
                }
179
            }
180
181
            $image = null;
182
            if ($this->product->hasMethod('getImage')) {
183
                if ($this->product->getImage()) {
184
                    $image = $this->product->getImage()->CMSThumbnail()->absoluteURL;
185
                }
186
                if ($image) {
187
                    $fields->push(
188
                        HiddenField::create('image')
189
                            ->setValue(
190
                                self::getGeneratedValue($code, 'image', $image, 'value')
191
                            )
192
                    );
193
                }
194
            }
195
196
            $optionsSet = $this->getProductOptionSet();
197
            $fields->push($optionsSet);
198
            $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...
199
                FoxyHelper::config()->get('MaxQuantity') :
200
                10;
201
            $fields->push(QuantityField::create('x:visibleQuantity')->setTitle('Quantity')->setValue(1));
202
            $fields->push(
203
                HiddenField::create('quantity')
204
                    ->setValue(
205
                        self::getGeneratedValue($code, 'quantity', 1, 'value')
206
                    )
207
            );
208
209
            $fields->push(
210
                HeaderField::create('submitPrice', '$' . $this->product->Price, 4)
211
                    ->addExtraClass('submit-price')
212
            );
213
            $fields->push(
214
                $unavailable = HeaderField::create('unavailableText', 'Selection unavailable', 4)
215
                    ->addExtraClass('unavailable-text')
216
            );
217
            if (!empty(trim($this->helper->getStoreCartURL())) && $this->product->isAvailable()) {
218
                $unavailable->addExtraClass('hidden');
219
            }
220
        } else {
221
            $fields->push(HeaderField::create('unavailableText', 'currently unavaiable', 4));
222
        }
223
224
        $this->extend('updateProductFields', $fields);
225
226
        return $fields;
227
    }
228
229
    /**
230
     * @param FieldList $actions
231
     *
232
     * @return FieldList
233
     */
234
    protected function getProductActions(FieldList $actions)
235
    {
236
        if (!empty(trim($this->helper->getStoreCartURL())) && $this->product->isAvailable()) {
237
            $actions->push(
238
                FormAction::create(
239
                    'x:submit',
240
                    _t(__CLASS__ . '.AddToCart', 'Add to Cart')
241
                )
242
                    ->addExtraClass('fs-add-to-cart-button')
243
                    ->setName('x:submit')
244
            );
245
        }
246
247
        $this->extend('updateProductActions', $actions);
248
249
        return $actions;
250
    }
251
252
    /**
253
     * @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...
254
     * @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...
255
     * @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...
256
     * @param string $method
257
     * @param bool $output
258
     * @param bool $urlEncode
259
     *
260
     * @return null|string
261
     */
262
    // todo - Purchasable Extension or AddToCartForm? protected in Form
263
    public static function getGeneratedValue(
264
        $productCode = null,
265
        $optionName = null,
266
        $optionValue = null,
267
        $method = 'name',
268
        $output = false,
269
        $urlEncode = false
270
    ) {
271
        $optionName = ($optionName !== null) ? preg_replace('/\s/', '_', $optionName) : $optionName;
0 ignored issues
show
introduced by
The condition $optionName !== null is always false.
Loading history...
272
        $helper = FoxyHelper::create();
273
274
        return $helper::fc_hash_value($productCode, $optionName, $optionValue, $method, $output, $urlEncode);
275
    }
276
277
    /**
278
     * @return CompositeField
279
     */
280
    protected function getProductOptionSet()
281
    {
282
        /** @var CompositeField $optionsSet */
283
        $optionsSet = CompositeField::create();
284
285
        $types = $this->product->OptionTypes();
286
287
        foreach ($types as $type) {
288
            $title = $type->Title;
289
            $fieldName = preg_replace('/\s/', '_', $title);
290
            $disabled = [];
291
            $fullOptions = [];
292
293
            foreach ($type->Options() as $option) {
294
                $option = $this->setAvailability($option);
295
                $name = self::getGeneratedValue(
296
                    $this->product->Code,
297
                    $type->Title,
298
                    $option->getGeneratedValue(),
299
                    'value'
300
                );
301
302
                $fullOptions[$name] = $option->getGeneratedTitle();
303
                if (!$option->Availability) {
304
                    array_push($disabled, $name);
305
                }
306
            }
307
308
            $optionsSet->push(
309
                $dropdown = DropdownField::create($fieldName, $title, $fullOptions)->setTitle($title)
310
            );
311
312
            if (!empty($disabled)) {
313
                $dropdown->setDisabledItems($disabled);
314
            }
315
316
            $dropdown->addExtraClass("product-options");
317
        }
318
319
        $optionsSet->addExtraClass('foxycartOptionsContainer');
320
321
        return $optionsSet;
322
    }
323
324
    /**
325
     * @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...
326
     * @return OptionItem
327
     */
328
    protected function setAvailability(ProductOption $option)
329
    {
330
        $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...
331
        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...
332
    }
333
}
334