You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
289 lines
9.8 KiB
PHTML
289 lines
9.8 KiB
PHTML
8 months ago
|
<?php
|
||
|
/**
|
||
|
* Show SEO Score on the front end.
|
||
|
*
|
||
|
* @since 0.9.0
|
||
|
* @package RankMath
|
||
|
* @author Rank Math <support@rankmath.com>
|
||
|
*/
|
||
|
|
||
|
namespace RankMath;
|
||
|
|
||
|
use RankMath\KB;
|
||
|
use RankMath\Post;
|
||
|
use RankMath\Helper;
|
||
|
use RankMath\Traits\Hooker;
|
||
|
use RankMath\Traits\Shortcode;
|
||
|
use RankMath\Admin\Admin_Helper;
|
||
|
|
||
|
defined( 'ABSPATH' ) || exit;
|
||
|
|
||
|
/**
|
||
|
* Frontend_SEO_Score class.
|
||
|
*/
|
||
|
class Frontend_SEO_Score {
|
||
|
|
||
|
use Hooker, Shortcode;
|
||
|
|
||
|
/**
|
||
|
* SEO Score.
|
||
|
*
|
||
|
* @var array
|
||
|
*/
|
||
|
private $score = 0;
|
||
|
|
||
|
/**
|
||
|
* Flag to only add CSS once.
|
||
|
*
|
||
|
* @var array
|
||
|
*/
|
||
|
private $css_added = false;
|
||
|
|
||
|
/**
|
||
|
* Convenience method to output as string.
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function __toString() {
|
||
|
return $this->get_output();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* The Constructor
|
||
|
*
|
||
|
* @codeCoverageIgnore
|
||
|
*/
|
||
|
public function __construct() {
|
||
|
$this->filter( 'the_content', 'insert_score' );
|
||
|
|
||
|
$this->add_shortcode( 'rank_math_seo_score', 'shortcode' );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Insert score before/after content.
|
||
|
*
|
||
|
* @param string $content Original post content.
|
||
|
* @return string $content New content.
|
||
|
*/
|
||
|
public function insert_score( $content ) {
|
||
|
|
||
|
if ( ! $this->score_enabled() ) {
|
||
|
return $content;
|
||
|
}
|
||
|
|
||
|
$score_location = Helper::get_settings( 'general.frontend_seo_score_position' );
|
||
|
if ( 'custom' === $score_location ) {
|
||
|
return $content;
|
||
|
}
|
||
|
|
||
|
if ( 'top' === $score_location || 'both' === $score_location ) {
|
||
|
$content = $this->get_output( [ 'class' => 'before-content' ] ) . $content;
|
||
|
}
|
||
|
|
||
|
if ( 'bottom' === $score_location || 'both' === $score_location ) {
|
||
|
$content = $content . $this->get_output( [ 'class' => 'after-content' ] );
|
||
|
}
|
||
|
|
||
|
return $content;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check if front end SEO score is enabled for this post.
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function score_enabled() {
|
||
|
/*
|
||
|
* The loop_start check ensures this only runs after wp_head.
|
||
|
*/
|
||
|
if ( is_front_page() || ! is_singular() || ! did_action( 'loop_start' ) ) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$post_type = get_post_type();
|
||
|
$post_id = get_the_ID();
|
||
|
$score_enabled = Helper::get_settings( 'general.frontend_seo_score' )
|
||
|
&& Helper::is_score_enabled()
|
||
|
&& in_array( $post_type, (array) Helper::get_settings( 'general.frontend_seo_score_post_types' ), true )
|
||
|
&& get_post_meta( $post_id, 'rank_math_dont_show_seo_score', true ) !== 'on';
|
||
|
|
||
|
return $score_enabled;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the SEO score HTML.
|
||
|
*
|
||
|
* @param array $args Arguments.
|
||
|
* @return string
|
||
|
*/
|
||
|
public function get_output( $args = [] ) {
|
||
|
$args = $this->do_filter(
|
||
|
'frontend/seo_score/args',
|
||
|
wp_parse_args(
|
||
|
$args,
|
||
|
[
|
||
|
'template' => Helper::get_settings( 'general.frontend_seo_score_template' ),
|
||
|
'backlink' => Helper::get_settings( 'general.support_rank_math' ),
|
||
|
'post_id' => '0',
|
||
|
'class' => '',
|
||
|
]
|
||
|
)
|
||
|
);
|
||
|
|
||
|
$score = (int) $this->get_score( $args['post_id'] );
|
||
|
$rating = $this->get_rating( $score );
|
||
|
|
||
|
if ( ! $score ) {
|
||
|
return $this->do_filter( 'frontend/seo_score/html', '', $args, $score );
|
||
|
}
|
||
|
|
||
|
// If template is empty we output $score value directly.
|
||
|
$html = $score;
|
||
|
$backlink = '<a href="' . KB::get( 'seo-suite', 'Frontend SEO score' ) . '" target="_blank" rel="noopener">Rank Math SEO</a>';
|
||
|
if ( ! empty( $args['template'] ) ) {
|
||
|
ob_start();
|
||
|
|
||
|
?>
|
||
|
<div class="rank-math-seo-score template-<?php echo sanitize_html_class( $args['template'], 'circle' ); ?> <?php echo sanitize_html_class( $rating, 'unknown' ); ?>-seo <?php echo esc_attr( $args['class'] ); ?>">
|
||
|
|
||
|
<span class="score">
|
||
|
<?php echo esc_html( absint( $score ) ); ?>
|
||
|
<span class="outof">
|
||
|
/ 100
|
||
|
</span>
|
||
|
</span>
|
||
|
|
||
|
<?php if ( $args['backlink'] ) : ?>
|
||
|
<div class="backlink">
|
||
|
<span class="poweredby">
|
||
|
<?php
|
||
|
printf(
|
||
|
/* translators: %s is a Rank Math link. */
|
||
|
__( 'Powered by %s', 'rank-math' ),
|
||
|
$this->do_filter( 'frontend/seo_score/backlink', $backlink )
|
||
|
);
|
||
|
?>
|
||
|
</span>
|
||
|
</div>
|
||
|
<?php endif; ?>
|
||
|
|
||
|
<span class="label">
|
||
|
<?php esc_html__( 'SEO Score', 'rank-math' ); ?>
|
||
|
</span>
|
||
|
|
||
|
</div>
|
||
|
<?php
|
||
|
$this->add_css();
|
||
|
|
||
|
$html = ob_get_clean();
|
||
|
}
|
||
|
|
||
|
return $this->do_filter( 'frontend/seo_score/html', $html, $args, $score );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Turn numeric score into textual rating.
|
||
|
*
|
||
|
* @param int $score SEO Score.
|
||
|
* @return string
|
||
|
*/
|
||
|
public function get_rating( $score ) {
|
||
|
$hash = [
|
||
|
'unknown' => 0,
|
||
|
'bad' => 50,
|
||
|
'good' => 80,
|
||
|
'great' => 100,
|
||
|
];
|
||
|
|
||
|
foreach ( $hash as $key => $value ) {
|
||
|
if ( $score <= $value ) {
|
||
|
return $key;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return array_keys( $hash )[0];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the SEO score for given post.
|
||
|
*
|
||
|
* @param int $post_id Post ID.
|
||
|
* @return int
|
||
|
*/
|
||
|
public function get_score( $post_id = 0 ) {
|
||
|
global $post;
|
||
|
if ( empty( $post_id ) ) {
|
||
|
$post_id = $post->ID;
|
||
|
}
|
||
|
|
||
|
return get_post_meta( $post_id, 'rank_math_seo_score', true );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Show field check callback.
|
||
|
*
|
||
|
* @param CMB2_Field $field The current field.
|
||
|
* @return boolean
|
||
|
*/
|
||
|
public static function show_on( $field = [] ) {
|
||
|
// Early Bail if is sttic homepage.
|
||
|
if ( Admin_Helper::is_home_page() ) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$post_type = get_post_type();
|
||
|
return Helper::get_settings( 'general.frontend_seo_score' ) &&
|
||
|
in_array( $post_type, (array) Helper::get_settings( 'general.frontend_seo_score_post_types' ), true );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Shortcode output.
|
||
|
*
|
||
|
* @param array $atts Shortcode attributes.
|
||
|
*/
|
||
|
public function shortcode( $atts ) {
|
||
|
if ( ! $this->score_enabled() ) {
|
||
|
return '';
|
||
|
}
|
||
|
|
||
|
$atts = shortcode_atts(
|
||
|
[
|
||
|
'class' => 'as-shortcode',
|
||
|
],
|
||
|
$atts,
|
||
|
'rank-math-seo-score'
|
||
|
);
|
||
|
|
||
|
return $this->get_output( $atts );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Add CSS inline, once.
|
||
|
*/
|
||
|
public function add_css() {
|
||
|
if ( $this->css_added ) {
|
||
|
return;
|
||
|
}
|
||
|
?>
|
||
|
<style type="text/css">
|
||
|
.rank-math-seo-score{font-family:sans-serif;position:relative;display:inline-block;height:96px;width:96px;margin:20px 20px 30px;text-align:center;color:#fff;border:none;border-radius:50%;background:#eee;-webkit-box-shadow:1px 1px 1px #bbb;box-shadow:1px 1px 1px #bbb}.rank-math-seo-score.before-content{margin:0 0 30px 20px;float:right}.rank-math-seo-score.after-content{margin:20px 0 30px 20px}.rank-math-seo-score.as-shortcode{display:inline-block}.rank-math-seo-score .label{font-size:12px;position:absolute;top:100px;left:0;display:block;width:100%;color:#979ea5}.rank-math-seo-score .score{font-size:42px;font-weight:bold;line-height:42px;display:block}.rank-math-seo-score .outof{font-size:12px;font-weight:normal;line-height:12px;display:block;color:rgba(255,255,255,0.7)}.rank-math-seo-score .backlink{font-size:12px;position:absolute;top:-94px;left:-12px;display:block;visibility:hidden;width:120px;padding:8px 10px;-webkit-transition:.25s all ease;transition:.25s all ease;-webkit-transition-delay:.25s;transition-delay:.25s;opacity:0;color:#a8a8a8;border:none;border-radius:8px;background:#fff;-webkit-box-shadow:0 4px 14px rgba(60,60,90,0.2);box-shadow:0 4px 12px rgba(60,60,90,0.15)}.rank-math-seo-score .backlink:after{position:absolute;bottom:-8px;left:calc(50% - 7px);width:0;height:0;content:'';border-width:8px 7.5px 0 7.5px;border-style:solid;border-color:#fff transparent transparent transparent}.rank-math-seo-score:hover .backlink{top:-74px;visibility:visible;opacity:1}.rank-math-seo-score .poweredby{font-size:13px;color:#a8a8a8}.rank-math-seo-score .poweredby a{display:block;font-weight:normal;text-decoration:none;color:#6372b6;border:none}.rank-math-seo-score.unknown-seo{background:#eee;background:linear-gradient(135deg, #b9b9b9 0%, #989898 100%);-webkit-box-shadow:1px 1px 1px #bbb;box-shadow:1px 1px 1px #bbb}.rank-math-seo-score.bad-seo{background:#f8b0a2;background:linear-gradient(135deg, #f8b0a2 0%, #f1938c 100%);-webkit-box-shadow:1px 1px 1px #e48982;box-shadow:1px 1px 1px #e48982;filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#f8b0a2', endColorstr='#f1938c',GradientType=1 )}.rank-math-seo-score.good-seo{background:#fdd07a;background:linear-gradient(135deg, #fdd07a 0%, #fcbe6c 100%);-webkit-box-shadow:1px 1px 1px #efb463;box-shadow:1px 1px 1px #efb463;filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#fdd07a', endColorstr='#fcbe6c',GradientType=1 )}.rank-math-seo-score.great-seo{background:#99d484;background:linear-gradient(135deg, #99d484 0%, #83c97f 100%);-webkit-box-shadow:1px 1px 1px #5ba857;box-shadow:1px 1px 1px #5ba857;filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#99d484', endColorstr='#83c97f',GradientType=1 )}.rank-math-seo-score.template-circle .score{margin-top:22px !important}.rank-math-seo-score.template-square{height:80px;width:110px;border-radius:12px}.rank-math-seo-score.template-square .score{margin:10px 12px;text-align:left}.rank-math-seo-score.template-square .outof{display:inline-block;margin-left:-8px}.rank-math-seo-score.template-square .label{font-size:13px;top:52px;left:14px;text-align:left;color:rgba(255,255,255,0.8)}.rank-math-seo-score.template-square .backlink{left:-5px}.rank-math-seo-score.template-square.before-content{margin-bottom:20px}.rank-math-seo-score.template-square.after-content{margin-bottom:0}.theme-twentytwenty .rank-math-seo-score{width:96px !important}.theme-twentytwenty .rank-math-seo-score.template-square{width:110px !important}.theme-twentytwenty .rank-math-seo-score.before-content{margin:0 auto 30px auto;display:inherit;float:none}.theme-twentytwenty .rank-math-seo-score.template-circle .score,.theme-twentytwenty .rank-math-seo-score.template-square .score{transform:translateY(22px)}
|
||
|
</style>
|
||
|
<?php
|
||
|
$this->css_added = true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Settings field default callback.
|
||
|
*/
|
||
|
public static function post_types_field_default() {
|
||
|
$seo_score = Helper::get_settings( 'general.frontend_seo_score' );
|
||
|
$post_types = Helper::get_settings( 'general.frontend_seo_score_post_types' );
|
||
|
|
||
|
if ( 'on' === $seo_score && '' === $post_types ) {
|
||
|
return [];
|
||
|
}
|
||
|
|
||
|
return [ 'post' ];
|
||
|
}
|
||
|
}
|