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

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