Weighted Inventory

Apply a custom inventory weight to a field such that it consumes additional inventory per requested item.

Read the Walkthrough

Code

Filename: gpi-weighted-inventory.php

<?php
/**
 * Gravity Perks // Inventory // Weighted Inventory
 * https://gravitywiz.com/documentation/gravity-forms-inventory/
 *
 * Apply a custom inventory weight to a field such that it consumes additional inventory per requested item.
 *
 * For example, Product A is for single tickets. Product B is for a group of 8 tickets. Both share the same Tickets
 * resource. Any quantity of Product B will subtract 8 from the inventory instead of 1.
 *
 * Known Limitations
 *
 * - Only works with Shared Inventory resources.
 * - Can only be applied to a single field per Shared Inventory resource even if fields are on different forms.
 * - Does not work with the available inventory message – the available inventory will only show up correctly for the weighted field.
 * – Does not work with choice-based fields.
 *
 * Plugin Name:  GP Inventory — Weighted Inventory
 * Plugin URI:   https://gravitywiz.com/documentation/gravity-forms-inventory/
 * Description:  Apply a custom inventory weight to a field such that it consumes additional inventory per requested item.
 * Author:       Gravity Wiz
 * Version:      0.1
 * Author URI:   https://gravitywiz.com
 */
class GPI_Weighted_Inventory {

	public function __construct( $args = array() ) {

		$this->_args = wp_parse_args( $args, array(
			'form_id'  => false,
			'field_id' => false,
			'weight'   => false,
		) );

		add_action( 'init', array( $this, 'init' ) );

	}

	public function init() {

		add_filter( 'gpi_claimed_inventory', array( $this, 'apply_weights_to_claimed_inventory' ), 10, 2 );
		add_filter( 'gpi_requested_quantity', array( $this, 'apply_weights_requested_quantity' ), 10, 3 );
		add_filter( 'gpi_is_in_stock', array( $this, 'is_in_stock' ), 10, 3 );

	}

	public function apply_weights_to_claimed_inventory( $claimed, $field ) {
		global $wpdb;

		if ( ! $this->is_applicable_form( $field->formId ) ) {
			return $claimed;
		}

		$resource_id     = rgar( $field, 'gpiResource' );
		$resource_fields = gp_inventory_type_advanced()->get_resource_fields( $resource_id );

		if ( empty( $resource_fields ) || ! $this->has_weighted_field( $resource_fields ) ) {
			return $claimed;
		}

		$claimed = 0;

		foreach ( $resource_fields as $resource_field ) {
			$weight = 1;
			if ( $this->is_applicable_field( $resource_field ) ) {
				$weight = $this->_args['weight'];
			}

			// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
			$field_sum = (int) $wpdb->get_var( implode( "n", gp_inventory_type_advanced()->get_claimed_inventory_query( $resource_field ) ) );
			$claimed  += $field_sum * $weight;
		}

		return $claimed;
	}

	public function apply_weights_requested_quantity( $quantity, $field, $form ) {
		if ( $this->is_applicable_field( $field ) && (int) $quantity > 0 ) {
			$quantity *= $this->_args['weight'];
		}
		return $quantity;
	}

	public function is_in_stock( $is_in_stock, $field, $available_stock ) {
		if ( $this->is_applicable_field( $field ) && $available_stock < $this->_args['weight'] ) {
			$is_in_stock = false;
		}
		return $is_in_stock;
	}

	public function has_weighted_field( $resource_fields ) {
		foreach ( $resource_fields as $resource_field ) {
			if ( $this->is_applicable_field( $resource_field ) ) {
				return true;
			}
		}
		return false;
	}

	public function is_applicable_field( $field ) {
		return $this->is_applicable_form( $field->formId ) && $field->id === (int) $this->_args['field_id'];
	}

	public function is_applicable_form( $form ) {

		$form_id = isset( $form['id'] ) ? $form['id'] : $form;

		return empty( $this->_args['form_id'] ) || (int) $form_id === (int) $this->_args['form_id'];
	}

}

# Configuration

new GPI_Weighted_Inventory( array(
	'form_id'  => 123,
	'field_id' => 4,
	'weight'   => 5,
) );

Leave a Reply

Your email address will not be published. Required fields are marked *

  • Trouble installing this snippet? See our troubleshooting tips.
  • Need to include code? Create a gist and link to it in your comment.
  • Reporting a bug? Provide a URL where this issue can be recreated.

By commenting, I understand that I may receive emails related to Gravity Wiz and can unsubscribe at any time.