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.

382 lines
12 KiB
PHP

<?php
/**
* The admin post columns functionality.
*
* @since 0.9.0
* @package RankMath
* @subpackage RankMath\Admin
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Admin;
use RankMath\Helper;
use RankMath\Helpers\Str;
use RankMath\Helpers\Param;
use RankMath\Runner;
use RankMath\Traits\Hooker;
use RankMath\Admin\Database\Database;
defined( 'ABSPATH' ) || exit;
/**
* Post_Columns class.
*/
class Post_Columns implements Runner {
use Hooker;
/**
* SEO data.
*
* @var array
*/
private $data = [];
/**
* Register hooks.
*/
public function hooks() {
$this->action( 'admin_init', 'init' );
}
/**
* Intialize.
*/
public function init() {
if ( ! Helper::has_cap( 'onpage_general' ) ) {
return;
}
$this->register_post_columns();
$this->register_media_columns();
// Column Content.
$this->filter( 'rank_math_title', 'get_column_title', 5 );
$this->filter( 'rank_math_description', 'get_column_description', 5 );
$this->filter( 'rank_math_seo_details', 'get_column_seo_details', 5 );
}
/**
* Register post column hooks.
*/
private function register_post_columns() {
$post_types = Helper::get_allowed_post_types();
foreach ( $post_types as $post_type ) {
$this->filter( 'edd_download_columns', 'add_columns', 11 );
$this->filter( "manage_{$post_type}_posts_columns", 'add_columns', 11 );
$this->action( "manage_{$post_type}_posts_custom_column", 'columns_contents', 11, 2 );
$this->filter( "manage_edit-{$post_type}_sortable_columns", 'sortable_columns', 11 );
// Also make them hidden by default.
$user_id = get_current_user_id();
$columns_hidden = (array) get_user_meta( $user_id, "manageedit-{$post_type}columnshidden", true );
$maybe_hidden = get_user_meta( $user_id, "manageedit-{$post_type}columnshidden_default", true );
// Continue if default is already set.
if ( $maybe_hidden ) {
continue;
}
// Set it to hidden by default.
$columns_hidden = array_unique( array_merge( $columns_hidden, [ 'rank_math_title', 'rank_math_description' ] ) );
update_user_meta( $user_id, "manageedit-{$post_type}columnshidden", $columns_hidden );
update_user_meta( $user_id, "manageedit-{$post_type}columnshidden_default", '1' );
}
}
/**
* Register media column hooks.
*/
private function register_media_columns() {
if ( ! Helper::get_settings( 'titles.pt_attachment_bulk_editing' ) ) {
return;
}
$this->filter( 'manage_media_columns', 'add_media_columns', 11 );
$this->action( 'manage_media_custom_column', 'media_contents', 11, 2 );
}
/**
* Add new columns for SEO title, description and focus keywords.
*
* @param array $columns Array of column names.
*
* @return array
*/
public function add_columns( $columns ) {
global $post_type;
$current_pt = $post_type;
if ( ! $post_type && 'inline-save' === Param::post( 'action' ) ) {
$post_id = Param::post( 'post_ID', 0, FILTER_VALIDATE_INT );
$current_pt = get_post_type( $post_id );
}
$columns['rank_math_seo_details'] = esc_html__( 'SEO Details', 'rank-math' );
if ( Helper::get_settings( 'titles.pt_' . $current_pt . '_bulk_editing', true ) ) {
$columns['rank_math_title'] = esc_html__( 'SEO Title', 'rank-math' );
$columns['rank_math_description'] = esc_html__( 'SEO Desc', 'rank-math' );
}
return $columns;
}
/**
* Make the SEO Score column sortable.
*
* @param array $columns Array of column names.
*
* @return array
*/
public function sortable_columns( $columns ) {
$columns['rank_math_seo_details'] = 'rank_math_seo_score';
return $columns;
}
/**
* Add new columns for Media Alt & Title.
*
* @param array $columns Array of column names.
*
* @return array
*/
public function add_media_columns( $columns ) {
$columns['rank_math_image_title'] = esc_html__( 'Title', 'rank-math' );
$columns['rank_math_image_alt'] = esc_html__( 'Alternative Text', 'rank-math' );
return $columns;
}
/**
* Add content for custom column.
*
* @param string $column_name The name of the column to display.
* @param int $post_id The current post ID.
*/
public function columns_contents( $column_name, $post_id ) {
if ( Str::starts_with( 'rank_math', $column_name ) ) {
do_action( $column_name, $post_id );
}
}
/**
* Add content for title column.
*
* @param int $post_id The current post ID.
*/
public function get_column_title( $post_id ) {
$title = ! empty( $this->data[ $post_id ]['rank_math_title'] ) ? $this->data[ $post_id ]['rank_math_title'] : '';
if ( ! $title ) {
$post_type = get_post_type( $post_id );
$title = Helper::get_settings( "titles.pt_{$post_type}_title" );
}
?>
<span class="rank-math-column-display"><?php echo esc_html( $title ); ?></span>
<textarea class="rank-math-column-value" data-field="title" tabindex="11"><?php echo esc_attr( $title ); ?></textarea>
<div class="rank-math-column-edit">
<a href="#" class="rank-math-column-save"><?php esc_html_e( 'Save', 'rank-math' ); ?></a>
<a href="#" class="button-link-delete rank-math-column-cancel"><?php esc_html_e( 'Cancel', 'rank-math' ); ?></a>
</div>
<?php
}
/**
* Add content for title column.
*
* @param int $post_id The current post ID.
*/
public function get_column_description( $post_id ) {
$description = ! empty( $this->data[ $post_id ]['rank_math_description'] ) ? $this->data[ $post_id ]['rank_math_description'] : '';
if ( ! $description ) {
$post_type = get_post_type( $post_id );
$description = has_excerpt( $post_id ) ? '%excerpt%' : Helper::get_settings( "titles.pt_{$post_type}_description" );
}
?>
<span class="rank-math-column-display"><?php echo esc_html( $description ); ?></span>
<textarea class="rank-math-column-value" data-field="description" tabindex="11"><?php echo esc_attr( $description ); ?></textarea>
<div class="rank-math-column-edit">
<a href="#" class="rank-math-column-save"><?php esc_html_e( 'Save', 'rank-math' ); ?></a>
<a href="#" class="button-link-delete rank-math-column-cancel"><?php esc_html_e( 'Cancel', 'rank-math' ); ?></a>
</div>
<?php
}
/**
* Add content for title column.
*
* @param int $post_id The current post ID.
*/
public function get_column_seo_details( $post_id ) {
if ( empty( $this->data ) ) {
$this->get_seo_data();
}
$data = isset( $this->data[ $post_id ] ) ? $this->data[ $post_id ] : [];
if ( ! self::is_post_indexable( $post_id ) ) {
echo '<span class="rank-math-column-display seo-score no-score "><strong>N/A</strong></span>';
echo '<strong>' . esc_html__( 'No Index', 'rank-math' ) . '</strong>';
$this->do_action( 'post/column/seo_details', $post_id, $data, $this->data );
return;
}
$keyword = ! empty( $data['rank_math_focus_keyword'] ) ? $data['rank_math_focus_keyword'] : '';
$keyword = explode( ',', $keyword )[0];
$is_pillar = ! empty( $data['rank_math_pillar_content'] ) && 'on' === $data['rank_math_pillar_content'] ? true : false;
$score = empty( $keyword ) ? false : $this->get_seo_score( $data );
$class = ! $score ? 'no-score' : $this->get_seo_score_class( $score );
$score = $score ? $score . ' / 100' : 'N/A';
?>
<span class="rank-math-column-display seo-score <?php echo esc_attr( $class ); ?> <?php echo ! $score ? 'disabled' : ''; ?>">
<strong><?php echo esc_html( $score ); ?></strong>
<?php if ( $is_pillar ) { ?>
<img class="is-pillar" src="<?php echo esc_url( rank_math()->plugin_url() . 'assets/admin/img/pillar.svg' ); ?>" alt="<?php esc_html_e( 'Is Pillar', 'rank-math' ); ?>" title="<?php esc_html_e( 'Is Pillar', 'rank-math' ); ?>" width="25" />
<?php } ?>
</span>
<label><?php esc_html_e( 'Focus Keyword', 'rank-math' ); ?>:</label>
<span class="rank-math-column-display">
<strong title="Focus Keyword"><?php esc_html_e( 'Keyword', 'rank-math' ); ?>:</strong>
<span><?php echo $keyword ? esc_html( $keyword ) : esc_html__( 'Not Set', 'rank-math' ); ?></span>
</span>
<input class="rank-math-column-value" data-field="focus_keyword" tabindex="11" value="<?php echo esc_attr( $keyword ); ?>" />
<?php $this->do_action( 'post/column/seo_details', $post_id, $data, $this->data ); ?>
<div class="rank-math-column-edit">
<a href="#" class="rank-math-column-save"><?php esc_html_e( 'Save', 'rank-math' ); ?></a>
<a href="#" class="button-link-delete rank-math-column-cancel"><?php esc_html_e( 'Cancel', 'rank-math' ); ?></a>
</div>
<?php
}
/**
* Add content for custom media column.
*
* @param string $column_name The name of the column to display.
* @param int $post_id The current post ID.
*/
public function media_contents( $column_name, $post_id ) {
if ( 'rank_math_image_title' === $column_name ) {
$title = get_the_title( $post_id );
?>
<span class="rank-math-column-display"><?php echo esc_html( $title ); ?></span>
<input class="rank-math-column-value" data-field="image_title" tabindex="11" value="<?php echo esc_attr( $title ); ?>" />
<div class="rank-math-column-edit">
<a href="#" class="rank-math-column-save"><?php esc_html_e( 'Save', 'rank-math' ); ?></a>
<a href="#" class="button-link-delete rank-math-column-cancel"><?php esc_html_e( 'Cancel', 'rank-math' ); ?></a>
</div>
<?php
return;
}
if ( 'rank_math_image_alt' === $column_name ) {
$alt = get_post_meta( $post_id, '_wp_attachment_image_alt', true );
?>
<span class="rank-math-column-display"><?php echo esc_html( $alt ); ?></span>
<input class="rank-math-column-value" data-field="image_alt" tabindex="11" value="<?php echo esc_attr( $alt ); ?>" />
<div class="rank-math-column-edit">
<a href="#" class="rank-math-column-save"><?php esc_html_e( 'Save', 'rank-math' ); ?></a>
<a href="#" class="button-link-delete rank-math-column-cancel"><?php esc_html_e( 'Cancel', 'rank-math' ); ?></a>
</div>
<?php
return;
}
}
/**
* Get SEO data.
*/
private function get_seo_data() {
global $wp_query;
$post_ids = [];
if ( $wp_query->posts ) {
$post_ids = array_filter(
array_map(
function( $post ) {
return isset( $post->ID ) ? $post->ID : '';
},
$wp_query->posts
)
);
}
$post_id = (int) Param::post( 'post_ID' );
if ( $post_id ) {
$post_ids[] = $post_id;
}
if ( empty( $post_ids ) ) {
return false;
}
$results = Database::table( 'postmeta' )->select( [ 'post_id', 'meta_key', 'meta_value' ] )->whereIn( 'post_id', $post_ids )->whereLike( 'meta_key', 'rank_math' )->get( ARRAY_A );
if ( empty( $results ) ) {
return false;
}
foreach ( $results as $result ) {
$this->data[ $result['post_id'] ][ $result['meta_key'] ] = $result['meta_value'];
}
}
/**
* Get SEO score.
*
* @param array $data SEO data of current post.
*
* @return string
*/
private function get_seo_score( $data ) {
if ( ! isset( $data['rank_math_seo_score'] ) ) {
return false;
}
if ( ! Helper::is_score_enabled() ) {
return false;
}
return $data['rank_math_seo_score'] ? $data['rank_math_seo_score'] : 0;
}
/**
* Get SEO score rating string: great/good/bad.
*
* @param int $score Score.
*
* @return string
*/
private function get_seo_score_class( $score ) {
if ( $score > 80 ) {
return 'great';
}
if ( $score > 50 && $score < 81 ) {
return 'good';
}
return 'bad';
}
/**
* Check post indexable status.
*
* @param int $post_id Post ID.
*/
public static function is_post_indexable( $post_id ) {
$robots = Param::post( 'rank_math_robots', false, FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
$robots = apply_filters( 'rank_math/admin/robots', $robots, $post_id );
if ( ! empty( $robots ) ) {
return in_array( 'index', $robots, true ) ? true : false;
}
return Helper::is_post_indexable( $post_id );
}
}