PluginProbe
Elementor Website Builder – more than just a page builder / 3.18.3
Elementor Website Builder – more than just a page builder v3.18.3
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / includes / managers / widgets.php

widgets.php in Elementor Website Builder – more than just a page builder 3.18.3, at includes/managers/widgets.php

670 lines 15.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor;
3
4 use Elementor\Core\Common\Modules\Ajax\Module as Ajax;
5 use Elementor\Core\Utils\Collection;
6 use Elementor\Core\Utils\Exceptions;
7 use Elementor\Core\Utils\Force_Locale;
8 use Elementor\Modules\NestedAccordion\Widgets\Nested_Accordion;
9 use Elementor\Modules\NestedTabs\Widgets\NestedTabs;
10
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit; // Exit if accessed directly.
13 }
14
15 /**
16 * Elementor widgets manager.
17 *
18 * Elementor widgets manager handler class is responsible for registering and
19 * initializing all the supported Elementor widgets.
20 *
21 * @since 1.0.0
22 */
23 class Widgets_Manager {
24
25 /**
26 * Widget types.
27 *
28 * Holds the list of all the widget types.
29 *
30 * @since 1.0.0
31 * @access private
32 *
33 * @var Widget_Base[]
34 */
35 private $_widget_types = null;
36
37 /**
38 * Promoted widget types.
39 *
40 * Holds the list of all the Promoted widget types.
41 *
42 * @since 3.15.0
43 * @access private
44 *
45 * @var Widget_Base[]
46 */
47 private $_promoted_widgets = [
48 'nested-elements' => NestedTabs::class,
49 'nested-accordion' => Nested_Accordion::class,
50 ];
51
52 /**
53 * Init widgets.
54 *
55 * Initialize Elementor widgets manager. Include all the the widgets files
56 * and register each Elementor and WordPress widget.
57 *
58 * @since 2.0.0
59 * @access private
60 */
61 private function init_widgets() {
62 $build_widgets_filename = [
63 'common',
64 'inner-section',
65 'heading',
66 'image',
67 'text-editor',
68 'video',
69 'button',
70 'divider',
71 'spacer',
72 'image-box',
73 'google-maps',
74 'icon',
75 'icon-box',
76 'star-rating',
77 'image-carousel',
78 'image-gallery',
79 'icon-list',
80 'counter',
81 'progress',
82 'testimonial',
83 'tabs',
84 'accordion',
85 'toggle',
86 'social-icons',
87 'alert',
88 'audio',
89 'shortcode',
90 'html',
91 'menu-anchor',
92 'sidebar',
93 'read-more',
94 'rating',
95 ];
96
97 $this->_widget_types = [];
98
99 foreach ( $build_widgets_filename as $widget_filename ) {
100 include ELEMENTOR_PATH . 'includes/widgets/' . $widget_filename . '.php';
101
102 $class_name = str_replace( '-', '_', $widget_filename );
103
104 $class_name = __NAMESPACE__ . '\Widget_' . $class_name;
105
106 $this->register( new $class_name() );
107 }
108
109 $this->register_promoted_widgets();
110
111 $this->register_wp_widgets();
112
113 /**
114 * After widgets registered.
115 *
116 * Fires after Elementor widgets are registered.
117 *
118 * @since 1.0.0
119 * @deprecated 3.5.0 Use `elementor/widgets/register` hook instead.
120 *
121 * @param Widgets_Manager $this The widgets manager.
122 */
123 Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->do_deprecated_action(
124 'elementor/widgets/widgets_registered',
125 [ $this ],
126 '3.5.0',
127 'elementor/widgets/register'
128 );
129
130 /**
131 * After widgets registered.
132 *
133 * Fires after Elementor widgets are registered.
134 *
135 * @since 3.5.0
136 *
137 * @param Widgets_Manager $this The widgets manager.
138 */
139 do_action( 'elementor/widgets/register', $this );
140 }
141
142 /**
143 * Register WordPress widgets.
144 *
145 * Add native WordPress widget to the list of registered widget types.
146 *
147 * Exclude the widgets that are in Elementor widgets black list. Theme and
148 * plugin authors can filter the black list.
149 *
150 * @since 2.0.0
151 * @access private
152 */
153 private function register_wp_widgets() {
154 global $wp_widget_factory;
155
156 // Allow themes/plugins to filter out their widgets.
157 $black_list = [];
158
159 /**
160 * Elementor widgets black list.
161 *
162 * Filters the widgets black list that won't be displayed in the panel.
163 *
164 * @since 1.0.0
165 *
166 * @param array $black_list A black list of widgets. Default is an empty array.
167 */
168 $black_list = apply_filters( 'elementor/widgets/black_list', $black_list );
169
170 foreach ( $wp_widget_factory->widgets as $widget_class => $widget_obj ) {
171
172 if ( in_array( $widget_class, $black_list ) ) {
173 continue;
174 }
175
176 $elementor_widget_class = __NAMESPACE__ . '\Widget_WordPress';
177
178 $this->register(
179 new $elementor_widget_class( [], [
180 'widget_name' => $widget_class,
181 ] )
182 );
183 }
184 }
185
186 /**
187 * Require files.
188 *
189 * Require Elementor widget base class.
190 *
191 * @since 2.0.0
192 * @access private
193 */
194 private function require_files() {
195 require ELEMENTOR_PATH . 'includes/base/widget-base.php';
196 }
197
198 private function pluck_default_controls( $controls ) {
199 return ( new Collection( $controls ) )
200 ->reduce( function ( $controls_defaults, $control, $control_key ) {
201 if ( ! empty( $control['default'] ) ) {
202 $controls_defaults[ $control_key ]['default'] = $control['default'];
203 }
204
205 return $controls_defaults;
206 }, [] );
207 }
208
209 /**
210 * Register widget type.
211 *
212 * Add a new widget type to the list of registered widget types.
213 *
214 * @since 1.0.0
215 * @access public
216 * @deprecated 3.5.0 Use `register()` method instead.
217 *
218 * @param Widget_Base $widget Elementor widget.
219 *
220 * @return true True if the widget was registered.
221 */
222 public function register_widget_type( Widget_Base $widget ) {
223 Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function(
224 __METHOD__,
225 '3.5.0',
226 'register()'
227 );
228
229 return $this->register( $widget );
230 }
231
232 /**
233 * Register a new widget type.
234 *
235 * @param \Elementor\Widget_Base $widget_instance Elementor Widget.
236 *
237 * @return bool True if the widget was registered.
238 * @since 3.5.0
239 * @access public
240 */
241 public function register( Widget_Base $widget_instance ) {
242 if ( is_null( $this->_widget_types ) ) {
243 $this->init_widgets();
244 }
245
246 /**
247 * Should widget be registered.
248 *
249 * @since 3.18.0
250 *
251 * @param bool $should_register Should widget be registered. Default is `true`.
252 * @param \Elementor\Widget_Base $widget_instance Widget instance.
253 */
254 $should_register = apply_filters( 'elementor/widgets/is_widget_enabled', true, $widget_instance );
255
256 if ( ! $should_register ) {
257 return false;
258 }
259
260 $this->_widget_types[ $widget_instance->get_name() ] = $widget_instance;
261
262 return true;
263 }
264
265 /** Register promoted widgets
266 *
267 * Since we cannot allow widgets to place themselves is a specific
268 * location on our widgets panel we need to use a hard coded solution for this.
269 *
270 * @return void
271 */
272 private function register_promoted_widgets() {
273
274 foreach ( $this->_promoted_widgets as $module_name => $class_name ) {
275
276 if ( Plugin::$instance->experiments->is_feature_active( $module_name ) ) {
277 $instance = new $class_name();
278 $this->_widget_types[ $instance->get_name() ] = $instance;
279 }
280 }
281 }
282
283 /**
284 * Unregister widget type.
285 *
286 * Removes widget type from the list of registered widget types.
287 *
288 * @since 1.0.0
289 * @access public
290 * @deprecated 3.5.0 Use `unregister()` method instead.
291 *
292 * @param string $name Widget name.
293 *
294 * @return true True if the widget was unregistered, False otherwise.
295 */
296 public function unregister_widget_type( $name ) {
297 Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function(
298 __METHOD__,
299 '3.5.0',
300 'unregister()'
301 );
302
303 return $this->unregister( $name );
304 }
305
306 /**
307 * Unregister widget type.
308 *
309 * Removes widget type from the list of registered widget types.
310 *
311 * @since 3.5.0
312 * @access public
313 *
314 * @param string $name Widget name.
315 *
316 * @return boolean Whether the widget was unregistered.
317 */
318 public function unregister( $name ) {
319 if ( ! isset( $this->_widget_types[ $name ] ) ) {
320 return false;
321 }
322
323 unset( $this->_widget_types[ $name ] );
324
325 return true;
326 }
327
328 /**
329 * Get widget types.
330 *
331 * Retrieve the registered widget types list.
332 *
333 * @since 1.0.0
334 * @access public
335 *
336 * @param string $widget_name Optional. Widget name. Default is null.
337 *
338 * @return Widget_Base|Widget_Base[]|null Registered widget types.
339 */
340 public function get_widget_types( $widget_name = null ) {
341 if ( is_null( $this->_widget_types ) ) {
342 $this->init_widgets();
343 }
344
345 if ( null !== $widget_name ) {
346 return isset( $this->_widget_types[ $widget_name ] ) ? $this->_widget_types[ $widget_name ] : null;
347 }
348
349 return $this->_widget_types;
350 }
351
352 /**
353 * Get widget types config.
354 *
355 * Retrieve all the registered widgets with config for each widgets.
356 *
357 * @since 1.0.0
358 * @access public
359 *
360 * @return array Registered widget types with each widget config.
361 */
362 public function get_widget_types_config() {
363 $config = [];
364
365 foreach ( $this->get_widget_types() as $widget_key => $widget ) {
366 $config[ $widget_key ] = $widget->get_config();
367 }
368
369 return $config;
370 }
371
372 /**
373 * @throws \Exception
374 */
375 public function ajax_get_widget_types_controls_config( array $data ) {
376 Plugin::$instance->documents->check_permissions( $data['editor_post_id'] );
377
378 wp_raise_memory_limit( 'admin' );
379
380 $config = [];
381
382 foreach ( $this->get_widget_types() as $widget_key => $widget ) {
383 if ( isset( $data['exclude'][ $widget_key ] ) ) {
384 continue;
385 }
386
387 $config[ $widget_key ] = [
388 'controls' => $widget->get_stack( false )['controls'],
389 'tabs_controls' => $widget->get_tabs_controls(),
390 ];
391 }
392
393 return $config;
394 }
395
396 public function ajax_get_widgets_default_value_translations( array $data = [] ) {
397 $locale = empty( $data['locale'] )
398 ? get_locale()
399 : $data['locale'];
400
401 $force_locale = new Force_Locale( $locale );
402 $force_locale->force();
403
404 $controls = ( new Collection( $this->get_widget_types() ) )
405 ->map( function ( Widget_Base $widget ) {
406 $controls = $widget->get_stack( false )['controls'];
407
408 return [
409 'controls' => $this->pluck_default_controls( $controls ),
410 ];
411 } )
412 ->filter( function ( $widget ) {
413 return ! empty( $widget['controls'] );
414 } )
415 ->all();
416
417 $force_locale->restore();
418
419 return $controls;
420 }
421
422 /**
423 * Ajax render widget.
424 *
425 * Ajax handler for Elementor render_widget.
426 *
427 * Fired by `wp_ajax_elementor_render_widget` action.
428 *
429 * @since 1.0.0
430 * @access public
431 *
432 * @throws \Exception If current user don't have permissions to edit the post.
433 *
434 * @param array $request Ajax request.
435 *
436 * @return array {
437 * Rendered widget.
438 *
439 * @type string $render The rendered HTML.
440 * }
441 */
442 public function ajax_render_widget( $request ) {
443 $document = Plugin::$instance->documents->get_with_permissions( $request['editor_post_id'] );
444
445 // Override the global $post for the render.
446 query_posts(
447 [
448 'p' => $request['editor_post_id'],
449 'post_type' => 'any',
450 ]
451 );
452
453 $editor = Plugin::$instance->editor;
454 $is_edit_mode = $editor->is_edit_mode();
455 $editor->set_edit_mode( true );
456
457 Plugin::$instance->documents->switch_to_document( $document );
458
459 $render_html = $document->render_element( $request['data'] );
460
461 $editor->set_edit_mode( $is_edit_mode );
462
463 return [
464 'render' => $render_html,
465 ];
466 }
467
468 /**
469 * Ajax get WordPress widget form.
470 *
471 * Ajax handler for Elementor editor get_wp_widget_form.
472 *
473 * Fired by `wp_ajax_elementor_editor_get_wp_widget_form` action.
474 *
475 * @since 1.0.0
476 * @access public
477 *
478 * @param array $request Ajax request.
479 *
480 * @return bool|string Rendered widget form.
481 * @throws \Exception
482 */
483 public function ajax_get_wp_widget_form( $request ) {
484 Plugin::$instance->documents->check_permissions( $request['editor_post_id'] );
485
486 if ( empty( $request['widget_type'] ) ) {
487 return false;
488 }
489
490 if ( empty( $request['data'] ) ) {
491 $request['data'] = [];
492 }
493
494 $element_data = [
495 'id' => $request['id'],
496 'elType' => 'widget',
497 'widgetType' => $request['widget_type'],
498 'settings' => $request['data'],
499 ];
500
501 /**
502 * @var $widget_obj Widget_WordPress
503 */
504 $widget_obj = Plugin::$instance->elements_manager->create_element_instance( $element_data );
505
506 if ( ! $widget_obj ) {
507 return false;
508 }
509
510 return $widget_obj->get_form();
511 }
512
513 /**
514 * Render widgets content.
515 *
516 * Used to generate the widget templates on the editor using Underscore JS
517 * template, for all the registered widget types.
518 *
519 * @since 1.0.0
520 * @access public
521 */
522 public function render_widgets_content() {
523 foreach ( $this->get_widget_types() as $widget ) {
524 $widget->print_template();
525 }
526 }
527
528 /**
529 * Get widgets frontend settings keys.
530 *
531 * Retrieve frontend controls settings keys for all the registered widget
532 * types.
533 *
534 * @since 1.3.0
535 * @access public
536 *
537 * @return array Registered widget types with settings keys for each widget.
538 */
539 public function get_widgets_frontend_settings_keys() {
540 $keys = [];
541
542 foreach ( $this->get_widget_types() as $widget_type_name => $widget_type ) {
543 $widget_type_keys = $widget_type->get_frontend_settings_keys();
544
545 if ( $widget_type_keys ) {
546 $keys[ $widget_type_name ] = $widget_type_keys;
547 }
548 }
549
550 return $keys;
551 }
552
553 /**
554 * Enqueue widgets scripts.
555 *
556 * Enqueue all the scripts defined as a dependency for each widget.
557 *
558 * @since 1.3.0
559 * @access public
560 */
561 public function enqueue_widgets_scripts() {
562 foreach ( $this->get_widget_types() as $widget ) {
563 $widget->enqueue_scripts();
564 }
565 }
566
567 /**
568 * Enqueue widgets styles
569 *
570 * Enqueue all the styles defined as a dependency for each widget
571 *
572 * @access public
573 */
574 public function enqueue_widgets_styles() {
575 foreach ( $this->get_widget_types() as $widget ) {
576 $widget->enqueue_styles();
577 }
578 }
579
580 /**
581 * Retrieve inline editing configuration.
582 *
583 * Returns general inline editing configurations like toolbar types etc.
584 *
585 * @access public
586 * @since 1.8.0
587 *
588 * @return array {
589 * Inline editing configuration.
590 *
591 * @type array $toolbar {
592 * Toolbar types and the actions each toolbar includes.
593 * Note: Wysiwyg controls uses the advanced toolbar, textarea controls
594 * uses the basic toolbar and text controls has no toolbar.
595 *
596 * @type array $basic Basic actions included in the edit tool.
597 * @type array $advanced Advanced actions included in the edit tool.
598 * }
599 * }
600 */
601 public function get_inline_editing_config() {
602 $basic_tools = [
603 'bold',
604 'underline',
605 'italic',
606 ];
607
608 $advanced_tools = array_merge( $basic_tools, [
609 'createlink',
610 'unlink',
611 'h1' => [
612 'h1',
613 'h2',
614 'h3',
615 'h4',
616 'h5',
617 'h6',
618 'p',
619 'blockquote',
620 'pre',
621 ],
622 'list' => [
623 'insertOrderedList',
624 'insertUnorderedList',
625 ],
626 ] );
627
628 return [
629 'toolbar' => [
630 'basic' => $basic_tools,
631 'advanced' => $advanced_tools,
632 ],
633 ];
634 }
635
636 /**
637 * Widgets manager constructor.
638 *
639 * Initializing Elementor widgets manager.
640 *
641 * @since 1.0.0
642 * @access public
643 */
644 public function __construct() {
645 $this->require_files();
646
647 add_action( 'elementor/ajax/register_actions', [ $this, 'register_ajax_actions' ] );
648 }
649
650 /**
651 * Register ajax actions.
652 *
653 * Add new actions to handle data after an ajax requests returned.
654 *
655 * @since 2.0.0
656 * @access public
657 *
658 * @param Ajax $ajax_manager
659 */
660 public function register_ajax_actions( Ajax $ajax_manager ) {
661 $ajax_manager->register_ajax_action( 'render_widget', [ $this, 'ajax_render_widget' ] );
662 $ajax_manager->register_ajax_action( 'editor_get_wp_widget_form', [ $this, 'ajax_get_wp_widget_form' ] );
663 $ajax_manager->register_ajax_action( 'get_widgets_config', [ $this, 'ajax_get_widget_types_controls_config' ] );
664
665 $ajax_manager->register_ajax_action( 'get_widgets_default_value_translations', function ( array $data ) {
666 return $this->ajax_get_widgets_default_value_translations( $data );
667 } );
668 }
669 }
670