Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Adds input attributes like minimums or maximums to WooCommerce Measurement Price Calculator inputs
<?php // only copy this line if needed
/**
* These snippets work together to let you set attributes for WooCommerce Measurement Price Calculator inputs
* You can use post custom fields to set attributes like min, max, and step for a given measurement
*
* Example: if you want to limit width, name a field `mpc_width` -- format: `mpc_{measurementName}`
* The field value should be a comma-separated list of attributes, like min = 0, max = 10, step = 1
*/
/**
* Modify MPC inputs to add field attributes from product custom fields
*
* The product custom field must have a key that uses the measurement name,
* such as `mpc_width`, `mpc_length`, `mpc_volume`, etc.
*/
function sv_wc_measurement_price_calculator_input_min_max() {
// bail unless we're on a product page and MPC is active
if ( ! ( is_product() && class_exists( 'WC_Price_Calculator_Product' ) ) ) {
return;
}
global $product;
// bail unless the calculator is enabled for this product, this is also why we hook
// into the footer scripts, since this isn't available immediately at page load
if ( ! WC_Price_Calculator_Product::calculator_enabled( $product ) ) {
return;
}
// get the possible measurements for the current calculator set up
$settings = new WC_Price_Calculator_Settings( $product );
$measurements = $settings->get_calculator_measurements();
// get any rules we should add based on which measurements are enabled, +
// which custom fields exist
$rules = sv_mpc_generate_attributes_js( $product, $measurements );
wc_enqueue_js( $rules );
}
add_action( 'wp_print_footer_scripts', 'sv_wc_measurement_price_calculator_input_min_max' );
/**
* Helper function to generate javascript rules to add to the product page
*
* @param \WC_Product $product global product object
* @param array $measurements the enabled measurements for this product
* @return string the rules (in jQuery) to apply to the product
*/
function sv_mpc_generate_attributes_js( $product, $measurements ) {
$rules = array();
foreach( $measurements as $measurement ) {
// get the custom field for this measurement in array form
$vals = sv_mpc_generate_calculator_input_limits( $product, 'mpc_' . $measurement->get_name() );
// break for this measurement if it doesn't have a custom field
if ( empty( $vals ) ) {
continue;
}
// we have a value, so build a jQuery rule to change the input atts
$id = '#' . $measurement->get_name() . '_needed';
$rules[] = "$('" . $id . "').attr({ type: 'number', min: '" . esc_attr( $vals['min'] ) . "', max: '" . esc_attr( $vals['max'] ) . "', step: '" . esc_attr( $vals['step'] ) . "' }).addClass('input-text');";
}
// give back a string rules, one per line
return implode( "\n", $rules );
}
/**
* Helper function to generate an associative array from the custom field string
*
* @param \WC_Product $product global product object
* @param string $meta_key the meta key for the post meta to retrieve
* @return array the meta key values as an associative array
*/
function sv_mpc_generate_calculator_input_limits( $product, $meta_key ) {
// get the meta field, bail if it's not set
$meta_values = get_post_meta( $product->id, $meta_key, true );
if ( empty( $meta_values ) ) {
return array();
}
// turn this into a messy array ( [0] => 'key = value') for now
$meta_values = array_map( 'trim', explode( ',', $meta_values ) );
$new_values = array();
// break each string into an associative array like 'key' => 'value'
foreach ( $meta_values as $value ) {
$piece = explode ( '=', $value );
$piece[0] = sanitize_text_field( $piece[0] );
$piece[1] = floatval( trim( $piece[1] ) );
$new_values[ $piece[0] ] = $piece[1];
}
// return the new associative array for this field
return $new_values;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.