Completed
Pull Request — master (#287)
by Nic
07:56
created
code/pages/ProductHolder.php 1 patch
Braces   +3 added lines, -1 removed lines patch added patch discarded remove patch
@@ -81,7 +81,9 @@
 block discarded – undo
81 81
     {
82 82
         if ($children = $this->AllChildren()) {
83 83
             foreach ($children as $child) {
84
-                if (in_array($child->ID, $idList)) continue;
84
+                if (in_array($child->ID, $idList)) {
85
+                    continue;
86
+                }
85 87
 
86 88
                 if ($child instanceof ProductHolder) {
87 89
                     $idList[] = $child->ID;
Please login to merge, or discard this patch.
code/form/FoxyStripeDropdownField.php 1 patch
Indentation   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -50,41 +50,41 @@
 block discarded – undo
50 50
  */
51 51
 class FoxyStripeDropdownField extends DropdownField{
52 52
 
53
-	/**
54
-	 * Mark certain elements as disabled,
55
-	 * regardless of the {@link setDisabled()} settings.
56
-	 *
57
-	 * @param array $items Collection of array keys, as defined in the $source array
53
+    /**
54
+     * Mark certain elements as disabled,
55
+     * regardless of the {@link setDisabled()} settings.
56
+     *
57
+     * @param array $items Collection of array keys, as defined in the $source array
58 58
      * @return $this
59
-	 */
60
-	public function setDisabledItems($items){
61
-		$controller = Controller::curr();
62
-		$code = $controller->data()->Code;
63
-		$updated = [];
64
-		if(is_array($items) && !empty($items)){
65
-			foreach($items as $item){
66
-				array_push($updated, FoxyStripeProduct::getGeneratedValue($code, $this->getName(), $item, 'value'));
67
-			}
68
-		}
69
-		$this->disabledItems = $updated;
70
-		return $this;
71
-	}
59
+     */
60
+    public function setDisabledItems($items){
61
+        $controller = Controller::curr();
62
+        $code = $controller->data()->Code;
63
+        $updated = [];
64
+        if(is_array($items) && !empty($items)){
65
+            foreach($items as $item){
66
+                array_push($updated, FoxyStripeProduct::getGeneratedValue($code, $this->getName(), $item, 'value'));
67
+            }
68
+        }
69
+        $this->disabledItems = $updated;
70
+        return $this;
71
+    }
72 72
 
73
-	/**
74
-	 * @param array $source
73
+    /**
74
+     * @param array $source
75 75
      * @return $this
76
-	 */
77
-	public function setSource($source) {
78
-		$controller = Controller::curr();
79
-		$code = $controller->data()->Code;
80
-		$updated = [];
81
-		if(is_array($source) && !empty($source)){
82
-			foreach($source as $key => $val){
83
-				$updated[FoxyStripeProduct::getGeneratedValue($code, $this->getName(), $key, 'value')] = $val;
84
-			}
85
-		}
86
-		$this->source = $updated;
87
-		return $this;
88
-	}
76
+     */
77
+    public function setSource($source) {
78
+        $controller = Controller::curr();
79
+        $code = $controller->data()->Code;
80
+        $updated = [];
81
+        if(is_array($source) && !empty($source)){
82
+            foreach($source as $key => $val){
83
+                $updated[FoxyStripeProduct::getGeneratedValue($code, $this->getName(), $key, 'value')] = $val;
84
+            }
85
+        }
86
+        $this->source = $updated;
87
+        return $this;
88
+    }
89 89
 
90 90
 }
Please login to merge, or discard this patch.
code/objects/ProductImage.php 1 patch
Indentation   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -7,25 +7,25 @@  discard block
 block discarded – undo
7 7
 
8 8
 class ProductImage extends DataObject{
9 9
 
10
-	private static $db = array(
11
-		'Title' => 'Text',
12
-		'SortOrder' => 'Int'
13
-	);
10
+    private static $db = array(
11
+        'Title' => 'Text',
12
+        'SortOrder' => 'Int'
13
+    );
14 14
 
15
-	private static $has_one = array(
16
-		'Image' => 'Image',
17
-		'Product' => 'FoxyStripeProduct'
18
-	);
15
+    private static $has_one = array(
16
+        'Image' => 'Image',
17
+        'Product' => 'FoxyStripeProduct'
18
+    );
19 19
 
20
-	private static $default_sort = 'SortOrder';
20
+    private static $default_sort = 'SortOrder';
21 21
 
22
-	private static $summary_fields = array(
23
-		'Image.CMSThumbnail' => 'Image',
24
-		'Title' => 'Caption'
25
-	);
22
+    private static $summary_fields = array(
23
+        'Image.CMSThumbnail' => 'Image',
24
+        'Title' => 'Caption'
25
+    );
26 26
 
27
-	public function getCMSFields(){
28
-		$fields = FieldList::create(
27
+    public function getCMSFields(){
28
+        $fields = FieldList::create(
29 29
             TextField::create('Title')
30 30
                 ->setTitle(_t('ProductImage.Title', 'Product Image Title')),
31 31
             UploadField::create('Image')
@@ -34,25 +34,25 @@  discard block
 block discarded – undo
34 34
                 ->setAllowedExtensions(array('jpg', 'jpeg', 'gif', 'png'))
35 35
         );
36 36
 
37
-		$this->extend('updateCMSFields', $fields);
37
+        $this->extend('updateCMSFields', $fields);
38 38
 
39 39
         return $fields;
40
-	}
40
+    }
41 41
 
42
-	public function canView($member = false) {
43
-		return true;
44
-	}
42
+    public function canView($member = false) {
43
+        return true;
44
+    }
45 45
 
46
-	public function canEdit($member = null) {
47
-		return Permission::check('Product_CANCRUD');
48
-	}
46
+    public function canEdit($member = null) {
47
+        return Permission::check('Product_CANCRUD');
48
+    }
49 49
 
50
-	public function canDelete($member = null) {
51
-		return Permission::check('Product_CANCRUD');
52
-	}
50
+    public function canDelete($member = null) {
51
+        return Permission::check('Product_CANCRUD');
52
+    }
53 53
 
54
-	public function canCreate($member = null) {
55
-		return Permission::check('Product_CANCRUD');
56
-	}
54
+    public function canCreate($member = null) {
55
+        return Permission::check('Product_CANCRUD');
56
+    }
57 57
 
58 58
 }
Please login to merge, or discard this patch.
tests/FoxyStripeProductTest.php 2 patches
Braces   +6 added lines, -2 removed lines patch added patch discarded remove patch
@@ -55,14 +55,18 @@
 block discarded – undo
55 55
 
56 56
         $versions = DB::query('Select * FROM "FoxyStripeProduct_versions" WHERE "RecordID" = ' . $productID);
57 57
         $versionsPostPublish = array();
58
-        foreach ($versions as $versionRow) $versionsPostPublish[] = $versionRow;
58
+        foreach ($versions as $versionRow) {
59
+            $versionsPostPublish[] = $versionRow;
60
+        }
59 61
 
60 62
         $product2->delete();
61 63
         $this->assertTrue(!$product2->isPublished());
62 64
 
63 65
         $versions = DB::query('Select * FROM "FoxyStripeProduct_versions" WHERE "RecordID" = ' . $productID);
64 66
         $versionsPostDelete = array();
65
-        foreach ($versions as $versionRow) $versionsPostDelete[] = $versionRow;
67
+        foreach ($versions as $versionRow) {
68
+            $versionsPostDelete[] = $versionRow;
69
+        }
66 70
 
67 71
         $this->assertEquals($versionsPostPublish, $versionsPostDelete);
68 72
 
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -53,14 +53,14 @@
 block discarded – undo
53 53
         $product2->doPublish();
54 54
         $this->assertTrue($product2->isPublished());
55 55
 
56
-        $versions = DB::query('Select * FROM "ShippableProduct_versions" WHERE "RecordID" = ' . $productID);
56
+        $versions = DB::query('Select * FROM "ShippableProduct_versions" WHERE "RecordID" = '.$productID);
57 57
         $versionsPostPublish = array();
58 58
         foreach ($versions as $versionRow) $versionsPostPublish[] = $versionRow;
59 59
 
60 60
         $product2->delete();
61 61
         $this->assertTrue(!$product2->isPublished());
62 62
 
63
-        $versions = DB::query('Select * FROM "ShippableProduct_versions" WHERE "RecordID" = ' . $productID);
63
+        $versions = DB::query('Select * FROM "ShippableProduct_versions" WHERE "RecordID" = '.$productID);
64 64
         $versionsPostDelete = array();
65 65
         foreach ($versions as $versionRow) $versionsPostDelete[] = $versionRow;
66 66
 
Please login to merge, or discard this patch.
code/objects/products/FoxyStripeProduct.php 2 patches
Braces   +6 added lines, -2 removed lines patch added patch discarded remove patch
@@ -141,11 +141,15 @@
 block discarded – undo
141 141
                             Settings > FoxyStripe > Categories
142 142
                         </a>'
143 143
             ));
144
-        if (class_exists('QuickAddNewExtension')) $catField->useAddNew('FoxyCartProductCategory', $source);
144
+        if (class_exists('QuickAddNewExtension')) {
145
+            $catField->useAddNew('FoxyCartProductCategory', $source);
146
+        }
145 147
 
146 148
         // Product Images gridfield
147 149
         $config = GridFieldConfig_RelationEditor::create();
148
-        if (class_exists('GridFieldSortableRows')) $config->addComponent(new GridFieldSortableRows('SortOrder'));
150
+        if (class_exists('GridFieldSortableRows')) {
151
+            $config->addComponent(new GridFieldSortableRows('SortOrder'));
152
+        }
149 153
         if (class_exists('GridFieldBulkImageUpload')) {
150 154
             $config->addComponent(new GridFieldBulkUpload());
151 155
             $config->getComponentByType('GridFieldBulkUpload')->setUfConfig('folderName', 'Uploads/ProductImages');
Please login to merge, or discard this patch.
Spacing   +5 added lines, -6 removed lines patch added patch discarded remove patch
@@ -122,7 +122,7 @@  discard block
 block discarded – undo
122 122
         $previewDescription = ($this->stat('customPreviewDescription')) ? $this->stat('customPreviewDescription') : _t('ProductPage.PreviewImageDescription', 'Image used throughout site to represent this product');
123 123
 
124 124
         // Cateogry Dropdown field w/ add new
125
-        $source = function () {
125
+        $source = function() {
126 126
             return FoxyCartProductCategory::get()->map()->toArray();
127 127
         };
128 128
         $catField = DropdownField::create('CategoryID', _t('ProductPage.Category', 'FoxyCart Category'), $source())
@@ -159,7 +159,7 @@  discard block
 block discarded – undo
159 159
         if (class_exists('GridFieldSortableRows')) {
160 160
             $config->addComponent(new GridFieldSortableRows('SortOrder'));
161 161
             $products = $this->ProductOptions()->sort('SortOrder');
162
-        } else {
162
+        }else {
163 163
             $products = $this->ProductOptions();
164 164
         }
165 165
         $config->removeComponentsByType('GridFieldAddExistingAutocompleter');
@@ -215,7 +215,7 @@  discard block
 block discarded – undo
215 215
                 ->setFolderName('Uploads/Products')
216 216
                 ->setAllowedExtensions(['jpg', 'jpeg', 'gif', 'png'])
217 217
                 ->setAllowedMaxFileNumber(1),
218
-            HeaderField::create('ProductImagesHD', _t('ProductPage.ProductImagesHD' . 'Product Image Gallery'), 2),
218
+            HeaderField::create('ProductImagesHD', _t('ProductPage.ProductImagesHD'.'Product Image Gallery'), 2),
219 219
             $prodImagesField
220 220
                 ->setDescription(_t(
221 221
                     'ProductPage.ProductImagesDescription',
@@ -273,7 +273,7 @@  discard block
 block discarded – undo
273 273
             $product = ProductPage::get()->byID($this->ID);
274 274
             if (isset($product->ParentID)) {
275 275
                 $origParent = $product->ParentID;
276
-            } else {
276
+            }else {
277 277
                 $origParent = null;
278 278
             }
279 279
             $currentParent = $this->ParentID;
@@ -348,8 +348,7 @@  discard block
 block discarded – undo
348 348
     {
349 349
         $optionName = ($optionName !== null) ? preg_replace('/\s/', '_', $optionName) : $optionName;
350 350
         return (SiteConfig::current_site_config()->CartValidation)
351
-            ? FoxyCart_Helper::fc_hash_value($productCode, $optionName, $optionValue, $method, $output, $urlEncode) :
352
-            $optionValue;
351
+            ? FoxyCart_Helper::fc_hash_value($productCode, $optionName, $optionValue, $method, $output, $urlEncode) : $optionValue;
353 352
     }
354 353
 
355 354
     /**
Please login to merge, or discard this patch.
tests/ProductDiscountTierTest.php 1 patch
Indentation   +51 added lines, -51 removed lines patch added patch discarded remove patch
@@ -2,79 +2,79 @@
 block discarded – undo
2 2
 
3 3
 class ProductDiscountTierTest extends FS_Test{
4 4
 
5
-	protected static $use_draft_site = true;
5
+    protected static $use_draft_site = true;
6 6
 
7
-	function setUp(){
8
-		parent::setUp();
7
+    function setUp(){
8
+        parent::setUp();
9 9
 
10
-		$productHolder = ProductHolder::create();
11
-		$productHolder->Title = 'Product Holder';
12
-		$productHolder->write();
10
+        $productHolder = ProductHolder::create();
11
+        $productHolder->Title = 'Product Holder';
12
+        $productHolder->write();
13 13
 
14
-		$product = $this->objFromFixture('ShippableProduct', 'product1');
15
-		$product->ParentID = $productHolder->ID;
16
-		$product->write();
17
-	}
14
+        $product = $this->objFromFixture('ShippableProduct', 'product1');
15
+        $product->ParentID = $productHolder->ID;
16
+        $product->write();
17
+    }
18 18
 
19
-	public function testProductDiscountTierCreation(){
20
-		$this->logInWithPermission('Product_CANCRUD');
19
+    public function testProductDiscountTierCreation(){
20
+        $this->logInWithPermission('Product_CANCRUD');
21 21
 
22
-		$discount = ShippableProduct::get()->first();
22
+        $discount = ShippableProduct::get()->first();
23 23
 
24
-		$tier = $this->objFromFixture('ProductDiscountTier', 'fiveforten');
25
-		$tier->ShippableProductID = $discount->ID;
26
-		$tier->write();
27
-		$tierID = $tier->ID;
24
+        $tier = $this->objFromFixture('ProductDiscountTier', 'fiveforten');
25
+        $tier->ShippableProductID = $discount->ID;
26
+        $tier->write();
27
+        $tierID = $tier->ID;
28 28
 
29
-		$checkTier = ProductDiscountTier::get()->byID($tierID);
29
+        $checkTier = ProductDiscountTier::get()->byID($tierID);
30 30
 
31
-		$this->assertEquals($checkTier->Quantity, 5);
32
-		$this->assertEquals($checkTier->Percentage, 10);
31
+        $this->assertEquals($checkTier->Quantity, 5);
32
+        $this->assertEquals($checkTier->Percentage, 10);
33 33
 
34
-		$this->logOut();
35
-	}
34
+        $this->logOut();
35
+    }
36 36
 
37
-	public function testProductDiscountTierEdit(){
38
-		$this->logInWithPermission('ADMIN');
37
+    public function testProductDiscountTierEdit(){
38
+        $this->logInWithPermission('ADMIN');
39 39
 
40
-		$discount = ShippableProduct::get()->first();
40
+        $discount = ShippableProduct::get()->first();
41 41
 
42
-		$tier = $this->objFromFixture('ProductDiscountTier', 'fiveforten');
43
-		$tier->ShippableProductID = $discount->ID;
44
-		$tier->write();
45
-		$tierID = $tier->ID;
46
-		$this->logInWithPermission('Product_CANCRUD');
42
+        $tier = $this->objFromFixture('ProductDiscountTier', 'fiveforten');
43
+        $tier->ShippableProductID = $discount->ID;
44
+        $tier->write();
45
+        $tierID = $tier->ID;
46
+        $this->logInWithPermission('Product_CANCRUD');
47 47
 
48
-		$tier->Quantity = 2;
49
-		$tier->Percentage = 5;
50
-		$tier->write();
48
+        $tier->Quantity = 2;
49
+        $tier->Percentage = 5;
50
+        $tier->write();
51 51
 
52
-		$checkTier = ProductDiscountTier::get()->byID($tierID);
52
+        $checkTier = ProductDiscountTier::get()->byID($tierID);
53 53
 
54
-		$this->assertEquals($checkTier->Quantity, 2);
55
-		$this->assertEquals($checkTier->Percentage, 5);
54
+        $this->assertEquals($checkTier->Quantity, 2);
55
+        $this->assertEquals($checkTier->Percentage, 5);
56 56
 
57
-		$this->logOut();
58
-	}
57
+        $this->logOut();
58
+    }
59 59
 
60
-	public function testProductDiscountTierDeletion(){
61
-		$this->logInWithPermission('ADMIN');
60
+    public function testProductDiscountTierDeletion(){
61
+        $this->logInWithPermission('ADMIN');
62 62
 
63
-		$discount = ShippableProduct::get()->first();
63
+        $discount = ShippableProduct::get()->first();
64 64
 
65
-		$tier = $this->objFromFixture('ProductDiscountTier', 'fiveforten');
66
-		$tier->ShippableProductID = $discount->ID;
67
-		$tier->write();
68
-		$tierID = $tier->ID;
65
+        $tier = $this->objFromFixture('ProductDiscountTier', 'fiveforten');
66
+        $tier->ShippableProductID = $discount->ID;
67
+        $tier->write();
68
+        $tierID = $tier->ID;
69 69
 
70
-		$this->logOut();
70
+        $this->logOut();
71 71
 
72
-		$this->logInWithPermission('Product_CANCRUD');
72
+        $this->logInWithPermission('Product_CANCRUD');
73 73
 
74
-		$tier->delete();
75
-		$this->assertTrue(!ProductDiscountTier::get()->byID($tierID));
74
+        $tier->delete();
75
+        $this->assertTrue(!ProductDiscountTier::get()->byID($tierID));
76 76
 
77
-		$this->logOut();
78
-	}
77
+        $this->logOut();
78
+    }
79 79
 
80 80
 }
Please login to merge, or discard this patch.
code/model/foxycart.cart_validation.php 2 patches
Doc Comments   +6 added lines patch added patch discarded remove patch
@@ -30,10 +30,16 @@
 block discarded – undo
30 30
 	// protected static $cart_url = 'https://yourdomain.foxycart.com/cart';
31 31
 	protected static $cart_url;
32 32
 
33
+	/**
34
+	 * @param string $storeName
35
+	 */
33 36
 	public static function setCartURL($storeName = null){
34 37
 		self::$cart_url = 'https://'.$storeName.'.faxycart.com/cart';
35 38
 	}
36 39
 
40
+	/**
41
+	 * @param string $secret
42
+	 */
37 43
 	public static function setSecret($secret = null){
38 44
 		self::$secret = $secret;
39 45
 	}
Please login to merge, or discard this patch.
Indentation   +310 added lines, -310 removed lines patch added patch discarded remove patch
@@ -14,315 +14,315 @@
 block discarded – undo
14 14
  *   - Empty textareas are assumed to be "open"
15 15
  */
16 16
 class FoxyCart_Helper {
17
-	/**
18
-	 * API Key (Secret)
19
-	 *
20
-	 * @var string
21
-	 **/
22
-	private static $secret;
23
-
24
-	/**
25
-	 * Cart URL
26
-	 *
27
-	 * @var string
28
-	 * Notes: Could be 'https://yourdomain.foxycart.com/cart' or 'https://secure.yourdomain.com/cart'
29
-	 **/
30
-	// protected static $cart_url = 'https://yourdomain.foxycart.com/cart';
31
-	protected static $cart_url;
32
-
33
-	public static function setCartURL($storeName = null){
34
-		self::$cart_url = 'https://'.$storeName.'.faxycart.com/cart';
35
-	}
36
-
37
-	public static function setSecret($secret = null){
38
-		self::$secret = $secret;
39
-	}
40
-
41
-	public function __construct(){
42
-		static::setCartURL(FoxyCart::get_foxy_cart_store_name());
43
-		static::setSecret(FoxyCart::get_store_key());
44
-	}
45
-
46
-	public static function getSecret(){
47
-		return FoxyCart::get_store_key();
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
+        static::setCartURL(FoxyCart::get_foxy_cart_store_name());
43
+        static::setSecret(FoxyCart::get_store_key());
44
+    }
45
+
46
+    public static function getSecret(){
47
+        return FoxyCart::get_store_key();
48
+    }
49
+
50
+
51
+    /**
52
+     * Cart Excludes
53
+     *
54
+     * Arrays of values and prefixes that should be ignored when signing links and forms.
55
+     * @var array
56
+     */
57
+    protected static $cart_excludes = array(
58
+        // Cart values
59
+        'cart', 'fcsid', 'empty', 'coupon', 'output', 'sub_token', 'redirect', 'callback', '_',
60
+        // Checkout pre-population values
61
+        'customer_email', 'customer_first_name', 'customer_last_name', 'customer_address1', 'customer_address2',
62
+        'customer_city', 'customer_state', 'customer_postal_code', 'customer_country', 'customer_phone', 'customer_company',
63
+        'shipping_first_name', 'shipping_last_name', 'shipping_address1', 'shipping_address2',
64
+        'shipping_city', 'shipping_state', 'shipping_postal_code', 'shipping_country', 'shipping_phone', 'shipping_company',
65
+    );
66
+    protected static $cart_excludes_prefixes = array(
67
+        'h:', 'x:', '__',
68
+    );
69
+
70
+    /**
71
+     * Debugging
72
+     *
73
+     * Set to $debug to TRUE to enable debug logging.
74
+     *
75
+     */
76
+    protected static $debug = FALSE;
77
+    protected static $log = array();
78
+
79
+
80
+    /**
81
+     * "Link Method": Generate HMAC SHA256 for GET Query Strings
82
+     *
83
+     * Notes: Can't parse_str because PHP doesn't support non-alphanumeric characters as array keys.
84
+     * @return string
85
+     **/
86
+    public static function fc_hash_querystring($qs, $output = TRUE) {
87
+        self::$log[] = '<strong>Signing link</strong> with data: '.htmlspecialchars(substr($qs, 0, 150)).'...';
88
+        $fail = self::$cart_url.'?'.$qs;
89
+
90
+        // If the link appears to be hashed already, don't bother
91
+        if (strpos($qs, '||')) {
92
+            self::$log[] = '<strong>Link appears to be signed already</strong>: '.htmlspecialchars($code[0]);
93
+            return $fail;
94
+        }
95
+
96
+        // Stick an ampersand on the beginning of the querystring to make matching the first element a little easier
97
+        $qs = '&'.urldecode($qs);
98
+
99
+        // Get all the prefixes, codes, and name=value pairs
100
+        preg_match_all('%(?P<amp>&(?:amp;)?)(?P<prefix>[a-z0-9]{1,3}:)?(?P<name>[^=]+)=(?P<value>[^&]+)%', $qs, $pairs, PREG_SET_ORDER);
101
+        self::$log[] = 'Found the following pairs to sign:<pre>'.htmlspecialchars(print_r($pairs, true)).'</pre>';
102
+
103
+        // Get all the "code" values, set the matches in $codes
104
+        $codes = array();
105
+        foreach ($pairs as $pair) {
106
+            if ($pair['name'] == 'code') {
107
+                $codes[$pair['prefix']] = $pair['value'];
108
+            }
109
+        }
110
+        if ( ! count($codes)) {
111
+            self::$log[] = '<strong style="color:#600;">No code found</strong> for the above link.';
112
+            return $fail;
113
+        }
114
+        self::$log[] = '<strong style="color:orange;">CODES found:</strong> '.htmlspecialchars(print_r($codes, true));
115
+
116
+        // Sign the name/value pairs
117
+        foreach ($pairs as $pair) {
118
+            // Skip the cart excludes
119
+            if (in_array($pair['name'], self::$cart_excludes) || in_array($pair['prefix'], self::$cart_excludes_prefixes)) {
120
+                self::$log[] = '<strong style="color:purple;">Skipping</strong> the reserved parameter or prefix "'.$pair['prefix'].$pair['name'].'" = '.$pair['value'];
121
+                continue;
122
+            }
123
+
124
+            // Continue to sign the value and replace the name=value in the querystring with name=value||hash
125
+            $value = self::fc_hash_value($codes[$pair['prefix']], $pair['name'], $pair['value'], 'value', FALSE, 'urlencode');
126
+            $replacement = $pair['amp'].$pair['prefix'].urlencode($pair['name']).'='.$value;
127
+            $qs = str_replace($pair[0], $replacement, $qs);
128
+            self::$log[] = 'Signed <strong>'.$pair['name'].'</strong> = <strong>'.$pair['value'].'</strong> with '.$replacement.'.<br />Replacing: '.$pair[0].'<br />With... '.$replacement;
129
+        }
130
+        $qs = ltrim($qs, '&'); // Get rid of that leading ampersand we added earlier
131
+
132
+        if ($output) {
133
+            echo self::$cart_url.'?'.$qs;
134
+        } else {
135
+            return self::$cart_url.'?'.$qs;
136
+        }
137
+    }
138
+
139
+
140
+    /**
141
+     * "Form Method": Generate HMAC SHA256 for form elements or individual <input />s
142
+     *
143
+     * @return string
144
+     **/
145
+    public static function fc_hash_value($product_code, $option_name, $option_value = '', $method = 'name', $output = TRUE, $urlencode = false) {
146
+        if (!$product_code || !$option_name) {
147
+            return FALSE;
148
+        }
149
+        if ($option_value == '--OPEN--') {
150
+            $hash = hash_hmac('sha256', $product_code.$option_name.$option_value, self::getSecret());
151
+            $value = ($urlencode) ? urlencode($option_name).'||'.$hash.'||open' : $option_name.'||'.$hash.'||open';
152
+        } else {
153
+            $hash = hash_hmac('sha256', $product_code.$option_name.$option_value, self::getSecret());
154
+            if ($method == 'name') {
155
+                $value = ($urlencode) ? urlencode($option_name).'||'.$hash : $option_name.'||'.$hash;
156
+            } else {
157
+                $value = ($urlencode) ? urlencode($option_value).'||'.$hash : $option_value.'||'.$hash;
158
+            }
159
+        }
160
+
161
+        if ($output) {
162
+            echo $value;
163
+        } else {
164
+            return $value;
165
+        }
166
+    }
167
+
168
+    /**
169
+     * Raw HTML Signing: Sign all links and form elements in a block of HTML
170
+     *
171
+     * Accepts a string of HTML and signs all links and forms.
172
+     * Requires link 'href' and form 'action' attributes to use 'https' and not 'http'.
173
+     * Requires a 'code' to be set in every form.
174
+     *
175
+     * @return string
176
+     **/
177
+    public static function fc_hash_html($html) {
178
+        // Initialize some counting
179
+        $count['temp'] = 0; // temp counter
180
+        $count['links'] = 0;
181
+        $count['forms'] = 0;
182
+        $count['inputs'] = 0;
183
+        $count['lists'] = 0;
184
+        $count['textareas'] = 0;
185
+
186
+        // Find and sign all the links
187
+        preg_match_all('%<a .*?href=[\'"]'.preg_quote(self::$cart_url).'(?:\.php)?\?(.+?)[\'"].*?>%i', $html, $querystrings);
188
+        // print_r($querystrings);
189
+        foreach ($querystrings[1] as $querystring) {
190
+            // If it's already signed, skip it.
191
+            if (preg_match('%&(?:amp;)?hash=%i', $querystring)) {
192
+                continue;
193
+            }
194
+            $pattern = '%(href=[\'"])'.preg_quote(self::$cart_url, '%').'(?:\.php)?\?'.preg_quote($querystring, '%').'([\'"])%i';
195
+            $signed = self::fc_hash_querystring($querystring, FALSE);
196
+            $html = preg_replace($pattern, '$1'.$signed.'$2', $html, -1, $count['temp']);
197
+            $count['links'] += $count['temp'];
198
+        }
199
+        unset($querystrings);
200
+
201
+        // Find and sign all form values
202
+        preg_match_all('%<form [^>]*?action=[\'"]'.preg_quote(self::$cart_url).'?[\'"].*?>(.+?)</form>%is', $html, $forms);
203
+        foreach ($forms[1] as $form) {
204
+            $count['forms']++;
205
+            self::$log[] = '<strong>Signing form</strong> with data: '.htmlspecialchars(substr($form, 0, 150)).'...';
206
+
207
+            // Store the original form so we can replace it when we're done
208
+            $form_original = $form;
209
+
210
+            // Check for the "code" input, set the matches in $codes
211
+            if (!preg_match_all('%<[^>]*?name=([\'"])([0-9]{1,3}:)?code\1[^>]*?>%i', $form, $codes, PREG_SET_ORDER)) {
212
+                self::$log[] = '<strong style="color:#600;">No code found</strong> for the above form.';
213
+                continue;
214
+            }
215
+            // For each code found, sign the appropriate inputs
216
+            foreach ($codes as $code) {
217
+                // If the form appears to be hashed already, don't bother
218
+                if (strpos($code[0], '||')) {
219
+                    self::$log[] = '<strong>Form appears to be signed already</strong>: '.htmlspecialchars($code[0]);
220
+                    continue;
221
+                }
222
+                // Get the code and the prefix
223
+                $prefix = (isset($code[2])) ? $code[2] : '';
224
+                preg_match('%<[^>]*?value=([\'"])(.+?)\1[^>]*?>%i', $code[0], $code);
225
+                $code = trim($code[2]);
226
+                self::$log[] = '<strong>Prefix for '.htmlspecialchars($code).'</strong>: '.htmlspecialchars($prefix);
227
+                if (!$code) { // If the code is empty, skip this form or specific prefixed elements
228
+                    continue;
229
+                }
230
+
231
+                // Sign all <input /> elements with matching prefix
232
+                preg_match_all('%<input [^>]*?name=([\'"])'.preg_quote($prefix).'(?![0-9]{1,3})(?:.+?)\1[^>]*>%i', $form, $inputs);
233
+                foreach ($inputs[0] as $input) {
234
+                    $count['inputs']++;
235
+                    // Test to make sure both name and value attributes are found
236
+                    if (preg_match('%name=([\'"])'.preg_quote($prefix).'(?![0-9]{1,3})(.+?)\1%i', $input, $name) > 0) {
237
+                        preg_match('%value=([\'"])(.*?)\1%i', $input, $value);
238
+                        $value = (count($value) > 0) ? $value : array('', '', '');
239
+                        preg_match('%type=([\'"])(.*?)\1%i', $input, $type);
240
+                        $type = (count($type) > 0) ? $type : array('', '', '');
241
+                        // Skip the cart excludes
242
+                        if (in_array($prefix.$name[2], self::$cart_excludes) || in_array(substr($prefix.$name[2], 0, 2), self::$cart_excludes_prefixes)) {
243
+                            self::$log[] = '<strong style="color:purple;">Skipping</strong> the reserved parameter or prefix "'.$prefix.$name[2].'" = '.$value[2];
244
+                            continue;
245
+                        }
246
+                        self::$log[] = '<strong>INPUT['.$type[2].']:</strong> Name: <strong>'.$prefix.htmlspecialchars(preg_quote($name[2])).'</strong>';
247
+                        self::$log[] = '<strong>Replacement Pattern:</strong> ([\'"])'.$prefix.preg_quote($name[2]).'\1';
248
+                        $value[2] = ($value[2] == '') ? '--OPEN--' : $value[2];
249
+                        if ($type[2] == 'radio') {
250
+                            $input_signed = preg_replace('%([\'"])'.preg_quote($value[2]).'\1%', '${1}'.self::fc_hash_value($code, $name[2], $value[2], 'value', FALSE)."$1", $input);
251
+                        } else {
252
+                            $input_signed = preg_replace('%([\'"])'.$prefix.preg_quote($name[2]).'\1%', '${1}'.$prefix.self::fc_hash_value($code, $name[2], $value[2], 'name', FALSE)."$1", $input);
253
+                        }
254
+                        self::$log[] = '<strong>INPUT:</strong> Code: <strong>'.htmlspecialchars($prefix.$code).
255
+                                        '</strong> :: Name: <strong>'.htmlspecialchars($prefix.$name[2]).
256
+                                        '</strong> :: Value: <strong>'.htmlspecialchars($value[2]).
257
+                                        '</strong><br />Initial input: '.htmlspecialchars($input).
258
+                                        '<br />Signed: <span style="color:#060;">'.htmlspecialchars($input_signed).'</span>';
259
+                        $form = str_replace($input, $input_signed, $form);
260
+                    }
261
+                }
262
+                self::$log[] = '<strong>FORM after INPUTS:</strong> <pre>'.htmlspecialchars($form).'</pre>';
263
+
264
+                // Sign all <option /> elements
265
+                preg_match_all('%<select [^>]*name=([\'"])'.preg_quote($prefix).'(?![0-9]{1,3})(.+?)\1[^>]*>(.+?)</select>%is', $form, $lists, PREG_SET_ORDER);
266
+                foreach ($lists as $list) {
267
+                    $count['lists']++;
268
+                    preg_match_all('%<option [^>]*value=([\'"])(.+?)\1[^>]*>(?:.*?)</option>%i', $list[0], $options, PREG_SET_ORDER);
269
+                    self::$log[] = '<strong>Options:</strong> <pre>'.htmlspecialchars(print_r($options, true)).'</pre>';
270
+                    unset( $form_part_signed );
271
+                    foreach ($options as $option) {
272
+                        if( !isset($form_part_signed) ) $form_part_signed = $list[0];
273
+                        $option_signed = preg_replace(
274
+                            '%'.preg_quote($option[1]).preg_quote($option[2]).preg_quote($option[1]).'%',
275
+                            $option[1].self::fc_hash_value($code, $list[2], $option[2], 'value', FALSE).$option[1],
276
+                            $option[0]);
277
+                        $form_part_signed = str_replace($option[0], $option_signed, $form_part_signed );
278
+                        self::$log[] = '<strong>OPTION:</strong> Code: <strong>'.htmlspecialchars($prefix.$code).
279
+                                        '</strong> :: Name: <strong>'.htmlspecialchars($prefix.$list[2]).
280
+                                        '</strong> :: Value: <strong>'.htmlspecialchars($option[2]).
281
+                                        '</strong><br />Initial option: '.htmlspecialchars($option[0]).
282
+                                        '<br />Signed: <span style="color:#060;">'.htmlspecialchars($option_signed).'</span>';
283
+                    }
284
+                    $form = str_replace($list[0], $form_part_signed, $form);
285
+                }
286
+                self::$log[] = '<strong>FORM after OPTIONS:</strong> <pre>'.htmlspecialchars($form).'</pre>';
287
+
288
+                // Sign all <textarea /> elements
289
+                preg_match_all('%<textarea [^>]*name=([\'"])'.preg_quote($prefix).'(?![0-9]{1,3})(.+?)\1[^>]*>(.*?)</textarea>%is', $form, $textareas, PREG_SET_ORDER);
290
+                // echo "\n\nTextareas: ".print_r($textareas, true);
291
+                foreach ($textareas as $textarea) {
292
+                    $count['textareas']++;
293
+                    // Tackle implied "--OPEN--" first, if textarea is empty
294
+                    $textarea[3] = ($textarea[3] == '') ? '--OPEN--' : $textarea[3];
295
+                    $textarea_signed = preg_replace('%([\'"])'.preg_quote($prefix.$textarea[2]).'\1%', "$1".self::fc_hash_value($code, $textarea[2], $textarea[3], 'name', FALSE)."$1", $textarea[0]);
296
+                    $form = str_replace($textarea[0], $textarea_signed, $form);
297
+                    self::$log[] = '<strong>TEXTAREA:</strong> Code: <strong>'.htmlspecialchars($prefix.$code).
298
+                                    '</strong> :: Name: <strong>'.htmlspecialchars($prefix.$textarea[2]).
299
+                                    '</strong> :: Value: <strong>'.htmlspecialchars($textarea[3]).
300
+                                    '</strong><br />Initial textarea: '.htmlspecialchars($textarea[0]).
301
+                                    '<br />Signed: <span style="color:#060;">'.htmlspecialchars($textarea_signed).'</span>';
302
+                }
303
+                self::$log[] = '<strong>FORM after TEXTAREAS:</strong> <pre>'.htmlspecialchars($form).'</pre>';
304
+
305
+                // Exclude all <button> elements
306
+                $form = preg_replace('%<button ([^>]*)name=([\'"])(.*?)\1([^>]*>.*?</button>)%i', "<button $1name=$2x:$3$4", $form);
307
+
308
+            }
309
+            // Replace the entire form
310
+            self::$log[] = '<strong>FORM after ALL:</strong> <pre>'.htmlspecialchars($form).'</pre>'.'replacing <pre>'.htmlspecialchars($form_original).'</pre>';
311
+            $html = str_replace($form_original, $form, $html);
312
+            self::$log[] = '<strong>FORM end</strong><hr />';
313
+        }
314
+
315
+        // Return the signed output
316
+        $output = '';
317
+        if (self::$debug) {
318
+            self::$log['Summary'] = $count['links'].' links signed. '.$count['forms'].' forms signed. '.$count['inputs'].' inputs signed. '.$count['lists'].' lists signed. '.$count['textareas'].' textareas signed.';
319
+            $output .= '<h3>FoxyCart HMAC Debugging:</h3><ul>';
320
+            foreach (self::$log as $name => $value) {
321
+                $output .= '<li><strong>'.$name.':</strong> '.$value.'</li>';
322
+            }
323
+            $output .= '</ul><hr />';
324
+        }
325
+        return $output.$html;
326
+    }
327 327
 
328 328
 }
329 329
\ No newline at end of file
Please login to merge, or discard this patch.
tests/StoreSettingsTest.php 1 patch
Indentation   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -2,28 +2,28 @@
 block discarded – undo
2 2
 
3 3
 class StoreSettingsTest extends FS_Test{
4 4
 
5
-	protected static $use_draft_site = true;
5
+    protected static $use_draft_site = true;
6 6
 
7
-	function setUp(){
8
-		parent::setUp();
7
+    function setUp(){
8
+        parent::setUp();
9 9
 
10
-		$siteConf = SiteConfig::current_site_config();
11
-		$siteConf->StoreName = 'foxystripe';
10
+        $siteConf = SiteConfig::current_site_config();
11
+        $siteConf->StoreName = 'foxystripe';
12 12
         $siteConf->requireDefaultRecords();
13
-		$siteConf->write();
14
-	}
13
+        $siteConf->write();
14
+    }
15 15
 
16
-	function testStoreKey(){
17
-		$siteConf = SiteConfig::current_site_config();
16
+    function testStoreKey(){
17
+        $siteConf = SiteConfig::current_site_config();
18 18
 
19
-		$this->assertTrue(ctype_alnum($siteConf->StoreKey));
19
+        $this->assertTrue(ctype_alnum($siteConf->StoreKey));
20 20
         $this->assertEquals(strlen($siteConf->StoreKey), 60);
21
-	}
21
+    }
22 22
 
23
-	function testStoreName(){
24
-		$siteConf = SiteConfig::current_site_config();
23
+    function testStoreName(){
24
+        $siteConf = SiteConfig::current_site_config();
25 25
 
26 26
         $this->assertEquals($siteConf->StoreName, 'foxystripe');
27
-	}
27
+    }
28 28
 
29 29
 }
Please login to merge, or discard this patch.
code/model/FoxyCart.php 1 patch
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -19,14 +19,14 @@  discard block
 block discarded – undo
19 19
      */
20 20
     public static function setStoreKey($length = 54, $count = 0)
21 21
     {
22
-        $charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' . strtotime('now');
22
+        $charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.strtotime('now');
23 23
         $strLength = strlen($charset);
24 24
         $str = '';
25 25
         while ($count < $length) {
26 26
             $str .= $charset[mt_rand(0, $strLength - 1)];
27 27
             $count++;
28 28
         }
29
-        return static::get_key_prefix() . substr(base64_encode($str), 0, $length);
29
+        return static::get_key_prefix().substr(base64_encode($str), 0, $length);
30 30
     }
31 31
 
32 32
     /**
@@ -82,11 +82,11 @@  discard block
 block discarded – undo
82 82
     private static function getAPIRequest($foxyData = array())
83 83
     {
84 84
 
85
-        $foxy_domain = static::get_foxy_cart_store_name() . '.foxycart.com';
85
+        $foxy_domain = static::get_foxy_cart_store_name().'.foxycart.com';
86 86
         $foxyData["api_token"] = FoxyCart::get_store_key();
87 87
 
88 88
         $ch = curl_init();
89
-        curl_setopt($ch, CURLOPT_URL, "https://" . $foxy_domain . "/api");
89
+        curl_setopt($ch, CURLOPT_URL, "https://".$foxy_domain."/api");
90 90
         curl_setopt($ch, CURLOPT_POSTFIELDS, $foxyData);
91 91
         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
92 92
         curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
@@ -95,7 +95,7 @@  discard block
 block discarded – undo
95 95
 
96 96
         // The following if block will print any CURL errors you might have
97 97
         if ($response == false) {
98
-            SS_Log::log("Could not connect to FoxyCart API: " . $response, SS_Log::ERR);
98
+            SS_Log::log("Could not connect to FoxyCart API: ".$response, SS_Log::ERR);
99 99
         }
100 100
         curl_close($ch);
101 101
 
@@ -130,7 +130,7 @@  discard block
 block discarded – undo
130 130
     public static function putCustomer(Member $Member = null)
131 131
     {
132 132
         // throw error if no $Member Object
133
-        if (!isset($Member)) ;//trigger_error('No Member set', E_USER_ERROR);
133
+        if (!isset($Member)); //trigger_error('No Member set', E_USER_ERROR);
134 134
 
135 135
         // send updated customer record from API
136 136
         $foxyData = array();
Please login to merge, or discard this patch.