Completed
Pull Request — master (#304)
by Jason
12:34
created

FoxyStripeSiteConfig::onBeforeWrite()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 20.1953

Importance

Changes 0
Metric Value
dl 0
loc 19
ccs 4
cts 15
cp 0.2667
rs 8.8571
c 0
b 0
f 0
cc 6
eloc 11
nc 4
nop 0
crap 20.1953
1
<?php
2
3
use Dynamic\FoxyStripe\Model\FoxyStripeClient;
4
5
class FoxyStripeSiteConfig extends DataExtension{
6
7
	private static $db = array(
8
	    'StoreTitle' => 'Varchar(255)',
9
		'StoreName' => 'Varchar(255)',
10
        'StoreURL' => 'Varchar(255)',
11
        'ReceiptURL' => 'Varchar(255)',
12
        'StoreEmail' => 'Varchar(255)',
13
        'FromEmail' => 'Varchar(255)',
14
        'StorePostalCode' => 'Varchar(10)',
15
        'StoreCountry' => 'Varchar(100)',
16
        'StoreRegion' => 'Varchar(100)',
17
        'StoreLocaleCode' => 'Varchar(10)',
18
        'StoreLogoURL' => 'Varchar(255)',
19
        'CheckoutType' => 'Varchar(50)',
20
        'BccEmail' => 'Boolean',
21
        'UseWebhook' => 'Boolean',
22
        'StoreKey' => 'Varchar(60)',
23
        'CartValidation' => 'Boolean',
24
        'UseSingleSignOn' => 'Boolean',
25
        'AllowMultiship' => 'Boolean',
26
        'StoreTimezone' => 'TimeZone',
27
		'MultiGroup' => 'Boolean',
28
		'ProductLimit' => 'Int',
29
		'MaxQuantity' => 'Int',
30
        'client_id' => 'Varchar(255)',
31
        'client_secret' => 'Varchar(255)',
32
        'access_token' => 'Varchar(255)',
33
        'refresh_token' => 'Varchar(255)',
34
	);
35
36
    // Set Default values
37
    private static $defaults = array(
38
        'ProductLimit' => 10
39
    );
40
41 1
	public function updateCMSFields(FieldList $fields){
42
43
        // set TabSet names to avoid spaces from camel case
44 1
        $fields->addFieldToTab('Root', new TabSet('FoxyStripe', 'FoxyStripe'));
45
46
        // settings tab
47 1
        $fields->addFieldsToTab('Root.FoxyStripe.Settings', array(
48
            // Store Details
49 1
			HeaderField::create('StoreDetails', _t('FoxyStripeSiteConfig.StoreDetails', 'Store Settings'), 3),
50 1
			LiteralField::create('DetailsIntro', _t(
51 1
				'FoxyStripeSiteConfig.DetailsIntro',
52
                '<p>Maps to data in your <a href="https://admin.foxycart.com/admin.php?ThisAction=EditStore" target="_blank">FoxyCart store settings</a>.'
53 1
            )),
54 1
            TextField::create('StoreTitle')
55 1
                ->setTitle(_t('FoxyStripeSiteConfig.StoreTitle', 'Store Name'))
56 1
                ->setDescription(_t('FoxyStripeSiteConfig.StoreTitleDescription', 'The name of your store as you\'d like it displayed to your customers')),
57 1
			TextField::create('StoreName')
58 1
				->setTitle(_t('FoxyStripeSiteConfig.StoreName', 'Store Domain'))
59 1
				->setDescription(_t('FoxyStripeSiteConfig.StoreNameDescription', 'This is a unique FoxyCart subdomain for your cart, checkout, and receipt')),
60 1
            TextField::create('StoreURL')
61 1
                ->setTitle(_t('FoxyStripeSiteConfig.StoreURL', 'Store URL'))
62 1
                ->setDescription(_t('FoxyStripeSiteConfig.StoreURLDescription', 'The URL of your online store')),
63 1
            TextField::create('ReceiptURL')
64 1
                ->setTitle(_t('FoxyStripeSiteConfig.ReceiptURL', 'Receipt URL'))
65 1
                ->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')),
66 1
            TextField::create('StoreEmail')
67 1
                ->setTitle(_t('FoxyStripeSiteConfig.StoreEmail', 'Store Email'))
68 1
                ->setDescription(_t('FoxyStripeSiteConfig.StoreEmailDescription', 'This is the email address of your store. By default, this will be the from address for your store receipts. ')),
69 1
            TextField::create('FromEmail')
70 1
                ->setTitle(_t('FoxyStripeSiteConfig.FromEmail', 'From Email'))
71 1
                ->setDescription(_t('FoxyStripeSiteConfig.FromEmailDescription', 'Used for when you want to specify a different from email than your store\'s email address')),
72 1
            TextField::create('StorePostalCode', 'Postal Code'),
73 1
            CountryDropdownField::create('StoreCountry', 'Country'),
74 1
            TextField::create('StoreRegion', 'State/Region'),
75 1
            TextField::create('StoreLocaleCode', 'Locale Code')
76 1
                ->setDescription('example: en_US'),
77 1
            TimeZoneField::create('StoreTimezone', 'Store timezone'),
78 1
            TextField::create('StoreLogoURL', 'Logo URL')
79 1
                ->setAttribute('placeholder', 'http://'),
80 1
            DropdownField::create('CheckoutType', 'Checkout Type', $this->getCheckoutTypes()),
81 1
            CheckboxField::create('BccEmail', 'BCC Admin Email')
82 1
                ->setDescription('bcc all receipts to store\'s email address'),
83 1
            CheckboxField::create('UseWebhook', 'Use Webhook')
84 1
                ->setDescription('record order history in CMS, allows customers to view their order history'),
85 1
            ReadonlyField::create('WebhookURL', 'Webhook URL', self::getDataFeedLink()),
86 1
            ReadonlyField::create('StoreKey', 'Webhook Key', self::getDataFeedLink()),
87 1
            CheckboxField::create('CartValidation', 'Use cart validation'),
88 1
            CheckboxField::create('UseSingleSignOn', 'Use single sign on')
89 1
                ->setDescription('Sync user accounts between FoxyCart and your website'),
90 1
            ReadonlyField::create('SingleSignOnURL', 'Single sign on URL', self::getSSOLink()),
91 1
            CheckboxField::create('AllowMultiship', 'Allow multiple shipments per order')
92
93
94
			// Advanced Settings
95
            /*
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...
96
			HeaderField::create('AdvanceHeader', _t('FoxyStripeSiteConfig.AdvancedHeader', 'Advanced Settings'), 3),
97
			LiteralField::create('AdvancedIntro', _t(
98
                'FoxyStripeSiteConfig.AdvancedIntro',
99
				'<p>Maps to data in your <a href="https://admin.foxycart.com/admin.php?ThisAction=EditAdvancedFeatures" target="_blank">FoxyCart advanced store settings</a>.</p>'
100
			)),
101
			ReadonlyField::create('DataFeedLink', _t('FoxyStripeSiteConfig.DataFeedLink', 'FoxyCart DataFeed URL'), self::getDataFeedLink())
102
				->setDescription(_t('FoxyStripeSiteConfig.DataFeedLinkDescription', 'copy/paste to FoxyCart')),
103
			CheckboxField::create('CartValidation')
104
				->setTitle(_t('FoxyStripeSiteConfig.CartValidation', 'Enable Cart Validation'))
105
				->setDescription(_t(
106
                    'FoxyStripeSiteConfig.CartValidationDescription',
107
                    '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.'
108
            )),
109
			ReadonlyField::create('StoreKey')
110
				->setTitle(_t('FoxyStripeSiteConfig.StoreKey', 'FoxyCart API Key'))
111
				->setDescription(_t('FoxyStripeSiteConfig.StoreKeyDescription', 'copy/paste to FoxyCart')),
112
			ReadonlyField::create('SSOLink', _t('FoxyStripeSiteConfig.SSOLink', 'Single Sign On URL'), self::getSSOLink())
113
				->setDescription(_t('FoxyStripeSiteConfig.SSOLinkDescription', 'copy/paste to FoxyCart'))
114
            */
115 1
        ));
116
117
        // configuration warning
118 1 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...
119 1
			$fields->insertBefore(LiteralField::create(
120 1
                "StoreSubDomainHeaderWarning",
121 1
                _t(
122 1
                    'FoxyStripeSiteConfig.StoreSubDomainHeadingWarning',
123
                    "<p class=\"message error\">Store sub-domain must be entered in the <a href=\"/admin/settings/\">site settings</a></p>"
124 1
                )
125 1
            ), 'StoreDetails');
0 ignored issues
show
Documentation introduced by
'StoreDetails' is of type string, but the function expects a object<FormField>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
126 1
		}
127
128
        // products tab
129 1
		$fields->addFieldsToTab('Root.FoxyStripe.Products', array(
130 1
			HeaderField::create('ProductHeader', _t('FoxyStripeSiteConfig.ProductHeader', 'Products'), 3),
131 1
			CheckboxField::create('MultiGroup')
132 1
				->setTitle(_t('FoxyStripeSiteConfig.MultiGroup', 'Multiple Groups'))
133 1
				->setDescription(_t(
134 1
                    'FoxyStripeSiteConfig.MultiGroupDescription',
135
                    'Allows products to be shown in multiple Product Groups'
136 1
                )),
137 1
			HeaderField::create('ProductGroupHD', _t('FoxyStripeSiteConfig.ProductGroupHD', 'Product Groups'), 3),
138 1
			NumericField::create('ProductLimit')
139 1
				->setTitle(_t('FoxyStripeSiteConfig.ProductLimit', 'Products per Page'))
140 1
				->setDescription(_t(
141 1
                    'FoxyStripeSiteConfig.ProductLimitDescription',
142
                    'Number of Products to show per page on a Product Group'
143 1
                )),
144 1
			HeaderField::create('ProductQuantityHD', _t('FoxyStripeSiteConfig.ProductQuantityHD', 'Product Form Max Quantity'), 3),
145 1
			NumericField::create('MaxQuantity')
146 1
				->setTitle(_t('FoxyStripeSiteConfig.MaxQuantity', 'Max Quantity'))
147 1
				->setDescription(_t(
148 1
                    'FoxyStripeSiteConfig.MaxQuantityDescription',
149
                    'Sets max quantity for product form dropdown (add to cart form - default 10)'
150 1
                ))
151 1
		));
152
153
        // categories tab
154 1
		$fields->addFieldsToTab('Root.FoxyStripe.Categories', array(
155 1
			HeaderField::create('CategoryHD', _t('FoxyStripeSiteConfig.CategoryHD', 'FoxyStripe Categories'), 3),
156 1
			LiteralField::create('CategoryDescrip', _t(
157 1
                'FoxyStripeSiteConfig.CategoryDescrip',
158
                '<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>'
159 1
            )),
160 1
			GridField::create(
161 1
                'ProductCategory',
162 1
                _t('FoxyStripeSiteConfig.ProductCategory', 'FoxyCart Categories'),
163 1
                ProductCategory::get(),
164 1
                GridFieldConfig_RecordEditor::create()
165 1
            )
166 1
		));
167
168
        // option groups tab
169 1
		$fields->addFieldsToTab('Root.FoxyStripe.Groups', array(
170 1
			HeaderField::create('OptionGroupsHead', _t('FoxyStripeSiteConfig', 'Product Option Groups'), 3),
171 1
			LiteralField::create('OptionGroupsDescrip', _t(
172 1
                'FoxyStripeSiteConfig.OptionGroupsDescrip',
173
                '<p>Product Option Groups allow you to name a set of product options.</p>'
174 1
            )),
175 1
			GridField::create(
176 1
                'OptionGroup',
177 1
                _t('FoxyStripeSiteConfig.OptionGroup', 'Product Option Groups'),
178 1
                OptionGroup::get(),
179 1
                GridFieldConfig_RecordEditor::create()
180 1
            )
181 1
		));
182
183
		// api tab
184 1
        $fields->addFieldsToTab('Root.FoxyStripe.API', [
185 1
            HeaderField::create('APIHD', 'FoxyCart API Settings', 3),
186 1
            TextField::create('client_id', 'FoxyCart Client ID'),
187 1
            TextField::create('client_secret', 'FoxyCart Client Secret'),
188 1
            TextField::create('access_token', 'FoxyCart Access Token'),
189 1
            TextField::create('refresh_token', 'FoxyCart Refresh Token'),
190 1
        ]);
191
192 1
	}
193
194 2
    private static function getSSOLink() {
195 2
        return Director::absoluteBaseURL()."foxystripe/sso/";
196
    }
197
198 2
    private static function getDataFeedLink() {
199 2
        return Director::absoluteBaseURL()."foxystripe/";
200
    }
201
202
    // generate key on install
203 3
    public function requireDefaultRecords() {
204
205 3
        parent::requireDefaultRecords();
206
207 3
        $siteConfig = SiteConfig::current_site_config();
208
209 3
        if(!$siteConfig->StoreKey) {
210 3
            $key = FoxyCart::setStoreKey();
211 3
            while(!ctype_alnum($key)){
212
                $key = FoxyCart::setStoreKey();
213
            }
214 3
            $siteConfig->StoreKey = $key;
215 3
            $siteConfig->write();
216 3
            DB::alteration_message($siteConfig->ClassName.": created FoxyCart Store Key " . $key, 'created');
217 3
        }
218 3
    }
219
220 1
    public function getCheckoutTypes()
221
    {
222
        return [
223 1
            "default_account" => "Allow guest and customer accounts, default to account",
224 1
            "default_guest" => "Allow guest and customer accounts, default to guest",
225 1
            "account_only" => "Allow customer accounts only",
226 1
            "guest_only" => "Allow guests only",
227 1
        ];
228
    }
229
230
    /**
231
     * @return array
232
     */
233 1
    public function getDataMap()
234
    {
235
        return [
236 1
            'store_name' => $this->owner->StoreTitle,
237 1
            'store_domain' => $this->owner->StoreName,
238 1
            'store_url' => $this->owner->StoreURL,
239 1
            'receipt_continue_url' => $this->owner->ReceiptURL,
240 1
            'store_email' => $this->owner->StoreEmail,
241 1
            'from_email' => $this->owner->FromEmail,
242 1
            'postal_code' => $this->owner->StorePostalCode,
243 1
            'country' => $this->owner->StoreCountry,
244 1
            'region' => $this->owner->StoreRegion,
245 1
            'locale_code' => $this->owner->StoreLocaleCode,
246 1
            'logo_url' => $this->owner->StoreLogoURL,
247 1
            'checkout_type' => $this->owner->CheckoutType,
248 1
            'bcc_on_receipt_email' => $this->owner->BccEmail,
249 1
            'use_webhook' => $this->owner->UseWebhook,
250 1
            'webhook_url' => $this->getDataFeedLink(),
251 1
            'webhook_key' => $this->owner->StoreKey,
252 1
            'use_cart_validation' => $this->owner->CartValidation,
253 1
            'use_single_sign_on' => $this->owner->UseSingleSignOn,
254 1
            'single_sign_on_url' => $this->getSSOLink(),
255 1
            'customer_password_hash_type' => 'sha1_salted_suffix',
256 1
            'customer_password_hash_config' => 40,
257 1
            'features_multiship' => $this->owner->AllowMultiship,
258 1
            'timezone' => $this->StoreTimezone,
0 ignored issues
show
Bug introduced by
The property StoreTimezone does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
259 1
        ];
260
    }
261
262
    /**
263
     * if StoreTitle is empty, grab values from FoxyCart
264
     *
265
     * example of 2 way sync for future reference
266
     */
267 48
    public function onBeforeWrite()
268
    {
269 48
        parent::onBeforeWrite();
270
271 48
        if ($this->owner->ID && !$this->owner->StoreTitle && $this->owner->access_token) {
272
            if ($fc = new FoxyStripeClient()) {
273
                $client = $fc->getClient();
274
                $errors = [];
275
276
                $result = $client->get($fc->getCurrentStore());
277
                $this->owner->StoreTitle = $result['store_name'];
278
279
                $errors = array_merge($errors, $client->getErrors($result));
280
                if (count($errors)) {
281
                    \SS_Log::log('FoxyStripeSiteConfig::onBeforeWrite errors - ' . json_encode($errors), \SS_Log::WARN);
282
                }
283
            }
284
        }
285 48
    }
286
287
    /**
288
     * push updated data to FoxyCart
289
     */
290 48
    public function onAfterWrite()
291
    {
292 48
        parent::onAfterWrite();
293
294 48
        if ($this->owner->isChanged() && $this->owner->access_token) {
295
            if ($fc = new FoxyStripeClient()) {
296
                $fc->updateStore($this->getDataMap());
297
            }
298
        }
299 48
    }
300
}
301