fragments[ 'div.elementor-element-' . $element['id'] . ' div.elementor-widget-container' ] = '
' . $content . '
'; } } } } } ); } } else { $fragments['div.elementor-widget-container .woocommerce .cross-sells'] = '
'; $fragments['div.elementor-widget-container .woocommerce section.up-sells'] = '
'; } return $fragments; } /** * Get Products Related Content. * * A function to return content for the 'related' products query type in the Products widget. * This function is declared in the Module file so it can be accessed during a WC fragment refresh * and also be used in the Product widget's render method. * * @since 3.7.0 * @access public * * @param array $settings * * @return mixed The content or false */ public static function get_products_related_content( $settings ) { global $product; $product = wc_get_product(); if ( ! $product ) { return; } return self::get_product_widget_content( $settings, 'related_products', 'woocommerce_product_related_products_heading', 'products_related_title_text' ); } /** * Get Upsells Content. * * A function to return content for the 'upsell' query type in the Products widget. * This function is declared in the Module file so it can be accessed during a WC fragment refresh * and also be used in the Product widget's render method. * * @since 3.7.0 * @access public * * @param array $settings * * @return mixed The content or false */ public static function get_upsells_content( $settings ) { return self::get_product_widget_content( $settings, 'upsells', 'woocommerce_product_upsells_products_heading', 'products_upsells_title_text' ); } /** * Get Cross Sells Content. * * A function to return content for the 'cross_sells' query type in the Products widget. * This function is declared in the Module file so it can be accessed during a WC fragment refresh * and also be used in the Product widget's render method. * * @since 3.7.0 * @access public * * @param array $settings * * @return mixed The content or false */ public static function get_cross_sells_content( $settings ) { return self::get_product_widget_content( $settings, 'cross_sells', 'woocommerce_product_cross_sells_products_heading', 'products_cross_sells_title_text' ); } /** * Print Woocommerce Shipping Message * * Format the shipping messages that will be displayed on the Cart and Checkout Widgets. * This will add extra classes to those messages so that we can target certain messages * with certain style controls. * * @since 3.5.0 * * @param string $html the original HTML from WC * @param string $classes the classes we will surround $html with * @return string the final formatted HTML that will be rendered */ private function print_woocommerce_shipping_message( $html, $classes ) { return '' . $html . ''; } /** * Should load WC Notices Styles * * Determine if we should load the WooCommerce notices CSS. * It should only load: * - When we are in the Editor, regardless if any notices have been activated. * - If WooCoomerce is active. * - When we are on the front end, if at least one notice is activated. * * It should not load in WP Admin. * * @return boolean */ private function should_load_wc_notices_styles() { if ( ! API::is_licence_has_feature( static::SITE_SETTINGS_NOTICES_LICENSE_FEATURE_NAME, API::BC_VALIDATION_CALLBACK ) ) { return false; } $woocommerce_active = in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ); $is_editor = ProUtils::_unstable_get_super_global_value( $_GET, 'elementor-preview' ); // Editor checks. if ( $woocommerce_active && $is_editor ) { return true; } // Front end checks. if ( 0 < count( $this->get_styled_notice_elements() ) // At least one notice has been activated. && $woocommerce_active // WooCommerce is active. && ( ! is_admin() || $is_editor ) // We are not in WP Admin. ) { return true; } return false; } /** * Get Product Widget Content. * * A general function to create markup for the new query types in the Products widget. * * @since 3.7.0 * @access private * * @param array $settings The widget settings. * @param string $type The query type to create content for. * @param string $title_hook The hook name to filter in the widget title. * @param string $title_key The control ID for the section title. * * @return mixed The content or false */ private static function get_product_widget_content( $settings, $type, $title_hook, $title_key = '' ) { add_filter( $title_hook, function ( $heading ) use ( $settings, $title_key ) { $title_text = isset( $settings[ $title_key ] ) ? $settings[ $title_key ] : ''; if ( ! empty( $title_text ) ) { return $title_text; } return $heading; }, 10, 1 ); ob_start(); $args = self::parse_product_widget_args( $settings, $type ); if ( 'related_products' === $type ) { woocommerce_related_products( $args ); } elseif ( 'upsells' === $type ) { woocommerce_upsell_display( $args['limit'], $args['columns'], $args['orderby'], $args['order'] ); } else { /** * We need to wrap this content in the 'woocommerce' class for the layout to have the correct styling. * Because this will only be used as a separate widget on the Cart page, * the normal 'woocommerce' div from the cart widget will be closed before this content. */ echo '
'; woocommerce_cross_sell_display( $args['limit'], $args['columns'], $args['orderby'], $args['order'] ); echo '
'; } $products_html = ob_get_clean(); remove_filter( $title_hook, function() {}, 10 ); if ( $products_html ) { $products_html = str_replace( '