Completed
Push — develop ( 42c7de...3b0479 )
by Gary
01:09
created

class-gamajo-dashboard-glancer.php (1 issue)

Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Gamajo Dashboard Glancer
4
 *
5
 * @package   Gamajo\DashboardGlancer
6
 * @author    Gary Jones
7
 * @link      https://github.com/gamajo/dashboard-glancer
8
 * @copyright 2013 Gary Jones, Gamajo
9
 * @license   GPL-2.0-or-later
10
 * @version   1.0.4
11
 */
12
13
/**
14
 * Easily add items to the At a Glance Dashboard widget in WordPress 3.8+.
15
 *
16
 * @package Gamajo\DashboardGlancer
17
 * @author  Gary Jones
18
 */
19
class Gamajo_Dashboard_Glancer {
20
	/**
21
	 * Hold all of the items to show.
22
	 *
23
	 * @since 1.0.0
24
	 *
25
	 * @var array
26
	 */
27
	protected $items;
28
29
	/**
30
	 * Automatically show any registered items.
31
	 *
32
	 * With this, there's no need to explicitly call show() during the
33
	 * `dashboard_glance_items` hook, and items can be registered at any time
34
	 * before `dashboard_glance_items` priority 20 (including on earlier hooks).
35
	 *
36
	 * @since 1.0.0
37
	 */
38
	public function __construct() {
39
		add_action( 'dashboard_glance_items', array( $this, 'show' ), 20 );
40
		add_action( 'admin_enqueue_scripts', array( $this, 'dashboard_css' ) );
41
	}
42
43
	/**
44
	 * Register one or more post type items to be shown on the dashboard widget.
45
	 *
46
	 * @since 1.0.0
47
	 *
48
	 * @param array|string $post_types Post type name, or array of post type names.
49
	 * @param array|string $statuses   Optional. Post status or array of
50
	 *                                 different post type statuses. Default is
51
	 *                                 `publish`.
52
	 * @return null Return early if action hook has already passed, or no valid
53
	 *              post types were given.
54
	 */
55
	public function add( $post_types, $statuses = 'publish' ) {
56
		// If relevant output action hook has already passed, then no point in proceeding.
57
		if ( did_action( 'dashboard_glance_items' ) ) {
58
			_doing_it_wrong( __CLASS__, 'Trying to add At a Glance items to dashboard widget afterhook already fired', '1.0.0' );
59
60
			return;
61
		}
62
63
		$post_types = $this->unset_invalid_post_types( (array) $post_types );
64
65
		// If all given post types were invalid, bail now.
66
		if ( ! $post_types ) {
67
			return;
68
		}
69
70
		// Register each combination of given post type and status.
71
		foreach ( $post_types as $post_type ) {
72
			foreach ( (array) $statuses as $status ) {
73
				$this->items[] = array(
74
					'type'   => $post_type,
75
					'status' => $status, // No checks yet to see if status is valid.
76
				);
77
			}
78
		}
79
	}
80
81
	/**
82
	 * Show the items on the dashboard widget.
83
	 *
84
	 * @since 1.0.0
85
	 */
86
	public function show() {
87
		foreach ( $this->items as $item ) {
88
			echo wp_kses_post( $this->get_single_item( $item ) );
89
		}
90
		// Reset items, so items aren't shown again if show() is re-called.
91
		unset( $this->items );
92
	}
93
94
	/**
95
	 * Check one or more post types to see if they are valid.
96
	 *
97
	 * @since 1.0.0
98
	 *
99
	 * @param array $post_types Each of the post types to check.
100
	 * @return array List of the given post types that are valid.
101
	 */
102
	protected function unset_invalid_post_types( array $post_types ) {
103
		foreach ( $post_types as $index => $post_type ) {
104
			$post_type_object = get_post_type_object( $post_type );
105
			if ( is_null( $post_type_object ) ) {
106
				unset( $post_types[ $index ] );
107
			}
108
		}
109
110
		return $post_types;
111
	}
112
113
	/**
114
	 * Build and return the data and markup for a single item.
115
	 *
116
	 * If the item count is zero, return an empty string, to avoid visual clutter.
117
	 *
118
	 * @since 1.0.0
119
	 *
120
	 * @param array $item Registered item.
121
	 * @return string Markup, or empty string if item count is zero.
122
	 */
123 View Code Duplication
	protected function get_single_item( array $item ) {
124
		$num_posts = wp_count_posts( $item['type'] );
125
		$count     = (int) $num_posts->{$item['status']};
126
127
		if ( ! $count ) {
128
			return '';
129
		}
130
131
		$href = $this->get_link_url( $item );
132
		$text = number_format_i18n( $count ) . ' ' . $this->get_label( $item, $count );
133
		$text = $this->maybe_link( $text, $href );
134
135
		return $this->get_markup( $text, $item['type'] );
136
	}
137
138
	/**
139
	 * Get the singular or plural label for an item.
140
	 *
141
	 * @since 1.0.0
142
	 *
143
	 * @param array $item  Registered item.
144
	 * @param int   $count Number of items present in WP.
145
	 * @return string
146
	 */
147
	protected function get_label( array $item, $count ) {
148
		$post_type_object = get_post_type_object( $item['type'] );
149
		$labels           = $post_type_object->labels;
150
		$label            = 1 === $count ? $labels->singular_name : $labels->name;
151
152
		// Append status for non-publish statuses for disambiguation.
153
		if ( 'publish' !== $item['status'] ) {
154
			$label .= ' (' . $item['status'] . ')';
155
		}
156
157
		return $label;
158
	}
159
160
	/**
161
	 * Build the URL that linked items use.
162
	 *
163
	 * @since 1.0.0
164
	 *
165
	 * @param array $item Registered item.
166
	 * @return string Admin URL to view the entries of the given post type with the given status
167
	 */
168
	public function get_link_url( array $item ) {
169
		return 'edit.php?post_status=' . $item['status'] . '&amp;post_type=' . $item['type'];
170
	}
171
172
	/**
173
	 * Wrap a glance item in a link, if the current user can edit posts.
174
	 *
175
	 * @since 1.0.0
176
	 *
177
	 * @param string $text Text to potentially wrap in a link.
178
	 * @param string $href Link target.
179
	 * @return string Text wrapped in a link if current user can edit posts, or original text otherwise.
180
	 */
181
	protected function maybe_link( $text, $href ) {
182
		if ( current_user_can( 'edit_posts' ) ) {
183
			return '<a href="' . esc_url( $href ) . '">' . esc_html( $text ) . '</a>';
184
		}
185
186
		return '<span>' . esc_html( $text ) . '</span>';
187
	}
188
189
	/**
190
	 * Wrap number and text within list item markup.
191
	 *
192
	 * The extra work for populating classes is to provide dashicons support.
193
	 *
194
	 * @since 1.0.0
195
	 *
196
	 * @param string $text      Text to display. May be wrapped in a link.
197
	 * @param string $post_type Post type.
198
	 * @return string Markup for list item.
199
	 */
200
	protected function get_markup( $text, $post_type ) {
201
		$class = '';
0 ignored issues
show
$class is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
202
		$classes[] = $post_type . '-count';
203
		$post_type_object = get_post_type_object( $post_type );
204
		$menu_icon = isset( $post_type_object->menu_icon ) ? $post_type_object->menu_icon : null;
205
206
		if ( 0 === strpos( $menu_icon, 'dashicons-' ) ) {
207
			$classes[] = 'dashicons-before';
208
			$classes[] = $menu_icon;
209
		}
210
211
		$class = join( ' ', sanitize_html_class( $classes ) );
212
213
		return '<li class="' . esc_attr( $class ) . '">' . wp_kses_post( $text ) . '</li>' . "\n";
214
	}
215
216
	/**
217
	 * Add post types icon styling to Dashboard page.
218
	 *
219
	 * To override the overly-specific core styles, we apply styles to ignore
220
	 * the default circle, and with the classes added to the list item (not
221
	 * anchor), get dashicons showing there instead.
222
	 *
223
	 * @since 1.1.0
224
	 *
225
	 * @return null Return early if style already added, or the Dashboard page.
226
	 */
227
	public function dashboard_css() {
228
		static $added_style;
229
230
		if ( $added_style ) {
231
			return;
232
		}
233
234
		$screen = get_current_screen();
235
236
		if ( ! in_array( $screen->base, array( 'dashboard' ), true ) ) {
237
			return;
238
		}
239
240
		// Remove default circle, and style dashicons we add via classes.
241
		echo '<style type="text/css">#dashboard_right_now li.dashicons-before a:before, #dashboard_right_now li.dashicons span:before {content: none;}#dashboard_right_now li.dashicons-before:before {color: #82878c;margin: 0 5px 0 0;}</style>';
242
243
		$added_style = true;
244
	}
245
}
246