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