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

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