_blog_id_local = $blog_id_local; $this->_blog_id_wpcom = $blog_id_wpcom; $this->_blog_charset = get_option( 'blog_charset' ); $this->_convert_charset = ( function_exists( 'iconv' ) && ! preg_match( '/^utf\-?8$/i', $this->_blog_charset ) ); add_action( 'admin_init', array( $this, 'action_admin_init' ) ); add_action( 'wp', array( $this, 'action_frontend_init' ) ); if ( ! class_exists( 'Jetpack_Media_Summary' ) ) { jetpack_require_lib( 'class.media-summary' ); } // Add Related Posts to the REST API Post response. if ( function_exists( 'register_rest_field' ) ) { add_action( 'rest_api_init', array( $this, 'rest_register_related_posts' ) ); } } /** * ================= * ACTIONS & FILTERS * ================= */ /** * Add a checkbox field to Settings > Reading for enabling related posts. * * @action admin_init * @uses add_settings_field, __, register_setting, add_action * @return null */ public function action_admin_init() { // Add the setting field [jetpack_relatedposts] and place it in Settings > Reading add_settings_field( 'jetpack_relatedposts', '' . __( 'Related posts', 'jetpack' ) . '', array( $this, 'print_setting_html' ), 'reading' ); register_setting( 'reading', 'jetpack_relatedposts', array( $this, 'parse_options' ) ); add_action('admin_head', array( $this, 'print_setting_head' ) ); if( 'options-reading.php' == $GLOBALS['pagenow'] ) { // Enqueue style for live preview on the reading settings page $this->_enqueue_assets( false, true ); } } /** * Load related posts assets if it's a elegiable front end page or execute search and return JSON if it's an endpoint request. * * @global $_GET * @action wp * @uses add_shortcode, get_the_ID * @returns null */ public function action_frontend_init() { // Add a shortcode handler that outputs nothing, this gets overridden later if we can display related content add_shortcode( self::SHORTCODE, array( $this, 'get_target_html_unsupported' ) ); if ( ! $this->_enabled_for_request() ) return; if ( isset( $_GET['relatedposts'] ) ) { $excludes = array(); if ( isset( $_GET['relatedposts_exclude'] ) ) { $excludes = explode( ',', $_GET['relatedposts_exclude'] ); } $this->_action_frontend_init_ajax( $excludes ); } else { if ( isset( $_GET['relatedposts_hit'], $_GET['relatedposts_origin'], $_GET['relatedposts_position'] ) ) { $this->_log_click( $_GET['relatedposts_origin'], get_the_ID(), $_GET['relatedposts_position'] ); $this->_previous_post_id = (int) $_GET['relatedposts_origin']; } $this->_action_frontend_init_page(); } } /** * Render insertion point. * * @since 4.2.0 * * @return string */ public function get_headline() { $options = $this->get_options(); if ( $options['show_headline'] ) { $headline = sprintf( '', esc_html( $options['headline'] ) ); } else { $headline = ''; } return $headline; } /** * Adds a target to the post content to load related posts into if a shortcode for it did not already exist. * * @filter the_content * @param string $content * @returns string */ public function filter_add_target_to_dom( $content ) { if ( !$this->_found_shortcode ) { $content .= "\n" . $this->get_target_html(); } return $content; } /** * Looks for our shortcode on the unfiltered content, this has to execute early. * * @filter the_content * @param string $content * @uses has_shortcode * @returns string */ public function test_for_shortcode( $content ) { $this->_found_shortcode = has_shortcode( $content, self::SHORTCODE ); return $content; } /** * Returns the HTML for the related posts section. * * @uses esc_html__, apply_filters * @returns string */ public function get_target_html() { require_once JETPACK__PLUGIN_DIR . '/sync/class.jetpack-sync-settings.php'; if ( Jetpack_Sync_Settings::is_syncing() ) { return ''; } /** * Filter the Related Posts headline. * * @module related-posts * * @since 3.0.0 * * @param string $headline Related Posts heading. */ $headline = apply_filters( 'jetpack_relatedposts_filter_headline', $this->get_headline() ); if ( $this->_previous_post_id ) { $exclude = "data-exclude='{$this->_previous_post_id}'"; } else { $exclude = ""; } return << $headline EOT; } /** * Returns the HTML for the related posts section if it's running in the loop or other instances where we don't support related posts. * * @returns string */ public function get_target_html_unsupported() { require_once JETPACK__PLUGIN_DIR . '/sync/class.jetpack-sync-settings.php'; if ( Jetpack_Sync_Settings::is_syncing() ) { return ''; } return "\n\n\n\n"; } /** * ======================== * PUBLIC UTILITY FUNCTIONS * ======================== */ /** * Gets options set for Jetpack_RelatedPosts and merge with defaults. * * @uses Jetpack_Options::get_option, apply_filters * @return array */ public function get_options() { if ( null === $this->_options ) { $this->_options = Jetpack_Options::get_option( 'relatedposts', array() ); if ( ! is_array( $this->_options ) ) $this->_options = array(); if ( ! isset( $this->_options['enabled'] ) ) $this->_options['enabled'] = true; if ( ! isset( $this->_options['show_headline'] ) ) $this->_options['show_headline'] = true; if ( ! isset( $this->_options['show_thumbnails'] ) ) $this->_options['show_thumbnails'] = false; if ( ! isset( $this->_options['show_date'] ) ) { $this->_options['show_date'] = true; } if ( ! isset( $this->_options['show_context'] ) ) { $this->_options['show_context'] = true; } if ( ! isset( $this->_options['layout'] ) ) { $this->_options['layout'] = 'grid'; } if ( ! isset( $this->_options['headline'] ) ) { $this->_options['headline'] = esc_html__( 'Related', 'jetpack' ); } if ( empty( $this->_options['size'] ) || (int)$this->_options['size'] < 1 ) $this->_options['size'] = 3; /** * Filter Related Posts basic options. * * @module related-posts * * @since 2.8.0 * * @param array $this->_options Array of basic Related Posts options. */ $this->_options = apply_filters( 'jetpack_relatedposts_filter_options', $this->_options ); } return $this->_options; } /** * Parses input and returns normalized options array. * * @param array $input * @uses self::get_options * @return array */ public function parse_options( $input ) { $current = $this->get_options(); if ( !is_array( $input ) ) $input = array(); if ( isset( $input['enabled'] ) && '1' == $input['enabled'] ) { $current['enabled'] = true; $current['show_headline'] = ( isset( $input['show_headline'] ) && '1' == $input['show_headline'] ); $current['show_thumbnails'] = ( isset( $input['show_thumbnails'] ) && '1' == $input['show_thumbnails'] ); $current['show_date'] = ( isset( $input['show_date'] ) && '1' == $input['show_date'] ); $current['show_context'] = ( isset( $input['show_context'] ) && '1' == $input['show_context'] ); $current['layout'] = isset( $input['layout'] ) && in_array( $input['layout'], array( 'grid', 'list' ), true ) ? $input['layout'] : 'grid'; $current['headline'] = isset( $input['headline'] ) ? $input['headline'] : esc_html__( 'Related', 'jetpack' ); } else { $current['enabled'] = false; } if ( isset( $input['size'] ) && (int)$input['size'] > 0 ) $current['size'] = (int)$input['size']; else $current['size'] = null; return $current; } /** * HTML for admin settings page. * * @uses self::get_options, checked, esc_html__ * @returns null */ public function print_setting_html() { $options = $this->get_options(); $ui_settings_template = <<
  • EOT; $ui_settings = sprintf( $ui_settings_template, checked( $options['show_headline'], true, false ), esc_html__( 'Show a "Related" header to more clearly separate the related section from posts', 'jetpack' ), checked( $options['show_thumbnails'], true, false ), esc_html__( 'Use a large and visually striking layout', 'jetpack' ), checked( $options['show_date'], true, false ), esc_html__( 'Show entry date', 'jetpack' ), checked( $options['show_context'], true, false ), esc_html__( 'Show context (category or tag)', 'jetpack' ), esc_html__( 'Preview:', 'jetpack' ) ); if ( !$this->_allow_feature_toggle() ) { $template = << %s EOT; printf( $template, $ui_settings ); } else { $template = <<
  • %s
  • EOT; printf( $template, checked( $options['enabled'], false, false ), esc_html__( 'Hide related content after posts', 'jetpack' ), checked( $options['enabled'], true, false ), esc_html__( 'Show related content after posts', 'jetpack' ), $ui_settings ); } } /** * Head JS/CSS for admin settings page. * * @uses esc_html__ * @returns null */ public function print_setting_head() { // only dislay the Related Posts JavaScript on the Reading Settings Admin Page $current_screen = get_current_screen(); if ( is_null( $current_screen ) ) { return; } if( 'options-reading' != $current_screen->id ) return; $related_headline = sprintf( '', esc_html__( 'Related', 'jetpack' ) ); $href_params = 'class="jp-relatedposts-post-a" href="#jetpack_relatedposts" rel="nofollow" data-origin="0" data-position="0"'; $related_with_images = <<