Completed
Pull Request — master (#287)
by Nic
03:54
created

FoxyStripeProduct   D

Complexity

Total Complexity 37

Size/Duplication

Total Lines 413
Duplicated Lines 1.45 %

Coupling/Cohesion

Components 2
Dependencies 24

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 37
lcom 2
cbo 24
dl 6
loc 413
c 0
b 0
f 0
ccs 0
cts 190
cp 0
rs 4.5047

16 Methods

Rating   Name   Duplication   Size   Complexity  
A fieldLabels() 0 14 1
D getCMSFields() 6 144 9
B onBeforeWrite() 0 33 6
A onAfterWrite() 0 6 1
B onBeforeDelete() 0 19 6
A validate() 0 18 1
A getCMSValidator() 0 4 1
A getGeneratedValue() 0 7 3
A getCartScript() 0 4 1
A getDiscountFieldValue() 0 9 2
A canEdit() 0 4 1
A canDelete() 0 4 1
A canCreate() 0 4 1
A canPublish() 0 4 1
A providePermissions() 0 6 1
A getPurchaseForm() 0 12 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/**
4
 * Class ProductPage
5
 * @package foxystripe
6
 * @property string $Title
7
 * @property HTMLText $Content
8
 */
9
class FoxyStripeProduct extends DataObject implements PermissionProvider
10
{
11
12
    /**
13
     * @var string
14
     */
15
    private static $singular_name = 'Product';
16
    /**
17
     * @var string
18
     */
19
    private static $plural_name = 'Products';
20
    /**
21
     * @var string
22
     */
23
    private static $description = 'A product that can be added to the shopping cart';
24
25
    /**
26
     * @var array
27
     */
28
    private static $db = [
29
        'Title' => 'Varchar(255)',
30
        'Content' => 'HTMLText',
31
        'Price' => 'Currency',
32
        'Weight' => 'Decimal',
33
        'Code' => 'Varchar(100)',
34
        'ReceiptTitle' => 'HTMLVarchar(255)',
35
        'Featured' => 'Boolean',
36
        'Available' => 'Boolean',
37
        'DiscountTitle' => 'Varchar(50)'
38
    ];
39
40
    /**
41
     * @var array
42
     */
43
    private static $has_one = [
44
        'PreviewImage' => 'Image',
45
        'Category' => 'FoxyCartProductCategory'
46
    ];
47
48
    /**
49
     * @var array
50
     */
51
    private static $has_many = [
52
        'ProductImages' => 'ProductImage',
53
        'ProductOptions' => 'OptionItem',
54
        'OrderDetails' => 'OrderDetail',
55
        'ProductDiscountTiers' => 'ProductDiscountTier'
56
    ];
57
58
    /**
59
     * @var array
60
     */
61
    private static $belongs_many_many = [
62
        'ProductHolders' => 'ProductHolder'
63
    ];
64
65
    /**
66
     * @var array
67
     */
68
    private static $indexes = [
69
        'Code' => true,
70
    ];
71
72
    /**
73
     * @var array
74
     */
75
    private static $defaults = [
76
        'ShowInMenus' => false,
77
        'Available' => true,
78
        'Weight' => '1.0'
79
    ];
80
81
    /**
82
     * @var array
83
     */
84
    private static $summary_fields = [
85
        'Title',
86
        'Code',
87
        'Price.Nice',
88
        'Category.Title'
89
    ];
90
91
    /**
92
     * @var array
93
     */
94
    private static $searchable_fields = [
95
        'Title',
96
        'Code',
97
        'Featured',
98
        'Available',
99
        'Category.ID'
100
    ];
101
102
    public function fieldLabels($includeRelations = true)
103
    {
104
        $labels = parent::fieldLabels($includeRelations);
105
106
        $labels['Title'] = _t('ProductPage.TitleLabel', 'Name');
107
        $labels['Code'] = _t('ProductPage.CodeLabel', "Code");
108
        $labels['Price.Nice'] = _t('ProductPage.PriceLabel', 'Price');
109
        $labels['Featured.Nice'] = _t('ProductPage.NiceLabel', 'Featured');
110
        $labels['Available.Nice'] = _t('ProductPage.AvailableLabel', 'Available');
111
        $labels['Category.ID'] = _t('ProductPage.IDLabel', 'Category');
112
        $labels['Category.Title'] = _t('ProductPage.CategoryTitleLabel', 'Category');
113
114
        return $labels;
115
    }
116
117
    /**
118
     * @return FieldList
119
     */
120
    public function getCMSFields()
121
    {
122
        $fields = parent::getCMSFields();
123
124
        // allow extensions of ProductPage to override the PreviewImage field description
125
        $previewDescription = ($this->stat('customPreviewDescription')) ? $this->stat('customPreviewDescription') : _t('ProductPage.PreviewImageDescription', 'Image used throughout site to represent this product');
126
127
        // Cateogry Dropdown field w/ add new
128
        $source = function () {
129
            return FoxyCartProductCategory::get()->map()->toArray();
130
        };
131
        $catField = DropdownField::create('CategoryID', _t('ProductPage.Category', 'FoxyCart Category'), $source())
132
            ->setEmptyString('')
133
            ->setDescription(_t(
134
                'ProductPage.CategoryDescription',
135
                'Required, must also exist in
136
                    <a href="https://admin.foxycart.com/admin.php?ThisAction=ManageProductCategories" target="_blank">
137
                        FoxyCart Categories
138
                    </a>.
139
                    Used to set category specific options like shipping and taxes. Managed in
140
                        <a href="admin/settings">
141
                            Settings > FoxyStripe > Categories
142
                        </a>'
143
            ));
144
        if (class_exists('QuickAddNewExtension')) $catField->useAddNew('FoxyCartProductCategory', $source);
145
146
        // Product Images gridfield
147
        $config = GridFieldConfig_RelationEditor::create();
148
        if (class_exists('GridFieldSortableRows')) $config->addComponent(new GridFieldSortableRows('SortOrder'));
149
        if (class_exists('GridFieldBulkImageUpload')) {
150
            $config->addComponent(new GridFieldBulkUpload());
151
            $config->getComponentByType('GridFieldBulkUpload')->setUfConfig('folderName', 'Uploads/ProductImages');
0 ignored issues
show
Bug introduced by
The method setUfConfig() does not seem to exist on object<GridFieldComponent>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
152
        }
153
        $prodImagesField = GridField::create(
154
            'ProductImages',
155
            _t('ProductPage.ProductImages', 'Images'),
156
            $this->ProductImages(),
0 ignored issues
show
Documentation Bug introduced by
The method ProductImages does not exist on object<FoxyStripeProduct>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
157
            $config
158
        );
159
160
        // Product Options field
161
        $config = GridFieldConfig_RelationEditor::create();
162
        if (class_exists('GridFieldSortableRows')) {
163
            $config->addComponent(new GridFieldSortableRows('SortOrder'));
164
            $products = $this->ProductOptions()->sort('SortOrder');
0 ignored issues
show
Documentation Bug introduced by
The method ProductOptions does not exist on object<FoxyStripeProduct>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
165
        } else {
166
            $products = $this->ProductOptions();
0 ignored issues
show
Documentation Bug introduced by
The method ProductOptions does not exist on object<FoxyStripeProduct>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
167
        }
168
        $config->removeComponentsByType('GridFieldAddExistingAutocompleter');
169
        $prodOptField = GridField::create(
170
            'ProductOptions',
171
            _t('ProductPage.ProductOptions', 'Options'),
172
            $products,
173
            $config
174
        );
175
176
        // Details tab
177
        $fields->addFieldsToTab('Root.Details', [
178
            HeaderField::create('DetailHD', 'Product Details', 2),
179
            CheckboxField::create('Available')
180
                ->setTitle(_t('ProductPage.Available', 'Available for purchase'))
181
                ->setDescription(_t(
182
                    'ProductPage.AvailableDescription',
183
                    'If unchecked, will remove "Add to Cart" form and instead display "Currently unavailable"'
184
                )),
185
            TextField::create('Code')
186
                ->setTitle(_t('ProductPage.Code', 'Product Code'))
187
                ->setDescription(_t(
188
                    'ProductPage.CodeDescription',
189
                    'Required, must be unique. Product identifier used by FoxyCart in transactions'
190
                )),
191
            $catField,
192
            CurrencyField::create('Price')
193
                ->setTitle(_t('ProductPage.Price', 'Price'))
194
                ->setDescription(_t(
195
                    'ProductPage.PriceDescription',
196
                    'Base price for this product. Can be modified using Product Options'
197
                )),
198
            NumericField::create('Weight')
199
                ->setTitle(_t('ProductPage.Weight', 'Weight'))
200
                ->setDescription(_t(
201
                    'ProductPage.WeightDescription',
202
                    'Base weight for this product in lbs. Can be modified using Product Options'
203
                )),
204
            CheckboxField::create('Featured')
205
                ->setTitle(_t('ProductPage.Featured', 'Featured Product')),
206
            TextField::create('ReceiptTitle')
207
                ->setTitle(_t('ProductPage.ReceiptTitle', 'Product Title for Receipt'))
208
                ->setDescription(_t(
209
                    'ProductPage.ReceiptTitleDescription', 'Optional'
210
                ))
211
        ]);
212
213
        // Images tab
214
        $fields->addFieldsToTab('Root.Images', [
215
            HeaderField::create('MainImageHD', _t('ProductPage.MainImageHD', 'Product Image'), 2),
216
            UploadField::create('PreviewImage', '')
217
                ->setDescription($previewDescription)
218
                ->setFolderName('Uploads/Products')
219
                ->setAllowedExtensions(['jpg', 'jpeg', 'gif', 'png'])
220
                ->setAllowedMaxFileNumber(1),
221
            HeaderField::create('ProductImagesHD', _t('ProductPage.ProductImagesHD' . 'Product Image Gallery'), 2),
222
            $prodImagesField
223
                ->setDescription(_t(
224
                    'ProductPage.ProductImagesDescription',
225
                    'Additional Product Images, shown in gallery on Product page'
226
                ))
227
        ]);
228
229
        // Options Tab
230
        $fields->addFieldsToTab('Root.Options', [
231
            HeaderField::create('OptionsHD', _t('ProductPage.OptionsHD', 'Product Options'), 2),
232
            LiteralField::create('OptionsDescrip', _t(
233
                'Page.OptionsDescrip',
234
                '<p>Product Options allow products to be customized by attributes such as size or color.
235
                    Options can also modify the product\'s price, weight or code.</p>'
236
            )),
237
            $prodOptField
238
        ]);
239
240
        if (!$this->DiscountTitle && $this->ProductDiscountTiers()->exists()) {
0 ignored issues
show
Documentation introduced by
The property DiscountTitle does not exist on object<FoxyStripeProduct>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation Bug introduced by
The method ProductDiscountTiers does not exist on object<FoxyStripeProduct>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
241
            $fields->addFieldTotab('Root.Discounts', new LiteralField("ProductDiscountHeaderWarning", "<p class=\"message warning\">A discount title is required for FoxyCart to properly parse the value. The discounts will not be applied until a title is entered.</p>"));
242
        }
243
244
        $fields->addFieldToTab('Root.Discounts', TextField::create('DiscountTitle')->setTitle(_t('Product.DiscountTitle', 'Discount Title')));
245
        $discountsConfig = GridFieldConfig_RelationEditor::create();
246
        $discountsConfig->removeComponentsByType('GridFieldAddExistingAutocompleter');
247
        $discountsConfig->removeComponentsByType('GridFieldDeleteAction');
248
        $discountsConfig->addComponent(new GridFieldDeleteAction(false));
249
        $discountGrid = GridField::create('ProductDiscountTiers', 'Product Discounts', $this->ProductDiscountTiers(), $discountsConfig);
0 ignored issues
show
Documentation Bug introduced by
The method ProductDiscountTiers does not exist on object<FoxyStripeProduct>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
250
        $fields->addFieldToTab('Root.Discounts', $discountGrid);
251
252 View Code Duplication
        if (FoxyCart::store_name_warning() !== null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
253
            $fields->addFieldToTab('Root.Main', LiteralField::create("StoreSubDomainHeaderWarning", _t(
254
                'ProductPage.StoreSubDomainHeaderWarning',
255
                "<p class=\"message error\">Store sub-domain must be entered in the <a href=\"/admin/settings/\">site settings</a></p>"
256
            )), 'Title');
257
        }
258
259
        // allows CMS fields to be extended
260
        $this->extend('updateCMSFields', $fields);
261
262
        return $fields;
263
    }
264
265
    public function onBeforeWrite()
266
    {
267
        parent::onBeforeWrite();
268
        if (!$this->CategoryID) {
0 ignored issues
show
Documentation introduced by
The property CategoryID does not exist on object<FoxyStripeProduct>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
269
            $default = FoxyCartProductCategory::get()->filter(['Code' => 'DEFAULT'])->first();
270
            $this->CategoryID = $default->ID;
0 ignored issues
show
Documentation introduced by
The property CategoryID does not exist on object<FoxyStripeProduct>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
271
        }
272
273
        //update many_many lists when multi-group is on
274
        if (SiteConfig::current_site_config()->MultiGroup) {
275
            $holders = $this->ProductHolders();
0 ignored issues
show
Documentation Bug introduced by
The method ProductHolders does not exist on object<FoxyStripeProduct>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
276
            $product = ProductPage::get()->byID($this->ID);
277
            if (isset($product->ParentID)) {
278
                $origParent = $product->ParentID;
279
            } else {
280
                $origParent = null;
281
            }
282
            $currentParent = $this->ParentID;
0 ignored issues
show
Documentation introduced by
The property ParentID does not exist on object<FoxyStripeProduct>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
283
            if ($origParent != $currentParent) {
284
                if ($holders->find('ID', $origParent)) {
285
                    $holders->removeByID($origParent);
286
                }
287
288
            }
289
            $holders->add($currentParent);
290
        }
291
292
        $title = ltrim($this->Title);
293
        $title = rtrim($title);
294
        $this->Title = $title;
295
296
297
    }
298
299
    public function onAfterWrite()
300
    {
301
        parent::onAfterWrite();
302
303
304
    }
305
306
    public function onBeforeDelete()
307
    {
308
        if ($this->Status != "Published") {
0 ignored issues
show
Documentation introduced by
The property Status does not exist on object<FoxyStripeProduct>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
309
            if ($this->ProductOptions()) {
0 ignored issues
show
Documentation Bug introduced by
The method ProductOptions does not exist on object<FoxyStripeProduct>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
310
                $options = $this->getComponents('ProductOptions');
311
                foreach ($options as $option) {
312
                    $option->delete();
313
                }
314
            }
315
            if ($this->ProductImages()) {
0 ignored issues
show
Documentation Bug introduced by
The method ProductImages does not exist on object<FoxyStripeProduct>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
316
                //delete product image dataobjects, not the images themselves.
317
                $images = $this->getComponents('ProductImages');
318
                foreach ($images as $image) {
319
                    $image->delete();
320
                }
321
            }
322
        }
323
        parent::onBeforeDelete();
324
    }
325
326
    public function validate()
327
    {
328
        $result = parent::validate();
329
330
        /*if($this->ID>0){
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
331
            if($this->Price <= 0) {
332
                $result->error('Must set a positive price value');
333
            }
334
            if($this->Weight <= 0){
335
                $result->error('Must set a positive weight value');
336
            }
337
            if($this->Code == ''){
338
                $result->error('Must set a product code');
339
            }
340
        }*/
341
342
        return $result;
343
    }
344
345
    public function getCMSValidator()
346
    {
347
        return new RequiredFields(['CategoryID', 'Price', 'Weight', 'Code']);
348
    }
349
350
    public static function getGeneratedValue($productCode = null, $optionName = null, $optionValue = null, $method = 'name', $output = false, $urlEncode = false)
351
    {
352
        $optionName = ($optionName !== null) ? preg_replace('/\s/', '_', $optionName) : $optionName;
353
        return (SiteConfig::current_site_config()->CartValidation)
354
            ? FoxyCart_Helper::fc_hash_value($productCode, $optionName, $optionValue, $method, $output, $urlEncode) :
355
            $optionValue;
356
    }
357
358
    // get FoxyCart Store Name for JS call
359
    public function getCartScript()
360
    {
361
        return '<script src="https://cdn.foxycart.com/' . FoxyCart::getFoxyCartStoreName() . '/loader.js" async defer></script>';
362
    }
363
364
    public function getDiscountFieldValue()
365
    {
366
        $tiers = $this->ProductDiscountTiers();
0 ignored issues
show
Documentation Bug introduced by
The method ProductDiscountTiers does not exist on object<FoxyStripeProduct>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
367
        $bulkString = '';
368
        foreach ($tiers as $tier) {
369
            $bulkString .= "|{$tier->Quantity}-{$tier->Percentage}";
370
        }
371
        return "{$this->Title}{allunits{$bulkString}}";
372
    }
373
374
    /**
375
     * @param Member $member
376
     * @return boolean
377
     */
378
    public function canEdit($member = null)
379
    {
380
        return Permission::check('Product_CANCRUD');
381
    }
382
383
    public function canDelete($member = null)
384
    {
385
        return Permission::check('Product_CANCRUD');
386
    }
387
388
    public function canCreate($member = null)
389
    {
390
        return Permission::check('Product_CANCRUD');
391
    }
392
393
    public function canPublish($member = null)
0 ignored issues
show
Unused Code introduced by
The parameter $member is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
394
    {
395
        return Permission::check('Product_CANCRUD');
396
    }
397
398
    public function providePermissions()
399
    {
400
        return [
401
            'Product_CANCRUD' => 'Allow user to manage Products and related objects'
402
        ];
403
    }
404
405
    /**
406
     * @return FoxyStripePurchaseForm
407
     */
408
    public function getPurchaseForm()
409
    {
410
411
        $product = $this;
412
413
        $form = FoxyStripePurchaseForm::create(Controller::curr(), __FUNCTION__, null, null, null, $product);
414
415
        $this->extend('updateFoxyStripePurchaseForm', $form);
416
417
        return $form;
418
419
    }
420
421
}