geno/wp-content/plugins/ti-woocommerce-wishlist/includes/product.helper.php
2024-02-01 11:54:18 +00:00

780 lines
21 KiB
PHP

<?php
/**
* Product function class
*
* @since 1.5.0
* @package TInvWishlist\Products
*/
// If this file is called directly, abort.
if ( ! defined( 'ABSPATH' ) ) {
die;
}
/**
* Product function class
*/
class TInvWL_Product {
/**
* Table name
*
* @var string
*/
private $table;
/**
* Plugin name
*
* @var string
*/
private $_name;
/**
* Wishlist object
*
* @var array
*/
public $wishlist;
/**
* User id
*
* @var integer
*/
public $user;
/**
* Constructor
*
* @param array $wishlist Object wishlist.
* @param string $plugin_name Plugin name.
*
* @global wpdb $wpdb
*
*/
function __construct( $wishlist = array(), $plugin_name = TINVWL_PREFIX ) {
global $wpdb;
$this->wishlist = (array) $wishlist;
$this->_name = $plugin_name;
$this->table = sprintf( '%s%s_%s', $wpdb->prefix, $this->_name, 'items' );
$this->user = $this->wishlist_author();
if ( empty( $this->user ) ) {
$user = wp_get_current_user();
if ( $user->exists() ) {
$this->user = $user->ID;
}
}
add_filter( 'tinvwl_addtowishlist_add_form', array( $this, 'clean_meta' ), 10, 1 );
}
/**
* Get wishlist id
*
* @return int
*/
function wishlist_id() {
if ( is_array( $this->wishlist ) && array_key_exists( 'ID', $this->wishlist ) ) {
return $this->wishlist['ID'];
}
return 0;
}
/**
* Get author wishlist
*
* @return int
*/
function wishlist_author() {
if ( is_array( $this->wishlist ) && array_key_exists( 'author', $this->wishlist ) ) {
return $this->wishlist['author'];
}
return 0;
}
/**
* Add\Update product
*
* @param array $data Object product.
* @param array $meta Object meta form data.
*
* @return boolean
*/
function add_product( $data = array(), $meta = array() ) {
$_data = filter_var_array( $data, array(
'product_id' => FILTER_VALIDATE_INT,
'variation_id' => FILTER_VALIDATE_INT,
'wishlist_id' => FILTER_VALIDATE_INT,
'quantity' => FILTER_VALIDATE_INT,
) );
if ( empty( $_data['quantity'] ) ) {
$_data['quantity'] = 1;
}
if ( empty( $_data['wishlist_id'] ) ) {
$_data['wishlist_id'] = $this->wishlist_id();
}
$product_data = $this->check_product( $_data['product_id'], $_data['variation_id'], $_data['wishlist_id'], $meta );
if ( false === $product_data ) {
return false;
}
if ( $product_data ) {
return $this->update( $data, $meta, $product_data['ID'] );
} else {
return $this->add( $data, $meta );
}
}
/**
* Add product
*
* @param array $data Object product.
* @param array $meta Object meta form data.
*
* @return boolean
* @global wpdb $wpdb
*
*/
function add( $data = array(), $meta = array() ) {
$default = array(
'wishlist_id' => $this->wishlist_id(),
'product_id' => 0,
'variation_id' => 0,
'formdata' => '',
'author' => $this->user,
'date' => current_time( 'Y-m-d H:i:s' ),
'quantity' => 1,
'price' => 0,
'in_stock' => 1,
);
$data = apply_filters( 'tinvwl_wishlist_product_add_field', filter_var_array( $data, array(
'author' => FILTER_VALIDATE_INT,
'product_id' => FILTER_VALIDATE_INT,
'quantity' => FILTER_VALIDATE_INT,
'variation_id' => FILTER_VALIDATE_INT,
'wishlist_id' => FILTER_VALIDATE_INT,
) ) );
$data = array_filter( $data );
$data = tinv_array_merge( $default, $data );
if ( empty( $data['wishlist_id'] ) || empty( $data['product_id'] ) ) {
return false;
}
$product_data = $this->product_data( $data['product_id'], $data['variation_id'] );
if ( $data['quantity'] <= 0 || ! $product_data ) {
return false;
}
if ( $product_data->is_sold_individually() ) {
$data['quantity'] = 1;
}
$data = apply_filters( 'tinvwl_wishlist_product_add', $data );
$data['in_stock'] = $product_data->is_in_stock();
$data['formdata'] = $this->prepare_save_meta( $meta, $data['product_id'], $data['variation_id'] );
if ( $product_data->is_type( 'variable' ) ) {
$data['price'] = filter_var( $product_data->get_variation_price( 'max', false ), FILTER_VALIDATE_FLOAT );
} else {
$data['price'] = filter_var( ( $product_data->get_price() ), FILTER_VALIDATE_FLOAT );
}
global $wpdb;
if ( $wpdb->insert( $this->table, $data ) ) { // @codingStandardsIgnoreLine WordPress.VIP.DirectDatabaseQuery.DirectQuery
$id = $wpdb->insert_id;
/* Run a 3rd party code when product added to a wishlist.
*
* @param array $data product data including author and wishlist IDs.
* */
do_action( 'tinvwl_product_added', $data );
$wla = new TInvWL_Analytics( $this->wishlist );
$wla->cart_product( $data['product_id'], $data['variation_id'] );
return $id;
}
return false;
}
/**
* Get products by wishlist
*
* @param array $data Request.
*
* @return array
*/
function get_wishlist( $data = array(), $count = false ) {
if ( ! array_key_exists( 'wishlist_id', $data ) ) {
$data['wishlist_id'] = $this->wishlist_id();
}
if ( empty( $data['wishlist_id'] ) ) {
return array();
}
return $this->get( $data, $count );
}
/**
* Check existing product
*
* @param integer $product_id Product id.
* @param integer $variation_id Product variaton id.
* @param integer $wishlist_id If exist wishlist object, you can put 0.
* @param array $meta Object meta form data.
*
* @return mixed
*/
function check_product( $product_id, $variation_id = 0, $wishlist_id = 0, $meta = array() ) {
$product_id = absint( $product_id );
$variation_id = absint( $variation_id );
$wishlist_id = absint( $wishlist_id );
if ( empty( $wishlist_id ) ) {
$wishlist_id = $this->wishlist_id();
}
if ( empty( $wishlist_id ) || empty( $product_id ) ) {
return false;
}
$product_data = $this->product_data( $product_id, $variation_id );
if ( ! $product_data ) {
return false;
}
$product_id = $product_data->is_type( 'variation' ) ? $product_data->get_parent_id() : $product_data->get_id();
$variation_id = $product_data->is_type( 'variation' ) ? $product_data->get_id() : 0;
$products = $this->get( array(
'product_id' => $product_id,
'variation_id' => $variation_id,
'wishlist_id' => $wishlist_id,
'formdata' => $this->prepare_save_meta( $meta, $product_id, $variation_id ),
'count' => 1,
'external' => false,
) );
return array_shift( $products );
}
/**
* Get products
*
* @param array $data Request.
* @param bool $count COUNT QUERY.
*
* @return array
* @global wpdb $wpdb
*
*/
function get( $data = array(), $count = false ) {
global $wpdb;
$default = array(
'count' => 10,
'field' => null,
'offset' => 0,
'order' => 'DESC',
'order_by' => 'date',
'external' => true,
'sql' => '',
);
foreach ( $default as $_k => $_v ) {
if ( array_key_exists( $_k, $data ) ) {
$default[ $_k ] = $data[ $_k ];
unset( $data[ $_k ] );
}
}
$default['offset'] = absint( $default['offset'] );
$default['count'] = absint( $default['count'] );
if ( is_array( $default['field'] ) ) {
$default['field'] = '`' . implode( '`,`', $default['field'] ) . '`';
} elseif ( is_string( $default['field'] ) ) {
$default['field'] = array( 'ID', $default['field'] );
$default['field'] = '`' . implode( '`,`', $default['field'] ) . '`';
} else {
$default['field'] = '*';
}
if ( $count ) {
$default['field'] = 'COUNT(`ID`) as `count`';
}
$sql = "SELECT {$default[ 'field' ]} FROM `{$this->table}`";
$where = '1';
if ( ! empty( $data ) && is_array( $data ) ) {
if ( array_key_exists( 'meta', $data ) ) {
unset( $data['meta'] );
}
foreach ( $data as $f => $v ) {
$s = is_array( $v ) ? ' IN ' : '=';
if ( is_array( $v ) ) {
foreach ( $v as $_f => $_v ) {
$v[ $_f ] = $wpdb->prepare( '%s', $_v );
}
$v = implode( ',', $v );
$v = "($v)";
} else {
$v = $wpdb->prepare( '%s', $v );
}
$data[ $f ] = sprintf( '`%s`%s%s', $f, $s, $v );
}
$where = implode( ' AND ', $data );
$sql .= ' WHERE ' . $where;
}
$sql .= sprintf( ' ORDER BY `%s` %s LIMIT %d,%d;', $default['order_by'], $default['order'], $default['offset'], $default['count'] );
if ( ! empty( $default['sql'] ) ) {
$replacer = $replace = array();
$replace[0] = '{table}';
$replacer[0] = $this->table;
$replace[1] = '{where}';
$replacer[1] = $where;
foreach ( $default as $key => $value ) {
$i = count( $replace );
$replace[ $i ] = '{' . $key . '}';
$replacer[ $i ] = $value;
}
$sql = str_replace( $replace, $replacer, $default['sql'] );
}
$products = $wpdb->get_results( $sql, ARRAY_A ); // WPCS: db call ok; no-cache ok; unprepared SQL ok.
if ( empty( $products ) || is_wp_error( $products ) ) {
return array();
}
if ( $count ) {
return $products[0]['count'];
}
$ids = array();
foreach ( $products as $k => $product ) {
if ( empty( $default['sql'] ) ) {
$product = filter_var_array( $product, array(
'ID' => FILTER_VALIDATE_INT,
'wishlist_id' => FILTER_VALIDATE_INT,
'product_id' => FILTER_VALIDATE_INT,
'variation_id' => FILTER_VALIDATE_INT,
'author' => FILTER_VALIDATE_INT,
'date' => FILTER_DEFAULT,
'formdata' => FILTER_DEFAULT,
'quantity' => FILTER_VALIDATE_INT,
'price' => FILTER_SANITIZE_NUMBER_FLOAT | FILTER_FLAG_ALLOW_FRACTION,
'in_stock' => FILTER_VALIDATE_BOOLEAN,
) );
$product['quantity'] = 1;
}
if ( $default['external'] ) {
if ( isset( $product['product_id'] ) ) {
$ids[] = ( apply_filters( 'wpml_object_id', $product['product_id'], 'product', false ) ) ? apply_filters( 'wpml_object_id', $product['product_id'], 'product', false ) : $product['product_id'];
}
}
$product['meta'] = array();
if ( array_key_exists( 'formdata', $product ) ) {
$meta = $product['formdata'];
unset( $product['formdata'] );
$product['meta'] = $this->prepare_retrun_meta( $meta, $product['product_id'], $product['variation_id'], $product['quantity'] );
}
$products[ $k ] = apply_filters( 'tinvwl_wishlist_product_get', $product );
}
if ( ! empty( $ids ) ) {
$args = array(
'include' => $ids,
'limit' => count( $ids ),
);
$_products = wc_get_products( $args );
foreach ( $_products as $_product ) {
foreach ( $products as $key => $wlproduct ) {
if ( ! isset( $wlproduct['product_id'] ) ) {
continue;
}
if ( $_product->get_id() === absint( ( apply_filters( 'wpml_object_id', $wlproduct['product_id'], 'product', false ) ) ? apply_filters( 'wpml_object_id', $wlproduct['product_id'], 'product', false ) : $wlproduct['product_id'] ) ) {
if ( in_array( $_product->get_type(), array( 'variable', 'grouped' ) ) ) {
$use_original_id = false;
if ( function_exists( 'pll_is_translated_post_type' ) ) {
$use_original_id = true;
}
if ( function_exists( 'wpml_get_current_language' ) ) {
global $sitepress;
if ( $sitepress && $sitepress instanceof SitePress ) {
$wpml_settings = $sitepress->get_settings();
if ( isset( $wpml_settings['custom_posts_sync_option'] ) && isset( $wpml_settings['custom_posts_sync_option']['product_variation'] ) && in_array( $wpml_settings['custom_posts_sync_option']['product_variation'], array(
1,
2,
) ) ) {
$use_original_id = true;
}
}
}
$products[ $key ]['data'] = $wlproduct['variation_id'] ? wc_get_product( apply_filters( 'wpml_object_id', $wlproduct['variation_id'], 'product_variation', $use_original_id ) ) : $_product;
} else {
$products[ $key ]['data'] = $_product;
}
}
}
}
// remove deleted products from database
if ( $default['external'] && ! function_exists( 'wpml_get_current_language' ) ) {
foreach ( $products as $key => $product ) {
if ( empty( $product['data'] ) ) {
unset( $products[ $key ] );
$this->remove( $product );
}
}
}
}
// Filter wishlist products
$products = apply_filters( 'tinvwl_wishlist_get_products', $products, $this );
return $products;
}
/**
* Get product info
*
* @param integer $product_id Product id.
* @param integer $variation_id Product variation id.
*
* @return mixed
*/
function product_data( $product_id, $variation_id = 0 ) {
$product_id = absint( $product_id );
$variation_id = absint( $variation_id );
$product_data = apply_filters( 'tinvwl_product_data', wc_get_product( $variation_id ? $variation_id : $product_id ), $product_id, $variation_id );
if ( ! $product_data || 'trash' === get_post( $product_data->get_id() )->post_status ) {
return null;
}
$product_data->variation_id = absint( ( $product_data->is_type( 'variation' ) ? $product_data->get_id() : 0 ) );
return $product_data;
}
/**
* Update product
*
* @param array $data Object product.
* @param array $meta Object meta form data.
* @param int $id Wishlist item ID.
*
* @return boolean
* @global wpdb $wpdb
*
*/
function update( $data = array(), $meta = array(), $id = 0 ) {
if ( empty( $meta ) && array_key_exists( 'meta', $data ) && ! empty( $data['meta'] ) ) {
$meta = $data['meta'];
}
$data = filter_var_array( $data, apply_filters( 'tinvwl_wishlist_product_update_field', array(
'product_id' => FILTER_VALIDATE_INT,
'quantity' => FILTER_VALIDATE_INT,
'variation_id' => FILTER_VALIDATE_INT,
'wishlist_id' => FILTER_VALIDATE_INT,
'author' => FILTER_VALIDATE_INT,
) ) );
$data = array_filter( $data );
if ( ! array_key_exists( 'wishlist_id', $data ) ) {
$data['wishlist_id'] = $this->wishlist_id();
}
if ( ! array_key_exists( 'variation_id', $data ) ) {
$data['variation_id'] = 0;
}
if ( empty( $data['wishlist_id'] ) || empty( $data['product_id'] ) ) {
return false;
}
$product_data = $this->product_data( $data['product_id'], $data['variation_id'] );
if ( ! $product_data ) {
return false;
}
if ( $product_data->is_sold_individually() ) {
$data['quantity'] = 1;
}
$data = apply_filters( 'tinvwl_wishlist_product_update', $data );
$data['in_stock'] = $product_data->is_in_stock();
if ( $product_data->is_type( 'variable' ) ) {
$data['price'] = filter_var( $product_data->get_variation_price( 'max', false ), FILTER_VALIDATE_FLOAT );
} else {
$data['price'] = filter_var( $product_data->get_price(), FILTER_VALIDATE_FLOAT );
}
global $wpdb;
$res_update = $wpdb->update( $this->table, $data, array(
'product_id' => $data['product_id'],
'variation_id' => $data['variation_id'],
'wishlist_id' => $data['wishlist_id'],
'formdata' => $this->prepare_save_meta( $meta, $data['product_id'], $data['variation_id'] ),
) );
if ( $res_update !== false ) { // @codingStandardsIgnoreLine WordPress.VIP.DirectDatabaseQuery.DirectQuery
/* Run a 3rd party code when product updated on a wishlist.
*
* @param array $data product data including author and wishlist IDs.
* */
do_action( 'tinvwl_product_updated', $data );
return ( $id ) ? $id : true;
}
return false;
}
/**
* Remove product from wishlist.
*
* @param int $wishlist_id If exist wishlist object, you can put 0.
* @param int $product_id Product ID.
* @param int $variation_id Product variation ID.
* @param array $meta Object meta form data.
*
* @return bool
*/
function remove_product_from_wl( int $wishlist_id = 0, int $product_id = 0, int $variation_id = 0, array $meta = [] ): bool {
global $wpdb;
if ( empty( $wishlist_id ) ) {
$wishlist_id = $this->wishlist_id();
}
if ( empty( $wishlist_id ) ) {
return false;
}
if ( empty( $product_id ) ) {
return false !== $wpdb->delete( $this->table, [ 'wishlist_id' => $wishlist_id ] ); // WPCS: db call ok; no-cache ok; unprepared SQL ok.
}
$original_meta = $meta;
if ( ! empty( $meta ) && array_key_exists( 'tinvwl-hidden-fields', $meta ) ) {
unset( $meta['tinvwl-hidden-fields'] );
}
$data = [
'wishlist_id' => $wishlist_id,
'product_id' => $product_id,
'variation_id' => $variation_id,
];
$data['formdata'] = $this->prepare_save_meta( $meta, $data['product_id'], $data['variation_id'] );
$data['original_meta'] = $this->prepare_save_meta( $original_meta, $data['product_id'], $data['variation_id'] );
$sql = "DELETE FROM $this->table WHERE `wishlist_id` = %d AND `product_id` = %d AND `variation_id` = %d";
$args = [ $data['wishlist_id'], $data['product_id'], $data['variation_id'] ];
if ( ! empty( $meta ) ) {
$sql .= " AND (`formdata` = %s OR `formdata` = %s OR `formdata` = %s OR `formdata` = %s)";
$args[] = $data['formdata'];
$args[] = $data['original_meta'];
$args[] = '{"tinvwl-hidden-fields":"[]"}';
$args[] = '';
}
$prepared_sql = $wpdb->prepare( $sql, $args );
$result = $wpdb->query( $prepared_sql );
if ( $result ) {
do_action( 'tinvwl_wishlist_product_removed_from_wishlist', $wishlist_id, $product_id, $variation_id );
}
return (bool) $result;
}
/**
* Remove product
*
* @param integer $product_id Product id.
*
* @return boolean
* @global wpdb $wpdb
*
*/
function remove_product( $product_id = 0 ) {
if ( empty( $product_id ) ) {
return false;
}
global $wpdb;
$result = false !== $wpdb->delete( $this->table, array( 'product_id' => $product_id ) ); // WPCS: db call ok; no-cache ok; unprepared SQL ok.
if ( $result ) {
do_action( 'tinvwl_wishlist_product_removed_by_product', $product_id );
}
return $result;
}
/**
* Get wishlist data by product from wishlist
*
* @param integer $product_id Product id.
*
* @return bool|array
* @global wpdb $wpdb
*
*/
function get_wishlist_by_product_id( $product_id = 0 ) {
if ( empty( $product_id ) ) {
return false;
}
global $wpdb;
$sql = "SELECT `wishlist_id` FROM `{$this->table}` WHERE `ID`={$product_id}";
$result = $wpdb->get_results( $sql, ARRAY_A );
if ( ! $result ) {
return false;
}
$wl = new TInvWL_Wishlist();
return $wl->get_by_id( $result[0]['wishlist_id'] );
}
/**
* Remove product by ID
*
* @param array $data Product data.
*
* @return boolean
* @global wpdb $wpdb
*
*/
function remove( $data ) {
if ( ! isset( $data['ID'] ) || empty( $data['ID'] ) ) {
return false;
}
global $wpdb;
$result = false !== $wpdb->delete( $this->table, array( 'ID' => $data['ID'] ) ); // WPCS: db call ok; no-cache ok; unprepared SQL ok.
if ( $result ) {
/* Run a 3rd party code when product removed from a wishlist.
*
* @param array $data product data including author and wishlist IDs.
* */
do_action( 'tinvwl_product_removed', $data );
}
return $result;
}
/**
* Clean meta from default values.
*
* @param array $meta Meta array.
*
* @return array
*/
function clean_meta( $meta ) {
foreach (
array(
'add-to-cart',
'product_id',
'variation_id',
'quantity',
'undefined',
'product_sku',
) as $field
) {
if ( array_key_exists( $field, $meta ) ) {
unset( $meta[ $field ] );
}
}
$meta = array_filter( $meta );
return $meta;
}
/**
* Prepare to save meta in database
*
* @param array $meta Meta array.
* @param int $product_id Woocommerce product ID.
* @param int $variation_id Woocommerce product variation ID.
*
* @return string
*/
function prepare_save_meta( $meta = array(), $product_id = 0, $variation_id = 0 ) {
if ( ! is_array( $meta ) ) {
$meta = array();
}
$meta = apply_filters( 'tinvwl_product_prepare_meta', $meta, $product_id, $variation_id );
foreach (
array(
'add-to-cart',
'product_id',
'variation_id',
'quantity',
'undefined',
'product_sku',
) as $field
) {
if ( array_key_exists( $field, $meta ) ) {
unset( $meta[ $field ] );
}
}
$meta = array_filter( $meta );
if ( empty( $meta ) ) {
return '';
}
return json_encode( $meta );
}
/**
* Convert meta string to array
*
* @param string $meta Meta array.
* @param integer $product_id Product ID.
* @param integer $variation_id Variation product ID.
* @param integer $quantity Quantity product.
*
* @return array
*/
function prepare_retrun_meta( $meta = '', $product_id = 0, $variation_id = 0, $quantity = 1 ) {
if ( empty( $meta ) ) {
return array();
}
$meta = @json_decode( $meta, true );
if ( empty( $meta ) || ! is_array( $meta ) ) {
return array();
}
if ( ! empty( $product_id ) ) {
$meta['add-to-cart'] = $product_id;
$meta['product_id'] = $product_id;
$meta['quantity'] = $quantity;
if ( ! empty( $variation_id ) ) {
$meta['variation_id'] = $variation_id;
}
}
return apply_filters( 'tinvwl_wishlist_product_unprepare_meta', $meta );
}
}