How is the correct way to customize the ExternalLinksExtension in the services.yml on Symfony 4/5/6.1?
according to official documentation ExternalLinksExtension it is assumed that the configuration parameters must be passed to the Enviroment. However, the Enviroment is not a service and is not instantiated as a service, even if it is declared as such. It is instantiated directly from the function that initializes the CommonMarkdown bundle, where empty arguments are passed on to it.
By making a custom extension there is also no way to modify the configuration of the current environment. Inheriting from ExtensionInterface
does not give you such access.
The current way I do it is to copy all the content of the native extension ExternalLinksExtension
and in the configureSchema method merge the configuration of the current environment with custom arguments.
class ExternalLinksExtension implements ConfigurableExtensionInterface
{
public function configureSchema(ConfigurationBuilderInterface $builder): void
{
$applyOptions = [
ExternalLinkProcessor::APPLY_NONE,
ExternalLinkProcessor::APPLY_ALL,
ExternalLinkProcessor::APPLY_INTERNAL,
ExternalLinkProcessor::APPLY_EXTERNAL,
];
$builder->addSchema('external_link', Expect::structure([
'internal_hosts' => Expect::type('string|string[]'),
'open_in_new_window' => Expect::bool(false),
'html_class' => Expect::string()->default(''),
'nofollow' => Expect::anyOf(...$applyOptions)->default(ExternalLinkProcessor::APPLY_NONE),
'noopener' => Expect::anyOf(...$applyOptions)->default(ExternalLinkProcessor::APPLY_EXTERNAL),
'noreferrer' => Expect::anyOf(...$applyOptions)->default(ExternalLinkProcessor::APPLY_EXTERNAL),
]));
//this is where I pass custom arfuments
$builder->merge([
'external_link' => [
'internal_hosts' => ["localhost"],
'open_in_new_window' => true,
'html_class' => 'external-link',
'nofollow' => '',
'noopener' => 'external',
'noreferrer' => 'external',
]
]);
}
public function register(EnvironmentBuilderInterface $environment): void
{
$environment->addEventListener(DocumentParsedEvent::class, new ExternalLinkProcessor($environment->getConfiguration()), -50);
}
}
This way it works for me, but I believe that it is not convenient to have to be copying all the extensions that you want to customize or that you must make this type of hacks, there should be another more direct method of configuration.
In my service.yml file
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
- '../src/Tests/'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller/'
tags: ['controller.service_arguments']
League\CommonMark\Environment\Environment:
public: true
arguments:
-
external_link:
-
internal_hosts: [ "localhost" ]
open_in_new_window: true
html_class: "external-link"
nofollow: ""
noopener: "external"
noreferrer: "external"
League\CommonMark\Extension\Table\TableExtension:
tags:
- { name: twig.markdown.league_extension }
League\CommonMark\Extension\Autolink\AutolinkExtension:
tags:
- { name: twig.markdown.league_extension }
League\CommonMark\Extension\Strikethrough\StrikethroughExtension:
tags:
- { name: twig.markdown.league_extension }
App\Service\League\CommonMark\ExternalLinksExtension:
arguments: ... ##arguments here also doesnt work with the native extension
tags:
- { name: twig.markdown.league_extension }
the twig docs, mentions that the extensions must go with the tag twig.markdown.league_extension
According to this discussion and the PR that followed, since Twig 3.3.5, the Twig/Extra-Bundle contains a factory that simply relies on declaring the desired extensions in services.yaml, with the specific tag
twig.markdown.league_extension
:This worked for me, with TableExtension and my twig/extra-bundle v3.3.8.