diff --git a/composer.json b/composer.json index fdb6459f..a09eafa0 100644 --- a/composer.json +++ b/composer.json @@ -71,7 +71,7 @@ "phpunit/phpunit": "^10.4", "roave/security-advisories": "dev-master", "shlinkio/php-coding-standard": "~2.3.0", - "shlinkio/shlink-test-utils": "^4.0", + "shlinkio/shlink-test-utils": "^4.1", "symfony/var-dumper": "^7.0", "veewee/composer-run-parallel": "^1.3" }, diff --git a/module/Core/src/RedirectRule/Entity/RedirectCondition.php b/module/Core/src/RedirectRule/Entity/RedirectCondition.php index 5f3de073..da235f9e 100644 --- a/module/Core/src/RedirectRule/Entity/RedirectCondition.php +++ b/module/Core/src/RedirectRule/Entity/RedirectCondition.php @@ -16,8 +16,8 @@ class RedirectCondition extends AbstractEntity private function __construct( public readonly string $name, private readonly RedirectConditionType $type, - public readonly string $matchValue, - public readonly ?string $matchKey = null, + private readonly string $matchValue, + private readonly ?string $matchKey = null, ) { } diff --git a/module/Core/src/RedirectRule/Entity/ShortUrlRedirectRule.php b/module/Core/src/RedirectRule/Entity/ShortUrlRedirectRule.php index 74a87930..9e84e4fb 100644 --- a/module/Core/src/RedirectRule/Entity/ShortUrlRedirectRule.php +++ b/module/Core/src/RedirectRule/Entity/ShortUrlRedirectRule.php @@ -19,7 +19,7 @@ class ShortUrlRedirectRule extends AbstractEntity private readonly ShortUrl $shortUrl, // No need to read this field. It's used by doctrine private readonly int $priority, public readonly string $longUrl, - public readonly Collection $conditions = new ArrayCollection(), + private Collection $conditions = new ArrayCollection(), ) { } diff --git a/module/Core/test-api/Action/RedirectTest.php b/module/Core/test-api/Action/RedirectTest.php index bbcc6fec..64c5fd95 100644 --- a/module/Core/test-api/Action/RedirectTest.php +++ b/module/Core/test-api/Action/RedirectTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace ShlinkioApiTest\Shlink\Core\Action; +use GuzzleHttp\RequestOptions; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase; @@ -15,9 +16,9 @@ use const ShlinkioTest\Shlink\IOS_USER_AGENT; class RedirectTest extends ApiTestCase { #[Test, DataProvider('provideUserAgents')] - public function properRedirectHappensBasedOnUserAgent(?string $userAgent, string $expectedRedirect): void + public function properRedirectHappensBasedOnUserAgent(array $options, string $expectedRedirect): void { - $response = $this->callShortUrl('def456', $userAgent); + $response = $this->callShortUrl('def456', $options); self::assertEquals(302, $response->getStatusCode()); self::assertEquals($expectedRedirect, $response->getHeaderLine('Location')); @@ -25,15 +26,48 @@ class RedirectTest extends ApiTestCase public static function provideUserAgents(): iterable { - yield 'android' => [ANDROID_USER_AGENT, 'https://blog.alejandrocelaya.com/android']; - yield 'ios' => [IOS_USER_AGENT, 'https://blog.alejandrocelaya.com/ios']; + yield 'android' => [ + [ + RequestOptions::HEADERS => ['User-Agent' => ANDROID_USER_AGENT], + ], + 'https://blog.alejandrocelaya.com/android', + ]; + yield 'ios' => [ + [ + RequestOptions::HEADERS => ['User-Agent' => IOS_USER_AGENT], + ], + 'https://blog.alejandrocelaya.com/ios', + ]; yield 'desktop' => [ - DESKTOP_USER_AGENT, + [ + RequestOptions::HEADERS => ['User-Agent' => DESKTOP_USER_AGENT], + ], 'https://blog.alejandrocelaya.com/2017/12/09/acmailer-7-0-the-most-important-release-in-a-long-time/', ]; yield 'unknown' => [ - null, + [], 'https://blog.alejandrocelaya.com/2017/12/09/acmailer-7-0-the-most-important-release-in-a-long-time/', ]; + yield 'rule: english and foo' => [ + [ + RequestOptions::HEADERS => [ + 'Accept-Language' => 'en-UK', + ], + RequestOptions::QUERY => ['foo' => 'bar'], + ], + 'https://example.com/english-and-foo-query?foo=bar', + ]; + yield 'rule: multiple query params' => [ + [ + RequestOptions::QUERY => ['foo' => 'bar', 'hello' => 'world'], + ], + 'https://example.com/multiple-query-params?foo=bar&hello=world', + ]; + yield 'rule: english' => [ + [ + RequestOptions::HEADERS => ['Accept-Language' => 'en-UK'], + ], + 'https://example.com/only-english', + ]; } } diff --git a/module/Rest/test-api/Fixtures/ShortUrlRedirectRulesFixture.php b/module/Rest/test-api/Fixtures/ShortUrlRedirectRulesFixture.php new file mode 100644 index 00000000..8f40af7d --- /dev/null +++ b/module/Rest/test-api/Fixtures/ShortUrlRedirectRulesFixture.php @@ -0,0 +1,62 @@ +getReference('def456_short_url'); + + $englishCondition = RedirectCondition::forLanguage('en-UK'); + $manager->persist($englishCondition); + + $fooQueryCondition = RedirectCondition::forQueryParam('foo', 'bar'); + $manager->persist($fooQueryCondition); + + $helloQueryCondition = RedirectCondition::forQueryParam('hello', 'world'); + $manager->persist($helloQueryCondition); + + $englishAndFooQueryRule = new ShortUrlRedirectRule( + $defShortUrl, + 1, + 'https://example.com/english-and-foo-query', + new ArrayCollection([$englishCondition, $fooQueryCondition]), + ); + $manager->persist($englishAndFooQueryRule); + + $multipleQueryParamsRule = new ShortUrlRedirectRule( + $defShortUrl, + 2, + 'https://example.com/multiple-query-params', + new ArrayCollection([$helloQueryCondition, $fooQueryCondition]), + ); + $manager->persist($multipleQueryParamsRule); + + $onlyEnglishRule = new ShortUrlRedirectRule( + $defShortUrl, + 3, + 'https://example.com/only-english', + new ArrayCollection([$englishCondition]), + ); + $manager->persist($onlyEnglishRule); + + $manager->flush(); + } +}