PageRenderTime 26ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/elementor/includes/controls/groups/base.php

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