*/ namespace RankMath\Frontend; use RankMath\Post; use RankMath\Helper; use RankMath\Paper\Paper; use RankMath\Traits\Hooker; use RankMath\OpenGraph\Twitter; use RankMath\OpenGraph\Facebook; use RankMath\Frontend\Shortcodes; defined( 'ABSPATH' ) || exit; /** * Frontend class. */ class Frontend { use Hooker; /** * The Constructor. */ public function __construct() { $this->includes(); $this->hooks(); /** * Fires when frontend is included/loaded. */ $this->do_action( 'frontend/loaded' ); } /** * Include required files. */ private function includes() { rank_math()->shortcodes = new Shortcodes; if ( Helper::get_settings( 'general.breadcrumbs' ) ) { /** * If RM's breadcrumbs are enabled then we can remove the bbPress breadcrumbs. */ add_filter( 'bbp_get_breadcrumb', '__return_false' ); } new Add_Attributes; new Remove_Reply_To_Com; } /** * Hook into actions and filters. */ private function hooks() { $this->action( 'wp_enqueue_scripts', 'enqueue' ); $this->action( 'wp', 'integrations' ); $this->filter( 'the_content_feed', 'embed_rssfooter' ); $this->filter( 'the_excerpt_rss', 'embed_rssfooter_excerpt' ); // Reorder categories listing: put primary at the beginning. $this->filter( 'get_the_terms', 'reorder_the_terms', 10, 3 ); // Redirect attachment page to parent post. if ( Helper::get_settings( 'general.attachment_redirect_urls', true ) ) { $this->action( 'wp', 'attachment_redirect_urls' ); } // Redirect archives. if ( Helper::get_settings( 'titles.disable_author_archives' ) || Helper::get_settings( 'titles.disable_date_archives' ) ) { $this->action( 'wp', 'archive_redirect' ); } // Custom robots text. if ( Helper::get_settings( 'general.robots_txt_content' ) ) { $this->action( 'robots_txt', 'robots_txt', 10, 2 ); } } /** * Initialize integrations. */ public function integrations() { $type = get_query_var( 'sitemap' ); if ( ! empty( $type ) || is_customize_preview() ) { return; } Paper::get(); new Facebook; new Twitter; // Leave this for backwards compatibility as AMP plugin uses head function. We can remove this in the future update. rank_math()->head = new Head; } /** * Enqueue Styles and Scripts required by plugin. */ public function enqueue() { if ( ! is_admin_bar_showing() || ! Helper::has_cap( 'admin_bar' ) ) { return; } wp_enqueue_style( 'rank-math', rank_math()->assets() . 'css/rank-math.css', null, rank_math()->version ); wp_enqueue_script( 'rank-math', rank_math()->assets() . 'js/rank-math.js', [ 'jquery' ], rank_math()->version, true ); if ( is_singular() ) { Helper::add_json( 'objectID', Post::get_simple_page_id() ); Helper::add_json( 'objectType', 'post' ); } elseif ( is_category() || is_tag() || is_tax() ) { Helper::add_json( 'objectID', get_queried_object_id() ); Helper::add_json( 'objectType', 'term' ); } elseif ( is_author() ) { Helper::add_json( 'objectID', get_queried_object_id() ); Helper::add_json( 'objectType', 'user' ); } } /** * Redirects attachment to its parent post if it has one. */ public function attachment_redirect_urls() { global $post; // Early bail. if ( ! is_attachment() ) { return; } $redirect = ! empty( $post->post_parent ) ? get_permalink( $post->post_parent ) : Helper::get_settings( 'general.attachment_redirect_default' ); /** * Redirect atachment to its parent post. * * @param string $redirect URL as calculated for redirection. */ Helper::redirect( $this->do_filter( 'frontend/attachment/redirect_url', $redirect ), 301 ); exit; } /** * When certain archives are disabled, this redirects those to the homepage. */ public function archive_redirect() { global $wp_query; if ( ( Helper::get_settings( 'titles.disable_date_archives' ) && $wp_query->is_date ) || ( true === Helper::get_settings( 'titles.disable_author_archives' ) && $wp_query->is_author ) ) { Helper::redirect( get_bloginfo( 'url' ), 301 ); exit; } } /** * Replace robots.txt content. * * @param string $content Robots.txt file content. * @param bool $public Whether the site is considered "public". * @return string New robots.txt content. */ public function robots_txt( $content, $public ) { if ( is_admin() ) { return $content; } return 0 === absint( $public ) ? $content : Helper::get_settings( 'general.robots_txt_content' ); } /** * Adds the RSS header and footer messages to the RSS feed item content. * * @param string $content Feed item content. * @return string */ public function embed_rssfooter( $content ) { return $this->embed_rss( $content, 'full' ); } /** * Adds the RSS header and footer messages to the RSS feed item excerpt. * * @param string $content Feed item excerpt. * @return string */ public function embed_rssfooter_excerpt( $content ) { return $this->embed_rss( $content, 'excerpt' ); } /** * Inserts the RSS header and footer messages in the RSS feed item. * * @param string $content Feed item content. * @param string $context Feed item context, 'excerpt' or 'full'. * @return string */ private function embed_rss( $content, $context = 'full' ) { if ( false === $this->can_embed_footer( $content, $context ) ) { return $content; } $before = $this->do_filter( 'frontend/rss/before_content', Helper::get_settings( 'general.rss_before_content' ) ); $after = $this->do_filter( 'frontend/rss/after_content', Helper::get_settings( 'general.rss_after_content' ) ); if ( '' !== $before ) { $before = wpautop( $this->rss_replace_vars( $before ) ); } if ( '' !== $after ) { $after = wpautop( $this->rss_replace_vars( $after ) ); } if ( '' !== $before || '' !== $after ) { if ( 'excerpt' === $context && '' !== trim( $content ) ) { $content = wpautop( $content ); } $content = $before . $content . $after; } return $content; } /** * Check if we can add the RSS footer and/or header to the RSS feed item. * * @param string $content Feed item content. * @param string $context Feed item context, either 'excerpt' or 'full'. * * @return boolean */ private function can_embed_footer( $content, $context ) { /** * Allow the RSS footer to be dynamically shown/hidden. * * @param bool $show_embed Indicates if the RSS footer should be shown or not. * @param string $context The context of the RSS content - 'full' or 'excerpt'. */ if ( false === $this->do_filter( 'frontend/rss/include_footer', true, $context ) ) { return false; } if ( ! is_feed() ) { return false; } return true; } /** * Replace variables with the actual values in RSS header and footer messages. * * @param string $content The RSS content. * * @return string */ private function rss_replace_vars( $content ) { global $post; /** * Add nofollow for the links in the RSS header and footer messages. Default: true. * * @param bool $unsigned Whether or not to follow the links in RSS feed, defaults to true. */ $no_follow = $this->do_filter( 'frontend/rss/nofollow_links', true ); $no_follow = true === $no_follow ? 'rel="nofollow" ' : ''; $author_link = ''; if ( is_object( $post ) ) { $author_link = '' . esc_html( get_the_author() ) . ''; } $post_link = '' . esc_html( get_the_title() ) . ''; $blog_link = '' . esc_html( get_bloginfo( 'name' ) ) . ''; $blog_desc_link = '' . esc_html( get_bloginfo( 'name' ) ) . ' - ' . esc_html( get_bloginfo( 'description' ) ) . ''; // Featured image. $image = Helper::get_thumbnail_with_fallback( $post->ID, 'full' ); $image = isset( $image[0] ) ? '' : ''; $content = stripslashes( trim( $content ) ); $content = str_replace( '%AUTHORLINK%', $author_link, $content ); $content = str_replace( '%POSTLINK%', $post_link, $content ); $content = str_replace( '%BLOGLINK%', $blog_link, $content ); $content = str_replace( '%BLOGDESCLINK%', $blog_desc_link, $content ); $content = str_replace( '%FEATUREDIMAGE%', $image, $content ); return $content; } /** * Reorder terms for a post to put primary category to the beginning. * * @param array|WP_Error $terms List of attached terms, or WP_Error on failure. * @param int $post_id Post ID. * @param string $taxonomy Name of the taxonomy. * @return array */ public function reorder_the_terms( $terms, $post_id, $taxonomy ) { /** * Filter: Allow disabling the primary term feature. * * @param bool $return True to disable. */ if ( true === $this->do_filter( 'primary_term', false ) ) { return $terms; } $post_id = empty( $post_id ) ? $GLOBALS['post']->ID : $post_id; // Get Primary Term. $primary = absint( Helper::get_post_meta( "primary_{$taxonomy}", $post_id ) ); if ( ! $primary ) { return $terms; } if ( empty( $terms ) || is_wp_error( $terms ) ) { return [ $primary ]; } $primary_term = null; foreach ( $terms as $index => $term ) { if ( $primary === $term->term_id ) { $primary_term = $term; unset( $terms[ $index ] ); array_unshift( $terms, $primary_term ); break; } } return $terms; } }