Skip to content
Snippets Groups Projects
cfafa-form-action-product.php 8.73 KiB
Newer Older
  • Learn to ignore specific revisions
  • Christian Wach's avatar
    Christian Wach committed
    <?php
    /**
     * "WooCommerce Product" ACFE Form Action Class.
     *
     * Handles the "WooCommerce Product" ACFE Form Action.
     *
     * @package Conditional_Form_Actions_For_ACFE
     * @since 0.1
     */
    
    // Exit if accessed directly.
    defined( 'ABSPATH' ) || exit;
    
    /**
     * CiviCRM Profile Sync "WooCommerce Product" ACFE Form Action Class.
     *
     * A class that handles the "WooCommerce Product" ACFE Form Action.
     *
     * @since 0.1
     */
    class CFAFA_Form_Action_Product extends CFAFA_Form_Action_Base {
    
    	/**
    	 * Plugin object.
    	 *
    	 * @since 0.1
    	 * @access public
    	 * @var object $plugin The plugin object.
    	 */
    	public $plugin;
    
    	/**
    	 * Parent (calling) object.
    	 *
    	 * @since 0.1
    	 * @access public
    	 * @var object $acf The parent object.
    	 */
    	public $acfe;
    
    	/**
    	 * Form Action Name.
    	 *
    	 * @since 0.1
    	 * @access public
    	 * @var string $action_name The unique name of the Form Action.
    	 */
    	public $action_name = 'woo_cfafa_product';
    
    	/**
    	 * Field Key Prefix.
    	 *
    	 * @since 0.1
    	 * @access public
    	 * @var string $field_key The prefix for the Field Key.
    	 */
    	public $field_key = 'field_cfafa_woo_product_';
    
    	/**
    	 * Field Name Prefix.
    	 *
    	 * @since 0.1
    	 * @access public
    	 * @var string $field_name The prefix for the Field Name.
    	 */
    	public $field_name = 'cfafa_woo_product_';
    
    	/**
    	 * Constructor.
    	 *
    	 * @since 0.1
    	 *
    	 * @param object $parent The parent object reference.
    	 */
    	public function __construct( $parent ) {
    
    		// Store references to objects.
    		$this->plugin = $parent->plugin;
    		$this->acfe = $parent;
    
    		// Label this Form Action.
    		$this->action_label = __( 'WooCommerce Product action', 'conditional-form-actions-for-acfe' );
    
    		// Alias Placeholder for this Form Action.
    		$this->alias_placeholder = __( 'WooCommerce Product', 'conditional-form-actions-for-acfe' );
    
    		// Init parent.
    		parent::__construct();
    
    	}
    
    	/**
    	 * Configure this object.
    	 *
    	 * @since 0.1
    	 */
    	public function configure() {
    
    		// WooCommerce Product Conditional Field.
    		$this->mapping_field_filters_add( 'product_conditional' );
    
    	}
    
    	/**
    	 * Performs the action when the Form the Action is attached to is submitted.
    	 *
    	 * @since 0.1
    	 *
    	 * @param array $form The array of Form data.
    	 * @param integer $current_post_id The ID of the Post from which the Form has been submitted.
    	 * @param string $action The customised name of the action.
    	 */
    	public function make( $form, $current_post_id, $action ) {
    
    		// Bail if a filter has overridden the action.
    		if ( false === $this->make_skip( $form, $current_post_id, $action ) ) {
    			return;
    		}
    
    		// Get some Form details.
    		$form_name = acf_maybe_get( $form, 'name' );
    		$form_id = acf_maybe_get( $form, 'ID' );
    
    		// Populate Product data array.
    		$product_data = $this->form_data_get( $form, $current_post_id, $action );
    
    		// Act with the data from the Form.
    		$product_data = $this->form_product_save( $product_data );
    
    		// Save the results of this Action for later use.
    		$this->make_action_save( $action, $product_data );
    
    	}
    
    	/**
    	 * Defines additional Fields for the "Action" Tab.
    	 *
    	 * @since 0.1
    	 *
    	 * @return array $fields The array of Fields for this section.
    	 */
    	public function tab_action_append() {
    
    		// Init Fields.
    		$fields = [];
    
    		$fields[] = [
    			'key' => $this->field_key . 'product_id',
    			'label' => __( 'WooCommerce Product', 'conditional-form-actions-for-acfe' ),
    			'name' => $this->field_name . 'product_id',
    			'type' => 'select',
    			'instructions' => __( 'Use this to add a WooCommerce Product to the Cart.', 'conditional-form-actions-for-acfe' ),
    			'required' => 0,
    			'conditional_logic' => 0,
    			'wrapper' => [
    				'width' => '',
    				'class' => '',
    				'id' => '',
    				'data-instruction-placement' => 'field',
    			],
    			'acfe_permissions' => '',
    			'default_value' => '',
    			'placeholder' => '',
    			'allow_null' => 1,
    			'multiple' => 0,
    			'ui' => 0,
    			//'ajax' => 1,
    			//'ajax_action' => 'cfafa_get_products',
    			'return_format' => 'value',
    			'choices' => $this->product_choices_get(),
    		];
    
    		// Add Conditional Field.
    		$code = 'product_conditional';
    		$label = __( 'Conditional On', 'conditional-form-actions-for-acfe' );
    		$conditional = $this->mapping_field_get( $code, $label );
    		$conditional['placeholder'] = __( 'Always add', 'conditional-form-actions-for-acfe' );
    		$conditional['wrapper']['data-instruction-placement'] = 'field';
    		$conditional['instructions'] = __( 'To add the Product to the Cart only when a Form Field is populated (e.g. "First Name") link this to the Form Field. To add the Product to the Cart only when more complex conditions are met, link this to a Hidden Field with value "1" where the conditional logic of that Field shows it when the conditions are met.', 'conditional-form-actions-for-acfe' );
    		$fields[] = $conditional;
    
    		// --<
    		return $fields;
    
    	}
    
    	/**
    	 * Builds Product data array from mapped Fields.
    	 *
    	 * @since 0.1
    	 *
    	 * @param array $form The array of Form data.
    	 * @param integer $current_post_id The ID of the Post from which the Form has been submitted.
    	 * @param string $action The customised name of the action.
    	 * @return array $data The array of Product data.
    	 */
    	public function form_data_get( $form, $current_post_id, $action ) {
    
    		// Add Product ID.
    		$data['product_id'] = get_sub_field( $this->field_key . 'product_id' );
    
    		// Get Product Conditional Reference.
    		$data['product_conditional_ref'] = get_sub_field( $this->field_key . 'map_product_conditional' );
    		$conditionals = [ $data['product_conditional_ref'] ];
    
    		// Populate array with mapped Conditional Field values.
    		$conditionals = acfe_form_map_vs_fields( $conditionals, $conditionals, $current_post_id, $form );
    
    		// Save Product Conditional.
    		$data['product_conditional'] = array_pop( $conditionals );
    
    		// --<
    		return $data;
    
    	}
    
    	/**
    	 * Sends the WooCommerce Product given data from mapped Fields.
    	 *
    	 * @since 0.1
    	 *
    	 * @param array $product_data The array of Product data.
    	 * @return array|bool $product_data The Product data array, or false on failure.
    	 */
    	public function form_product_save( $product_data ) {
    
    		// Skip if the Product Conditional Reference Field has a value.
    		if ( ! empty( $product_data['product_conditional_ref'] ) ) {
    			// And the Product Conditional Field has no value.
    			if ( empty( $product_data['product_conditional'] ) ) {
    				return $product_data;
    			}
    		}
    
    		// Unset Product Conditionals.
    		if ( isset( $product_data['product_conditional'] ) ) {
    			unset( $product_data['product_conditional'] );
    		}
    		if ( isset( $product_data['product_conditional_ref'] ) ) {
    			unset( $product_data['product_conditional_ref'] );
    		}
    
    		// Strip out empty Fields.
    		$product_data = $this->form_data_prepare( $product_data );
    
    		// Sanity check.
    		if ( empty( $product_data['product_id'] ) ) {
    			return false;
    		}
    
    		// Add the Product to the WooCommerce Cart.
    		$result = $this->product_add_to_cart( $product_data );
    
    		// Bail on failure.
    		if ( $result === false ) {
    			return false;
    		}
    
    		// Add Cart Item key to Product data.
    		$product_data['cart_item_key'] = $result;
    
    		// --<
    		return $product_data;
    
    	}
    
    	/**
    	 * Gets the WooCommerce Products as an array of options for ACF.
    	 *
    	 * @since 0.1
    	 *
    	 * @return array $options The array of Products formatted for ACF.
    	 */
    	public function product_choices_get() {
    
    		// Init return.
    		$options = [];
    
    		/*
    		 * Build params to get all published Products.
    		 *
    		 * We have to query directly because WooCommerce has not been initialised
    		 * at this point and wc_get_products() does not return any results. This
    		 * is because ACF hooks into `init` with priority 5 *before* WooCommerce
    		 * initialises.
    		 *
    		 * This may need to be looked at again in future.
    		 */
    		$args = [
    			'post_type' => 'product',
    			'post_status' => [ 'publish' ],
    			'no_found_rows' => true,
    			'posts_per_page' => -1,
    		];
    
    		// Do query.
    		$query = new WP_Query( $args );
    
    		// Do the loop.
    		if ( $query->have_posts() ) {
    			foreach ( $query->get_posts() as $found ) {
    				$options[ $found->ID ] = $found->post_title;
    			}
    		}
    
    		// Reset Post data just in case.
    		wp_reset_postdata();
    
    		// --<
    		return $options;
    
    	}
    
    	/**
    	 * Adds the Product to the Cart.
    	 *
    	 * @since 0.1
    	 *
    	 * @param array $product_data The array of Product data.
    	 * @return integer|bool $cart_item_key The key of the Cart Item, or false otherwise.
    	 */
    	public function product_add_to_cart( $product_data ) {
    
    		// Get the Product.
    		$product = wc_get_product( $product_data['product_id'] );
    
    		// Sanity check.
    		if ( empty( $product ) ) {
    			return false;
    		}
    
    		// Some defaults.
    		$product_id = $product->get_id();
    		$quantity = 1;
    		$variation_id = 0;
    		$variation = [];
    		$cart_item_data = [];
    
    		// Build Cart Item data?
    
     		// Add the configured Product to the Cart.
     		$cart_item_key = WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variation, $cart_item_data );
    
     		// --<
     		return $cart_item_key;
    
    	}
    
    } // Class ends.