Skip to content

Commit

Permalink
Merge pull request #67 from acelaya-forks/feature/shlink-4.3
Browse files Browse the repository at this point in the history
Shlink 4.3 support
  • Loading branch information
acelaya authored Nov 25, 2024
2 parents 62d17a1 + 21810d5 commit 7e8fc0a
Show file tree
Hide file tree
Showing 11 changed files with 70 additions and 6 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
strategy:
matrix:
php-version: ['8.2', '8.3', '8.4']
shlink-version: ['4.2', '4.1', '4.0', '3.7', '3.6', '3.5.4', '3.4.0', '3.3.2']
shlink-version: ['4.3', '4.2', '4.1', '4.0', '3.7', '3.6', '3.5.4', '3.4.0', '3.3.2']
shlink-api-version: ['3']
steps:
- name: Checkout code
Expand Down
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ 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).

## [Unreleased]
## [2.4.0] - 2024-11-25
### Added
* *Nothing*
* Add support for PHP 8.4
* Add support for Shlink 4.3

### Changed
* Switch to xdebug for code coverage reports, as pcov is not marking functions as covered
Expand Down
10 changes: 10 additions & 0 deletions src/RedirectRules/Model/RedirectCondition.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ public static function forIpAddress(string $ipAddressPattern): self
return new self(RedirectConditionType::IP_ADDRESS, $ipAddressPattern);
}

public static function forGeolocationCountryCode(string $countryCode): self
{
return new self(RedirectConditionType::GEOLOCATION_COUNTRY_CODE, $countryCode);
}

public static function forGeolocationCityName(string $cityName): self
{
return new self(RedirectConditionType::GEOLOCATION_CITY_NAME, $cityName);
}

public static function fromArray(array $payload): self
{
$originalType = $payload['type'] ?? '';
Expand Down
2 changes: 2 additions & 0 deletions src/RedirectRules/Model/RedirectConditionType.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ enum RedirectConditionType: string
case LANGUAGE = 'language';
case QUERY_PARAM = 'query-param';
case IP_ADDRESS = 'ip-address';
case GEOLOCATION_COUNTRY_CODE = 'geolocation-country-code';
case GEOLOCATION_CITY_NAME = 'geolocation-city-name';
case UNKNOWN = 'unknown';
}
5 changes: 5 additions & 0 deletions src/ShortUrls/Model/ShortUrl.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
/** @deprecated Not returned by Shlink 4.0.0 */
public DeviceLongUrls|null $deviceLongUrls;

/**
* @param $hasRedirectRules - It's `null` for Shlink older than 4.3
*/
private function __construct(
public string $shortCode,
public string $shortUrl,
Expand All @@ -24,6 +27,7 @@ private function __construct(
public string|null $title,
public bool $crawlable,
public bool $forwardQuery,
public bool|null $hasRedirectRules,
public array $tags,
public ShortUrlMeta $meta,
public VisitsSummary $visitsSummary,
Expand All @@ -48,6 +52,7 @@ public static function fromArray(array $payload): self
title: $payload['title'] ?? null,
crawlable: $payload['crawlable'] ?? false,
forwardQuery: $payload['forwardQuery'] ?? false,
hasRedirectRules: $payload['hasRedirectRules'] ?? null,
tags: $payload['tags'] ?? [],
meta: ShortUrlMeta::fromArray($payload['meta'] ?? []),
visitsSummary: VisitsSummary::fromArrayWithFallback($payload['visitsSummary'] ?? [], $visitsCount),
Expand Down
5 changes: 5 additions & 0 deletions src/ShortUrls/Model/ShortUrlsFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ public function orderingDescBy(ShortUrlListOrderField $field): self
return $this->cloneWithProp('orderBy', sprintf('%s-DESC', $field->value));
}

public function forDomain(string $domain): self
{
return $this->cloneWithProp('domain', $domain);
}

private function cloneWithProp(string $prop, mixed $value): self
{
$clone = new self($this->query);
Expand Down
10 changes: 7 additions & 3 deletions src/Visits/Model/OrphanVisit.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@

final readonly class OrphanVisit implements VisitInterface
{
private function __construct(private Visit $visit, private string $visitedUrl, private OrphanVisitType $type)
private function __construct(private Visit $visit, private OrphanVisitType $type)
{
}

public static function fromArray(array $payload): self
{
return new self(
visit: Visit::fromArray($payload),
visitedUrl: $payload['visitedUrl'] ?? '',
type: OrphanVisitType::tryFrom($payload['type'] ?? '') ?? OrphanVisitType::REGULAR_NOT_FOUND,
);
}
Expand Down Expand Up @@ -48,7 +47,12 @@ public function location(): VisitLocation|null

public function visitedUrl(): string
{
return $this->visitedUrl;
return $this->visit->visitedUrl();
}

public function redirectUrl(): string|null
{
return $this->visit->redirectUrl();
}

public function type(): OrphanVisitType
Expand Down
14 changes: 14 additions & 0 deletions src/Visits/Model/Visit.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ private function __construct(
private DateTimeInterface $date,
private string $userAgent,
private bool $potentialBot,
private string $visitedUrl,
private string|null $redirectUrl,
private VisitLocation|null $location,
) {
}
Expand All @@ -26,6 +28,8 @@ public static function fromArray(array $payload): self
date: DateTimeImmutable::createFromFormat(DateTimeInterface::ATOM, $payload['date']),
userAgent: $payload['userAgent'] ?? '',
potentialBot: $payload['potentialBot'] ?? false,
visitedUrl: $payload['visitedUrl'] ?? '',
redirectUrl: $payload['redirectUrl'] ?? null,
location: isset($payload['visitLocation']) ? VisitLocation::fromArray($payload['visitLocation']) : null,
);
}
Expand Down Expand Up @@ -54,4 +58,14 @@ public function location(): VisitLocation|null
{
return $this->location;
}

public function visitedUrl(): string
{
return $this->visitedUrl;
}

public function redirectUrl(): string|null
{
return $this->redirectUrl;
}
}
2 changes: 2 additions & 0 deletions src/Visits/Model/VisitInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ public function date(): DateTimeInterface;
public function userAgent(): string;
public function potentialBot(): bool;
public function location(): VisitLocation|null;
public function visitedUrl(): string;
public function redirectUrl(): string|null;
}
20 changes: 20 additions & 0 deletions test/RedirectRules/Model/RedirectConditionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,24 @@ public function forIpAddressCreatesExpectedCondition(): void
self::assertEquals('192.168.1.100', $condition->matchValue);
self::assertNull($condition->matchKey);
}

#[Test]
public function forGeolocationCountryCodeCreatesExpectedCondition(): void
{
$condition = RedirectCondition::forGeolocationCountryCode('US');

self::assertEquals(RedirectConditionType::GEOLOCATION_COUNTRY_CODE, $condition->type);
self::assertEquals('US', $condition->matchValue);
self::assertNull($condition->matchKey);
}

#[Test]
public function forGeolocationCityNameCreatesExpectedCondition(): void
{
$condition = RedirectCondition::forGeolocationCityName('Los Angeles');

self::assertEquals(RedirectConditionType::GEOLOCATION_CITY_NAME, $condition->type);
self::assertEquals('Los Angeles', $condition->matchValue);
self::assertNull($condition->matchKey);
}
}
1 change: 1 addition & 0 deletions test/ShortUrls/Model/ShortUrlsFilterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,6 @@ public static function providePayloads(): iterable
fn () => ShortUrlsFilter::create()->excludingMaxVisitsReached()->excludingPastValidUntil(),
['excludeMaxVisitsReached' => 'true', 'excludePastValidUntil' => 'true'],
];
yield [fn () => ShortUrlsFilter::create()->forDomain('s.test'), ['domain' => 's.test']];
}
}

0 comments on commit 7e8fc0a

Please sign in to comment.