Passed
Pull Request — master (#309)
by Jason
13:47
created

FoxyStripeSiteConfig::onBeforeWrite()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.2
c 0
b 0
f 0
cc 4
eloc 2
nc 2
nop 0
1
<?php
2
3
namespace Dynamic\FoxyStripe\ORM;
4
5
use Dynamic\CountryDropdownField\Fields\CountryDropdownField;
6
use Dynamic\FoxyStripe\Model\FoxyCart;
7
use Dynamic\FoxyStripe\Model\FoxyStripeClient;
8
use Dynamic\FoxyStripe\Model\OptionGroup;
9
use Dynamic\FoxyStripe\Model\ProductCategory;
10
use Psr\Log\LoggerInterface;
11
use SilverStripe\Control\Director;
12
use SilverStripe\Core\Injector\Injector;
13
use SilverStripe\Forms\CheckboxField;
14
use SilverStripe\Forms\DropdownField;
15
use SilverStripe\Forms\FieldList;
16
use SilverStripe\Forms\GridField\GridField;
17
use SilverStripe\Forms\GridField\GridFieldConfig_RecordEditor;
18
use SilverStripe\Forms\HeaderField;
19
use SilverStripe\Forms\LiteralField;
20
use SilverStripe\Forms\NumericField;
21
use SilverStripe\Forms\ReadonlyField;
22
use SilverStripe\Forms\TabSet;
23
use SilverStripe\Forms\TextField;
24
use SilverStripe\ORM\DataExtension;
25
use SilverStripe\ORM\DB;
26
use SilverStripe\SiteConfig\SiteConfig;
27
28
class FoxyStripeSiteConfig extends DataExtension
29
{
30
31
	private static $db = array(
0 ignored issues
show
introduced by
The private property $db is not used, and could be removed.
Loading history...
32
	    'StoreTitle' => 'Varchar(255)',
33
		'StoreName' => 'Varchar(255)',
34
        'StoreURL' => 'Varchar(255)',
35
        'ReceiptURL' => 'Varchar(255)',
36
        'StoreEmail' => 'Varchar(255)',
37
        'FromEmail' => 'Varchar(255)',
38
        'StorePostalCode' => 'Varchar(10)',
39
        'StoreCountry' => 'Varchar(100)',
40
        'StoreRegion' => 'Varchar(100)',
41
        'StoreLocaleCode' => 'Varchar(10)',
42
        'StoreLogoURL' => 'Varchar(255)',
43
        'CheckoutType' => 'Varchar(50)',
44
        'BccEmail' => 'Boolean',
45
        'UseWebhook' => 'Boolean',
46
        'StoreKey' => 'Varchar(60)',
47
        'CartValidation' => 'Boolean',
48
        'UseSingleSignOn' => 'Boolean',
49
        'AllowMultiship' => 'Boolean',
50
        'StoreTimezone' => 'Varchar(100)',
51
		'MultiGroup' => 'Boolean',
52
		'ProductLimit' => 'Int',
53
		'MaxQuantity' => 'Int',
54
        'client_id' => 'Varchar(255)',
55
        'client_secret' => 'Varchar(255)',
56
        'access_token' => 'Varchar(255)',
57
        'refresh_token' => 'Varchar(255)',
58
	);
59
60
    // Set Default values
61
    private static $defaults = array(
0 ignored issues
show
introduced by
The private property $defaults is not used, and could be removed.
Loading history...
62
        'ProductLimit' => 10
63
    );
64
65
	public function updateCMSFields(FieldList $fields){
66
67
        // set TabSet names to avoid spaces from camel case
68
        $fields->addFieldToTab('Root', new TabSet('FoxyStripe', 'FoxyStripe'));
69
70
        // settings tab
71
        $fields->addFieldsToTab('Root.FoxyStripe.Settings', array(
72
            // Store Details
73
			HeaderField::create('StoreDetails', _t('FoxyStripeSiteConfig.StoreDetails', 'Store Settings'), 3),
0 ignored issues
show
Bug introduced by
'StoreDetails' of type string is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

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

73
			HeaderField::create(/** @scrutinizer ignore-type */ 'StoreDetails', _t('FoxyStripeSiteConfig.StoreDetails', 'Store Settings'), 3),
Loading history...
Bug introduced by
3 of type integer is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

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

73
			HeaderField::create('StoreDetails', _t('FoxyStripeSiteConfig.StoreDetails', 'Store Settings'), /** @scrutinizer ignore-type */ 3),
Loading history...
74
			LiteralField::create('DetailsIntro', _t(
75
				'FoxyStripeSiteConfig.DetailsIntro',
76
                '<p>Maps to data in your <a href="https://admin.foxycart.com/admin.php?ThisAction=EditStore" target="_blank">FoxyCart store settings</a>.'
77
            )),
78
            TextField::create('StoreTitle')
79
                ->setTitle(_t('FoxyStripeSiteConfig.StoreTitle', 'Store Name'))
80
                ->setDescription(_t('FoxyStripeSiteConfig.StoreTitleDescription', 'The name of your store as you\'d like it displayed to your customers')),
81
			TextField::create('StoreName')
82
				->setTitle(_t('FoxyStripeSiteConfig.StoreName', 'Store Domain'))
83
				->setDescription(_t('FoxyStripeSiteConfig.StoreNameDescription', 'This is a unique FoxyCart subdomain for your cart, checkout, and receipt')),
84
            TextField::create('StoreURL')
85
                ->setTitle(_t('FoxyStripeSiteConfig.StoreURL', 'Store URL'))
86
                ->setDescription(_t('FoxyStripeSiteConfig.StoreURLDescription', 'The URL of your online store')),
87
            TextField::create('ReceiptURL')
88
                ->setTitle(_t('FoxyStripeSiteConfig.ReceiptURL', 'Receipt URL'))
89
                ->setDescription(_t('FoxyStripeSiteConfig.ReceiptURLDescription', 'By default, FoxyCart sends customers back to the page referrer after completing a purchase. Instead, you can set a specific URL here')),
90
            TextField::create('StoreEmail')
91
                ->setTitle(_t('FoxyStripeSiteConfig.StoreEmail', 'Store Email'))
92
                ->setDescription(_t('FoxyStripeSiteConfig.StoreEmailDescription', 'This is the email address of your store. By default, this will be the from address for your store receipts. ')),
93
            TextField::create('FromEmail')
94
                ->setTitle(_t('FoxyStripeSiteConfig.FromEmail', 'From Email'))
95
                ->setDescription(_t('FoxyStripeSiteConfig.FromEmailDescription', 'Used for when you want to specify a different from email than your store\'s email address')),
96
            TextField::create('StorePostalCode', 'Postal Code'),
97
            CountryDropdownField::create('StoreCountry', 'Country'),
98
            TextField::create('StoreRegion', 'State/Region'),
99
            TextField::create('StoreLocaleCode', 'Locale Code')
100
                ->setDescription('example: en_US'),
101
            TextField::create('StoreTimezone', 'Store timezone'),
102
            TextField::create('StoreLogoURL', 'Logo URL')
103
                ->setAttribute('placeholder', 'http://')
104
105
			// Advanced Settings
106
            /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% 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...
107
			HeaderField::create('AdvanceHeader', _t('FoxyStripeSiteConfig.AdvancedHeader', 'Advanced Settings'), 3),
108
			LiteralField::create('AdvancedIntro', _t(
109
                'FoxyStripeSiteConfig.AdvancedIntro',
110
				'<p>Maps to data in your <a href="https://admin.foxycart.com/admin.php?ThisAction=EditAdvancedFeatures" target="_blank">FoxyCart advanced store settings</a>.</p>'
111
			)),
112
			ReadonlyField::create('DataFeedLink', _t('FoxyStripeSiteConfig.DataFeedLink', 'FoxyCart DataFeed URL'), self::getDataFeedLink())
113
				->setDescription(_t('FoxyStripeSiteConfig.DataFeedLinkDescription', 'copy/paste to FoxyCart')),
114
			CheckboxField::create('CartValidation')
115
				->setTitle(_t('FoxyStripeSiteConfig.CartValidation', 'Enable Cart Validation'))
116
				->setDescription(_t(
117
                    'FoxyStripeSiteConfig.CartValidationDescription',
118
                    'You must <a href="https://admin.foxycart.com/admin.php?ThisAction=EditAdvancedFeatures#use_cart_validation" target="_blank">enable cart validation</a> in the FoxyCart admin.'
119
            )),
120
			ReadonlyField::create('StoreKey')
121
				->setTitle(_t('FoxyStripeSiteConfig.StoreKey', 'FoxyCart API Key'))
122
				->setDescription(_t('FoxyStripeSiteConfig.StoreKeyDescription', 'copy/paste to FoxyCart')),
123
			ReadonlyField::create('SSOLink', _t('FoxyStripeSiteConfig.SSOLink', 'Single Sign On URL'), self::getSSOLink())
124
				->setDescription(_t('FoxyStripeSiteConfig.SSOLinkDescription', 'copy/paste to FoxyCart'))
125
            */
126
        ));
127
128
        $fields->addFieldsToTab('Root.FoxyStripe.Advanced', [
129
            HeaderField::create('AdvanceHeader', _t('FoxyStripeSiteConfig.AdvancedHeader', 'Advanced Settings'), 3),
130
            LiteralField::create('AdvancedIntro', _t(
131
                'FoxyStripeSiteConfig.AdvancedIntro',
132
                '<p>Maps to data in your <a href="https://admin.foxycart.com/admin.php?ThisAction=EditAdvancedFeatures" target="_blank">FoxyCart advanced store settings</a>.</p>'
133
            )),
134
            DropdownField::create('CheckoutType', 'Checkout Type', $this->getCheckoutTypes()),
135
            CheckboxField::create('BccEmail', 'BCC Admin Email')
136
                ->setDescription('bcc all receipts to store\'s email address'),
137
            CheckboxField::create('UseWebhook', 'Use Webhook')
138
                ->setDescription('record order history in CMS, allows customers to view their order history'),
139
            ReadonlyField::create('WebhookURL', 'Webhook URL', self::getDataFeedLink()),
140
            ReadonlyField::create('StoreKey', 'Webhook Key', self::getDataFeedLink()),
141
            CheckboxField::create('CartValidation', 'Use cart validation'),
142
            CheckboxField::create('UseSingleSignOn', 'Use single sign on')
143
                ->setDescription('Sync user accounts between FoxyCart and your website'),
144
            ReadonlyField::create('SingleSignOnURL', 'Single sign on URL', self::getSSOLink()),
145
            CheckboxField::create('AllowMultiship', 'Allow multiple shipments per order')
146
        ]);
147
148
        // configuration warning
149
		if(FoxyCart::store_name_warning()!==null){
150
			$fields->insertBefore(LiteralField::create(
151
                "StoreSubDomainHeaderWarning",
152
                _t(
153
                    'FoxyStripeSiteConfig.StoreSubDomainHeadingWarning',
154
                    "<p class=\"message error\">Store sub-domain must be entered in the <a href=\"/admin/settings/\">site settings</a></p>"
155
                )
156
            ), 'StoreDetails');
0 ignored issues
show
Bug introduced by
'StoreDetails' of type string is incompatible with the type SilverStripe\Forms\FormField expected by parameter $item of SilverStripe\Forms\FieldList::insertBefore(). ( Ignorable by Annotation )

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

156
            ), /** @scrutinizer ignore-type */ 'StoreDetails');
Loading history...
157
		}
158
159
        // products tab
160
		$fields->addFieldsToTab('Root.FoxyStripe.Products', array(
161
			HeaderField::create('ProductHeader', _t('FoxyStripeSiteConfig.ProductHeader', 'Products'), 3),
162
			CheckboxField::create('MultiGroup')
163
				->setTitle(_t('FoxyStripeSiteConfig.MultiGroup', 'Multiple Groups'))
164
				->setDescription(_t(
165
                    'FoxyStripeSiteConfig.MultiGroupDescription',
166
                    'Allows products to be shown in multiple Product Groups'
167
                )),
168
			HeaderField::create('ProductGroupHD', _t('FoxyStripeSiteConfig.ProductGroupHD', 'Product Groups'), 3),
169
			NumericField::create('ProductLimit')
170
				->setTitle(_t('FoxyStripeSiteConfig.ProductLimit', 'Products per Page'))
171
				->setDescription(_t(
172
                    'FoxyStripeSiteConfig.ProductLimitDescription',
173
                    'Number of Products to show per page on a Product Group'
174
                )),
175
			HeaderField::create('ProductQuantityHD', _t('FoxyStripeSiteConfig.ProductQuantityHD', 'Product Form Max Quantity'), 3),
176
			NumericField::create('MaxQuantity')
177
				->setTitle(_t('FoxyStripeSiteConfig.MaxQuantity', 'Max Quantity'))
178
				->setDescription(_t(
179
                    'FoxyStripeSiteConfig.MaxQuantityDescription',
180
                    'Sets max quantity for product form dropdown (add to cart form - default 10)'
181
                ))
182
		));
183
184
        // categories tab
185
		$fields->addFieldsToTab('Root.FoxyStripe.Categories', array(
186
			HeaderField::create('CategoryHD', _t('FoxyStripeSiteConfig.CategoryHD', 'FoxyStripe Categories'), 3),
187
			LiteralField::create('CategoryDescrip', _t(
188
                'FoxyStripeSiteConfig.CategoryDescrip',
189
                '<p>FoxyCart Categories offer a way to give products additional behaviors that cannot be accomplished by product options alone, including category specific coupon codes, shipping and handling fees, and email receipts. <a href="https://wiki.foxycart.com/v/2.0/categories" target="_blank">Learn More</a></p><p>Categories you\'ve created in FoxyStripe must also be created in your <a href="https://admin.foxycart.com/admin.php?ThisAction=ManageProductCategories" target="_blank">FoxyCart Categories</a> admin panel.</p>'
190
            )),
191
			GridField::create(
192
                'ProductCategory',
193
                _t('FoxyStripeSiteConfig.ProductCategory', 'FoxyCart Categories'),
194
                ProductCategory::get(),
0 ignored issues
show
Bug introduced by
Dynamic\FoxyStripe\Model\ProductCategory::get() of type SilverStripe\ORM\DataList is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

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

194
                /** @scrutinizer ignore-type */ ProductCategory::get(),
Loading history...
195
                GridFieldConfig_RecordEditor::create()
196
            )
197
		));
198
199
        // option groups tab
200
		$fields->addFieldsToTab('Root.FoxyStripe.Groups', array(
201
			HeaderField::create('OptionGroupsHead', _t('FoxyStripeSiteConfig', 'Product Option Groups'), 3),
202
			LiteralField::create('OptionGroupsDescrip', _t(
203
                'FoxyStripeSiteConfig.OptionGroupsDescrip',
204
                '<p>Product Option Groups allow you to name a set of product options.</p>'
205
            )),
206
			GridField::create(
207
                'OptionGroup',
208
                _t('FoxyStripeSiteConfig.OptionGroup', 'Product Option Groups'),
209
                OptionGroup::get(),
210
                GridFieldConfig_RecordEditor::create()
211
            )
212
		));
213
214
		// api tab
215
        $fields->addFieldsToTab('Root.FoxyStripe.API', [
216
            HeaderField::create('APIHD', 'FoxyCart API Settings', 3),
217
            TextField::create('client_id', 'FoxyCart Client ID'),
218
            TextField::create('client_secret', 'FoxyCart Client Secret'),
219
            TextField::create('access_token', 'FoxyCart Access Token'),
220
            TextField::create('refresh_token', 'FoxyCart Refresh Token'),
221
        ]);
222
223
	}
224
225
    /**
226
     * @return string
227
     */
228
    private static function getSSOLink() {
229
        return Director::absoluteBaseURL()."foxystripe/sso/";
230
    }
231
232
    /**
233
     * @return string
234
     */
235
    private static function getDataFeedLink() {
236
        return Director::absoluteBaseURL()."foxystripe/";
237
    }
238
239
    /**
240
     * generate key on install
241
     *
242
     * @throws \SilverStripe\ORM\ValidationException
243
     */
244
    public function requireDefaultRecords() {
245
246
        parent::requireDefaultRecords();
247
248
        $siteConfig = SiteConfig::current_site_config();
249
250
        if(!$siteConfig->StoreKey) {
251
            $key = FoxyCart::setStoreKey();
252
            while(!ctype_alnum($key)){
253
                $key = FoxyCart::setStoreKey();
254
            }
255
            $siteConfig->StoreKey = $key;
256
            $siteConfig->write();
257
            DB::alteration_message($siteConfig->ClassName.": created FoxyCart Store Key " . $key, 'created');
258
        }
259
    }
260
261
    /**
262
     * @return array
263
     */
264
    public function getCheckoutTypes()
265
    {
266
        return [
267
            "default_account" => "Allow guest and customer accounts, default to account",
268
            "default_guest" => "Allow guest and customer accounts, default to guest",
269
            "account_only" => "Allow customer accounts only",
270
            "guest_only" => "Allow guests only",
271
        ];
272
    }
273
274
    /**
275
     * @return array
276
     */
277
    public function getDataMap()
278
    {
279
        return [
280
            'store_name' => $this->owner->StoreTitle,
281
            'store_domain' => $this->owner->StoreName,
282
            'store_url' => $this->owner->StoreURL,
283
            'receipt_continue_url' => $this->owner->ReceiptURL,
284
            'store_email' => $this->owner->StoreEmail,
285
            'from_email' => $this->owner->FromEmail,
286
            'postal_code' => $this->owner->StorePostalCode,
287
            'country' => $this->owner->StoreCountry,
288
            'region' => $this->owner->StoreRegion,
289
            'locale_code' => $this->owner->StoreLocaleCode,
290
            'logo_url' => $this->owner->StoreLogoURL,
291
            'checkout_type' => $this->owner->CheckoutType,
292
            'bcc_on_receipt_email' => $this->owner->BccEmail,
293
            'use_webhook' => $this->owner->UseWebhook,
294
            'webhook_url' => $this->getDataFeedLink(),
295
            'webhook_key' => $this->owner->StoreKey,
296
            'use_cart_validation' => $this->owner->CartValidation,
297
            'use_single_sign_on' => $this->owner->UseSingleSignOn,
298
            'single_sign_on_url' => $this->getSSOLink(),
299
            'customer_password_hash_type' => 'sha1_salted_suffix',
300
            'customer_password_hash_config' => 40,
301
            'features_multiship' => $this->owner->AllowMultiship,
302
            //'timezone' => $this->StoreTimezone,
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...
303
        ];
304
    }
305
306
    /**
307
     * if StoreTitle is empty, grab values from FoxyCart
308
     *
309
     * example of 2 way sync for future reference
310
     *
311
     * @throws \Psr\Container\NotFoundExceptionInterface
312
     */
313
    public function onBeforeWrite()
314
    {
315
        parent::onBeforeWrite();
316
317
        if ($this->owner->ID && !$this->owner->StoreTitle && $this->owner->access_token) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
318
            /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
56% 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...
319
            if ($fc = new FoxyStripeClient()) {
320
                $client = $fc->getClient();
321
                $errors = [];
322
323
                $result = $client->get($fc->getCurrentStore());
324
                $this->owner->StoreTitle = $result['store_name'];
325
326
                $errors = array_merge($errors, $client->getErrors($result));
327
                if (count($errors)) {
328
                    Injector::inst()->get(LoggerInterface::class)
329
                        ->error('FoxyStripeSiteConfig::onBeforeWrite errors - ' . json_encode($errors));
330
                }
331
            }
332
            */
333
        }
334
    }
335
336
    /**
337
     * @throws \Psr\Container\NotFoundExceptionInterface
338
     */
339
    public function onAfterWrite()
340
    {
341
        parent::onAfterWrite();
342
343
        if ($this->owner->isChanged() && $this->owner->access_token) {
344
            if ($fc = new FoxyStripeClient()) {
345
                $fc->updateStore($this->getDataMap());
346
            }
347
        }
348
    }
349
}
350