Appearance
Hooks
The hooks below are for your own add-on: to react to the cart, the checkout, payments and orders, to add variables to the checkout or sections and actions to the order page in the CP. The shipping hooks are mainly used by the Store add-ons themselves (Store Shipping, Store Pickup, Store MyParcel and Store Tax). The Store has a few more hooks for the tax and the price rules that are only used by those add-ons and can change without notice, so they are not listed here.
Using the hooks in your own add-on
The Store calls a hook with ee()->extensions->call(), so the rules of ExpressionEngine extensions apply. Store Shipping, Store MyParcel, Store Pickup, Store Tax, Store Price Rule and Store Email use the same hooks, keep these rules so your add-on works together with them:
- Pass on the result of the previous extension. When more than one add-on uses a hook (e.g.
reinos_store_view_order_actions,reinos_store_gateway_listorreinos_store_is_shipped), every extension gets the result of the previous one inee()->extensions->last_call(falsefor the first one). Start from it and return it unchanged for a cart or an order that isn't yours, otherwise you overwrite the result of the other add-on. - Set a priority when the order matters. Extensions with the same priority (EE's default is 10) run in the order of their class name. Set
'priority'in$methodsof your installer when your add-on has to run before or after another one. - Return what the Store expects. Most hooks return the (changed) first argument, a hook that the Store doesn't use the result of may return anything. When in doubt, return
last_call. - Escape your own values. The
titleandcontentof a section of thereinos_store_view_order_1/2/3hooks are shown as HTML (so you can add a logo or a table), escape the values you put in them. Theedit_urlandexternal_urlare escaped by the Store.
Store services for add-ons
Next to the hooks, an add-on can use these methods of the Store:
storeServiceSettings()->save_store_settings($keys): save the posted Store settings of your own settings page (e.g.['tax_type', 'tax_default_rate']). Only the given keys are saved, and only when they are a Store setting and posted. From v4.0.0storeServiceSettings()->save_setting($key, $value, $siteId): save one Store setting, for the current site or for the given site (MSM,$siteIdfrom v4.0.0). A setting that doesn't exist yet for that site is added.storeServiceWeight()->unit(),->toGrams($weight)and->convert($weight, $fromUnit): the Weight unit setting (kg,gorlbs), a weight in that unit in whole grams, and a weight in another unit converted to that unit. From v4.0.0storeServiceStatus()->isShipped($order): whether an order is shipped, see reinos_store_is_shipped. From v4.0.0storeServiceEmail()->isSuppressed():truewhile an order is made with Create order in the CP. The hooks of the new order can change it (e.g. Store MyParcel sets the shipping status), an email add-on doesn't send on those changes then: the CP calls reinos_store_resend_confirmation_mail or reinos_store_manual_order_no_email when the order is done. From v4.0.0storeServiceDiscount()->setCouponCodeError($error): tell the customer why the coupon code gives no discount (invalidorused), for an add-on that checks its own codes and removes a code from the cart. It is shown as{cart:coupon_code_error}in the same request. Thereinos_store_price_rule_save_coupon_codehook can return['valid' => false, 'error' => 'used']for the same message on the next page. From v4.0.0storeServiceCart()->cartHasEntryIds($entryIds): whether the cart of the visitor holds one of the given entry ids (an id or an array of ids).storeServiceCart()->cartQuantity(): the total quantity of the items in the cart of the visitor.storeServiceCart()->cartTotal(): the total of the items in the cart of the visitor, price times quantity, excluding tax and before discounts and shipping.These three read the database directly, which is faster than calculating the cart. They count every cart item, also e.g. the free items of a Store Price Rule Buy X Get Y rule.
cartHasEntryIds()always returnstrueorfalse. Without a cartcartQuantity()andcartTotal()return0, for a saved cart without itemsnull.
Cart hooks
reinos_store_cart_item_add_start
Added in 3.1.0
Called before a product is added to the cart. $values are the values of the new cart item, $existingItems the cart items of the same product that are already in the cart (a collection, empty when there are none). Return a non-empty string to stop adding the product: the product is then not added to the cart.
if (ee()->extensions->active_hook('reinos_store_cart_item_add_start') === TRUE)
{
$error = ee()->extensions->call('reinos_store_cart_item_add_start', $values, $existingItems);
}reinos_store_cart_item_add_end
Added in 3.1.0
if (ee()->extensions->active_hook('reinos_store_cart_item_add_end') === TRUE)
{
ee()->extensions->call('reinos_store_cart_item_add_end', $values, $cartItem);
}reinos_store_cart_item_update_start
Added in 3.1.0
Called when a cart item is updated, also when it is removed: a quantity of 0 in the cart and, from v4.0.0, the delete_cart_item tag ($values is then ['qty' => 0]).
if (ee()->extensions->active_hook('reinos_store_cart_item_update_start') === TRUE)
{
ee()->extensions->call('reinos_store_cart_item_update_start', $values, $cartItem);
}reinos_store_cart_item_update_end
Added in 3.1.0
if (ee()->extensions->active_hook('reinos_store_cart_item_update_end') === TRUE)
{
ee()->extensions->call('reinos_store_cart_item_update_end', $values, $cartItem);
}reinos_store_cart_clear_items_start
Added in 3.1.0
if (ee()->extensions->active_hook('reinos_store_cart_clear_items_start') === TRUE)
{
ee()->extensions->call('reinos_store_cart_clear_items_start', $cartItems);
}reinos_store_cart_clear_items_end
Added in 3.1.0
if (ee()->extensions->active_hook('reinos_store_cart_clear_items_end') === TRUE)
{
ee()->extensions->call('reinos_store_cart_clear_items_end');
}reinos_store_add_to_cart
Called after a product is added to the cart with the add_to_cart form, with the cart service. Not called when the product is out of stock.
if (ee()->extensions->active_hook('reinos_store_add_to_cart') === TRUE)
{
ee()->extensions->call('reinos_store_add_to_cart', $cart);
}reinos_store_update_cart
Called after the cart items are updated (or the cart is cleared) with the update form of the cart tag, before the customer is redirected, with the cart service.
if (ee()->extensions->active_hook('reinos_store_update_cart') === TRUE)
{
ee()->extensions->call('reinos_store_update_cart', $cart);
}Checkout hooks
reinos_store_checkout_start
Added in 3.1.0
if (ee()->extensions->active_hook('reinos_store_checkout_start') === TRUE)
{
ee()->extensions->call('reinos_store_checkout_start');
}reinos_store_checkout_before_validation
Called when the checkout is posted, before the final check of the errors and before the order is created. $checkout is the checkout service. Add your own validation here: an error you add to $checkout->errors (e.g. $checkout->errors['my_field'] = 'My field is required') stops the checkout and is shown like the other checkout errors.
if (ee()->extensions->active_hook('reinos_store_checkout_before_validation') === TRUE)
{
ee()->extensions->call('reinos_store_checkout_before_validation', $checkout);
}reinos_store_checkout_after_validation
Called when the checkout has no errors, right before the order is created. $checkout is the checkout service. Errors added here are not checked anymore, use reinos_store_checkout_before_validation for validation.
if (ee()->extensions->active_hook('reinos_store_checkout_after_validation') === TRUE)
{
ee()->extensions->call('reinos_store_checkout_after_validation', $checkout);
}reinos_store_validate_address
Available from v4.0.0
Called when an address is validated, e.g. by the checkout with Validate addresses on. $errors are the errors per field (address, city, zip, state) as an error code, e.g. ['zip' => 'invalid_zip'], $address the fields without prefix and the country. Return the errors, with your own added or removed. The checkout shows the language line reinos_store_<code> of an error code when it exists, otherwise the returned text itself, e.g. ['address' => 'This address is not known at the postal service'].
if (ee()->extensions->active_hook('reinos_store_validate_address') === TRUE)
{
$errors = ee()->extensions->call('reinos_store_validate_address', $errors, $address);
}Add-ons can use the service themselves as well: storeServiceAddress()->validate($address), storeServiceAddress()->normalizePostalCode($zip, $country) and storeServiceAddress()->zipExample($country).
reinos_store_validate_phone
Available from v4.0.0
Called when a phone number is validated, e.g. by the checkout with Validate phone numbers on. $error is invalid_phone, or null when the number is valid or can't be checked (a number without a calling code for a country that is not known), $number the number as it was entered and $country the country it is read for. Return the error as a string (an error code or a message, see reinos_store_validate_address), or an empty string '' when the number is fine. Any other value (null, false or nothing) keeps the result of the Store.
if (ee()->extensions->active_hook('reinos_store_validate_phone') === TRUE)
{
$error = ee()->extensions->call('reinos_store_validate_phone', $error, $number, $country);
}Add-ons can use the service themselves as well: storeServicePhone()->validate($number, $country), storeServicePhone()->normalize($number, $country) (E.164) and storeServicePhone()->example($country).
reinos_store_checkout_tag_variables
Add or change the variables of the checkout tag. Return the (changed) array of variables.
if (ee()->extensions->active_hook('reinos_store_checkout_tag_variables') === TRUE)
{
$variables = ee()->extensions->call('reinos_store_checkout_tag_variables', $variables);
}reinos_store_checkout_end
Called once, when the order becomes complete. From 4.0.0 this can also happen in the webhook (notify) request of the payment provider, when the webhook arrives before the customer returns. That request has no session of the customer, so don't rely on the cart, cookies or the logged-in member in this hook.
It is also called for an order of the Manual gateway when it is placed (it gets the Status of a new order of the Manual gateway, pending by default, and is not paid), and for an order made with Create order in the CP. Check $order->status or $order->is_paid when you only want paid orders.
Added in 3.1.0
if (ee()->extensions->active_hook('reinos_store_checkout_end') === TRUE)
{
ee()->extensions->call('reinos_store_checkout_end', $order);
}reinos_store_finish_order
Called when the customer is sent to the order page of a placed order: after a payment that completed the order (on the customer's return or on the checkout itself, e.g. Stripe on-site), for an order with nothing to pay, and for every order of the manual gateway. It is not called by the webhook of the payment provider.
Added in 3.4.0
if (ee()->extensions->active_hook('reinos_store_finish_order') === TRUE)
{
ee()->extensions->call('reinos_store_finish_order', $order);
}Inventory hooks
reinos_store_inventory_update
Added in 3.1.0
if (ee()->extensions->active_hook('reinos_store_inventory_update') === TRUE)
{
ee()->extensions->call('reinos_store_inventory_update', $orderItem, $oldInventory, $newInventory);
}Payment hooks
reinos_store_payment_start
Added in 3.1.0
if (ee()->extensions->active_hook('reinos_store_payment_start') === TRUE)
{
ee()->extensions->call('reinos_store_payment_start', $order, $gateway);
}reinos_store_payment_end
Called once, when the order becomes complete. From 4.0.0 this can also happen in the webhook (notify) request of the payment provider, when the webhook arrives before the customer returns. That request has no session of the customer, so don't rely on the cart, cookies or the logged-in member in this hook.
It is also called for an order of the Manual gateway when it is placed (it gets the Status of a new order of the Manual gateway, pending by default, and is not paid), and for an order made with Create order in the CP. Check $order->status or $order->is_paid when you only want paid orders.
Added in 3.1.0
if (ee()->extensions->active_hook('reinos_store_payment_end') === TRUE)
{
ee()->extensions->call('reinos_store_payment_end', $order, $gateway);
}Shipping hooks
These hooks are used by Store Shipping, Store MyParcel and Store Pickup. More than one add-on can listen to the same hook: read ee()->extensions->last_call and build on it (e.g. add your methods to the list of the add-on before you) instead of replacing it.
reinos_store_shipping_options
Return the shipping methods the customer can choose from, an array of methods with the keys name (the value that is posted as shipping_method), title, selected, price, price:formatted, price_plus_tax and price_plus_tax:formatted. The shipping of the Store itself (native) is added after it when Store Shipping and Store MyParcel are not installed and Ship orders is on.
if (ee()->extensions->active_hook('reinos_store_shipping_options') === TRUE)
{
$shippingMethods = ee()->extensions->call('reinos_store_shipping_options');
}reinos_store_manual_order_shipping_options
Return the shipping methods for an order made with Create order in the CP, added to the methods of the previous extensions on this hook (ee()->extensions->last_call). The CP has no cart, so $context holds the order of the form: country, state, zip and city of the shipping address, weight (the total weight), quantity, entry_ids, items (per line entry_id, qty and weight), subtotal, subtotal_plus_tax and site_id. A method is an array with name (saved as the shipping method of the order), title (shown in the list), carrier (saved as the carrier of the order, the title when it is not given) and price (as entered: including tax with the Tax type inclusive, like reinos_store_calculate_shipping). A method without a name or a numeric price is skipped. When the subtotal (excl. tax) is above Free shipping above, the Store sets the price of every method to 0. The shipping of the Store itself (native) is added before it when Store Shipping and Store MyParcel are not installed and Ship orders is on. The hook is called for every live calculation of the form (e.g. when the address or the products change) and when the order is saved.
Added in 4.0.0
if (ee()->extensions->active_hook('reinos_store_manual_order_shipping_options') === TRUE)
{
$shippingMethods = ee()->extensions->call('reinos_store_manual_order_shipping_options', $context);
}reinos_store_calculate_shipping
Return the shipping costs (as entered: including tax with the Tax type inclusive) of the chosen method $shippingMethod when it is not native. The Store calculates the tax with the shipping tax rate.
if (ee()->extensions->active_hook('reinos_store_calculate_shipping') === TRUE)
{
$shippingCosts = ee()->extensions->call('reinos_store_calculate_shipping', $shippingMethod);
}reinos_store_checkout_validate_shipping
Called in the checkout after the shipping method is chosen. Return 'no_shipping_method_selected' to refuse the checkout with {global_error:shipping_method_missing}, or an array with shipping_carrier and shipping_method, which are saved on the order.
if (ee()->extensions->active_hook('reinos_store_checkout_validate_shipping') === TRUE)
{
$result = ee()->extensions->call('reinos_store_checkout_validate_shipping', $checkout);
}reinos_store_checkout_before_check_gateway
Called before the checkout checks the chosen payment method. Return the name of a gateway to use that one instead (e.g. Store Pickup's pay at the location), anything else keeps the chosen gateway.
if (ee()->extensions->active_hook('reinos_store_checkout_before_check_gateway') === TRUE)
{
$gateway = ee()->extensions->call('reinos_store_checkout_before_check_gateway', $gateway, $shippingMethod);
}reinos_store_save_cart_details
Called after the checkout saved the customer and address fields on the cart. $cart is the cart service, $cart->cart the cart model.
if (ee()->extensions->active_hook('reinos_store_save_cart_details') === TRUE)
{
ee()->extensions->call('reinos_store_save_cart_details', $cart);
}reinos_store_shipping_tax_calculation
Return the tax rate (a number, also 0) for the shipping costs, e.g. the rate of a tax rule of Store Tax. $source is the cart or the order the shipping is for (null for the current cart). Without a number the Shipping TAX percentage setting is used.
if (ee()->extensions->active_hook('reinos_store_shipping_tax_calculation') === TRUE)
{
$rate = ee()->extensions->call('reinos_store_shipping_tax_calculation', $billingCountry, $customerCompany, $source);
}Order hooks
reinos_store_status_update
Added in 3.1.0
if (ee()->extensions->active_hook('reinos_store_status_update') === TRUE)
{
ee()->extensions->call('reinos_store_status_update', $order, $oldStatus);
}Called after the status of the order changed. $order->status is the new status, $oldStatus the status before the change.
reinos_store_shipping_status_update
Added in 3.8.0
if (ee()->extensions->active_hook('reinos_store_shipping_status_update') === TRUE)
{
ee()->extensions->call('reinos_store_shipping_status_update', $order, $oldShippingStatus);
}$order->shipping_status is the new shipping status, $oldShippingStatus the one before the change.
reinos_store_order_created
Added in 3.9.4
Called once for every new order (once from v4.0.0, before a checkout order called it twice), right after it is saved: by the checkout and Create order in the CP. $orderId is the ID of the new order. The order items are not saved yet at this point. You can change and save the order in the hook.
if (ee()->extensions->active_hook('reinos_store_order_created') === TRUE)
{
ee()->extensions->call('reinos_store_order_created', $order, $orderId);
}reinos_store_order_updated
Added in 3.9.4
if (ee()->extensions->active_hook('reinos_store_order_updated') === TRUE)
{
ee()->extensions->call('reinos_store_order_updated', $order, $updatedFields);
}Called after an existing order is saved. $updatedFields holds the fields that changed, with their previous values (e.g. ['status' => 'open']); the new values are on $order.
reinos_store_order_deleted
Added in 3.9.4
if (ee()->extensions->active_hook('reinos_store_order_deleted') === TRUE)
{
ee()->extensions->call('reinos_store_order_deleted', $order);
}reinos_store_is_paid_update
Added in 3.8.0
if (ee()->extensions->active_hook('reinos_store_is_paid_update') === TRUE)
{
ee()->extensions->call('reinos_store_is_paid_update', $order, $oldIsPaid);
}$order->is_paid is the new value, $oldIsPaid the value before the change.
reinos_store_format_shipping_status
Available from v4.0.0 (the $format argument)
Return your own label for the shipping status of an order, e.g. for a shipping status your add-on sets. Return ee()->extensions->last_call for an order that is not yours, so the label of another add-on (or the default label) is kept. $format is html for the status badge in the CP, where you can return HTML, or text for {order:shipping_status} in templates and emails. The Store removes any HTML from a text result. Use text as the default of the argument, older Store versions don't pass it.
if (ee()->extensions->active_hook('reinos_store_format_shipping_status') === TRUE)
{
$label = ee()->extensions->call('reinos_store_format_shipping_status', $order, $format);
}reinos_store_is_shipped
Available from v4.0.0
Decide whether an order is shipped for the shipping statuses of your add-on, e.g. used by {order:is_shipped} and the "Is Shipped" trigger of Store Email. $isShipped is the answer of the Store (true for shipped and parcel shipped). Return true or false for an order with one of your statuses. For any other order return ee()->extensions->last_call, or $isShipped when last_call is false (you are the first extension).
if (ee()->extensions->active_hook('reinos_store_is_shipped') === TRUE)
{
$isShipped = ee()->extensions->call('reinos_store_is_shipped', $order, $isShipped);
}reinos_store_gateway_list
Available from v4.0.0 (a list of options, and called when no gateway is enabled)
Add payment options to the {exp:reinos_store:gateway_list} tag, e.g. Store Pickup adds "pay at the location" for a pickup order. Return one option or a list of options with an id, a name (the gateway the checkout uses) and a label. An option with the same name as an enabled gateway replaces that gateway in the list. Return ee()->extensions->last_call when you add nothing.
if (ee()->extensions->active_hook('reinos_store_gateway_list') === TRUE)
{
$options = ee()->extensions->call('reinos_store_gateway_list');
}Sync hooks
reinos_store_sync_order
Added in 3.1.0
if (ee()->extensions->active_hook('reinos_store_sync_order') === TRUE)
{
ee()->extensions->call('reinos_store_sync_order', $order, $entry);
}reinos_store_sync_order_item
Added in 3.1.0
if (ee()->extensions->active_hook('reinos_store_sync_order_item') === TRUE)
{
ee()->extensions->call('reinos_store_sync_order_item', $order, $entry);
}CP hooks
reinos_store_resend_confirmation_mail
Called when the admin sends the confirmation email again from the order page in the CP, and when an order is made with Create order in the CP with Send an email to the customer on (from v4.0.0). Store Email sends its templates that match the order on this hook.
Added in 3.4.0
if (ee()->extensions->active_hook('reinos_store_resend_confirmation_mail') === TRUE)
{
ee()->extensions->call('reinos_store_resend_confirmation_mail', $order);
}reinos_store_manual_order_no_email
Called when an order is made with Create order in the CP with Send an email to the customer off, after the other hooks of the new order. Store Email marks its templates that match the order as sent, without sending them, so a later change of the order doesn't send them after all.
Added in 4.0.0
if (ee()->extensions->active_hook('reinos_store_manual_order_no_email') === TRUE)
{
ee()->extensions->call('reinos_store_manual_order_no_email', $order);
}reinos_store_before_view_order
Called on the order page in the CP before the order is shown. Return the (changed) order, or false to keep it.
if (ee()->extensions->active_hook('reinos_store_before_view_order') === TRUE)
{
$order = ee()->extensions->call('reinos_store_before_view_order', $order);
}reinos_store_view_order_1, _2 and _3
Add a section of your own to the order page in the CP: _1 above the billing address, _2 above the order fields and _3 above the products. Return an array with a title and a content (both HTML, escape your own values), and optionally an edit_url and an external_url for the links next to the title. A section without a title or content is not shown. Only the result of the last extension is used.
if (ee()->extensions->active_hook('reinos_store_view_order_1') === TRUE)
{
$section = ee()->extensions->call('reinos_store_view_order_1', $order);
}reinos_store_view_order_actions
Called on the order page in the CP, to add actions to the Actions dropdown in the toolbar. Return the (changed) array of actions. An action has a label, an optional icon (a Phosphor icon name, e.g. package) and a url, with an optional target (e.g. _blank). Delete is always added as the last action.
Added in 4.0.0
if (ee()->extensions->active_hook('reinos_store_view_order_actions') === TRUE)
{
$actions = ee()->extensions->call('reinos_store_view_order_actions', $actions, $order);
}Example:
public function reinos_store_view_order_actions($actions, $order)
{
// the actions of other add-ons
if (ee()->extensions->last_call !== false) {
$actions = ee()->extensions->last_call;
}
$actions['create_parcel'] = [
'label' => 'Create parcel',
'icon' => 'package',
'url' => ee('CP/URL', 'addons/settings/my_addon/create_parcel/' . $order->order_id),
];
return $actions;
}