Skip to content

Extension points

phil/redirects-bundle
PointHow
Redirects of another packageImplement Application\Contract\RedirectProvider, register it, and list it in providers with phil_redirects.provider.stored
A change in a provider's redirectsCall RedirectTableCache::invalidate()
What the 404 log ignoresImplement Application\Contract\NotFoundFilter; autoconfiguration tags it phil_redirects.not_found_filter
Where the redirects are keptImplement Domain\Contract\RedirectRepository and alias it
Where the 404 log is keptImplement Domain\Contract\NotFoundLogRepository and alias it
Creating redirects from codeApplication\Redirects: create(), update(), enable(), delete(), import(), check()
Resolving a path from codeApplication\RedirectResolver::resolve()
The words of the administrationThe messages of the phil_redirects domain
The pages of the administrationadmin.layout, and the templates under @PhilRedirects/admin/ overridden in templates/bundles/PhilRedirectsBundle/
The clockThe clock option: the bundle never reads the time itself

A provider

A provider gives RedirectRules, read when the table is built:

use Phil\RedirectsBundle\Application\Contract\RedirectProvider;
use Phil\RedirectsBundle\Domain\ValueObject\RedirectRule;
use Phil\RedirectsBundle\Domain\ValueObject\SourcePattern;
use Phil\RedirectsBundle\Domain\ValueObject\Target;

final readonly class FormerSlugs implements RedirectProvider
{
    public function __construct(private SlugHistory $history)
    {
    }

    public function redirects(): iterable
    {
        foreach ($this->history->formerSlugs() as $former => $current) {
            yield new RedirectRule(SourcePattern::exact('/pages/'.$former), Target::route('page', ['slug' => $current]));
        }
    }
}
phil_redirects:
    providers: [phil_redirects.provider.stored, App\Redirects\FormerSlugs]

The invariants:

  • the rules are read when the table is built, then kept with it: a provider calls RedirectTableCache::invalidate() when its redirects change;
  • the first provider listed wins a source given twice, so the stored redirects listed first let the administration override any provided redirect;
  • a provided rule has no identifier, so its hits are not counted;
  • the checks of a save take the provided rules into account: a stored redirect that would make a loop or a chain with them is refused.

A filter

use Phil\RedirectsBundle\Application\Contract\NotFoundFilter;
use Phil\RedirectsBundle\Application\NotFoundHit;

final readonly class NoAssets implements NotFoundFilter
{
    public function ignores(NotFoundHit $hit): bool
    {
        return 1 === preg_match('/\.(?:map|php)$/', $hit->path);
    }
}

A filter sees the host, the path, the referrer, the user agent and the robot verdict; the log keeps only the host, the path and the host of the referrer.