mirror of
https://github.com/shlinkio/shlink.git
synced 2026-03-09 08:43:13 +08:00
Implement command to manage redirect rules for a short URL
This commit is contained in:
@@ -13,6 +13,7 @@ use function Shlinkio\Shlink\Core\acceptLanguageToLocales;
|
||||
use function Shlinkio\Shlink\Core\ArrayUtils\some;
|
||||
use function Shlinkio\Shlink\Core\normalizeLocale;
|
||||
use function Shlinkio\Shlink\Core\splitLocale;
|
||||
use function sprintf;
|
||||
use function strtolower;
|
||||
use function trim;
|
||||
|
||||
@@ -107,4 +108,17 @@ class RedirectCondition extends AbstractEntity implements JsonSerializable
|
||||
'matchValue' => $this->matchValue,
|
||||
];
|
||||
}
|
||||
|
||||
public function toHumanFriendly(): string
|
||||
{
|
||||
return match ($this->type) {
|
||||
RedirectConditionType::DEVICE => sprintf('device is %s', $this->matchValue),
|
||||
RedirectConditionType::LANGUAGE => sprintf('%s language is accepted', $this->matchValue),
|
||||
RedirectConditionType::QUERY_PARAM => sprintf(
|
||||
'query string contains %s=%s',
|
||||
$this->matchKey,
|
||||
$this->matchValue,
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ use function Shlinkio\Shlink\Core\ArrayUtils\every;
|
||||
class ShortUrlRedirectRule extends AbstractEntity implements JsonSerializable
|
||||
{
|
||||
/**
|
||||
* @param Collection<RedirectCondition> $conditions
|
||||
* @param Collection<int, RedirectCondition> $conditions
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly ShortUrl $shortUrl, // No need to read this field. It's used by doctrine
|
||||
@@ -41,6 +41,16 @@ class ShortUrlRedirectRule extends AbstractEntity implements JsonSerializable
|
||||
$this->conditions->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @template R
|
||||
* @param callable(RedirectCondition $condition): R $callback
|
||||
* @return R[]
|
||||
*/
|
||||
public function mapConditions(callable $callback): array
|
||||
{
|
||||
return $this->conditions->map($callback(...))->toArray();
|
||||
}
|
||||
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
return [
|
||||
|
||||
@@ -6,5 +6,5 @@ enum RedirectConditionType: string
|
||||
{
|
||||
case DEVICE = 'device';
|
||||
case LANGUAGE = 'language';
|
||||
case QUERY_PARAM = 'query';
|
||||
case QUERY_PARAM = 'query-param';
|
||||
}
|
||||
|
||||
@@ -34,23 +34,6 @@ readonly class ShortUrlRedirectRuleService implements ShortUrlRedirectRuleServic
|
||||
*/
|
||||
public function setRulesForShortUrl(ShortUrl $shortUrl, RedirectRulesData $data): array
|
||||
{
|
||||
return $this->em->wrapInTransaction(fn () => $this->doSetRulesForShortUrl($shortUrl, $data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ShortUrlRedirectRule[]
|
||||
*/
|
||||
private function doSetRulesForShortUrl(ShortUrl $shortUrl, RedirectRulesData $data): array
|
||||
{
|
||||
// First, delete existing rules for the short URL
|
||||
$oldRules = $this->rulesForShortUrl($shortUrl);
|
||||
foreach ($oldRules as $oldRule) {
|
||||
$oldRule->clearConditions(); // This will trigger the orphan removal of old conditions
|
||||
$this->em->remove($oldRule);
|
||||
}
|
||||
$this->em->flush();
|
||||
|
||||
// Then insert new rules
|
||||
$rules = [];
|
||||
foreach ($data->rules as $index => $rule) {
|
||||
$rule = new ShortUrlRedirectRule(
|
||||
@@ -64,9 +47,30 @@ readonly class ShortUrlRedirectRuleService implements ShortUrlRedirectRuleServic
|
||||
);
|
||||
|
||||
$rules[] = $rule;
|
||||
$this->em->persist($rule);
|
||||
}
|
||||
|
||||
$this->saveRulesForShortUrl($shortUrl, $rules);
|
||||
return $rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ShortUrlRedirectRule[] $rules
|
||||
*/
|
||||
public function saveRulesForShortUrl(ShortUrl $shortUrl, array $rules): void
|
||||
{
|
||||
$this->em->wrapInTransaction(function () use ($shortUrl, $rules): void {
|
||||
// First, delete existing rules for the short URL
|
||||
$oldRules = $this->rulesForShortUrl($shortUrl);
|
||||
foreach ($oldRules as $oldRule) {
|
||||
$oldRule->clearConditions(); // This will trigger the orphan removal of old conditions
|
||||
$this->em->remove($oldRule);
|
||||
}
|
||||
$this->em->flush();
|
||||
|
||||
// Then insert new rules
|
||||
foreach ($rules as $rule) {
|
||||
$this->em->persist($rule);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,4 +17,9 @@ interface ShortUrlRedirectRuleServiceInterface
|
||||
* @return ShortUrlRedirectRule[]
|
||||
*/
|
||||
public function setRulesForShortUrl(ShortUrl $shortUrl, RedirectRulesData $data): array;
|
||||
|
||||
/**
|
||||
* @param ShortUrlRedirectRule[] $rules
|
||||
*/
|
||||
public function saveRulesForShortUrl(ShortUrl $shortUrl, array $rules): void;
|
||||
}
|
||||
|
||||
@@ -124,6 +124,9 @@ class ShortUrlInputFilter extends InputFilter
|
||||
$this->add($apiKeyInput);
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Extract to its own validator class
|
||||
*/
|
||||
public static function longUrlValidators(bool $allowNull = false): Validator\ValidatorChain
|
||||
{
|
||||
$emptyModifiers = [
|
||||
|
||||
Reference in New Issue
Block a user