HEX
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/7.4.30
System: Linux iZj6c1151k3ad370bosnmsZ 3.10.0-1160.76.1.el7.x86_64 #1 SMP Wed Aug 10 16:21:17 UTC 2022 x86_64
User: root (0)
PHP: 7.4.30
Disabled: NONE
Upload Files
File: /var/www/html/sparkle/wp-content/plugins/flexible-product-fields/classes/fpf-cart.php
<?php

/**
 * Handles WooCommerce add to cart.
 */
class FPF_Cart {

	/**
	 * Priority before default
	 */
	const HOOK_BEFORE_DEFAULT = 9;

	/**
	 * Priority after default
	 */
	const HOOK_AFTER_DEFAULT = 20;

	/**
	 * Plugin
	 *
	 * @var Flexible_Product_Fields_Plugin
	 */
	private $_plugin;

	/**
	 * @var FPF_Product_Fields
	 */
    private $_product_fields = null;

	/**
	 * @var FPF_Product|null
	 */
    private $_product = null;

	/**
	 * Product price.
	 *
	 * @var FPF_Product_Price|null
	 */
	private $product_price = null;

	/**
	 * FPF_Cart constructor.
	 *
	 * @param Flexible_Product_Fields_Plugin $plugin
	 * @param FPF_Product_Fields $product_fields
	 * @param FPF_Product $product
	 */
    public function __construct( Flexible_Product_Fields_Plugin $plugin, FPF_Product_Fields $product_fields, FPF_Product $product, FPF_Product_Price $product_price ) {
        $this->_plugin = $plugin;
        $this->_product_fields = $product_fields;
        $this->_product = $product;
	    $this->product_price = $product_price;
        add_action( 'plugins_loaded', array( $this, 'hooks' ) );
    }

	/**
	 * Define hooks
	 */
    public function hooks() {
	    add_filter( 'woocommerce_add_to_cart_handler', array( $this, 'woocommerce_add_to_cart_handler' ), 10, 2 );
        add_filter( 'woocommerce_get_cart_item_from_session', array( $this, 'woocommerce_get_cart_item_from_session' ), self::HOOK_AFTER_DEFAULT, 2 );
        add_filter( 'woocommerce_get_item_data', array( $this, 'woocommerce_get_item_data' ), 10, 2 );
		add_action( 'woocommerce_new_order_item', array( $this, 'woocommerce_new_order_item' ), 10, 3 );
    }

	/**
	 * Handle filters and actions for add to cart process but not for grouped product.
	 * @param string $type
	 * @param int $product_id
	 *
	 * @return string
	 */
    public function woocommerce_add_to_cart_handler( $type, $product_id ) {
		if ( $type != FPF_Product_Extendend_Info::PRODUCT_TYPE_GROUPED ) {
			add_filter( 'woocommerce_add_cart_item', array( $this, 'woocommerce_add_cart_item' ), self::HOOK_AFTER_DEFAULT, 1 );
			add_filter( 'woocommerce_add_cart_item_data', array( $this, 'woocommerce_add_cart_item_data' ), self::HOOK_AFTER_DEFAULT, 3 );
		}
		return $type;
	}

    private function validate_product_referer_id( array $product_data ): bool {
    	$product_id = $product_data['product_id'] ?? null;
    	$referer_id = $product_data['flexible_product_fields_product_id'] ?? null;

    	return ( ( $product_id !== null ) && ( $referer_id !== null ) && ( $product_id == $referer_id ) );
	}

	/**
	 * @param int $item_id
	 * @param array $values
	 */
	public function woocommerce_add_order_item_meta( $item_id, $values ) {
    	$fields = $values['flexible_product_fields'] ?? [];
    	if ( $fields && $this->validate_product_referer_id( $values ) ) {
            foreach ( $fields as $field ) {
                $name = $field['name'];
                wc_add_order_item_meta( $item_id, $name, $field['value'] );
            }
        }
    }

	/**
	 * @param int $item_id
	 * @param mixed $item
	 * @param int $order_id
	 */
    public function woocommerce_new_order_item( $item_id, $item, $order_id ) {
		if ( $item instanceof WC_Order_Item_Product ) {
			if ( ! empty( $item->legacy_values ) && ! empty( $item->legacy_values['flexible_product_fields'] )
				&& $this->validate_product_referer_id( $item->legacy_values ) ) {
			    foreach ( $item->legacy_values['flexible_product_fields'] as $field ) {
				    $name = $field['name'];
				    wc_add_order_item_meta( $item_id, $name, $field['value'] );
			    }
		    }
	    }
    }

	/**
	 * @param array $cart_item
	 * @param array $values
	 *
	 * @return mixed
	 */
    public function woocommerce_get_cart_item_from_session( $cart_item, $values ) {
    	$fields = $values['flexible_product_fields'] ?? [];
    	if ( ! $fields || ! $this->validate_product_referer_id( $values ) ) {
        	return $cart_item;
		}

		$cart_item['flexible_product_fields'] = $values['flexible_product_fields'];
		return $this->woocommerce_add_cart_item( $cart_item );
    }

	/**
	 * @param array $cart_item
	 *
	 * @return array mixed
	 */
    public function woocommerce_add_cart_item( $cart_item ) {
    	$fields = $cart_item['flexible_product_fields'] ?? [];
    	if ( ! $fields || ! $this->validate_product_referer_id( $cart_item ) ) {
        	return $cart_item;
		}

    	$extra_cost = 0;
		foreach ( $fields as $field ) {
			if ( isset( $field['price_type'] ) && $field['price_type'] != '' && isset( $field['price'] ) && floatval( $field['price'] ) != 0 ) {
				$price = floatval( $field['price'] );
				$extra_cost += $price;
			}
		}
		$cart_item['data']->set_price( $cart_item['data']->get_price( 'edit' ) + $extra_cost );

        return $cart_item;
    }

	/**
	 * Get field data from posted fields.
	 *
	 * @param array       $field Field.
	 * @param array       $field_type Settings of field type.
	 * @param string|null $value Value of field.
	 * @param int         $product_id Product ID.
	 * @param int         $variation_id Variation ID.
	 *
	 * @return array|bool|WP_Error
	 */
    private function get_field_data( $field, $field_type, $value, $product_id, $variation_id ) {
		$ret = false;

        if ( $value != null ) {
            $ret = array(
                'name' => $field['title'],
                'value' => $value,
            );
            if ( $field['type'] == 'checkbox' ) {
            	if ( !isset( $field['value'] ) ) {
            	    $ret['value'] = __( 'yes', 'flexible-product-fields' );
	            }
	            else {
		            $ret['value'] = $field['value'];
	            }
            }
            if ( $field_type['has_price'] ) {
            	if ( !isset( $field['price_type'] ) ) {
		            $field['price_type'] = 'fixed';
	            }
                if ( isset($field['price_type']) && $field['price_type'] != '' && isset($field['price']) && $field['price'] != '' ) {
                    $ret['price_type'] = $field['price_type'];
                    $ret['price'] = $field['price'];
                }
            }
            if ( $field_type['has_options'] ) {
                foreach ( $field['options'] as $option ) {
                    if ( trim( $option['value'] ) === $ret['value'] ) {
                        $ret['value'] = $option['label'];
                        if ( ! $field_type['has_price_in_options'] ) {
							continue;
						}

						$price_values       = $field['price_values'] ?? [];
						$option_price_type  = $price_values[ $option['value'] ]['price_type'] ?? ( $option['price_type'] ?? '' );
						$option_price_value = $price_values[ $option['value'] ]['price'] ?? ( $option['price'] ?? '' );

						if ( ( $option_price_type === '' ) || ( $option_price_value === '' ) ) {
							continue;
						}

						$ret['price_type'] = $option_price_type;
						$ret['price']      = $option_price_value;
                    }
                }
            }
            if ( isset($ret['price_type']) && $ret['price_type'] != '' && isset($ret['price']) && $ret['price'] != '' ) {
            	if ( $variation_id ) {
            		$product_id = $variation_id;
				}

                $product = wc_get_product( $product_id );
				$price = $this->product_price->calculate_price( floatval( $ret['price'] ), $ret['price_type'], $product );
	            $sign = 1;
	            if ( $price < 0 ) {
		            $sign = -1;
		            $price = $price * $sign;
	            }

	            $price = $sign * $price;
	            $ret['price'] = $price ;

				$price = $this->product_price->multicurrency_calculate_price_to_display( $price );
				$price = $this->product_price->wc_price( $price );

                $ret['value'] .= ' (' . $price . ')';

            }
        }
		return $ret;
    }

	/**
	 * @param array $other_data
	 * @param array $cart_item
	 *
	 * @return array
	 */
    public function woocommerce_get_item_data( $other_data, $cart_item ) {
    	$fields = $cart_item['flexible_product_fields'] ?? [];
    	if ( ! $fields || ! $this->validate_product_referer_id( $cart_item ) ) {
        	return $other_data;
		}

		foreach ( $fields as $field ) {
			$name         = $field['name'];
			$other_data[] = array(
				'name'    => $name,
				'value'   => $field['value'],
				'display' => $field['display'] ?? ''
			);
		}

        return $other_data;
    }

	/**
	 * @param array $cart_item_data
	 * @param int $product_id
	 * @param int $variation_id
	 *
	 * @return array
	 * @throws Exception
	 */
    public function woocommerce_add_cart_item_data( $cart_item_data, $product_id, $variation_id ) {
	    $product_data = wc_get_product( $product_id );
        $fields = $this->_product->get_translated_fields_for_product( $product_data );

        $post_data    = wp_unslash( $_POST );
	    $fields       = apply_filters( 'flexible_product_fields_apply_logic_rules', $fields, $post_data );
		$fields_types = $this->_product_fields->get_field_types_by_type();

		foreach ( $fields['fields'] as $field ) {
			if ( ! isset( $fields_types[ $field['type'] ] ) ) {
				continue;
			}

        	$field_type   = $fields_types[ $field['type'] ];
        	$field_values = $field_type['type_object']->get_field_value( $field['id'] );

			try {
				do_action( 'flexible_product_fields/validate_field', $field, $field_values, $field_type );
			} catch( \Exception $e ) {
				throw new \Exception( $e->getMessage() );
			}

        	if ( ! is_array( $field_values ) ) {
				$field_values = [ $field_values ];
			}

        	foreach ( $field_values as $field_value ) {
				$data = $this->get_field_data( $field, $field_type, $field_value, $product_id, $variation_id );
				if ( $data ) {
					if ( !isset( $cart_item_data['flexible_product_fields'] ) ) {
						$cart_item_data['flexible_product_fields'] = array();
					}
					$cart_item_data['flexible_product_fields'][] = $data;
				}
			}
        }

		if ( isset( $cart_item_data['flexible_product_fields'] ) ) {
			$cart_item_data['flexible_product_fields_product_id'] = $post_data['_fpf_product_id'];
		}

		return $cart_item_data;
    }


}