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

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