PluginProbe
Redirection / 2.9
Redirection v2.9
5.10.0 5.9.0 5.8.1 5.8.0 3.7.2 3.7.3 4.0 4.0.1 4.1 4.1.1 4.2 4.2.1 4.2.2 4.2.3 4.3 4.3.1 4.3.2 4.3.3 4.4 4.4.1 4.4.2 4.5 4.5.1 4.6.2 4.7.1 All 130 releases
← All changes | redirection-api.php +399 -93 4.02.9 View file →
@@ -1,123 +1,429 @@
1 1 <?php
2 2
3 -include_once dirname( __FILE__ ) . '/api/api-group.php';
4 -include_once dirname( __FILE__ ) . '/api/api-redirect.php';
5 -include_once dirname( __FILE__ ) . '/api/api-log.php';
6 -include_once dirname( __FILE__ ) . '/api/api-404.php';
7 -include_once dirname( __FILE__ ) . '/api/api-settings.php';
8 -include_once dirname( __FILE__ ) . '/api/api-plugin.php';
9 -include_once dirname( __FILE__ ) . '/api/api-import.php';
10 -include_once dirname( __FILE__ ) . '/api/api-export.php';
3 +// Todo: use the JSON API
4 +class Redirection_Api {
5 + public $endpoints = array(
6 + 'load_settings',
7 + 'save_settings',
8 + 'get_logs',
9 + 'log_action',
10 + 'delete_all',
11 + 'delete_plugin',
12 + 'get_redirect',
13 + 'set_redirect',
14 + 'redirect_action',
15 + 'get_group',
16 + 'set_group',
17 + 'group_action',
18 + 'import_data',
19 + 'export_data',
20 + 'ping',
21 + 'plugin_status',
22 + 'get_importers',
23 + );
11 24
12 -define( 'REDIRECTION_API_NAMESPACE', 'redirection/v1' );
25 + public function __construct() {
26 + global $wpdb;
13 27
14 -class Redirection_Api_Route {
15 - protected function add_error_details( WP_Error $error, $line, $code = 400 ) {
28 + $wpdb->hide_errors();
29 +
30 + foreach ( $this->endpoints as $point ) {
31 + add_action( 'wp_ajax_red_'.$point, array( $this, 'check_auth' ), 9 );
32 + add_action( 'wp_ajax_red_'.$point, array( $this, 'ajax_'.$point ), 10 );
33 + }
34 + }
35 +
36 + private function addDatabaseError( $response ) {
16 37 global $wpdb;
17 38
18 - $data = array(
19 - 'status' => $code,
20 - 'error_code' => $line,
39 + if ( isset( $response['error'] ) && isset( $wpdb->last_error ) && $wpdb->last_error ) {
40 + $response['error']['wpdb'] = $wpdb->last_error;
41 + }
42 +
43 + return $response;
44 + }
45 +
46 + private function getError( $message, $line ) {
47 + return array(
48 + 'error' => array(
49 + 'message' => $message,
50 + 'code' => $line,
51 + )
21 52 );
53 + }
22 54
23 - if ( isset( $wpdb->last_error ) && $wpdb->last_error ) {
24 - $data['wpdb'] = $wpdb->last_error;
55 + public function check_auth( $params ) {
56 + if ( check_ajax_referer( 'wp_rest', false, false ) === false ) {
57 + $error = $this->getError( 'Unable to perform action - bad nonce "wp_rest"', __LINE__ );
58 + $error['error']['action'] = 'reload';
59 + wp_die( $this->output_ajax_response( $error ) );
25 60 }
26 61
27 - $error->add_data( $data );
28 - return $error;
62 + if ( $this->user_has_access() === false ) {
63 + wp_die( $this->output_ajax_response( $this->getError( 'No permissions to perform action', __LINE__ ) ) );
64 + }
29 65 }
30 66
31 - public function permission_callback( WP_REST_Request $request ) {
32 - return current_user_can( apply_filters( 'redirection_role', 'manage_options' ) );
67 + private function get_params( $params = array() ) {
68 + if ( empty( $params ) && isset( $_POST['data'] ) ) {
69 + $params = json_decode( wp_unslash( $_POST['data'] ), true );
70 + }
71 +
72 + return $params;
33 73 }
34 74
35 - public function get_route( $method, $callback ) {
36 - return array(
37 - 'methods' => $method,
38 - 'callback' => array( $this, $callback ),
39 - 'permission_callback' => array( $this, 'permission_callback' ),
40 - );
75 + public function ajax_ping() {
76 + return $this->output_ajax_response( array( 'nonce' => wp_create_nonce( 'wp_rest' ) ) );
41 77 }
42 -}
43 78
44 -class Redirection_Api_Filter_Route extends Redirection_Api_Route {
45 - protected function get_filter_args( $filter_fields, $order_fields ) {
46 - return array(
47 - 'filterBy' => array(
48 - 'description' => 'Field to filter by',
49 - 'type' => 'enum',
50 - 'enum' => $filter_fields,
51 - ),
52 - 'filter' => array(
53 - 'description' => 'Value to filter by',
54 - 'type' => 'string',
55 - ),
56 - 'orderby' => array(
57 - 'description' => 'Field to order results by',
58 - 'type' => 'enum',
59 - 'enum' => $order_fields,
60 - ),
61 - 'direction' => array(
62 - 'description' => 'Direction of ordered results',
63 - 'type' => 'enum',
64 - 'default' => 'desc',
65 - 'enum' => array( 'asc', 'desc' ),
66 - ),
67 - 'per_page' => array(
68 - 'description' => 'Number of results per page',
69 - 'type' => 'integer',
70 - 'default' => 25,
71 - 'minimum' => 5,
72 - 'maximum' => RED_MAX_PER_PAGE,
73 - ),
74 - 'page' => array(
75 - 'description' => 'Page offset',
76 - 'type' => 'integer',
77 - 'minimum' => 0,
78 - 'default' => 0,
79 - ),
80 - );
79 + public function ajax_import_data( $params ) {
80 + $params = $this->get_params( $params );
81 + $upload = isset( $_FILES[ 'file' ] ) ? $_FILES[ 'file' ] : false;
82 + $group_id = isset( $params['group'] ) ? intval( $params['group'], 10 ) : 0;
83 +
84 + $result = $this->getError( 'Invalid file', __LINE__ );
85 + if ( $upload && is_uploaded_file( $upload['tmp_name'] ) ) {
86 + $result = $this->getError( 'Invalid group', __LINE__ );
87 +
88 + $count = Red_FileIO::import( $group_id, $upload );
89 + if ( $count !== false ) {
90 + $result = array(
91 + 'imported' => $count,
92 + );
93 + }
94 + }
95 +
96 + return $this->output_ajax_response( $result );
81 97 }
82 98
83 - public function register_bulk( $namespace, $route, $filters, $orders, $callback ) {
84 - register_rest_route( $namespace, $route, array(
85 - $this->get_route( WP_REST_Server::EDITABLE, $callback ),
86 - 'args' => array_merge( $this->get_filter_args( $filters, $orders ), array(
87 - 'items' => array(
88 - 'description' => 'Comma separated list of item IDs to perform action on',
89 - 'type' => 'string|integer',
90 - 'required' => true,
91 - ),
92 - ) ),
99 + public function ajax_export_data( $params ) {
100 + $params = $this->get_params( $params );
101 + $moduleId = isset( $params['module'] ) ? intval( $params['module'], 10 ) : false;
102 + $format = 'json';
103 +
104 + if ( isset( $params['format'] ) && in_array( $params['format'], array( 'csv', 'apache', 'nginx', 'json' ) ) ) {
105 + $format = $params['format'];
106 + }
107 +
108 + $result = $this->getError( 'Invalid module', __LINE__ );
109 +
110 + $export = Red_FileIO::export( $moduleId, $format );
111 + if ( $export !== false ) {
112 + $result = array(
113 + 'data' => $export['data'],
114 + 'total' => $export['total'],
115 + );
116 + }
117 +
118 + return $this->output_ajax_response( $result );
119 + }
120 +
121 + public function ajax_group_action( $params ) {
122 + $params = $this->get_params( $params );
123 +
124 + $action = false;
125 + $items = array();
126 + if ( isset( $params['items'] ) ) {
127 + $items = array_map( 'intval', explode( ',', $params['items'] ) );
128 + }
129 +
130 + if ( isset( $params['bulk'] ) && in_array( $params['bulk'], array( 'delete', 'enable', 'disable' ) ) ) {
131 + $action = $params['bulk'];
132 +
133 + foreach ( $items as $item ) {
134 + $group = Red_Group::get( intval( $item, 10 ) );
135 +
136 + if ( $group ) {
137 + if ( $action === 'delete' ) {
138 + $group->delete();
139 + } else if ( $action === 'disable' ) {
140 + $group->disable();
141 + } else if ( $action === 'enable' ) {
142 + $group->enable();
143 + }
144 + }
145 + }
146 + }
147 +
148 + return $this->output_ajax_response( Red_Group::get_filtered( $params ) );
149 + }
150 +
151 + public function ajax_get_group( $params ) {
152 + $params = $this->get_params( $params );
153 +
154 + return $this->output_ajax_response( Red_Group::get_filtered( $params ) );
155 + }
156 +
157 + public function ajax_set_group( $params ) {
158 + $params = $this->get_params( $params );
159 +
160 + $groupId = 0;
161 + $name = '';
162 + $moduleId = 0;
163 + if ( isset( $params['id'] ) ) {
164 + $groupId = intval( $params['id'], 10 );
165 + }
166 +
167 + $result = $this->getError( 'Invalid group or parameters', __LINE__ );
168 + if ( $groupId > 0 ) {
169 + $group = Red_Group::get( $groupId );
170 +
171 + if ( $group && isset( $params['name'] ) && isset( $params['moduleId'] ) ) {
172 + if ( $group->update( $params ) ) {
173 + $result = array( 'item' => $group->to_json() );
174 + }
175 + }
176 + } else {
177 + $group = Red_Group::create( isset( $params['name'] ) ? $params['name'] : '', isset( $params['moduleId'] ) ? $params['moduleId'] : 0 );
178 +
179 + if ( $group ) {
180 + $result = Red_Group::get_filtered( $params );
181 + }
182 + }
183 +
184 + return $this->output_ajax_response( $result );
185 + }
186 +
187 + public function ajax_get_redirect( $params ) {
188 + $params = $this->get_params( $params );
189 +
190 + return $this->output_ajax_response( Red_Item::get_filtered( $params ) );
191 + }
192 +
193 + public function ajax_set_redirect( $params ) {
194 + $params = $this->get_params( $params );
195 +
196 + $redirectId = 0;
197 + if ( isset( $params['id'] ) ) {
198 + $redirectId = intval( $params['id'], 10 );
199 + }
200 +
201 + $result = $this->getError( 'Invalid redirect details', __LINE__ );
202 + if ( $redirectId === 0 ) {
203 + $redirect = Red_Item::create( $params );
204 +
205 + if ( is_wp_error( $redirect ) ) {
206 + $result = $this->getError( $redirect->get_error_message(), __LINE__ );
207 + } else {
208 + $result = Red_Item::get_filtered( $params );
209 + }
210 + } else {
211 + $redirect = Red_Item::get_by_id( $redirectId );
212 +
213 + if ( $redirect ) {
214 + $result = $redirect->update( $params );
215 +
216 + if ( is_wp_error( $result ) ) {
217 + $result = $this->getError( $result->get_error_message(), __LINE__ );
218 + } else {
219 + $result = array( 'item' => $redirect->to_json() );
220 + }
221 + }
222 + }
223 +
224 + return $this->output_ajax_response( $result );
225 + }
226 +
227 + public function ajax_redirect_action( $params ) {
228 + $params = $this->get_params( $params );
229 +
230 + $action = false;
231 + $items = array();
232 +
233 + if ( isset( $params['items'] ) ) {
234 + $items = array_map( 'intval', explode( ',', $params['items'] ) );
235 + }
236 +
237 + if ( isset( $params['bulk'] ) && in_array( $params['bulk'], array( 'delete', 'enable', 'disable', 'reset' ) ) ) {
238 + $action = $params['bulk'];
239 +
240 + foreach ( $items as $item ) {
241 + $redirect = Red_Item::get_by_id( intval( $item, 10 ) );
242 +
243 + if ( $redirect ) {
244 + if ( $action === 'delete' ) {
245 + $redirect->delete();
246 + } else if ( $action === 'disable' ) {
247 + $redirect->disable();
248 + } else if ( $action === 'enable' ) {
249 + $redirect->enable();
250 + } else if ( $action === 'reset' ) {
251 + $redirect->reset();
252 + }
253 + }
254 + }
255 + }
256 +
257 + return $this->output_ajax_response( Red_Item::get_filtered( $params ) );
258 + }
259 +
260 + public function ajax_delete_plugin() {
261 + $plugin = Redirection_Admin::init();
262 + $plugin->plugin_uninstall();
263 +
264 + $current = get_option( 'active_plugins' );
265 + array_splice( $current, array_search( basename( dirname( REDIRECTION_FILE ) ).'/'.basename( REDIRECTION_FILE ), $current ), 1 );
266 + update_option( 'active_plugins', $current );
267 +
268 + return $this->output_ajax_response( array( 'location' => admin_url().'plugins.php' ) );
269 + }
270 +
271 + public function ajax_load_settings() {
272 + return $this->output_ajax_response( array(
273 + 'settings' => red_get_options(),
274 + 'groups' => $this->groups_to_json( Red_Group::get_for_select() ),
275 + 'installed' => get_home_path(),
93 276 ) );
94 277 }
95 -}
96 278
97 -class Redirection_Api {
98 - private static $instance = null;
99 - private $routes = array();
279 + public function ajax_save_settings( $settings = array() ) {
280 + red_set_options( $this->get_params( $settings ) );
100 281
101 - static function init() {
102 - if ( is_null( self::$instance ) ) {
103 - self::$instance = new Redirection_Api();
282 + return $this->ajax_load_settings();
283 + }
284 +
285 + public function ajax_get_logs( $params ) {
286 + $params = $this->get_params( $params );
287 + $result = $this->get_logs( $params );
288 +
289 + return $this->output_ajax_response( $result );
290 + }
291 +
292 + public function ajax_log_action( $params ) {
293 + $params = $this->get_params( $params );
294 +
295 + // Do the action
296 + if ( isset( $params['bulk'] ) && isset( $params['items'] ) && $params['bulk'] === 'delete' ) {
297 + $items = explode( ',', $params['items'] );
298 +
299 + if ( $this->get_log_type( $params ) === 'log' ) {
300 + array_map( array( 'RE_Log', 'delete' ), $items );
301 + } else {
302 + array_map( array( 'RE_404', 'delete' ), $items );
303 + }
104 304 }
105 305
106 - return self::$instance;
306 + $result = $this->get_logs( $params );
307 +
308 + return $this->output_ajax_response( $result );
107 309 }
108 310
109 - public function __construct() {
110 - global $wpdb;
311 + public function ajax_delete_all( $params ) {
312 + $params = $this->get_params( $params );
313 + $filter = '';
314 + $filterBy = '';
315 + if ( isset( $params['filter'] ) ) {
316 + $filter = $params['filter'];
317 + }
111 318
112 - $wpdb->hide_errors();
319 + if ( isset( $params['filterBy'] ) && in_array( $params['filterBy'], array( 'url', 'ip', 'url-exact' ), true ) ) {
320 + $filterBy = $params['filterBy'];
321 + unset( $params['filter'] );
322 + unset( $params['filterBy'] );
323 + }
113 324
114 - $this->routes[] = new Redirection_Api_Redirect( REDIRECTION_API_NAMESPACE );
115 - $this->routes[] = new Redirection_Api_Group( REDIRECTION_API_NAMESPACE );
116 - $this->routes[] = new Redirection_Api_Log( REDIRECTION_API_NAMESPACE );
117 - $this->routes[] = new Redirection_Api_404( REDIRECTION_API_NAMESPACE );
118 - $this->routes[] = new Redirection_Api_Settings( REDIRECTION_API_NAMESPACE );
119 - $this->routes[] = new Redirection_Api_Plugin( REDIRECTION_API_NAMESPACE );
120 - $this->routes[] = new Redirection_Api_Import( REDIRECTION_API_NAMESPACE );
121 - $this->routes[] = new Redirection_Api_Export( REDIRECTION_API_NAMESPACE );
325 + if ( isset( $params['logType'] ) ) {
326 + if ( $params['logType'] === 'log' ) {
327 + RE_Log::delete_all( $filterBy, $filter );
328 + } else {
329 + RE_404::delete_all( $filterBy, $filter );
330 + }
331 + }
332 +
333 + $result = $this->get_logs( $params );
334 +
335 + return $this->output_ajax_response( $result );
336 + }
337 +
338 + public function ajax_plugin_status( $params ) {
339 + $params = $this->get_params( $params );
340 +
341 + $fixit = false;
342 + if ( isset( $params['fixIt'] ) && $params['fixIt'] ) {
343 + $fixit = true;
344 + }
345 +
346 + include_once dirname( REDIRECTION_FILE ).'/models/fixer.php';
347 +
348 + $fixer = new Red_Fixer();
349 + $result = $fixer->get_status();
350 +
351 + if ( $fixit ) {
352 + $result = $fixer->fix( $result );
353 + }
354 +
355 + return $this->output_ajax_response( $result );
356 + }
357 +
358 + public function ajax_get_importers( $params ) {
359 + include_once dirname( __FILE__ ).'/models/importer.php';
360 +
361 + $params = $this->get_params( $params );
362 +
363 + if ( isset( $params['plugin'] ) ) {
364 + $groups = Red_Group::get_all();
365 + $result = array( 'imported' => Red_Plugin_Importer::import( $params['plugin'], $groups[ 0 ]['id'] ) );
366 + } else {
367 + $result = array( 'importers' => Red_Plugin_Importer::get_plugins() );
368 + }
369 +
370 + return $this->output_ajax_response( $result );
371 + }
372 +
373 + private function get_log_type( $params ) {
374 + $type = 'log';
375 +
376 + if ( isset( $params['logType'] ) && in_array( $params['logType'], array( 'log', '404' ), true ) ) {
377 + $type = $params['logType'];
378 + }
379 +
380 + return $type;
381 + }
382 +
383 + private function get_logs( array $params ) {
384 + $type = $this->get_log_type( $params );
385 +
386 + if ( $type === 'log' ) {
387 + return RE_Filter_Log::get( 'redirection_logs', 'RE_Log', $params );
388 + } else if ( $type === '404' ) {
389 + if ( isset( $params['filterBy'] ) && isset( $params['filter'] ) && $params['filterBy'] === 'ip' ) {
390 + $params['filter'] = ip2long( $params['filter'] );
391 + }
392 +
393 + return RE_Filter_Log::get( 'redirection_404', 'RE_404', $params );
394 + }
395 +
396 + return array( 'items' => array(), 'total' => 0 );
397 + }
398 +
399 + private function groups_to_json( $groups, $depth = 0 ) {
400 + $items = array();
401 +
402 + foreach ( $groups as $text => $value ) {
403 + if ( is_array( $value ) && $depth === 0 ) {
404 + $items[] = (object)array( 'text' => $text, 'value' => $this->groups_to_json( $value, 1 ) );
405 + } else {
406 + $items[] = (object)array( 'text' => $value, 'value' => $text );
407 + }
408 + }
409 +
410 + return $items;
411 + }
412 +
413 + private function output_ajax_response( $data ) {
414 + $data = $this->addDatabaseError( $data );
415 + $result = wp_json_encode( $data );
416 +
417 + if ( defined( 'DOING_AJAX' ) ) {
418 + header( 'Content-Type: application/json' );
419 + echo $result;
420 + wp_die();
421 + }
422 +
423 + return $result;
424 + }
425 +
426 + private function user_has_access() {
427 + return current_user_can( apply_filters( 'redirection_role', 'administrator' ) );
122 428 }
123 429 }