PluginProbe
Elementor Website Builder – more than just a page builder / 3.20.0-dev3
Elementor Website Builder – more than just a page builder v3.20.0-dev3
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.20.0-dev3, at includes/managers/widgets.php

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