├── .github └── ISSUE_TEMPLATE ├── .gitignore ├── README.md ├── docs ├── .sidebar.json ├── README.md ├── developers │ ├── events-reference.md │ └── templating.md ├── feature-tour │ └── multi-add.md ├── get-started │ ├── installation-setup.md │ └── requirements.md └── support │ ├── credits.md │ └── get-support.md ├── multiadd ├── MultiAddPlugin.php ├── controllers │ └── MultiAddController.php ├── resources │ └── icon.svg ├── services │ └── MultiAdd_CartService.php ├── templates │ └── _settings.html └── variables │ └── MultiAddVariable.php └── releases.json /.github/ISSUE_TEMPLATE: -------------------------------------------------------------------------------- 1 | ### Description 2 | 3 | 4 | 5 | ### Steps to reproduce 6 | 7 | 1. 8 | 2. 9 | 10 | ### Additional info 11 | 12 | - Plugin version: 13 | - Craft version: -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # CRAFT ENVIRONMENT 2 | .env.php 3 | .env.sh 4 | .env 5 | 6 | # COMPOSER 7 | /vendor 8 | 9 | # BUILD FILES 10 | /bower_components/* 11 | /node_modules/* 12 | /build/* 13 | /yarn-error.log 14 | 15 | # MISC FILES 16 | .cache 17 | .DS_Store 18 | .idea 19 | .project 20 | .settings 21 | *.esproj 22 | *.sublime-workspace 23 | *.sublime-project 24 | *.tmproj 25 | *.tmproject 26 | .vscode/* 27 | !.vscode/settings.json 28 | !.vscode/tasks.json 29 | !.vscode/launch.json 30 | !.vscode/extensions.json 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > 2 | > ### Multi Add is for Craft 2 only, and will not make the migration to Craft 3. Mostly because you don't need it anymore! Read about it in our [blog post](https://verbb.io/blog/goodbye-multi-add). 3 | > 4 | 5 | # Multi Add Plugin for Craft CMS 6 | 7 | 8 | 9 | Provides an alternative controller to assist in adding multiple items to your Craft Commerce cart at once. 10 | 11 | Also provides some handy twig tags for adding items, removing a line item, and clearing the cart directly in your templates. 12 | 13 | ## Documentation 14 | 15 | Visit the [Multi Add Plugin page](https://verbb.io/craft-plugins/multi-add) for all documentation, guides, pricing and developer resources. 16 | 17 | ## Support 18 | 19 | Get in touch with us via the [Multi Add Support page](https://verbb.io/craft-plugins/multi-add/support) or by [creating a Github issue](/verbb/multi-add/issues) 20 | 21 |

22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/.sidebar.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "title": "Get Started", 4 | "collapsable": false, 5 | "children": [ 6 | "get-started/installation-setup", 7 | "get-started/requirements" 8 | ] 9 | }, 10 | { 11 | "title": "Feature Tour", 12 | "collapsable": false, 13 | "children": [ 14 | "feature-tour/multi-add" 15 | ] 16 | }, 17 | { 18 | "title": "Developers", 19 | "collapsable": false, 20 | "children": [ 21 | "developers/events-reference", 22 | "developers/templating" 23 | ] 24 | }, 25 | { 26 | "title": "Support", 27 | "collapsable": false, 28 | "children": [ 29 | "support/get-support", 30 | "support/credits" 31 | ] 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/verbb/multi-add/715000d6c8b9f5358ff9c2fdb70a9a3b98ee79c0/docs/README.md -------------------------------------------------------------------------------- /docs/developers/events-reference.md: -------------------------------------------------------------------------------- 1 | # Events Reference 2 | 3 | This plugin raises two events, much like normal the Commerce add to cart, which you can listen for in the same way. They are: 4 | 5 | `onBeforeMultiAddToCart` and `onMultiAddToCart` 6 | 7 | In each case the event parameters are: 8 | 9 | `order` (Commerce_OrderModel) `lineItems` (an array of Commerce_LineItemModel) 10 | 11 | ```php 12 | craft()->on('multiAdd_cart.onBeforeMultiAddToCart', function($event) { 13 | $order = $event->params['order']; 14 | $lineItems = $event->params['lineItems']; 15 | $event->performAction = false; 16 | }); 17 | ``` -------------------------------------------------------------------------------- /docs/developers/templating.md: -------------------------------------------------------------------------------- 1 | # Templating 2 | 3 | MultiAdd also provides a few extra useful twig tags that you can use to perform cart operations directly in your templates. 4 | 5 | Example - Setup: 6 | 7 | ```twig 8 | {% set cart = craft.commerce.cart %} 9 | {% set items = [] %} 10 | 11 | {% set items = items|merge([{"purchasableId":1385,"qty":1, "note":"Test note"}]) %} 12 | {% set items = items|merge([{"purchasableId":854,"qty":2, "options": {"colour":"green"} }]) %} 13 | ``` 14 | 15 | Items is an array, and now holds: 16 | 17 | ```php 18 | array(2) { 19 | [0]=> 20 | array(3) { 21 | ["purchasableId"]=> 22 | int(1385) 23 | ["qty"]=> 24 | int(1) 25 | ["note"]=> 26 | string(9) "Test note" 27 | } 28 | [1]=> 29 | array(3) { 30 | ["purchasableId"]=> 31 | int(854) 32 | ["qty"]=> 33 | int(2) 34 | ["options"]=> 35 | array(1) { 36 | ["colour"]=> 37 | string(9) "green" 38 | } 39 | } 40 | } 41 | ``` 42 | 43 | Example Twig Operations: 44 | 45 | ```twig 46 | # add items to cart 47 | {{ craft.multiAdd.multiAddToCart(cart, items) }} 48 | 49 | # remove the first line item 50 | {{ craft.multiAdd.removeLineItem(cart, cart.lineItems[0].id ) }} 51 | 52 | # clear the cart 53 | {{ craft.multiAdd.removeAllLineItems(cart) }} 54 | ``` -------------------------------------------------------------------------------- /docs/feature-tour/multi-add.md: -------------------------------------------------------------------------------- 1 | # Multi Add 2 | 3 | Provides an alternative controller to assist in adding multiple items to your Craft Commerce cart at once. 4 | 5 | Also provides some handy twig tags for adding items, removing a line item, and clearing the cart directly in your templates. 6 | 7 | ## Adding Multiple Items To Your Cart 8 | 9 | Use the following code in your product template to make use of this new controller. 10 | 11 | Notes: 12 | 13 | - The array _must_ be named `items` and you must supply at least a `purchasableId` and a `qty`. 14 | - Attributes are grouped together by a key in the form `items[key][attribute]` where key can be any value but must be the same for each of the attributes. `loop.index` is an obvious choice for this if iterative over products or variations in a loop. 15 | - You can also POST an optional `note` per line item 16 | - You can also POST arbitrary options, e.g. `[options][color]` 17 | - Items with a zero `qty` are simply skipped and not added to the cart. 18 | 19 | Here's some example code to get you started - if you get stuck, just ask on the Craft CMS Slack #craftcommerce channel for help. 20 | 21 | This code displays all your products in one form: 22 | 23 | ```twig 24 |
25 | 26 | 27 | {{ getCsrfInput() }} 28 | 29 | {% for product in craft.commerce.products.find() %} 30 | 31 | 32 | 33 | 34 | 39 | {% endfor %} 40 |
41 | ``` 42 | 43 | Or say you want to list the variants of a particular product out: 44 | 45 | ```twig 46 |
47 | 48 | 49 | {{ getCsrfInput() }} 50 | 51 | {% set product = craft.commerce.products.slug('your-product') %} 52 | 53 | {% for variant in product.variants %} 54 | 55 | 56 | 57 | {% endfor %} 58 |
59 | ``` 60 | 61 | Alternatively, submit via Ajax & get a JSON response, which (on success) includes a comprehensive cart object with all the data you should need. 62 | 63 | ```js 64 | $("#addToCart").submit(function(e) { 65 | e.preventDefault(); 66 | 67 | var data = $(this).serialize(); 68 | data[window.csrfTokenName] = window.csrfTokenValue; 69 | 70 | $.post('/actions/' + $('input[name=action]').val(), data, function(response) { 71 | if (response.success) { 72 | $("#addToCartButton").val("Added!"); 73 | cart.update( response.cart ); 74 | } else { 75 | $("#addToCartButton").val("Error!"); 76 | } 77 | }); 78 | }); 79 | ``` 80 | 81 | ## Updating Multiple Items In Your Cart 82 | 83 | When viewing your cart, it's currently not possible to update all your line items at once - instead it must be done for each line item as a separate event. This controller let's you update multiple line items at once. This might be desirable when a user has multiple line items in their cart, and wants to update quantities all at once by clicking an 'Update Cart' button. 84 | 85 | To achieve this, create your cart template using the following guide: 86 | 87 | ```twig 88 |
89 | 90 | 91 | {{ getCsrfInput() }} 92 | 93 | {% for item in cart.lineItems %} 94 | 95 | {% endfor %} 96 | 97 | 98 |
99 | ``` -------------------------------------------------------------------------------- /docs/get-started/installation-setup.md: -------------------------------------------------------------------------------- 1 | # Installation & Setup 2 | 3 | Installing Multi Add is as simple as any other Craft plugin - just drop the `multiadd` folder in your `craft/plugins` directory and install. 4 | 5 | ## Installation 6 | 7 | 1. [Download the latest version](/craft-plugins/multi-add/pricing) of Multi Add and unzip. 8 | 2. Copy the `multiadd/` directory into your `craft/plugins/` directory. 9 | 3. Inside the Craft control panel, navigate to _Settings → Plugins_. 10 | 4. Locate the row showing the Multi Add plugin and click _Install_. -------------------------------------------------------------------------------- /docs/get-started/requirements.md: -------------------------------------------------------------------------------- 1 | # Requirements 2 | 3 | ### Craft CMS 4 | 5 | Multi Add requires Craft CMS 2.6 or greater. 6 | 7 | ### Craft Commerce 8 | 9 | Multi Add requires Craft Commerce 1.2 or greater. 10 | 11 | ### PHP 12 | 13 | Multi Add requires PHP 5.4 or greater. -------------------------------------------------------------------------------- /docs/support/credits.md: -------------------------------------------------------------------------------- 1 | # Credits 2 | 3 | By [Verbb](https://verbb.io) and [Jeremy Daalder](https://github.com/bossanova808) (@jeremydaalder), with thanks to [Luke Holder](https://github.com/lukeholder) (@lukeholder). -------------------------------------------------------------------------------- /docs/support/get-support.md: -------------------------------------------------------------------------------- 1 | # Get Support 2 | 3 | ### Slack 4 | 5 | Get in touch via the [Craft Community Slack](https://buildwithcraft.com/community#slack) and be sure to post in the `#help` channel. Mention one of our team members on the following handles: 6 | 7 | - `@verbb` 8 | - `@crawf` 9 | 10 | ### GitHub 11 | 12 | If you've found a bug, or would like to make a feature request, head to the [GitHub Repo](https://github.com/verbb/multi-add/issues) and file an issue. Pull requests are also most welcome! 13 | 14 | ### Twitter 15 | 16 | Get our attention on Twitter by using the `#craftcms` hashtag and mentioning [@verbb\_io](https://twitter.com/verbb_io) 17 | 18 | [](https://twitter.com/verbb_io) 19 | 20 | ### Stack Exchange 21 | 22 | Ask a question via the [Craft Stack Exchange](http://craftcms.stackexchange.com/) and tag your question with `plugin-multiadd`. 23 | 24 | ### Email 25 | 26 | Any feedback, comments, questions or suggestions please email us at `support at verbb.io`. -------------------------------------------------------------------------------- /multiadd/MultiAddPlugin.php: -------------------------------------------------------------------------------- 1 | AttributeType::Bool, 66 | 'debugPOST' => AttributeType::Bool, 67 | ); 68 | } 69 | 70 | public function getSettingsHtml() 71 | { 72 | $settings = self::$settings; 73 | 74 | $variables = array( 75 | 'name' => $this->getName(), 76 | 'description' => $this->getDescription(), 77 | 'version' => $this->getVersion(), 78 | 'settings' => $settings, 79 | ); 80 | 81 | return craft()->templates->render('multiadd/_settings', $variables); 82 | } 83 | 84 | public function init() 85 | { 86 | self::$settings = $this->getSettings(); 87 | } 88 | 89 | 90 | // ========================================================================= 91 | // PLUGIN LOGGING 92 | // ========================================================================= 93 | 94 | public static function logError($msg) 95 | { 96 | MultiAddPlugin::log($msg, LogLevel::Error, $force = true); 97 | } 98 | 99 | public static function logWarning($msg) 100 | { 101 | MultiAddPlugin::log($msg, LogLevel::Warning, $force = true); 102 | } 103 | 104 | // If debugging is set to true in this plugin's settings, then log every message, devMode or not. 105 | public static function log($msg, $level = LogLevel::Profile, $force = false) 106 | { 107 | if (self::$settings['debug']) { 108 | $force = true; 109 | } 110 | 111 | if (is_string($msg)) { 112 | $msg = "\n\n" . $msg . "\n"; 113 | } else { 114 | $msg = "\n\n" . print_r($msg, true) . "\n"; 115 | } 116 | 117 | parent::log($msg, $level, $force); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /multiadd/controllers/MultiAddController.php: -------------------------------------------------------------------------------- 1 | request->isAjaxRequest(); 19 | 20 | // Get plugin settings 21 | $settings = craft()->plugins->getPlugin('multiAdd')->getSettings(); 22 | 23 | // Settings to control behavour when testing - we don't want to debug via ajax or it stuffs up the JSON response... 24 | $debug = ($settings->debugPOST and !$ajax); 25 | 26 | // Store items added to the cart in case of later failure & rollback required 27 | $rollback = array(); 28 | 29 | // Require POST request & set up error handling 30 | $this->requirePostRequest(); 31 | $errors = array(); 32 | 33 | // Get the cart & form data 34 | $cart = craft()->commerce_cart->getCart(); 35 | $items = craft()->request->getPost('items'); 36 | 37 | // Some crude debugging support 38 | if ($debug) { 39 | echo '

Items

';
 40 |             print_r($items);
 41 |             echo '
'; 42 | } 43 | 44 | if (!isset($items)) { 45 | $errors[] = "No items to add."; 46 | } else { 47 | $itemsToProcess = false; 48 | 49 | // Prevent submission of all 0 qtys 50 | foreach ($items as $key => $item) { 51 | $qty = isset($item['qty']) ? (int)$item['qty'] : 0; 52 | 53 | if ($qty >0){ 54 | $itemsToProcess = true; 55 | break; 56 | } 57 | } 58 | 59 | if (!$itemsToProcess) { 60 | $errors[] = "All items have 0 quantity."; 61 | } 62 | } 63 | 64 | // Do some cart-adding using our new, faster, rollback-able service 65 | if (!$errors) { 66 | $error = ""; 67 | 68 | if (!craft()->multiAdd_cart->multiAddToCart($cart, $items, $error)) { 69 | $errors[] = $error; 70 | } 71 | } 72 | 73 | if ($errors) { 74 | // Try to log referrer in case of misadventure - might help track down odd errors 75 | MultiAddPlugin::logError(craft()->request->getUrlReferrer()); 76 | 77 | foreach ($errors as $error) { 78 | MultiAddPlugin::logError($error); 79 | } 80 | 81 | craft()->urlManager->setRouteVariables(['error' => $errors]); 82 | } else { 83 | craft()->userSession->setFlash('notice', 'Products have been added to cart'); 84 | 85 | // Only redirect if we're not debugging and we haven't submitted by ajax 86 | if (!$debug and !$ajax) { 87 | $this->redirectToPostedUrl(); 88 | } 89 | } 90 | 91 | // Appropriate Ajax responses... 92 | if ($ajax) { 93 | if ($errors) { 94 | $this->returnErrorJson($errors); 95 | } else { 96 | $this->returnJson(['success' => true, 'cart' => $this->cartArray($cart)]); 97 | } 98 | } 99 | 100 | // Not AJAX? We're done! 101 | } 102 | 103 | public function actionUpdateCart() 104 | { 105 | $this->requirePostRequest(); 106 | $cart = craft()->commerce_cart->getCart(); 107 | 108 | $errors = array(); 109 | $items = craft()->request->getPost('items'); 110 | 111 | foreach ($items as $lineItemId => $item) { 112 | $lineItem = craft()->commerce_lineItems->getLineItemById($lineItemId); 113 | 114 | // Fail silently if its not their line item or it doesn't exist. 115 | if (!$lineItem || !$lineItem->id || ($cart->id != $lineItem->orderId)) { 116 | return true; 117 | } 118 | 119 | $lineItem->qty = $item['qty']; 120 | 121 | if (isset($item['options'])) { 122 | ksort($item['options']); 123 | $lineItem->options = $item['options']; 124 | $lineItem->optionsSignature = md5(json_encode($item['options'])); 125 | } 126 | 127 | if (!craft()->commerce_lineItems->updateLineItem($cart, $lineItem, $error)) { 128 | $errors[] = $error; 129 | } 130 | } 131 | 132 | // Set Coupon on Cart 133 | $couponCode = craft()->request->getPost('couponCode'); 134 | 135 | if ($couponCode) { 136 | if (!craft()->commerce_cart->applyCoupon($cart, $couponCode, $error)) { 137 | $errors[] = $error; 138 | } 139 | } 140 | 141 | if ($errors) { 142 | craft()->userSession->setError(Craft::t('Couldn’t update line item: {message}', [ 143 | 'message' => $error 144 | ])); 145 | 146 | MultiAddPlugin::logError('Couldn’t update line item: [$error]'); 147 | } else { 148 | craft()->userSession->setNotice(Craft::t('Items updated.')); 149 | $this->redirectToPostedUrl(); 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /multiadd/resources/icon.svg: -------------------------------------------------------------------------------- 1 | iconLayer 1Layer 1 -------------------------------------------------------------------------------- /multiadd/services/MultiAdd_CartService.php: -------------------------------------------------------------------------------- 1 | db->getCurrentTransaction() === null ? craft()->db->beginTransaction() : null; 24 | 25 | // Saving current cart if it's new and empty 26 | if (!$order->id) { 27 | if (!craft()->commerce_orders->saveOrder($order)) { 28 | if ($transaction !== null) 29 | { 30 | $transaction->rollback(); 31 | } 32 | $error = Craft::t('Error on creating empty cart: ') . print_r($order->getAllErrors(), true); 33 | MultiAddPlugin::logError($error); 34 | throw new Exception($error); 35 | } 36 | } 37 | 38 | // Now loop through all our items and attempt to add them if any one fails, the whole thing fails 39 | $lineItems = []; 40 | 41 | foreach ($items as $key => $item) { 42 | $qty = isset($item['qty']) ? (int)$item['qty'] : 0; 43 | 44 | // Save time by only dealing with items we're actually trying to add 45 | if ($qty > 0) { 46 | 47 | $purchasableId = $item['purchasableId']; 48 | $note = isset($item['note']) ? $item['note'] : ""; 49 | $error = ""; 50 | 51 | // The following line means you can pass arbitrary options like this: items[0][options][note] 52 | $options = isset($item['options']) ? $item['options'] : []; 53 | 54 | // Filling item model 55 | $lineItem = craft()->commerce_lineItems->getLineItemByOrderPurchasableOptions($order->id, $purchasableId, $options); 56 | 57 | if ($lineItem) { 58 | foreach ($order->getLineItems() as $item) { 59 | if ($item->id == $lineItem->id) { 60 | $lineItem = $item; 61 | } 62 | } 63 | 64 | $lineItem->qty += $qty; 65 | } 66 | else { 67 | $lineItem = craft()->commerce_lineItems->createLineItem($purchasableId, $order, $options, $qty); 68 | } 69 | 70 | if ($note) { 71 | $lineItem->note = $note; 72 | } 73 | 74 | $lineItems[] = $lineItem; 75 | } 76 | } 77 | 78 | // Be bold, be brave, assume success...! 79 | $success = true; 80 | 81 | // Raising event 82 | $event = new Event($this, [ 83 | 'lineItems' => $lineItems, 84 | 'order' => $order, 85 | ]); 86 | $this->onBeforeMultiAddToCart($event); 87 | 88 | if (!$event->performAction) { 89 | $success = false; 90 | } 91 | else { 92 | foreach ($lineItems as $lineItem) { 93 | $lineItem->validate(); 94 | $lineItem->purchasable->validateLineItem($lineItem); 95 | 96 | if (!$lineItem->hasErrors()) { 97 | if (!craft()->commerce_lineItems->saveLineItem($lineItem)) { 98 | MultiAddPlugin::logError('Error when saving lineItem: ' . print_r($lineItem->getAllErrors(), true)); 99 | $success = false; 100 | $errors = $lineItem->getAllErrors(); 101 | break; 102 | } 103 | } 104 | else { 105 | MultiAddPlugin::logError('lineItem failed vaildation: ' . print_r($lineItem->getAllErrors(), true)); 106 | $success = false; 107 | $errors = $lineItem->getAllErrors(); 108 | break; 109 | } 110 | 111 | } 112 | } 113 | 114 | if ($success) { 115 | $orderSaveSuccess = craft()->commerce_orders->saveOrder($order); 116 | 117 | if ($orderSaveSuccess) { 118 | if ($transaction !== null) 119 | { 120 | $transaction->commit(); 121 | } 122 | } 123 | else { 124 | MultiAddPlugin::logError('Error when saving order: ' . print_r($order->getAllErrors(), true)); 125 | 126 | $errors = $order->getErrors(); 127 | $error = array_pop($errors); 128 | 129 | if ($transaction !== null) 130 | { 131 | $transaction->rollback(); 132 | } 133 | 134 | return false; 135 | } 136 | 137 | // Raising event 138 | $event = new Event($this, [ 139 | 'lineItems' => $lineItems, 140 | 'order' => $order, 141 | ]); 142 | $this->onMultiAddToCart($event); 143 | 144 | return true; 145 | } 146 | else { 147 | 148 | if ($transaction !== null) 149 | { 150 | $transaction->rollback(); 151 | } 152 | 153 | $errors = $lineItem->getAllErrors(); 154 | $error = array_pop($errors); 155 | 156 | return false; 157 | } 158 | } 159 | 160 | 161 | // Event Handlers 162 | // ========================================================================= 163 | 164 | /** 165 | * Before Event 166 | * Event params: order(Commerce_OrderModel), lineItems (array of Commerce_LineItemModel) 167 | * 168 | * @param \CEvent $event 169 | * 170 | * @throws \CException 171 | */ 172 | public function onBeforeMultiAddToCart(\CEvent $event) 173 | { 174 | $params = $event->params; 175 | 176 | if (empty($params['order']) || !($params['order'] instanceof Commerce_OrderModel)) { 177 | throw new Exception('onBeforeMultiAddToCart event requires "order" param with OrderModel instance'); 178 | } 179 | 180 | if (empty($params['lineItems'])) { 181 | throw new Exception('onBeforeMultiAddToCart event requires "lineItems" param with array of LineItemModel instances'); 182 | } 183 | 184 | $this->raiseEvent('onBeforeMultiAddToCart', $event); 185 | } 186 | 187 | /** 188 | * Event method. 189 | * Event params: order(Commerce_OrderModel), lineItems (array of Commerce_LineItemModel) 190 | * 191 | * @param \CEvent $event 192 | * 193 | * @throws \CException 194 | */ 195 | public function onMultiAddToCart(\CEvent $event) 196 | { 197 | $params = $event->params; 198 | 199 | if (empty($params['order']) || !($params['order'] instanceof Commerce_OrderModel)) { 200 | throw new Exception('onMultiAddToCart event requires "order" param with OrderModel instance'); 201 | } 202 | 203 | if (empty($params['lineItems'])) { 204 | throw new Exception('onMultiAddToCart event requires "lineItems" param with array of LineItemModel instances'); 205 | } 206 | 207 | $this->raiseEvent('onMultiAddToCart', $event); 208 | } 209 | 210 | } 211 | -------------------------------------------------------------------------------- /multiadd/templates/_settings.html: -------------------------------------------------------------------------------- 1 | {% import "_includes/forms" as forms %} 2 | 3 | {% block content %} 4 | 5 |
6 |

{{ 'Version: {version}' | t({ version: version }) }}

7 |

{{ description }}

8 |
9 | 10 |
11 |

{{ 'Debugging?' | t }}

12 | 13 | {{ forms.lightswitch({ 14 | onLabel: "On", 15 | offLabel: "Off", 16 | name: "debug", 17 | on: settings.debug, 18 | }) }} 19 | 20 |

Makes all log messages get logged.

21 |

(LogLevel::Warning and LogLevel::Error are always logged).

22 | 23 |
24 | 25 |

{{ 'Debug POST?' | t }}

26 | 27 | {{ forms.lightswitch({ 28 | onLabel: "On", 29 | offLabel: "Off", 30 | name: "debugPOST", 31 | on: settings.debugPOST, 32 | }) }} 33 | 34 |

{{ "Dumps the POST data back to the page & prevents redirects, so you can see if your form is submitting the correct data. (This setting is ignored if you're submitting by ajax - use your developer console to check that!)" | t }}

35 | 36 |
37 | {% endblock %} 38 | -------------------------------------------------------------------------------- /multiadd/variables/MultiAddVariable.php: -------------------------------------------------------------------------------- 1 | multiAdd_cart->multiAddToCart($cart, $items, $error); 17 | } 18 | 19 | if($error){ 20 | return $error; 21 | } 22 | else { 23 | return "Items added to cart"; 24 | } 25 | 26 | } 27 | 28 | public function removeAllLineItems($cart){ 29 | 30 | craft()->commerce_cart->clearCart($cart); 31 | 32 | } 33 | 34 | public function removeLineItem($cart, $lineItemId){ 35 | 36 | craft()->commerce_cart->removeFromCart($cart, $lineItemId); 37 | 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /releases.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "version": "0.2.1", 4 | "downloadUrl": "https://github.com/engram-design/MultiAdd/archive/0.2.1.zip", 5 | "date": "2017-10-18T00:00:00+10:00", 6 | "notes": [ 7 | "[Added] Verbb marketing (new plugin icon, readme, etc).", 8 | "[Added] Added coupon support to actionUpdateCart method.", 9 | "[Improved] `actionUpdateCart` - check for found lineItem before adjusting qty. Can produce `Creating default object from empty value` error.", 10 | "[Improved] Update for latest Commerce which deprecates CommerceDbHelper.", 11 | "[Improved] Update Cart Action - allow options to be updated." 12 | ] 13 | }, 14 | { 15 | "version": "0.1.9", 16 | "downloadUrl": "https://github.com/engram-design/MultiAdd/archive/0.1.9.zip", 17 | "date": "2016-10-21T11:17:28+10:00", 18 | "notes": [ 19 | "[Added] Twig tags for adding item(s) to cart, removing a line item, and clearing the cart", 20 | ] 21 | }, 22 | { 23 | "version": "0.1.8", 24 | "downloadUrl": "https://github.com/engram-design/MultiAdd/archive/0.1.8.zip", 25 | "date": "2016-08-24T11:17:28+10:00", 26 | "notes": [ 27 | "[Fixed] Better logging support", 28 | ] 29 | }, 30 | { 31 | "version": "0.1.7", 32 | "downloadUrl": "https://github.com/engram-design/MultiAdd/archive/0.1.7.zip", 33 | "date": "2016-08-24T11:17:28+10:00", 34 | "notes": [ 35 | "[Fixed] Added more logging/rollback of transactions if various errors occur - help with possible rare race condition?", 36 | "[Added] Debugging swtich now controls log of all log messages, debug POST offers previous debugging behaviour" 37 | ] 38 | }, 39 | { 40 | "version": "0.1.6", 41 | "downloadUrl": "https://github.com/engram-design/MultiAdd/archive/0.1.6.zip", 42 | "date": "2016-08-16T11:17:28+10:00", 43 | "notes": [ 44 | "[Added] updateCart endpoint to update multiple line items in one go, e.g. via na Update Cart button", 45 | "[Fixed] fix for missing descriptions variable in plugin settings" 46 | ] 47 | }, 48 | { 49 | "version": "0.1.5", 50 | "downloadUrl": "https://github.com/engram-design/MultiAdd/archive/0.1.5.zip", 51 | "date": "2016-04-27T11:17:28+10:00", 52 | "notes": [ 53 | "[Fixed] Fix releases.json so no errors in Craft Logs" 54 | ] 55 | }, 56 | { 57 | "version": "0.1.4", 58 | "downloadUrl": "https://github.com/engram-design/MultiAdd/archive/0.1.4.zip", 59 | "date": "2016-04-27T11:17:28+10:00", 60 | "notes": [ 61 | "[Fixed] Fix for error reporting" 62 | ] 63 | }, 64 | { 65 | "version": "0.1.3", 66 | "downloadUrl": "https://github.com/engram-design/MultiAdd/archive/0.1.3.zip", 67 | "date": "2016-04-27T11:17:28+10:00", 68 | "notes": [ 69 | "[Fixed] Updates for addToCart changes in Commerce 1.1.1207" 70 | ] 71 | }, 72 | { 73 | "version": "0.1.0", 74 | "downloadUrl": "https://github.com/engram-design/MultiAdd/archive/0.1.0.zip", 75 | "date": "2016-04-27T11:17:28+10:00", 76 | "notes": [ 77 | "[Improved] Error Handling" 78 | ] 79 | }, 80 | { 81 | "version": "0.0.9", 82 | "downloadUrl": "https://github.com/engram-design/MultiAdd/archive/0.0.9.zip", 83 | "date": "2016-04-26T11:17:28+10:00", 84 | "notes": [ 85 | "[Added] Add releases.json for updates" 86 | ] 87 | } 88 | ] 89 | --------------------------------------------------------------------------------