Fix inconsistencies when editing rules and saving a mix of new and old ones

This commit is contained in:
Alejandro Celaya 2024-03-03 09:09:19 +01:00
parent 3bfb29a51c
commit a843c59d77
4 changed files with 30 additions and 2 deletions

View File

@ -76,6 +76,7 @@ class ManageRedirectRulesCommand extends Command
$rulesToSave = $this->processRules($shortUrl, $io, $this->ruleService->rulesForShortUrl($shortUrl));
if ($rulesToSave !== null) {
$this->ruleService->saveRulesForShortUrl($shortUrl, $rulesToSave);
$io->success('Rules properly saved');
}
return ExitCode::EXIT_SUCCESS;

View File

@ -25,6 +25,16 @@ class ShortUrlRedirectRule extends AbstractEntity implements JsonSerializable
) {
}
public function withPriority(int $newPriority): self
{
return new self(
$this->shortUrl,
$newPriority,
$this->longUrl,
$this->conditions,
);
}
/**
* Tells if this condition matches provided request
*/

View File

@ -11,6 +11,7 @@ use Shlinkio\Shlink\Core\RedirectRule\Model\Validation\RedirectRulesInputFilter;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
use function array_map;
use function Shlinkio\Shlink\Core\ArrayUtils\map;
readonly class ShortUrlRedirectRuleService implements ShortUrlRedirectRuleServiceInterface
{
@ -49,7 +50,7 @@ readonly class ShortUrlRedirectRuleService implements ShortUrlRedirectRuleServic
$rules[] = $rule;
}
$this->saveRulesForShortUrl($shortUrl, $rules);
$this->doSetRulesForShortUrl($shortUrl, $rules);
return $rules;
}
@ -57,6 +58,23 @@ readonly class ShortUrlRedirectRuleService implements ShortUrlRedirectRuleServic
* @param ShortUrlRedirectRule[] $rules
*/
public function saveRulesForShortUrl(ShortUrl $shortUrl, array $rules): void
{
$normalizedAndDetachedRules = map($rules, function (ShortUrlRedirectRule $rule, int|string|float $priority) {
// Make sure all rules and conditions are detached so that the EM considers them new.
$rule->mapConditions(fn (RedirectCondition $cond) => $this->em->detach($cond));
$this->em->detach($rule);
// Normalize priorities so that they are sequential
return $rule->withPriority(((int) $priority) + 1);
});
$this->doSetRulesForShortUrl($shortUrl, $normalizedAndDetachedRules);
}
/**
* @param ShortUrlRedirectRule[] $rules
*/
public function doSetRulesForShortUrl(ShortUrl $shortUrl, array $rules): void
{
$this->em->wrapInTransaction(function () use ($shortUrl, $rules): void {
// First, delete existing rules for the short URL

View File

@ -6,7 +6,6 @@ use Doctrine\Common\Collections\ArrayCollection;
use Laminas\Diactoros\ServerRequestFactory;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\Attributes\TestWith;
use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\Core\RedirectRule\Entity\RedirectCondition;
use Shlinkio\Shlink\Core\RedirectRule\Entity\ShortUrlRedirectRule;