class-yoast-dashboard-widget.php 5.39 KB
Newer Older
imac's avatar
imac committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
<?php
/**
 * @package WPSEO\Admin
 */

/**
 * Class to change or add WordPress dashboard widgets
 */
class Yoast_Dashboard_Widget {

	const CACHE_TRANSIENT_KEY = 'wpseo-dashboard-totals';

	/**
	 * @var WPSEO_Statistics
	 */
	protected $statistics;

	/**
	 * @param WPSEO_Statistics $statistics The statistics class to retrieve statistics from.
	 */
	public function __construct( WPSEO_Statistics $statistics = null ) {
		if ( null === $statistics ) {
			$statistics = new WPSEO_Statistics();
		}

		$this->statistics = $statistics;

		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_dashboard_stylesheet' ) );
		add_action( 'wp_insert_post', array( $this, 'clear_cache' ) );
		add_action( 'delete_post', array( $this, 'clear_cache' ) );

		if ( $this->show_widget() ) {
			add_action( 'wp_dashboard_setup', array( $this, 'add_dashboard_widget' ) );
		}
	}

	/**
	 * Adds dashboard widget to WordPress
	 */
	public function add_dashboard_widget() {
		add_filter( 'postbox_classes_dashboard_wpseo-dashboard-overview', array( $this, 'wpseo_dashboard_overview_class' ) );
		wp_add_dashboard_widget(
			'wpseo-dashboard-overview',
			/* translators: %s is the plugin name */
			sprintf( __( '%s Posts Overview', 'wordpress-seo' ), 'Yoast SEO' ),
			array( $this, 'display_dashboard_widget' )
		);
	}

	/**
	 * Adds CSS classes to the dashboard widget.
	 *
	 * @param array $classes An array of postbox CSS classes.
	 *
	 * @return array
	 */
	public function wpseo_dashboard_overview_class( $classes ) {
		$classes[] = 'yoast wpseo-dashboard-overview';
		return $classes;
	}

	/**
	 * Display the dashboard widget
	 */
	public function display_dashboard_widget() {
		$statistics = $this->statistic_items();

		$onpage_option = new WPSEO_OnPage_Option();
		$onpage        = false;
		if ( $onpage_option->is_enabled() ) {
			$onpage = array(
					'indexable' => $onpage_option->get_status(),
					'can_fetch' => $onpage_option->should_be_fetched(),
			);
		}

		include WPSEO_PATH . '/admin/views/dashboard-widget.php';
	}

	/**
	 * Enqueue's stylesheet for the dashboard if the current page is the dashboard
	 */
	public function enqueue_dashboard_stylesheet() {
		$current_screen = get_current_screen();

		if ( $current_screen instanceof WP_Screen && 'dashboard' === $current_screen->id ) {
			$asset_manager = new WPSEO_Admin_Asset_Manager();
			$asset_manager->enqueue_style( 'wp-dashboard' );
		}
	}

	/**
	 * Clears the dashboard widget items cache
	 */
	public function clear_cache() {
		delete_transient( self::CACHE_TRANSIENT_KEY );
	}

	/**
	 * An array representing items to be added to the At a Glance dashboard widget
	 *
	 * @return array
	 */
	private function statistic_items() {
		$transient = get_transient( self::CACHE_TRANSIENT_KEY );
		$user_id   = get_current_user_id();

		if ( isset( $transient[ $user_id ] ) ) {
			return $transient[ $user_id ];
		}

		return $this->set_statistic_items_for_this_user( $transient );
	}

	/**
	 * Set the cache for a specific user
	 *
	 * @param array|boolean $transient The current stored transient with the cached data.
	 *
	 * @return mixed
	 */
	private function set_statistic_items_for_this_user( $transient ) {
		if ( $transient === false ) {
			$transient = array();
		}

		$user_id               = get_current_user_id();
		$transient[ $user_id ] = array_filter( $this->get_seo_scores_with_post_count(), array( $this, 'filter_items' ) );

		set_transient( self::CACHE_TRANSIENT_KEY, $transient, DAY_IN_SECONDS );

		return $transient[ $user_id ];
	}

	/**
	 * Set the SEO scores belonging to their SEO score result
	 *
	 * @return array
	 */
	private function get_seo_scores_with_post_count() {
		$ranks = WPSEO_Rank::get_all_ranks();

		return array_map( array( $this, 'map_rank_to_widget' ), $ranks );
	}

	/**
	 * Converts a rank to data usable in the dashboard widget
	 *
	 * @param WPSEO_Rank $rank The rank to map.
	 *
	 * @return array
	 */
	private function map_rank_to_widget( WPSEO_Rank $rank ) {
		return array(
			'seo_rank'   => $rank->get_rank(),
			'title'      => $this->get_title_for_rank( $rank ),
			'class'      => 'wpseo-glance-' . $rank->get_css_class(),
			'icon_class' => $rank->get_css_class(),
			'count'      => $this->statistics->get_post_count( $rank ),
		);
	}

	/**
	 * Returns a dashboard widget label to use for a certain rank
	 *
	 * @param WPSEO_Rank $rank The rank to return a label for.
	 *
	 * @return string
	 */
	private function get_title_for_rank( WPSEO_Rank $rank ) {
		$labels = array(
			WPSEO_Rank::NO_FOCUS => __( 'Posts without focus keyword', 'wordpress-seo' ),
			WPSEO_Rank::BAD      => __( 'Posts with bad SEO score', 'wordpress-seo' ),
			WPSEO_Rank::OK       => __( 'Posts with OK SEO score', 'wordpress-seo' ),
			WPSEO_Rank::GOOD     => __( 'Posts with good SEO score', 'wordpress-seo' ),
			/* translators: %s expands to <span lang="en">noindex</span> */
			WPSEO_Rank::NO_INDEX => sprintf( __( 'Posts that are set to &#8220;%s&#8221;', 'wordpress-seo' ), '<span lang="en">noindex</span>' ),
		);

		return $labels[ $rank->get_rank() ];
	}

	/**
	 * Filter items if they have a count of zero
	 *
	 * @param array $item Data array.
	 *
	 * @return bool
	 */
	private function filter_items( $item ) {
		return 0 !== $item['count'];
	}

	/**
	 * Returns true when the dashboard widget should be shown.
	 *
	 * @return bool
	 */
	private function show_widget() {
		$analysis_seo = new WPSEO_Metabox_Analysis_SEO();

		return $analysis_seo->is_enabled() && current_user_can( 'edit_posts' );
	}
}