Resolve double redirects automatically
And test that it does so.
This commit is contained in:
parent
75cf6e4e77
commit
c3fd28afaf
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "fwdekker/death-notifier",
|
||||
"description": "Get notified when a famous person dies.",
|
||||
"version": "0.19.10", "_comment_version": "Also update version in `package.json`!",
|
||||
"version": "0.19.11", "_comment_version": "Also update version in `package.json`!",
|
||||
"type": "project",
|
||||
"license": "MIT",
|
||||
"homepage": "https://git.fwdekker.com/tools/death-notifier",
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "death-notifier",
|
||||
"version": "0.19.10", "_comment_version": "Also update version in `composer.json`!",
|
||||
"version": "0.19.11", "_comment_version": "Also update version in `composer.json`!",
|
||||
"description": "Get notified when a famous person dies.",
|
||||
"author": "Florine W. Dekker",
|
||||
"browser": "dist/bundle.js",
|
||||
|
|
|
@ -408,7 +408,7 @@
|
|||
<small id="delete-account-email-hint" data-hint-for="delete-account-email"></small>
|
||||
|
||||
<input type="checkbox" role="switch" id="delete-account-confirm" />
|
||||
<label for="delete-account-confirm">I want to permanently delete my account</label>
|
||||
<label for="delete-account-confirm">I want to permanently delete my account.</label>
|
||||
<br />
|
||||
<small id="delete-account-confirm-hint" data-hint-for="delete-account-confirm"></small>
|
||||
<br /><br />
|
||||
|
|
|
@ -19,22 +19,12 @@ class Redirects implements IteratorAggregate
|
|||
/**
|
||||
* @var array<string, string> the known redirects
|
||||
*/
|
||||
private readonly array $redirects;
|
||||
private array $redirects = [];
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new `Redirects`.
|
||||
*
|
||||
* @param array<string, string> $redirects the redirects to start with
|
||||
*/
|
||||
public function __construct(array $redirects = [])
|
||||
{
|
||||
$this->redirects = $redirects;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a single redirect, and returns a new `Redirects` containing the current redirects and the new redirects.
|
||||
* Adds new redirects and resolves double redirects, and returns a new `Redirects` containing the old and new
|
||||
* redirects.
|
||||
*
|
||||
* If there already exists a redirect `a -> b`, and the redirect `b -> c` is added, then `a -> b` is changed to
|
||||
* `a -> c`.
|
||||
|
@ -43,18 +33,24 @@ class Redirects implements IteratorAggregate
|
|||
* `a -> c`.
|
||||
*
|
||||
* @param array<string, string> $redirects the redirects to add
|
||||
* @return Redirects a new `Redirects` containing the current redirects and the new redirects
|
||||
* @return Redirects a new `Redirects` containing the old and new redirects
|
||||
*/
|
||||
public function add_redirects(array $redirects): Redirects
|
||||
public function add(array $redirects): Redirects
|
||||
{
|
||||
$new_redirects = $this->redirects;
|
||||
$all_redirects = $this->redirects;
|
||||
|
||||
foreach ($redirects as $from => $to) {
|
||||
$already_redirected = array_search($from, $new_redirects);
|
||||
$new_redirects[$already_redirected === false ? $from : $already_redirected] = $to;
|
||||
$to_redirects_to = $all_redirects[$to] ?? $to;
|
||||
$all_redirects[$from] = $to_redirects_to;
|
||||
|
||||
$redirects_to_from = array_keys($all_redirects, $from);
|
||||
foreach ($redirects_to_from as $redirect_to_from)
|
||||
$all_redirects[$redirect_to_from] = $to_redirects_to;
|
||||
}
|
||||
|
||||
return new Redirects($new_redirects);
|
||||
$new_object = new Redirects();
|
||||
$new_object->redirects = $all_redirects;
|
||||
return $new_object;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,7 +61,7 @@ class Redirects implements IteratorAggregate
|
|||
*/
|
||||
public function resolve(string $from): string
|
||||
{
|
||||
return !isset($this->redirects[$from]) ? $from : $this->redirects[$from];
|
||||
return $this->redirects[$from] ?? $from;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -133,14 +133,14 @@ class Wikipedia
|
|||
array_map(fn($it) => strval($it), array_column($response["normalized"] ?? [], "from")),
|
||||
array_map(fn($it) => strval($it), array_column($response["normalized"] ?? [], "to"))
|
||||
);
|
||||
$redirects = $redirects->add_redirects($new_normalizations);
|
||||
$redirects = $redirects->add($new_normalizations);
|
||||
|
||||
$new_redirects =
|
||||
array_combine(
|
||||
array_map(fn($it) => strval($it), array_column($response["redirects"] ?? [], "from")),
|
||||
array_map(fn($it) => strval($it), array_column($response["redirects"] ?? [], "to"))
|
||||
);
|
||||
$redirects = $redirects->add_redirects($new_redirects);
|
||||
$redirects = $redirects->add($new_redirects);
|
||||
}
|
||||
|
||||
return new QueryOutput($articles, $redirects, $missing);
|
||||
|
@ -220,7 +220,7 @@ class Wikipedia
|
|||
|
||||
return new QueryOutput(
|
||||
array_replace($output_base->results, $output_of_moves->results),
|
||||
$output_base->redirects->add_redirects($moves),
|
||||
$output_base->redirects->add($moves),
|
||||
$not_moved
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
<?php
|
||||
|
||||
namespace com\fwdekker\deathnotifier\wikipedia;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
|
||||
/**
|
||||
* Unit tests for {@see Redirects}.
|
||||
*/
|
||||
class RedirectsTest extends TestCase
|
||||
{
|
||||
public function test_resolve_returns_key_if_empty(): void
|
||||
{
|
||||
$redirects = new Redirects();
|
||||
|
||||
self::assertEquals("does-not-exist", $redirects->resolve("does-not-exist"));
|
||||
}
|
||||
|
||||
public function test_resolve_returns_key_if_key_not_added(): void
|
||||
{
|
||||
$redirects = new Redirects();
|
||||
$redirects = $redirects->add(["from" => "to"]);
|
||||
|
||||
self::assertEquals("does-not-exist", $redirects->resolve("does-not-exist"));
|
||||
}
|
||||
|
||||
public function test_resolve_returns_target_if_key_added(): void
|
||||
{
|
||||
$redirects = new Redirects();
|
||||
$redirects = $redirects->add(["from" => "to"]);
|
||||
|
||||
self::assertEquals("to", $redirects->resolve("from"));
|
||||
}
|
||||
|
||||
public function test_resolve_returns_new_target_if_key_overridden(): void
|
||||
{
|
||||
$redirects = new Redirects();
|
||||
$redirects = $redirects->add(["from" => "to"]);
|
||||
|
||||
$redirects = $redirects->add(["from" => "new"]);
|
||||
|
||||
self::assertEquals("new", $redirects->resolve("from"));
|
||||
}
|
||||
|
||||
|
||||
public function test_add_does_not_alter_old_object(): void
|
||||
{
|
||||
$redirects = new Redirects();
|
||||
$redirects = $redirects->add(["from" => "to"]);
|
||||
|
||||
$new_redirects = $redirects->add(["from" => "new"]);
|
||||
|
||||
self::assertEquals("to", $redirects->resolve("from"));
|
||||
self::assertEquals("new", $new_redirects->resolve("from"));
|
||||
}
|
||||
|
||||
public function test_add_inserts_new_key(): void
|
||||
{
|
||||
$redirects = new Redirects();
|
||||
|
||||
$redirects = $redirects->add(["from" => "to"]);
|
||||
|
||||
self::assertEquals("to", $redirects->resolve("from"));
|
||||
}
|
||||
|
||||
public function test_add_inserts_multiple_new_keys(): void
|
||||
{
|
||||
$redirects = new Redirects();
|
||||
|
||||
$redirects = $redirects->add(["a" => "one", "b" => "two", "c" => "three"]);
|
||||
|
||||
self::assertEquals("one", $redirects->resolve("a"));
|
||||
self::assertEquals("two", $redirects->resolve("b"));
|
||||
self::assertEquals("three", $redirects->resolve("c"));
|
||||
}
|
||||
|
||||
public function test_merges_ab_and_bc_to_ac(): void
|
||||
{
|
||||
$redirects = new Redirects();
|
||||
|
||||
$redirects = $redirects->add([
|
||||
"a" => "b",
|
||||
"b" => "c",
|
||||
]);
|
||||
|
||||
self::assertEquals("c", $redirects->resolve("a"));
|
||||
self::assertEquals("c", $redirects->resolve("b"));
|
||||
self::assertEquals("c", $redirects->resolve("c"));
|
||||
}
|
||||
|
||||
public function test_merges_bc_and_ab_to_ac(): void
|
||||
{
|
||||
$redirects = new Redirects();
|
||||
|
||||
$redirects = $redirects->add([
|
||||
"b" => "c",
|
||||
"a" => "b",
|
||||
]);
|
||||
|
||||
self::assertEquals("c", $redirects->resolve("a"));
|
||||
self::assertEquals("c", $redirects->resolve("b"));
|
||||
self::assertEquals("c", $redirects->resolve("c"));
|
||||
}
|
||||
|
||||
public function test_merges_ab_cd_and_bc_to_ad(): void
|
||||
{
|
||||
$redirects = new Redirects();
|
||||
|
||||
$redirects = $redirects->add([
|
||||
"a" => "b",
|
||||
"c" => "d",
|
||||
"b" => "c",
|
||||
]);
|
||||
|
||||
self::assertEquals("d", $redirects->resolve("a"));
|
||||
self::assertEquals("d", $redirects->resolve("b"));
|
||||
self::assertEquals("d", $redirects->resolve("c"));
|
||||
self::assertEquals("d", $redirects->resolve("d"));
|
||||
}
|
||||
|
||||
|
||||
public function test_has_non_reflexive_redirects_is_false_if_empty(): void
|
||||
{
|
||||
$redirects = new Redirects();
|
||||
|
||||
self::assertFalse($redirects->has_non_reflexive_redirects());
|
||||
}
|
||||
|
||||
public function test_has_non_reflexive_redirects_is_false_if_all_are_reflexive(): void
|
||||
{
|
||||
$redirects = new Redirects();
|
||||
$redirects = $redirects->add(["a" => "a", "b" => "b", "c" => "c"]);
|
||||
|
||||
self::assertFalse($redirects->has_non_reflexive_redirects());
|
||||
}
|
||||
|
||||
public function test_has_non_reflexive_redirects_is_true_if_all_are_non_reflexive(): void
|
||||
{
|
||||
$redirects = new Redirects();
|
||||
$redirects = $redirects->add(["a" => "one", "b" => "two", "c" => "three"]);
|
||||
|
||||
self::assertTrue($redirects->has_non_reflexive_redirects());
|
||||
}
|
||||
|
||||
public function test_has_non_reflexive_redirects_is_true_if_some_are_non_reflexive(): void
|
||||
{
|
||||
$redirects = new Redirects();
|
||||
$redirects = $redirects->add(["a" => "one", "self" => "self", "c" => "three"]);
|
||||
|
||||
self::assertTrue($redirects->has_non_reflexive_redirects());
|
||||
}
|
||||
|
||||
|
||||
public function test_iterator_iterates_over_all_redirects(): void
|
||||
{
|
||||
$inserted = ["a" => "one", "b" => "two", "c" => "three"];
|
||||
|
||||
$redirects = new Redirects();
|
||||
$redirects = $redirects->add($inserted);
|
||||
|
||||
$extracted = [];
|
||||
foreach ($redirects as $from => $to)
|
||||
$extracted[$from] = $to;
|
||||
|
||||
self::assertTrue($extracted === $inserted);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue