<?php
/**
 * Class: Eac_Custom_Attributes
 *
 * Description: Cré la section et le control nécessaire pour valoriser les attributs
 * Affecte des attributs (Key|Value) aux sections, colonnes et éléments avant le rendu
 *
 * @since 1.6.6
 */

namespace EACCustomWidgets\Includes\Elementor\CustomAttributes;

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

use Elementor\Controls_Manager;
use Elementor\Element_Base;

class Eac_Custom_Attributes {

	/**
	 * Add Action hook
	 */
	public function __construct() {
		add_action( 'elementor/element/after_section_end', array( $this, 'eac_attributes_controls_section' ), 10, 2 );
		add_action( 'elementor/frontend/before_render', array( $this, 'eac_render_attributes' ) );
	}

	/**
	 * eac_attributes_controls_section
	 *
	 * Supprime le control 'custom_attributes_pro' de la version PRO
	 * Ajout de la nouvelle section et du control
	 *
	 * @param Element_Base $element        abstract class Element_Base extends Controls_Stack
	 * @param String       $section_id
	 * @param Array        $args
	 */
	public function eac_attributes_controls_section( $element, $section_id ) {

		if ( ! $element instanceof Element_Base ) {
			return;
		}

		// Le control PRO existe
		if ( 'section_custom_attributes_pro' === $section_id ) {
			$section_pro = \Elementor\Plugin::$instance->controls_manager->get_control_from_stack( $element->get_unique_name(), $section_id );

			if ( ! is_wp_error( $section_pro ) && in_array( $section_pro['tab'], array( 'advanced' ), true ) ) {
				\Elementor\Plugin::$instance->controls_manager->remove_control_from_stack( $element->get_unique_name(), array( $section_id, 'custom_attributes_pro' ) );

				$element->start_controls_section(
					'eac_custom_element_attributes',
					array(
						'label' => esc_html__( 'Custom attributes', 'eac-components' ),
						'tab'   => Controls_Manager::TAB_ADVANCED,
					)
				);

				$element->add_control(
					'eac_attributes',
					array(
						'label'       => esc_html__( 'Add your attributes', 'eac-components' ),
						'type'        => Controls_Manager::TEXTAREA,
						'placeholder' => esc_html__( 'Key|Value', 'eac-components' ),
						'dynamic'     => array(
							'active' => true,
						),
						'render_type' => 'none',
						'classes'     => 'elementor-control-direction-ltr',
					)
				);

				$element->add_control(
					'eac_attributes_usage',
					array(
						'type' => Controls_Manager::RAW_HTML,
						'raw'  => sprintf(
							'%1$s %2$s%3$s%4$s',
							esc_html__( "Separate the attribute key from the value using the character pipe '|'. Each attribute on a separate line", 'eac-components' ),
							'<a href="https://elementor-addon-components.com/add-your-custom-attributes-with-elementor/#how-to-add-attributes-to-an-element" target="_blank" rel="noopener noreferrer">',
							esc_html__( 'Consult the documentation', 'eac-components' ),
							'</a>'
						),
						'content_classes' => 'elementor-descriptor',
					)
				);

				$element->end_controls_section();
			}
		}
	}

	/**
	 * eac_render_attributes
	 *
	 * Affecte les Key|Value au wrapper de l'élément Section, Column ou Widget
	 *
	 * @param Element_Base $element
	 */
	public function eac_render_attributes( $element ) {
		$settings = $element->get_settings_for_display();

		// Le control existe et il est renseigné
		if ( isset( $settings['eac_attributes'] ) && ! empty( $settings['eac_attributes'] ) ) {
			/**console_log('Element name::' . $element->get_name() . "::" . $element->get_type() . "::" . json_encode($element->get_raw_data()));*/

			// Analyse du contenu du control
			$attributes = $this->parse_custom_attributes( $settings['eac_attributes'], "\n" );

			// La liste des attributs interdits
			$black_list = $this->get_black_list_attributes();

			foreach ( $attributes as $attribute => $value ) {
				if ( ! in_array( $attribute, $black_list, true ) ) {
					$element->add_render_attribute( '_wrapper', $attribute, $value );
				}
			}
		}
	}

	/**
	 * parse_custom_attributes
	 *
	 * Retourne un tableau filtré de Key|Value
	 *
	 * @param String $attributes_string Le tableau des attributs à analyser
	 * @param String $delimiter Le séparateur des 'Key|Value'
	 */
	private function parse_custom_attributes( $attributes_string, $delimiter = ',' ) {
		$attributes = explode( $delimiter, $attributes_string );
		$result     = array();

		/** Boucle sur les Clé|Valeur */
		foreach ( $attributes as $attribute ) {
			$attr_key_value = explode( '|', $attribute );

			$attr_key = mb_strtolower( $attr_key_value[0], 'UTF-8' );

			// Recherche les caractères autorisés dans la clé
			preg_match( '/[-_a-z0-9]+/', $attr_key, $attr_key_matches );

			if ( empty( $attr_key_matches[0] ) ) {
				continue;
			}

			$attr_key = $attr_key_matches[0];

			/**
			 * On saute les événements Javascript, la clé href because injection XSS et les styles
			 */
			if ( 'href' === $attr_key || 'on' === substr( $attr_key, 0, 2 ) || 'style' === $attr_key ) {
				continue;
			}

			if ( isset( $attr_key_value[1] ) ) {
				$attr_value = trim( $attr_key_value[1] );
			} else {
				$attr_value = '';
			}
			$result[ $attr_key ] = $attr_value;
		}
		return $result;
	}

	/**
	 * get_black_list_attributes
	 *
	 * Retourne la liste des attributs interdits utilisés dans les section, colonne, widget et container Elementor
	 */
	private function get_black_list_attributes() {
		static $black_list = null;

		if ( null === $black_list ) {
			$black_list = array( 'id', 'class', 'data-id', 'data-settings', 'data-element_type', 'data-widget_type', 'data-model-cid' );

			/**
			 * Liste des attributs d'Elementor qui ne sont pas autorisés
			 *
			 * Filtrer/Exclure les attributs utilisés en standard par Elementor
			 *
			 * Protéger Elementor des attributs qui ne peuvent être utilisés pour éviter un crash
			 *
			 * @param array $black_list Liste des attributs à éviter.
			 */
			$black_list = apply_filters( 'elementor/element/attributes/black_list', $black_list );
		}
		return $black_list;
	}
}
