Completed
Push — master ( 4e24b6...14289c )
by Jamie
03:44
created

FrmListHelper::pagination()   F

Complexity

Conditions 15
Paths 6145

Size

Total Lines 110
Code Lines 74

Duplication

Lines 34
Ratio 30.91 %
Metric Value
dl 34
loc 110
rs 2
cc 15
eloc 74
nc 6145
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
if ( ! defined('ABSPATH') ) {
3
	die( 'You are not allowed to call this page directly.' );
4
}
5
6
class FrmListHelper {
7
	/**
8
	 * The current list of items
9
	 *
10
	 * @since 2.0.18
11
	 * @var array
12
	 * @access public
13
	 */
14
	public $items;
15
16
	/**
17
	 * Various information about the current table
18
	 *
19
	 * @since 2.0.18
20
	 * @var array
21
	 * @access protected
22
	 */
23
	protected $_args;
24
25
	/**
26
	 * Various information needed for displaying the pagination
27
	 *
28
	 * @since 2.0.18
29
	 * @var array
30
	 */
31
	protected $_pagination_args = array();
32
33
	/**
34
	 * The current screen
35
	 *
36
	 * @since 2.0.18
37
	 * @var object
38
	 * @access protected
39
	 */
40
	protected $screen;
41
42
	/**
43
	 * Cached bulk actions
44
	 *
45
	 * @since 2.0.18
46
	 * @var array
47
	 * @access private
48
	 */
49
	private $_actions;
50
51
	/**
52
	 * Cached pagination output
53
	 *
54
	 * @since 2.0.18
55
	 * @var string
56
	 * @access private
57
	 */
58
	private $_pagination;
59
60
	/**
61
	 * The view switcher modes.
62
	 *
63
	 * @since 2.0.18
64
	 * @var array
65
	 * @access protected
66
	 */
67
	protected $modes = array();
68
69
	/**
70
	*
71
	* @var array
72
	*/
73
    protected $params;
74
75
	/**
76
	 * Stores the value returned by ->get_column_info()
77
	 *
78
	 * @var array
79
	 */
80
	protected $_column_headers;
81
82
	protected $compat_fields = array( '_args', '_pagination_args', 'screen', '_actions', '_pagination' );
83
84
	protected $compat_methods = array( 'set_pagination_args', 'get_views', 'get_bulk_actions', 'bulk_actions',
0 ignored issues
show
introduced by
The first value in a multi-value array must be on a new line
Loading history...
85
		'row_actions', 'months_dropdown', 'view_switcher', 'comments_bubble', 'get_items_per_page', 'pagination',
86
		'get_sortable_columns', 'get_column_info', 'get_table_classes', 'display_tablenav', 'extra_tablenav',
87
		'single_row_columns' );
0 ignored issues
show
introduced by
Comma required after last value in array declaration
Loading history...
88
89
	/**
90
	* Construct the table object
91
	*/
92
	public function __construct( $args ) {
93
	    $args = wp_parse_args( $args, array(
94
			'params' => array(),
95
			'plural' => '',
96
			'singular' => '',
97
			'ajax' => false,
98
			'screen' => null,
99
		) );
100
101
		$this->params = $args['params'];
102
103
		$this->screen = convert_to_screen( $args['screen'] );
104
105
		add_filter( "manage_{$this->screen->id}_columns", array( $this, 'get_columns' ), 0 );
106
107
		if ( !$args['plural'] )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
introduced by
Expected 1 space after "!"; 0 found
Loading history...
108
			$args['plural'] = $this->screen->base;
109
110
		$args['plural'] = sanitize_key( $args['plural'] );
111
		$args['singular'] = sanitize_key( $args['singular'] );
112
113
		$this->_args = $args;
114
115
		if ( $args['ajax'] ) {
116
			// wp_enqueue_script( 'list-table' );
117
			add_action( 'admin_footer', array( $this, '_js_vars' ) );
118
		}
119
120
		if ( empty( $this->modes ) ) {
121
			$this->modes = array(
122
				'list'    => __( 'List View' ),
123
				'excerpt' => __( 'Excerpt View' )
124
			);
125
		}
126
	}
127
128
	public function ajax_user_can() {
129
		return current_user_can( 'administrator' );
130
	}
131
132
	public function get_columns() {
133
		return array();
134
	}
135
136
	public function display_rows() {
137
		$style = '';
138
		foreach ( $this->items as $item ) {
139
			$style = ( ' class="alternate"' == $style ) ? '' : ' class="alternate"';
140
			echo "\n\t", $this->single_row( $item, $style );
0 ignored issues
show
Unused Code introduced by
The call to FrmListHelper::single_row() has too many arguments starting with $style.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
141
		}
142
	}
143
144
	/**
145
	 * Make private properties readable for backwards compatibility.
146
	 *
147
	 * @since 4.0.0
148
	 * @access public
149
	 *
150
	 * @param string $name Property to get.
151
	 * @return mixed Property.
152
	 */
153
	public function __get( $name ) {
154
		if ( in_array( $name, $this->compat_fields ) ) {
155
			return $this->$name;
156
		}
157
	}
158
159
	/**
160
	 * Make private properties settable for backwards compatibility.
161
	 *
162
	 * @since 4.0.0
163
	 * @access public
164
	 *
165
	 * @param string $name  Property to check if set.
166
	 * @param mixed  $value Property value.
167
	 * @return mixed Newly-set property.
168
	 */
169
	public function __set( $name, $value ) {
170
		if ( in_array( $name, $this->compat_fields ) ) {
171
			return $this->$name = $value;
172
		}
173
	}
174
175
	/**
176
	 * Make private properties checkable for backwards compatibility.
177
	 *
178
	 * @since 4.0.0
179
	 * @access public
180
	 *
181
	 * @param string $name Property to check if set.
182
	 * @return bool Whether the property is set.
183
	 */
184
	public function __isset( $name ) {
185
		if ( in_array( $name, $this->compat_fields ) ) {
186
			return isset( $this->$name );
187
		}
188
	}
189
190
	/**
191
	 * Make private properties un-settable for backwards compatibility.
192
	 *
193
	 * @since 4.0.0
194
	 * @access public
195
	 *
196
	 * @param string $name Property to unset.
197
	 */
198
	public function __unset( $name ) {
199
		if ( in_array( $name, $this->compat_fields ) ) {
200
			unset( $this->$name );
201
		}
202
	}
203
204
	/**
205
	 * Make private/protected methods readable for backwards compatibility.
206
	 *
207
	 * @since 4.0.0
208
	 * @access public
209
	 *
210
	 * @param callable $name      Method to call.
211
	 * @param array    $arguments Arguments to pass when calling.
212
	 * @return mixed|bool Return value of the callback, false otherwise.
213
	 */
214
	public function __call( $name, $arguments ) {
215
		if ( in_array( $name, $this->compat_methods ) ) {
216
			return call_user_func_array( array( $this, $name ), $arguments );
217
		}
218
		return false;
219
	}
220
221
	/**
222
	 * Prepares the list of items for displaying.
223
	 * @uses FrmListHelper::set_pagination_args()
224
	 *
225
	 * @since 2.0.18
226
	 * @access public
227
	 * @abstract
228
	 */
229
	public function prepare_items() {
230
		die( 'function FrmListHelper::prepare_items() must be over-ridden in a sub-class.' );
231
	}
232
233
	/**
234
	 * An internal method that sets all the necessary pagination arguments
235
	 *
236
	 * @param array $args An associative array with information about the pagination
237
	 * @access protected
238
	 *
239
	 * @param array|string $args
240
	 */
241
	protected function set_pagination_args( $args ) {
242
		$args = wp_parse_args( $args, array(
243
			'total_items' => 0,
244
			'total_pages' => 0,
245
			'per_page' => 0,
246
		) );
247
248
		if ( !$args['total_pages'] && $args['per_page'] > 0 )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
introduced by
Expected 1 space after "!"; 0 found
Loading history...
249
			$args['total_pages'] = ceil( $args['total_items'] / $args['per_page'] );
250
251
		// Redirect if page number is invalid and headers are not already sent.
252
		if ( ! headers_sent() && ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) && $args['total_pages'] > 0 && $this->get_pagenum() > $args['total_pages'] ) {
253
			wp_redirect( add_query_arg( 'paged', $args['total_pages'] ) );
254
			exit;
255
		}
256
257
		$this->_pagination_args = $args;
258
	}
259
260
	/**
261
	 * Access the pagination args.
262
	 *
263
	 * @since 2.0.18
264
	 * @access public
265
	 *
266
	 * @param string $key Pagination argument to retrieve. Common values include 'total_items',
267
	 *                    'total_pages', 'per_page', or 'infinite_scroll'.
268
	 * @return int Number of items that correspond to the given pagination argument.
269
	 */
270
	public function get_pagination_arg( $key ) {
271
		if ( 'page' == $key )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
272
			return $this->get_pagenum();
273
274
		if ( isset( $this->_pagination_args[$key] ) )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
275
			return $this->_pagination_args[$key];
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
276
	}
277
278
	/**
279
	 * Whether the table has items to display or not
280
	 *
281
	 * @since 2.0.18
282
	 * @access public
283
	 *
284
	 * @return bool
285
	 */
286
	public function has_items() {
287
		return !empty( $this->items );
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
288
	}
289
290
	/**
291
	 * Message to be displayed when there are no items
292
	 *
293
	 * @since 2.0.18
294
	 * @access public
295
	 */
296
	public function no_items() {
297
		_e( 'No items found.' );
298
	}
299
300
	/**
301
	 * Display the search box.
302
	 *
303
	 * @since 2.0.18
304
	 * @access public
305
	 *
306
	 * @param string $text The search button text
307
	 * @param string $input_id The search input id
308
	 */
309
	public function search_box( $text, $input_id ) {
310
		if ( empty( $_REQUEST['s'] ) && !$this->has_items() )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
introduced by
Expected 1 space after "!"; 0 found
Loading history...
311
			return;
312
313
		$input_id = $input_id . '-search-input';
314
315 View Code Duplication
		if ( ! empty( $_REQUEST['orderby'] ) )
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
316
			echo '<input type="hidden" name="orderby" value="' . esc_attr( $_REQUEST['orderby'] ) . '" />';
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
317 View Code Duplication
		if ( ! empty( $_REQUEST['order'] ) )
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
318
			echo '<input type="hidden" name="order" value="' . esc_attr( $_REQUEST['order'] ) . '" />';
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
319 View Code Duplication
		if ( ! empty( $_REQUEST['post_mime_type'] ) )
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
320
			echo '<input type="hidden" name="post_mime_type" value="' . esc_attr( $_REQUEST['post_mime_type'] ) . '" />';
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
321 View Code Duplication
		if ( ! empty( $_REQUEST['detached'] ) )
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
322
			echo '<input type="hidden" name="detached" value="' . esc_attr( $_REQUEST['detached'] ) . '" />';
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
323
?>
324
<p class="search-box">
325
	<label class="screen-reader-text" for="<?php echo $input_id ?>"><?php echo $text; ?>:</label>
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$input_id'
Loading history...
introduced by
Expected next thing to be a escaping function, not '$text'
Loading history...
326
	<input type="search" id="<?php echo $input_id ?>" name="s" value="<?php _admin_search_query(); ?>" />
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$input_id'
Loading history...
327
	<?php submit_button( $text, 'button', '', false, array('id' => 'search-submit') ); ?>
0 ignored issues
show
introduced by
No space after opening parenthesis of array is bad style
Loading history...
introduced by
No space before closing parenthesis of array is bad style
Loading history...
328
</p>
329
<?php
330
	}
331
332
	/**
333
	 * Get an associative array ( id => link ) with the list
334
	 * of views available on this table.
335
	 *
336
	 * @since 2.0.18
337
	 * @access protected
338
	 *
339
	 * @return array
340
	 */
341
	protected function get_views() {
342
		return array();
343
	}
344
345
	/**
346
	 * Display the list of views available on this table.
347
	 *
348
	 * @since 2.0.18
349
	 * @access public
350
	 */
351
	public function views() {
352
		$views = $this->get_views();
353
		/**
354
		 * Filter the list of available list table views.
355
		 *
356
		 * The dynamic portion of the hook name, `$this->screen->id`, refers
357
		 * to the ID of the current screen, usually a string.
358
		 *
359
		 * @since 3.5.0
360
		 *
361
		 * @param array $views An array of available list table views.
362
		 */
363
		$views = apply_filters( "views_{$this->screen->id}", $views );
364
365
		if ( empty( $views ) )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
366
			return;
367
368
		echo "<ul class='subsubsub'>\n";
369
		foreach ( $views as $class => $view ) {
370
			$views[ $class ] = "\t<li class='$class'>$view";
371
		}
372
		echo implode( " |</li>\n", $views ) . "</li>\n";
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'implode'
Loading history...
373
		echo "</ul>";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal </ul> does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
374
	}
375
376
	/**
377
	 * Get an associative array ( option_name => option_title ) with the list
378
	 * of bulk actions available on this table.
379
	 *
380
	 * @since 2.0.18
381
	 * @access protected
382
	 *
383
	 * @return array
384
	 */
385
	protected function get_bulk_actions() {
386
		return array();
387
	}
388
389
	/**
390
	 * Display the bulk actions dropdown.
391
	 *
392
	 * @since 2.0.18
393
	 * @access protected
394
	 *
395
	 * @param string $which The location of the bulk actions: 'top' or 'bottom'.
396
	 *                      This is designated as optional for backwards-compatibility.
397
	 */
398
	protected function bulk_actions( $which = '' ) {
399
		if ( is_null( $this->_actions ) ) {
400
			$no_new_actions = $this->_actions = $this->get_bulk_actions();
401
			/**
402
			 * Filter the list table Bulk Actions drop-down.
403
			 *
404
			 * The dynamic portion of the hook name, `$this->screen->id`, refers
405
			 * to the ID of the current screen, usually a string.
406
			 *
407
			 * This filter can currently only be used to remove bulk actions.
408
			 *
409
			 * @since 3.5.0
410
			 *
411
			 * @param array $actions An array of the available bulk actions.
412
			 */
413
			$this->_actions = apply_filters( "bulk_actions-{$this->screen->id}", $this->_actions );
414
			$this->_actions = array_intersect_assoc( $this->_actions, $no_new_actions );
415
			$two = '';
416
		} else {
417
			$two = '2';
418
		}
419
420
		if ( empty( $this->_actions ) )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
421
			return;
422
423
		echo "<label for='bulk-action-selector-" . esc_attr( $which ) . "' class='screen-reader-text'>" . __( 'Select bulk action' ) . "</label>";
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw '__'
Loading history...
Coding Style Comprehensibility introduced by
The string literal </label> does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
424
		echo "<select name='action$two' id='bulk-action-selector-" . esc_attr( $which ) . "'>\n";
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '"<select name='action$two' id='bulk-action-selector-"'
Loading history...
425
		echo "<option value='-1' selected='selected'>" . __( 'Bulk Actions' ) . "</option>\n";
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw '__'
Loading history...
426
427
		foreach ( $this->_actions as $name => $title ) {
428
			$class = 'edit' == $name ? ' class="hide-if-no-js"' : '';
429
430
			echo "\t<option value='$name'$class>$title</option>\n";
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '"\t<option value='$name'$class>$title</option>\n"'
Loading history...
431
		}
432
433
		echo "</select>\n";
434
435
		submit_button( __( 'Apply' ), 'action', '', false, array( 'id' => "doaction$two" ) );
436
		echo "\n";
437
	}
438
439
	/**
440
	 * Get the current action selected from the bulk actions dropdown.
441
	 *
442
	 * @since 2.0.18
443
	 * @access public
444
	 *
445
	 * @return string|false The action name or False if no action was selected
446
	 */
447
	public function current_action() {
448
		if ( isset( $_REQUEST['filter_action'] ) && ! empty( $_REQUEST['filter_action'] ) )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
449
			return false;
450
451 View Code Duplication
		if ( isset( $_REQUEST['action'] ) && -1 != $_REQUEST['action'] )
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
452
			return $_REQUEST['action'];
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
453
454 View Code Duplication
		if ( isset( $_REQUEST['action2'] ) && -1 != $_REQUEST['action2'] )
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
455
			return $_REQUEST['action2'];
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_REQUEST
Loading history...
456
457
		return false;
458
	}
459
460
	/**
461
	 * Generate row actions div
462
	 *
463
	 * @since 2.0.18
464
	 * @access protected
465
	 *
466
	 * @param array $actions The list of actions
467
	 * @param bool $always_visible Whether the actions should be always visible
468
	 * @return string
469
	 */
470
	protected function row_actions( $actions, $always_visible = false ) {
471
		$action_count = count( $actions );
472
		$i = 0;
473
474
		if ( !$action_count )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
introduced by
Expected 1 space after "!"; 0 found
Loading history...
475
			return '';
476
477
		$out = '<div class="' . ( $always_visible ? 'row-actions visible' : 'row-actions' ) . '">';
478
		foreach ( $actions as $action => $link ) {
479
			++$i;
480
			( $i == $action_count ) ? $sep = '' : $sep = ' | ';
481
			$out .= "<span class='$action'>$link$sep</span>";
482
		}
483
		$out .= '</div>';
484
485
		$out .= '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __( 'Show more details' ) . '</span></button>';
486
487
		return $out;
488
	}
489
490
	/**
491
	 * Display a monthly dropdown for filtering items
492
	 *
493
	 * @since 2.0.18
494
	 * @access protected
495
	 *
496
	 * @global wpdb      $wpdb
497
	 * @global WP_Locale $wp_locale
498
	 *
499
	 * @param string $post_type
500
	 */
501
	protected function months_dropdown( $post_type ) {
502
		global $wpdb, $wp_locale;
503
504
		/**
505
		 * Filter whether to remove the 'Months' drop-down from the post list table.
506
		 *
507
		 * @since 4.2.0
508
		 *
509
		 * @param bool   $disable   Whether to disable the drop-down. Default false.
510
		 * @param string $post_type The post type.
511
		 */
512
		if ( apply_filters( 'disable_months_dropdown', false, $post_type ) ) {
513
			return;
514
		}
515
516
		$months = $wpdb->get_results( $wpdb->prepare( "
517
			SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month
518
			FROM $wpdb->posts
519
			WHERE post_type = %s
520
			ORDER BY post_date DESC
521
		", $post_type ) );
522
523
		/**
524
		 * Filter the 'Months' drop-down results.
525
		 *
526
		 * @since 3.7.0
527
		 *
528
		 * @param object $months    The months drop-down query results.
529
		 * @param string $post_type The post type.
530
		 */
531
		$months = apply_filters( 'months_dropdown_results', $months, $post_type );
532
533
		$month_count = count( $months );
534
535
		if ( !$month_count || ( 1 == $month_count && 0 == $months[0]->month ) )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
introduced by
Expected 1 space after "!"; 0 found
Loading history...
536
			return;
537
538
		$m = isset( $_GET['m'] ) ? (int) $_GET['m'] : 0;
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
539
?>
540
		<label for="filter-by-date" class="screen-reader-text"><?php _e( 'Filter by date' ); ?></label>
541
		<select name="m" id="filter-by-date">
542
			<option<?php selected( $m, 0 ); ?> value="0"><?php _e( 'All dates' ); ?></option>
543
<?php
544
		foreach ( $months as $arc_row ) {
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 0 tabs, found 2
Loading history...
545
			if ( 0 == $arc_row->year )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
546
				continue;
547
548
			$month = zeroise( $arc_row->month, 2 );
549
			$year = $arc_row->year;
550
551
			printf( "<option %s value='%s'>%s</option>\n",
552
				selected( $m, $year . $month, false ),
553
				esc_attr( $arc_row->year . $month ),
554
				/* translators: 1: month name, 2: 4-digit year */
555
				sprintf( __( '%1$s %2$d' ), $wp_locale->get_month( $month ), $year )
556
			);
557
		}
558
?>
559
		</select>
560
<?php
561
	}
562
563
	/**
564
	 * Display a view switcher
565
	 *
566
	 * @since 2.0.18
567
	 * @access protected
568
	 *
569
	 * @param string $current_mode
570
	 */
571
	protected function view_switcher( $current_mode ) {
572
?>
573
		<input type="hidden" name="mode" value="<?php echo esc_attr( $current_mode ); ?>" />
574
		<div class="view-switch">
575
<?php
576
			foreach ( $this->modes as $mode => $title ) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 0 tabs, found 3
Loading history...
577
				$classes = array( 'view-' . $mode );
578
				if ( $current_mode == $mode )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
579
					$classes[] = 'current';
580
				printf(
581
					"<a href='%s' class='%s' id='view-switch-$mode'><span class='screen-reader-text'>%s</span></a>\n",
582
					esc_url( add_query_arg( 'mode', $mode ) ),
583
					implode( ' ', $classes ),
584
					$title
585
				);
586
			}
587
		?>
588
		</div>
589
<?php
590
	}
591
592
	/**
593
	 * Display a comment count bubble
594
	 *
595
	 * @since 2.0.18
596
	 * @access protected
597
	 *
598
	 * @param int $post_id          The post ID.
599
	 * @param int $pending_comments Number of pending comments.
600
	 */
601
	protected function comments_bubble( $post_id, $pending_comments ) {
602
		$approved_comments = get_comments_number();
603
604
		$approved_comments_number = number_format_i18n( $approved_comments );
605
		$pending_comments_number = number_format_i18n( $pending_comments );
606
607
		$approved_only_phrase = sprintf( _n( '%s comment', '%s comments', $approved_comments ), $approved_comments_number );
608
		$approved_phrase = sprintf( _n( '%s approved comment', '%s approved comments', $approved_comments ), $approved_comments_number );
609
		$pending_phrase = sprintf( _n( '%s pending comment', '%s pending comments', $pending_comments ), $pending_comments_number );
610
611
		// No comments at all.
612
		if ( ! $approved_comments && ! $pending_comments ) {
613
			printf( '<span aria-hidden="true">—</span><span class="screen-reader-text">%s</span>',
614
				__( 'No comments' )
615
			);
616
		// Approved comments have different display depending on some conditions.
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected at least 3 tabs, found 2
Loading history...
617 View Code Duplication
		} elseif ( $approved_comments ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
618
			printf( '<a href="%s" class="post-com-count post-com-count-approved"><span class="comment-count-approved" aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></a>',
619
				esc_url( add_query_arg( array( 'p' => $post_id, 'comment_status' => 'approved' ), admin_url( 'edit-comments.php' ) ) ),
620
				$approved_comments_number,
621
				$pending_comments ? $approved_phrase : $approved_only_phrase
622
			);
623
		} else {
624
			printf( '<span class="post-com-count post-com-count-no-comments"><span class="comment-count comment-count-no-comments" aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></span>',
625
				$approved_comments_number,
626
				$pending_comments ? __( 'No approved comments' ) : __( 'No comments' )
627
			);
628
		}
629
630 View Code Duplication
		if ( $pending_comments ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
631
			printf( '<a href="%s" class="post-com-count post-com-count-pending"><span class="comment-count-pending" aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></a>',
632
				esc_url( add_query_arg( array( 'p' => $post_id, 'comment_status' => 'moderated' ), admin_url( 'edit-comments.php' ) ) ),
633
				$pending_comments_number,
634
				$pending_phrase
635
			);
636
		}
637
	}
638
639
	/**
640
	 * Get the current page number
641
	 *
642
	 * @since 2.0.18
643
	 * @access public
644
	 *
645
	 * @return int
646
	 */
647
	public function get_pagenum() {
648
		$pagenum = isset( $_REQUEST['paged'] ) ? absint( $_REQUEST['paged'] ) : 0;
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
649
650
		if ( isset( $this->_pagination_args['total_pages'] ) && $pagenum > $this->_pagination_args['total_pages'] )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
651
			$pagenum = $this->_pagination_args['total_pages'];
652
653
		return max( 1, $pagenum );
654
	}
655
656
	/**
657
	 * Get number of items to display on a single page
658
	 *
659
	 * @since 2.0.18
660
	 * @access protected
661
	 *
662
	 * @param string $option
663
	 * @param int    $default
664
	 * @return int
665
	 */
666
	protected function get_items_per_page( $option, $default = 20 ) {
667
		$per_page = (int) get_user_option( $option );
668
		if ( empty( $per_page ) || $per_page < 1 )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
669
			$per_page = $default;
670
671
		/**
672
		 * Filter the number of items to be displayed on each page of the list table.
673
		 *
674
		 * The dynamic hook name, $option, refers to the `per_page` option depending
675
		 * on the type of list table in use. Possible values include: 'edit_comments_per_page',
676
		 * 'sites_network_per_page', 'site_themes_network_per_page', 'themes_network_per_page',
677
		 * 'users_network_per_page', 'edit_post_per_page', 'edit_page_per_page',
678
		 * 'edit_{$post_type}_per_page', etc.
679
		 *
680
		 * @since 2.9.0
681
		 *
682
		 * @param int $per_page Number of items to be displayed. Default 20.
683
		 */
684
		return (int) apply_filters( $option, $per_page );
685
	}
686
687
	/**
688
	 * Display the pagination.
689
	 *
690
	 * @since 2.0.18
691
	 * @access protected
692
	 *
693
	 * @param string $which
694
	 */
695
	protected function pagination( $which ) {
696
		if ( empty( $this->_pagination_args ) ) {
697
			return;
698
		}
699
700
		$total_items = $this->_pagination_args['total_items'];
701
		$total_pages = $this->_pagination_args['total_pages'];
702
		$infinite_scroll = false;
703
		if ( isset( $this->_pagination_args['infinite_scroll'] ) ) {
704
			$infinite_scroll = $this->_pagination_args['infinite_scroll'];
705
		}
706
707
		$output = '<span class="displaying-num">' . sprintf( _n( '%s item', '%s items', $total_items ), number_format_i18n( $total_items ) ) . '</span>';
708
709
		$current = $this->get_pagenum();
710
711
		$current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
0 ignored issues
show
introduced by
Detected usage of a non-validated input variable: $_SERVER
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_SERVER
Loading history...
712
713
		$current_url = remove_query_arg( array( 'hotkeys_highlight_last', 'hotkeys_highlight_first' ), $current_url );
714
715
		$page_links = array();
716
717
		$total_pages_before = '<span class="paging-input">';
718
		$total_pages_after  = '</span>';
719
720
		$disable_first = $disable_last = $disable_prev = $disable_next = false;
721
722
 		if ( $current == 1 ) {
723
			$disable_first = true;
724
			$disable_prev = true;
725
 		}
726
		if ( $current == 2 ) {
727
			$disable_first = true;
728
		}
729
 		if ( $current == $total_pages ) {
730
			$disable_last = true;
731
			$disable_next = true;
732
 		}
733
		if ( $current == $total_pages - 1 ) {
734
			$disable_last = true;
735
		}
736
737 View Code Duplication
		if ( $disable_first ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
738
			$page_links[] = '<span class="tablenav-pages-navspan" aria-hidden="true">&laquo;</span>';
739
		} else {
740
			$page_links[] = sprintf( "<a class='first-page' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
741
				esc_url( remove_query_arg( 'paged', $current_url ) ),
742
				__( 'First page' ),
743
				'&laquo;'
744
			);
745
		}
746
747
		if ( $disable_prev ) {
748
			$page_links[] = '<span class="tablenav-pages-navspan" aria-hidden="true">&lsaquo;</span>';
749 View Code Duplication
		} else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
750
			$page_links[] = sprintf( "<a class='prev-page' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
751
				esc_url( add_query_arg( 'paged', max( 1, $current-1 ), $current_url ) ),
0 ignored issues
show
introduced by
Expected 1 space before "-"; 0 found
Loading history...
752
				__( 'Previous page' ),
753
				'&lsaquo;'
754
			);
755
		}
756
757
		if ( 'bottom' == $which ) {
758
			$html_current_page  = $current;
759
			$total_pages_before = '<span class="screen-reader-text">' . __( 'Current Page' ) . '</span><span id="table-paging" class="paging-input">';
760
		} else {
761
			$html_current_page = sprintf( "%s<input class='current-page' id='current-page-selector' type='text' name='paged' value='%s' size='%d' aria-describedby='table-paging' />",
762
				'<label for="current-page-selector" class="screen-reader-text">' . __( 'Current Page' ) . '</label>',
763
				$current,
764
				strlen( $total_pages )
765
			);
766
		}
767
		$html_total_pages = sprintf( "<span class='total-pages'>%s</span>", number_format_i18n( $total_pages ) );
768
		$page_links[] = $total_pages_before . sprintf( _x( '%1$s of %2$s', 'paging' ), $html_current_page, $html_total_pages ) . $total_pages_after;
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$total_pages_after'
Loading history...
769
770 View Code Duplication
		if ( $disable_next ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
771
			$page_links[] = '<span class="tablenav-pages-navspan" aria-hidden="true">&rsaquo;</span>';
772
		} else {
773
			$page_links[] = sprintf( "<a class='next-page' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
774
				esc_url( add_query_arg( 'paged', min( $total_pages, $current+1 ), $current_url ) ),
0 ignored issues
show
introduced by
Expected 1 space before "+"; 0 found
Loading history...
introduced by
Expected 1 space after "+"; 0 found
Loading history...
775
				__( 'Next page' ),
776
				'&rsaquo;'
777
			);
778
		}
779
780 View Code Duplication
		if ( $disable_last ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
781
			$page_links[] = '<span class="tablenav-pages-navspan" aria-hidden="true">&raquo;</span>';
782
		} else {
783
			$page_links[] = sprintf( "<a class='last-page' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
784
				esc_url( add_query_arg( 'paged', $total_pages, $current_url ) ),
785
				__( 'Last page' ),
786
				'&raquo;'
787
			);
788
		}
789
790
		$pagination_links_class = 'pagination-links';
791
		if ( ! empty( $infinite_scroll ) ) {
792
			$pagination_links_class = ' hide-if-js';
793
		}
794
		$output .= "\n<span class='$pagination_links_class'>" . join( "\n", $page_links ) . '</span>';
795
796
		if ( $total_pages ) {
797
			$page_class = $total_pages < 2 ? ' one-page' : '';
798
		} else {
799
			$page_class = ' no-pages';
800
		}
801
		$this->_pagination = "<div class='tablenav-pages{$page_class}'>$output</div>";
802
803
		echo $this->_pagination;
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
804
	}
805
806
	/**
807
	 * Get a list of sortable columns. The format is:
808
	 * 'internal-name' => 'orderby'
809
	 * or
810
	 * 'internal-name' => array( 'orderby', true )
811
	 *
812
	 * The second format will make the initial sorting order be descending
813
	 *
814
	 * @since 2.0.18
815
	 * @access protected
816
	 *
817
	 * @return array
818
	 */
819
	protected function get_sortable_columns() {
820
		return array();
821
	}
822
823
	/**
824
	 * Gets the name of the default primary column.
825
	 *
826
	 * @since 4.3.0
827
	 * @access protected
828
	 *
829
	 * @return string Name of the default primary column, in this case, an empty string.
830
	 */
831
	protected function get_default_primary_column_name() {
832
		$columns = $this->get_columns();
833
		$column = '';
834
835
		// We need a primary defined so responsive views show something,
836
		// so let's fall back to the first non-checkbox column.
837
		foreach( $columns as $col => $column_name ) {
0 ignored issues
show
introduced by
Space after opening control structure is required
Loading history...
introduced by
No space before opening parenthesis is prohibited
Loading history...
838
			if ( 'cb' === $col ) {
839
				continue;
840
			}
841
842
			$column = $col;
843
			break;
844
		}
845
846
		return $column;
847
	}
848
849
	/**
850
	 * Gets the name of the primary column.
851
	 *
852
	 * @since 4.3.0
853
	 * @access protected
854
	 *
855
	 * @return string The name of the primary column.
856
	 */
857
	protected function get_primary_column_name() {
858
		$columns = $this->get_columns();
859
		$default = $this->get_default_primary_column_name();
860
861
		// If the primary column doesn't exist fall back to the
862
		// first non-checkbox column.
863
		if ( ! isset( $columns[ $default ] ) ) {
864
			$default = FrmListHelper::get_default_primary_column_name();
865
		}
866
867
		/**
868
		 * Filter the name of the primary column for the current list table.
869
		 *
870
		 * @since 4.3.0
871
		 *
872
		 * @param string $default Column name default for the specific list table, e.g. 'name'.
873
		 * @param string $context Screen ID for specific list table, e.g. 'plugins'.
874
		 */
875
		$column  = apply_filters( 'list_table_primary_column', $default, $this->screen->id );
876
877
		if ( empty( $column ) || ! isset( $columns[ $column ] ) ) {
878
			$column = $default;
879
		}
880
881
		return $column;
882
	}
883
884
	/**
885
	 * Get a list of all, hidden and sortable columns, with filter applied
886
	 *
887
	 * @since 2.0.18
888
	 * @access protected
889
	 *
890
	 * @return array
891
	 */
892
	protected function get_column_info() {
893
		// $_column_headers is already set / cached
894
		if ( isset( $this->_column_headers ) && is_array( $this->_column_headers ) ) {
895
			// Back-compat for list tables that have been manually setting $_column_headers for horse reasons.
896
			// In 4.3, we added a fourth argument for primary column.
897
			$column_headers = array( array(), array(), array(), $this->get_primary_column_name() );
898
			foreach ( $this->_column_headers as $key => $value ) {
899
				$column_headers[ $key ] = $value;
900
			}
901
902
			return $column_headers;
903
		}
904
905
		$columns = get_column_headers( $this->screen );
906
		$hidden = get_hidden_columns( $this->screen );
907
908
		$sortable_columns = $this->get_sortable_columns();
909
		/**
910
		 * Filter the list table sortable columns for a specific screen.
911
		 *
912
		 * The dynamic portion of the hook name, `$this->screen->id`, refers
913
		 * to the ID of the current screen, usually a string.
914
		 *
915
		 * @since 3.5.0
916
		 *
917
		 * @param array $sortable_columns An array of sortable columns.
918
		 */
919
		$_sortable = apply_filters( "manage_{$this->screen->id}_sortable_columns", $sortable_columns );
920
921
		$sortable = array();
922
		foreach ( $_sortable as $id => $data ) {
923
			if ( empty( $data ) )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
924
				continue;
925
926
			$data = (array) $data;
927
			if ( !isset( $data[1] ) )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
introduced by
Expected 1 space after "!"; 0 found
Loading history...
928
				$data[1] = false;
929
930
			$sortable[$id] = $data;
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
931
		}
932
933
		$primary = $this->get_primary_column_name();
934
		$this->_column_headers = array( $columns, $hidden, $sortable, $primary );
935
936
		return $this->_column_headers;
937
	}
938
939
	/**
940
	 * Return number of visible columns
941
	 *
942
	 * @since 2.0.18
943
	 * @access public
944
	 *
945
	 * @return int
946
	 */
947
	public function get_column_count() {
948
		list ( $columns, $hidden ) = $this->get_column_info();
949
		$hidden = array_intersect( array_keys( $columns ), array_filter( $hidden ) );
950
		return count( $columns ) - count( $hidden );
951
	}
952
953
	/**
954
	 * Print column headers, accounting for hidden and sortable columns.
955
	 *
956
	 * @since 2.0.18
957
	 * @access public
958
	 *
959
	 * @staticvar int $cb_counter
960
	 *
961
	 * @param bool $with_id Whether to set the id attribute or not
962
	 */
963
	public function print_column_headers( $with_id = true ) {
964
		list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
965
966
		$current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
0 ignored issues
show
introduced by
Detected usage of a non-validated input variable: $_SERVER
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_SERVER
Loading history...
967
		$current_url = remove_query_arg( 'paged', $current_url );
968
969
		if ( isset( $_GET['orderby'] ) )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
970
			$current_orderby = $_GET['orderby'];
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
971
		else
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
972
			$current_orderby = '';
973
974
		if ( isset( $_GET['order'] ) && 'desc' == $_GET['order'] )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
975
			$current_order = 'desc';
976
		else
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
977
			$current_order = 'asc';
978
979
		if ( ! empty( $columns['cb'] ) ) {
980
			static $cb_counter = 1;
981
			$columns['cb'] = '<label class="screen-reader-text" for="cb-select-all-' . $cb_counter . '">' . __( 'Select All' ) . '</label>'
982
				. '<input id="cb-select-all-' . $cb_counter . '" type="checkbox" />';
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$cb_counter'
Loading history...
983
			$cb_counter++;
984
		}
985
986
		foreach ( $columns as $column_key => $column_display_name ) {
987
			$class = array( 'manage-column', "column-$column_key" );
988
989
			if ( in_array( $column_key, $hidden ) ) {
990
				$class[] = 'hidden';
991
			}
992
993
			if ( 'cb' == $column_key )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
994
				$class[] = 'check-column';
995
			elseif ( in_array( $column_key, array( 'posts', 'comments', 'links' ) ) )
996
				$class[] = 'num';
997
998
			if ( $column_key === $primary ) {
999
				$class[] = 'column-primary';
1000
			}
1001
1002
			if ( isset( $sortable[$column_key] ) ) {
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
1003
				list( $orderby, $desc_first ) = $sortable[$column_key];
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
1004
1005
				if ( $current_orderby == $orderby ) {
1006
					$order = 'asc' == $current_order ? 'desc' : 'asc';
1007
					$class[] = 'sorted';
1008
					$class[] = $current_order;
1009
				} else {
1010
					$order = $desc_first ? 'desc' : 'asc';
1011
					$class[] = 'sortable';
1012
					$class[] = $desc_first ? 'asc' : 'desc';
1013
				}
1014
1015
				$column_display_name = '<a href="' . esc_url( add_query_arg( compact( 'orderby', 'order' ), $current_url ) ) . '"><span>' . $column_display_name . '</span><span class="sorting-indicator"></span></a>';
1016
			}
1017
1018
			$tag = ( 'cb' === $column_key ) ? 'td' : 'th';
1019
			$scope = ( 'th' === $tag ) ? 'scope="col"' : '';
1020
			$id = $with_id ? "id='$column_key'" : '';
1021
1022
			if ( !empty( $class ) )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
introduced by
Expected 1 space after "!"; 0 found
Loading history...
1023
				$class = "class='" . join( ' ', $class ) . "'";
1024
1025
			echo "<$tag $scope $id $class>$column_display_name</$tag>";
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '"<$tag $scope $id $class>$column_display_name</$tag>"'
Loading history...
1026
		}
1027
	}
1028
1029
	/**
1030
	 * Display the table
1031
	 *
1032
	 * @since 2.0.18
1033
	 * @access public
1034
	 */
1035
	public function display() {
1036
		$singular = $this->_args['singular'];
1037
1038
		$this->display_tablenav( 'top' );
1039
?>
1040
<table class="wp-list-table <?php echo implode( ' ', $this->get_table_classes() ); ?>">
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'implode'
Loading history...
1041
	<thead>
1042
	<tr>
1043
		<?php $this->print_column_headers(); ?>
1044
	</tr>
1045
	</thead>
1046
1047
	<tbody id="the-list"<?php
1048
		if ( $singular ) {
1 ignored issue
show
Coding Style introduced by
Line indented incorrectly; expected 1 tabs, found 2
Loading history...
1049
			echo " data-wp-lists='list:$singular'";
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '" data-wp-lists='list:$singular'"'
Loading history...
1050
		} ?>>
1051
		<?php $this->display_rows_or_placeholder(); ?>
1052
	</tbody>
1053
1054
	<tfoot>
1055
	<tr>
1056
		<?php $this->print_column_headers( false ); ?>
1057
	</tr>
1058
	</tfoot>
1059
1060
</table>
1061
<?php
1062
		$this->display_tablenav( 'bottom' );
1063
	}
1064
1065
	/**
1066
	 * Get a list of CSS classes for the list table table tag.
1067
	 *
1068
	 * @since 2.0.18
1069
	 * @access protected
1070
	 *
1071
	 * @return array List of CSS classes for the table tag.
1072
	 */
1073
	protected function get_table_classes() {
1074
		return array( 'widefat', 'fixed', 'striped', $this->_args['plural'] );
1075
	}
1076
1077
	/**
1078
	 * Generate the table navigation above or below the table
1079
	 *
1080
	 * @since 2.0.18
1081
	 * @access protected
1082
	 * @param string $which
1083
	 */
1084
	protected function display_tablenav( $which ) {
1085
		if ( 'top' == $which )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
1086
			wp_nonce_field( 'bulk-' . $this->_args['plural'] );
1087
?>
1088
	<div class="tablenav <?php echo esc_attr( $which ); ?>">
1089
1090
		<div class="alignleft actions bulkactions">
1091
			<?php $this->bulk_actions( $which ); ?>
1092
		</div>
1093
<?php
1094
		$this->extra_tablenav( $which );
1095
		$this->pagination( $which );
1096
?>
1097
1098
		<br class="clear" />
1099
	</div>
1100
<?php
1101
	}
1102
1103
	/**
1104
	 * Extra controls to be displayed between bulk actions and pagination
1105
	 *
1106
	 * @since 2.0.18
1107
	 * @access protected
1108
	 *
1109
	 * @param string $which
1110
	 */
1111
	protected function extra_tablenav( $which ) {}
1112
1113
	/**
1114
	 * Generate the tbody element for the list table.
1115
	 *
1116
	 * @since 2.0.18
1117
	 * @access public
1118
	 */
1119
	public function display_rows_or_placeholder() {
1120
		if ( $this->has_items() ) {
1121
			$this->display_rows();
1122
		} else {
1123
			echo '<tr class="no-items"><td class="colspanchange" colspan="' . $this->get_column_count() . '">';
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
1124
			$this->no_items();
1125
			echo '</td></tr>';
1126
		}
1127
	}
1128
1129
	/**
1130
	 * Generates content for a single row of the table
1131
	 *
1132
	 * @since 2.0.18
1133
	 * @access public
1134
	 *
1135
	 * @param object $item The current item
1136
	 */
1137
	public function single_row( $item ) {
1138
		echo '<tr>';
1139
		$this->single_row_columns( $item );
1140
		echo '</tr>';
1141
	}
1142
1143
	/**
1144
	 *
1145
	 * @param object $item
1146
	 * @param string $column_name
1147
	 */
1148
	protected function column_default( $item, $column_name ) {}
0 ignored issues
show
Unused Code introduced by
The parameter $item is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $column_name is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1149
1150
	/**
1151
	 *
1152
	 * @param object $item
1153
	 */
1154
	protected function column_cb( $item ) {}
0 ignored issues
show
Unused Code introduced by
The parameter $item is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1155
1156
	/**
1157
	 * Generates the columns for a single row of the table
1158
	 *
1159
	 * @since 2.0.18
1160
	 * @access protected
1161
	 *
1162
	 * @param object $item The current item
1163
	 */
1164
	protected function single_row_columns( $item ) {
1165
		list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
0 ignored issues
show
Unused Code introduced by
The assignment to $sortable is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
1166
1167
		foreach ( $columns as $column_name => $column_display_name ) {
1168
			$classes = "$column_name column-$column_name";
1169
			if ( $primary === $column_name ) {
1170
				$classes .= ' has-row-actions column-primary';
1171
			}
1172
1173
			if ( in_array( $column_name, $hidden ) ) {
1174
				$classes .= ' hidden';
1175
			}
1176
1177
			// Comments column uses HTML in the display name with screen reader text.
1178
			// Instead of using esc_attr(), we strip tags to get closer to a user-friendly string.
1179
			$data = 'data-colname="' . wp_strip_all_tags( $column_display_name ) . '"';
1180
1181
			$attributes = "class='$classes' $data";
1182
1183
			if ( 'cb' == $column_name ) {
1184
				echo '<th scope="row" class="check-column">';
1185
				echo $this->column_cb( $item );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
1186
				echo '</th>';
1187
			} elseif ( method_exists( $this, '_column_' . $column_name ) ) {
1188
				echo call_user_func(
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'call_user_func'
Loading history...
1189
					array( $this, '_column_' . $column_name ),
1190
					$item,
1191
					$classes,
1192
					$data,
1193
					$primary
1194
				);
1195
			} elseif ( method_exists( $this, 'column_' . $column_name ) ) {
1196
				echo "<td $attributes>";
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '"<td $attributes>"'
Loading history...
1197
				echo call_user_func( array( $this, 'column_' . $column_name ), $item );
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'call_user_func'
Loading history...
1198
				echo $this->handle_row_actions( $item, $column_name, $primary );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
1199
				echo "</td>";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal </td> does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
1200
			} else {
1201
				echo "<td $attributes>";
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '"<td $attributes>"'
Loading history...
1202
				echo $this->column_default( $item, $column_name );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
1203
				echo $this->handle_row_actions( $item, $column_name, $primary );
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$this'
Loading history...
1204
				echo "</td>";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal </td> does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
1205
			}
1206
		}
1207
	}
1208
1209
	/**
1210
	 * Generates and display row actions links for the list table.
1211
	 *
1212
	 * @since 4.3.0
1213
	 * @access protected
1214
	 *
1215
	 * @param object $item        The item being acted upon.
1216
	 * @param string $column_name Current column name.
1217
	 * @param string $primary     Primary column name.
1218
	 * @return string The row actions output. In this case, an empty string.
1219
	 */
1220
	protected function handle_row_actions( $item, $column_name, $primary ) {
0 ignored issues
show
Unused Code introduced by
The parameter $item is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1221
		return $column_name == $primary ? '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __( 'Show more details' ) . '</span></button>' : '';
1222
 	}
1223
1224
	/**
1225
	 * Handle an incoming ajax request (called from admin-ajax.php)
1226
	 *
1227
	 * @since 2.0.18
1228
	 * @access public
1229
	 */
1230
	public function ajax_response() {
1231
		$this->prepare_items();
1232
1233
		ob_start();
1234
		if ( ! empty( $_REQUEST['no_placeholder'] ) ) {
0 ignored issues
show
introduced by
Detected access of super global var $_REQUEST, probably need manual inspection.
Loading history...
1235
			$this->display_rows();
1236
		} else {
1237
			$this->display_rows_or_placeholder();
1238
		}
1239
1240
		$rows = ob_get_clean();
1241
1242
		$response = array( 'rows' => $rows );
1243
1244
		if ( isset( $this->_pagination_args['total_items'] ) ) {
1245
			$response['total_items_i18n'] = sprintf(
1246
				_n( '%s item', '%s items', $this->_pagination_args['total_items'] ),
1247
				number_format_i18n( $this->_pagination_args['total_items'] )
1248
			);
1249
		}
1250
		if ( isset( $this->_pagination_args['total_pages'] ) ) {
1251
			$response['total_pages'] = $this->_pagination_args['total_pages'];
1252
			$response['total_pages_i18n'] = number_format_i18n( $this->_pagination_args['total_pages'] );
1253
		}
1254
1255
		die( wp_json_encode( $response ) );
1256
	}
1257
1258
	/**
1259
	 * Send required variables to JavaScript land
1260
	 *
1261
	 * @access public
1262
	 */
1263
	public function _js_vars() {
1264
		$args = array(
1265
			'class'  => get_class( $this ),
1266
			'screen' => array(
1267
				'id'   => $this->screen->id,
1268
				'base' => $this->screen->base,
1269
			)
1270
		);
1271
1272
		printf( "<script type='text/javascript'>list_args = %s;</script>\n", wp_json_encode( $args ) );
1273
	}
1274
}
1275