balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

base.php (14253B)


      1 <?php
      2 namespace Elementor;
      3 
      4 if ( ! defined( 'ABSPATH' ) ) {
      5 	exit; // Exit if accessed directly.
      6 }
      7 
      8 /**
      9  * Elementor group control base.
     10  *
     11  * An abstract class for creating new group controls in the panel.
     12  *
     13  * @since 1.0.0
     14  * @abstract
     15  */
     16 abstract class Group_Control_Base implements Group_Control_Interface {
     17 
     18 	/**
     19 	 * Arguments.
     20 	 *
     21 	 * Holds all the group control arguments.
     22 	 *
     23 	 * @access private
     24 	 *
     25 	 * @var array Group control arguments.
     26 	 */
     27 	private $args = [];
     28 
     29 	/**
     30 	 * Options.
     31 	 *
     32 	 * Holds all the group control options.
     33 	 *
     34 	 * Currently supports only the popover options.
     35 	 *
     36 	 * @access private
     37 	 *
     38 	 * @var array Group control options.
     39 	 */
     40 	private $options;
     41 
     42 	/**
     43 	 * Get options.
     44 	 *
     45 	 * Retrieve group control options. If options are not set, it will initialize default options.
     46 	 *
     47 	 * @since 1.9.0
     48 	 * @access public
     49 	 *
     50 	 * @param array $option Optional. Single option.
     51 	 *
     52 	 * @return mixed Group control options. If option parameter was not specified, it will
     53 	 *               return an array of all the options. If single option specified, it will
     54 	 *               return the option value or `null` if option does not exists.
     55 	 */
     56 	final public function get_options( $option = null ) {
     57 		if ( null === $this->options ) {
     58 			$this->init_options();
     59 		}
     60 
     61 		if ( $option ) {
     62 			if ( isset( $this->options[ $option ] ) ) {
     63 				return $this->options[ $option ];
     64 			}
     65 
     66 			return null;
     67 		}
     68 
     69 		return $this->options;
     70 	}
     71 
     72 	/**
     73 	 * Add new controls to stack.
     74 	 *
     75 	 * Register multiple controls to allow the user to set/update data.
     76 	 *
     77 	 * @since 1.0.0
     78 	 * @access public
     79 	 *
     80 	 * @param Controls_Stack $element   The element stack.
     81 	 * @param array          $user_args The control arguments defined by the user.
     82 	 * @param array          $options   Optional. The element options. Default is
     83 	 *                                  an empty array.
     84 	 */
     85 	final public function add_controls( Controls_Stack $element, array $user_args, array $options = [] ) {
     86 		$this->init_args( $user_args );
     87 
     88 		// Filter which controls to display
     89 		$filtered_fields = $this->filter_fields();
     90 		$filtered_fields = $this->prepare_fields( $filtered_fields );
     91 
     92 		// For php < 7
     93 		reset( $filtered_fields );
     94 
     95 		if ( isset( $this->args['separator'] ) ) {
     96 			$filtered_fields[ key( $filtered_fields ) ]['separator'] = $this->args['separator'];
     97 		}
     98 
     99 		$has_injection = false;
    100 
    101 		if ( ! empty( $options['position'] ) ) {
    102 			$has_injection = true;
    103 
    104 			$element->start_injection( $options['position'] );
    105 
    106 			unset( $options['position'] );
    107 		}
    108 
    109 		if ( $this->get_options( 'popover' ) ) {
    110 			$this->start_popover( $element );
    111 		}
    112 
    113 		foreach ( $filtered_fields as $field_id => $field_args ) {
    114 			// Add the global group args to the control
    115 			$field_args = $this->add_group_args_to_field( $field_id, $field_args );
    116 
    117 			// Register the control
    118 			$id = $this->get_controls_prefix() . $field_id;
    119 
    120 			if ( ! empty( $field_args['responsive'] ) ) {
    121 				unset( $field_args['responsive'] );
    122 
    123 				$element->add_responsive_control( $id, $field_args, $options );
    124 			} else {
    125 				$element->add_control( $id, $field_args, $options );
    126 			}
    127 		}
    128 
    129 		if ( $this->get_options( 'popover' ) ) {
    130 			$element->end_popover();
    131 		}
    132 
    133 		if ( $has_injection ) {
    134 			$element->end_injection();
    135 		}
    136 	}
    137 
    138 	/**
    139 	 * Get arguments.
    140 	 *
    141 	 * Retrieve group control arguments.
    142 	 *
    143 	 * @since 1.0.0
    144 	 * @access public
    145 	 *
    146 	 * @return array Group control arguments.
    147 	 */
    148 	final public function get_args() {
    149 		return $this->args;
    150 	}
    151 
    152 	/**
    153 	 * Get fields.
    154 	 *
    155 	 * Retrieve group control fields.
    156 	 *
    157 	 * @since 1.2.2
    158 	 * @access public
    159 	 *
    160 	 * @return array Control fields.
    161 	 */
    162 	final public function get_fields() {
    163 		if ( null === static::$fields ) {
    164 			static::$fields = $this->init_fields();
    165 		}
    166 
    167 		return static::$fields;
    168 	}
    169 
    170 	/**
    171 	 * Get controls prefix.
    172 	 *
    173 	 * Retrieve the prefix of the group control, which is `{{ControlName}}_`.
    174 	 *
    175 	 * @since 1.0.0
    176 	 * @access public
    177 	 *
    178 	 * @return string Control prefix.
    179 	 */
    180 	public function get_controls_prefix() {
    181 		return $this->args['name'] . '_';
    182 	}
    183 
    184 	/**
    185 	 * Get group control classes.
    186 	 *
    187 	 * Retrieve the classes of the group control.
    188 	 *
    189 	 * @since 1.0.0
    190 	 * @access public
    191 	 *
    192 	 * @return string Group control classes.
    193 	 */
    194 	public function get_base_group_classes() {
    195 		return 'elementor-group-control-' . static::get_type() . ' elementor-group-control';
    196 	}
    197 
    198 	/**
    199 	 * Init fields.
    200 	 *
    201 	 * Initialize group control fields.
    202 	 *
    203 	 * @abstract
    204 	 * @since 1.2.2
    205 	 * @access protected
    206 	 */
    207 	abstract protected function init_fields();
    208 
    209 	/**
    210 	 * Get default options.
    211 	 *
    212 	 * Retrieve the default options of the group control. Used to return the
    213 	 * default options while initializing the group control.
    214 	 *
    215 	 * @since 1.9.0
    216 	 * @access protected
    217 	 *
    218 	 * @return array Default group control options.
    219 	 */
    220 	protected function get_default_options() {
    221 		return [];
    222 	}
    223 
    224 	/**
    225 	 * Get child default arguments.
    226 	 *
    227 	 * Retrieve the default arguments for all the child controls for a specific group
    228 	 * control.
    229 	 *
    230 	 * @since 1.2.2
    231 	 * @access protected
    232 	 *
    233 	 * @return array Default arguments for all the child controls.
    234 	 */
    235 	protected function get_child_default_args() {
    236 		return [];
    237 	}
    238 
    239 	/**
    240 	 * Filter fields.
    241 	 *
    242 	 * Filter which controls to display, using `include`, `exclude` and the
    243 	 * `condition` arguments.
    244 	 *
    245 	 * @since 1.2.2
    246 	 * @access protected
    247 	 *
    248 	 * @return array Control fields.
    249 	 */
    250 	protected function filter_fields() {
    251 		$args = $this->get_args();
    252 
    253 		$fields = $this->get_fields();
    254 
    255 		if ( ! empty( $args['include'] ) ) {
    256 			$fields = array_intersect_key( $fields, array_flip( $args['include'] ) );
    257 		}
    258 
    259 		if ( ! empty( $args['exclude'] ) ) {
    260 			$fields = array_diff_key( $fields, array_flip( $args['exclude'] ) );
    261 		}
    262 
    263 		return $fields;
    264 	}
    265 
    266 	/**
    267 	 * Add group arguments to field.
    268 	 *
    269 	 * Register field arguments to group control.
    270 	 *
    271 	 * @since 1.2.2
    272 	 * @access protected
    273 	 *
    274 	 * @param string $control_id Group control id.
    275 	 * @param array  $field_args Group control field arguments.
    276 	 *
    277 	 * @return array
    278 	 */
    279 	protected function add_group_args_to_field( $control_id, $field_args ) {
    280 		$args = $this->get_args();
    281 
    282 		if ( ! empty( $args['tab'] ) ) {
    283 			$field_args['tab'] = $args['tab'];
    284 		}
    285 
    286 		if ( ! empty( $args['section'] ) ) {
    287 			$field_args['section'] = $args['section'];
    288 		}
    289 
    290 		$field_args['classes'] = $this->get_base_group_classes() . ' elementor-group-control-' . $control_id;
    291 
    292 		foreach ( [ 'condition', 'conditions' ] as $condition_type ) {
    293 			if ( ! empty( $args[ $condition_type ] ) ) {
    294 				if ( empty( $field_args[ $condition_type ] ) ) {
    295 					$field_args[ $condition_type ] = [];
    296 				}
    297 
    298 				$field_args[ $condition_type ] += $args[ $condition_type ];
    299 			}
    300 		}
    301 
    302 		return $field_args;
    303 	}
    304 
    305 	/**
    306 	 * Prepare fields.
    307 	 *
    308 	 * Process group control fields before adding them to `add_control()`.
    309 	 *
    310 	 * @since 1.2.2
    311 	 * @access protected
    312 	 *
    313 	 * @param array $fields Group control fields.
    314 	 *
    315 	 * @return array Processed fields.
    316 	 */
    317 	protected function prepare_fields( $fields ) {
    318 		$popover_options = $this->get_options( 'popover' );
    319 
    320 		$popover_name = ! $popover_options ? null : $popover_options['starter_name'];
    321 
    322 		foreach ( $fields as $field_key => &$field ) {
    323 			if ( $popover_name ) {
    324 				$field['condition'][ $popover_name . '!' ] = '';
    325 			}
    326 
    327 			if ( isset( $this->args['fields_options']['__all'] ) ) {
    328 				$field = array_merge( $field, $this->args['fields_options']['__all'] );
    329 			}
    330 
    331 			if ( isset( $this->args['fields_options'][ $field_key ] ) ) {
    332 				$field = array_merge( $field, $this->args['fields_options'][ $field_key ] );
    333 			}
    334 
    335 			if ( ! empty( $field['condition'] ) ) {
    336 				$field = $this->add_condition_prefix( $field );
    337 			}
    338 
    339 			if ( ! empty( $field['conditions'] ) ) {
    340 				$field['conditions'] = $this->add_conditions_prefix( $field['conditions'] );
    341 			}
    342 
    343 			if ( ! empty( $field['selectors'] ) ) {
    344 				$field['selectors'] = $this->handle_selectors( $field['selectors'] );
    345 			}
    346 
    347 			if ( ! empty( $field['device_args'] ) ) {
    348 				foreach ( $field['device_args'] as $device => $device_arg ) {
    349 					if ( ! empty( $field['device_args'][ $device ]['condition'] ) ) {
    350 						$field['device_args'][ $device ] = $this->add_condition_prefix( $field['device_args'][ $device ] );
    351 					}
    352 
    353 					if ( ! empty( $field['device_args'][ $device ]['conditions'] ) ) {
    354 						$field['device_args'][ $device ]['conditions'] = $this->add_conditions_prefix( $field['device_args'][ $device ]['conditions'] );
    355 					}
    356 
    357 					if ( ! empty( $device_arg['selectors'] ) ) {
    358 						$field['device_args'][ $device ]['selectors'] = $this->handle_selectors( $device_arg['selectors'] );
    359 					}
    360 				}
    361 			}
    362 		}
    363 
    364 		return $fields;
    365 	}
    366 
    367 	/**
    368 	 * Init options.
    369 	 *
    370 	 * Initializing group control options.
    371 	 *
    372 	 * @since 1.9.0
    373 	 * @access private
    374 	 */
    375 	private function init_options() {
    376 		$default_options = [
    377 			'popover' => [
    378 				'starter_name' => 'popover_toggle',
    379 				'starter_value' => 'custom',
    380 				'starter_title' => '',
    381 			],
    382 		];
    383 
    384 		$this->options = array_replace_recursive( $default_options, $this->get_default_options() );
    385 	}
    386 
    387 	/**
    388 	 * Init arguments.
    389 	 *
    390 	 * Initializing group control base class.
    391 	 *
    392 	 * @since 1.2.2
    393 	 * @access protected
    394 	 *
    395 	 * @param array $args Group control settings value.
    396 	 */
    397 	protected function init_args( $args ) {
    398 		$this->args = array_merge( $this->get_default_args(), $this->get_child_default_args(), $args );
    399 
    400 		if ( isset( $this->args['scheme'] ) ) {
    401 			$this->args['global']['default'] = Plugin::$instance->kits_manager->convert_scheme_to_global( $this->args['scheme'] );
    402 		}
    403 	}
    404 
    405 	/**
    406 	 * Get default arguments.
    407 	 *
    408 	 * Retrieve the default arguments of the group control. Used to return the
    409 	 * default arguments while initializing the group control.
    410 	 *
    411 	 * @since 1.2.2
    412 	 * @access private
    413 	 *
    414 	 * @return array Control default arguments.
    415 	 */
    416 	private function get_default_args() {
    417 		return [
    418 			'default' => '',
    419 			'selector' => '{{WRAPPER}}',
    420 			'fields_options' => [],
    421 		];
    422 	}
    423 
    424 	/**
    425 	 * Add condition prefix.
    426 	 *
    427 	 * Used to add the group prefix to controls with conditions, to
    428 	 * distinguish them from other controls with the same name.
    429 	 *
    430 	 * This way Elementor can apply condition logic to a specific control in a
    431 	 * group control.
    432 	 *
    433 	 * @since 1.2.0
    434 	 * @access private
    435 	 *
    436 	 * @param array $field Group control field.
    437 	 *
    438 	 * @return array Group control field.
    439 	 */
    440 	private function add_condition_prefix( $field ) {
    441 		$controls_prefix = $this->get_controls_prefix();
    442 
    443 		$prefixed_condition_keys = array_map(
    444 			function( $key ) use ( $controls_prefix ) {
    445 				return $controls_prefix . $key;
    446 			},
    447 			array_keys( $field['condition'] )
    448 		);
    449 
    450 		$field['condition'] = array_combine(
    451 			$prefixed_condition_keys,
    452 			$field['condition']
    453 		);
    454 
    455 		return $field;
    456 	}
    457 
    458 	private function add_conditions_prefix( $conditions ) {
    459 		$controls_prefix = $this->get_controls_prefix();
    460 
    461 		foreach ( $conditions['terms'] as & $condition ) {
    462 			if ( isset( $condition['terms'] ) ) {
    463 				$condition = $this->add_conditions_prefix( $condition );
    464 
    465 				continue;
    466 			}
    467 
    468 			$condition['name'] = $controls_prefix . $condition['name'];
    469 		}
    470 
    471 		return $conditions;
    472 	}
    473 
    474 	/**
    475 	 * Handle selectors.
    476 	 *
    477 	 * Used to process the CSS selector of group control fields. When using
    478 	 * group control, Elementor needs to apply the selector to different fields.
    479 	 * This method handles the process.
    480 	 *
    481 	 * In addition, it handles selector values from other fields and process the
    482 	 * css.
    483 	 *
    484 	 * @since 1.2.2
    485 	 * @access private
    486 	 *
    487 	 * @param array $selectors An array of selectors to process.
    488 	 *
    489 	 * @return array Processed selectors.
    490 	 */
    491 	private function handle_selectors( $selectors ) {
    492 		$args = $this->get_args();
    493 
    494 		$selectors = array_combine(
    495 			array_map(
    496 				function( $key ) use ( $args ) {
    497 					return str_replace( '{{SELECTOR}}', $args['selector'], $key );
    498 				}, array_keys( $selectors )
    499 			),
    500 			$selectors
    501 		);
    502 
    503 		if ( ! $selectors ) {
    504 			return $selectors;
    505 		}
    506 
    507 		$controls_prefix = $this->get_controls_prefix();
    508 
    509 		foreach ( $selectors as &$selector ) {
    510 			$selector = preg_replace_callback( '/{{\K(.*?)(?=}})/', function( $matches ) use ( $controls_prefix ) {
    511 				$is_external_reference = false;
    512 
    513 				return preg_replace_callback( '/[^ ]+?(?=\.)\./', function( $sub_matches ) use ( $controls_prefix, &$is_external_reference ) {
    514 					$placeholder = $sub_matches[0];
    515 
    516 					if ( 'external.' === $placeholder ) {
    517 						$is_external_reference = true;
    518 
    519 						return '';
    520 					}
    521 
    522 					if ( $is_external_reference ) {
    523 						$is_external_reference = false;
    524 
    525 						return $placeholder;
    526 					}
    527 
    528 					return $controls_prefix . $placeholder;
    529 				}, $matches[1] );
    530 			}, $selector );
    531 		}
    532 
    533 		return $selectors;
    534 	}
    535 
    536 	/**
    537 	 * Start popover.
    538 	 *
    539 	 * Starts a group controls popover.
    540 	 *
    541 	 * @since 1.9.1
    542 	 * @access private
    543 	 * @param Controls_Stack $element Element.
    544 	 */
    545 	private function start_popover( Controls_Stack $element ) {
    546 		$popover_options = $this->get_options( 'popover' );
    547 
    548 		$settings = $this->get_args();
    549 
    550 		if ( isset( $settings['global'] ) ) {
    551 			if ( ! isset( $popover_options['settings']['global'] ) ) {
    552 				$popover_options['settings']['global'] = [];
    553 			}
    554 
    555 			$popover_options['settings']['global'] = array_replace_recursive( $popover_options['settings']['global'], $settings['global'] );
    556 		}
    557 
    558 		if ( isset( $settings['label'] ) ) {
    559 			$label = $settings['label'];
    560 		} else {
    561 			$label = $popover_options['starter_title'];
    562 		}
    563 
    564 		$control_params = [
    565 			'type' => Controls_Manager::POPOVER_TOGGLE,
    566 			'label' => $label,
    567 			'return_value' => $popover_options['starter_value'],
    568 		];
    569 
    570 		if ( ! empty( $popover_options['settings'] ) ) {
    571 			$control_params = array_replace_recursive( $control_params, $popover_options['settings'] );
    572 		}
    573 
    574 		foreach ( [ 'condition', 'conditions' ] as $key ) {
    575 			if ( ! empty( $settings[ $key ] ) ) {
    576 				$control_params[ $key ] = $settings[ $key ];
    577 			}
    578 		}
    579 
    580 		$starter_name = $popover_options['starter_name'];
    581 
    582 		if ( isset( $this->args['fields_options'][ $starter_name ] ) ) {
    583 			$control_params = array_merge( $control_params, $this->args['fields_options'][ $starter_name ] );
    584 		}
    585 
    586 		$control_params['groupPrefix'] = $this->get_controls_prefix();
    587 
    588 		$element->add_control( $this->get_controls_prefix() . $starter_name, $control_params );
    589 
    590 		$element->start_popover();
    591 	}
    592 }