PluginProbe
Redirection / 5.3.7
Redirection v5.3.7
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
redirection / redirection-admin.php

redirection-admin.php in Redirection 5.3.7, at redirection-admin.php

738 lines 23.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 require_once __DIR__ . '/models/group.php';
4 require_once __DIR__ . '/models/monitor.php';
5 require_once __DIR__ . '/models/file-io.php';
6 require_once __DIR__ . '/database/database.php';
7 require_once __DIR__ . '/redirection-capabilities.php';
8
9 define( 'RED_DEFAULT_PER_PAGE', 25 );
10 define( 'RED_MAX_PER_PAGE', 200 );
11
12 class Redirection_Admin {
13 private static $instance = null;
14 private $monitor;
15 private $fixit_failed = false;
16
17 public static function init() {
18 if ( is_null( self::$instance ) ) {
19 self::$instance = new Redirection_Admin();
20 }
21
22 return self::$instance;
23 }
24
25 public function __construct() {
26 add_action( 'admin_menu', [ $this, 'admin_menu' ] );
27 add_action( 'admin_notices', [ $this, 'update_nag' ] );
28 add_filter( 'plugin_action_links_' . basename( dirname( REDIRECTION_FILE ) ) . '/' . basename( REDIRECTION_FILE ), [ $this, 'plugin_settings' ], 10, 4 );
29 add_filter( 'plugin_row_meta', [ $this, 'plugin_row_meta' ], 10, 4 );
30 add_filter( 'redirection_save_options', [ $this, 'flush_schedule' ] );
31 add_filter( 'set-screen-option', [ $this, 'set_per_page' ], 10, 3 );
32 add_filter( 'set_screen_option_redirection_log_per_page', function( $ignore, $option, $value ) {
33 return $value;
34 }, 10, 3 );
35 add_action( 'redirection_redirect_updated', [ $this, 'set_default_group' ], 10, 2 );
36 add_action( 'redirection_redirect_updated', [ $this, 'clear_cache' ], 10, 2 );
37 add_filter( 'load_script_translation_file', [ $this, 'load_script_translation_file' ], 10, 3 );
38
39 if ( defined( 'REDIRECTION_FLYING_SOLO' ) && REDIRECTION_FLYING_SOLO ) {
40 add_filter( 'script_loader_src', [ $this, 'flying_solo' ], 10, 2 );
41 }
42
43 register_deactivation_hook( REDIRECTION_FILE, [ 'Redirection_Admin', 'plugin_deactivated' ] );
44 register_uninstall_hook( REDIRECTION_FILE, [ 'Redirection_Admin', 'plugin_uninstall' ] );
45
46 $this->monitor = new Red_Monitor( red_get_options() );
47 $this->run_hacks();
48 }
49
50 /**
51 * Massage the Redirection WP translations.
52 *
53 * @param string $file File.
54 * @param string $handle File.
55 * @param string $domain File.
56 * @return string
57 */
58 public function load_script_translation_file( $file, $handle, $domain ) {
59 if ( $domain === 'redirection' ) {
60 return preg_replace( '/-\w*\.json$/', '.json', $file );
61 }
62
63 return $file;
64 }
65
66 // These are only called on the single standard site, or in the network admin of the multisite - they run across all available sites
67 public static function plugin_activated() {
68 Red_Database::apply_to_sites( function() {
69 Red_Flusher::clear();
70 red_set_options();
71 } );
72 }
73
74 // These are only called on the single standard site, or in the network admin of the multisite - they run across all available sites
75 public static function plugin_deactivated() {
76 Red_Database::apply_to_sites( function() {
77 Red_Flusher::clear();
78 } );
79 }
80
81 // These are only called on the single standard site, or in the network admin of the multisite - they run across all available sites
82 public static function plugin_uninstall() {
83 $database = Red_Database::get_latest_database();
84
85 Red_Database::apply_to_sites( function() use ( $database ) {
86 $database->remove();
87 } );
88 }
89
90 /**
91 * Show the database upgrade nag
92 *
93 * @return void
94 */
95 public function update_nag() {
96 $options = red_get_options();
97
98 // Is the site configured to upgrade automatically?
99 if ( $options['plugin_update'] === 'admin' ) {
100 $this->automatic_upgrade();
101 return;
102 }
103
104 // Can the user perform a manual database upgrade?
105 if ( ! Redirection_Capabilities::has_access( Redirection_Capabilities::CAP_OPTION_MANAGE ) ) {
106 return;
107 }
108
109 // Default manual update, with nag
110 $status = new Red_Database_Status();
111
112 $message = false;
113 if ( $status->needs_installing() ) {
114 /* translators: 1: URL to plugin page */
115 $message = sprintf( __( 'Please complete your <a href="%s">Redirection setup</a> to activate the plugin.', 'redirection' ), esc_url( $this->get_plugin_url() ) );
116 } elseif ( $status->needs_updating() ) {
117 /* translators: 1: URL to plugin page, 2: current version, 3: target version */
118 $message = sprintf( __( 'Redirection\'s database needs to be updated - <a href="%1$1s">click to update</a>.', 'redirection' ), esc_url( $this->get_plugin_url() ) );
119 }
120
121 if ( ! $message || strpos( Redirection_Request::get_request_url(), 'page=redirection.php' ) !== false ) {
122 return;
123 }
124
125 // Known HTML and so isn't escaped
126 // phpcs:ignore
127 echo '<div class="update-nag notice notice-warning" style="width: 95%">' . $message . '</div>';
128 }
129
130 /**
131 * Perform an automatic DB upgrade
132 *
133 * @return void
134 */
135 private function automatic_upgrade() {
136 $loop = 0;
137 $status = new Red_Database_Status();
138 $database = new Red_Database();
139
140 // Loop until the DB is upgraded, or until a max is exceeded (just in case)
141 while ( $loop < 20 ) {
142 if ( ! $status->needs_updating() ) {
143 break;
144 }
145
146 $database->apply_upgrade( $status );
147
148 if ( $status->is_error() ) {
149 // If an error occurs then switch to 'prompt' mode and let the user deal with it.
150 red_set_options( [ 'plugin_update' => 'prompt' ] );
151 return;
152 }
153
154 $loop++;
155 }
156 }
157
158 // So it finally came to this... some plugins include their JS in all pages, whether they are needed or not. If there is an error
159 // then this can prevent Redirection running and it's a little sensitive about that. We use the nuclear option here to disable
160 // all other JS while viewing Redirection
161 public function flying_solo( $src, $handle ) {
162 $request = Redirection_Request::get_request_url();
163
164 if ( strpos( $request, 'page=redirection.php' ) !== false ) {
165 if ( substr( $src, 0, 4 ) === 'http' && $handle !== 'redirection' && strpos( $src, 'plugins' ) !== false ) {
166 if ( $this->ignore_this_plugin( $src ) ) {
167 return false;
168 }
169 }
170 }
171
172 return $src;
173 }
174
175 private function ignore_this_plugin( $src ) {
176 $ignore = array(
177 'mootools',
178 'wp-seo-',
179 'authenticate',
180 'wordpress-seo',
181 'yikes',
182 );
183
184 foreach ( $ignore as $text ) {
185 if ( strpos( $src, $text ) !== false ) {
186 return true;
187 }
188 }
189
190 return false;
191 }
192
193 public function flush_schedule( $options ) {
194 Red_Flusher::schedule();
195 return $options;
196 }
197
198 public function set_per_page( $status, $option, $value ) {
199 if ( $option === 'redirection_log_per_page' ) {
200 $value = max( 1, min( intval( $value, 10 ), RED_MAX_PER_PAGE ) );
201 return $value;
202 }
203
204 return $status;
205 }
206
207 public function plugin_settings( $links ) {
208 $status = new Red_Database_Status();
209 if ( $status->needs_updating() ) {
210 array_unshift( $links, '<a style="color: red" href="' . esc_url( $this->get_plugin_url() ) . '&amp;sub=support">' . __( 'Upgrade Database', 'redirection' ) . '</a>' );
211 }
212
213 array_unshift( $links, '<a href="' . esc_url( $this->get_plugin_url() ) . '&amp;sub=options">' . __( 'Settings', 'redirection' ) . '</a>' );
214 return $links;
215 }
216
217 public function plugin_row_meta( $plugin_meta, $plugin_file, $plugin_data, $status ) {
218 if ( $plugin_file === basename( dirname( REDIRECTION_FILE ) ) . '/' . basename( REDIRECTION_FILE ) ) {
219 $plugin_data['Description'] .= '<p>' . __( 'Please upgrade your database', 'redirection' ) . '</p>';
220 }
221
222 return $plugin_meta;
223 }
224
225 private function get_plugin_url() {
226 return admin_url( 'tools.php?page=' . basename( REDIRECTION_FILE ) );
227 }
228
229 private function get_first_available_page_url() {
230 $pages = Redirection_Capabilities::get_available_pages();
231
232 if ( count( $pages ) > 0 ) {
233 return $this->get_plugin_url() . ( $pages[0] === 'redirect' ? '' : '&sub=' . rawurlencode( $pages[0] ) );
234 }
235
236 return admin_url();
237 }
238
239 private function get_query( $name ) {
240 if ( isset( $_GET[ $name ] ) ) {
241 return sanitize_text_field( $_GET[ $name ] );
242 }
243
244 return null;
245 }
246
247 public function redirection_head() {
248 global $wp_version;
249
250 // Does user have access to this page?
251 if ( $this->get_current_page() === false ) {
252 // Redirect to root plugin page
253 wp_safe_redirect( $this->get_first_available_page_url() );
254 die();
255 }
256
257 if ( isset( $_REQUEST['action'] ) && isset( $_REQUEST['_wpnonce'] ) && is_string( $_REQUEST['action'] ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'wp_rest' ) ) {
258 $action = sanitize_text_field( $_REQUEST['action'] );
259
260 if ( $action === 'fixit' ) {
261 $this->run_fixit();
262 } elseif ( $action === 'rest_api' ) {
263 $this->set_rest_api( intval( $_REQUEST['rest_api'], 10 ) );
264 }
265 }
266
267 $build = REDIRECTION_VERSION . '-' . REDIRECTION_BUILD;
268 $preload = $this->get_preload_data();
269 $options = red_get_options();
270 $versions = array(
271 'Plugin: ' . REDIRECTION_VERSION . ' ' . REDIRECTION_DB_VERSION,
272 'WordPress: ' . $wp_version . ' (' . ( is_multisite() ? 'multi' : 'single' ) . ')',
273 'PHP: ' . phpversion(),
274 'Browser: ' . Redirection_Request::get_user_agent(),
275 'JavaScript: ' . plugin_dir_url( REDIRECTION_FILE ) . 'redirection.js?ver=' . $build,
276 'REST API: ' . red_get_rest_api(),
277 );
278
279 $this->inject();
280
281 // Add contextual help to some pages
282 if ( in_array( $this->get_current_page(), [ 'redirect', 'log', '404s', 'groups' ], true ) ) {
283 add_screen_option( 'per_page', array(
284 /* translators: maximum number of log entries */
285 'label' => sprintf( __( 'Log entries (%d max)', 'redirection' ), RED_MAX_PER_PAGE ),
286 'default' => RED_DEFAULT_PER_PAGE,
287 'option' => 'redirection_log_per_page',
288 ) );
289 }
290
291 if ( defined( 'REDIRECTION_DEV_MODE' ) && REDIRECTION_DEV_MODE ) {
292 wp_enqueue_script( 'redirection', 'http://localhost:3312/redirection.js', array(), $build, true );
293 } else {
294 wp_enqueue_script( 'redirection', plugin_dir_url( REDIRECTION_FILE ) . 'redirection.js', array(), $build, true );
295 }
296
297 wp_enqueue_style( 'redirection', plugin_dir_url( REDIRECTION_FILE ) . 'redirection.css', array(), $build );
298
299 $is_new = false;
300 $major_version = implode( '.', array_slice( explode( '.', REDIRECTION_VERSION ), 0, 2 ) );
301
302 if ( $this->get_query( 'page' ) === 'redirection.php' && strpos( REDIRECTION_VERSION, '-beta' ) === false ) {
303 $is_new = version_compare( $options['update_notice'], $major_version ) < 0;
304 }
305
306 $status = new Red_Database_Status();
307 $status->check_tables_exist();
308
309 // Fix some sites having a version set to +OK - not sure why
310 if ( isset( $options['database'] ) && $options['database'] === '+OK' ) {
311 red_set_options( [ 'database' => REDIRECTION_DB_VERSION ] );
312 $status->stop_update();
313 }
314
315 $translations = $this->get_i18n_data();
316
317 wp_localize_script( 'redirection', 'Redirectioni10n', array(
318 'api' => [
319 'WP_API_root' => esc_url_raw( red_get_rest_api() ),
320 'WP_API_nonce' => wp_create_nonce( 'wp_rest' ),
321 'site_health' => admin_url( 'site-health.php' ),
322 'current' => $options['rest_api'],
323 'routes' => [
324 REDIRECTION_API_JSON => red_get_rest_api( REDIRECTION_API_JSON ),
325 REDIRECTION_API_JSON_INDEX => red_get_rest_api( REDIRECTION_API_JSON_INDEX ),
326 REDIRECTION_API_JSON_RELATIVE => red_get_rest_api( REDIRECTION_API_JSON_RELATIVE ),
327 ],
328 ],
329 'pluginBaseUrl' => plugins_url( '', REDIRECTION_FILE ),
330 'pluginRoot' => $this->get_plugin_url(),
331 'per_page' => $this->get_per_page(),
332 'locale' => implode( '-', array_slice( explode( '-', str_replace( '_', '-', get_locale() ) ), 0, 2 ) ),
333 'settings' => $options,
334 'preload' => $preload,
335 'versions' => implode( "\n", $versions ),
336 'version' => REDIRECTION_VERSION,
337 'database' => $status->get_json(),
338 'caps' => [
339 'pages' => Redirection_Capabilities::get_available_pages(),
340 'capabilities' => Redirection_Capabilities::get_all_capabilities(),
341 ],
342 'update_notice' => $is_new ? $major_version : false,
343 ) );
344
345 wp_set_script_translations( 'redirection', 'redirection', plugin_dir_path( __FILE__ ) . 'locale/json/' );
346
347 $this->add_help_tab();
348 }
349
350 // Some plugins misbehave, so this attempts to 'fix' them so Redirection can get on with it's work
351 private function run_hacks() {
352 add_filter( 'ip-geo-block-admin', array( $this, 'ip_geo_block' ) );
353 }
354
355 /*
356 * This works around the IP Geo Block plugin being very aggressive and breaking Redirection
357 */
358 public function ip_geo_block( $validate ) {
359 $url = Redirection_Request::get_request_url();
360 $override = array(
361 'tools.php?page=redirection.php',
362 'action=red_proxy&rest_path=redirection',
363 );
364
365 foreach ( $override as $path ) {
366 if ( strpos( $url, $path ) !== false ) {
367 return array(
368 'result' => 'passed',
369 'auth' => false,
370 'asn' => false,
371 'code' => false,
372 'ip' => false,
373 );
374 }
375 }
376
377 return $validate;
378 }
379
380 private function run_fixit() {
381 if ( Redirection_Capabilities::has_access( Redirection_Capabilities::CAP_SUPPORT_MANAGE ) ) {
382 require_once dirname( REDIRECTION_FILE ) . '/models/fixer.php';
383
384 $fixer = new Red_Fixer();
385 $result = $fixer->fix( $fixer->get_status() );
386
387 if ( is_wp_error( $result ) ) {
388 $this->fixit_failed = $result;
389 }
390 }
391 }
392
393 private function set_rest_api( $api ) {
394 if ( $api >= 0 && $api <= REDIRECTION_API_JSON_RELATIVE ) {
395 red_set_options( array( 'rest_api' => intval( $api, 10 ) ) );
396 }
397 }
398
399 private function get_preload_data() {
400 $status = new Red_Database_Status();
401
402 if ( $status->needs_installing() ) {
403 include_once __DIR__ . '/models/importer.php';
404
405 return [
406 'importers' => Red_Plugin_Importer::get_plugins(),
407 ];
408 }
409
410 if ( $this->get_current_page() === 'support' ) {
411 require_once dirname( REDIRECTION_FILE ) . '/models/fixer.php';
412
413 $fixer = new Red_Fixer();
414
415 return array(
416 'pluginStatus' => $fixer->get_json(),
417 );
418 }
419
420 return [];
421 }
422
423 private function add_help_tab() {
424 /* translators: URL */
425 $content = sprintf( __( 'You can find full documentation about using Redirection on the <a href="%s" target="_blank">redirection.me</a> support site.', 'redirection' ), 'https://redirection.me/support/?utm_source=redirection&utm_medium=plugin&utm_campaign=context-help' );
426 $title = __( 'Redirection Support', 'redirection' );
427
428 $current_screen = get_current_screen();
429 $current_screen->add_help_tab( array(
430 'id' => 'redirection',
431 'title' => 'Redirection',
432 'content' => "<h2>$title</h2><p>$content</p>",
433 ) );
434 }
435
436 private function get_per_page() {
437 $per_page = intval( get_user_meta( get_current_user_id(), 'redirection_log_per_page', true ), 10 );
438
439 return $per_page > 0 ? max( 5, min( $per_page, RED_MAX_PER_PAGE ) ) : RED_DEFAULT_PER_PAGE;
440 }
441
442 private function get_i18n_data() {
443 $locale = get_locale();
444
445 // WP 4.7
446 if ( function_exists( 'get_user_locale' ) ) {
447 $locale = get_user_locale();
448 }
449
450 $i18n_json = dirname( REDIRECTION_FILE ) . '/locale/json/redirection-' . $locale . '.json';
451
452 if ( is_file( $i18n_json ) && is_readable( $i18n_json ) ) {
453 // phpcs:ignore
454 $locale_data = @file_get_contents( $i18n_json );
455
456 if ( $locale_data ) {
457 return json_decode( $locale_data, true );
458 }
459 }
460
461 // Return empty if we have nothing to return so it doesn't fail when parsed in JS
462 return array();
463 }
464
465 public function admin_menu() {
466 $hook = add_management_page( 'Redirection', 'Redirection', Redirection_Capabilities::get_plugin_access(), basename( REDIRECTION_FILE ), [ $this, 'admin_screen' ] );
467 add_action( 'load-' . $hook, [ $this, 'redirection_head' ] );
468 }
469
470 private function check_minimum_wp() {
471 $wp_version = get_bloginfo( 'version' );
472
473 if ( version_compare( $wp_version, REDIRECTION_MIN_WP, '<' ) ) {
474 return false;
475 }
476
477 return true;
478 }
479
480 /**
481 * Update the cache key when updating or creating a redirect
482 *
483 * @return void
484 */
485 public function clear_cache() {
486 $settings = red_get_options();
487
488 if ( $settings['cache_key'] > 0 ) {
489 red_set_options( [ 'cache_key' => time() ] );
490 }
491 }
492
493 public function set_default_group( $id, $redirect ) {
494 red_set_options( array( 'last_group_id' => $redirect->get_group_id() ) );
495 }
496
497 public function admin_screen() {
498 if ( count( Redirection_Capabilities::get_all_capabilities() ) === 0 ) {
499 die( 'You do not have sufficient permissions to access this page.' );
500 }
501
502 if ( $this->check_minimum_wp() === false ) {
503 return $this->show_minimum_wordpress();
504 }
505
506 if ( $this->fixit_failed ) {
507 $this->show_fixit_failed();
508 }
509
510 Red_Flusher::schedule();
511
512 $this->show_main();
513 }
514
515 private function show_fixit_failed() {
516 ?>
517 <div class="notice notice-error">
518 <h1><?php echo esc_html( $this->fixit_failed->get_error_message() ); ?></h1>
519 <p><?php echo esc_html( $this->fixit_failed->get_error_data() ); ?></p>
520 </div>
521 <?php
522 }
523
524 private function show_minimum_wordpress() {
525 global $wp_version;
526
527 /* translators: 1: Expected WordPress version, 2: Actual WordPress version */
528 $wp_requirement = sprintf( __( 'Redirection requires WordPress v%1$1s, you are using v%2$2s - please update your WordPress', 'redirection' ), REDIRECTION_MIN_WP, $wp_version );
529 ?>
530 <div class="react-error">
531 <h1><?php esc_html_e( 'Unable to load Redirection', 'redirection' ); ?></h1>
532 <p><?php echo esc_html( $wp_requirement ); ?></p>
533 </div>
534 <?php
535 }
536
537 private function show_load_fail() {
538 ?>
539 <div class="react-error" style="display: none">
540 <h1><?php esc_html_e( 'Unable to load Redirection ☹️', 'redirection' ); ?> v<?php echo esc_html( REDIRECTION_VERSION ); ?></h1>
541 <p><?php esc_html_e( "This may be caused by another plugin - look at your browser's error console for more details.", 'redirection' ); ?></p>
542 <p><?php esc_html_e( 'If you are using a page caching plugin or service (CloudFlare, OVH, etc) then you can also try clearing that cache.', 'redirection' ); ?></p>
543 <p><?php _e( 'Also check if your browser is able to load <code>redirection.js</code>:', 'redirection' ); ?></p>
544 <p><code><?php echo esc_html( plugin_dir_url( REDIRECTION_FILE ) . 'redirection.js?ver=' . rawurlencode( REDIRECTION_VERSION ) . '-' . rawurlencode( REDIRECTION_BUILD ) ); ?></code></p>
545 <p><?php esc_html_e( 'Please note that Redirection requires the WordPress REST API to be enabled. If you have disabled this then you won\'t be able to use Redirection', 'redirection' ); ?></p>
546 <p><?php _e( 'Please see the <a href="https://redirection.me/support/problems/">list of common problems</a>.', 'redirection' ); ?></p>
547 <p><?php esc_html_e( 'If you think Redirection is at fault then create an issue.', 'redirection' ); ?></p>
548 <p class="versions"><?php _e( '<code>Redirectioni10n</code> is not defined. This usually means another plugin is blocking Redirection from loading. Please disable all plugins and try again.', 'redirection' ); ?></p>
549 <p>
550 <a class="button-primary" target="_blank" href="https://github.com/johngodley/redirection/issues/new?title=Problem%20starting%20Redirection%20<?php echo esc_attr( REDIRECTION_VERSION ); ?>">
551 <?php esc_html_e( 'Create Issue', 'redirection' ); ?>
552 </a>
553 </p>
554 </div>
555 <?php
556 }
557
558 private function show_main() {
559 ?>
560 <div id="react-modal"></div>
561 <div id="react-ui">
562 <div class="react-loading">
563 <h1><?php esc_html_e( 'Loading, please wait...', 'redirection' ); ?></h1>
564
565 <span class="react-loading-spinner"></span>
566 </div>
567 <noscript><?php esc_html_e( 'Please enable JavaScript', 'redirection' ); ?></noscript>
568
569 <?php $this->show_load_fail(); ?>
570 </div>
571
572 <script>
573 var prevError = window.onerror;
574 var errors = [];
575 var timeout = 0;
576 var timer = setInterval( function() {
577 if ( isRedirectionLoaded() ) {
578 resetAll();
579 } else if ( errors.length > 0 || timeout++ === 5 ) {
580 showError();
581 }
582 }, 5000 );
583
584 function isRedirectionLoaded() {
585 return typeof redirection !== 'undefined';
586 }
587
588 function showError() {
589 var errorText = "";
590
591 if ( errors.length > 0 ) {
592 errorText = "```\n" + errors.join( ',' ) + "\n```\n\n";
593 }
594
595 resetAll();
596
597 if ( document.querySelector( '.react-loading' ) ) {
598 document.querySelector( '.react-loading' ).style.display = 'none';
599 document.querySelector( '.react-error' ).style.display = 'block';
600
601 if ( typeof Redirectioni10n !== 'undefined' && Redirectioni10n ) {
602 document.querySelector( '.versions' ).innerHTML = Redirectioni10n.versions.replace( /\n/g, '<br />' );
603 document.querySelector( '.react-error .button-primary' ).href += '&body=' + encodeURIComponent( errorText ) + encodeURIComponent( Redirectioni10n.versions );
604 }
605 } else {
606 document.querySelector( '#react-ui' ).innerHTML = '<p>Sorry something went very wrong.</p>';
607 }
608 }
609
610 function resetAll() {
611 clearInterval( timer );
612 window.onerror = prevError;
613 }
614
615 window.onerror = function( error, url, line ) {
616 console.error( error );
617 errors.push( error + ' ' + url + ' ' + line );
618 };
619 </script>
620 <?php
621 }
622
623 /**
624 * Get the current plugin page.
625 * Uses $_GET['sub'] to determine the current page unless a page is supplied.
626 *
627 * @param string $page Current page.
628 *
629 * @return string|boolean Current page, or false.
630 */
631 private function get_current_page( $page = false ) {
632 if ( ! $page ) {
633 // phpcs:ignore
634 $page = 'redirect';
635
636 if ( $this->get_query( 'sub' ) ) {
637 $page = $this->get_query( 'sub' );
638 }
639 }
640
641 // Are we allowed to access this page?
642 if ( in_array( $page, Redirection_Capabilities::get_available_pages(), true ) ) {
643 // phpcs:ignore
644 return $page;
645 }
646
647 return false;
648 }
649
650 private function inject() {
651 // phpcs:ignore
652 $page = false;
653 if ( $this->get_query( 'page' ) ) {
654 $page = $this->get_query( 'page' );
655 }
656
657 if ( $page && $this->get_current_page() !== 'redirect' && $page === 'redirection.php' ) {
658 $this->try_export_logs();
659 $this->try_export_redirects();
660 $this->try_export_rss();
661 }
662 }
663
664 public function try_export_rss() {
665 $token = $this->get_query( 'token' );
666 $sub = $this->get_query( 'sub' );
667
668 if ( $token && $sub === 'rss' && Redirection_Capabilities::has_access( Redirection_Capabilities::CAP_REDIRECT_MANAGE ) ) {
669 $options = red_get_options();
670
671 // phpcs:ignore
672 if ( $token === $options['token'] && ! empty( $options['token'] ) ) {
673 $module = $this->get_query( 'module' );
674
675 // phpcs:ignore
676 $items = Red_Item::get_all_for_module( intval( $module, 10 ) );
677
678 $exporter = Red_FileIO::create( 'rss' );
679 $exporter->force_download();
680
681 // phpcs:ignore
682 echo $exporter->get_data( $items, array() );
683 die();
684 }
685 }
686 }
687
688 private function try_export_logs() {
689 if ( Redirection_Capabilities::has_access( Redirection_Capabilities::CAP_IO_MANAGE ) && isset( $_POST['export-csv'] ) && check_admin_referer( 'wp_rest' ) ) {
690 if ( $this->get_current_page() === 'log' ) {
691 Red_Redirect_Log::export_to_csv();
692 } elseif ( $this->get_current_page() === '404s' ) {
693 Red_404_Log::export_to_csv();
694 }
695
696 die();
697 }
698 }
699
700 private function try_export_redirects() {
701 // phpcs:ignore
702 $sub = $this->get_query( 'sub' );
703 if ( $sub !== 'io' ) {
704 return;
705 }
706
707 $export = $this->get_query( 'export' );
708 $exporter = $this->get_query( 'exporter' );
709
710 if ( Redirection_Capabilities::has_access( Redirection_Capabilities::CAP_IO_MANAGE ) && $export && $exporter && check_admin_referer( 'wp_rest' ) ) {
711 $export = Red_FileIO::export( $export, $exporter );
712
713 if ( $export !== false ) {
714 $export['exporter']->force_download();
715
716 // This data is not displayed and will be downloaded to a file
717 echo str_replace( '&amp;', '&', wp_kses( $export['data'], 'strip' ) );
718 die();
719 }
720 }
721 }
722 }
723
724 register_activation_hook( REDIRECTION_FILE, array( 'Redirection_Admin', 'plugin_activated' ) );
725
726 add_action( 'init', array( 'Redirection_Admin', 'init' ) );
727
728 // This is causing a lot of problems with the REST API - disable qTranslate
729 add_filter( 'qtranslate_language_detect_redirect', function( $lang, $url ) {
730 $url = Redirection_Request::get_request_url();
731
732 if ( strpos( $url, '/wp-json/' ) !== false || strpos( $url, '?rest_route' ) !== false ) {
733 return false;
734 }
735
736 return $lang;
737 }, 10, 2 );
738