Guide

Cart and order hooks

Once a configuration is added to the cart it stops being browser state and becomes WooCommerce data. These hooks control how it is priced, how it reads in the cart and at checkout, and what is written onto the order.

Cart and order display share most of their machinery — mkl_pc_cart_item_choice and friends are fired from both — so they are documented together here.

See the hook reference index for how to register callbacks.

Cart display

HookTypeArgumentsPurpose
mkl_pc/wc_cart_get_item_data/choicesfilter$choices, $cartItemThe full list of choices shown for a cart line
mkl_pc/wc_cart_get_item_data/choicefilter$choice, $selectedChoice, $cartItemOne choice row
mkl_pc/wc_cart_get_item_data/choice_thumbnailfilter$html, $selectedChoiceThe thumbnail markup beside a choice
mkl_pc/wc_cart_get_item_data/display_choice_imagefiltertrueWhether thumbnails are shown at all
mkl_pc_cart_item_choicefilter$html, $key, $value, $before, $afterThe finished markup for one choice
mkl_pc_cart_item_choice_beforefilter$html, $choiceOpening wrapper for a choice
mkl_pc_cart_item_choice_afterfilter$html, $choiceClosing wrapper
mkl_pc_cart_item_choice__classesfilter$classes, $layerClasses on the wrapper
mkl_pc_cart_item_choice_datafilter$item, $choiceThe data array a choice row is built from
mkl_pc_user_can_edit_item_from_cartfilter$canEditWhether the "edit configuration" link is shown
mkl_pc_edit_configuration_labelfilter$labelThat link's label
mkl_pc/wc_cart_add_item_data/choice_weightfilter$weight, $layerWeight a choice contributes to the line
mkl_pc/cart_item/merge_layer_image_idfilter$imageToken, $layerImage token used when merging the preview
mkl_pc_3d_screenshot_temp_max_agefilter48 * HOUR_IN_SECONDSHow long unused 3D screenshots are kept
mkl_pc_3d_screenshot_dimensionsfilter$dimensionsSize of the 3D cart screenshot, and the largest one accepted

Order meta

HookTypeArgumentsPurpose
mkl_pc/order_created/save_layer_metafilter$itemData, $layer, $orderItem, [], $countOne layer's data as it is written to the order
mkl_pc/order_created/after_save_layer_metaaction$layer, $orderItem, $orderAfter each layer is saved
mkl_pc/order_created/after_saved_dataaction$item, $order, $configuratorDataAfter the whole configuration is saved
mkl_pc/order_created/saved_data/labelfilter$label, $itemMeta key for the combined configuration
mkl_pc/order_created/get_data/labelfilter$label, $orderItem, $configuratorDataDisplay label for that meta
mkl_pc/order_created/individual_meta/keyfilter$key, $layer, $itemMeta key for one layer
mkl_pc/order_created/individual_meta/valuefilter$value, $layer, $itemMeta value for one layer
mkl_pc/order_created/individual_meta/keep_htmlfilterfalse, $layer, $itemKeep markup in the individual metas
mkl_pc_order_item_metafilter$meta, $layer, $productA layer's label/value pair, cart and order
mkl_pc/order_image_sizefilter$size, $orderItem, $configuratorDataImage size for the configuration preview
mkl_pc/do_not_show_image_download_linkfilterfalseSuppress the image download link entirely
mkl_pc/customer_can_see_image_download_linkfilter$hide, $itemId, $item, $orderWhether to hide it for this order

mkl_pc_order_item_meta

The single most useful hook in this group. Every layer, in both cart and order, passes through it as a label / value / layer array. Add-ons build on it — Extra Price appends the price here, Form Fields appends the field value.

php functions.php
add_filter( 'mkl_pc_order_item_meta', function ( $meta, $layer, $product ) {	if ( $sku = $layer->get_choice( 'sku' ) ) {		$meta['value'] .= ' <code>' . esc_html( $sku ) . '</code>';	}	return $meta;}, 10, 3 );
mkl_pc_order_item_meta.

Return an empty array to drop the layer from display altogether. $layer is an MKL\PC\Choice — use get_layer( 'name' ) for the layer and get_choice( 'name' ) for the selection.

mkl_pc_cart_item_choice and its wrappers

These build the rendered HTML for a choice row, in the cart and the order. Four filters run in order:

  1. mkl_pc_cart_item_choice__classes — the class list, before sanitising
  2. mkl_pc_cart_item_choice_before — the opening <div …>
  3. mkl_pc_cart_item_choice_after — the closing </div>
  4. mkl_pc_cart_item_choice — the assembled row, with all of the above already in it
php functions.php
// Tag rows by layer type so they can be styled.add_filter( 'mkl_pc_cart_item_choice__classes', function ( $classes, $layer ) {	$classes[] = 'my-row';	return $classes;}, 10, 2 );// Or replace the row wholesale.add_filter( 'mkl_pc_cart_item_choice', function ( $html, $key, $value, $before, $after ) {	return $before . '<span class="k">' . $key . '</span><span class="v">' . $value . '</span>' . $after;}, 10, 5 );
mkl_pc_cart_item_choice and its wrappers.

The label and value reaching mkl_pc_cart_item_choice have already been through Utils::kses_basic_inline_html(), so only simple inline markup survives. If you need richer markup, add it around them in the before/after filters rather than inside the value.

mkl_pc/wc_cart_get_item_data/choices

The complete list of choices for a cart line, just before it is rendered. Use it to reorder, filter or collapse rows:

php functions.php
add_filter( 'mkl_pc/wc_cart_get_item_data/choices', function ( $choices, $cart_item ) {	// Show at most five rows in the cart.	return array_slice( $choices, 0, 5 );}, 10, 2 );
mkl_pc/wc_cart_get_item_data/choices.

Each entry is [ 'name' => …, 'value' => …, 'layer' => MKL\PC\Choice ]. Choices whose layer or choice has Hide in cart set never reach this filter.

mkl_pc/wc_cart_get_item_data/choice_thumbnail and …/display_choice_image

Thumbnails are rendered as <span class="choice-thumb"><img …></span> when the choice has one. Return an empty string from the first filter to drop it for particular choices, or false from the second to switch them off site-wide:

php functions.php
add_filter( 'mkl_pc/wc_cart_get_item_data/display_choice_image', '__return_false' );
mkl_pc/wc_cart_get_item_data/choice_thumbnail and …/display_choice_image.

mkl_pc/wc_cart_add_item_data/choice_weight

Each choice can carry a weight, which is summed into the cart line's shipping weight. This filter sees each one as a float.

php functions.php
add_filter( 'mkl_pc/wc_cart_add_item_data/choice_weight', function ( $weight, $layer ) {	// Packaging adds 10% on top of the parts.	return $weight * 1.1;}, 10, 2 );
mkl_pc/wc_cart_add_item_data/choice_weight.

mkl_pc_user_can_edit_item_from_cart and mkl_pc_edit_configuration_label

The first decides whether the cart shows a link back into the configurator, defaulting to the Show edit configuration link setting. The second is that link's text.

php functions.php
add_filter( 'mkl_pc_user_can_edit_item_from_cart', function ( $can_edit ) {	// Never offer editing to guests.	return is_user_logged_in() ? $can_edit : false;} );
mkl_pc_user_can_edit_item_from_cart and mkl_pc_edit_configuration_label.

Configuration meta mode, and which order hooks fire

How a configuration is written onto the order depends on the configuration meta mode:

ModeCombined metaPer-layer meta
single (default)yesno
individualnoyes

That decides which hooks you get. mkl_pc/order_created/saved_data/label and mkl_pc/order_created/get_data/label only matter when the combined meta is written; the individual_meta/* filters only fire in the other case. Check the mode — with mkl_pc_get_configuration_meta_mode() — before assuming your filter runs.

mkl_pc/order_created/individual_meta/key and …/value

The per-layer meta written for machine readability — for exports, packing slips, and anything reading order meta directly.

php functions.php
add_filter( 'mkl_pc/order_created/individual_meta/key', function ( $key, $layer, $item ) {	return 'cfg_' . sanitize_key( $key );}, 10, 3 );
mkl_pc/order_created/individual_meta/key and …/value.

Markup is stripped by default, which is the point of these metas — set mkl_pc/order_created/individual_meta/keep_html to true only if you have a reason. Empty values are skipped entirely, so returning '' from the value filter removes the meta.

mkl_pc/order_created/save_layer_meta and …/after_save_layer_meta

The filter shapes each layer's label / value data as it is stored; the action fires immediately after, and is the place to write meta of your own.

php functions.php
add_action( 'mkl_pc/order_created/after_save_layer_meta', function ( $layer, $order_item, $order ) {	if ( $code = $layer->get_choice( 'supplier_code' ) ) {		$order_item->add_meta_data( '_supplier_code', $code, false );	}}, 10, 3 );
mkl_pc/order_created/save_layer_meta and …/after_save_layer_meta.

The item is saved after all layers are processed, so you do not need to call save() yourself.

mkl_pc/order_created/after_saved_data

Fires once per configured item, after the configuration meta and SKU have been written. The right hook for anything that needs the whole configuration — a supplier notification, an ERP push, a production record.

php functions.php
add_action( 'mkl_pc/order_created/after_saved_data', function ( $item, $order, $configurator_data ) {	my_queue_production_job( $order->get_id(), $item->get_id(), $configurator_data );}, 10, 3 );
mkl_pc/order_created/after_saved_data.

Keep it fast, or schedule the real work — this runs during checkout.

Note the inverted sense: returning true hides the link. The default is 'completed' != $order->get_status(), so the link appears only once the order is complete.

php functions.php
// Always show it, whatever the status.add_filter( 'mkl_pc/customer_can_see_image_download_link', '__return_false' );
mkl_pc/customer_can_see_image_download_link.

mkl_pc/do_not_show_image_download_link reads the way you would expect — true suppresses the link — and is checked first.

mkl_pc/order_image_size

The registered image size used for the configuration preview on an order, defaulting to the Cart thumbnail size setting.

php functions.php
add_filter( 'mkl_pc/order_image_size', function ( $size, $order_item, $data ) {	return 'full';}, 10, 3 );
mkl_pc/order_image_size.

mkl_pc/cart_item/merge_layer_image_id

The image token for a choice when the preview image is merged server-side — usually an attachment id, sometimes the basename of a temporary upload. Returning an empty value drops that layer from the merged image.

It runs on the token the choice has already resolved, which for a cart item, an order or a quote is the one saved with the configuration — see mkl_pc/choice/source.

mkl_pc_3d_screenshot_temp_max_age

3D products post a screenshot with the configuration, held in a temporary location until the order is placed. Orphans are cleaned up after 48 hours by default.

php functions.php
add_filter( 'mkl_pc_3d_screenshot_temp_max_age', function () {	return 7 * DAY_IN_SECONDS;} );
mkl_pc_3d_screenshot_temp_max_age.

mkl_pc_3d_screenshot_dimensions

The width and height the 3D viewer captures the cart, quote and order picture at, as array( 'width' => …, 'height' => … ). It follows the Merge size setting, 800 × 800 for full size.

It is also the largest picture accepted. The screenshot is posted by the browser, so a picture that is not a PNG, or is larger than this size, is refused and the line has no image. Change the size here rather than in JavaScript, so the two stay in step.

php functions.php
add_filter( 'mkl_pc_3d_screenshot_dimensions', function ( $dimensions ) {	return array( 'width' => 1200, 'height' => 900 );} );
mkl_pc_3d_screenshot_dimensions.

WooCommerce hooks fired here

To keep existing customisations working, the plugin fires several WooCommerce hooks itself when it renders configured lines: woocommerce_cart_item_product, …_product_id, …_visible, …_permalink, …_thumbnail, and woocommerce_order_item_display_meta_key / …_meta_value. All carry WooCommerce's own arguments.