*/ namespace RankMath; use RankMath\Paper\Paper; use RankMath\Traits\Ajax; use RankMath\Traits\Meta; use RankMath\Traits\Hooker; use MyThemeShop\Helpers\Arr; use MyThemeShop\Helpers\Str; use MyThemeShop\Helpers\Url; use MyThemeShop\Helpers\Param; defined( 'ABSPATH' ) || exit; /** * Common class. */ class Common { use Hooker, Ajax, Meta; /** * Constructor method. */ public function __construct() { $this->action( 'admin_bar_menu', 'admin_bar_menu', 100 ); $this->action( 'loginout', 'nofollow_link' ); $this->filter( 'register', 'nofollow_link' ); $this->filter( 'rank_math/excluded_taxonomies', 'default_excluded_taxonomies' ); add_action( 'init', [ '\RankMath\Replace_Vars', 'setup' ], 99 ); // Change Permalink for primary term. $this->filter( 'post_type_link', 'post_type_link', 9, 2 ); $this->filter( 'post_link_category', 'post_link_category', 10, 3 ); // Strip stopwords from slugs. if ( Helper::get_settings( 'general.url_strip_stopwords' ) ) { $this->filter( 'get_sample_permalink', 'stopwords_default_permalink', 10, 3 ); } // "Mark page as..." functionality in the top admin bar. $this->ajax( 'mark_page_as', 'mark_page_as' ); add_action( 'wp_ajax_nopriv_rank_math_overlay_thumb', [ $this, 'generate_overlay_thumbnail' ] ); } /** * Remove stopwords from the default permalink generated automatically. * * @param array $permalink The permalink generated by WordPress. * @param int $post_id The post ID. * @param string $title The title of the post. * * @return array */ public function stopwords_default_permalink( $permalink, $post_id, $title ) { if ( empty( $title ) ) { return $permalink; } // The second element is the slug. // Turn it to an array and strip stopwords by comparing against our array of stopwords. $new_slug_parts = array_diff( explode( '-', $permalink[1] ), $this->get_stopwords() ); // Only change it if the resulting URL is at least 3 words long. if ( count( $new_slug_parts ) > 2 ) { $permalink[1] = join( '-', $new_slug_parts ); } return $permalink; } /** * Get stop words. * * @return array List of stop words. */ private function get_stopwords() { /* translators: this should be an array of stop words for your language, separated by comma's. */ $stopwords = explode( ',', esc_html__( "a,about,above,after,again,against,all,am,an,and,any,are,as,at,be,because,been,before,being,below,between,both,but,by,could,did,do,does,doing,down,during,each,few,for,from,further,had,has,have,having,he,he'd,he'll,he's,her,here,here's,hers,herself,him,himself,his,how,how's,i,i'd,i'll,i'm,i've,if,in,into,is,it,it's,its,itself,let's,me,more,most,my,myself,nor,of,on,once,only,or,other,ought,our,ours,ourselves,out,over,own,same,she,she'd,she'll,she's,should,so,some,such,than,that,that's,the,their,theirs,them,themselves,then,there,there's,these,they,they'd,they'll,they're,they've,this,those,through,to,too,under,until,up,very,was,we,we'd,we'll,we're,we've,were,what,what's,when,when's,where,where's,which,while,who,who's,whom,why,why's,with,would,you,you'd,you'll,you're,you've,your,yours,yourself,yourselves", 'rank-math' ) ); $custom = Helper::get_settings( 'general.stopwords' ); $custom = Str::to_arr_no_empty( $custom ); return array_unique( array_merge( $stopwords, $custom ) ); } /** * Filters the category that gets used in the %category% permalink token. * * @param WP_Term $term The category to use in the permalink. * @param array $terms Array of all categories (WP_Term objects) associated with the post. * @param WP_Post $post The post in question. * * @return WP_Term */ public function post_link_category( $term, $terms, $post ) { $primary_term = $this->get_primary_term( $term->taxonomy, $post->ID ); return false === $primary_term ? $term : $primary_term; } /** * Filters the permalink for a post of a custom post type. * * @param string $post_link The post's permalink. * @param WP_Post $post The post in question. * * @return string */ public function post_type_link( $post_link, $post ) { $taxonomies = Helper::get_object_taxonomies( $post->post_type, 'objects' ); $taxonomies = wp_filter_object_list( $taxonomies, [ 'hierarchical' => true ], 'and', 'name' ); foreach ( $taxonomies as $taxonomy ) { $find = "%{$taxonomy}%"; if ( ! Str::contains( $find, $post_link ) ) { continue; } $primary_term = $this->get_primary_term( $taxonomy, $post->ID ); if ( false !== $primary_term ) { // Get the hierachical terms. $parents = $this->get_hierarchical_link( $primary_term ); // Replace the placeholder rewrite tag with hierachical terms. $post_link = str_replace( $find, $parents, $post_link ); } } return $post_link; } /** * Get chain of hierarchical links. * * @param WP_Term $term The term in question. * * @return string */ private function get_hierarchical_link( $term ) { if ( is_wp_error( $term ) ) { return $term->slug; } $chain = []; $name = $term->slug; if ( $term->parent && ( $term->parent !== $term->term_id ) ) { $chain[] = $this->get_hierarchical_link( get_term( $term->parent, $term->taxonomy ) ); } $chain[] = $name; return implode( '/', $chain ); } /** * Get primary term of the post. * * @param string $taxonomy Taxonomy name. * @param int $post_id Post ID. * * @return object|false Primary term on success, false if there are no terms, WP_Error on failure. */ private function get_primary_term( $taxonomy, $post_id ) { $primary = Helper::get_post_meta( "primary_{$taxonomy}", $post_id ); if ( ! $primary ) { return false; } $primary = get_term( $primary, $taxonomy ); return is_wp_error( $primary ) ? false : $primary; } /** * Exclude taxonomies. * * @param array $taxonomies Excluded taxonomies. * * @return array */ public function default_excluded_taxonomies( $taxonomies ) { if ( ! current_theme_supports( 'post-formats' ) ) { unset( $taxonomies['post_format'] ); } unset( $taxonomies['product_shipping_class'] ); return $taxonomies; } /** * Add rel="nofollow" to a link. * * @param string $link The link as a string. * * @return string */ public function nofollow_link( $link ) { // Check if link is nofollow already. if ( strpos( $link, ' rel="nofollow"' ) || strpos( $link, " rel='nofollow'" ) ) { return $link; } return str_replace( ' 'rank-math', 'title' => '' . $this->get_icon() . '' . esc_html( 'Rank Math SEO', 'rank-math' ) . '', 'href' => Helper::get_admin_url( $first_menu ), 'meta' => [ 'title' => esc_html__( 'Rank Math Dashboard', 'rank-math' ) ], '_priority' => 10, ]; if ( current_user_can( 'manage_options' ) ) { $items['dashboard'] = [ 'id' => 'rank-math-dashboard', 'title' => esc_html__( 'Dashboard', 'rank-math' ), 'href' => $items['main']['href'], 'parent' => 'rank-math', 'meta' => [ 'title' => esc_html__( 'Dashboard', 'rank-math' ) ], '_priority' => 20, ]; } if ( ! is_admin() ) { $this->seo_tools_menu_item( $items ); } if ( Helper::has_cap( 'titles' ) ) { if ( is_home() ) { $items['local'] = [ 'id' => 'rank-math-home', 'title' => esc_html__( 'Homepage SEO', 'rank-math' ), 'href' => Helper::get_admin_url( 'options-titles#setting-panel-homepage' ), 'parent' => 'rank-math', 'meta' => [ 'title' => esc_html__( 'Edit Homepage SEO Settings', 'rank-math' ) ], '_priority' => 35, ]; } elseif ( is_singular( Helper::get_accessible_post_types() ) ) { $mark_me = true; $object = get_post_type_object( $post_type ); $object_type = 'post'; $items['local'] = [ 'id' => 'rank-math-posttype', /* translators: Post Type Singular Name */ 'title' => sprintf( esc_html__( 'SEO Settings for %s', 'rank-math' ), $object->labels->name ), 'href' => Helper::get_admin_url( 'options-titles#setting-panel-post-type-' . $post_type ), 'parent' => 'rank-math', 'meta' => [ 'title' => esc_html__( 'Edit default SEO settings for this post type', 'rank-math' ) ], '_priority' => 35, ]; } elseif ( ( is_category() || is_tag() || is_tax() ) && in_array( $post_type, Helper::get_accessible_post_types(), true ) ) { $mark_me = true; $term = get_queried_object(); $labels = get_taxonomy_labels( get_taxonomy( $term->taxonomy ) ); $object_type = 'term'; $items['local'] = [ 'id' => 'rank-math-tax', /* translators: Taxonomy Singular Name */ 'title' => sprintf( esc_html__( 'SEO Settings for %s', 'rank-math' ), $labels->name ), 'href' => Helper::get_admin_url( 'options-titles#setting-panel-taxonomy-' . $term->taxonomy ), 'parent' => 'rank-math', 'meta' => [ 'title' => esc_html__( 'Edit SEO settings for this archive page', 'rank-math' ) ], '_priority' => 35, ]; } elseif ( is_date() ) { $items['local'] = [ 'id' => 'rank-math-date', 'title' => esc_html__( 'SEO Settings for Date Archives', 'rank-math' ), 'href' => Helper::get_admin_url( 'options-titles#setting-panel-global' ), 'parent' => 'rank-math', 'meta' => [ 'title' => esc_html__( 'Edit SEO settings for this archive page', 'rank-math' ) ], '_priority' => 35, ]; } elseif ( is_search() ) { $items['local'] = [ 'id' => 'rank-math-search', 'title' => esc_html__( 'SEO Settings for Search Page', 'rank-math' ), 'href' => Helper::get_admin_url( 'options-titles#setting-panel-global' ), 'parent' => 'rank-math', 'meta' => [ 'title' => esc_html__( 'Edit SEO settings for the search results page', 'rank-math' ) ], '_priority' => 35, ]; } } if ( is_author() ) { $mark_me = true; $object_type = 'user'; } if ( $mark_me && Helper::has_cap( 'onpage_general' ) ) { $items['mark'] = [ 'id' => 'rank-math-mark-me', 'title' => esc_html__( 'Mark this page', 'rank-math' ), 'href' => '#', 'parent' => 'rank-math', '_priority' => 100, ]; $dashicon_format = ''; $ispillar_check = ''; if ( is_singular( Helper::get_accessible_post_types() ) ) { if ( get_post_meta( get_the_ID(), 'rank_math_pillar_content', true ) === 'on' ) { $ispillar_check = sprintf( $dashicon_format, 'yes' ); } $items['pillar-content'] = [ 'id' => 'rank-math-pillar-content', 'title' => $ispillar_check . esc_html__( 'As Pillar Content', 'rank-math' ), 'href' => '#pillar_content', 'parent' => 'rank-math-mark-me', 'meta' => [ 'class' => 'mark-page-as' ], '_priority' => 110, ]; } if ( ! is_admin() && Paper::get() ) { $robots = Paper::get()->get_robots(); $noindex_check = in_array( 'noindex', $robots, true ) ? sprintf( $dashicon_format, 'yes' ) : ''; $items['no-index'] = [ 'id' => 'rank-math-no-index', 'title' => $noindex_check . esc_html__( 'As NoIndex', 'rank-math' ), 'href' => '#noindex', 'parent' => 'rank-math-mark-me', 'meta' => [ 'class' => 'mark-page-as' ], '_priority' => 120, ]; $nofollow_check = in_array( 'nofollow', $robots, true ) ? sprintf( $dashicon_format, 'yes' ) : ''; $items['no-follow'] = [ 'id' => 'rank-math-no-follow', 'title' => $nofollow_check . esc_html__( 'As NoFollow', 'rank-math' ), 'href' => '#nofollow', 'parent' => 'rank-math-mark-me', 'meta' => [ 'class' => 'mark-page-as' ], '_priority' => 130, ]; } } /** * Add item to rank math admin bar node. * * @param array $items Array of nodes for rank math menu. */ $items = $this->do_filter( 'admin_bar/items', $items ); // Keep original order when uasort() deals with equal "_priority" values. $orig_order_counter = 0; foreach ( $items as &$item ) { $item['_original_order'] = $orig_order_counter++; } uasort( $items, [ $this, 'sort_admin_bar_items' ] ); foreach ( $items as $item ) { $wp_admin_bar->add_node( $item ); } } /** * Third party SEO Tools, like the Google Structured Data Testing Tool. * * @param array $items Array to add menu into. */ private function seo_tools_menu_item( &$items ) { $link_urlencoded = ( ! is_admin() && ! is_preview() ) ? urlencode( Url::get_current_url() ) : ''; $items['third-party'] = [ 'id' => 'rank-math-third-party', 'title' => esc_html__( 'External Tools', 'rank-math' ), 'href' => '#', 'parent' => 'rank-math', 'meta' => [ 'title' => esc_html__( 'Third Party SEO Tools', 'rank-math' ) ], '_priority' => 200, ]; $items['third-party-google-structured-data'] = [ 'id' => 'rank-math-google-structured-data', 'title' => esc_html__( 'Google Structured Data', 'rank-math' ), 'href' => 'https://search.google.com/structured-data/testing-tool/?url=' . $link_urlencoded, 'parent' => 'rank-math-third-party', 'meta' => [ 'title' => esc_html__( 'Google Structured Data Testing Tool', 'rank-math' ), 'target' => '_blank', ], '_priority' => 210, ]; $items['third-party-google-pagespeed'] = [ 'id' => 'rank-math-google-pagespeed', 'title' => esc_html__( 'Google PageSpeed', 'rank-math' ), 'href' => 'https://developers.google.com/speed/pagespeed/insights/?url=' . $link_urlencoded, 'parent' => 'rank-math-third-party', 'meta' => [ 'title' => esc_html__( 'Google PageSpeed Insights', 'rank-math' ), 'target' => '_blank', ], '_priority' => 220, ]; $items['third-party-google-mobilefriendly'] = [ 'id' => 'rank-math-google-mobilefriendly', 'title' => esc_html__( 'Google Mobile-Friendly', 'rank-math' ), 'href' => 'https://search.google.com/test/mobile-friendly?url=' . $link_urlencoded, 'parent' => 'rank-math-third-party', 'meta' => [ 'title' => esc_html__( 'Google Mobile-Friendly Test', 'rank-math' ), 'target' => '_blank', ], '_priority' => 230, ]; if ( ! is_admin() && ! is_preview() ) { $items['third-party-google-cache'] = [ 'id' => 'rank-math-google-cache', 'title' => esc_html__( 'Google Cache', 'rank-math' ), 'href' => 'https://webcache.googleusercontent.com/search?q=cache:' . $link_urlencoded, 'parent' => 'rank-math-third-party', 'meta' => [ 'title' => esc_html__( 'See Google\'s cached version of your site', 'rank-math' ), 'target' => '_blank', ], '_priority' => 240, ]; } $items['third-party-fb-debugger'] = [ 'id' => 'rank-math-fb-debugger', 'title' => esc_html__( 'Facebook Debugger', 'rank-math' ), 'href' => 'https://developers.facebook.com/tools/debug/sharing/?q=' . $link_urlencoded, 'parent' => 'rank-math-third-party', 'meta' => [ 'title' => esc_html__( 'Facebook Sharing Debugger', 'rank-math' ), 'target' => '_blank', ], '_priority' => 250, ]; } /** * Sort admin bar items callback. * * @param array $item1 Item A to compare. * @param array $item2 Item B to compare. * * @return integer */ public function sort_admin_bar_items( $item1, $item2 ) { if ( ! isset( $item1['_priority'] ) || ! isset( $item2['_priority'] ) || $item1['_priority'] === $item2['_priority'] ) { return $item1['_original_order'] < $item2['_original_order'] ? -1 : 1; } return $item1['_priority'] < $item2['_priority'] ? -1 : 1; } /** * AJAX function to mark page as Pillar Content/Noindex/Nofollow. */ public function mark_page_as() { check_ajax_referer( 'rank-math-ajax-nonce', 'security' ); $this->has_cap_ajax( 'onpage_general' ); $what = Param::post( 'what' ); $object_id = Param::post( 'objectID' ); $object_type = Param::post( 'objectType' ); if ( ! $what || ! $object_id || ! $object_type || ! in_array( $what, [ 'pillar_content', 'noindex', 'nofollow' ], true ) ) { return 0; } if ( 'pillar_content' === $what ) { $current = $this->get_meta( $object_type, $object_id, 'rank_math_pillar_content' ); $updated = 'on' === $current ? 'off' : 'on'; $this->update_meta( $object_type, $object_id, 'rank_math_pillar_content', $updated ); die( '1' ); } if ( 'noindex' === $what || 'nofollow' === $what ) { $robots = (array) $this->get_meta( $object_type, $object_id, 'rank_math_robots' ); $robots = array_filter( $robots ); Arr::add_delete_value( $robots, $what ); $robots = array_unique( $robots ); $this->update_meta( $object_type, $object_id, 'rank_math_robots', $robots ); die( '1' ); } die(); } /** * AJAX function to generate overlay image. Used in social thumbnails. */ public function generate_overlay_thumbnail() { $thumbnail_id = Param::request( 'id', 0, FILTER_VALIDATE_INT ); $type = Param::request( 'type', 'play' ); $overlay_image = Helper::choices_overlay_images()[ $type ]['url']; $image = wp_get_attachment_image_src( $thumbnail_id, 'full' ); if ( ! empty( $image ) ) { $this->create_overlay_image( $image[0], $overlay_image ); } die(); } /** * Create Overlay Image. * * @param string $image_file The permalink generated for this post by WordPress. * @param string $overlay_image The ID of the post. */ public function create_overlay_image( $image_file, $overlay_image ) { $image_format = pathinfo( $image_file, PATHINFO_EXTENSION ); if ( ! in_array( $image_format, [ 'jpg', 'jpeg', 'gif', 'png' ], true ) ) { return; } if ( 'jpg' === $image_format ) { $image_format = 'jpeg'; } $imagecreatef = 'imagecreatefrom' . $image_format; $stamp = imagecreatefrompng( $overlay_image ); $image = $imagecreatef( $image_file ); // Set the margins for the stamp and get the height/width of the stamp image. $img_width = imagesx( $stamp ); $img_height = imagesy( $stamp ); $margin_right = round( abs( imagesx( $image ) - $img_width ) / 2 ); $margin_bottom = round( abs( imagesy( $image ) - $img_height ) / 2 ); // Copy the stamp image onto our photo using the margin offsets and the photo width to calculate positioning of the stamp. imagecopy( $image, $stamp, $margin_right, $margin_bottom, 0, 0, $img_width, $img_height ); // Output and free memory. header( 'Content-type: image/png' ); imagepng( $image ); imagedestroy( $image ); } /** * Get Rank Math icon. * * @param integer $width Width of the icon. * * @return string */ private function get_icon( $width = 20 ) { return ''; } }