Skip to content

Commit

Permalink
Merge pull request #341 from 10up/fix/86v2
Browse files Browse the repository at this point in the history
fix/86: Display starting vertices whenever a redirect cycle/loop is present
  • Loading branch information
Sidsector9 committed Aug 29, 2023
2 parents 563be0b + cc11274 commit 92b575e
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 20 deletions.
47 changes: 34 additions & 13 deletions inc/classes/class-srm-loop-detection.php
Expand Up @@ -62,7 +62,10 @@ private static function get_directed_graph() {
}

// Add an edge from the source URL to the destination URL.
$graph[ $source_url ][] = $destination_url;
$graph[ $source_url ][] = array(
'id' => $redirect['ID'],
'destination' => $destination_url,
);
}
}

Expand All @@ -78,27 +81,25 @@ private static function get_directed_graph() {
* @param string $vertex Node in the graph that holds URL of source or destination.
* @param array $visited Array of nodes visited during traversal.
* @param array $current_path Array of paths traversed.
* @param array $cycle_source Array of starting point of detected cycles.
*
* @return boolean
* @return void
*/
private static function has_cycle_recursive( $graph, $vertex, &$visited, &$current_path ) {
private static function has_cycle_recursive( $graph, $vertex, &$visited, &$current_path, &$cycle_source ) {
$visited[ $vertex ] = true;
$current_path[ $vertex ] = true;

if ( isset( $graph[ $vertex ] ) ) {
foreach ( $graph[ $vertex ] as $neighbor ) {
if ( ! isset( $visited[ $neighbor ] ) ) {
if ( self::has_cycle_recursive( $graph, $neighbor, $visited, $current_path ) ) {
return true;
}
} elseif ( isset( $current_path[ $neighbor ] ) ) {
return true;
if ( ! isset( $visited[ $neighbor['destination'] ] ) ) {
self::has_cycle_recursive( $graph, $neighbor['destination'], $visited, $current_path, $cycle_source );
} elseif ( isset( $current_path[ $neighbor['destination'] ] ) ) {
$cycle_source[] = $neighbor;
}
}
}

unset( $current_path[ $vertex ] );
return false;
}

/**
Expand All @@ -110,15 +111,35 @@ public static function detect_redirect_loops() {
$graph = self::get_directed_graph();
$visited = array();
$current_path = array();
$cycle_source = array();

foreach ( $graph as $vertex => $destinations ) {
if ( ! isset( $visited[ $vertex ] ) ) {
if ( self::has_cycle_recursive( $graph, $vertex, $visited, $current_path ) ) {
return true;
if ( self::has_cycle_recursive( $graph, $vertex, $visited, $current_path, $cycle_source ) ) {
return $cycle_source;
}
}
}

return false;
return $cycle_source;
}

/**
* Returns an array of "Redirect From" values that are the starting vertices of redirect loops.
*
* @param array $cycle_source Array of redirect loops.
*
* @return array
*/
public static function get_cycle_source( $cycle_source = array() ) {
return array_map(
function( $source ) {
return array(
'path' => wp_parse_url( esc_url( $source['destination'] ), PHP_URL_PATH ),
'id' => $source['id'],
);
},
$cycle_source
);
}
}
31 changes: 24 additions & 7 deletions inc/classes/class-srm-post-type.php
Expand Up @@ -231,14 +231,31 @@ public function action_redirect_chain_alert() {
if ( $this->is_plugin_page() ) {

/**
* check_for_possible_redirect_loops() runs in best case Theta(n^2) so if you have 100 redirects, this method
* will be running slow. Let's disable it by default.
* Hook to toggle check for redirect loop.
*
* @param boolean $enable_loop_detection Detects redirect loop if true.
*/
if ( apply_filters( 'srm_check_for_possible_redirect_loops', false ) ) {
if ( SRM_Loop_Detection::detect_redirect_loops() ) {
if ( apply_filters( 'srm_check_for_possible_redirect_loops', true ) ) {
$cycle_source = SRM_Loop_Detection::detect_redirect_loops();
$paths = SRM_Loop_Detection::get_cycle_source( $cycle_source );

if ( ! empty( $cycle_source ) ) {
?>
<div class="notice notice-warning">
<p><?php esc_html_e( 'Safe Redirect Manager Warning: Possible redirect loops and/or chains have been created.', 'safe-redirect-manager' ); ?></p>
<p><?php esc_html_e( 'Safe Redirect Manager Warning: The following redirects with the "Redirect To" value have created redirect chain/loops.', 'safe-redirect-manager' ); ?></p>
<ul style="list-style: inside;">
<?php foreach ( $paths as $path ) : ?>
<li>
<?php
printf(
'<a href="%s">%s</a>',
esc_url( get_edit_post_link( esc_html( $path['id'] ) ) ),
esc_html( $path['path'] )
);
?>
</li>
<?php endforeach; ?>
</ul style>
</div>
<?php
}
Expand Down Expand Up @@ -710,8 +727,8 @@ public function load_resources() {
'redirectjs',
'redirectValidation',
array(
'urlError' => __( 'There are some issues validating the URL. Please try again.', 'safe-redirect-manager' ),
'fail' => __( 'There is an existing redirect with the same Redirect From URL. You may <a href="%s">Edit</a> the redirect or try other `from` URL.', 'safe-redirect-manager' ),
'urlError' => __( 'There are some issues validating the URL. Please try again.', 'safe-redirect-manager' ),
'fail' => __( 'There is an existing redirect with the same Redirect From URL. You may <a href="%s">Edit</a> the redirect or try other `from` URL.', 'safe-redirect-manager' ),
'ajax_url' => admin_url( 'admin-ajax.php' ),
'ajax_nonce' => wp_create_nonce( 'srm_autocomplete_nonce' ),
)
Expand Down

0 comments on commit 92b575e

Please sign in to comment.