{ continue; } } // Setting up stuff for all modules except social sharing. if ( Hustle_Module_Model::SOCIAL_SHARING_MODULE !== $module->module_type ) { $settings = $module->get_settings(); // Check the schedule. Ssharing modules don't have schedules. if ( ! $avoid_static_cache && ! $settings->is_currently_scheduled() ) { continue; } $module->load(); // Skip if Google fonts were deativated via hook. if ( $use_google_fonts ) { $google_fonts = array_merge_recursive( $google_fonts, $module->get_google_fonts() ); } if ( 'optin' === $module->module_mode ) { if ( ! $datepicker_found || empty( $recaptcha_language ) ) { $form_fields = $module->get_form_fields(); // Datepicker. // Check if the module has a datepicker unless we already found one in other modules. // We'll localize some variables if the modules have a datepicker. if ( ! $datepicker_found ) { $field_types = wp_list_pluck( $form_fields, 'type', true ); $datepicker_found = in_array( 'datepicker', $field_types, true ); } // Recaptcha. // Check if the module has a recaptcha to enqueue scripts unless we already found one. // We'll queue the script afterwards. if ( ! empty( $form_fields['recaptcha'] ) && empty( $recaptcha_language ) ) { $recaptcha_found = true; $recaptcha_field = $form_fields['recaptcha']; // Get only first recaptcha language. Skip if not set or it's "automatic". if ( ! empty( $recaptcha_field['recaptcha_language'] ) && 'automatic' !== $recaptcha_field['recaptcha_language'] ) { $recaptcha_language = $recaptcha_field['recaptcha_language']; } } } // Select2. // We're only using select2 for Mailchimp dropdown groups. if ( ! $select2_found ) { $mailchimp_settings = $module->get_provider_settings( 'mailchimp' ); if ( ! empty( $mailchimp_settings ) && ! is_null( $mailchimp_settings['group'] ) && '-1' !== $mailchimp_settings['group'] && 'dropdown' === $mailchimp_settings['group_type'] ) { $select2_found = true; } } } // For popups and slideins. if ( $is_non_inline_module ) { $this->non_inline_modules[ $module->module_id ] = $module; if ( ! $enqueue_adblock ) { $settings = $settings->to_array(); // If trigger is adblock. if ( in_array( 'adblock', $settings['triggers']['trigger'], true ) ) { $enqueue_adblock = true; } } } elseif ( Hustle_Module_Model::EMBEDDED_MODULE === $module->module_type ) { $this->inline_modules[ $module->module_id ] = $module; } } else { // Social sharing modules. $ssharing_networks = $module->get_content()->get_social_icons(); if ( ! empty( $ssharing_networks ) && in_array( 'pinterest', array_keys( $ssharing_networks ), true ) && empty( $ssharing_networks['pinterest']['link'] ) ) { $pinterest_found = true; } $this->inline_modules[ $module->module_id ] = $module; $this->non_inline_modules[ $module->module_id ] = $module; } $this->log_module_type_to_load_styles( $module ); $this->modules[] = $module->get_module_data_to_display(); } // End looping through the modules. // Set flag for scripts: datepicker field. if ( $datepicker_found ) { $this->modules_data_for_scripts['datepicker'] = true; } // Set flag for scripts: adblocker. if ( $enqueue_adblock ) { $this->modules_data_for_scripts['adblocker'] = true; } // Set flag for scripts: select2. if ( $select2_found ) { $this->modules_data_for_scripts['select2'] = true; } // Set flag for scripts: recaptcha field. if ( $recaptcha_found ) { $this->modules_data_for_scripts['recaptcha'] = array( 'language' => $recaptcha_language ); } if ( $pinterest_found ) { $this->modules_data_for_scripts['pinterest'] = true; } // Before removing it in future - check shortcode method - it's a flag there. $this->modules_data_for_scripts['fonts'] = $google_fonts; } /** * Store the modules' types to be displayed in order to enqueue * their required styles. * Called within self::create_modules() method. * * @since 4.0.1 * * @param Hustle_Model $module Current module to check. */ private function log_module_type_to_load_styles( Hustle_Model $module ) { // Keep track of the of the modules types and modes to display // in order to queue the required styles only. $this->module_types_to_display[ $module->module_type ] = 1; // Register the module mode for non SSharing modules. if ( Hustle_Module_Model::SOCIAL_SHARING_MODULE !== $module->module_type ) { $this->module_types_to_display[ $module->module_mode ] = 1; } else { // Register the module display type for SSharing modules. // Floating display. if ( $module->is_display_type_active( Hustle_SShare_Model::FLOAT_MOBILE ) || $module->is_display_type_active( Hustle_SShare_Model::FLOAT_DESKTOP ) ) { $this->module_types_to_display[ Hustle_SShare_Model::FLOAT_MODULE ] = 1; } // Inline display. if ( $module->is_display_type_active( Hustle_SShare_Model::INLINE_MODULE ) || $module->is_display_type_active( Hustle_SShare_Model::WIDGET_MODULE ) || $module->is_display_type_active( Hustle_SShare_Model::SHORTCODE_MODULE ) ) { $this->module_types_to_display[ Hustle_SShare_Model::INLINE_MODULE ] = 1; } } } /** * Check if current page has renderable opt-ins. **/ public function has_modules() { $has_modules = ! empty( $this->non_inline_modules ) || ! empty( $this->inline_modules ); return apply_filters( 'hustle_front_handler', $has_modules ); } /** * By-pass NextGEN Gallery resource manager * * @return false */ public function nextgen_compat() { return false; } /** * Render non inline modules */ public function render_non_inline_modules() { foreach ( $this->non_inline_modules as $module ) { if ( Hustle_Module_Model::SOCIAL_SHARING_MODULE !== $module->module_type ) { $module->display(); } elseif ( $module->is_display_type_active( Hustle_SShare_Model::FLOAT_DESKTOP ) || $module->is_display_type_active( Hustle_SShare_Model::FLOAT_MOBILE ) ) { $module->display( Hustle_SShare_Model::FLOAT_MODULE ); } } } /** * Handles the data for the unsubscribe shortcode * * @since 3.0.5 * @param array $atts The values passed through the shortcode attributes. * @return string The content to be rendered within the shortcode. */ public function unsubscribe_shortcode( $atts ) { $messages = Hustle_Settings_Admin::get_unsubscribe_messages(); $email = filter_input( INPUT_GET, 'email', FILTER_VALIDATE_EMAIL ); $nonce = filter_input( INPUT_GET, 'token', FILTER_SANITIZE_SPECIAL_CHARS ); if ( $nonce && $email ) { $error_message = $messages['invalid_data']; $entry = new Hustle_Entry_Model(); $unsubscribed = $entry->unsubscribe_email( $email, $nonce ); if ( $unsubscribed ) { return $messages['successful_unsubscription']; } else { return $error_message; } } // Show all modules' lists by default. $attributes = shortcode_atts( array( 'id' => '-1', 'skip_confirmation' => false, ), $atts ); $params = array( 'ajax_step' => false, 'shortcode_attr_id' => $attributes['id'], 'skip_confirmation' => $attributes['skip_confirmation'], 'messages' => $messages, ); $renderer = new Hustle_Layout_Helper(); $html = $renderer->render( 'general/unsubscribe-form', $params, true ); $html = apply_filters( 'hustle_render_unsubscribe_form_html', $html, $params ); return $html; } /** * Get unsubscribe form. */ public function get_unsubscribe_form() { Opt_In_Utils::validate_ajax_call( 'hustle_gutenberg_get_unsubscribe_form' ); $atts = array(); $ids = filter_input( INPUT_GET, 'module_ids', FILTER_SANITIZE_SPECIAL_CHARS ); $skip = filter_input( INPUT_GET, 'skip_confirmation', FILTER_VALIDATE_BOOLEAN ); if ( $ids ) { $atts['id'] = $ids; } if ( $skip ) { $atts['skip_confirmation'] = true; } $html = $this->unsubscribe_shortcode( $atts ); wp_send_json_success( $html ); } /** * Render the modules' wrapper to render the actual module using their shortcodes. * * @since the beginning of time. * * @param array $atts Attrs. * @param string $content Content. * @return string */ public function shortcode( $atts, $content ) { $atts = shortcode_atts( array( 'id' => '', 'type' => 'embedded', 'css_class' => '', ), $atts, self::SHORTCODE ); if ( empty( $atts['id'] ) ) { return ''; } if ( ! $this->modules_data_for_scripts ) { // This case for AJAX. $this->create_modules(); } $type = $atts['type']; // If shortcode type is not embed or sshare. if ( 'embedded' !== $type && 'social_sharing' !== $type ) { // Do not enforce embedded/social_sharing type. $enforce_type = false; } else { // Enforce embedded/social_sharing type. $enforce_type = true; } $module_id = Hustle_Model::get_module_id_by_shortcode_id( $atts['id'] ); $custom_classes = esc_attr( $atts['css_class'] ); if ( isset( $this->inline_modules[ $module_id ] ) ) { $module = $this->inline_modules[ $module_id ]; if ( ! $module->is_display_type_active( Hustle_Module_Model::SHORTCODE_MODULE ) ) { return ''; } // Display the module. ob_start(); $module->display( Hustle_Module_Model::SHORTCODE_MODULE, $custom_classes ); return ob_get_clean(); } if ( isset( $this->non_inline_modules[ $module_id ] ) && ! empty( $content ) ) { $module = $this->non_inline_modules[ $module_id ]; // If shortcode click trigger is disabled, print nothing. $settings = $module->get_settings()->to_array(); if ( ! isset( $settings['triggers']['enable_on_click_shortcode'] ) || '0' === $settings['triggers']['enable_on_click_shortcode'] ) { return ''; } return sprintf( '%s', 'hustle_module_shortcode_trigger', esc_attr( $module->id ), esc_attr( $custom_classes ), esc_attr( $module->id ), esc_attr( $type ), wp_kses_post( $content ) ); } return ''; } /** * Display inline modules. * Embedded and Social Sharing modules only. * * @since the beginning of time. * * @param string $content Content. * @return string */ public function show_after_page_post_content( $content ) { // Return the content immediately if there are no modules or the page doesn't have a content to embed into. if ( ! count( $this->inline_modules ) || isset( $_REQUEST['fl_builder'] ) || is_home() || is_archive() ) {// phpcs:ignore WordPress.Security.NonceVerification.Recommended return $content; } $in_the_loop = in_the_loop(); /** * Filters whether to skip inline modules because we're not in da loop. * This can also be used to prevent loading the inline modules conditionally. * * @param bool $in_the_loop Returned value from WordPress' in_the_loop() function. * @since 4.2.0 */ $is_in_da_loop = apply_filters( 'hustle_inline_modules_render_in_the_loop', $in_the_loop ); // We only render the inline modules in the first call of 'the_content' filter. // Prevent the modules from being printed when they shouldn't and // leaving the page's main content without them. if ( ! $is_in_da_loop ) { return $content; } $modules = apply_filters( 'hustle_inline_modules_to_display', $this->inline_modules ); foreach ( $modules as $module ) { // Skip if "inline" display is disabled. if ( ! $module->is_display_type_active( Hustle_Module_Model::INLINE_MODULE ) ) { continue; } $custom_classes = apply_filters( 'hustle_inline_module_custom_classes', '', $module ); ob_start(); $module->display( Hustle_Module_Model::INLINE_MODULE, $custom_classes ); $module_markup = ob_get_clean(); $display = $module->get_display()->to_array(); $display_position = $display['inline_position']; if ( 'both' === $display_position ) { $content = $module_markup . $content . $module_markup; } elseif ( 'above' === $display_position ) { $content = $module_markup . $content; } else { // Below. $content .= $module_markup; } } $is_render_inline_once = true; /** * Filters whether to render the inline modules once. * By default, we only render the inline modules in the first call of 'the_content' filter. * Allow rendering them in following calls of the filter if needed. * * @param bool $is_render_inline_once Whether to render the inline modules in several calls. * @since 4.2.0 */ $is_render_inline_once = apply_filters( 'hustle_inline_modules_render_once', $is_render_inline_once ); if ( $is_render_inline_once ) { remove_filter( 'the_content', array( $this, 'show_after_page_post_content' ), self::$the_content_filter_priority ); } return $content; } /** * If new post content includes unsubscribe shortcode - safe the post URL. * * @param int $post_ID Post ID. * @param WP_Post $post_after Post object following the update. * @param WP_Post $post_before Post object before the update. * @return null|void */ public static function maybe_unsubscribe_page( $post_ID, $post_after, $post_before ) { if ( ! strpos( $post_after->post_content, 'wd_hustle_unsubscribe' ) ) { return; } $post_url = get_permalink( $post_after ); if ( $post_url ) { update_option( 'hustle_unsubscribe_page', $post_url ); } } }