FoxyStripePurchaseForm::getProductActions()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 8
c 1
b 0
f 0
dl 0
loc 14
ccs 0
cts 9
cp 0
rs 10
cc 3
nc 2
nop 1
crap 12
1
<?php
2
3
namespace Dynamic\FoxyStripe\Form;
4
5
use Dynamic\FoxyStripe\Model\FoxyCart;
6
use Dynamic\FoxyStripe\Model\FoxyStripeSetting;
7
use Dynamic\FoxyStripe\Model\OptionGroup;
8
use Dynamic\FoxyStripe\Model\OptionItem;
9
use Dynamic\FoxyStripe\ORM\ProductPageLegacy;
0 ignored issues
show
Bug introduced by
The type Dynamic\FoxyStripe\ORM\ProductPageLegacy 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...
10
use Dynamic\FoxyStripe\Page\ProductPage;
11
use SilverStripe\CMS\Controllers\ContentController;
12
use SilverStripe\Dev\Debug;
13
use SilverStripe\Forms\CompositeField;
14
use SilverStripe\Forms\DropdownField;
15
use SilverStripe\Forms\FieldList;
16
use SilverStripe\Forms\Form;
17
use SilverStripe\Forms\FormAction;
18
use SilverStripe\Forms\HeaderField;
19
use SilverStripe\Forms\HiddenField;
20
use SilverStripe\Forms\RequiredFields;
21
use SilverStripe\ORM\DataList;
22
use SilverStripe\ORM\GroupedList;
23
use SilverStripe\SiteConfig\SiteConfig;
24
use SilverStripe\View\Requirements;
25
26
/**
27
 * Class FoxyStripePurchaseForm.
28
 *
29
 * @property FoxyStripeSetting $site_config
30
 * @property ProductPage $product
31
 */
32
class FoxyStripePurchaseForm extends Form
33
{
34
    /**
35
     * @var
36
     */
37
    protected $site_config;
38
39
    /**
40
     * @var
41
     */
42
    private $product;
43
44
    /**
45
     * @param $siteConfig
46
     *
47
     * @return $this
48
     */
49
    public function setSiteConfig($siteConfig)
50
    {
51
        $siteConfig = $siteConfig === null ? FoxyStripeSetting::current_foxystripe_setting() : $siteConfig;
52
        if ($siteConfig instanceof FoxyStripeSetting) {
53
            $this->site_config = $siteConfig;
54
55
            return $this;
56
        }
57
        throw new \InvalidArgumentException('$siteConfig needs to be an instance of FoxyStripeSetting.');
58
    }
59
60
    /**
61
     * @return FoxyStripeSetting
62
     */
63
    public function getSiteConfig()
64
    {
65
        if (!$this->site_config) {
66
            $this->setSiteConfig(FoxyStripeSetting::current_foxystripe_setting());
67
        }
68
69
        return $this->site_config;
70
    }
71
72
    /**
73
     * @param $product
74
     *
75
     * @return $this
76
     */
77
    public function setProduct($product)
78
    {
79
        if ($product instanceof ProductPage) {
80
            $this->product = $product;
81
82
            return $this;
83
        }
84
        throw new \InvalidArgumentException('$product needs to be an instance of ProductPage.');
85
    }
86
87
    /**
88
     * @return ProductPage
89
     */
90
    public function getProduct()
91
    {
92
        return $this->product;
93
    }
94
95
    /**
96
     * FoxyStripePurchaseForm constructor.
97
     *
98
     * @param ContentController $controller
99
     * @param string $name
100
     * @param FieldList|null $fields
101
     * @param FieldList|null $actions
102
     * @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...
103
     * @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...
104
     * @param null $siteConfig
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $siteConfig is correct as it would always require null to be passed?
Loading history...
105
     *
106
     */
107
    public function __construct(
108
        $controller,
109
        $name,
110
        FieldList $fields = null,
111
        FieldList $actions = null,
112
        $validator = null,
113
        $product = null,
114
        $siteConfig = null
115
    ) {
116
        $this->setProduct($product);
117
        $this->setSiteConfig($siteConfig);
118
119
        $fields = ($fields != null && $fields->exists()) ?
120
            $this->getProductFields($fields) :
121
            $this->getProductFields(FieldList::create());
122
123
        $actions = ($actions != null && $actions->exists()) ?
124
            $this->getProductActions($actions) :
125
            $this->getProductActions(FieldList::create());
126
        $validator = (!empty($validator) || $validator != null) ? $validator : RequiredFields::create();
127
128
        parent::__construct($controller, $name, $fields, $actions, $validator);
129
130
        //have to call after parent::__construct()
131
        $this->setAttribute('action', FoxyCart::FormActionURL());
132
        $this->disableSecurityToken();
133
134
        $this->setHTMLID($this->getTemplateHelper()->generateFormID($this) . "_{$product->ID}");
135
    }
136
137
    /**
138
     * @param FieldList $fields
139
     *
140
     * @return FieldList
141
     */
142
    protected function getProductFields(FieldList $fields)
143
    {
144
        //Requirements::javascript('dynamic/foxystripe: client/dist/javascript/scripts.min.js');
145
        $hiddenTitle = ($this->product->ReceiptTitle) ?
146
            htmlspecialchars($this->product->ReceiptTitle) :
147
            htmlspecialchars($this->product->Title);
148
        $code = $this->product->Code;
149
150
        if ($this->getProduct()->getIsAvailable()) {
151
            $fields->push(
152
                HiddenField::create('name')
153
                    ->setValue(
154
                        ProductPage::getGeneratedValue($code, 'name', $hiddenTitle, 'value')
155
                    )
156
            );
157
            $fields->push(
158
                HiddenField::create('category')
159
                    ->setValue(
160
                        ProductPage::getGeneratedValue($code, 'category', $this->product->Category()->Code, 'value')
161
                    )
162
            );
163
            $fields->push(
164
                HiddenField::create('code')
165
                    ->setValue(
166
                        ProductPage::getGeneratedValue($code, 'code', $this->product->Code, 'value')
167
                    )
168
            );
169
            $fields->push(
170
                HiddenField::create(
171
                    'product_id'
172
                )->setValue(
173
                    ProductPage::getGeneratedValue($code, 'product_id', $this->product->ID, 'value')
174
                )
175
            );
176
            $fields->push(
177
                HiddenField::create('price')
178
                    ->setValue(
179
                        ProductPage::getGeneratedValue($code, 'price', $this->product->Price, 'value')
180
                    )
181
            );//can't override id
182
            if ($this->product->Weight > 0) {
183
                $fields->push(
184
                    HiddenField::create('weight')
185
                        ->setValue(
186
                            ProductPage::getGeneratedValue($code, 'weight', $this->product->Weight, 'value')
187
                        )
188
                );
189
            }
190
191
            $image = null;
192
            if ($this->product->Image() || ProductPage::has_extension(ProductPageLegacy::class)) {
193
                if ($this->product->Image()) {
194
                    $image = $this->product->Image()->Pad(80, 80)->absoluteURL;
195
                } elseif (ProductPage::has_extension(ProductPageLegacy::class) &&
196
                    $this->product->PreviewImage()->exists()) {
0 ignored issues
show
Bug introduced by
The method PreviewImage() does not exist on Dynamic\FoxyStripe\Page\ProductPage. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

196
                    $this->product->/** @scrutinizer ignore-call */ 
197
                                    PreviewImage()->exists()) {
Loading history...
197
                    $image = $this->product->PreviewImage()->Pad(80, 80)->absoluteURL;
198
                }
199
200
                if ($image) {
201
                    $fields->push(
202
                        HiddenField::create('image')
203
                            ->setValue(
204
                                ProductPage::getGeneratedValue($code, 'image', $image, 'value')
205
                            )
206
                    );
207
                }
208
            }
209
210
            $optionsSet = $this->getProductOptionSet();
211
            $fields->push($optionsSet);
212
213
            $quantityMax = ($this->site_config->MaxQuantity) ? $this->site_config->MaxQuantity : 10;
0 ignored issues
show
Unused Code introduced by
The assignment to $quantityMax is dead and can be removed.
Loading history...
214
215
            $fields->push(QuantityField::create('x:visibleQuantity')->setTitle('Quantity')->setValue(1));
216
            $fields->push(
217
                HiddenField::create('quantity')
218
                    ->setValue(
219
                        ProductPage::getGeneratedValue($code, 'quantity', 1, 'value')
220
                    )
221
            );
222
223
            $fields->push(
224
                HeaderField::create('submitPrice', '$' . $this->product->Price, 4)
225
                    ->addExtraClass('submit-price')
226
            );
227
            $fields->push(
228
                $unavailable = HeaderField::create('unavailableText', 'Selection unavailable', 4)
229
                    ->addExtraClass('unavailable-text')
230
            );
231
232
            if (!empty(trim($this->getSiteConfig()->StoreName)) && $this->getProduct()->getIsAvailable()) {
233
                $unavailable->addExtraClass('hidden');
234
            }
235
236
            $this->extend('updatePurchaseFormFields', $fields);
237
        } else {
238
            $fields->push(HeaderField::create('unavailableText', 'Currently Out of Stock', 4));
239
        }
240
241
        $this->extend('updateFoxyStripePurchaseFormFields', $fields);
242
243
        return $fields;
244
    }
245
246
    /**
247
     * @param FieldList $actions
248
     *
249
     * @return FieldList
250
     */
251
    protected function getProductActions(FieldList $actions)
252
    {
253
        if (!empty(trim($this->getSiteConfig()->StoreName)) && $this->getProduct()->getIsAvailable()) {
254
            $actions->push(
255
                $submit = FormAction::create(
256
                    'x:submit',
257
                    _t('ProductForm.AddToCart', 'Add to Cart')
258
                )->addExtraClass('fs-add-to-cart-button')
259
            );
260
        }
261
262
        $this->extend('updateFoxyStripePurchaseFormActions', $actions);
263
264
        return $actions;
265
    }
266
267
    /**
268
     * @return CompositeField
269
     */
270
    protected function getProductOptionSet()
271
    {
272
        $options = $this->product->ProductOptions();
273
        $groupedOptions = new GroupedList($options);
274
        $groupedBy = $groupedOptions->groupBy('ProductOptionGroupID');
275
276
        /** @var CompositeField $optionsSet */
277
        $optionsSet = CompositeField::create();
278
279
        /** @var DataList $set */
280
        foreach ($groupedBy as $id => $set) {
281
            $group = OptionGroup::get()->byID($id);
282
            $title = $group->Title;
283
            $fieldName = preg_replace('/\s/', '_', $title);
284
            $disabled = [];
285
            $fullOptions = [];
286
287
            foreach ($set as $item) {
288
                $item = $this->setAvailability($item);
289
290
                $name = ProductPage::getGeneratedValue(
291
                    $this->product->Code,
292
                    $group->Title,
293
                    $item->getGeneratedValue(),
294
                    'value'
295
                );
296
297
                $fullOptions[$name] = $item->getGeneratedTitle();
298
                if (!$item->Availability) {
0 ignored issues
show
Bug Best Practice introduced by
The property Availability does not exist on Dynamic\FoxyStripe\Model\OptionItem. Since you implemented __get, consider adding a @property annotation.
Loading history...
299
                    array_push($disabled, $name);
300
                }
301
            }
302
303
            $optionsSet->push(
304
                $dropdown = DropdownField::create($fieldName, $title, $fullOptions)->setTitle($title)
305
            );
306
307
            if (!empty($disabled)) {
308
                $dropdown->setDisabledItems($disabled);
309
            }
310
311
            $dropdown->addExtraClass("product-options");
312
        }
313
314
        $optionsSet->addExtraClass('foxycartOptionsContainer');
315
316
        return $optionsSet;
317
    }
318
319
    /**
320
     * @param OptionItem $option
321
     * @return OptionItem
322
     */
323
    protected function setAvailability(OptionItem $option)
324
    {
325
        $option->Available = ($option->getAvailability()) ? true : false;
0 ignored issues
show
Documentation Bug introduced by
It seems like $option->getAvailability() ? true : false of type boolean is incompatible with the declared type SilverStripe\ORM\FieldType\DBBoolean of property $Available.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
326
327
        return $option;
328
    }
329
}
330