For information about adding your own TerminalCommand please refer to the tutorial.
So you want to implement a TerminalCommand but sadly some information you need to execute compile() in a meaningful way is not supplied by the coding-standard yet.
To fix that you need to do the following.
- Add a TerminalCommand interface
- Add a TerminalCommandDecorator
- Register your TerminalCommandDecorator
- Add a Trait
Let's say you want to add the information 'SuperCool' so it can be used while compiling a TerminalCommand.
First create an interface in a sub-namespace of
Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalComand
and name it appropriately.
Let's call it SuperInformedTerminalCommand.php
in Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalComand\SuperInformation
.
This interface will tell a TerminalCommand what methods it needs to implement
to be super informed.
interface SuperInformedTerminalCommand extends TerminalCommand
{
/**
* Lets the command know what's up.
*
* @param string $information
*/
public function addInformation(string $information): void;
}
Well that was easy. Let's continue with the decorator.
The TerminalCommandDecorator will actually inject your super cool information into
TerminalCommands. Place your new TerminalCommandDecorator in
Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalComand\SuperInformation
and call it SuperCoolInformationDecorator.php
.
// Use the TerminalCommandDecorator interface so we know what's what.
class SuperCoolInformationDecorator implements TerminalCommandDecorator
{
// As the TerminalCommandDecorator is also a EventSubscriber we need to tell
// the world what events we are interested in. If you want to know more
// about EventSubscribers I refer you to
// https://symfony.com/doc/current/components/event_dispatcher.html
public static function getSubscribedEvents(): array
{
// Please choose at least this event and bind it to the decorate method.
return [AbstractToolCommand::EVENT_DECORATE_TERMINAL_COMMAND => ['decorate', 50]];
}
/**
* This method decorates the TerminalCommand contained in the generic event.
* It will read information from the surrounding infrastructure or the command input.
*/
public function decorate(DecorateEvent $event): void
{
// Check if the TerminalCommand want's to be super informed. Not
// only is it rude to tell people things they don't want to hear.
// It will also crash the coding-standard
$terminalCommand = $event->getTerminalCommand();
if (!$terminalCommand instanceof SuperInformedTerminalCommand) {
return;
}
// Now we actually inject the information. As we just implemented the
// interface we can be sure that this method exists.
$terminalCommand->addInformation('SuperCool');
}
So you wrote your SuperCoolInformationDecorator. Nice! But you need to tell
the coding-standard about its existence. That is as easy as writing a name
on a list. Open Zooroyal\CodingStandard\CommandLine\ApplicationLifeCycle\EventDispatcherFactory
class EventDispatcherFactory
{
/** @var array<string> */
private const SUBSCRIBERS
= [
GitCommandPreconditionChecker::class,
TerminalCommandPreconditionChecker::class,
ExclusionDecorator::class,
ExtensionDecorator::class,
FixDecorator::class,
TargetDecorator::class,
VerbosityDecorator::class,
SuperCoolInformationDecorator::class // Add Decorater to the list
];
private Container $container;
// [...]
}
Well. That was easy.
Well... strictly speaking the trait is not needed for everything to work but to make the life of other developers easier you should definitely consider it.
The trait should reside next to your other code so let's add it right there in
Zooroyal\CodingStandard\CommandLine\StaticCodeAnalysis\Generic\TerminalCommand\SuperInformation
As names are important – to us; Coding-Standard not so much – call your new
trait SuperInformedTrait.php
trait SuperInformedTrait
{
// Choose a field to store the information it receives from your decorator.
// Don't forget to give it some default value.
// As traits are interpreter supported copy and paste, please do not try to
// interact with anything outside of your trait. Please don't.
protected string $information = '';
// Now add a sensible default implementation for your information
// gathering method. The signatures is forced by your interface so don't
// look at me if you think it's wonky ^^
/**
* Receive super important information.
*
* @param string $information
*/
final public function addInformation(string $information): void
{
$this->information = $information;
}
}