mirror of
https://github.com/shlinkio/shlink.git
synced 2024-10-22 20:25:35 +03:00
commit
16f64f6247
10 changed files with 119 additions and 44 deletions
9
.github/ISSUE_TEMPLATE/Bug.yml
vendored
9
.github/ISSUE_TEMPLATE/Bug.yml
vendored
|
@ -58,5 +58,10 @@ body:
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
attributes:
|
attributes:
|
||||||
label: How to reproduce
|
label: Minimum steps to reproduce
|
||||||
value: '<!-- Provide steps to reproduce the bug. -->'
|
value: |
|
||||||
|
<!--
|
||||||
|
Emphasis in MINIMUM: What is the simplest way to reproduce the bug?
|
||||||
|
Avoid things like "Create a kubernetes cluster", or anything related with cloud providers, as that is rarely the root cause and the bug may be closed as "not reproducible".
|
||||||
|
If you can provide a simple docker compose config, that's even better.
|
||||||
|
-->
|
||||||
|
|
18
CHANGELOG.md
18
CHANGELOG.md
|
@ -4,6 +4,24 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com), and this project adheres to [Semantic Versioning](https://semver.org).
|
The format is based on [Keep a Changelog](https://keepachangelog.com), and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
|
|
||||||
|
## [4.0.3] - 2024-03-15
|
||||||
|
### Added
|
||||||
|
* *Nothing*
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* *Nothing*
|
||||||
|
|
||||||
|
### Deprecated
|
||||||
|
* *Nothing*
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
* *Nothing*
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* [#2058](https://github.com/shlinkio/shlink/issues/2058) Fix DB credentials provided as env vars being casted to `int` if they include only numbers.
|
||||||
|
* [#2060](https://github.com/shlinkio/shlink/issues/2060) Fix error when trying to redirect to a non-http long URL.
|
||||||
|
|
||||||
|
|
||||||
## [4.0.2] - 2024-03-09
|
## [4.0.2] - 2024-03-09
|
||||||
### Added
|
### Added
|
||||||
* *Nothing*
|
* *Nothing*
|
||||||
|
|
|
@ -16,6 +16,10 @@ return (static function (): array {
|
||||||
'mssql' => 'pdo_sqlsrv',
|
'mssql' => 'pdo_sqlsrv',
|
||||||
default => 'pdo_mysql',
|
default => 'pdo_mysql',
|
||||||
};
|
};
|
||||||
|
$readCredentialAsString = static function (EnvVars $envVar): string|null {
|
||||||
|
$value = $envVar->loadFromEnv();
|
||||||
|
return $value === null ? null : (string) $value;
|
||||||
|
};
|
||||||
$resolveDefaultPort = static fn () => match ($driver) {
|
$resolveDefaultPort = static fn () => match ($driver) {
|
||||||
'postgres' => '5432',
|
'postgres' => '5432',
|
||||||
'mssql' => '1433',
|
'mssql' => '1433',
|
||||||
|
@ -28,6 +32,7 @@ return (static function (): array {
|
||||||
'postgres' => 'utf8',
|
'postgres' => 'utf8',
|
||||||
default => null,
|
default => null,
|
||||||
};
|
};
|
||||||
|
|
||||||
$resolveConnection = static fn () => match ($driver) {
|
$resolveConnection = static fn () => match ($driver) {
|
||||||
null, 'sqlite' => [
|
null, 'sqlite' => [
|
||||||
'driver' => 'pdo_sqlite',
|
'driver' => 'pdo_sqlite',
|
||||||
|
@ -36,8 +41,8 @@ return (static function (): array {
|
||||||
default => [
|
default => [
|
||||||
'driver' => $resolveDriver(),
|
'driver' => $resolveDriver(),
|
||||||
'dbname' => EnvVars::DB_NAME->loadFromEnv('shlink'),
|
'dbname' => EnvVars::DB_NAME->loadFromEnv('shlink'),
|
||||||
'user' => EnvVars::DB_USER->loadFromEnv(),
|
'user' => $readCredentialAsString(EnvVars::DB_USER),
|
||||||
'password' => EnvVars::DB_PASSWORD->loadFromEnv(),
|
'password' => $readCredentialAsString(EnvVars::DB_PASSWORD),
|
||||||
'host' => EnvVars::DB_HOST->loadFromEnv(EnvVars::DB_UNIX_SOCKET->loadFromEnv()),
|
'host' => EnvVars::DB_HOST->loadFromEnv(EnvVars::DB_UNIX_SOCKET->loadFromEnv()),
|
||||||
'port' => EnvVars::DB_PORT->loadFromEnv($resolveDefaultPort()),
|
'port' => EnvVars::DB_PORT->loadFromEnv($resolveDefaultPort()),
|
||||||
'unix_socket' => $isMysqlCompatible ? EnvVars::DB_UNIX_SOCKET->loadFromEnv() : null,
|
'unix_socket' => $isMysqlCompatible ? EnvVars::DB_UNIX_SOCKET->loadFromEnv() : null,
|
||||||
|
|
|
@ -17,7 +17,6 @@ function contains(mixed $value, array $array): bool
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array[] $multiArray
|
* @param array[] $multiArray
|
||||||
* @return array
|
|
||||||
*/
|
*/
|
||||||
function flatten(array $multiArray): array
|
function flatten(array $multiArray): array
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||||
namespace Shlinkio\Shlink\Core\ShortUrl\Helper;
|
namespace Shlinkio\Shlink\Core\ShortUrl\Helper;
|
||||||
|
|
||||||
use GuzzleHttp\Psr7\Query;
|
use GuzzleHttp\Psr7\Query;
|
||||||
use Laminas\Diactoros\Uri;
|
use GuzzleHttp\Psr7\Uri;
|
||||||
use Laminas\Stdlib\ArrayUtils;
|
use Laminas\Stdlib\ArrayUtils;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use Shlinkio\Shlink\Core\Options\TrackingOptions;
|
use Shlinkio\Shlink\Core\Options\TrackingOptions;
|
||||||
|
@ -30,16 +30,18 @@ readonly class ShortUrlRedirectionBuilder implements ShortUrlRedirectionBuilderI
|
||||||
$uri = new Uri($this->redirectionResolver->resolveLongUrl($shortUrl, $request));
|
$uri = new Uri($this->redirectionResolver->resolveLongUrl($shortUrl, $request));
|
||||||
$currentQuery = $request->getQueryParams();
|
$currentQuery = $request->getQueryParams();
|
||||||
$shouldForwardQuery = $shortUrl->forwardQuery();
|
$shouldForwardQuery = $shortUrl->forwardQuery();
|
||||||
|
$baseQueryString = $uri->getQuery();
|
||||||
|
$basePath = $uri->getPath();
|
||||||
|
|
||||||
return $uri
|
return $uri
|
||||||
->withQuery($shouldForwardQuery ? $this->resolveQuery($uri, $currentQuery) : $uri->getQuery())
|
->withQuery($shouldForwardQuery ? $this->resolveQuery($baseQueryString, $currentQuery) : $baseQueryString)
|
||||||
->withPath($this->resolvePath($uri, $extraPath))
|
->withPath($this->resolvePath($basePath, $extraPath))
|
||||||
->__toString();
|
->__toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function resolveQuery(Uri $uri, array $currentQuery): string
|
private function resolveQuery(string $baseQueryString, array $currentQuery): string
|
||||||
{
|
{
|
||||||
$hardcodedQuery = Query::parse($uri->getQuery());
|
$hardcodedQuery = Query::parse($baseQueryString);
|
||||||
|
|
||||||
$disableTrackParam = $this->trackingOptions->disableTrackParam;
|
$disableTrackParam = $this->trackingOptions->disableTrackParam;
|
||||||
if ($disableTrackParam !== null) {
|
if ($disableTrackParam !== null) {
|
||||||
|
@ -47,14 +49,13 @@ readonly class ShortUrlRedirectionBuilder implements ShortUrlRedirectionBuilderI
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want to merge preserving numeric keys, as some params might be numbers
|
// We want to merge preserving numeric keys, as some params might be numbers
|
||||||
$mergedQuery = ArrayUtils::merge($hardcodedQuery, $currentQuery, true);
|
$mergedQuery = ArrayUtils::merge($hardcodedQuery, $currentQuery, preserveNumericKeys: true);
|
||||||
|
|
||||||
return Query::build($mergedQuery);
|
return Query::build($mergedQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function resolvePath(Uri $uri, ?string $extraPath): string
|
private function resolvePath(string $basePath, ?string $extraPath): string
|
||||||
{
|
{
|
||||||
$hardcodedPath = $uri->getPath();
|
return $extraPath === null ? $basePath : sprintf('%s%s', $basePath, $extraPath);
|
||||||
return $extraPath === null ? $hardcodedPath : sprintf('%s%s', $hardcodedPath, $extraPath);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ class ExtraPathRedirectMiddleware implements MiddlewareInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array{0: string, 1: string|null}
|
* @return array{string, string|null}
|
||||||
*/
|
*/
|
||||||
private function resolvePotentialShortCodeAndExtraPath(UriInterface $uri, int $shortCodeSegments): array
|
private function resolvePotentialShortCodeAndExtraPath(UriInterface $uri, int $shortCodeSegments): array
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,6 +7,7 @@ namespace ShlinkioApiTest\Shlink\Core\Action;
|
||||||
use GuzzleHttp\RequestOptions;
|
use GuzzleHttp\RequestOptions;
|
||||||
use PHPUnit\Framework\Attributes\DataProvider;
|
use PHPUnit\Framework\Attributes\DataProvider;
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
use PHPUnit\Framework\Attributes\Test;
|
||||||
|
use PHPUnit\Framework\Attributes\TestWith;
|
||||||
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
|
||||||
|
|
||||||
use const ShlinkioTest\Shlink\ANDROID_USER_AGENT;
|
use const ShlinkioTest\Shlink\ANDROID_USER_AGENT;
|
||||||
|
@ -15,8 +16,8 @@ use const ShlinkioTest\Shlink\IOS_USER_AGENT;
|
||||||
|
|
||||||
class RedirectTest extends ApiTestCase
|
class RedirectTest extends ApiTestCase
|
||||||
{
|
{
|
||||||
#[Test, DataProvider('provideUserAgents')]
|
#[Test, DataProvider('provideRequestOptions')]
|
||||||
public function properRedirectHappensBasedOnUserAgent(array $options, string $expectedRedirect): void
|
public function properRedirectHappensBasedOnRedirectRules(array $options, string $expectedRedirect): void
|
||||||
{
|
{
|
||||||
$response = $this->callShortUrl('def456', $options);
|
$response = $this->callShortUrl('def456', $options);
|
||||||
|
|
||||||
|
@ -24,19 +25,19 @@ class RedirectTest extends ApiTestCase
|
||||||
self::assertEquals($expectedRedirect, $response->getHeaderLine('Location'));
|
self::assertEquals($expectedRedirect, $response->getHeaderLine('Location'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function provideUserAgents(): iterable
|
public static function provideRequestOptions(): iterable
|
||||||
{
|
{
|
||||||
yield 'android' => [
|
yield 'android' => [
|
||||||
[
|
[
|
||||||
RequestOptions::HEADERS => ['User-Agent' => ANDROID_USER_AGENT],
|
RequestOptions::HEADERS => ['User-Agent' => ANDROID_USER_AGENT],
|
||||||
],
|
],
|
||||||
'https://blog.alejandrocelaya.com/android',
|
'android://foo/bar',
|
||||||
];
|
];
|
||||||
yield 'ios' => [
|
yield 'ios' => [
|
||||||
[
|
[
|
||||||
RequestOptions::HEADERS => ['User-Agent' => IOS_USER_AGENT],
|
RequestOptions::HEADERS => ['User-Agent' => IOS_USER_AGENT],
|
||||||
],
|
],
|
||||||
'https://blog.alejandrocelaya.com/ios',
|
'fb://profile/33138223345',
|
||||||
];
|
];
|
||||||
yield 'desktop' => [
|
yield 'desktop' => [
|
||||||
[
|
[
|
||||||
|
@ -86,4 +87,27 @@ class RedirectTest extends ApiTestCase
|
||||||
'https://blog.alejandrocelaya.com/2017/12/09/acmailer-7-0-the-most-important-release-in-a-long-time/',
|
'https://blog.alejandrocelaya.com/2017/12/09/acmailer-7-0-the-most-important-release-in-a-long-time/',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param non-empty-string $longUrl
|
||||||
|
*/
|
||||||
|
#[Test]
|
||||||
|
#[TestWith(['android://foo/bar'])]
|
||||||
|
#[TestWith(['fb://profile/33138223345'])]
|
||||||
|
#[TestWith(['viber://pa?chatURI=1234'])]
|
||||||
|
public function properRedirectHappensForNonHttpLongUrls(string $longUrl): void
|
||||||
|
{
|
||||||
|
$slug = 'non-http-schema';
|
||||||
|
$this->callApiWithKey('POST', '/short-urls', [
|
||||||
|
RequestOptions::JSON => [
|
||||||
|
'longUrl' => $longUrl,
|
||||||
|
'customSlug' => $slug,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response = $this->callShortUrl($slug);
|
||||||
|
|
||||||
|
self::assertEquals(302, $response->getStatusCode());
|
||||||
|
self::assertEquals($longUrl, $response->getHeaderLine('Location'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ namespace ShlinkioTest\Shlink\Core\ShortUrl\Helper;
|
||||||
use Laminas\Diactoros\ServerRequestFactory;
|
use Laminas\Diactoros\ServerRequestFactory;
|
||||||
use PHPUnit\Framework\Attributes\DataProvider;
|
use PHPUnit\Framework\Attributes\DataProvider;
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
use PHPUnit\Framework\Attributes\Test;
|
||||||
|
use PHPUnit\Framework\Attributes\TestWith;
|
||||||
use PHPUnit\Framework\MockObject\MockObject;
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
@ -37,7 +38,7 @@ class ShortUrlRedirectionBuilderTest extends TestCase
|
||||||
?bool $forwardQuery,
|
?bool $forwardQuery,
|
||||||
): void {
|
): void {
|
||||||
$shortUrl = ShortUrl::create(ShortUrlCreation::fromRawData([
|
$shortUrl = ShortUrl::create(ShortUrlCreation::fromRawData([
|
||||||
'longUrl' => 'https://domain.com/foo/bar?some=thing',
|
'longUrl' => 'https://example.com/foo/bar?some=thing',
|
||||||
'forwardQuery' => $forwardQuery,
|
'forwardQuery' => $forwardQuery,
|
||||||
]));
|
]));
|
||||||
$this->redirectionResolver->expects($this->once())->method('resolveLongUrl')->with(
|
$this->redirectionResolver->expects($this->once())->method('resolveLongUrl')->with(
|
||||||
|
@ -54,59 +55,81 @@ class ShortUrlRedirectionBuilderTest extends TestCase
|
||||||
{
|
{
|
||||||
$request = static fn (array $query = []) => ServerRequestFactory::fromGlobals()->withQueryParams($query);
|
$request = static fn (array $query = []) => ServerRequestFactory::fromGlobals()->withQueryParams($query);
|
||||||
|
|
||||||
yield ['https://domain.com/foo/bar?some=thing', $request(), null, true];
|
yield ['https://example.com/foo/bar?some=thing', $request(), null, true];
|
||||||
yield ['https://domain.com/foo/bar?some=thing', $request(), null, null];
|
yield ['https://example.com/foo/bar?some=thing', $request(), null, null];
|
||||||
yield ['https://domain.com/foo/bar?some=thing', $request(), null, false];
|
yield ['https://example.com/foo/bar?some=thing', $request(), null, false];
|
||||||
yield ['https://domain.com/foo/bar?some=thing&else', $request(['else' => null]), null, true];
|
yield ['https://example.com/foo/bar?some=thing&else', $request(['else' => null]), null, true];
|
||||||
yield ['https://domain.com/foo/bar?some=thing&foo=bar', $request(['foo' => 'bar']), null, true];
|
yield ['https://example.com/foo/bar?some=thing&foo=bar', $request(['foo' => 'bar']), null, true];
|
||||||
yield ['https://domain.com/foo/bar?some=thing&foo=bar', $request(['foo' => 'bar']), null, null];
|
yield ['https://example.com/foo/bar?some=thing&foo=bar', $request(['foo' => 'bar']), null, null];
|
||||||
yield ['https://domain.com/foo/bar?some=thing', $request(['foo' => 'bar']), null, false];
|
yield ['https://example.com/foo/bar?some=thing', $request(['foo' => 'bar']), null, false];
|
||||||
yield ['https://domain.com/foo/bar?some=thing&123=foo', $request(['123' => 'foo']), null, true];
|
yield ['https://example.com/foo/bar?some=thing&123=foo', $request(['123' => 'foo']), null, true];
|
||||||
yield ['https://domain.com/foo/bar?some=thing&456=foo', $request([456 => 'foo']), null, true];
|
yield ['https://example.com/foo/bar?some=thing&456=foo', $request([456 => 'foo']), null, true];
|
||||||
yield ['https://domain.com/foo/bar?some=thing&456=foo', $request([456 => 'foo']), null, null];
|
yield ['https://example.com/foo/bar?some=thing&456=foo', $request([456 => 'foo']), null, null];
|
||||||
yield ['https://domain.com/foo/bar?some=thing', $request([456 => 'foo']), null, false];
|
yield ['https://example.com/foo/bar?some=thing', $request([456 => 'foo']), null, false];
|
||||||
yield [
|
yield [
|
||||||
'https://domain.com/foo/bar?some=overwritten&foo=bar',
|
'https://example.com/foo/bar?some=overwritten&foo=bar',
|
||||||
$request(['foo' => 'bar', 'some' => 'overwritten']),
|
$request(['foo' => 'bar', 'some' => 'overwritten']),
|
||||||
null,
|
null,
|
||||||
true,
|
true,
|
||||||
];
|
];
|
||||||
yield [
|
yield [
|
||||||
'https://domain.com/foo/bar?some=overwritten',
|
'https://example.com/foo/bar?some=overwritten',
|
||||||
$request(['foobar' => 'notrack', 'some' => 'overwritten']),
|
$request(['foobar' => 'notrack', 'some' => 'overwritten']),
|
||||||
null,
|
null,
|
||||||
true,
|
true,
|
||||||
];
|
];
|
||||||
yield [
|
yield [
|
||||||
'https://domain.com/foo/bar?some=overwritten',
|
'https://example.com/foo/bar?some=overwritten',
|
||||||
$request(['foobar' => 'notrack', 'some' => 'overwritten']),
|
$request(['foobar' => 'notrack', 'some' => 'overwritten']),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
];
|
];
|
||||||
yield [
|
yield [
|
||||||
'https://domain.com/foo/bar?some=thing',
|
'https://example.com/foo/bar?some=thing',
|
||||||
$request(['foobar' => 'notrack', 'some' => 'overwritten']),
|
$request(['foobar' => 'notrack', 'some' => 'overwritten']),
|
||||||
null,
|
null,
|
||||||
false,
|
false,
|
||||||
];
|
];
|
||||||
yield ['https://domain.com/foo/bar/something/else-baz?some=thing', $request(), '/something/else-baz', true];
|
yield ['https://example.com/foo/bar/something/else-baz?some=thing', $request(), '/something/else-baz', true];
|
||||||
yield [
|
yield [
|
||||||
'https://domain.com/foo/bar/something/else-baz?some=thing&hello=world',
|
'https://example.com/foo/bar/something/else-baz?some=thing&hello=world',
|
||||||
$request(['hello' => 'world']),
|
$request(['hello' => 'world']),
|
||||||
'/something/else-baz',
|
'/something/else-baz',
|
||||||
true,
|
true,
|
||||||
];
|
];
|
||||||
yield [
|
yield [
|
||||||
'https://domain.com/foo/bar/something/else-baz?some=thing&hello=world',
|
'https://example.com/foo/bar/something/else-baz?some=thing&hello=world',
|
||||||
$request(['hello' => 'world']),
|
$request(['hello' => 'world']),
|
||||||
'/something/else-baz',
|
'/something/else-baz',
|
||||||
null,
|
null,
|
||||||
];
|
];
|
||||||
yield [
|
yield [
|
||||||
'https://domain.com/foo/bar/something/else-baz?some=thing',
|
'https://example.com/foo/bar/something/else-baz?some=thing',
|
||||||
$request(['hello' => 'world']),
|
$request(['hello' => 'world']),
|
||||||
'/something/else-baz',
|
'/something/else-baz',
|
||||||
false,
|
false,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param non-empty-string $longUrl
|
||||||
|
*/
|
||||||
|
#[Test]
|
||||||
|
#[TestWith(['android://foo/bar'])]
|
||||||
|
#[TestWith(['fb://profile/33138223345'])]
|
||||||
|
#[TestWith(['viber://pa?chatURI=1234'])]
|
||||||
|
public function buildShortUrlRedirectBuildsNonHttpUrls(string $longUrl): void
|
||||||
|
{
|
||||||
|
$shortUrl = ShortUrl::withLongUrl($longUrl);
|
||||||
|
$request = ServerRequestFactory::fromGlobals();
|
||||||
|
|
||||||
|
$this->redirectionResolver->expects($this->once())->method('resolveLongUrl')->with(
|
||||||
|
$shortUrl,
|
||||||
|
$request,
|
||||||
|
)->willReturn($shortUrl->getLongUrl());
|
||||||
|
|
||||||
|
$result = $this->redirectionBuilder->buildShortUrlRedirect($shortUrl, $request);
|
||||||
|
|
||||||
|
self::assertEquals($longUrl, $result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ class ListRedirectRulesTest extends ApiTestCase
|
||||||
'conditions' => [self::LANGUAGE_EN_CONDITION],
|
'conditions' => [self::LANGUAGE_EN_CONDITION],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'longUrl' => 'https://blog.alejandrocelaya.com/android',
|
'longUrl' => 'android://foo/bar',
|
||||||
'priority' => 4,
|
'priority' => 4,
|
||||||
'conditions' => [
|
'conditions' => [
|
||||||
[
|
[
|
||||||
|
@ -77,7 +77,7 @@ class ListRedirectRulesTest extends ApiTestCase
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'longUrl' => 'https://blog.alejandrocelaya.com/ios',
|
'longUrl' => 'fb://profile/33138223345',
|
||||||
'priority' => 5,
|
'priority' => 5,
|
||||||
'conditions' => [
|
'conditions' => [
|
||||||
[
|
[
|
||||||
|
|
|
@ -49,7 +49,7 @@ class ShortUrlRedirectRulesFixture extends AbstractFixture implements DependentF
|
||||||
$androidRule = new ShortUrlRedirectRule(
|
$androidRule = new ShortUrlRedirectRule(
|
||||||
shortUrl: $defShortUrl,
|
shortUrl: $defShortUrl,
|
||||||
priority: 4,
|
priority: 4,
|
||||||
longUrl: 'https://blog.alejandrocelaya.com/android',
|
longUrl: 'android://foo/bar',
|
||||||
conditions: new ArrayCollection([RedirectCondition::forDevice(DeviceType::ANDROID)]),
|
conditions: new ArrayCollection([RedirectCondition::forDevice(DeviceType::ANDROID)]),
|
||||||
);
|
);
|
||||||
$manager->persist($androidRule);
|
$manager->persist($androidRule);
|
||||||
|
@ -65,7 +65,7 @@ class ShortUrlRedirectRulesFixture extends AbstractFixture implements DependentF
|
||||||
$iosRule = new ShortUrlRedirectRule(
|
$iosRule = new ShortUrlRedirectRule(
|
||||||
shortUrl: $defShortUrl,
|
shortUrl: $defShortUrl,
|
||||||
priority: 5,
|
priority: 5,
|
||||||
longUrl: 'https://blog.alejandrocelaya.com/ios',
|
longUrl: 'fb://profile/33138223345',
|
||||||
conditions: new ArrayCollection([RedirectCondition::forDevice(DeviceType::IOS)]),
|
conditions: new ArrayCollection([RedirectCondition::forDevice(DeviceType::IOS)]),
|
||||||
);
|
);
|
||||||
$manager->persist($iosRule);
|
$manager->persist($iosRule);
|
||||||
|
|
Loading…
Reference in a new issue