Version Description
(Feb. 13, 2015) = * Use home_url() instead of site_url(). Props swalkinshaw * Don't redirect if redirect to location is invalid. Props vaurdan * Redirection plugin importer. Props eugene-manuilov
Download this release
Release Info
Developer | tlovett1 |
Plugin | Safe Redirect Manager |
Version | 1.7.6 |
Comparing to | |
See all releases |
Code changes from version 1.7.5 to 1.7.6
- .gitignore +0 -1
- assets/banner-772x250.png +0 -0
- assets/icon-256x256.png +0 -0
- inc/wp-cli.php +70 -2
- readme.txt +7 -2
- safe-redirect-manager.php +83 -5
- tests/test-core.php +79 -34
.gitignore
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
.svn
|
|
assets/banner-772x250.png
DELETED
Binary file
|
assets/icon-256x256.png
DELETED
Binary file
|
inc/wp-cli.php
CHANGED
@@ -132,7 +132,7 @@ class Safe_Redirect_Manager_CLI extends WP_CLI_Command {
|
|
132 |
$created = 0;
|
133 |
$skipped = 0;
|
134 |
foreach( $pieces as $piece ) {
|
135 |
-
|
136 |
// Ignore if this line isn't a redirect
|
137 |
if ( ! preg_match( '/^Redirect( permanent)?/i', $piece ) )
|
138 |
continue;
|
@@ -141,7 +141,7 @@ class Safe_Redirect_Manager_CLI extends WP_CLI_Command {
|
|
141 |
$redirect = preg_replace( '/\s{2,}/', ' ', $piece );
|
142 |
$redirect = preg_replace( '/^Redirect( permanent)? (.*)$/i', '$2', trim( $redirect ) );
|
143 |
$redirect = explode( ' ', $redirect );
|
144 |
-
|
145 |
// if there are three parts to the redirect, we assume the first part is a status code
|
146 |
if ( 2 == count( $redirect ) ) {
|
147 |
$from = $redirect[0];
|
@@ -176,5 +176,73 @@ class Safe_Redirect_Manager_CLI extends WP_CLI_Command {
|
|
176 |
WP_CLI::success( "All done! {$created} redirects were created, {$skipped} were skipped" );
|
177 |
}
|
178 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
179 |
|
180 |
}
|
132 |
$created = 0;
|
133 |
$skipped = 0;
|
134 |
foreach( $pieces as $piece ) {
|
135 |
+
|
136 |
// Ignore if this line isn't a redirect
|
137 |
if ( ! preg_match( '/^Redirect( permanent)?/i', $piece ) )
|
138 |
continue;
|
141 |
$redirect = preg_replace( '/\s{2,}/', ' ', $piece );
|
142 |
$redirect = preg_replace( '/^Redirect( permanent)? (.*)$/i', '$2', trim( $redirect ) );
|
143 |
$redirect = explode( ' ', $redirect );
|
144 |
+
|
145 |
// if there are three parts to the redirect, we assume the first part is a status code
|
146 |
if ( 2 == count( $redirect ) ) {
|
147 |
$from = $redirect[0];
|
176 |
WP_CLI::success( "All done! {$created} redirects were created, {$skipped} were skipped" );
|
177 |
}
|
178 |
|
179 |
+
/**
|
180 |
+
* Imports redirects from CSV file.
|
181 |
+
*
|
182 |
+
* ## OPTIONS
|
183 |
+
*
|
184 |
+
* <file>
|
185 |
+
* : Path to one or more valid CSV file for import. This file should contain
|
186 |
+
* redirection from and to URLs, regex flag and HTTP redirection code. Here
|
187 |
+
* is example table:
|
188 |
+
*
|
189 |
+
* | source | target | regex | code |
|
190 |
+
* |----------------------------|--------------------|-------|------|
|
191 |
+
* | /legacy-url | /new-url | 0 | 301 |
|
192 |
+
* | /category-1 | /new-category-slug | 0 | 302 |
|
193 |
+
* | /tes?t/[0-9]+/path/[^/]+/? | /go/here | 1 | 302 |
|
194 |
+
* | ... | ... | ... | ... |
|
195 |
+
*
|
196 |
+
* You can also use exported redirects from "Redirection" plugin, which you
|
197 |
+
* can download here: /wp-admin/tools.php?page=redirection.php&sub=modules
|
198 |
+
*
|
199 |
+
* <source-column>
|
200 |
+
* : Header title for sources column mapping.
|
201 |
+
*
|
202 |
+
* <target-column>
|
203 |
+
* : Header title for target column mapping.
|
204 |
+
*
|
205 |
+
* <regex-column>
|
206 |
+
* : Header title for regex column mapping.
|
207 |
+
*
|
208 |
+
* <code-column>
|
209 |
+
* : Header title for code column mapping.
|
210 |
+
*
|
211 |
+
* ## EXAMPLE
|
212 |
+
*
|
213 |
+
* wp safe-redirect-manager import redirections.csv
|
214 |
+
*
|
215 |
+
* @synopsis <file> [--source=<source-column>] [--target=<target-column>] [--regex=<regex-column>] [--code=<code-column>]
|
216 |
+
*
|
217 |
+
* @since 1.7.6
|
218 |
+
*
|
219 |
+
* @access public
|
220 |
+
* @global SRM_Safe_Redirect_Manager $safe_redirect_manager The plugin instance.
|
221 |
+
* @param array $args The array of input files.
|
222 |
+
* @param array $assoc_args The array of column mappings.
|
223 |
+
*/
|
224 |
+
public function import( $args, $assoc_args ) {
|
225 |
+
global $safe_redirect_manager;
|
226 |
+
|
227 |
+
$mapping = wp_parse_args( $assoc_args, array(
|
228 |
+
'source' => 'source',
|
229 |
+
'target' => 'target',
|
230 |
+
'regex' => 'regex',
|
231 |
+
'code' => 'code',
|
232 |
+
) );
|
233 |
+
|
234 |
+
$created = $skipped = 0;
|
235 |
+
foreach ( $args as $file ) {
|
236 |
+
$processed = $safe_redirect_manager->import_file( $file, $mapping );
|
237 |
+
if ( ! empty( $processed ) ) {
|
238 |
+
$created += $processed['created'];
|
239 |
+
$skipped += $processed['skipped'];
|
240 |
+
|
241 |
+
WP_CLI::success( basename( $file ) . ' file processed successfully.' );
|
242 |
+
}
|
243 |
+
}
|
244 |
+
|
245 |
+
WP_CLI::success( "All done! {$created} redirects were imported, {$skipped} were skipped" );
|
246 |
+
}
|
247 |
|
248 |
}
|
readme.txt
CHANGED
@@ -2,8 +2,8 @@
|
|
2 |
Contributors: tlovett1, tollmanz, taylorde, 10up, jakemgold, danielbachhuber, VentureBeat
|
3 |
Tags: http redirects, redirect manager, url redirection, safe http redirection, multisite redirects
|
4 |
Requires at least: 3.1
|
5 |
-
Tested up to: 4.
|
6 |
-
Stable tag: 1.7.
|
7 |
|
8 |
Safely and easily manage your website's HTTP redirects.
|
9 |
|
@@ -24,6 +24,11 @@ Extract the zip file and just drop the contents in the wp-content/plugins/ direc
|
|
24 |
|
25 |
== Changelog ==
|
26 |
|
|
|
|
|
|
|
|
|
|
|
27 |
= 1.7.5 (Sept. 9, 2014) =
|
28 |
* Don't always lowercase matched parts in redirect to replace. Props[francescolaffi](https://github.com/francescolaffi)
|
29 |
* Plugin icon/banner
|
2 |
Contributors: tlovett1, tollmanz, taylorde, 10up, jakemgold, danielbachhuber, VentureBeat
|
3 |
Tags: http redirects, redirect manager, url redirection, safe http redirection, multisite redirects
|
4 |
Requires at least: 3.1
|
5 |
+
Tested up to: 4.2
|
6 |
+
Stable tag: 1.7.6
|
7 |
|
8 |
Safely and easily manage your website's HTTP redirects.
|
9 |
|
24 |
|
25 |
== Changelog ==
|
26 |
|
27 |
+
= 1.7.6 (Feb. 13, 2015) =
|
28 |
+
* Use home_url() instead of site_url(). Props [swalkinshaw](https://github.com/swalkinshaw)
|
29 |
+
* Don't redirect if redirect to location is invalid. Props [vaurdan](https://github.com/vaurdan)
|
30 |
+
* Redirection plugin importer. Props [eugene-manuilov](https://github.com/eugene-manuilov)
|
31 |
+
|
32 |
= 1.7.5 (Sept. 9, 2014) =
|
33 |
* Don't always lowercase matched parts in redirect to replace. Props[francescolaffi](https://github.com/francescolaffi)
|
34 |
* Plugin icon/banner
|
safe-redirect-manager.php
CHANGED
@@ -4,7 +4,7 @@ Plugin Name: Safe Redirect Manager
|
|
4 |
Plugin URI: http://www.10up.com
|
5 |
Description: Easily and safely manage HTTP redirects.
|
6 |
Author: Taylor Lovett (10up)
|
7 |
-
Version: 1.7.
|
8 |
Author URI: http://www.10up.com
|
9 |
|
10 |
GNU General Public License, Free Software Foundation <http://creativecommons.org/licenses/GPL/2.0/>
|
@@ -805,9 +805,9 @@ class SRM_Safe_Redirect_Manager {
|
|
805 |
* If WordPress resides in a directory that is not the public root, we have to chop
|
806 |
* the pre-WP path off the requested path.
|
807 |
*/
|
808 |
-
$
|
809 |
-
if ( isset( $
|
810 |
-
$requested_path = preg_replace( '@' . $
|
811 |
}
|
812 |
|
813 |
// Allow redirects to be filtered
|
@@ -834,6 +834,10 @@ class SRM_Safe_Redirect_Manager {
|
|
834 |
$status_code = $redirect['status_code'];
|
835 |
$enable_regex = ( isset( $redirect['enable_regex'] ) ) ? $redirect['enable_regex'] : false;
|
836 |
|
|
|
|
|
|
|
|
|
837 |
// check if requested path is the same as the redirect from path
|
838 |
if ( $enable_regex ) {
|
839 |
$matched_path = preg_match( '@' . $redirect_from . '@' . $regex_flag, $requested_path );
|
@@ -977,7 +981,81 @@ class SRM_Safe_Redirect_Manager {
|
|
977 |
|
978 |
return home_url( $redirect_from );
|
979 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
980 |
}
|
981 |
|
982 |
global $safe_redirect_manager;
|
983 |
-
$safe_redirect_manager = new SRM_Safe_Redirect_Manager();
|
4 |
Plugin URI: http://www.10up.com
|
5 |
Description: Easily and safely manage HTTP redirects.
|
6 |
Author: Taylor Lovett (10up)
|
7 |
+
Version: 1.7.6
|
8 |
Author URI: http://www.10up.com
|
9 |
|
10 |
GNU General Public License, Free Software Foundation <http://creativecommons.org/licenses/GPL/2.0/>
|
805 |
* If WordPress resides in a directory that is not the public root, we have to chop
|
806 |
* the pre-WP path off the requested path.
|
807 |
*/
|
808 |
+
$parsed_home_url = parse_url( home_url() );
|
809 |
+
if ( isset( $parsed_home_url['path'] ) && '/' != $parsed_home_url['path'] ) {
|
810 |
+
$requested_path = preg_replace( '@' . $parsed_home_url['path'] . '@i', '', $requested_path, 1 );
|
811 |
}
|
812 |
|
813 |
// Allow redirects to be filtered
|
834 |
$status_code = $redirect['status_code'];
|
835 |
$enable_regex = ( isset( $redirect['enable_regex'] ) ) ? $redirect['enable_regex'] : false;
|
836 |
|
837 |
+
// check if the redirection destination is valid, otherwise just skip it
|
838 |
+
if ( empty( $redirect_to ) )
|
839 |
+
continue;
|
840 |
+
|
841 |
// check if requested path is the same as the redirect from path
|
842 |
if ( $enable_regex ) {
|
843 |
$matched_path = preg_match( '@' . $redirect_from . '@' . $regex_flag, $requested_path );
|
981 |
|
982 |
return home_url( $redirect_from );
|
983 |
}
|
984 |
+
|
985 |
+
/**
|
986 |
+
* Imports redirects from CSV file or stream.
|
987 |
+
*
|
988 |
+
* @since 1.7.6
|
989 |
+
*
|
990 |
+
* @access public
|
991 |
+
* @param string|resource $file File path, file pointer or stream to read redirects from.
|
992 |
+
* @param array $args The array of arguments. Includes column mapping and CSV settings.
|
993 |
+
* @return array Returns importing statistic on success, otherwise FALSE.
|
994 |
+
*/
|
995 |
+
public function import_file( $file, $args ) {
|
996 |
+
$handle = $file;
|
997 |
+
$close_handle = false;
|
998 |
+
$doing_wp_cli = defined( 'WP_CLI' ) && WP_CLI;
|
999 |
+
|
1000 |
+
// filter arguments
|
1001 |
+
$args = apply_filters( 'srm_import_file_args', $args );
|
1002 |
+
|
1003 |
+
// enable line endings auto detection
|
1004 |
+
@ini_set( 'auto_detect_line_endings', true );
|
1005 |
+
|
1006 |
+
// open file pointer if $file is not a resource
|
1007 |
+
if ( ! is_resource( $file ) ) {
|
1008 |
+
$handle = fopen( $file, 'rb' );
|
1009 |
+
if ( ! $handle ) {
|
1010 |
+
$doing_wp_cli && WP_CLI::error( sprintf( "Error retrieving %s file", basename( $file ) ) );
|
1011 |
+
return false;
|
1012 |
+
}
|
1013 |
+
|
1014 |
+
$close_handle = true;
|
1015 |
+
}
|
1016 |
+
|
1017 |
+
// process all rows of the file
|
1018 |
+
$created = $skipped = 0;
|
1019 |
+
$headers = fgetcsv( $handle );
|
1020 |
+
while( ( $row = fgetcsv( $handle ) ) ) {
|
1021 |
+
// validate
|
1022 |
+
$rule = array_combine( $headers, $row );
|
1023 |
+
if ( empty( $rule[$args['source']] ) || empty( $rule[$args['target']] ) ) {
|
1024 |
+
$doing_wp_cli && WP_CLI::warning( "Skipping - redirection rule is formatted improperly." );
|
1025 |
+
$skipped++;
|
1026 |
+
continue;
|
1027 |
+
}
|
1028 |
+
|
1029 |
+
// sanitize
|
1030 |
+
$redirect_from = $this->sanitize_redirect_from( $rule[$args['source']] );
|
1031 |
+
$redirect_to = $this->sanitize_redirect_to( $rule[$args['target']] );
|
1032 |
+
$status_code = ! empty( $rule[$args['code']] ) ? $rule[$args['code']] : 302;
|
1033 |
+
$regex = ! empty( $rule[$args['regex']] ) ? filter_var( $rule[$args['regex']], FILTER_VALIDATE_BOOLEAN ) : false;
|
1034 |
+
|
1035 |
+
// import
|
1036 |
+
$id = $this->create_redirect( $redirect_from, $redirect_to, $status_code, $regex );
|
1037 |
+
if ( is_wp_error( $id ) ) {
|
1038 |
+
$doing_wp_cli && WP_CLI::error( $id );
|
1039 |
+
$skipped++;
|
1040 |
+
} else {
|
1041 |
+
$doing_wp_cli && WP_CLI::line( "Success - Created redirect from '{$redirect_from}' to '{$redirect_to}'" );
|
1042 |
+
$created++;
|
1043 |
+
}
|
1044 |
+
}
|
1045 |
+
|
1046 |
+
// close an open file pointer if we've opened it
|
1047 |
+
if ( $close_handle ) {
|
1048 |
+
fclose( $handle );
|
1049 |
+
}
|
1050 |
+
|
1051 |
+
// return result statistic
|
1052 |
+
return array(
|
1053 |
+
'created' => $created,
|
1054 |
+
'skipped' => $skipped,
|
1055 |
+
);
|
1056 |
+
}
|
1057 |
+
|
1058 |
}
|
1059 |
|
1060 |
global $safe_redirect_manager;
|
1061 |
+
$safe_redirect_manager = new SRM_Safe_Redirect_Manager();
|
tests/test-core.php
CHANGED
@@ -396,44 +396,89 @@ class SRMTestCore extends WP_UnitTestCase {
|
|
396 |
$this->assertTrue( ! $redirected );
|
397 |
}
|
398 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
399 |
/**
|
400 |
-
*
|
|
|
|
|
401 |
*
|
402 |
-
* @
|
|
|
403 |
*/
|
404 |
-
public function
|
405 |
global $safe_redirect_manager;
|
406 |
|
407 |
-
// with
|
408 |
-
$
|
409 |
-
|
410 |
-
$
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
$
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
//
|
424 |
-
$
|
425 |
-
$
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
}
|
|
|
439 |
}
|
396 |
$this->assertTrue( ! $redirected );
|
397 |
}
|
398 |
|
399 |
+
/**
|
400 |
+
* Test that replace (both wildcard and regex) doesn't change the casing on the matched part
|
401 |
+
*
|
402 |
+
* @since 1.7.5
|
403 |
+
*/
|
404 |
+
public function testReplaceCasing() {
|
405 |
+
global $safe_redirect_manager;
|
406 |
+
|
407 |
+
// with wildcard
|
408 |
+
$_SERVER['REQUEST_URI'] = '/myfiles1/FooBar.JPEG';
|
409 |
+
$redirected = false;
|
410 |
+
$redirect_to = '/images1/*';
|
411 |
+
$safe_redirect_manager->create_redirect( '/myfiles1/*', $redirect_to );
|
412 |
+
|
413 |
+
add_action( 'srm_do_redirect', function( $requested_path, $redirected_to, $status_code ) use ( &$redirect_to, &$redirected ) {
|
414 |
+
if ( $redirected_to === '/images1/FooBar.JPEG' ) {
|
415 |
+
$redirected = true;
|
416 |
+
}
|
417 |
+
}, 10, 3 );
|
418 |
+
|
419 |
+
$safe_redirect_manager->action_parse_request();
|
420 |
+
|
421 |
+
$this->assertTrue( $redirected );
|
422 |
+
|
423 |
+
// with regex
|
424 |
+
$_SERVER['REQUEST_URI'] = '/myfiles2/FooBar.JPEG';
|
425 |
+
$redirected = false;
|
426 |
+
$redirect_to = '/images2/$1';
|
427 |
+
$safe_redirect_manager->create_redirect( '/myfiles2/(.*\.jpe?g)', $redirect_to, 301, true );
|
428 |
+
|
429 |
+
add_action( 'srm_do_redirect', function( $requested_path, $redirected_to, $status_code ) use ( &$redirect_to, &$redirected ) {
|
430 |
+
if ( $redirected_to === '/images2/FooBar.JPEG' ) {
|
431 |
+
$redirected = true;
|
432 |
+
}
|
433 |
+
}, 10, 3 );
|
434 |
+
|
435 |
+
$safe_redirect_manager->action_parse_request();
|
436 |
+
|
437 |
+
$this->assertTrue( $redirected );
|
438 |
+
}
|
439 |
+
|
440 |
/**
|
441 |
+
* Tests import redirects from file.
|
442 |
+
*
|
443 |
+
* @since 1.7.6
|
444 |
*
|
445 |
+
* @access public
|
446 |
+
* @global SRM_Safe_Redirect_Manager $safe_redirect_manager The plugin instance.
|
447 |
*/
|
448 |
+
public function testFileImport() {
|
449 |
global $safe_redirect_manager;
|
450 |
|
451 |
+
// create temp file and fill up it with redirects
|
452 |
+
$tmp_file = tmpfile();
|
453 |
+
|
454 |
+
$redirects = array(
|
455 |
+
// headers
|
456 |
+
array( 'http code', 'legacy url', 'new url', 'is_regex' ),
|
457 |
+
// redirects
|
458 |
+
array( 302, '/some-url', '/new-url', 0 ),
|
459 |
+
array( 301, '/broken-url', '/fixed-url', 0 ),
|
460 |
+
array( 301, '/reg?ex/\d+/path', '/go/here', 1 ),
|
461 |
+
);
|
462 |
+
|
463 |
+
foreach ( $redirects as $row ) {
|
464 |
+
fputcsv( $tmp_file, $row );
|
465 |
+
}
|
466 |
+
|
467 |
+
// let's import it
|
468 |
+
fseek( $tmp_file, 0 );
|
469 |
+
$processed = $safe_redirect_manager->import_file( $tmp_file, array(
|
470 |
+
'source' => 'legacy url',
|
471 |
+
'target' => 'new url',
|
472 |
+
'regex' => 'is_regex',
|
473 |
+
'code' => 'http code',
|
474 |
+
) );
|
475 |
+
|
476 |
+
// assert results
|
477 |
+
$this->assertTrue( is_array( $processed ) && ! empty( $processed['created'] ) );
|
478 |
+
$this->assertEquals( count( $redirects ) - 1, $processed['created'] );
|
479 |
+
|
480 |
+
// close temp file
|
481 |
+
fclose( $tmp_file );
|
482 |
}
|
483 |
+
|
484 |
}
|