The PHP functions, classes and JavaScript objects that are safe to call from your own code. This is a much smaller surface than the hook reference — the plugin is customised mainly through hooks, and these are what you use inside those callbacks.
Anything not listed here is internal. It may exist, it may look useful, and it may change without notice.
PHP functions
All of these are available once the plugin has loaded. Hook onto mkl_pc_is_loaded, or anything
later than plugins_loaded, before calling them.
| Function | Returns | Purpose |
|---|---|---|
mkl_pc( $component = false ) | object|false | The plugin instance, or one of its components |
mkl_pc_is_configurable( $product_id = null ) | bool | Whether a product has a configurator |
mkl_pc_get_configurator_type( $product_id = null ) | string|false | 'configurator', '3d', or false |
mkl_pc_get_configuration_meta_mode( $product = false ) | string | How configuration meta is written to orders |
mkl_pc_get_allowed_3d_material_properties() | array | Material properties a 3D choice may set |
mkl_pc_sanitize_3d_material_property_name( $name ) | string|false | Validate one against that list |
mkl_pc_get_settings_page_url( $query_args = array() ) | string | URL of the plugin's settings page |
mkl_pc_is_settings_page() | bool | Whether the current screen is that page |
mkl_pc_get_admin_menu_slug() | string | The admin menu slug |
mkl_pc_get_admin_menu_capability() | string | The capability required to see it |
mkl_pc_include_svg_icon( $icon ) | void | Print one of the plugin's SVG icons |
mkl_pc()
The service locator. Called with no argument it returns the plugin instance; with a component name it returns that component.
$theme = mkl_pc( 'settings' )->get_theme();$show_prices = mkl_pc( 'settings' )->get( 'show_price_in_configurator' );
| Component | What it is |
|---|---|
settings | Plugin settings and labels |
db | The configuration data store |
cache | Cached config files |
themes | Configurator themes |
languages | Translation integration |
frontend | Frontend rendering |
admin | The editor (admin requests only) |
ajax | AJAX endpoints |
customizer | Customizer integration |
frontend_security | Tokens, captcha and rate limiting |
An unknown name returns false rather than throwing, so guard when you are not sure:
$admin = mkl_pc( 'admin' );if ( $admin ) { // only exists on admin requests}
mkl_pc_is_configurable() and mkl_pc_get_configurator_type()
The two guards most third-party code needs. Both fall back to the current post when called with no argument, so inside the loop you can omit it.
add_action( 'woocommerce_after_add_to_cart_form', function () { if ( ! mkl_pc_is_configurable() ) { return; } if ( '3d' === mkl_pc_get_configurator_type() ) { echo '<p>' . esc_html__( 'Drag to rotate the model.', 'my-plugin' ) . '</p>'; }} );
mkl_pc_get_configurator_type() returns 'configurator' for a 2D configurator, '3d' for a 3D
one, and false when the id is not a product at all. It resolves global configurators too, so a
product that inherits its configurator still reports the right type.
mkl_pc_get_configuration_meta_mode()
Returns 'single' or 'individual', which determines which
order hooks fire. Check it before assuming your
filter runs.
Settings
mkl_pc( 'settings' ) is the one component you will use regularly.
| Method | Purpose |
|---|---|
get( $setting, $default = false, $return_default_if_empty = false ) | Read a setting |
get_label( $setting, $default ) | Read a translatable label |
get_theme() | The active configurator theme id |
set( $key, $value ) | Write a setting |
$label = mkl_pc( 'settings' )->get_label( 'mkl_pc__button_label', __( 'Configure', 'my-plugin' ));
Use get_label() rather than get() for anything shown to a customer — it runs the value through
the translation layer, so WPML and Polylang work.
The third argument to get() matters more than it looks: by default an empty stored value is
returned as-is, so a setting a merchant has cleared comes back as '' rather than your default.
Pass true to fall back to the default in that case.
set() writes to the options table. It is intended for migrations and admin tooling, not for
per-request use.
MKL\PC\Choice
The object representing one selected choice in a configuration. Cart and order hooks hand you
these — see mkl_pc_item_meta.
| Method | Purpose |
|---|---|
get_layer( $key ) | A value from the layer — name, type, class_name, … |
get_choice( $key ) | A value from the choice — name, sku, extra_price, and any custom field |
set_choice( $key, $value ) | Overwrite a choice value |
set_layer_value( $key, $value ) | Overwrite a layer value |
is_choice() | Whether this represents a real selection |
get_image( $type = 'image' ) | The image array |
get_image_url( $type = 'image' ) | Its URL |
get_image_id( $type = 'image' ) | Its attachment id |
get_choice_thumbnail() | The thumbnail array |
get_choice_by_id( $id ) | Another choice from the same layer |
add_filter( 'mkl_pc_item_meta', function ( $meta, $layer, $product, $item_key, $context ) { if ( ! $layer->is_choice() ) { return $meta; } $sku = $layer->get_choice( 'sku' ); if ( $sku ) { $meta['value'] .= ' <code>' . esc_html( $sku ) . '</code>'; } return $meta;}, 10, 5 );
The variable is conventionally named $layer in core even though it is a Choice — it carries
both the layer and the selected choice, which is why it has two families of getter.
Always call is_choice() first. A Choice can represent a group or a layer with nothing
selected, and the getters return empty values in that case rather than failing.
Choices are serialised into cart and order data. A property you add is lost unless you also add
it to
mkl_pc_choice_sleep_properties.
MKL\PC\Configuration
A saved configuration — the object behind saved designs, presets and order configurations.
| Method | Purpose |
|---|---|
get_layers() | Its choices, as Choice objects |
get_item_data( $context = 'cart' ) | The label/value pairs for display |
get_configured_price( $args = array() ) | base, extra and total |
get_image( $size, $attr, $lazy ) | The rendered preview as an <img> |
get_image_url( $lazy, $size ) | Its URL |
save( $args = array() ) | Persist it |
update( $args ) | Update it |
delete() | Remove it |
configuration_exists() | Whether it is stored |
configuration_image_exists() | Whether its preview has been generated |
$configuration = new \MKL\PC\Configuration( $configuration_id );$prices = $configuration->get_configured_price( array( 'quantity' => 2 ) );if ( ! is_wp_error( $prices ) ) { echo wc_price( $prices['total'] );}foreach ( $configuration->get_layers() as $layer ) { echo esc_html( $layer->get_layer( 'name' ) . ': ' . $layer->get_choice( 'name' ) );}
get_configured_price() returns a WP_Error when the product cannot be resolved — check for it.
Its extra figure is only meaningful when the Extra Price add-on is active.
Constructing one with an id loads it; constructing with null and an args array builds a new
one from raw content, which is how the plugin renders previews for order items.
MKL\PC\Utils
Static helpers. Most are internal, but a few are genuinely reusable:
| Method | Purpose |
|---|---|
Utils::is_configurable( $product_id ) | What mkl_pc_is_configurable() calls |
Utils::is_product( $post_id ) | Whether a post is a product or variation |
Utils::is_configurator_owner( $post_id ) | Whether it owns a configurator |
Utils::kses_basic_inline_html( $html ) | Sanitise to the inline tags the plugin allows |
Utils::sanitize_html_classes( $classes ) | Sanitise an array of class names |
Utils::get_registered_image_size( $size ) | Resolve a registered image size |
Utils::inline_svg( $file_path ) | Read an SVG safely for inline output |
kses_basic_inline_html() is the one to remember. Cart and order display run every label and
value through it, so matching it in your own filters keeps output consistent:
add_filter( 'mkl_pc_cart_item_choice', function ( $html, $key, $value ) { return \MKL\PC\Utils::kses_basic_inline_html( $html );}, 20, 3 );
Frontend JavaScript
PC.fe is the running configurator. It only exists once the configurator has been opened — do
your work from PC.fe.start rather than on page load.
| Member | Type | Purpose |
|---|---|---|
PC.fe.layers | Collection | Every layer |
PC.fe.angles | Collection | Every angle |
PC.fe.currentProductData | object | The data the configurator was built from |
PC.fe.config | object | Behaviour flags, from PC_config.config |
PC.fe.opened | bool | Whether the configurator is open |
PC.fe.is_setting_config | bool | True while a stored configuration is being applied |
PC.fe.active_product | int | The product being configured |
PC.fe.getLayerContent( layerId ) | Collection|false | A layer's choices |
PC.fe.get_choice_model( layerId, choiceId ) | Model|false | One choice |
PC.fe.get_product_price() | number | The base price |
PC.fe.setConfig( configItems ) | void | Apply a stored configuration |
PC.fe.open( productId, parentId, $el, reset ) | void | Open the configurator |
PC.fe.close() | void | Close it |
PC.fe.goto( … ) | void | Move to a layer or step |
PC.fe.save_data.save() | string | The configuration as JSON |
PC.fe.save_data.get_choices( reset ) | array | The same, as an array |
PC.fe.save_data.getSaveDataAsync() | Promise<string> | The same, awaiting registered promises |
wp.hooks.addAction( 'PC.fe.start', 'my-plugin/configurator', function () { PC.fe.layers.each( function ( layer ) { const choices = PC.fe.getLayerContent( layer.id ); const active = choices ? choices.findWhere( { active: true } ) : null; console.log( layer.get( 'name' ), '→', active ? active.get( 'name' ) : '(none)' ); } );} );
getLayerContent() returns false for a layer with no choices — a group or a summary layer — so
check before using it.
PC.fe.is_setting_config is how you distinguish a customer's click from a restored selection
inside a PC.fe.choice.set_choice handler:
wp.hooks.addAction( 'PC.fe.choice.set_choice', 'my-plugin/configurator', function ( model ) { if ( PC.fe.is_setting_config ) return; // restoring, not a real click myAnalytics.track( 'choice', { name: model.get( 'name' ) } );} );
Use getSaveDataAsync() rather than save() if anything on the site registers
PC.fe.save_data.before_save.promises
— Text Overlay and the 3D viewer both do, and save() will not wait for them.
PC.utils
| Method | Purpose |
|---|---|
PC.utils.formatMoney( amount, useCurrency ) | Format a number using the store's currency settings |
PC.utils.escape_html( string ) | Escape for output |
PC.utils.strip_html( string ) | Remove tags |
PC.utils._isMobile() | Mobile viewport check |
PC.utils._isTouch() | Touch device check |
document.querySelector( '#my-total' ).textContent = PC.utils.formatMoney( 1234.5 );
formatMoney() honours the decimal and thousand separators, the symbol position and the
precision configured in WooCommerce, so use it rather than toFixed().
3D
The 3D viewer exposes a live runtime API rather than a static object — scene, camera, renderer, material registry, events. See The 3D runtime API.
Constants
| Constant | Purpose |
|---|---|
MKL_PC_VERSION | Plugin version |
MKL_PC_PREFIX | Meta key prefix (_mkl_pc_) |
MKL_PC_ASSETS_URL | URL of the plugin's assets directory |
MKL_PC_ASSETS_PATH | Filesystem path to it |
Use MKL_PC_PREFIX when reading the plugin's own meta directly rather than hard-coding the
prefix — it has changed once already.