Completed
Push — 2 ( 76c155...18ff94 )
by Jason
10:10
created
code/admin/OrderAdmin.php 1 patch
Indentation   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -2,13 +2,13 @@
 block discarded – undo
2 2
 
3 3
 class OrderAdmin extends ModelAdmin {
4 4
 
5
-	public static $managed_models = array(
6
-		'Order'
7
-	);
5
+    public static $managed_models = array(
6
+        'Order'
7
+    );
8 8
 	
9
-	static $url_segment = 'orders';
9
+    static $url_segment = 'orders';
10 10
 	
11
-	static $menu_title = 'Orders';
11
+    static $menu_title = 'Orders';
12 12
 
13 13
     public function getEditForm($id = null, $fields = null) {
14 14
         $form = parent::getEditForm($id, $fields);
Please login to merge, or discard this patch.
code/model/foxycart.cart_validation.php 1 patch
Indentation   +310 added lines, -310 removed lines patch added patch discarded remove patch
@@ -14,315 +14,315 @@
 block discarded – undo
14 14
  *   - Empty textareas are assumed to be "open"
15 15
  */
16 16
 class FoxyCart_Helper {
17
-	/**
18
-	 * API Key (Secret)
19
-	 *
20
-	 * @var string
21
-	 **/
22
-	private static $secret;
23
-
24
-	/**
25
-	 * Cart URL
26
-	 *
27
-	 * @var string
28
-	 * Notes: Could be 'https://yourdomain.foxycart.com/cart' or 'https://secure.yourdomain.com/cart'
29
-	 **/
30
-	// protected static $cart_url = 'https://yourdomain.foxycart.com/cart';
31
-	protected static $cart_url;
32
-
33
-	public static function setCartURL($storeName = null){
34
-		self::$cart_url = 'https://'.$storeName.'.faxycart.com/cart';
35
-	}
36
-
37
-	public static function setSecret($secret = null){
38
-		self::$secret = $secret;
39
-	}
40
-
41
-	public function __construct(){
42
-		self::setCartURL(FoxyCart::getFoxyCartStoreName());
43
-		self::setSecret(FoxyCart::getStoreKey());
44
-	}
45
-
46
-	public static function getSecret(){
47
-		return FoxyCart::getStoreKey();
48
-	}
49
-
50
-
51
-	/**
52
-	 * Cart Excludes
53
-	 *
54
-	 * Arrays of values and prefixes that should be ignored when signing links and forms.
55
-	 * @var array
56
-	 */
57
-	protected static $cart_excludes = array(
58
-		// Cart values
59
-		'cart', 'fcsid', 'empty', 'coupon', 'output', 'sub_token', 'redirect', 'callback', '_',
60
-		// Checkout pre-population values
61
-		'customer_email', 'customer_first_name', 'customer_last_name', 'customer_address1', 'customer_address2',
62
-		'customer_city', 'customer_state', 'customer_postal_code', 'customer_country', 'customer_phone', 'customer_company',
63
-		'shipping_first_name', 'shipping_last_name', 'shipping_address1', 'shipping_address2',
64
-		'shipping_city', 'shipping_state', 'shipping_postal_code', 'shipping_country', 'shipping_phone', 'shipping_company',
65
-	);
66
-	protected static $cart_excludes_prefixes = array(
67
-		'h:', 'x:', '__',
68
-	);
69
-
70
-	/**
71
-	 * Debugging
72
-	 *
73
-	 * Set to $debug to TRUE to enable debug logging.
74
-	 *
75
-	 */
76
-	protected static $debug = FALSE;
77
-	protected static $log = array();
78
-
79
-
80
-	/**
81
-	 * "Link Method": Generate HMAC SHA256 for GET Query Strings
82
-	 *
83
-	 * Notes: Can't parse_str because PHP doesn't support non-alphanumeric characters as array keys.
84
-	 * @return string
85
-	 **/
86
-	public static function fc_hash_querystring($qs, $output = TRUE) {
87
-		self::$log[] = '<strong>Signing link</strong> with data: '.htmlspecialchars(substr($qs, 0, 150)).'...';
88
-		$fail = self::$cart_url.'?'.$qs;
89
-
90
-		// If the link appears to be hashed already, don't bother
91
-		if (strpos($qs, '||')) {
92
-			self::$log[] = '<strong>Link appears to be signed already</strong>: '.htmlspecialchars($code[0]);
93
-			return $fail;
94
-		}
95
-
96
-		// Stick an ampersand on the beginning of the querystring to make matching the first element a little easier
97
-		$qs = '&'.urldecode($qs);
98
-
99
-		// Get all the prefixes, codes, and name=value pairs
100
-		preg_match_all('%(?P<amp>&(?:amp;)?)(?P<prefix>[a-z0-9]{1,3}:)?(?P<name>[^=]+)=(?P<value>[^&]+)%', $qs, $pairs, PREG_SET_ORDER);
101
-		self::$log[] = 'Found the following pairs to sign:<pre>'.htmlspecialchars(print_r($pairs, true)).'</pre>';
102
-
103
-		// Get all the "code" values, set the matches in $codes
104
-		$codes = array();
105
-		foreach ($pairs as $pair) {
106
-			if ($pair['name'] == 'code') {
107
-				$codes[$pair['prefix']] = $pair['value'];
108
-			}
109
-		}
110
-		if ( ! count($codes)) {
111
-			self::$log[] = '<strong style="color:#600;">No code found</strong> for the above link.';
112
-			return $fail;
113
-		}
114
-		self::$log[] = '<strong style="color:orange;">CODES found:</strong> '.htmlspecialchars(print_r($codes, true));
115
-
116
-		// Sign the name/value pairs
117
-		foreach ($pairs as $pair) {
118
-			// Skip the cart excludes
119
-			if (in_array($pair['name'], self::$cart_excludes) || in_array($pair['prefix'], self::$cart_excludes_prefixes)) {
120
-				self::$log[] = '<strong style="color:purple;">Skipping</strong> the reserved parameter or prefix "'.$pair['prefix'].$pair['name'].'" = '.$pair['value'];
121
-				continue;
122
-			}
123
-
124
-			// Continue to sign the value and replace the name=value in the querystring with name=value||hash
125
-			$value = self::fc_hash_value($codes[$pair['prefix']], $pair['name'], $pair['value'], 'value', FALSE, 'urlencode');
126
-			$replacement = $pair['amp'].$pair['prefix'].urlencode($pair['name']).'='.$value;
127
-			$qs = str_replace($pair[0], $replacement, $qs);
128
-			self::$log[] = 'Signed <strong>'.$pair['name'].'</strong> = <strong>'.$pair['value'].'</strong> with '.$replacement.'.<br />Replacing: '.$pair[0].'<br />With... '.$replacement;
129
-		}
130
-		$qs = ltrim($qs, '&'); // Get rid of that leading ampersand we added earlier
131
-
132
-		if ($output) {
133
-			echo self::$cart_url.'?'.$qs;
134
-		} else {
135
-			return self::$cart_url.'?'.$qs;
136
-		}
137
-	}
138
-
139
-
140
-	/**
141
-	 * "Form Method": Generate HMAC SHA256 for form elements or individual <input />s
142
-	 *
143
-	 * @return string
144
-	 **/
145
-	public static function fc_hash_value($product_code, $option_name, $option_value = '', $method = 'name', $output = TRUE, $urlencode = false) {
146
-		if (!$product_code || !$option_name) {
147
-			return FALSE;
148
-		}
149
-		if ($option_value == '--OPEN--') {
150
-			$hash = hash_hmac('sha256', $product_code.$option_name.$option_value, self::getSecret());
151
-			$value = ($urlencode) ? urlencode($option_name).'||'.$hash.'||open' : $option_name.'||'.$hash.'||open';
152
-		} else {
153
-			$hash = hash_hmac('sha256', $product_code.$option_name.$option_value, self::getSecret());
154
-			if ($method == 'name') {
155
-				$value = ($urlencode) ? urlencode($option_name).'||'.$hash : $option_name.'||'.$hash;
156
-			} else {
157
-				$value = ($urlencode) ? urlencode($option_value).'||'.$hash : $option_value.'||'.$hash;
158
-			}
159
-		}
160
-
161
-		if ($output) {
162
-			echo $value;
163
-		} else {
164
-			return $value;
165
-		}
166
-	}
167
-
168
-	/**
169
-	 * Raw HTML Signing: Sign all links and form elements in a block of HTML
170
-	 *
171
-	 * Accepts a string of HTML and signs all links and forms.
172
-	 * Requires link 'href' and form 'action' attributes to use 'https' and not 'http'.
173
-	 * Requires a 'code' to be set in every form.
174
-	 *
175
-	 * @return string
176
-	 **/
177
-	public static function fc_hash_html($html) {
178
-		// Initialize some counting
179
-		$count['temp'] = 0; // temp counter
180
-		$count['links'] = 0;
181
-		$count['forms'] = 0;
182
-		$count['inputs'] = 0;
183
-		$count['lists'] = 0;
184
-		$count['textareas'] = 0;
185
-
186
-		// Find and sign all the links
187
-		preg_match_all('%<a .*?href=[\'"]'.preg_quote(self::$cart_url).'(?:\.php)?\?(.+?)[\'"].*?>%i', $html, $querystrings);
188
-		// print_r($querystrings);
189
-		foreach ($querystrings[1] as $querystring) {
190
-			// If it's already signed, skip it.
191
-			if (preg_match('%&(?:amp;)?hash=%i', $querystring)) {
192
-				continue;
193
-			}
194
-			$pattern = '%(href=[\'"])'.preg_quote(self::$cart_url, '%').'(?:\.php)?\?'.preg_quote($querystring, '%').'([\'"])%i';
195
-			$signed = self::fc_hash_querystring($querystring, FALSE);
196
-			$html = preg_replace($pattern, '$1'.$signed.'$2', $html, -1, $count['temp']);
197
-			$count['links'] += $count['temp'];
198
-		}
199
-		unset($querystrings);
200
-
201
-		// Find and sign all form values
202
-		preg_match_all('%<form [^>]*?action=[\'"]'.preg_quote(self::$cart_url).'?[\'"].*?>(.+?)</form>%is', $html, $forms);
203
-		foreach ($forms[1] as $form) {
204
-			$count['forms']++;
205
-			self::$log[] = '<strong>Signing form</strong> with data: '.htmlspecialchars(substr($form, 0, 150)).'...';
206
-
207
-			// Store the original form so we can replace it when we're done
208
-			$form_original = $form;
209
-
210
-			// Check for the "code" input, set the matches in $codes
211
-			if (!preg_match_all('%<[^>]*?name=([\'"])([0-9]{1,3}:)?code\1[^>]*?>%i', $form, $codes, PREG_SET_ORDER)) {
212
-				self::$log[] = '<strong style="color:#600;">No code found</strong> for the above form.';
213
-				continue;
214
-			}
215
-			// For each code found, sign the appropriate inputs
216
-			foreach ($codes as $code) {
217
-				// If the form appears to be hashed already, don't bother
218
-				if (strpos($code[0], '||')) {
219
-					self::$log[] = '<strong>Form appears to be signed already</strong>: '.htmlspecialchars($code[0]);
220
-					continue;
221
-				}
222
-				// Get the code and the prefix
223
-				$prefix = (isset($code[2])) ? $code[2] : '';
224
-				preg_match('%<[^>]*?value=([\'"])(.+?)\1[^>]*?>%i', $code[0], $code);
225
-				$code = trim($code[2]);
226
-				self::$log[] = '<strong>Prefix for '.htmlspecialchars($code).'</strong>: '.htmlspecialchars($prefix);
227
-				if (!$code) { // If the code is empty, skip this form or specific prefixed elements
228
-					continue;
229
-				}
230
-
231
-				// Sign all <input /> elements with matching prefix
232
-				preg_match_all('%<input [^>]*?name=([\'"])'.preg_quote($prefix).'(?![0-9]{1,3})(?:.+?)\1[^>]*>%i', $form, $inputs);
233
-				foreach ($inputs[0] as $input) {
234
-					$count['inputs']++;
235
-					// Test to make sure both name and value attributes are found
236
-					if (preg_match('%name=([\'"])'.preg_quote($prefix).'(?![0-9]{1,3})(.+?)\1%i', $input, $name) > 0) {
237
-						preg_match('%value=([\'"])(.*?)\1%i', $input, $value);
238
-						$value = (count($value) > 0) ? $value : array('', '', '');
239
-						preg_match('%type=([\'"])(.*?)\1%i', $input, $type);
240
-						$type = (count($type) > 0) ? $type : array('', '', '');
241
-						// Skip the cart excludes
242
-						if (in_array($prefix.$name[2], self::$cart_excludes) || in_array(substr($prefix.$name[2], 0, 2), self::$cart_excludes_prefixes)) {
243
-							self::$log[] = '<strong style="color:purple;">Skipping</strong> the reserved parameter or prefix "'.$prefix.$name[2].'" = '.$value[2];
244
-							continue;
245
-						}
246
-						self::$log[] = '<strong>INPUT['.$type[2].']:</strong> Name: <strong>'.$prefix.htmlspecialchars(preg_quote($name[2])).'</strong>';
247
-						self::$log[] = '<strong>Replacement Pattern:</strong> ([\'"])'.$prefix.preg_quote($name[2]).'\1';
248
-						$value[2] = ($value[2] == '') ? '--OPEN--' : $value[2];
249
-						if ($type[2] == 'radio') {
250
-							$input_signed = preg_replace('%([\'"])'.preg_quote($value[2]).'\1%', '${1}'.self::fc_hash_value($code, $name[2], $value[2], 'value', FALSE)."$1", $input);
251
-						} else {
252
-							$input_signed = preg_replace('%([\'"])'.$prefix.preg_quote($name[2]).'\1%', '${1}'.$prefix.self::fc_hash_value($code, $name[2], $value[2], 'name', FALSE)."$1", $input);
253
-						}
254
-						self::$log[] = '<strong>INPUT:</strong> Code: <strong>'.htmlspecialchars($prefix.$code).
255
-						               '</strong> :: Name: <strong>'.htmlspecialchars($prefix.$name[2]).
256
-						               '</strong> :: Value: <strong>'.htmlspecialchars($value[2]).
257
-						               '</strong><br />Initial input: '.htmlspecialchars($input).
258
-						               '<br />Signed: <span style="color:#060;">'.htmlspecialchars($input_signed).'</span>';
259
-						$form = str_replace($input, $input_signed, $form);
260
-					}
261
-				}
262
-				self::$log[] = '<strong>FORM after INPUTS:</strong> <pre>'.htmlspecialchars($form).'</pre>';
263
-
264
-				// Sign all <option /> elements
265
-				preg_match_all('%<select [^>]*name=([\'"])'.preg_quote($prefix).'(?![0-9]{1,3})(.+?)\1[^>]*>(.+?)</select>%is', $form, $lists, PREG_SET_ORDER);
266
-				foreach ($lists as $list) {
267
-					$count['lists']++;
268
-					preg_match_all('%<option [^>]*value=([\'"])(.+?)\1[^>]*>(?:.*?)</option>%i', $list[0], $options, PREG_SET_ORDER);
269
-					self::$log[] = '<strong>Options:</strong> <pre>'.htmlspecialchars(print_r($options, true)).'</pre>';
270
-					unset( $form_part_signed );
271
-					foreach ($options as $option) {
272
-						if( !isset($form_part_signed) ) $form_part_signed = $list[0];
273
-						$option_signed = preg_replace(
274
-							'%'.preg_quote($option[1]).preg_quote($option[2]).preg_quote($option[1]).'%',
275
-							$option[1].self::fc_hash_value($code, $list[2], $option[2], 'value', FALSE).$option[1],
276
-							$option[0]);
277
-						$form_part_signed = str_replace($option[0], $option_signed, $form_part_signed );
278
-						self::$log[] = '<strong>OPTION:</strong> Code: <strong>'.htmlspecialchars($prefix.$code).
279
-						               '</strong> :: Name: <strong>'.htmlspecialchars($prefix.$list[2]).
280
-						               '</strong> :: Value: <strong>'.htmlspecialchars($option[2]).
281
-						               '</strong><br />Initial option: '.htmlspecialchars($option[0]).
282
-						               '<br />Signed: <span style="color:#060;">'.htmlspecialchars($option_signed).'</span>';
283
-					}
284
-					$form = str_replace($list[0], $form_part_signed, $form);
285
-				}
286
-				self::$log[] = '<strong>FORM after OPTIONS:</strong> <pre>'.htmlspecialchars($form).'</pre>';
287
-
288
-				// Sign all <textarea /> elements
289
-				preg_match_all('%<textarea [^>]*name=([\'"])'.preg_quote($prefix).'(?![0-9]{1,3})(.+?)\1[^>]*>(.*?)</textarea>%is', $form, $textareas, PREG_SET_ORDER);
290
-				// echo "\n\nTextareas: ".print_r($textareas, true);
291
-				foreach ($textareas as $textarea) {
292
-					$count['textareas']++;
293
-					// Tackle implied "--OPEN--" first, if textarea is empty
294
-					$textarea[3] = ($textarea[3] == '') ? '--OPEN--' : $textarea[3];
295
-					$textarea_signed = preg_replace('%([\'"])'.preg_quote($prefix.$textarea[2]).'\1%', "$1".self::fc_hash_value($code, $textarea[2], $textarea[3], 'name', FALSE)."$1", $textarea[0]);
296
-					$form = str_replace($textarea[0], $textarea_signed, $form);
297
-					self::$log[] = '<strong>TEXTAREA:</strong> Code: <strong>'.htmlspecialchars($prefix.$code).
298
-					               '</strong> :: Name: <strong>'.htmlspecialchars($prefix.$textarea[2]).
299
-					               '</strong> :: Value: <strong>'.htmlspecialchars($textarea[3]).
300
-					               '</strong><br />Initial textarea: '.htmlspecialchars($textarea[0]).
301
-					               '<br />Signed: <span style="color:#060;">'.htmlspecialchars($textarea_signed).'</span>';
302
-				}
303
-				self::$log[] = '<strong>FORM after TEXTAREAS:</strong> <pre>'.htmlspecialchars($form).'</pre>';
304
-
305
-				// Exclude all <button> elements
306
-				$form = preg_replace('%<button ([^>]*)name=([\'"])(.*?)\1([^>]*>.*?</button>)%i', "<button $1name=$2x:$3$4", $form);
307
-
308
-			}
309
-			// Replace the entire form
310
-			self::$log[] = '<strong>FORM after ALL:</strong> <pre>'.htmlspecialchars($form).'</pre>'.'replacing <pre>'.htmlspecialchars($form_original).'</pre>';
311
-			$html = str_replace($form_original, $form, $html);
312
-			self::$log[] = '<strong>FORM end</strong><hr />';
313
-		}
314
-
315
-		// Return the signed output
316
-		$output = '';
317
-		if (self::$debug) {
318
-			self::$log['Summary'] = $count['links'].' links signed. '.$count['forms'].' forms signed. '.$count['inputs'].' inputs signed. '.$count['lists'].' lists signed. '.$count['textareas'].' textareas signed.';
319
-			$output .= '<h3>FoxyCart HMAC Debugging:</h3><ul>';
320
-			foreach (self::$log as $name => $value) {
321
-				$output .= '<li><strong>'.$name.':</strong> '.$value.'</li>';
322
-			}
323
-			$output .= '</ul><hr />';
324
-		}
325
-		return $output.$html;
326
-	}
17
+    /**
18
+     * API Key (Secret)
19
+     *
20
+     * @var string
21
+     **/
22
+    private static $secret;
23
+
24
+    /**
25
+     * Cart URL
26
+     *
27
+     * @var string
28
+     * Notes: Could be 'https://yourdomain.foxycart.com/cart' or 'https://secure.yourdomain.com/cart'
29
+     **/
30
+    // protected static $cart_url = 'https://yourdomain.foxycart.com/cart';
31
+    protected static $cart_url;
32
+
33
+    public static function setCartURL($storeName = null){
34
+        self::$cart_url = 'https://'.$storeName.'.faxycart.com/cart';
35
+    }
36
+
37
+    public static function setSecret($secret = null){
38
+        self::$secret = $secret;
39
+    }
40
+
41
+    public function __construct(){
42
+        self::setCartURL(FoxyCart::getFoxyCartStoreName());
43
+        self::setSecret(FoxyCart::getStoreKey());
44
+    }
45
+
46
+    public static function getSecret(){
47
+        return FoxyCart::getStoreKey();
48
+    }
49
+
50
+
51
+    /**
52
+     * Cart Excludes
53
+     *
54
+     * Arrays of values and prefixes that should be ignored when signing links and forms.
55
+     * @var array
56
+     */
57
+    protected static $cart_excludes = array(
58
+        // Cart values
59
+        'cart', 'fcsid', 'empty', 'coupon', 'output', 'sub_token', 'redirect', 'callback', '_',
60
+        // Checkout pre-population values
61
+        'customer_email', 'customer_first_name', 'customer_last_name', 'customer_address1', 'customer_address2',
62
+        'customer_city', 'customer_state', 'customer_postal_code', 'customer_country', 'customer_phone', 'customer_company',
63
+        'shipping_first_name', 'shipping_last_name', 'shipping_address1', 'shipping_address2',
64
+        'shipping_city', 'shipping_state', 'shipping_postal_code', 'shipping_country', 'shipping_phone', 'shipping_company',
65
+    );
66
+    protected static $cart_excludes_prefixes = array(
67
+        'h:', 'x:', '__',
68
+    );
69
+
70
+    /**
71
+     * Debugging
72
+     *
73
+     * Set to $debug to TRUE to enable debug logging.
74
+     *
75
+     */
76
+    protected static $debug = FALSE;
77
+    protected static $log = array();
78
+
79
+
80
+    /**
81
+     * "Link Method": Generate HMAC SHA256 for GET Query Strings
82
+     *
83
+     * Notes: Can't parse_str because PHP doesn't support non-alphanumeric characters as array keys.
84
+     * @return string
85
+     **/
86
+    public static function fc_hash_querystring($qs, $output = TRUE) {
87
+        self::$log[] = '<strong>Signing link</strong> with data: '.htmlspecialchars(substr($qs, 0, 150)).'...';
88
+        $fail = self::$cart_url.'?'.$qs;
89
+
90
+        // If the link appears to be hashed already, don't bother
91
+        if (strpos($qs, '||')) {
92
+            self::$log[] = '<strong>Link appears to be signed already</strong>: '.htmlspecialchars($code[0]);
93
+            return $fail;
94
+        }
95
+
96
+        // Stick an ampersand on the beginning of the querystring to make matching the first element a little easier
97
+        $qs = '&'.urldecode($qs);
98
+
99
+        // Get all the prefixes, codes, and name=value pairs
100
+        preg_match_all('%(?P<amp>&(?:amp;)?)(?P<prefix>[a-z0-9]{1,3}:)?(?P<name>[^=]+)=(?P<value>[^&]+)%', $qs, $pairs, PREG_SET_ORDER);
101
+        self::$log[] = 'Found the following pairs to sign:<pre>'.htmlspecialchars(print_r($pairs, true)).'</pre>';
102
+
103
+        // Get all the "code" values, set the matches in $codes
104
+        $codes = array();
105
+        foreach ($pairs as $pair) {
106
+            if ($pair['name'] == 'code') {
107
+                $codes[$pair['prefix']] = $pair['value'];
108
+            }
109
+        }
110
+        if ( ! count($codes)) {
111
+            self::$log[] = '<strong style="color:#600;">No code found</strong> for the above link.';
112
+            return $fail;
113
+        }
114
+        self::$log[] = '<strong style="color:orange;">CODES found:</strong> '.htmlspecialchars(print_r($codes, true));
115
+
116
+        // Sign the name/value pairs
117
+        foreach ($pairs as $pair) {
118
+            // Skip the cart excludes
119
+            if (in_array($pair['name'], self::$cart_excludes) || in_array($pair['prefix'], self::$cart_excludes_prefixes)) {
120
+                self::$log[] = '<strong style="color:purple;">Skipping</strong> the reserved parameter or prefix "'.$pair['prefix'].$pair['name'].'" = '.$pair['value'];
121
+                continue;
122
+            }
123
+
124
+            // Continue to sign the value and replace the name=value in the querystring with name=value||hash
125
+            $value = self::fc_hash_value($codes[$pair['prefix']], $pair['name'], $pair['value'], 'value', FALSE, 'urlencode');
126
+            $replacement = $pair['amp'].$pair['prefix'].urlencode($pair['name']).'='.$value;
127
+            $qs = str_replace($pair[0], $replacement, $qs);
128
+            self::$log[] = 'Signed <strong>'.$pair['name'].'</strong> = <strong>'.$pair['value'].'</strong> with '.$replacement.'.<br />Replacing: '.$pair[0].'<br />With... '.$replacement;
129
+        }
130
+        $qs = ltrim($qs, '&'); // Get rid of that leading ampersand we added earlier
131
+
132
+        if ($output) {
133
+            echo self::$cart_url.'?'.$qs;
134
+        } else {
135
+            return self::$cart_url.'?'.$qs;
136
+        }
137
+    }
138
+
139
+
140
+    /**
141
+     * "Form Method": Generate HMAC SHA256 for form elements or individual <input />s
142
+     *
143
+     * @return string
144
+     **/
145
+    public static function fc_hash_value($product_code, $option_name, $option_value = '', $method = 'name', $output = TRUE, $urlencode = false) {
146
+        if (!$product_code || !$option_name) {
147
+            return FALSE;
148
+        }
149
+        if ($option_value == '--OPEN--') {
150
+            $hash = hash_hmac('sha256', $product_code.$option_name.$option_value, self::getSecret());
151
+            $value = ($urlencode) ? urlencode($option_name).'||'.$hash.'||open' : $option_name.'||'.$hash.'||open';
152
+        } else {
153
+            $hash = hash_hmac('sha256', $product_code.$option_name.$option_value, self::getSecret());
154
+            if ($method == 'name') {
155
+                $value = ($urlencode) ? urlencode($option_name).'||'.$hash : $option_name.'||'.$hash;
156
+            } else {
157
+                $value = ($urlencode) ? urlencode($option_value).'||'.$hash : $option_value.'||'.$hash;
158
+            }
159
+        }
160
+
161
+        if ($output) {
162
+            echo $value;
163
+        } else {
164
+            return $value;
165
+        }
166
+    }
167
+
168
+    /**
169
+     * Raw HTML Signing: Sign all links and form elements in a block of HTML
170
+     *
171
+     * Accepts a string of HTML and signs all links and forms.
172
+     * Requires link 'href' and form 'action' attributes to use 'https' and not 'http'.
173
+     * Requires a 'code' to be set in every form.
174
+     *
175
+     * @return string
176
+     **/
177
+    public static function fc_hash_html($html) {
178
+        // Initialize some counting
179
+        $count['temp'] = 0; // temp counter
180
+        $count['links'] = 0;
181
+        $count['forms'] = 0;
182
+        $count['inputs'] = 0;
183
+        $count['lists'] = 0;
184
+        $count['textareas'] = 0;
185
+
186
+        // Find and sign all the links
187
+        preg_match_all('%<a .*?href=[\'"]'.preg_quote(self::$cart_url).'(?:\.php)?\?(.+?)[\'"].*?>%i', $html, $querystrings);
188
+        // print_r($querystrings);
189
+        foreach ($querystrings[1] as $querystring) {
190
+            // If it's already signed, skip it.
191
+            if (preg_match('%&(?:amp;)?hash=%i', $querystring)) {
192
+                continue;
193
+            }
194
+            $pattern = '%(href=[\'"])'.preg_quote(self::$cart_url, '%').'(?:\.php)?\?'.preg_quote($querystring, '%').'([\'"])%i';
195
+            $signed = self::fc_hash_querystring($querystring, FALSE);
196
+            $html = preg_replace($pattern, '$1'.$signed.'$2', $html, -1, $count['temp']);
197
+            $count['links'] += $count['temp'];
198
+        }
199
+        unset($querystrings);
200
+
201
+        // Find and sign all form values
202
+        preg_match_all('%<form [^>]*?action=[\'"]'.preg_quote(self::$cart_url).'?[\'"].*?>(.+?)</form>%is', $html, $forms);
203
+        foreach ($forms[1] as $form) {
204
+            $count['forms']++;
205
+            self::$log[] = '<strong>Signing form</strong> with data: '.htmlspecialchars(substr($form, 0, 150)).'...';
206
+
207
+            // Store the original form so we can replace it when we're done
208
+            $form_original = $form;
209
+
210
+            // Check for the "code" input, set the matches in $codes
211
+            if (!preg_match_all('%<[^>]*?name=([\'"])([0-9]{1,3}:)?code\1[^>]*?>%i', $form, $codes, PREG_SET_ORDER)) {
212
+                self::$log[] = '<strong style="color:#600;">No code found</strong> for the above form.';
213
+                continue;
214
+            }
215
+            // For each code found, sign the appropriate inputs
216
+            foreach ($codes as $code) {
217
+                // If the form appears to be hashed already, don't bother
218
+                if (strpos($code[0], '||')) {
219
+                    self::$log[] = '<strong>Form appears to be signed already</strong>: '.htmlspecialchars($code[0]);
220
+                    continue;
221
+                }
222
+                // Get the code and the prefix
223
+                $prefix = (isset($code[2])) ? $code[2] : '';
224
+                preg_match('%<[^>]*?value=([\'"])(.+?)\1[^>]*?>%i', $code[0], $code);
225
+                $code = trim($code[2]);
226
+                self::$log[] = '<strong>Prefix for '.htmlspecialchars($code).'</strong>: '.htmlspecialchars($prefix);
227
+                if (!$code) { // If the code is empty, skip this form or specific prefixed elements
228
+                    continue;
229
+                }
230
+
231
+                // Sign all <input /> elements with matching prefix
232
+                preg_match_all('%<input [^>]*?name=([\'"])'.preg_quote($prefix).'(?![0-9]{1,3})(?:.+?)\1[^>]*>%i', $form, $inputs);
233
+                foreach ($inputs[0] as $input) {
234
+                    $count['inputs']++;
235
+                    // Test to make sure both name and value attributes are found
236
+                    if (preg_match('%name=([\'"])'.preg_quote($prefix).'(?![0-9]{1,3})(.+?)\1%i', $input, $name) > 0) {
237
+                        preg_match('%value=([\'"])(.*?)\1%i', $input, $value);
238
+                        $value = (count($value) > 0) ? $value : array('', '', '');
239
+                        preg_match('%type=([\'"])(.*?)\1%i', $input, $type);
240
+                        $type = (count($type) > 0) ? $type : array('', '', '');
241
+                        // Skip the cart excludes
242
+                        if (in_array($prefix.$name[2], self::$cart_excludes) || in_array(substr($prefix.$name[2], 0, 2), self::$cart_excludes_prefixes)) {
243
+                            self::$log[] = '<strong style="color:purple;">Skipping</strong> the reserved parameter or prefix "'.$prefix.$name[2].'" = '.$value[2];
244
+                            continue;
245
+                        }
246
+                        self::$log[] = '<strong>INPUT['.$type[2].']:</strong> Name: <strong>'.$prefix.htmlspecialchars(preg_quote($name[2])).'</strong>';
247
+                        self::$log[] = '<strong>Replacement Pattern:</strong> ([\'"])'.$prefix.preg_quote($name[2]).'\1';
248
+                        $value[2] = ($value[2] == '') ? '--OPEN--' : $value[2];
249
+                        if ($type[2] == 'radio') {
250
+                            $input_signed = preg_replace('%([\'"])'.preg_quote($value[2]).'\1%', '${1}'.self::fc_hash_value($code, $name[2], $value[2], 'value', FALSE)."$1", $input);
251
+                        } else {
252
+                            $input_signed = preg_replace('%([\'"])'.$prefix.preg_quote($name[2]).'\1%', '${1}'.$prefix.self::fc_hash_value($code, $name[2], $value[2], 'name', FALSE)."$1", $input);
253
+                        }
254
+                        self::$log[] = '<strong>INPUT:</strong> Code: <strong>'.htmlspecialchars($prefix.$code).
255
+                                        '</strong> :: Name: <strong>'.htmlspecialchars($prefix.$name[2]).
256
+                                        '</strong> :: Value: <strong>'.htmlspecialchars($value[2]).
257
+                                        '</strong><br />Initial input: '.htmlspecialchars($input).
258
+                                        '<br />Signed: <span style="color:#060;">'.htmlspecialchars($input_signed).'</span>';
259
+                        $form = str_replace($input, $input_signed, $form);
260
+                    }
261
+                }
262
+                self::$log[] = '<strong>FORM after INPUTS:</strong> <pre>'.htmlspecialchars($form).'</pre>';
263
+
264
+                // Sign all <option /> elements
265
+                preg_match_all('%<select [^>]*name=([\'"])'.preg_quote($prefix).'(?![0-9]{1,3})(.+?)\1[^>]*>(.+?)</select>%is', $form, $lists, PREG_SET_ORDER);
266
+                foreach ($lists as $list) {
267
+                    $count['lists']++;
268
+                    preg_match_all('%<option [^>]*value=([\'"])(.+?)\1[^>]*>(?:.*?)</option>%i', $list[0], $options, PREG_SET_ORDER);
269
+                    self::$log[] = '<strong>Options:</strong> <pre>'.htmlspecialchars(print_r($options, true)).'</pre>';
270
+                    unset( $form_part_signed );
271
+                    foreach ($options as $option) {
272
+                        if( !isset($form_part_signed) ) $form_part_signed = $list[0];
273
+                        $option_signed = preg_replace(
274
+                            '%'.preg_quote($option[1]).preg_quote($option[2]).preg_quote($option[1]).'%',
275
+                            $option[1].self::fc_hash_value($code, $list[2], $option[2], 'value', FALSE).$option[1],
276
+                            $option[0]);
277
+                        $form_part_signed = str_replace($option[0], $option_signed, $form_part_signed );
278
+                        self::$log[] = '<strong>OPTION:</strong> Code: <strong>'.htmlspecialchars($prefix.$code).
279
+                                        '</strong> :: Name: <strong>'.htmlspecialchars($prefix.$list[2]).
280
+                                        '</strong> :: Value: <strong>'.htmlspecialchars($option[2]).
281
+                                        '</strong><br />Initial option: '.htmlspecialchars($option[0]).
282
+                                        '<br />Signed: <span style="color:#060;">'.htmlspecialchars($option_signed).'</span>';
283
+                    }
284
+                    $form = str_replace($list[0], $form_part_signed, $form);
285
+                }
286
+                self::$log[] = '<strong>FORM after OPTIONS:</strong> <pre>'.htmlspecialchars($form).'</pre>';
287
+
288
+                // Sign all <textarea /> elements
289
+                preg_match_all('%<textarea [^>]*name=([\'"])'.preg_quote($prefix).'(?![0-9]{1,3})(.+?)\1[^>]*>(.*?)</textarea>%is', $form, $textareas, PREG_SET_ORDER);
290
+                // echo "\n\nTextareas: ".print_r($textareas, true);
291
+                foreach ($textareas as $textarea) {
292
+                    $count['textareas']++;
293
+                    // Tackle implied "--OPEN--" first, if textarea is empty
294
+                    $textarea[3] = ($textarea[3] == '') ? '--OPEN--' : $textarea[3];
295
+                    $textarea_signed = preg_replace('%([\'"])'.preg_quote($prefix.$textarea[2]).'\1%', "$1".self::fc_hash_value($code, $textarea[2], $textarea[3], 'name', FALSE)."$1", $textarea[0]);
296
+                    $form = str_replace($textarea[0], $textarea_signed, $form);
297
+                    self::$log[] = '<strong>TEXTAREA:</strong> Code: <strong>'.htmlspecialchars($prefix.$code).
298
+                                    '</strong> :: Name: <strong>'.htmlspecialchars($prefix.$textarea[2]).
299
+                                    '</strong> :: Value: <strong>'.htmlspecialchars($textarea[3]).
300
+                                    '</strong><br />Initial textarea: '.htmlspecialchars($textarea[0]).
301
+                                    '<br />Signed: <span style="color:#060;">'.htmlspecialchars($textarea_signed).'</span>';
302
+                }
303
+                self::$log[] = '<strong>FORM after TEXTAREAS:</strong> <pre>'.htmlspecialchars($form).'</pre>';
304
+
305
+                // Exclude all <button> elements
306
+                $form = preg_replace('%<button ([^>]*)name=([\'"])(.*?)\1([^>]*>.*?</button>)%i', "<button $1name=$2x:$3$4", $form);
307
+
308
+            }
309
+            // Replace the entire form
310
+            self::$log[] = '<strong>FORM after ALL:</strong> <pre>'.htmlspecialchars($form).'</pre>'.'replacing <pre>'.htmlspecialchars($form_original).'</pre>';
311
+            $html = str_replace($form_original, $form, $html);
312
+            self::$log[] = '<strong>FORM end</strong><hr />';
313
+        }
314
+
315
+        // Return the signed output
316
+        $output = '';
317
+        if (self::$debug) {
318
+            self::$log['Summary'] = $count['links'].' links signed. '.$count['forms'].' forms signed. '.$count['inputs'].' inputs signed. '.$count['lists'].' lists signed. '.$count['textareas'].' textareas signed.';
319
+            $output .= '<h3>FoxyCart HMAC Debugging:</h3><ul>';
320
+            foreach (self::$log as $name => $value) {
321
+                $output .= '<li><strong>'.$name.':</strong> '.$value.'</li>';
322
+            }
323
+            $output .= '</ul><hr />';
324
+        }
325
+        return $output.$html;
326
+    }
327 327
 
328 328
 }
329 329
\ No newline at end of file
Please login to merge, or discard this patch.
code/model/FoxyCart.php 1 patch
Indentation   +43 added lines, -43 removed lines patch added patch discarded remove patch
@@ -7,46 +7,46 @@  discard block
 block discarded – undo
7 7
 
8 8
 class FoxyCart extends Object {
9 9
 
10
-	private static $keyPrefix = 'dYnm1c';
11
-
12
-	public static function setStoreKey($length = 54, $count = 0){
13
-		$charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.strtotime('now');
14
-		$strLength = strlen($charset);
15
-		$str = '';
16
-		while($count < $length){
17
-			$str .= $charset[mt_rand(0, $strLength-1)];
18
-			$count++;
19
-		}
20
-		return self::getKeyPrefix().substr(base64_encode($str),0,$length);
21
-	}
22
-
23
-	public static function getStoreKey(){
24
-		$config = SiteConfig::current_site_config();
25
-		if($config->StoreKey){
26
-			return $config->StoreKey;
27
-		}
28
-		return null;
29
-	}
30
-
31
-	public static function store_name_warning(){
32
-		$warning = null;
33
-		if(self::getFoxyCartStoreName()===null){
34
-			$warning = 'Must define FoxyCart Store Name in your site settings in the cms';
35
-		}
36
-		return $warning;
37
-	}
38
-
39
-	public static function getFoxyCartStoreName(){
40
-		$config = SiteConfig::current_site_config();
41
-		if($config->StoreName){
42
-			return $config->StoreName;
43
-		}
44
-		return null;
45
-	}
46
-
47
-	public static function FormActionURL() {
48
-		return sprintf('https://%s.foxycart.com/cart', self::getFoxyCartStoreName() );
49
-	}
10
+    private static $keyPrefix = 'dYnm1c';
11
+
12
+    public static function setStoreKey($length = 54, $count = 0){
13
+        $charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.strtotime('now');
14
+        $strLength = strlen($charset);
15
+        $str = '';
16
+        while($count < $length){
17
+            $str .= $charset[mt_rand(0, $strLength-1)];
18
+            $count++;
19
+        }
20
+        return self::getKeyPrefix().substr(base64_encode($str),0,$length);
21
+    }
22
+
23
+    public static function getStoreKey(){
24
+        $config = SiteConfig::current_site_config();
25
+        if($config->StoreKey){
26
+            return $config->StoreKey;
27
+        }
28
+        return null;
29
+    }
30
+
31
+    public static function store_name_warning(){
32
+        $warning = null;
33
+        if(self::getFoxyCartStoreName()===null){
34
+            $warning = 'Must define FoxyCart Store Name in your site settings in the cms';
35
+        }
36
+        return $warning;
37
+    }
38
+
39
+    public static function getFoxyCartStoreName(){
40
+        $config = SiteConfig::current_site_config();
41
+        if($config->StoreName){
42
+            return $config->StoreName;
43
+        }
44
+        return null;
45
+    }
46
+
47
+    public static function FormActionURL() {
48
+        return sprintf('https://%s.foxycart.com/cart', self::getFoxyCartStoreName() );
49
+    }
50 50
 
51 51
     /**
52 52
      * FoxyCart API v1.1 functions
@@ -112,8 +112,8 @@  discard block
 block discarded – undo
112 112
         return self::getAPIRequest($foxyData);
113 113
     }
114 114
 
115
-	public static function getKeyPrefix(){
116
-		return self::$keyPrefix;
117
-	}
115
+    public static function getKeyPrefix(){
116
+        return self::$keyPrefix;
117
+    }
118 118
 
119 119
 }
Please login to merge, or discard this patch.
code/objects/ProductImage.php 1 patch
Indentation   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -7,25 +7,25 @@  discard block
 block discarded – undo
7 7
 
8 8
 class ProductImage extends DataObject{
9 9
 
10
-	private static $db = array(
11
-		'Title' => 'Text',
12
-		'SortOrder' => 'Int'
13
-	);
10
+    private static $db = array(
11
+        'Title' => 'Text',
12
+        'SortOrder' => 'Int'
13
+    );
14 14
 
15
-	private static $has_one = array(
16
-		'Image' => 'Image',
17
-		'Parent' => 'SiteTree'
18
-	);
15
+    private static $has_one = array(
16
+        'Image' => 'Image',
17
+        'Parent' => 'SiteTree'
18
+    );
19 19
 
20
-	private static $default_sort = 'SortOrder';
20
+    private static $default_sort = 'SortOrder';
21 21
 
22
-	private static $summary_fields = array(
23
-		'Image.CMSThumbnail' => 'Image',
24
-		'Title' => 'Caption'
25
-	);
22
+    private static $summary_fields = array(
23
+        'Image.CMSThumbnail' => 'Image',
24
+        'Title' => 'Caption'
25
+    );
26 26
 
27
-	public function getCMSFields(){
28
-		$fields = FieldList::create(
27
+    public function getCMSFields(){
28
+        $fields = FieldList::create(
29 29
             TextField::create('Title')
30 30
                 ->setTitle(_t('ProductImage.Title', 'Product Image Title')),
31 31
             UploadField::create('Image')
@@ -34,25 +34,25 @@  discard block
 block discarded – undo
34 34
                 ->setAllowedExtensions(array('jpg', 'jpeg', 'gif', 'png'))
35 35
         );
36 36
 
37
-		$this->extend('updateCMSFields', $fields);
37
+        $this->extend('updateCMSFields', $fields);
38 38
 
39 39
         return $fields;
40
-	}
40
+    }
41 41
 
42
-	public function canView($member = false) {
43
-		return true;
44
-	}
42
+    public function canView($member = false) {
43
+        return true;
44
+    }
45 45
 
46
-	public function canEdit($member = null) {
47
-		return Permission::check('Product_CANCRUD');
48
-	}
46
+    public function canEdit($member = null) {
47
+        return Permission::check('Product_CANCRUD');
48
+    }
49 49
 
50
-	public function canDelete($member = null) {
51
-		return Permission::check('Product_CANCRUD');
52
-	}
50
+    public function canDelete($member = null) {
51
+        return Permission::check('Product_CANCRUD');
52
+    }
53 53
 
54
-	public function canCreate($member = null) {
55
-		return Permission::check('Product_CANCRUD');
56
-	}
54
+    public function canCreate($member = null) {
55
+        return Permission::check('Product_CANCRUD');
56
+    }
57 57
 
58 58
 }
Please login to merge, or discard this patch.
code/objects/ProductCategory.php 1 patch
Indentation   +37 added lines, -37 removed lines patch added patch discarded remove patch
@@ -8,9 +8,9 @@  discard block
 block discarded – undo
8 8
 class ProductCategory extends DataObject {
9 9
 
10 10
     private static $db = array(
11
-		'Title' => 'Varchar(255)',
12
-		'Code' => 'Varchar(50)'
13
-	);
11
+        'Title' => 'Varchar(255)',
12
+        'Code' => 'Varchar(50)'
13
+    );
14 14
 
15 15
     private static $singular_name = 'FoxyCart Category';
16 16
     private static $plural_name = 'FoxyCart Categories';
@@ -21,13 +21,13 @@  discard block
 block discarded – undo
21 21
         'Code' => 'Code'
22 22
     );
23 23
 
24
-	private static $indexes = array(
25
-		'Code' => true
26
-	);
24
+    private static $indexes = array(
25
+        'Code' => true
26
+    );
27 27
 
28 28
     public function getCMSFields() {
29 29
 
30
-		$fields = FieldList::create(
30
+        $fields = FieldList::create(
31 31
             LiteralField::create(
32 32
                 'PCIntro',
33 33
                 _t(
@@ -50,35 +50,35 @@  discard block
 block discarded – undo
50 50
         $this->extend('updateCMSFields', $fields);
51 51
 
52 52
         return $fields;
53
-	}
54
-
55
-	public function requireDefaultRecords() {
56
-		parent::requireDefaultRecords();
57
-		$allCats = DataObject::get('ProductCategory');
58
-		if(!$allCats->count()){
59
-			$cat = new ProductCategory();
60
-			$cat->Title = 'Default';
61
-			$cat->Code = 'DEFAULT';
62
-			$cat->write();
63
-		}
64
-	}
65
-
66
-	public function canView($member = false) {
67
-		return true;
68
-	}
69
-
70
-	public function canEdit($member = null) {
71
-		return Permission::check('Product_CANCRUD');
72
-	}
73
-
74
-	public function canDelete($member = null) {
75
-
76
-		//don't allow deletion of DEFAULT category
77
-		return ($this->Code == 'DEFAULT') ? false : Permission::check('Product_CANCRUD');
78
-	}
79
-
80
-	public function canCreate($member = null) {
81
-		return Permission::check('Product_CANCRUD');
82
-	}
53
+    }
54
+
55
+    public function requireDefaultRecords() {
56
+        parent::requireDefaultRecords();
57
+        $allCats = DataObject::get('ProductCategory');
58
+        if(!$allCats->count()){
59
+            $cat = new ProductCategory();
60
+            $cat->Title = 'Default';
61
+            $cat->Code = 'DEFAULT';
62
+            $cat->write();
63
+        }
64
+    }
65
+
66
+    public function canView($member = false) {
67
+        return true;
68
+    }
69
+
70
+    public function canEdit($member = null) {
71
+        return Permission::check('Product_CANCRUD');
72
+    }
73
+
74
+    public function canDelete($member = null) {
75
+
76
+        //don't allow deletion of DEFAULT category
77
+        return ($this->Code == 'DEFAULT') ? false : Permission::check('Product_CANCRUD');
78
+    }
79
+
80
+    public function canCreate($member = null) {
81
+        return Permission::check('Product_CANCRUD');
82
+    }
83 83
 
84 84
 }
Please login to merge, or discard this patch.
code/form/FoxyStripeDropdownField.php 1 patch
Indentation   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -50,39 +50,39 @@
 block discarded – undo
50 50
  */
51 51
 class FoxyStripeDropdownField extends DropdownField{
52 52
 
53
-	/**
54
-	 * Mark certain elements as disabled,
55
-	 * regardless of the {@link setDisabled()} settings.
56
-	 *
57
-	 * @param array $items Collection of array keys, as defined in the $source array
58
-	 */
59
-	public function setDisabledItems($items){
60
-		$controller = Controller::curr();
61
-		$code = $controller->data()->Code;
62
-		$updated = [];
63
-		if(is_array($items) && !empty($items)){
64
-			foreach($items as $item){
65
-				array_push($updated, ProductPage::getGeneratedValue($code, $this->getName(), $item, 'value'));
66
-			}
67
-		}
68
-		$this->disabledItems = $updated;
69
-		return $this;
70
-	}
53
+    /**
54
+     * Mark certain elements as disabled,
55
+     * regardless of the {@link setDisabled()} settings.
56
+     *
57
+     * @param array $items Collection of array keys, as defined in the $source array
58
+     */
59
+    public function setDisabledItems($items){
60
+        $controller = Controller::curr();
61
+        $code = $controller->data()->Code;
62
+        $updated = [];
63
+        if(is_array($items) && !empty($items)){
64
+            foreach($items as $item){
65
+                array_push($updated, ProductPage::getGeneratedValue($code, $this->getName(), $item, 'value'));
66
+            }
67
+        }
68
+        $this->disabledItems = $updated;
69
+        return $this;
70
+    }
71 71
 
72
-	/**
73
-	 * @param array $source
74
-	 */
75
-	public function setSource($source) {
76
-		$controller = Controller::curr();
77
-		$code = $controller->data()->Code;
78
-		$updated = [];
79
-		if(is_array($source) && !empty($source)){
80
-			foreach($source as $key => $val){
81
-				$updated[ProductPage::getGeneratedValue($code, $this->getName(), $key, 'value')] = $val;
82
-			}
83
-		}
84
-		$this->source = $updated;
85
-		return $this;
86
-	}
72
+    /**
73
+     * @param array $source
74
+     */
75
+    public function setSource($source) {
76
+        $controller = Controller::curr();
77
+        $code = $controller->data()->Code;
78
+        $updated = [];
79
+        if(is_array($source) && !empty($source)){
80
+            foreach($source as $key => $val){
81
+                $updated[ProductPage::getGeneratedValue($code, $this->getName(), $key, 'value')] = $val;
82
+            }
83
+        }
84
+        $this->source = $updated;
85
+        return $this;
86
+    }
87 87
 
88 88
 }
Please login to merge, or discard this patch.
code/controllers/FoxyStripe_Controller.php 1 patch
Indentation   +23 added lines, -23 removed lines patch added patch discarded remove patch
@@ -2,37 +2,37 @@  discard block
 block discarded – undo
2 2
 
3 3
 class FoxyStripe_Controller extends Page_Controller {
4 4
 	
5
-	const URLSegment = 'foxystripe';
5
+    const URLSegment = 'foxystripe';
6 6
 
7
-	public function getURLSegment() {
8
-		return self::URLSegment;
9
-	}
7
+    public function getURLSegment() {
8
+        return self::URLSegment;
9
+    }
10 10
 	
11
-	static $allowed_actions = array(
12
-		'index',
11
+    static $allowed_actions = array(
12
+        'index',
13 13
         'sso'
14
-	);
14
+    );
15 15
 	
16
-	public function index() {
17
-	    // handle POST from FoxyCart API transaction
18
-		if ((isset($_POST["FoxyData"]) OR isset($_POST['FoxySubscriptionData']))) {
19
-			$FoxyData_encrypted = (isset($_POST["FoxyData"])) ?
16
+    public function index() {
17
+        // handle POST from FoxyCart API transaction
18
+        if ((isset($_POST["FoxyData"]) OR isset($_POST['FoxySubscriptionData']))) {
19
+            $FoxyData_encrypted = (isset($_POST["FoxyData"])) ?
20 20
                 urldecode($_POST["FoxyData"]) :
21 21
                 urldecode($_POST["FoxySubscriptionData"]);
22
-			$FoxyData_decrypted = rc4crypt::decrypt(FoxyCart::getStoreKey(),$FoxyData_encrypted);
23
-			self::handleDataFeed($FoxyData_encrypted, $FoxyData_decrypted);
22
+            $FoxyData_decrypted = rc4crypt::decrypt(FoxyCart::getStoreKey(),$FoxyData_encrypted);
23
+            self::handleDataFeed($FoxyData_encrypted, $FoxyData_decrypted);
24 24
 			
25
-			// extend to allow for additional integrations with Datafeed
26
-			$this->extend('addIntegrations', $FoxyData_encrypted);
25
+            // extend to allow for additional integrations with Datafeed
26
+            $this->extend('addIntegrations', $FoxyData_encrypted);
27 27
 			
28
-			return 'foxy';
28
+            return 'foxy';
29 29
 			
30
-		} else {
30
+        } else {
31 31
 			
32
-			return "No FoxyData or FoxySubscriptionData received.";
32
+            return "No FoxyData or FoxySubscriptionData received.";
33 33
 			
34
-		}
35
-	}
34
+        }
35
+    }
36 36
 
37 37
     public function handleDataFeed($encrypted, $decrypted){
38 38
         //handle encrypted & decrypted data
@@ -203,10 +203,10 @@  discard block
 block discarded – undo
203 203
 
204 204
 
205 205
 
206
-	// Single Sign on integration with FoxyCart
206
+    // Single Sign on integration with FoxyCart
207 207
     public function sso() {
208 208
 
209
-	    // GET variables from FoxyCart Request
209
+        // GET variables from FoxyCart Request
210 210
         $fcsid = $this->request->getVar('fcsid');
211 211
         $timestampNew = strtotime('+30 days');
212 212
 
@@ -225,7 +225,7 @@  discard block
 block discarded – undo
225 225
         $redirect_complete = 'https://' . FoxyCart::getFoxyCartStoreName() . '.foxycart.com/checkout?fc_auth_token=' . $auth_token .
226 226
             '&fcsid=' . $fcsid . '&fc_customer_id=' . $Member->Customer_ID . '&timestamp=' . $timestampNew;
227 227
 	
228
-	    $this->redirect($redirect_complete);
228
+        $this->redirect($redirect_complete);
229 229
 
230 230
     }
231 231
 	
Please login to merge, or discard this patch.
code/pages/OrderHistoryPage.php 1 patch
Indentation   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -11,14 +11,14 @@  discard block
 block discarded – undo
11 11
     private static $plural_name = 'Order History Pages';
12 12
     private static $description = 'Show a customers past orders. Requires authentication';
13 13
 
14
-	public function getCMSFields(){
15
-		$fields = parent::getCMSFields();
14
+    public function getCMSFields(){
15
+        $fields = parent::getCMSFields();
16 16
 
17 17
 
18 18
 
19
-		$this->extend('updateCMSFields', $fields);
20
-		return $fields;
21
-	}
19
+        $this->extend('updateCMSFields', $fields);
20
+        return $fields;
21
+    }
22 22
 
23 23
     // return all current Member's Orders
24 24
     public function getOrders($limit = 10) {
@@ -36,7 +36,7 @@  discard block
 block discarded – undo
36 36
 
37 37
 class OrderHistoryPage_Controller extends Page_Controller {
38 38
 	
39
-	private static $allowed_actions = array(
39
+    private static $allowed_actions = array(
40 40
         'index'
41 41
     );
42 42
 
Please login to merge, or discard this patch.
code/extensions/FoxyStripeSiteConfig.php 1 patch
Indentation   +58 added lines, -58 removed lines patch added patch discarded remove patch
@@ -2,21 +2,21 @@  discard block
 block discarded – undo
2 2
 
3 3
 class FoxyStripeSiteConfig extends DataExtension{
4 4
 
5
-	private static $db = array(
6
-		'StoreName' => 'Varchar(255)',
7
-		'StoreKey' => 'Varchar(60)',
8
-		'MultiGroup' => 'Boolean',
9
-		'ProductLimit' => 'Int',
10
-		'CartValidation' => 'Boolean',
11
-		'MaxQuantity' => 'Int'
12
-	);
5
+    private static $db = array(
6
+        'StoreName' => 'Varchar(255)',
7
+        'StoreKey' => 'Varchar(60)',
8
+        'MultiGroup' => 'Boolean',
9
+        'ProductLimit' => 'Int',
10
+        'CartValidation' => 'Boolean',
11
+        'MaxQuantity' => 'Int'
12
+    );
13 13
 
14 14
     // Set Default values
15 15
     private static $defaults = array(
16 16
         'ProductLimit' => 10
17 17
     );
18 18
 
19
-	public function updateCMSFields(FieldList $fields){
19
+    public function updateCMSFields(FieldList $fields){
20 20
 
21 21
         // set TabSet names to avoid spaces from camel case
22 22
         $fields->addFieldToTab('Root', new TabSet('FoxyStripe', 'FoxyStripe'));
@@ -24,103 +24,103 @@  discard block
 block discarded – undo
24 24
         // settings tab
25 25
         $fields->addFieldsToTab('Root.FoxyStripe.Settings', array(
26 26
             // Store Details
27
-			HeaderField::create('StoreDetails', _t('FoxyStripeSiteConfig.StoreDetails', 'Store Settings'), 3),
28
-			LiteralField::create('DetailsIntro', _t(
29
-				'FoxyStripeSiteConfig.DetailsIntro',
27
+            HeaderField::create('StoreDetails', _t('FoxyStripeSiteConfig.StoreDetails', 'Store Settings'), 3),
28
+            LiteralField::create('DetailsIntro', _t(
29
+                'FoxyStripeSiteConfig.DetailsIntro',
30 30
                 '<p>Maps to data in your <a href="https://admin.foxycart.com/admin.php?ThisAction=EditStore" target="_blank">FoxyCart store settings</a>.'
31 31
             )),
32
-			TextField::create('StoreName')
33
-				->setTitle(_t('FoxyStripeSiteConfig.StoreName', 'Store Sub Domain'))
34
-				->setDescription(_t('FoxyStripeSiteConfig.StoreNameDescription', 'the sub domain for your FoxyCart store')),
32
+            TextField::create('StoreName')
33
+                ->setTitle(_t('FoxyStripeSiteConfig.StoreName', 'Store Sub Domain'))
34
+                ->setDescription(_t('FoxyStripeSiteConfig.StoreNameDescription', 'the sub domain for your FoxyCart store')),
35 35
 
36
-			// Advanced Settings
37
-			HeaderField::create('AdvanceHeader', _t('FoxyStripeSiteConfig.AdvancedHeader', 'Advanced Settings'), 3),
38
-			LiteralField::create('AdvancedIntro', _t(
36
+            // Advanced Settings
37
+            HeaderField::create('AdvanceHeader', _t('FoxyStripeSiteConfig.AdvancedHeader', 'Advanced Settings'), 3),
38
+            LiteralField::create('AdvancedIntro', _t(
39 39
                 'FoxyStripeSiteConfig.AdvancedIntro',
40
-				'<p>Maps to data in your <a href="https://admin.foxycart.com/admin.php?ThisAction=EditAdvancedFeatures" target="_blank">FoxyCart advanced store settings</a>.</p>'
41
-			)),
42
-			ReadonlyField::create('DataFeedLink', _t('FoxyStripeSiteConfig.DataFeedLink', 'FoxyCart DataFeed URL'), self::getDataFeedLink())
43
-				->setDescription(_t('FoxyStripeSiteConfig.DataFeedLinkDescription', 'copy/paste to FoxyCart')),
44
-			CheckboxField::create('CartValidation')
45
-				->setTitle(_t('FoxyStripeSiteConfig.CartValidation', 'Enable Cart Validation'))
46
-				->setDescription(_t(
40
+                '<p>Maps to data in your <a href="https://admin.foxycart.com/admin.php?ThisAction=EditAdvancedFeatures" target="_blank">FoxyCart advanced store settings</a>.</p>'
41
+            )),
42
+            ReadonlyField::create('DataFeedLink', _t('FoxyStripeSiteConfig.DataFeedLink', 'FoxyCart DataFeed URL'), self::getDataFeedLink())
43
+                ->setDescription(_t('FoxyStripeSiteConfig.DataFeedLinkDescription', 'copy/paste to FoxyCart')),
44
+            CheckboxField::create('CartValidation')
45
+                ->setTitle(_t('FoxyStripeSiteConfig.CartValidation', 'Enable Cart Validation'))
46
+                ->setDescription(_t(
47 47
                     'FoxyStripeSiteConfig.CartValidationDescription',
48 48
                     '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.'
49 49
             )),
50
-			ReadonlyField::create('StoreKey')
51
-				->setTitle(_t('FoxyStripeSiteConfig.StoreKey', 'FoxyCart API Key'))
52
-				->setDescription(_t('FoxyStripeSiteConfig.StoreKeyDescription', 'copy/paste to FoxyCart')),
53
-			ReadonlyField::create('SSOLink', _t('FoxyStripeSiteConfig.SSOLink', 'Single Sign On URL'), self::getSSOLink())
54
-				->setDescription(_t('FoxyStripeSiteConfig.SSOLinkDescription', 'copy/paste to FoxyCart'))
50
+            ReadonlyField::create('StoreKey')
51
+                ->setTitle(_t('FoxyStripeSiteConfig.StoreKey', 'FoxyCart API Key'))
52
+                ->setDescription(_t('FoxyStripeSiteConfig.StoreKeyDescription', 'copy/paste to FoxyCart')),
53
+            ReadonlyField::create('SSOLink', _t('FoxyStripeSiteConfig.SSOLink', 'Single Sign On URL'), self::getSSOLink())
54
+                ->setDescription(_t('FoxyStripeSiteConfig.SSOLinkDescription', 'copy/paste to FoxyCart'))
55 55
         ));
56 56
 
57 57
         // configuration warning
58
-		if(FoxyCart::store_name_warning()!==null){
59
-			$fields->insertBefore(LiteralField::create(
58
+        if(FoxyCart::store_name_warning()!==null){
59
+            $fields->insertBefore(LiteralField::create(
60 60
                 "StoreSubDomainHeaderWarning",
61 61
                 _t(
62 62
                     'FoxyStripeSiteConfig.StoreSubDomainHeadingWarning',
63 63
                     "<p class=\"message error\">Store sub-domain must be entered in the <a href=\"/admin/settings/\">site settings</a></p>"
64 64
                 )
65 65
             ), 'StoreDetails');
66
-		}
66
+        }
67 67
 
68 68
         // products tab
69
-		$fields->addFieldsToTab('Root.FoxyStripe.Products', array(
70
-			HeaderField::create('ProductHeader', _t('FoxyStripeSiteConfig.ProductHeader', 'Products'), 3),
71
-			CheckboxField::create('MultiGroup')
72
-				->setTitle(_t('FoxyStripeSiteConfig.MultiGroup', 'Multiple Groups'))
73
-				->setDescription(_t(
69
+        $fields->addFieldsToTab('Root.FoxyStripe.Products', array(
70
+            HeaderField::create('ProductHeader', _t('FoxyStripeSiteConfig.ProductHeader', 'Products'), 3),
71
+            CheckboxField::create('MultiGroup')
72
+                ->setTitle(_t('FoxyStripeSiteConfig.MultiGroup', 'Multiple Groups'))
73
+                ->setDescription(_t(
74 74
                     'FoxyStripeSiteConfig.MultiGroupDescription',
75 75
                     'Allows products to be shown in multiple Product Groups'
76 76
                 )),
77
-			HeaderField::create('ProductGroupHD', _t('FoxyStripeSiteConfig.ProductGroupHD', 'Product Groups'), 3),
78
-			NumericField::create('ProductLimit')
79
-				->setTitle(_t('FoxyStripeSiteConfig.ProductLimit', 'Products per Page'))
80
-				->setDescription(_t(
77
+            HeaderField::create('ProductGroupHD', _t('FoxyStripeSiteConfig.ProductGroupHD', 'Product Groups'), 3),
78
+            NumericField::create('ProductLimit')
79
+                ->setTitle(_t('FoxyStripeSiteConfig.ProductLimit', 'Products per Page'))
80
+                ->setDescription(_t(
81 81
                     'FoxyStripeSiteConfig.ProductLimitDescription',
82 82
                     'Number of Products to show per page on a Product Group'
83 83
                 )),
84
-			HeaderField::create('ProductQuantityHD', _t('FoxyStripeSiteConfig.ProductQuantityHD', 'Product Form Max Quantity'), 3),
85
-			NumericField::create('MaxQuantity')
86
-				->setTitle(_t('FoxyStripeSiteConfig.MaxQuantity', 'Max Quantity'))
87
-				->setDescription(_t(
84
+            HeaderField::create('ProductQuantityHD', _t('FoxyStripeSiteConfig.ProductQuantityHD', 'Product Form Max Quantity'), 3),
85
+            NumericField::create('MaxQuantity')
86
+                ->setTitle(_t('FoxyStripeSiteConfig.MaxQuantity', 'Max Quantity'))
87
+                ->setDescription(_t(
88 88
                     'FoxyStripeSiteConfig.MaxQuantityDescription',
89 89
                     'Sets max quantity for product form dropdown (add to cart form - default 10)'
90 90
                 ))
91
-		));
91
+        ));
92 92
 
93 93
         // categories tab
94
-		$fields->addFieldsToTab('Root.FoxyStripe.Categories', array(
95
-			HeaderField::create('CategoryHD', _t('FoxyStripeSiteConfig.CategoryHD', 'FoxyStripe Categories'), 3),
96
-			LiteralField::create('CategoryDescrip', _t(
94
+        $fields->addFieldsToTab('Root.FoxyStripe.Categories', array(
95
+            HeaderField::create('CategoryHD', _t('FoxyStripeSiteConfig.CategoryHD', 'FoxyStripe Categories'), 3),
96
+            LiteralField::create('CategoryDescrip', _t(
97 97
                 'FoxyStripeSiteConfig.CategoryDescrip',
98 98
                 '<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>'
99 99
             )),
100
-			GridField::create(
100
+            GridField::create(
101 101
                 'ProductCategory',
102 102
                 _t('FoxyStripeSiteConfig.ProductCategory', 'FoxyCart Categories'),
103 103
                 ProductCategory::get(),
104 104
                 GridFieldConfig_RecordEditor::create()
105 105
             )
106
-		));
106
+        ));
107 107
 
108 108
         // option groups tab
109
-		$fields->addFieldsToTab('Root.FoxyStripe.Groups', array(
110
-			HeaderField::create('OptionGroupsHead', _t('FoxyStripeSiteConfig', 'Product Option Groups'), 3),
111
-			LiteralField::create('OptionGroupsDescrip', _t(
109
+        $fields->addFieldsToTab('Root.FoxyStripe.Groups', array(
110
+            HeaderField::create('OptionGroupsHead', _t('FoxyStripeSiteConfig', 'Product Option Groups'), 3),
111
+            LiteralField::create('OptionGroupsDescrip', _t(
112 112
                 'FoxyStripeSiteConfig.OptionGroupsDescrip',
113 113
                 '<p>Product Option Groups allow you to name a set of product options.</p>'
114 114
             )),
115
-			GridField::create(
115
+            GridField::create(
116 116
                 'OptionGroup',
117 117
                 _t('FoxyStripeSiteConfig.OptionGroup', 'Product Option Groups'),
118 118
                 OptionGroup::get(),
119 119
                 GridFieldConfig_RecordEditor::create()
120 120
             )
121
-		));
121
+        ));
122 122
 
123
-	}
123
+    }
124 124
 
125 125
     private static function getSSOLink() {
126 126
         return Director::absoluteBaseURL()."foxystripe/sso/";
Please login to merge, or discard this patch.