register_modules(); $this->register_fullwidth_modules(); $this->register_structural_modules(); $this->register_woo_modules(); $this->register_shortcode(); } /** * Start registering shortcodes. * * @since 4.10.0 * @access public * @return void */ public function register_shortcode() { // is_saving_cache or other scenarios where we need to load everything. if ( et_builder_should_load_all_module_data() ) { $this->register_all_shortcodes(); } else { $this->register_lazy_shortcodes(); } } /** * Register normal modules. * * Modules dependent to each other will have * to have a dependency parameter on them. * Eg : et_pb_accordion_item needs et_pb_toggle so we * have to pass add that on the `deps` key. * * @since 4.10.0 * @access public * @return void */ public function register_modules() { $modules = [ 'et_pb_accordion' => [ 'classname' => 'ET_Builder_Module_Accordion', ], 'et_pb_accordion_item' => [ 'classname' => 'ET_Builder_Module_Accordion_Item', 'deps' => array( 'et_pb_toggle' ), ], 'et_pb_audio' => [ 'classname' => 'ET_Builder_Module_Audio', ], 'et_pb_counters' => [ 'classname' => 'ET_Builder_Module_Bar_Counters', ], 'et_pb_counter' => [ 'classname' => 'ET_Builder_Module_Bar_Counters_Item', ], 'et_pb_blog' => [ 'classname' => 'ET_Builder_Module_Blog', ], 'et_pb_blurb' => [ 'classname' => 'ET_Builder_Module_Blurb', ], 'et_pb_button' => [ 'classname' => 'ET_Builder_Module_Button', ], 'et_pb_circle_counter' => [ 'classname' => 'ET_Builder_Module_Circle_Counter', ], 'et_pb_code' => [ 'classname' => 'ET_Builder_Module_Code', ], 'et_pb_comments' => [ 'classname' => 'ET_Builder_Module_Comments', ], 'et_pb_contact_form' => [ 'classname' => 'ET_Builder_Module_Contact_Form', ], 'et_pb_contact_field' => [ 'classname' => 'ET_Builder_Module_Contact_Form_Item', ], 'et_pb_countdown_timer' => [ 'classname' => 'ET_Builder_Module_Countdown_Timer', ], 'et_pb_cta' => [ 'classname' => 'ET_Builder_Module_Cta', ], 'et_pb_divider' => [ 'classname' => 'ET_Builder_Module_Divider', ], 'et_pb_filterable_portfolio' => [ 'classname' => 'ET_Builder_Module_Filterable_Portfolio', ], 'et_pb_gallery' => [ 'classname' => 'ET_Builder_Module_Gallery', ], 'et_pb_image' => [ 'classname' => 'ET_Builder_Module_Image', ], 'et_pb_login' => [ 'classname' => 'ET_Builder_Module_Login', ], 'et_pb_map' => [ 'classname' => 'ET_Builder_Module_Map', ], 'et_pb_map_pin' => [ 'classname' => 'ET_Builder_Module_Map_Item', ], 'et_pb_menu' => [ 'classname' => 'ET_Builder_Module_Menu', ], 'et_pb_number_counter' => [ 'classname' => 'ET_Builder_Module_Number_Counter', ], 'et_pb_portfolio' => [ 'classname' => 'ET_Builder_Module_Portfolio', ], 'et_pb_post_content' => [ 'classname' => 'ET_Builder_Module_PostContent', ], 'et_pb_post_slider' => [ 'classname' => 'ET_Builder_Module_Post_Slider', ], 'et_pb_post_title' => [ 'classname' => 'ET_Builder_Module_Post_Title', ], 'et_pb_post_nav' => [ 'classname' => 'ET_Builder_Module_Posts_Navigation', ], 'et_pb_pricing_tables' => [ 'classname' => 'ET_Builder_Module_Pricing_Tables', ], 'et_pb_pricing_table' => [ 'classname' => 'ET_Builder_Module_Pricing_Tables_Item', ], 'et_pb_search' => [ 'classname' => 'ET_Builder_Module_Search', ], 'et_pb_sidebar' => [ 'classname' => 'ET_Builder_Module_Sidebar', ], 'et_pb_signup' => [ 'classname' => 'ET_Builder_Module_Signup', ], 'et_pb_signup_custom_field' => [ 'classname' => 'ET_Builder_Module_Signup_Item', 'preload_deps' => array( 'et_pb_contact_field' ), ], 'et_pb_slider' => [ 'classname' => 'ET_Builder_Module_Slider', ], 'et_pb_slide' => [ 'classname' => 'ET_Builder_Module_Slider_Item', ], 'et_pb_social_media_follow' => [ 'classname' => 'ET_Builder_Module_Social_Media_Follow', ], 'et_pb_social_media_follow_network' => [ 'classname' => 'ET_Builder_Module_Social_Media_Follow_Item', ], 'et_pb_tabs' => [ 'classname' => 'ET_Builder_Module_Tabs', ], 'et_pb_tab' => [ 'classname' => 'ET_Builder_Module_Tabs_Item', ], 'et_pb_team_member' => [ 'classname' => 'ET_Builder_Module_Team_Member', ], 'et_pb_testimonial' => [ 'classname' => 'ET_Builder_Module_Testimonial', ], 'et_pb_text' => [ 'classname' => 'ET_Builder_Module_Text', ], 'et_pb_toggle' => [ 'classname' => 'ET_Builder_Module_Toggle', ], 'et_pb_video' => [ 'classname' => 'ET_Builder_Module_Video', ], 'et_pb_video_slider' => [ 'classname' => 'ET_Builder_Module_Video_Slider', ], 'et_pb_video_slider_item' => [ 'classname' => 'ET_Builder_Module_Video_Slider_Item', ], 'et_pb_icon' => [ 'classname' => 'ET_Builder_Module_Icon', ], ]; /** * Filters built-in Divi Builder module class names. * * 3rd-party plugins can use this filter to override Divi Builder modules. * * NOTE: Overriding built-in modules is not ideal and should only be used as a temporary solution. * The recommended approach for achieving this is using the official API: * https://www.elegantthemes.com/documentation/developers/divi-module/how-to-create-a-divi-builder-module/ * * @since 4.11.0 * * @param array $additional_modules Additional modules. */ $additional_modules = apply_filters( 'et_module_classes', [] ); $this->_modules_map = array_merge( $this->_modules_map, $modules, $additional_modules ); } /** * Register fullwidth modules. * * @since 4.10.0 * @access public * @return void */ public function register_fullwidth_modules() { $modules = [ 'et_pb_fullwidth_code' => [ 'classname' => 'ET_Builder_Module_Fullwidth_Code', ], 'et_pb_fullwidth_header' => [ 'classname' => 'ET_Builder_Module_Fullwidth_Header', ], 'et_pb_fullwidth_image' => [ 'classname' => 'ET_Builder_Module_Fullwidth_Image', ], 'et_pb_fullwidth_map' => [ 'classname' => 'ET_Builder_Module_Fullwidth_Map', ], 'et_pb_fullwidth_menu' => [ 'classname' => 'ET_Builder_Module_Fullwidth_Menu', ], 'et_pb_fullwidth_portfolio' => [ 'classname' => 'ET_Builder_Module_Fullwidth_Portfolio', ], 'et_pb_fullwidth_post_content' => [ 'classname' => 'ET_Builder_Module_Fullwidth_PostContent', ], 'et_pb_fullwidth_post_slider' => [ 'classname' => 'ET_Builder_Module_Fullwidth_Post_Slider', ], 'et_pb_fullwidth_post_title' => [ 'classname' => 'ET_Builder_Module_Fullwidth_Post_Title', ], 'et_pb_fullwidth_slider' => [ 'classname' => 'ET_Builder_Module_Fullwidth_Slider', ], ]; /** * Filters built-in Divi Builder module class names. * * 3rd-party plugins can use this filter to override Divi Builder modules. * * NOTE: Overriding built-in modules is not ideal and should only be used as a temporary solution. * The recommended approach for achieving this is using the official API: * https://www.elegantthemes.com/documentation/developers/divi-module/how-to-create-a-divi-builder-module/ * * @since 4.11.0 * * @param array $additional_modules Additional modules. */ $additional_modules = apply_filters( 'et_fullwidth_module_classes', [] ); $this->_modules_map = array_merge( $this->_modules_map, $modules, $additional_modules ); } /** * Register structural modules. * * @since 4.10.0 * @access public * @return void */ public function register_structural_modules() { $modules = [ 'et_pb_section' => [ 'classname' => 'ET_Builder_Section', ], 'et_pb_row' => [ 'classname' => 'ET_Builder_Row', ], 'et_pb_row_inner' => [ 'classname' => 'ET_Builder_Row_Inner', ], 'et_pb_column' => [ 'classname' => 'ET_Builder_Column', ], ]; /** * Filters built-in Divi Builder module class names. * * 3rd-party plugins can use this filter to override Divi Builder modules. * * NOTE: Overriding built-in modules is not ideal and should only be used as a temporary solution. * The recommended approach for achieving this is using the official API: * https://www.elegantthemes.com/documentation/developers/divi-module/how-to-create-a-divi-builder-module/ * * @since 4.11.0 * * @param array $additional_modules Additional modules. */ $additional_modules = apply_filters( 'et_structural_module_classes', [] ); $this->_structural_modules_map = array_merge( $modules, $additional_modules ); } /** * Register woocommerce modules. * * @since 4.10.0 * @access public * @return void */ public function register_woo_modules() { // Only add wooModules if woo is active. if ( ! et_is_woocommerce_plugin_active() ) { return; } $woo_modules = [ 'et_pb_wc_add_to_cart' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Add_To_Cart', ], 'et_pb_wc_additional_info' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Additional_Info', ], 'et_pb_wc_breadcrumb' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Breadcrumb', ], 'et_pb_wc_cart_notice' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Cart_Notice', ], 'et_pb_wc_description' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Description', ], 'et_pb_wc_gallery' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Gallery', ], 'et_pb_wc_images' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Images', ], 'et_pb_wc_meta' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Meta', ], 'et_pb_wc_price' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Price', ], 'et_pb_wc_rating' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Rating', ], 'et_pb_wc_related_products' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Related_Products', ], 'et_pb_wc_reviews' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Reviews', ], 'et_pb_wc_stock' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Stock', ], 'et_pb_wc_tabs' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Tabs', ], 'et_pb_wc_title' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Title', ], 'et_pb_wc_upsells' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Upsells', ], 'et_pb_wc_cart_products' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Cart_Products', ], 'et_pb_wc_cross_sells' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Cross_Sells', ], 'et_pb_wc_cart_totals' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Cart_Totals', ], 'et_pb_wc_checkout_billing' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Checkout_Billing', ], 'et_pb_wc_checkout_shipping' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Checkout_Shipping', ], 'et_pb_wc_checkout_order_details' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Checkout_Order_Details', ], 'et_pb_wc_checkout_payment_info' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Checkout_Payment_Info', ], 'et_pb_wc_checkout_additional_info' => [ 'classname' => 'ET_Builder_Module_Woocommerce_Checkout_Additional_Info', ], 'et_pb_shop' => [ 'classname' => 'ET_Builder_Module_Shop', ], ]; /** * Filters built-in Divi Builder module class names. * * 3rd-party plugins can use this filter to override Divi Builder modules. * * NOTE: Overriding built-in modules is not ideal and should only be used as a temporary solution. * The recommended approach for achieving this is using the official API: * https://www.elegantthemes.com/documentation/developers/divi-module/how-to-create-a-divi-builder-module/ * * @since 4.11.0 * * @param array $additional_modules Additional modules. */ $additional_modules = apply_filters( 'et_woo_module_classes', [] ); $this->_woo_modules_map = $woo_modules; $this->_modules_map = array_merge( $this->_modules_map, $woo_modules, $additional_modules ); } /** * Register shortcode. * * @since 4.10.0 * @access public * @return void */ public function register_all_shortcodes() { $et_builder_module_files = glob( ET_BUILDER_DIR . 'module/*.php' ); $et_builder_module_types = glob( ET_BUILDER_DIR . 'module/type/*.php' ); if ( ! $et_builder_module_files ) { return; } /** * Fires before the builder's module classes are loaded. * * @since 3.0.77 */ do_action( 'et_builder_modules_load' ); foreach ( $et_builder_module_types as $module_type ) { require_once $module_type; } foreach ( $et_builder_module_files as $module_file ) { // skip this all caps version, if it exists. // See https://github.com/elegantthemes/Divi/issues/24780. if ( 'CTA.php' === basename( $module_file ) ) { continue; } require_once $module_file; } if ( et_is_woocommerce_plugin_active() ) { $et_builder_woocommerce_module_files = glob( ET_BUILDER_DIR . 'module/woocommerce/*.php' ); foreach ( $et_builder_woocommerce_module_files as $module_type ) { require_once $module_type; } } /** * Fires after the builder's module classes are loaded. * * NOTE: this hook only fires on : * - Visual Builder pages * - Front end cache prime initial request * * IT DOES NOT fire on ALL front end requests * * @since 3.0.77 * @deprecated ?? Introduced shortcode manager. * Use {@see et_builder_module_loading}/{@see et_builder_module_loaded}/{@see et_builder_ready} instead. */ do_action( 'et_builder_modules_loaded' ); } /** * Lazy load shortcodes. * * @since 4.10.0 * @access public * @return void */ public function register_lazy_shortcodes() { // A fake handler has to be registered for every shortcode, otherways // code will exit early and the pre_do_shortcode_tag hook won't be executed. foreach ( $this->_modules_map as $shortcode_slug => $module_data ) { add_shortcode( $shortcode_slug, '__return_empty_string' ); } // Load modules as needed. add_filter( 'pre_do_shortcode_tag', [ $this, 'load_modules' ], 99, 2 ); // Ensure all our module slugs are always considered, even when not loaded (yet). add_filter( 'et_builder_get_module_slugs_by_post_type', [ $this, 'add_module_slugs' ] ); add_filter( 'et_builder_get_woocommerce_modules', [ $this, 'add_woo_slugs' ] ); // Ensure all our structural module slugs are always considered, even when not loaded (yet). add_filter( 'et_builder_get_structural_module_slugs', [ $this, 'add_structural_module_slugs' ] ); /** * Fires after the builder's module classes are loaded. * * This hook is fired here for legacy reasons only. * Do not depend on this hook in the future. * * @since 3.0.77 * @deprecated ?? Introduced shortcode manager. * Use {@see et_builder_module_loading}/{@see et_builder_module_loaded}/{@see et_builder_ready} instead. */ do_action( 'et_builder_modules_loaded' ); /** * Fires after the builder's module shortcodes are lazy registered. * * @since 4.10.0 */ do_action( 'et_builder_module_lazy_shortcodes_registered' ); } /** * Add slugs for all our woo modules. * * @since 4.10.0 * @access public * @param array $loaded Loaded woo modules slugs. * @return array */ public function add_woo_slugs( $loaded ) { static $module_slugs; // Only compute this once. if ( empty( $module_slugs ) ) { $module_slugs = array_keys( $this->_woo_modules_map ); } return array_unique( array_merge( $loaded, $module_slugs ) ); } /** * Add slugs for all our modules. * * @since 4.10.0 * @access public * @param array $loaded Loaded modules slugs. * @return array */ public function add_module_slugs( $loaded ) { static $module_slugs; // Only compute this once. if ( empty( $module_slugs ) ) { $module_slugs = array_keys( $this->_modules_map ); } return array_unique( array_merge( $loaded, $module_slugs ) ); } /** * Add slugs for all our structural modules. * * @since 4.10.0 * @access public * @param array $loaded Loaded modules slugs. * @return array */ public function add_structural_module_slugs( $loaded ) { static $structural_module_slugs; // Only compute this once. if ( empty( $structural_module_slugs ) ) { $structural_module_slugs = array_keys( $this->_structural_modules_map ); } return array_unique( array_merge( $loaded, $structural_module_slugs ) ); } /** * Load modules. * * @since 4.10.0 * @access public * @param mixed $override Whether to override do_shortcode return value or not. * @param string $tag Shortcode tag. * @return mixed */ public function load_modules( $override, $tag ) { $this->maybe_load_module_from_slug( $tag ); return $override; } /** * Instantiate module from a shortcode slug. * * @since 4.10.0 * @access public * @param string $tag Shortcode tag. * @return void */ public function maybe_load_module_from_slug( $tag ) { if ( empty( $this->_modules_map[ $tag ] ) ) { // None of our business. return; } $module =& $this->_modules_map[ $tag ]; if ( empty( $module['instance'] ) ) { /** * Fires before module class is instantiated. * * @param string $tag Shortcode tag for module. * @param array $module Module loading configuration details. * * @since 4.10.0 */ do_action( 'et_builder_module_loading', $tag, $module ); /** * Fires before module class is instantiated. * * The dynamic portion of the hook, `$tag`, refers to the shortcode tag. * * @param array $module Module loading configuration details. * * @since 4.10.0 */ do_action( "et_builder_module_loading_{$tag}", $module ); // Load dependency before the class if needed. if ( ! empty( $module['preload_deps'] ) ) { foreach ( $module['preload_deps'] as $slug ) { $this->maybe_load_module_from_slug( $slug ); } } $module['instance'] = new $module['classname'](); if ( ! empty( $module['deps'] ) ) { foreach ( $module['deps'] as $slug ) { $this->maybe_load_module_from_slug( $slug ); } } /** * Fires after module class is instantiated. * * @param string $tag Shortcode tag for module. * @param array $module Module loading configuration details. * * @since 4.10.0 */ do_action( 'et_builder_module_loaded', $tag, $module ); /** * Fires after module class is instantiated. * * The dynamic portion of the hook, `$tag`, refers to the shortcode tag. * * @param array $module Module loading configuration details. * * @since 4.10.0 */ do_action( "et_builder_module_loaded_{$tag}", $module ); } } }