Passed
Pull Request — master (#41)
by Jason
03:42
created

Purchasable::canEdit()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Dynamic\Foxy\Extension;
4
5
use Dynamic\Foxy\Model\Foxy;
6
use Dynamic\Foxy\Model\FoxyCategory;
7
use Dynamic\Foxy\Model\Setting;
8
use Dynamic\Foxy\Model\OptionType;
9
use SilverStripe\Forms\CheckboxField;
10
use SilverStripe\Forms\CurrencyField;
11
use SilverStripe\Forms\DropdownField;
12
use SilverStripe\Forms\FieldList;
13
use SilverStripe\Forms\LiteralField;
14
use SilverStripe\Forms\GridField\GridField;
15
use SilverStripe\Forms\GridField\GridFieldAddExistingAutocompleter;
16
use SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor;
17
use SilverStripe\Forms\NumericField;
18
use SilverStripe\Forms\TextField;
19
use SilverStripe\ORM\DataExtension;
20
use SilverStripe\ORM\ValidationResult;
21
use SilverStripe\Security\Permission;
22
use SilverStripe\Security\PermissionProvider;
23
use SilverStripe\Security\Security;
24
use Symbiote\GridFieldExtensions\GridFieldAddExistingSearchButton;
25
use Symbiote\GridFieldExtensions\GridFieldOrderableRows;
26
27
class Purchasable extends DataExtension implements PermissionProvider
28
{
29
    /**
30
     * @var array
31
     */
32
    private static $db = [
0 ignored issues
show
introduced by
The private property $db is not used, and could be removed.
Loading history...
33
        'Price' => 'Currency',
34
        'Code' => 'Varchar(100)',
35
        'ReceiptTitle' => 'HTMLVarchar(255)',
36
        'Available' => 'Boolean',
37
    ];
38
39
    /**
40
     * @var array
41
     */
42
    private static $has_one = [
0 ignored issues
show
introduced by
The private property $has_one is not used, and could be removed.
Loading history...
43
        'FoxyCategory' => FoxyCategory::class,
44
    ];
45
46
    /**
47
     * @var array
48
     */
49
    private static $has_many = [
0 ignored issues
show
introduced by
The private property $has_many is not used, and could be removed.
Loading history...
50
        'OptionTypes' => OptionType::class,
51
    ];
52
53
    /**
54
     * @var array
55
     */
56
    private static $indexes = [
0 ignored issues
show
introduced by
The private property $indexes is not used, and could be removed.
Loading history...
57
        'Code' => [
58
            'type' => 'unique',
59
            'columns' => ['Code'],
60
        ],
61
    ];
62
63
    /**
64
     * @var array
65
     */
66
    private static $defaults = [
0 ignored issues
show
introduced by
The private property $defaults is not used, and could be removed.
Loading history...
67
        'ShowInMenus' => false,
68
        'Available' => true,
69
        'Weight' => '0.0',
70
    ];
71
72
    /**
73
     * @var array
74
     */
75
    private static $summary_fields = [
0 ignored issues
show
introduced by
The private property $summary_fields is not used, and could be removed.
Loading history...
76
        'Image.CMSThumbnail',
77
        'Title',
78
        'Code',
79
        'Price.Nice',
80
    ];
81
82
    /**
83
     * @var array
84
     */
85
    private static $searchable_fields = [
0 ignored issues
show
introduced by
The private property $searchable_fields is not used, and could be removed.
Loading history...
86
        'Title',
87
        'Code',
88
        'Available',
89
    ];
90
91
    /**
92
     * @param bool $includerelations
93
     *
94
     * @return array
95
     */
96
    public function updateFieldLabels(&$labels)
97
    {
98
        $labels['Title'] = _t(__CLASS__ . '.TitleLabel', 'Product Name');
99
        $labels['Code'] = _t(__CLASS__ . '.CodeLabel', 'Code');
100
        $labels['Price'] = _t(__CLASS__ . '.PriceLabel', 'Price');
101
        $labels['Price.Nice'] = _t(__CLASS__ . '.PriceLabel', 'Price');
102
        $labels['Available'] = _t(__CLASS__ . '.AvailableLabel', 'Available for purchase');
103
        $labels['Available.Nice'] = _t(__CLASS__ . '.AvailableLabelNice', 'Available');
104
        $labels['Image.CMSThumbnail'] = _t(__CLASS__ . '.ImageLabel', 'Image');
105
        $labels['ReceiptTitle'] = _t(__CLASS__ . '.ReceiptTitleLabel', 'Product title for receipt');
106
        $labels['FoxyCategoryID'] = _t(__CLASS__ . '.FoxyCategoryLabel', 'Foxy Category');
107
    }
108
109
    /**
110
     * @param FieldList $fields
111
     */
112
    public function updateCMSFields(FieldList $fields)
113
    {
114
        $fields->addFieldsToTab(
115
            'Root.Foxy',
116
            [
117
                CurrencyField::create('Price')
118
                    ->setDescription(_t(
119
                        __CLASS__ . '.PriceDescription',
120
                        'Base price for this product. Can be modified using Product Options'
121
                    )),
122
                TextField::create('Code')
123
                    ->setDescription(_t(
124
                        __CLASS__ . '.CodeDescription',
125
                        'Required, must be unique. Product identifier used by FoxyCart in transactions'
126
                    )),
127
                DropdownField::create('FoxyCategoryID')
128
                    ->setSource(FoxyCategory::get()->map())
129
                    ->setDescription(_t(
130
                        __CLASS__ . '.FoxyCategoryDescription',
131
                        'Required. Must also exist in 
132
                        <a href="https://admin.foxycart.com/admin.php?ThisAction=ManageProductCategories" 
133
                            target="_blank">
134
                            Foxy Categories
135
                        </a>.
136
                        Used to set category specific options like shipping and taxes. Managed in Foxy > Categories'
137
                    ))
138
                    ->setEmptyString(''),
139
                TextField::create('ReceiptTitle')
140
                    ->setDescription(_t(
141
                        __CLASS__ . '.ReceiptTitleDescription',
142
                        'Optional. Alternate title to display on order receipt'
143
                    )),
144
                CheckboxField::create('Available')
145
                    ->setDescription(_t(
146
                        __CLASS__ . '.AvailableDescription',
147
                        'If unchecked, will remove "Add to Cart" form and instead display "Currently unavailable"'
148
                    )),
149
            ],
150
            'Content'
151
        );
152
153
        if ($this->owner->ID) {
154
            $config = GridFieldConfig_RelationEditor::create();
155
            $config
156
                ->addComponents([
157
                    new GridFieldOrderableRows('SortOrder'),
158
                ])
159
                ->removeComponentsByType([
160
                    GridFieldAddExistingAutocompleter::class,
161
                ]);
162
            $options = GridField::create(
163
                'OptionTypes',
164
                'Options',
165
                $this->owner->OptionTypes()->sort('SortOrder'),
166
                $config
167
            );
168
            $fields->addFieldToTab('Root.Foxy', $options);
169
        }
170
    }
171
172
    /**
173
     * @return \SilverStripe\ORM\ValidationResult
174
     */
175
    public function validate(ValidationResult $validationResult)
176
    {
177
        if (!$this->owner->Price) {
178
            $validationResult->addError(
179
                _t(__CLASS__ . '.PriceRequired', 'You must set a product price in the Foxy tab')
180
            );
181
        }
182
183
        if (!$this->owner->Code) {
184
            $validationResult->addError(
185
                _t(__CLASS__ . '.CodeRequired', 'You must set a product code in the Foxy tab')
186
            );
187
        }
188
189
        if (!$this->owner->FoxyCategoryID) {
190
            $validationResult->addError(
191
                _t(__CLASS__ . '.FoxyCategoryRequired', 'You must set a foxy category in the Foxy tab.')
192
            );
193
        }
194
    }
195
196
    /**
197
     * @return bool
198
     */
199
    public function isAvailable()
200
    {
201
        if (!$this->owner->Available) {
202
            return false;
203
        }
204
205
        if (!$this->owner->OptionTypes()->exists()) {
206
            return true;
207
        }
208
209
        foreach ($this->owner->OptionTypes() as $type) {
210
            foreach ($type->Options() as $option) {
211
                if ($option->Available) {
212
                    return true;
213
                }
214
            }
215
        }
216
        
217
        return false;
218
    }
219
220
    /**
221
     * @return bool
222
     */
223
    public function isProduct()
224
    {
225
        return true;
226
    }
227
228
    /**
229
     * @return array
230
     */
231
    public function providePermissions()
232
    {
233
        return [
234
            'MANAGE_PRODUCTS' => [
235
                'name' => _t(
236
                    __CLASS__ . '.PERMISSION_MANAGE_PRODUCTS_DESCRIPTION',
237
                    'Manage products'
238
                ),
239
                'category' => _t(
240
                    __CLASS__ . '.PERMISSIONS_CATEGORY',
241
                    'Foxy'
242
                ),
243
                'help' => _t(
244
                    __CLASS__ . '.PERMISSION_MANAGE_PRODUCTS_HELP',
245
                    'Manage products and related settings'
246
                ),
247
                'sort' => 400,
248
            ],
249
        ];
250
    }
251
252
    /**
253
     * @param $member
254
     * @return bool|int|void
255
     */
256
    public function canCreate($member)
257
    {
258
        if (!$member) {
259
            $member = Security::getCurrentUser();
260
        }
261
262
        return Permission::checkMember($member, 'MANAGE_PRODUCTS');
263
    }
264
265
    /**
266
     * @param $member
267
     * @return bool|int|void|null
268
     */
269
    public function canEdit($member)
270
    {
271
        if (!$member) {
272
            $member = Security::getCurrentUser();
273
        }
274
275
        return Permission::checkMember($member, 'MANAGE_PRODUCTS');
276
    }
277
278
    /**
279
     * @param $member
280
     * @return bool|int|void
281
     */
282
    public function canDelete($member)
283
    {
284
        if (!$member) {
285
            $member = Security::getCurrentUser();
286
        }
287
288
        return Permission::checkMember($member, 'MANAGE_PRODUCTS');
289
    }
290
291
    /**
292
     * @param null $member
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $member is correct as it would always require null to be passed?
Loading history...
293
     * @return bool|int
294
     */
295
    public function canUnpublish($member = null)
296
    {
297
        if (!$member) {
0 ignored issues
show
introduced by
$member is of type null, thus it always evaluated to false.
Loading history...
298
            $member = Security::getCurrentUser();
299
        }
300
301
        return Permission::checkMember($member, 'MANAGE_PRODUCTS');
302
    }
303
304
    /**
305
     * @param $member
306
     * @return bool|int
307
     */
308
    public function canArchive($member = null)
309
    {
310
        if (!$member) {
311
            $member = Security::getCurrentUser();
312
        }
313
314
        return Permission::checkMember($member, 'MANAGE_PRODUCTS');
315
    }
316
}
317