Completed
Push — master ( 4e5e5b...82e76a )
by Devin
37:33 queued 17:37
created

Give_API_Request_Log_Table::display_tablenav()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 19
rs 9.4285
cc 2
eloc 13
nc 2
nop 1
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 29 and the first side effect is on line 14.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * API Requests Log View Class
4
 *
5
 * @package     Give
6
 * @subpackage  Admin/Reports
7
 * @copyright   Copyright (c) 2016, WordImpress
8
 * @license     http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
 * @since       1.0
10
 */
11
12
// Exit if accessed directly
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
// Load WP_List_Table if not loaded
18
if ( ! class_exists( 'WP_List_Table' ) ) {
19
	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
20
}
21
22
/**
23
 * Give_API_Request_Log_Table List Table Class
24
 *
25
 * Renders the gateway errors list table
26
 *
27
 * @since 1.0
28
 */
29
class Give_API_Request_Log_Table extends WP_List_Table {
30
	/**
31
	 * Number of items per page
32
	 *
33
	 * @var int
34
	 * @since 1.0
35
	 */
36
	public $per_page = 30;
37
38
	/**
39
	 * Get things started
40
	 *
41
	 * @since 1.0
42
	 * @see   WP_List_Table::__construct()
43
	 */
44
	public function __construct() {
45
		global $status, $page;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
46
47
		// Set parent defaults
48
		parent::__construct( array(
49
			'singular' => give_get_forms_label_singular(),    // Singular name of the listed records
50
			'plural'   => give_get_forms_label_plural(),        // Plural name of the listed records
51
			'ajax'     => false                        // Does this table support ajax?
52
		) );
53
	}
54
55
	/**
56
	 * Show the search field
57
	 *
58
	 * @since  1.0
59
	 * @access public
60
	 *
61
	 * @param string $text     Label for the search box
62
	 * @param string $input_id ID of the search box
63
	 *
64
	 * @return void
65
	 */
66
	public function search_box( $text, $input_id ) {
67
		$input_id = $input_id . '-search-input';
68
69
		if ( ! empty( $_REQUEST['orderby'] ) ) {
70
			echo '<input type="hidden" name="orderby" value="' . esc_attr( $_REQUEST['orderby'] ) . '" />';
71
		}
72
		if ( ! empty( $_REQUEST['order'] ) ) {
73
			echo '<input type="hidden" name="order" value="' . esc_attr( $_REQUEST['order'] ) . '" />';
74
		}
75
		?>
76
		<p class="search-box">
77
			<label class="screen-reader-text" for="<?php echo $input_id ?>"><?php echo $text; ?>:</label>
78
			<input type="search" id="<?php echo $input_id ?>" name="s" value="<?php _admin_search_query(); ?>" />
79
			<?php submit_button( $text, 'button', false, false, array( 'ID' => 'search-submit' ) ); ?>
80
		</p>
81
	<?php
82
	}
83
84
	/**
85
	 * Retrieve the table columns
86
	 *
87
	 * @access public
88
	 * @since  1.0
89
	 * @return array $columns Array of all the list table columns
90
	 */
91
	public function get_columns() {
92
		$columns = array(
93
			'ID'      => __( 'Log ID', 'give' ),
94
			'details' => __( 'Request Details', 'give' ),
95
			'ip'      => __( 'Request IP', 'give' ),
96
			'date'    => __( 'Date', 'give' )
97
		);
98
99
		return $columns;
100
	}
101
102
	/**
103
	 * This function renders most of the columns in the list table.
104
	 *
105
	 * @access public
106
	 * @since  1.0
107
	 *
108
	 * @param array  $item        Contains all the data of the discount code
109
	 * @param string $column_name The name of the column
110
	 *
111
	 * @return string Column Name
112
	 */
113
	public function column_default( $item, $column_name ) {
114
		switch ( $column_name ) {
115
			default:
0 ignored issues
show
Unused Code introduced by
default: return $item[$column_name]; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
116
				return $item[ $column_name ];
117
		}
118
	}
119
120
	/**
121
	 * Output Error Message column
122
	 *
123
	 * @access public
124
	 * @since  1.0
125
	 *
126
	 * @param array $item Contains all the data of the log
127
	 *
128
	 * @return void
129
	 */
130
	public function column_details( $item ) {
131
		?>
132
		<a href="#TB_inline?width=640&amp;inlineId=log-details-<?php echo $item['ID']; ?>" class="thickbox" title="<?php _e( 'View Request Details', 'give' ); ?> "><?php _e( 'View Request', 'give' ); ?></a>
133
		<div id="log-details-<?php echo $item['ID']; ?>" style="display:none;">
134
			<?php
135
136
			$request = get_post_field( 'post_excerpt', $item['ID'] );
137
			$error   = get_post_field( 'post_content', $item['ID'] );
138
			echo '<p><strong>' . __( 'API Request:', 'give' ) . '</strong></p>';
139
			echo '<div>' . $request . '</div>';
140
			if ( ! empty( $error ) ) {
141
				echo '<p><strong>' . __( 'Error', 'give' ) . '</strong></p>';
142
				echo '<div>' . esc_html( $error ) . '</div>';
143
			}
144
			echo '<p><strong>' . __( 'API User:', 'give' ) . '</strong></p>';
145
			echo '<div>' . get_post_meta( $item['ID'], '_give_log_user', true ) . '</div>';
146
			echo '<p><strong>' . __( 'API Key:', 'give' ) . '</strong></p>';
147
			echo '<div>' . get_post_meta( $item['ID'], '_give_log_key', true ) . '</div>';
148
			echo '<p><strong>' . __( 'Request Date:', 'give' ) . '</strong></p>';
149
			echo '<div>' . get_post_field( 'post_date', $item['ID'] ) . '</div>';
150
			?>
151
		</div>
152
	<?php
153
	}
154
155
	/**
156
	 * Retrieves the search query string
157
	 *
158
	 * @access public
159
	 * @since  1.0
160
	 * @return mixed String if search is present, false otherwise
161
	 */
162
	public function get_search() {
163
		return ! empty( $_GET['s'] ) ? urldecode( trim( $_GET['s'] ) ) : false;
164
	}
165
166
167
	/**
168
	 * Display Tablenav (extended)
169
	 *
170
	 * @description: Display the table navigation above or below the table even when no items in the logs, so nav doesn't disappear
171
	 *
172
	 * @see: https://github.com/WordImpress/Give/issues/564
173
	 *
174
	 * @since 1.4.1
175
	 * @access protected
176
	 *
177
	 * @param string $which
178
	 */
179
	protected function display_tablenav( $which ) {
180
		if ( 'top' === $which ) {
181
			wp_nonce_field( 'bulk-' . $this->_args['plural'] );
182
		}
183
		?>
184
		<div class="tablenav <?php echo esc_attr( $which ); ?>">
185
186
			<div class="alignleft actions bulkactions">
187
				<?php $this->bulk_actions( $which ); ?>
188
			</div>
189
			<?php
190
			$this->extra_tablenav( $which );
191
			$this->pagination( $which );
192
			?>
193
194
			<br class="clear"/>
195
		</div>
196
		<?php
197
	}
198
199
	/**
200
	 * Gets the meta query for the log query
201
	 *
202
	 * This is used to return log entries that match our search query
203
	 *
204
	 * @access public
205
	 * @since  1.0
206
	 * @return array $meta_query
207
	 */
208
	function get_meta_query() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
209
		$meta_query = array();
210
211
		$search = $this->get_search();
212
213
		if ( $search ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $search of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
214
			if ( filter_var( $search, FILTER_VALIDATE_IP ) ) {
215
				// This is an IP address search
216
				$key = '_give_log_request_ip';
217
			} else if ( is_email( $search ) ) {
218
				// This is an email search
219
				$userdata = get_user_by( 'email', $search );
220
221
				if ( $userdata ) {
222
					$search = $userdata->ID;
223
				}
224
225
				$key = '_give_log_user';
226
			} elseif ( strlen( $search ) == 32 ) {
227
				// Look for an API key
228
				$key = '_give_log_key';
229
			} elseif ( stristr( $search, 'token:' ) ) {
230
				// Look for an API token
231
				$search = str_ireplace( 'token:', '', $search );
232
				$key    = '_give_log_token';
233
			} else {
234
				// This is (probably) a user ID search
235
				$userdata = get_userdata( $search );
236
237
				if ( $userdata ) {
238
					$search = $userdata->ID;
239
				}
240
241
				$key = '_give_log_user';
242
			}
243
244
			// Setup the meta query
245
			$meta_query[] = array(
246
				'key'     => $key,
247
				'value'   => $search,
248
				'compare' => '='
249
			);
250
		}
251
252
		return $meta_query;
253
	}
254
255
	/**
256
	 * Retrieve the current page number
257
	 *
258
	 * @access public
259
	 * @since  1.0
260
	 * @return int Current page number
261
	 */
262
	public function get_paged() {
263
		return isset( $_GET['paged'] ) ? absint( $_GET['paged'] ) : 1;
264
	}
265
266
	/**
267
	 * Outputs the log views
268
	 *
269
	 * @access public
270
	 * @since  1.0
271
	 * @return void
272
	 */
273
	function bulk_actions( $which = '' ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
274
		give_log_views();
275
	}
276
277
	/**
278
	 * Gets the log entries for the current view
279
	 *
280
	 * @access public
281
	 * @since  1.0
282
	 * @global object $give_logs Give Logs Object
283
	 * @return array $logs_data Array of all the Log entires
284
	 */
285
	public function get_logs() {
286
		global $give_logs;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
287
288
		$logs_data = array();
289
		$paged     = $this->get_paged();
290
		$log_query = array(
291
			'log_type'   => 'api_request',
292
			'paged'      => $paged,
293
			'meta_query' => $this->get_meta_query()
294
		);
295
296
		$logs = $give_logs->get_connected_logs( $log_query );
297
298
		if ( $logs ) {
299
			foreach ( $logs as $log ) {
300
301
				$logs_data[] = array(
302
					'ID'   => $log->ID,
303
					'ip'   => get_post_meta( $log->ID, '_give_log_request_ip', true ),
304
					'date' => $log->post_date
305
				);
306
			}
307
		}
308
309
		return $logs_data;
310
	}
311
312
	/**
313
	 * Setup the final data for the table
314
	 *
315
	 * @access public
316
	 * @since  1.0
317
	 * @global object $give_logs Give Logs Object
318
	 * @uses   Give_API_Request_Log_Table::get_columns()
319
	 * @uses   WP_List_Table::get_sortable_columns()
320
	 * @uses   Give_API_Request_Log_Table::get_pagenum()
321
	 * @uses   Give_API_Request_Log_Table::get_logs()
322
	 * @uses   Give_API_Request_Log_Table::get_log_count()
323
	 * @return void
324
	 */
325
	public function prepare_items() {
326
		global $give_logs;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
327
328
		$columns               = $this->get_columns();
329
		$hidden                = array(); // No hidden columns
330
		$sortable              = $this->get_sortable_columns();
331
		$this->_column_headers = array( $columns, $hidden, $sortable );
332
		$this->items           = $this->get_logs();
333
		$total_items           = $give_logs->get_log_count( 0, 'api_requests' );
334
335
		$this->set_pagination_args( array(
336
				'total_items' => $total_items,
337
				'per_page'    => $this->per_page,
338
				'total_pages' => ceil( $total_items / $this->per_page )
339
			)
340
		);
341
	}
342
}
343