| @@ -43,6 +43,9 @@ | ||
| 43 | 43 | self::setSecret(FoxyCart::getStoreKey()); | 
| 44 | 44 | } | 
| 45 | 45 | |
| 46 | + /** | |
| 47 | + * @return string | |
| 48 | + */ | |
| 46 | 49 |  	public static function getSecret(){ | 
| 47 | 50 | return FoxyCart::getStoreKey(); | 
| 48 | 51 | } | 
| @@ -30,20 +30,20 @@ discard block | ||
| 30 | 30 | // protected static $cart_url = 'https://yourdomain.foxycart.com/cart'; | 
| 31 | 31 | protected static $cart_url; | 
| 32 | 32 | |
| 33 | -	public static function setCartURL($storeName = null){ | |
| 33 | +	public static function setCartURL($storeName = null) { | |
| 34 | 34 | self::$cart_url = 'https://'.$storeName.'.faxycart.com/cart'; | 
| 35 | 35 | } | 
| 36 | 36 | |
| 37 | -	public static function setSecret($secret = null){ | |
| 37 | +	public static function setSecret($secret = null) { | |
| 38 | 38 | self::$secret = $secret; | 
| 39 | 39 | } | 
| 40 | 40 | |
| 41 | -	public function __construct(){ | |
| 41 | +	public function __construct() { | |
| 42 | 42 | self::setCartURL(FoxyCart::getFoxyCartStoreName()); | 
| 43 | 43 | self::setSecret(FoxyCart::getStoreKey()); | 
| 44 | 44 | } | 
| 45 | 45 | |
| 46 | -	public static function getSecret(){ | |
| 46 | +	public static function getSecret() { | |
| 47 | 47 | return FoxyCart::getStoreKey(); | 
| 48 | 48 | } | 
| 49 | 49 | |
| @@ -107,7 +107,7 @@ discard block | ||
| 107 | 107 | $codes[$pair['prefix']] = $pair['value']; | 
| 108 | 108 | } | 
| 109 | 109 | } | 
| 110 | -		if ( ! count($codes)) { | |
| 110 | +		if (!count($codes)) { | |
| 111 | 111 | self::$log[] = '<strong style="color:#600;">No code found</strong> for the above link.'; | 
| 112 | 112 | return $fail; | 
| 113 | 113 | } | 
| @@ -131,7 +131,7 @@ discard block | ||
| 131 | 131 | |
| 132 | 132 |  		if ($output) { | 
| 133 | 133 | echo self::$cart_url.'?'.$qs; | 
| 134 | -		} else { | |
| 134 | +		}else { | |
| 135 | 135 | return self::$cart_url.'?'.$qs; | 
| 136 | 136 | } | 
| 137 | 137 | } | 
| @@ -149,18 +149,18 @@ discard block | ||
| 149 | 149 |  		if ($option_value == '--OPEN--') { | 
| 150 | 150 |  			$hash = hash_hmac('sha256', $product_code.$option_name.$option_value, self::getSecret()); | 
| 151 | 151 | $value = ($urlencode) ? urlencode($option_name).'||'.$hash.'||open' : $option_name.'||'.$hash.'||open'; | 
| 152 | -		} else { | |
| 152 | +		}else { | |
| 153 | 153 |  			$hash = hash_hmac('sha256', $product_code.$option_name.$option_value, self::getSecret()); | 
| 154 | 154 |  			if ($method == 'name') { | 
| 155 | 155 | $value = ($urlencode) ? urlencode($option_name).'||'.$hash : $option_name.'||'.$hash; | 
| 156 | -			} else { | |
| 156 | +			}else { | |
| 157 | 157 | $value = ($urlencode) ? urlencode($option_value).'||'.$hash : $option_value.'||'.$hash; | 
| 158 | 158 | } | 
| 159 | 159 | } | 
| 160 | 160 | |
| 161 | 161 |  		if ($output) { | 
| 162 | 162 | echo $value; | 
| 163 | -		} else { | |
| 163 | +		}else { | |
| 164 | 164 | return $value; | 
| 165 | 165 | } | 
| 166 | 166 | } | 
| @@ -248,7 +248,7 @@ discard block | ||
| 248 | 248 | $value[2] = ($value[2] == '') ? '--OPEN--' : $value[2]; | 
| 249 | 249 |  						if ($type[2] == 'radio') { | 
| 250 | 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 { | |
| 251 | +						}else { | |
| 252 | 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 | 253 | } | 
| 254 | 254 | self::$log[] = '<strong>INPUT:</strong> Code: <strong>'.htmlspecialchars($prefix.$code). | 
| @@ -267,14 +267,14 @@ discard block | ||
| 267 | 267 | $count['lists']++; | 
| 268 | 268 |  					preg_match_all('%<option [^>]*value=([\'"])(.+?)\1[^>]*>(?:.*?)</option>%i', $list[0], $options, PREG_SET_ORDER); | 
| 269 | 269 | self::$log[] = '<strong>Options:</strong> <pre>'.htmlspecialchars(print_r($options, true)).'</pre>'; | 
| 270 | - unset( $form_part_signed ); | |
| 270 | + unset($form_part_signed); | |
| 271 | 271 |  					foreach ($options as $option) { | 
| 272 | - if( !isset($form_part_signed) ) $form_part_signed = $list[0]; | |
| 272 | + if (!isset($form_part_signed)) $form_part_signed = $list[0]; | |
| 273 | 273 | $option_signed = preg_replace( | 
| 274 | 274 | '%'.preg_quote($option[1]).preg_quote($option[2]).preg_quote($option[1]).'%', | 
| 275 | 275 | $option[1].self::fc_hash_value($code, $list[2], $option[2], 'value', FALSE).$option[1], | 
| 276 | 276 | $option[0]); | 
| 277 | - $form_part_signed = str_replace($option[0], $option_signed, $form_part_signed ); | |
| 277 | + $form_part_signed = str_replace($option[0], $option_signed, $form_part_signed); | |
| 278 | 278 | self::$log[] = '<strong>OPTION:</strong> Code: <strong>'.htmlspecialchars($prefix.$code). | 
| 279 | 279 | '</strong> :: Name: <strong>'.htmlspecialchars($prefix.$list[2]). | 
| 280 | 280 | '</strong> :: Value: <strong>'.htmlspecialchars($option[2]). | 
| @@ -14,315 +14,315 @@ | ||
| 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 | 
| @@ -269,7 +269,9 @@ | ||
| 269 | 269 | self::$log[] = '<strong>Options:</strong> <pre>'.htmlspecialchars(print_r($options, true)).'</pre>'; | 
| 270 | 270 | unset( $form_part_signed ); | 
| 271 | 271 |  					foreach ($options as $option) { | 
| 272 | - if( !isset($form_part_signed) ) $form_part_signed = $list[0]; | |
| 272 | +						if( !isset($form_part_signed) ) { | |
| 273 | + $form_part_signed = $list[0]; | |
| 274 | + } | |
| 273 | 275 | $option_signed = preg_replace( | 
| 274 | 276 | '%'.preg_quote($option[1]).preg_quote($option[2]).preg_quote($option[1]).'%', | 
| 275 | 277 | $option[1].self::fc_hash_value($code, $list[2], $option[2], 'value', FALSE).$option[1], | 
| @@ -9,43 +9,43 @@ discard block | ||
| 9 | 9 | |
| 10 | 10 | private static $keyPrefix = 'dYnm1c'; | 
| 11 | 11 | |
| 12 | -	public static function setStoreKey($length = 54, $count = 0){ | |
| 12 | +	public static function setStoreKey($length = 54, $count = 0) { | |
| 13 | 13 |  		$charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.strtotime('now'); | 
| 14 | 14 | $strLength = strlen($charset); | 
| 15 | 15 | $str = ''; | 
| 16 | -		while($count < $length){ | |
| 17 | - $str .= $charset[mt_rand(0, $strLength-1)]; | |
| 16 | +		while ($count < $length) { | |
| 17 | + $str .= $charset[mt_rand(0, $strLength - 1)]; | |
| 18 | 18 | $count++; | 
| 19 | 19 | } | 
| 20 | - return self::getKeyPrefix().substr(base64_encode($str),0,$length); | |
| 20 | + return self::getKeyPrefix().substr(base64_encode($str), 0, $length); | |
| 21 | 21 | } | 
| 22 | 22 | |
| 23 | -	public static function getStoreKey(){ | |
| 23 | +	public static function getStoreKey() { | |
| 24 | 24 | $config = SiteConfig::current_site_config(); | 
| 25 | -		if($config->StoreKey){ | |
| 25 | +		if ($config->StoreKey) { | |
| 26 | 26 | return $config->StoreKey; | 
| 27 | 27 | } | 
| 28 | 28 | return null; | 
| 29 | 29 | } | 
| 30 | 30 | |
| 31 | -	public static function store_name_warning(){ | |
| 31 | +	public static function store_name_warning() { | |
| 32 | 32 | $warning = null; | 
| 33 | -		if(self::getFoxyCartStoreName()===null){ | |
| 33 | +		if (self::getFoxyCartStoreName() === null) { | |
| 34 | 34 | $warning = 'Must define FoxyCart Store Name in your site settings in the cms'; | 
| 35 | 35 | } | 
| 36 | 36 | return $warning; | 
| 37 | 37 | } | 
| 38 | 38 | |
| 39 | -	public static function getFoxyCartStoreName(){ | |
| 39 | +	public static function getFoxyCartStoreName() { | |
| 40 | 40 | $config = SiteConfig::current_site_config(); | 
| 41 | -		if($config->StoreName){ | |
| 41 | +		if ($config->StoreName) { | |
| 42 | 42 | return $config->StoreName; | 
| 43 | 43 | } | 
| 44 | 44 | return null; | 
| 45 | 45 | } | 
| 46 | 46 | |
| 47 | 47 |  	public static function FormActionURL() { | 
| 48 | -		return sprintf('https://%s.foxycart.com/cart', self::getFoxyCartStoreName() ); | |
| 48 | +		return sprintf('https://%s.foxycart.com/cart', self::getFoxyCartStoreName()); | |
| 49 | 49 | } | 
| 50 | 50 | |
| 51 | 51 | /** | 
| @@ -59,7 +59,7 @@ discard block | ||
| 59 | 59 | $foxyData["api_token"] = FoxyCart::getStoreKey(); | 
| 60 | 60 | |
| 61 | 61 | $ch = curl_init(); | 
| 62 | - curl_setopt($ch, CURLOPT_URL, "https://" . $foxy_domain . "/api"); | |
| 62 | + curl_setopt($ch, CURLOPT_URL, "https://".$foxy_domain."/api"); | |
| 63 | 63 | curl_setopt($ch, CURLOPT_POSTFIELDS, $foxyData); | 
| 64 | 64 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | 
| 65 | 65 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); | 
| @@ -71,7 +71,7 @@ discard block | ||
| 71 | 71 | // The following if block will print any CURL errors you might have | 
| 72 | 72 |          if ($response == false) { | 
| 73 | 73 |              //trigger_error("Could not connect to FoxyCart API", E_USER_ERROR); | 
| 74 | -            SS_Log::log("Could not connect to FoxyCart API: " . $response, SS_Log::ERR); | |
| 74 | +            SS_Log::log("Could not connect to FoxyCart API: ".$response, SS_Log::ERR); | |
| 75 | 75 | } | 
| 76 | 76 | curl_close($ch); | 
| 77 | 77 | |
| @@ -96,7 +96,7 @@ discard block | ||
| 96 | 96 | |
| 97 | 97 |      public static function putCustomer($Member = null) { | 
| 98 | 98 | // throw error if no $Member Object | 
| 99 | -        if (!isset($Member)) ;//trigger_error('No Member set', E_USER_ERROR); | |
| 99 | +        if (!isset($Member)); //trigger_error('No Member set', E_USER_ERROR); | |
| 100 | 100 | |
| 101 | 101 | // send updated customer record from API | 
| 102 | 102 | $foxyData = array(); | 
| @@ -112,7 +112,7 @@ discard block | ||
| 112 | 112 | return self::getAPIRequest($foxyData); | 
| 113 | 113 | } | 
| 114 | 114 | |
| 115 | -	public static function getKeyPrefix(){ | |
| 115 | +	public static function getKeyPrefix() { | |
| 116 | 116 | return self::$keyPrefix; | 
| 117 | 117 | } | 
| 118 | 118 | |
| @@ -7,46 +7,46 @@ discard block | ||
| 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 | ||
| 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 | } | 
| @@ -81,13 +81,17 @@ discard block | ||
| 81 | 81 |      public static function getCustomer($Member = null) { | 
| 82 | 82 | |
| 83 | 83 | // throw error if no $Member Object | 
| 84 | -        if (!isset($Member)) trigger_error('No Member set', E_USER_ERROR); | |
| 84 | +        if (!isset($Member)) { | |
| 85 | +            trigger_error('No Member set', E_USER_ERROR); | |
| 86 | + } | |
| 85 | 87 | |
| 86 | 88 | // grab customer record from API | 
| 87 | 89 | |
| 88 | 90 | $foxyData = array(); | 
| 89 | 91 | $foxyData["api_action"] = "customer_get"; | 
| 90 | - if ($Member->Customer_ID) $foxyData["customer_id"] = $Member->Customer_ID; | |
| 92 | +        if ($Member->Customer_ID) { | |
| 93 | + $foxyData["customer_id"] = $Member->Customer_ID; | |
| 94 | + } | |
| 91 | 95 | $foxyData["customer_email"] = $Member->Email; | 
| 92 | 96 | |
| 93 | 97 | return self::getAPIRequest($foxyData); | 
| @@ -102,7 +106,9 @@ discard block | ||
| 102 | 106 | $foxyData = array(); | 
| 103 | 107 | $foxyData["api_action"] = "customer_save"; | 
| 104 | 108 | // customer_id will be 0 if created in SilverStripe. | 
| 105 | - if ($Member->Customer_ID) $foxyData["customer_id"] = $Member->Customer_ID; | |
| 109 | +        if ($Member->Customer_ID) { | |
| 110 | + $foxyData["customer_id"] = $Member->Customer_ID; | |
| 111 | + } | |
| 106 | 112 | $foxyData["customer_email"] = $Member->Email; | 
| 107 | 113 | $foxyData["customer_password_hash"] = $Member->Password; | 
| 108 | 114 | $foxyData["customer_password_salt"] = $Member->Salt; | 
| @@ -5,7 +5,7 @@ discard block | ||
| 5 | 5 | * | 
| 6 | 6 | */ | 
| 7 | 7 | |
| 8 | -class ProductImage extends DataObject{ | |
| 8 | +class ProductImage extends DataObject { | |
| 9 | 9 | |
| 10 | 10 | private static $db = array( | 
| 11 | 11 | 'Title' => 'Text', | 
| @@ -24,7 +24,7 @@ discard block | ||
| 24 | 24 | 'Title' => 'Caption' | 
| 25 | 25 | ); | 
| 26 | 26 | |
| 27 | -	public function getCMSFields(){ | |
| 27 | +	public function getCMSFields() { | |
| 28 | 28 | $fields = FieldList::create( | 
| 29 | 29 |              TextField::create('Title') | 
| 30 | 30 |                  ->setTitle(_t('ProductImage.Title', 'Product Image Title')), | 
| @@ -7,25 +7,25 @@ discard block | ||
| 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 | ||
| 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 | } | 
| @@ -5,7 +5,7 @@ discard block | ||
| 5 | 5 | * | 
| 6 | 6 | */ | 
| 7 | 7 | |
| 8 | -class OptionGroup extends DataObject{ | |
| 8 | +class OptionGroup extends DataObject { | |
| 9 | 9 | |
| 10 | 10 | private static $db = array( | 
| 11 | 11 | 'Title' => 'Varchar(100)' | 
| @@ -15,7 +15,7 @@ discard block | ||
| 15 | 15 | private static $plural_name = 'Product Option Groups'; | 
| 16 | 16 | private static $description = 'Groups of product options, e.g. size, color, etc'; | 
| 17 | 17 | |
| 18 | -	function getCMSFields(){ | |
| 18 | +	function getCMSFields() { | |
| 19 | 19 | |
| 20 | 20 | $fields = parent::getCMSFields(); | 
| 21 | 21 | |
| @@ -27,22 +27,22 @@ discard block | ||
| 27 | 27 |  	public function requireDefaultRecords() { | 
| 28 | 28 | parent::requireDefaultRecords(); | 
| 29 | 29 | // create a catch-all group | 
| 30 | -		if(!OptionGroup::get()->filter(array('Title' => 'Options'))->first()) { | |
| 30 | +		if (!OptionGroup::get()->filter(array('Title' => 'Options'))->first()) { | |
| 31 | 31 | $do = new OptionGroup(); | 
| 32 | 32 | $do->Title = "Options"; | 
| 33 | 33 | $do->write(); | 
| 34 | 34 | } | 
| 35 | -		if(!OptionGroup::get()->filter(array('Title' => 'Size'))->first()) { | |
| 35 | +		if (!OptionGroup::get()->filter(array('Title' => 'Size'))->first()) { | |
| 36 | 36 | $do = new OptionGroup(); | 
| 37 | 37 | $do->Title = "Size"; | 
| 38 | 38 | $do->write(); | 
| 39 | 39 | } | 
| 40 | -        if(!OptionGroup::get()->filter(array('Title' => 'Color'))->first()) { | |
| 40 | +        if (!OptionGroup::get()->filter(array('Title' => 'Color'))->first()) { | |
| 41 | 41 | $do = new OptionGroup(); | 
| 42 | 42 | $do->Title = "Color"; | 
| 43 | 43 | $do->write(); | 
| 44 | 44 | } | 
| 45 | -        if(!OptionGroup::get()->filter(array('Title' => 'Type'))->first()) { | |
| 45 | +        if (!OptionGroup::get()->filter(array('Title' => 'Type'))->first()) { | |
| 46 | 46 | $do = new OptionGroup(); | 
| 47 | 47 | $do->Title = "Type"; | 
| 48 | 48 | $do->write(); | 
| @@ -53,30 +53,30 @@ discard block | ||
| 53 | 53 |  		return new RequiredFields(array('Title')); | 
| 54 | 54 | } | 
| 55 | 55 | |
| 56 | -	public function validate(){ | |
| 56 | +	public function validate() { | |
| 57 | 57 | $result = parent::validate(); | 
| 58 | 58 | |
| 59 | 59 | $title = $this->Title; | 
| 60 | 60 | $firstChar = substr($title, 0, 1); | 
| 61 | -		if(preg_match('/[^a-zA-Z]/', $firstChar)){ | |
| 61 | +		if (preg_match('/[^a-zA-Z]/', $firstChar)) { | |
| 62 | 62 |  			$result->error('The first character of the Title can only be a letter', 'bad'); | 
| 63 | 63 | } | 
| 64 | -		if(preg_match('/[^a-zA-Z]\s/', $title)){ | |
| 64 | +		if (preg_match('/[^a-zA-Z]\s/', $title)) { | |
| 65 | 65 |  			$result->error('Please only use letters, numbers and spaces in the title', 'bad'); | 
| 66 | 66 | } | 
| 67 | 67 | |
| 68 | 68 | return $result; | 
| 69 | 69 | } | 
| 70 | 70 | |
| 71 | -	public function onBeforeDelete(){ | |
| 71 | +	public function onBeforeDelete() { | |
| 72 | 72 | parent::onBeforeDelete(); | 
| 73 | 73 | |
| 74 | 74 | //make sure that if we delete this option group, we reassign the group's option items to the 'None' group. | 
| 75 | 75 |  		$items = OptionItem::get()->filter(array('ProductOptionGroupID' => $this->ID)); | 
| 76 | 76 | |
| 77 | -		if(isset($items)){ | |
| 77 | +		if (isset($items)) { | |
| 78 | 78 |  			$noneGroup = OptionGroup::get()->filter(array('Title' => 'Options'))->first(); | 
| 79 | -			foreach($items as $item){ | |
| 79 | +			foreach ($items as $item) { | |
| 80 | 80 | $item->ProductOptionGroupID = $noneGroup->ID; | 
| 81 | 81 | $item->write(); | 
| 82 | 82 | } | 
| @@ -88,7 +88,7 @@ discard block | ||
| 88 | 88 | } | 
| 89 | 89 | |
| 90 | 90 |  	public function canEdit($member = null) { | 
| 91 | -		switch($this->Title){ | |
| 91 | +		switch ($this->Title) { | |
| 92 | 92 | case 'Options': | 
| 93 | 93 | return false; | 
| 94 | 94 | break; | 
| @@ -7,32 +7,32 @@ discard block | ||
| 7 | 7 | |
| 8 | 8 |  class OptionGroup extends DataObject{ | 
| 9 | 9 | |
| 10 | - private static $db = array( | |
| 11 | - 'Title' => 'Varchar(100)' | |
| 12 | - ); | |
| 10 | + private static $db = array( | |
| 11 | + 'Title' => 'Varchar(100)' | |
| 12 | + ); | |
| 13 | 13 | |
| 14 | 14 | private static $singular_name = 'Product Option Group'; | 
| 15 | - private static $plural_name = 'Product Option Groups'; | |
| 16 | - private static $description = 'Groups of product options, e.g. size, color, etc'; | |
| 15 | + private static $plural_name = 'Product Option Groups'; | |
| 16 | + private static $description = 'Groups of product options, e.g. size, color, etc'; | |
| 17 | 17 | |
| 18 | -	function getCMSFields(){ | |
| 18 | +    function getCMSFields(){ | |
| 19 | 19 | |
| 20 | - $fields = parent::getCMSFields(); | |
| 20 | + $fields = parent::getCMSFields(); | |
| 21 | 21 | |
| 22 | -		$this->extend('getCMSFields', $fields); | |
| 22 | +        $this->extend('getCMSFields', $fields); | |
| 23 | 23 | |
| 24 | - return $fields; | |
| 25 | - } | |
| 24 | + return $fields; | |
| 25 | + } | |
| 26 | 26 | |
| 27 | -	public function requireDefaultRecords() { | |
| 28 | - parent::requireDefaultRecords(); | |
| 29 | - // create a catch-all group | |
| 30 | -		if(!OptionGroup::get()->filter(array('Title' => 'Options'))->first()) { | |
| 31 | - $do = new OptionGroup(); | |
| 32 | - $do->Title = "Options"; | |
| 33 | - $do->write(); | |
| 34 | - } | |
| 35 | -		if(!OptionGroup::get()->filter(array('Title' => 'Size'))->first()) { | |
| 27 | +    public function requireDefaultRecords() { | |
| 28 | + parent::requireDefaultRecords(); | |
| 29 | + // create a catch-all group | |
| 30 | +        if(!OptionGroup::get()->filter(array('Title' => 'Options'))->first()) { | |
| 31 | + $do = new OptionGroup(); | |
| 32 | + $do->Title = "Options"; | |
| 33 | + $do->write(); | |
| 34 | + } | |
| 35 | +        if(!OptionGroup::get()->filter(array('Title' => 'Size'))->first()) { | |
| 36 | 36 | $do = new OptionGroup(); | 
| 37 | 37 | $do->Title = "Size"; | 
| 38 | 38 | $do->write(); | 
| @@ -47,64 +47,64 @@ discard block | ||
| 47 | 47 | $do->Title = "Type"; | 
| 48 | 48 | $do->write(); | 
| 49 | 49 | } | 
| 50 | - } | |
| 51 | - | |
| 52 | -	public function getCMSValidator() { | |
| 53 | -		return new RequiredFields(array('Title')); | |
| 54 | - } | |
| 55 | - | |
| 56 | -	public function validate(){ | |
| 57 | - $result = parent::validate(); | |
| 58 | - | |
| 59 | - $title = $this->Title; | |
| 60 | - $firstChar = substr($title, 0, 1); | |
| 61 | -		if(preg_match('/[^a-zA-Z]/', $firstChar)){ | |
| 62 | -			$result->error('The first character of the Title can only be a letter', 'bad'); | |
| 63 | - } | |
| 64 | -		if(preg_match('/[^a-zA-Z]\s/', $title)){ | |
| 65 | -			$result->error('Please only use letters, numbers and spaces in the title', 'bad'); | |
| 66 | - } | |
| 67 | - | |
| 68 | - return $result; | |
| 69 | - } | |
| 70 | - | |
| 71 | -	public function onBeforeDelete(){ | |
| 72 | - parent::onBeforeDelete(); | |
| 73 | - | |
| 74 | - //make sure that if we delete this option group, we reassign the group's option items to the 'None' group. | |
| 75 | -		$items = OptionItem::get()->filter(array('ProductOptionGroupID' => $this->ID)); | |
| 76 | - | |
| 77 | -		if(isset($items)){ | |
| 78 | -			$noneGroup = OptionGroup::get()->filter(array('Title' => 'Options'))->first(); | |
| 79 | -			foreach($items as $item){ | |
| 80 | - $item->ProductOptionGroupID = $noneGroup->ID; | |
| 81 | - $item->write(); | |
| 82 | - } | |
| 83 | - } | |
| 84 | - } | |
| 85 | - | |
| 86 | -	public function canView($member = false) { | |
| 87 | - return true; | |
| 88 | - } | |
| 89 | - | |
| 90 | -	public function canEdit($member = null) { | |
| 91 | -		switch($this->Title){ | |
| 92 | - case 'Options': | |
| 93 | - return false; | |
| 94 | - break; | |
| 95 | - default: | |
| 96 | -				return Permission::check('Product_CANCRUD'); | |
| 97 | - break; | |
| 98 | - } | |
| 99 | - | |
| 100 | - } | |
| 101 | - | |
| 102 | -	public function canDelete($member = null) { | |
| 103 | - return $this->canEdit(); | |
| 104 | - } | |
| 105 | - | |
| 106 | -	public function canCreate($member = null) { | |
| 107 | -		return Permission::check('Product_CANCRUD'); | |
| 108 | - } | |
| 50 | + } | |
| 51 | + | |
| 52 | +    public function getCMSValidator() { | |
| 53 | +        return new RequiredFields(array('Title')); | |
| 54 | + } | |
| 55 | + | |
| 56 | +    public function validate(){ | |
| 57 | + $result = parent::validate(); | |
| 58 | + | |
| 59 | + $title = $this->Title; | |
| 60 | + $firstChar = substr($title, 0, 1); | |
| 61 | +        if(preg_match('/[^a-zA-Z]/', $firstChar)){ | |
| 62 | +            $result->error('The first character of the Title can only be a letter', 'bad'); | |
| 63 | + } | |
| 64 | +        if(preg_match('/[^a-zA-Z]\s/', $title)){ | |
| 65 | +            $result->error('Please only use letters, numbers and spaces in the title', 'bad'); | |
| 66 | + } | |
| 67 | + | |
| 68 | + return $result; | |
| 69 | + } | |
| 70 | + | |
| 71 | +    public function onBeforeDelete(){ | |
| 72 | + parent::onBeforeDelete(); | |
| 73 | + | |
| 74 | + //make sure that if we delete this option group, we reassign the group's option items to the 'None' group. | |
| 75 | +        $items = OptionItem::get()->filter(array('ProductOptionGroupID' => $this->ID)); | |
| 76 | + | |
| 77 | +        if(isset($items)){ | |
| 78 | +            $noneGroup = OptionGroup::get()->filter(array('Title' => 'Options'))->first(); | |
| 79 | +            foreach($items as $item){ | |
| 80 | + $item->ProductOptionGroupID = $noneGroup->ID; | |
| 81 | + $item->write(); | |
| 82 | + } | |
| 83 | + } | |
| 84 | + } | |
| 85 | + | |
| 86 | +    public function canView($member = false) { | |
| 87 | + return true; | |
| 88 | + } | |
| 89 | + | |
| 90 | +    public function canEdit($member = null) { | |
| 91 | +        switch($this->Title){ | |
| 92 | + case 'Options': | |
| 93 | + return false; | |
| 94 | + break; | |
| 95 | + default: | |
| 96 | +                return Permission::check('Product_CANCRUD'); | |
| 97 | + break; | |
| 98 | + } | |
| 99 | + | |
| 100 | + } | |
| 101 | + | |
| 102 | +    public function canDelete($member = null) { | |
| 103 | + return $this->canEdit(); | |
| 104 | + } | |
| 105 | + | |
| 106 | +    public function canCreate($member = null) { | |
| 107 | +        return Permission::check('Product_CANCRUD'); | |
| 108 | + } | |
| 109 | 109 | |
| 110 | 110 | } | 
| @@ -55,7 +55,7 @@ | ||
| 55 | 55 |  	public function requireDefaultRecords() { | 
| 56 | 56 | parent::requireDefaultRecords(); | 
| 57 | 57 |  		$allCats = DataObject::get('ProductCategory'); | 
| 58 | -		if(!$allCats->count()){ | |
| 58 | +		if (!$allCats->count()) { | |
| 59 | 59 | $cat = new ProductCategory(); | 
| 60 | 60 | $cat->Title = 'Default'; | 
| 61 | 61 | $cat->Code = 'DEFAULT'; | 
| @@ -8,9 +8,9 @@ discard block | ||
| 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 | ||
| 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 | ||
| 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 | } | 
| @@ -11,7 +11,7 @@ discard block | ||
| 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(){ | |
| 14 | +	public function getCMSFields() { | |
| 15 | 15 | $fields = parent::getCMSFields(); | 
| 16 | 16 | |
| 17 | 17 | |
| @@ -41,10 +41,10 @@ discard block | ||
| 41 | 41 | ); | 
| 42 | 42 | |
| 43 | 43 |      public function checkMember() { | 
| 44 | -        if(Member::currentUser()) { | |
| 44 | +        if (Member::currentUser()) { | |
| 45 | 45 | return true; | 
| 46 | -        } else { | |
| 47 | - return Security::permissionFailure ($this, _t ( | |
| 46 | +        }else { | |
| 47 | + return Security::permissionFailure($this, _t( | |
| 48 | 48 | 'AccountPage.CANNOTCONFIRMLOGGEDIN', | 
| 49 | 49 | 'Please login to view this page.' | 
| 50 | 50 | )); | 
| @@ -11,14 +11,14 @@ discard block | ||
| 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 | ||
| 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 | |
| @@ -1,6 +1,6 @@ discard block | ||
| 1 | 1 | <?php | 
| 2 | 2 | |
| 3 | -class FoxyStripeSiteConfig extends DataExtension{ | |
| 3 | +class FoxyStripeSiteConfig extends DataExtension { | |
| 4 | 4 | |
| 5 | 5 | private static $db = array( | 
| 6 | 6 | 'StoreName' => 'Varchar(255)', | 
| @@ -16,7 +16,7 @@ discard block | ||
| 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')); | 
| @@ -55,7 +55,7 @@ discard block | ||
| 55 | 55 | )); | 
| 56 | 56 | |
| 57 | 57 | // configuration warning | 
| 58 | -		if(FoxyCart::store_name_warning()!==null){ | |
| 58 | +		if (FoxyCart::store_name_warning() !== null) { | |
| 59 | 59 | $fields->insertBefore(LiteralField::create( | 
| 60 | 60 | "StoreSubDomainHeaderWarning", | 
| 61 | 61 | _t( | 
| @@ -137,14 +137,14 @@ discard block | ||
| 137 | 137 | |
| 138 | 138 | $siteConfig = SiteConfig::current_site_config(); | 
| 139 | 139 | |
| 140 | -        if(!$siteConfig->StoreKey) { | |
| 140 | +        if (!$siteConfig->StoreKey) { | |
| 141 | 141 | $key = FoxyCart::setStoreKey(); | 
| 142 | -            while(!ctype_alnum($key)){ | |
| 142 | +            while (!ctype_alnum($key)) { | |
| 143 | 143 | $key = FoxyCart::setStoreKey(); | 
| 144 | 144 | } | 
| 145 | 145 | $siteConfig->StoreKey = $key; | 
| 146 | 146 | $siteConfig->write(); | 
| 147 | - DB::alteration_message($siteConfig->ClassName.": created FoxyCart Store Key " . $key, 'created'); | |
| 147 | + DB::alteration_message($siteConfig->ClassName.": created FoxyCart Store Key ".$key, 'created'); | |
| 148 | 148 | } | 
| 149 | 149 | } | 
| 150 | 150 | |
| @@ -2,21 +2,21 @@ discard block | ||
| 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 | ||
| 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/"; | 
| @@ -34,6 +34,9 @@ discard block | ||
| 34 | 34 | } | 
| 35 | 35 | } | 
| 36 | 36 | |
| 37 | + /** | |
| 38 | + * @param string $encrypted | |
| 39 | + */ | |
| 37 | 40 |      public function handleDataFeed($encrypted, $decrypted){ | 
| 38 | 41 | //handle encrypted & decrypted data | 
| 39 | 42 | $orders = new SimpleXMLElement($decrypted); | 
| @@ -79,6 +82,10 @@ discard block | ||
| 79 | 82 | } | 
| 80 | 83 | } | 
| 81 | 84 | |
| 85 | + /** | |
| 86 | + * @param SimpleXMLElement $orders | |
| 87 | + * @param DataObject $transaction | |
| 88 | + */ | |
| 82 | 89 |      public function parseOrderInfo($orders, $transaction) { | 
| 83 | 90 | |
| 84 | 91 |          foreach ($orders->transactions->transaction as $order) { | 
| @@ -95,6 +102,10 @@ discard block | ||
| 95 | 102 | } | 
| 96 | 103 | } | 
| 97 | 104 | |
| 105 | + /** | |
| 106 | + * @param SimpleXMLElement $orders | |
| 107 | + * @param DataObject $transaction | |
| 108 | + */ | |
| 98 | 109 |      public function parseOrderCustomer($orders, $transaction) { | 
| 99 | 110 | |
| 100 | 111 |          foreach ($orders->transactions->transaction as $order) { | 
| @@ -133,6 +144,10 @@ discard block | ||
| 133 | 144 | } | 
| 134 | 145 | } | 
| 135 | 146 | |
| 147 | + /** | |
| 148 | + * @param SimpleXMLElement $orders | |
| 149 | + * @param DataObject $transaction | |
| 150 | + */ | |
| 136 | 151 |      public function parseOrderDetails($orders, $transaction) { | 
| 137 | 152 | |
| 138 | 153 | // remove previous OrderDetails so we don't end up with duplicates | 
| @@ -2,37 +2,37 @@ discard block | ||
| 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 | ||
| 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 | ||
| 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 . '×tamp=' . $timestampNew; | 
| 227 | 227 | |
| 228 | - $this->redirect($redirect_complete); | |
| 228 | + $this->redirect($redirect_complete); | |
| 229 | 229 | |
| 230 | 230 | } | 
| 231 | 231 | |
| @@ -17,9 +17,8 @@ discard block | ||
| 17 | 17 | // handle POST from FoxyCart API transaction | 
| 18 | 18 |  		if ((isset($_POST["FoxyData"]) OR isset($_POST['FoxySubscriptionData']))) { | 
| 19 | 19 | $FoxyData_encrypted = (isset($_POST["FoxyData"])) ? | 
| 20 | - urldecode($_POST["FoxyData"]) : | |
| 21 | - urldecode($_POST["FoxySubscriptionData"]); | |
| 22 | - $FoxyData_decrypted = rc4crypt::decrypt(FoxyCart::getStoreKey(),$FoxyData_encrypted); | |
| 20 | + urldecode($_POST["FoxyData"]) : urldecode($_POST["FoxySubscriptionData"]); | |
| 21 | + $FoxyData_decrypted = rc4crypt::decrypt(FoxyCart::getStoreKey(), $FoxyData_encrypted); | |
| 23 | 22 | self::handleDataFeed($FoxyData_encrypted, $FoxyData_decrypted); | 
| 24 | 23 | |
| 25 | 24 | // extend to allow for additional integrations with Datafeed | 
| @@ -27,14 +26,14 @@ discard block | ||
| 27 | 26 | |
| 28 | 27 | return 'foxy'; | 
| 29 | 28 | |
| 30 | -		} else { | |
| 29 | +		}else { | |
| 31 | 30 | |
| 32 | 31 | return "No FoxyData or FoxySubscriptionData received."; | 
| 33 | 32 | |
| 34 | 33 | } | 
| 35 | 34 | } | 
| 36 | 35 | |
| 37 | -    public function handleDataFeed($encrypted, $decrypted){ | |
| 36 | +    public function handleDataFeed($encrypted, $decrypted) { | |
| 38 | 37 | //handle encrypted & decrypted data | 
| 39 | 38 | $orders = new SimpleXMLElement($decrypted); | 
| 40 | 39 | |
| @@ -43,12 +42,11 @@ discard block | ||
| 43 | 42 | |
| 44 | 43 |              if (isset($order->id)) { | 
| 45 | 44 |                  ($transaction = Order::get()->filter('Order_ID', $order->id)->First()) ? | 
| 46 | - $transaction : | |
| 47 | - $transaction = Order::create(); | |
| 45 | + $transaction : $transaction = Order::create(); | |
| 48 | 46 | } | 
| 49 | 47 | |
| 50 | 48 | // save base order info | 
| 51 | - $transaction->Order_ID = (int) $order->id; | |
| 49 | + $transaction->Order_ID = (int)$order->id; | |
| 52 | 50 | $transaction->Response = $decrypted; | 
| 53 | 51 | |
| 54 | 52 | // record transaction as order | 
| @@ -103,11 +101,11 @@ discard block | ||
| 103 | 101 |              if (isset($order->customer_email) && $order->is_anonymous == 0) { | 
| 104 | 102 | |
| 105 | 103 | // if Customer is existing member, associate with current order | 
| 106 | -                if(Member::get()->filter('Email', $order->customer_email)->First()) { | |
| 104 | +                if (Member::get()->filter('Email', $order->customer_email)->First()) { | |
| 107 | 105 | |
| 108 | 106 |                      $customer = Member::get()->filter('Email', $order->customer_email)->First(); | 
| 109 | 107 | |
| 110 | -                } else { | |
| 108 | +                }else { | |
| 111 | 109 | |
| 112 | 110 | // set PasswordEncryption to 'none' so imported, encrypted password is not encrypted again | 
| 113 | 111 |                      Config::inst()->update('Security', 'password_encryption_algorithm', 'none'); | 
| @@ -213,17 +211,17 @@ discard block | ||
| 213 | 211 | // get current member if logged in. If not, create a 'fake' user with Customer_ID = 0 | 
| 214 | 212 | // fake user will redirect to FC checkout, ask customer to log in | 
| 215 | 213 | // to do: consider a login/registration form here if not logged in | 
| 216 | -        if($Member = Member::currentUser()) { | |
| 214 | +        if ($Member = Member::currentUser()) { | |
| 217 | 215 | $Member = Member::currentUser(); | 
| 218 | -        } else { | |
| 216 | +        }else { | |
| 219 | 217 | $Member = new Member(); | 
| 220 | 218 | $Member->Customer_ID = 0; | 
| 221 | 219 | } | 
| 222 | 220 | |
| 223 | - $auth_token = sha1($Member->Customer_ID . '|' . $timestampNew . '|' . FoxyCart::getStoreKey()); | |
| 221 | + $auth_token = sha1($Member->Customer_ID.'|'.$timestampNew.'|'.FoxyCart::getStoreKey()); | |
| 224 | 222 | |
| 225 | - $redirect_complete = 'https://' . FoxyCart::getFoxyCartStoreName() . '.foxycart.com/checkout?fc_auth_token=' . $auth_token . | |
| 226 | - '&fcsid=' . $fcsid . '&fc_customer_id=' . $Member->Customer_ID . '×tamp=' . $timestampNew; | |
| 223 | + $redirect_complete = 'https://'.FoxyCart::getFoxyCartStoreName().'.foxycart.com/checkout?fc_auth_token='.$auth_token. | |
| 224 | + '&fcsid='.$fcsid.'&fc_customer_id='.$Member->Customer_ID.'×tamp='.$timestampNew; | |
| 227 | 225 | |
| 228 | 226 | $this->redirect($redirect_complete); | 
| 229 | 227 | |
| @@ -20,7 +20,7 @@ | ||
| 20 | 20 | private $product; | 
| 21 | 21 | |
| 22 | 22 | /** | 
| 23 | - * @param $siteConfig | |
| 23 | + * @param SiteConfig|null $siteConfig | |
| 24 | 24 | * @return $this | 
| 25 | 25 | */ | 
| 26 | 26 | public function setSiteConfig($siteConfig) | 
| @@ -120,7 +120,7 @@ discard block | ||
| 120 | 120 | $fields->push(HiddenField::create(ProductPage::getGeneratedValue($code, 'product_id', | 
| 121 | 121 | $this->product->ID))->setValue($this->product->ID)); | 
| 122 | 122 | $fields->push(HiddenField::create(ProductPage::getGeneratedValue($code, 'price', | 
| 123 | - $this->product->Price))->setValue($this->product->Price));//can't override id | |
| 123 | + $this->product->Price))->setValue($this->product->Price)); //can't override id | |
| 124 | 124 | $fields->push(HiddenField::create(ProductPage::getGeneratedValue($code, 'weight', | 
| 125 | 125 | $this->product->Weight))->setValue($this->product->Weight)); | 
| 126 | 126 | |
| @@ -148,11 +148,11 @@ discard block | ||
| 148 | 148 | |
| 149 | 149 |              $fields->push(DropdownField::create('quantity', 'Quantity', $quantity)); | 
| 150 | 150 | |
| 151 | -            $fields->push(HeaderField::create('submitPrice', '$' . $this->product->Price, 4)->addExtraClass('submit-price')); | |
| 151 | +            $fields->push(HeaderField::create('submitPrice', '$'.$this->product->Price, 4)->addExtraClass('submit-price')); | |
| 152 | 152 |              $fields->push(HeaderField::create('unavailableText', 'Selection unavailable', 4)->addExtraClass('hidden unavailable-text')); | 
| 153 | 153 | |
| 154 | 154 |              $this->extend('updatePurchaseFormFields', $fields); | 
| 155 | -        } else { | |
| 155 | +        }else { | |
| 156 | 156 |              $fields->push(HeaderField::create('submitPrice', 'Currently Out of Stock'), 4); | 
| 157 | 157 | } | 
| 158 | 158 | |
| @@ -189,7 +189,7 @@ discard block | ||
| 189 | 189 | protected function getProductOptionSet() | 
| 190 | 190 |      { | 
| 191 | 191 | |
| 192 | -        $assignAvailable = function ($self) { | |
| 192 | +        $assignAvailable = function($self) { | |
| 193 | 193 |              $this->extend('updateFoxyStripePurchaseForm', $form); | 
| 194 | 194 | $self->Available = ($self->getAvailability()) ? true : false; | 
| 195 | 195 | }; |