HEX
Server: Apache
System: Linux webd006.cluster128.gra.hosting.ovh.net 6.18.42-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Wed Aug 5 15:59:48 CEST 2026 x86_64
User: zwafgyp (177615)
PHP: 7.4.33
Disabled: _dyuweyrj4,_dyuweyrj4r,dl
Upload Files
File: /home/zwafgyp/lacalita/wp-content/plugins/rey-core/inc/modules/variation-swatches/frontend.php
<?php
namespace ReyCore\Modules\VariationSwatches;

if (!defined('ABSPATH')) exit; // Exit if accessed directly

class Frontend
{

	public $loop_variations;

	public static $scrips_loaded;

	public $args = [];

	public $swatch_html;

	const CATALOG_MODE = 'rey_swatch_catalog_mode';

	public function __construct()
	{
		add_action( 'reycore/assets/register_scripts', [$this, 'register_assets']);
		add_action( 'wp_enqueue_scripts', [$this, 'enqueue_scripts']);
		add_action( 'reycore/woocommerce/product_page/scripts', [$this, 'enqueue_scripts']);
		add_action( 'reycore/module/after-atc-popup/scripts', [$this, 'load_scripts']);
		add_filter( 'woocommerce_dropdown_variation_attribute_options_html', [$this, 'variation_dropdown_start'], -1);
		add_filter( 'woocommerce_dropdown_variation_attribute_options_html', [$this, 'variation_dropdown_end'], 2000);
		add_filter( 'woocommerce_dropdown_variation_attribute_options_html', [$this, 'variation_dropdown'], 100, 2);
		add_filter( 'woocommerce_dropdown_variation_attribute_options_args', [$this, 'variation_dropdown_args'], 100);
		add_filter( 'woocommerce_ajax_variation_threshold', [$this, 'ajax_variation_threshold'], 10, 2 );
		add_filter( 'reycore/woocommerce/variations/variation_attribute_data', [$this, 'variation_attribute_data'] );
		add_action( 'reycore/woocommerce/variations/catalog/render_single', [$this, 'catalog_render_single_swatch'], 10, 2);
		add_action( 'reycore/woocommerce/variations/catalog/render_all', [$this, 'catalog_render_all_swatches'], 10, 2);
		add_filter( 'post_class', [$this, 'product_classes'], 30 );
		add_filter( 'woocommerce_reset_variations_link', [$this, 'reset_variations_link']);
		add_action( 'reycore/ajax/register_actions', [ $this, 'register_actions' ] );
		add_filter( 'rey/main_script_params', [$this, 'script_params']);
		add_filter( 'wp_footer', [$this, 'load_variations_template_catalog']);
		add_action( 'woocommerce_after_variations_table', [$this, 'table_rows_classes']);
		add_filter( 'woocommerce_available_variation', [$this, 'set_stock_status'], 10, 3);

	}

	/**
	 * Register Ajax Actions
	 *
	 * @param object $ajax_manager
	 * @return void
	 */
	public function register_actions( $ajax_manager ){
		// $ajax_manager->register_ajax_action( 'variations_load_catalog', [$this, 'ajax__lazy_load_catalog'], 3 );
	}

	public function get_product(){

		global $post;

		if( ! isset($post->ID) ){
			return;
		}

		$product_id = $post->ID && ('product' === get_post_type()) ? $post->ID : false;

		if( ! ( $product = wc_get_product( $product_id ) ) ){
			return;
		}

		return $product;
	}

	/**
	 * Product page load assets
	 *
	 * @return void
	 */
	public function enqueue_scripts(){

		if( Base::$settings['optimized_assets_load'] ){
			return;
		}

		if( ! reycore_wc__is_product() ){
			return;
		}
		$product = $this->get_product();

		if ( ! ($product && 'variable' === $product->get_type()) ) {
			return;
		}

		self::load_scripts();
	}

	public static function get_asset_handle( $type ){
		return Base::ASSET_HANDLE . '-' . $type;
	}

	/**
	 * Load frontend CSS and JS
	 *
	 * @return void
	 */
	public static function load_scripts(){

		if( self::$scrips_loaded ){
			return;
		}

		reycore_assets()->add_scripts([Base::ASSET_HANDLE, 'wc-add-to-cart-variation']);
		reycore_assets()->add_styles([Base::ASSET_HANDLE . '-lite', Base::ASSET_HANDLE]);

		self::$scrips_loaded = true;
	}

	/**
	 * Register mod assets
	 *
	 * @return void
	 */
	public function register_assets($assets){

		$assets->register_asset('styles', [
			Base::ASSET_HANDLE . '-lite' => [
				'src'      => Base::get_path( basename( __DIR__ ) ) . '/frontend-style-lite.css',
				'deps'     => [],
				'version'  => REY_CORE_VERSION,
				'priority' => 'high',
			]
		]);

		$assets->register_asset('styles', [
			Base::ASSET_HANDLE => [
				'src'      => Base::get_path( basename( __DIR__ ) ) . '/frontend-style.css',
				'deps'     => [Base::ASSET_HANDLE . '-lite'],
				'version'  => REY_CORE_VERSION,
				'priority' => 'low',
			]
		]);

		$assets->register_asset('scripts', [
			Base::ASSET_HANDLE => [
				'src'     => Base::get_path( basename( __DIR__ ) ) . '/frontend-script.js',
				'deps'    => ['reycore-woocommerce'],
				'version'   => REY_CORE_VERSION,
			]
		]);

	}

	public function script_params($params){
		$params['updateCatalogPriceSingleAttribute'] = Base::$settings['update_catalog_price_if_single_attribute'];
		return $params;
	}

	public function can_add_swatches(){
		return apply_filters('reycore/variation_swatches/support', true);
	}

	public function variation_dropdown_args( $args ){

		if( ! $this->can_add_swatches() ){
			return $args;
		}

		global $product;

		// replace id html attribute to be unique
		if( $product && ($product_id = $product->get_id()) ){

			if( get_queried_object_id() === $product_id ){
				if( Base::$settings['update_product_page_url'] ){
					$args['class'] = '--update-url';
				}
			}
			else {
				$args['id'] = $args['attribute'] . $product_id;
			}
		}

		$attribute_name = str_replace('pa_', '', $args['attribute']);

		if( $attribute_name === get_theme_mod('pdp_swatches__update_gallery', '') ){
			$args['class'] = '--update';
		}

		// Activate single variations from lists
		if(
			Base::$settings['autoselect_single_variation'] &&
			((isset( $args['selected'] ) && '' === $args['selected']) || ! isset( $args['selected'] )) &&
			isset( $args['options'] ) && 1 === count($args['options'])
		){
			$args['selected'] = $args['options'][0];
		}

		return $args;
	}

	public function variation_dropdown_start($html){
		return '<div class="__s-wrapper">' . $html;
	}

	public function variation_dropdown_end($html){
		return $html . '</div>';
	}

	public function table_rows_classes(){
		?><script type="text/javascript" id="reycore-variations-row-classes">
			document.querySelectorAll('.variations_form .variations tr [data-tr-class]').forEach(list => {
				var row = list.closest('tr');
				row.classList.add( list.getAttribute('data-tr-class') );
				row.setAttribute( 'data-id', list.getAttribute('data-tr-attribute') );
			});
		</script>
		<?php
	}

	/**
	 * Filter the variation dropdown, hide it and add html
	 *
	 * @param string $html
	 * @param array $args
	 * @return string
	 */
	public function variation_dropdown($html, $args){

		if( ! $this->can_add_swatches() ){
			return $html;
		}

		$this->swatch_html = $this->get_swatch_list_output($args);

		$html = apply_filters('reycore/variation_dropdown/before_render', $html, $this, $args);

		if( ! $this->swatch_html ){
			return $html;
		}

		$style_search = '<select ';
		$style_replace = 'style="display:none" ';

		$html = str_replace($style_search, $style_search . $style_replace, $html);

		if( ! Base::$settings['autoselect_catalog_variation'] && ! \ReyCore\WooCommerce\Pdp::is_single_true_product() ){
			$html = str_replace(' selected=', ' data-selected=', $html);
		}

		return $html . $this->swatch_html;
	}

	/**
	 * Outputs swatches list
	 *
	 * @param array $attribute
	 * @return string
	 */
	public function get_swatch_list_output( $args ){

		if( empty($args['options']) ){
			return;
		}

		if( ! ($taxonomy = $args['attribute']) ){
			return;
		}

		$attribute = [];

		$custom_attribute = false;

		$attribute_id = wc_attribute_taxonomy_id_by_name($taxonomy);

		if( $attribute_id && 0 !== strpos( $taxonomy, 'pa_') ){
			$attribute_id = false;
		}

		// custom attributes
		if( ! $attribute_id ){

			if( get_theme_mod('pdp_swatches__custom_use_button', false) ){

				$attribute = [
					'name'         => $taxonomy,
					'slug'         => sanitize_title( $taxonomy ),
					'type'         => Base::instance()->get_default_swatch(),
					'order_by'     => false,
					'has_archives' => false,
				];

				if( ($custom_attributes_data = self::get_custom_attributes_data()) && isset($custom_attributes_data[ $taxonomy ])  ){
					$attribute['type'] = $custom_attributes_data[ $taxonomy ]['type'];
				}

				$custom_attribute = true;
			}

			// bail bc. there's no attribute data
			else {
				return;
			}
		}
		else {
			$attribute = (array) wc_get_attribute($attribute_id);
		}

		if( empty($attribute) ){
			return;
		}

		// the scripts are only loaded for Rey's swatches, which is fine,
		// but the select is also needed to start the scripts properly
		if( 'select' === $attribute['type'] && Base::$settings['optimized_assets_load'] ){
			self::load_scripts();
		}

		if ( ! array_key_exists( $attribute['type'], Base::instance()->get_swatches_list() ) ) {
			return;
		}

		if( Base::$settings['optimized_assets_load'] ){
			self::load_scripts();
		}

		$list_args = $args;
		$list_args['attribute_data'] = $attribute;
		$list_args['custom_attribute'] = $custom_attribute;

		if( self::is_catalog_mode() && \ReyCore\Modules\VariationSwatches\SwatchLargeButton::TYPE_KEY === $attribute['type'] ){
			// get taxonomy's Large button settings
			$attribute_settings = Base::get_attributes_swatch_settings( $list_args['attribute_data']['slug'] );
			// set the type to fallback
			$attribute['type'] = isset($attribute_settings['swatch_fallback']) && ($fallback = $attribute_settings['swatch_fallback']) ? $fallback : 'rey_color';
		}

		return Base::instance()->get_swatches( $attribute['type'] )->render_list( $list_args );
	}

	public static function get_custom_attributes_data(){
		return apply_filters('reycore/variation_swatches/custom_attributes', []);
	}

	/**
	 * Checks if catalog mode
	 *
	 * @return boolean
	 */
	public static function is_catalog_mode(){
		return get_query_var(self::CATALOG_MODE, false);
	}

	public function ajax_variation_threshold( $threshold, $product ){

		// Force bump the treshold when "Disabled" or "Out of stock" variations
		// is enabled so that it's able to visually handle them.
		if( get_theme_mod('single_product_hide_out_of_stock_variation', true) ){
			return 100;
		}

		if( $custom = absint(get_theme_mod('pdp_swatches__ajax_threshold', 50)) ){
			return $custom;
		}

		return $threshold;
	}

	function variation_attribute_data( $data ){

		if( ! $this->can_add_swatches() ){
			return $data;
		}

		$attribute_id = wc_attribute_taxonomy_id_by_name($data['taxonomy_name']);
		$attribute = (array) wc_get_attribute($attribute_id);

		if ( isset($attribute['type']) && array_key_exists( $attribute['type'], Base::instance()->get_swatches_list() ) ) {
			$data['type'] =  $attribute['type'];
		}

		return $data;
	}

	public function set_stock_status( $available_attr, $product, $variation ){

		if( is_admin() ){
			return $available_attr;
		}

		$available_attr['stock_status'] = $variation->get_stock_status();

		return $available_attr;
	}

	public function get_transient_name($product_id){
		return \ReyCore\WooCommerce\Tags\VariationsLoop::transient_name( $product_id );
	}

	public function ajax__lazy_load_catalog( $data ){
	}

	/**
	 * Handle ajax variations loaded in product page.
	 * Makes a call to extract unavailable variations.
	 * Work in progress.
	 *
	 * @param array $a_data
	 * @return array
	 */
	public function ajax__variations_pdp( $a_data ){

		if( ! (isset($a_data['pid']) && ($product_id = absint($a_data['pid'])))){
			return;
		}

		if( ! ($product = wc_get_product($product_id)) ){
			return;
		}

		/**
		 * @var \WC_Product_Variable $product
		 */
		$available_variations = $product->get_available_variations();

		$unavailable_variations = [];

        foreach ($available_variations as $var) {

			if( ! $var['is_purchasable'] ){
				$unavailable_variations[] = $var['attributes'];
				continue;
			}

			if( ! $var['variation_is_active'] ){
				$unavailable_variations[] = $var['attributes'];
				continue;
			}

			if( ! $var['variation_is_visible'] ){
				$unavailable_variations[] = $var['attributes'];
				continue;
			}

			if( ! $var['is_in_stock'] && ! $var['backorders_allowed'] ){
				$unavailable_variations[] = $var['attributes'];
				continue;
			}

        }

		return $unavailable_variations;
	}

	protected function get_catalog_data( $product, $tax = '' ){

		$data = false;

		$product_id = $product->get_id();

		if( Base::$settings['loop_cache'] ){
			$data = get_transient( $this->get_transient_name($product_id) );
		}

		if( false === $data ){

			$data = '';

			$attributes = $product->get_variation_attributes();

			if( ! empty($attributes) ){

				$attr_output = '';

				foreach ( $attributes as $attribute_name => $options ) :

					if( $tax ){
						if( $attribute_name !== $tax ){
							continue;
						}
						if( count($options) === 1 && ! Base::$settings['catalog_show_single'] ){
							continue;
						}
					}

					ob_start();

					if( ! $tax && Base::$settings['show_all_labels'] ){
						printf('<div class="rey-swatchList-label"><label for="%s">%s</label></div>',
							esc_attr( sanitize_title( $attribute_name ) ),
							wc_attribute_label( $attribute_name )
						); // WPCS: XSS ok.
					}

					$dropdown_args = [
						'options'   => $options,
						'attribute' => $attribute_name,
						'product'   => $product,
					];

					$options_count = count($options);

					if( $tax ){
						if( ($limit = get_theme_mod('woocommerce_loop_variation_limit', 0)) && $limit < $options_count ){
							$dropdown_args['limit'] = $limit;
							$dropdown_args['limit_diff'] = $options_count - $limit;
							$dropdown_args['options'] = array_slice($options, 0, $limit);
						}
					}

					// set catalog mode
					set_query_var(self::CATALOG_MODE, true);

					wc_dropdown_variation_attribute_options( $dropdown_args );

					// reset
					set_query_var(self::CATALOG_MODE, false);

					$attr_output .= ob_get_clean();

				endforeach;

				if( $attr_output ){
					$data = sprintf('<form class="variations_form cart --catalog" action="%1$s" method="post" enctype="multipart/form-data" data-product_id="%2$s" data-product_variations="%3$s" data-atc-text="%4$s"><div class="variations">%5$s</div></form>',
						esc_url( apply_filters( 'woocommerce_add_to_cart_form_action', $product->get_permalink() ) ),
						absint( $product->get_id() ),
						wc_esc_json( wp_json_encode( $product->get_available_variations() ) ),
						esc_attr( $product->single_add_to_cart_text() ),
						$attr_output
					);
				}
			}

			if( Base::$settings['loop_cache'] ){
				set_transient( $this->get_transient_name($product_id), $data, MONTH_IN_SECONDS );
			}

		}

		return $data;
	}

	public function catalog_render( $product, $tax = '' ){

		// $over_threshold = count( $product->get_children() ) >= apply_filters( 'woocommerce_ajax_variation_threshold', 30, $product );
		$over_threshold = false;

		$data = false;

		if( ! $over_threshold ){
			$data = $this->get_catalog_data( $product, $tax );
		}

		if( $data || $over_threshold ){

			$position = get_theme_mod('woocommerce_loop_variation_position', 'after');
			$all = 'all_attributes' === $this->loop_variations->selected_attribute_taxonomy;

			$html_list_classes = [
				'rey-productVariations2',
				($all) ? '--all-attr' : '--single-attr',
				$over_threshold ? '--ajax' : '',
			];

			if(
				! $all &&
				get_theme_mod('woocommerce_loop_variation_single_click', false)
			 ){
				$html_list_classes[] = '--redirect-pdp';
			}

			if(
				in_array($position, ['first', 'before'], true) &&
				! $all &&
				get_theme_mod('woocommerce_loop_variation__side', false)
			 ){
				$html_list_classes[] = '--side';
			}

			$html_list_attributes = [
				'data-attribute' => esc_attr( $this->loop_variations->selected_attribute_taxonomy ),
				'data-position' => esc_attr( get_theme_mod('woocommerce_loop_variation_position', 'after') ),
			];

			$html_list_attributes['class'] = esc_attr( implode(' ', apply_filters('reycore/variation_swatches/catalog_classes', $html_list_classes) ) );

			printf('<div %s>%s</div>', reycore__implode_html_attributes($html_list_attributes),  $data);

			self::load_scripts();

		}

		else if( Base::$settings['show_empty_catalog_div'] ){
			echo '<div class="rey-productVariations2"></div>';
		}

	}

	function catalog_render_all_swatches( $product, $rey_catalog_variations ){
		if( ! $this->can_add_swatches() ){
			return;
		}
		$this->loop_variations = $rey_catalog_variations;
		$this->catalog_render( $product );
	}

	function catalog_render_single_swatch( $product, $rey_catalog_variations ){
		if( ! $this->can_add_swatches() ){
			return;
		}
		$this->loop_variations = $rey_catalog_variations;
		$this->catalog_render( $product, $this->loop_variations->selected_attribute_taxonomy_data['taxonomy_name'] );
	}

	/**
	 * Adds custom classes to the product element (div/li)
	 *
	 * @param array $classes
	 * @return array
	 */
	function product_classes( $classes ){

		if( ! $this->can_add_swatches() ){
			return $classes;
		}

		$product = $this->get_product();

		if ( ! $product ) {
			return $classes;
		}

		$classes['swatches'] = 'rey-swatches';
		$classes['show_selected'] = ($show_sel = get_theme_mod('pdp_swatches__selected_name_v2', '')) ? 'rey-swatches--show-selected--' . esc_attr($show_sel) : '';
		$classes['stretch_labels'] = get_theme_mod('pdp_swatches__stretch_label', false) ? 'rey-swatches--stretch-labels' : '';

		if( '' !== get_theme_mod('pdp_swatches__update_gallery', '') ){
			$classes['update_gallery'] = '--swatch-update-gallery';
		}

		return $classes;
	}

	/**
	 * Reset button
	 *
	 * @since 2.2.2
	 **/
	function reset_variations_link( $html )
	{

		if( ! $this->swatch_html ){
			return $html;
		}

		if( ! in_array(get_theme_mod('pdp_swatches__deselection', 'clear'), ['clear', 'both'], true) ){
			return;
		}

		return '<a class="rey-resetVariations --hidden" href="#">' . esc_html__( 'Clear', 'woocommerce' ) . '</a>';
	}

	public static function extract_custom_image($data){

		if( ! $data ){
			return;
		}

		$custom_image_url = false;

		if( isset($data['url']) && ($img_url = $data['url']) ){
			$custom_image_url = $img_url;
		}

		else if( isset($data['id']) && ($img_id = $data['id']) ) {
			$custom_image_url = wp_get_attachment_url($img_id);
		}

		if( $custom_image_url ){
			return sprintf('background-image:url(%s);', $custom_image_url );
		}

	}

	public function load_variations_template_catalog(){

		if( is_admin() || is_404() ){
			return;
		}

		if( is_account_page() || is_cart() || is_checkout() ){
			return;
		}

		if( 'disabled' === get_theme_mod('woocommerce_loop_variation', 'disabled') ){
			return;
		}

		wc_get_template( 'single-product/add-to-cart/variation.php' );

	}

}