Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[make:decorator] Add new maker to create decorator #1613

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

WedgeSama
Copy link

@WedgeSama WedgeSama commented Nov 10, 2024

Add new maker to create decorator.
#1401

Allow to create new decorator for existing services.

It try first to decorate by implements:

  • The service ID used is an interface => implements this interface
  • The service class implements one (or more) interface(s) and it do not declare more public method => implements those interfaces

If cannot implements, it will fallback to extends:

  • Simply extends the service's class
  • Do not work for final class

e.g.

bin/console make:decorator Symfony\Component\Routing\Generator\UrlGeneratorInterface MyUrlGenerator
<?php

namespace App;

use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
use Symfony\Component\DependencyInjection\Attribute\AutowireDecorated;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RequestContext;

#[AsDecorator(UrlGeneratorInterface::class)]
final class MyUrlGenerator implements UrlGeneratorInterface
{
    public function __construct(
        #[AutowireDecorated]
        private readonly UrlGeneratorInterface $inner,
    ) {
    }

    public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH): string
    {
        return $this->inner->generate($name, $parameters, $referenceType);
    }

    public function setContext(RequestContext $context): void
    {
        $this->inner->setContext($context);
    }

    public function getContext(): RequestContext
    {
        return $this->inner->getContext();
    }
}

@WedgeSama WedgeSama marked this pull request as ready for review November 10, 2024 13:58

($question = new Question($argument->getDescription()))
->setAutocompleterValues($this->ids)
->setValidator(fn ($answer) => Validator::serviceExists($answer, $this->ids))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

based on the issue I'd suggest that the command accept not only the id but a classname and tries to guess the id based on it (if the service does not exists for example)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can try something like that:

  1. If the class is use as ID => easy found
  2. If no id with the classname, try to find one service using it
  3. If more then one service, suggest to choose which service to decorate?
  4. If nothing found, just exit with error

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 yes with fault tolerance maybe ? serializer vs serialiser There are example in symfony's code about this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. I also did guess from class/interface short name.

$command
->addArgument('id', InputArgument::OPTIONAL, 'The ID of the service to decorate.')
->addArgument('decorator-class', InputArgument::OPTIONAL, \sprintf('The class name of the service to create (e.g. <fg=yellow>%sDecorator</>)', Str::asClassName(Str::getRandomTerm())))
->setHelp($this->getHelpFileContents('MakeDecorator.txt'))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

priorityand onInvalid could be added as options.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

return 'service_a';
}

public function getDefault(string $mode = self::MODE_FOO): ?string

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can use this test to check different argument representations. Ex: without type, without default value, PHP8 attributes, variadic arguments, etc.)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I test it here tests/Util/ClassSource/ClassMethodTest.php#L62
Is it enough?


public static function getCommandDescription(): string
{
return 'Create CRUD for Doctrine entity class';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return 'Create CRUD for Doctrine entity class';
return 'Create a decorator of a service class';

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

…ity/onInvalid

Also fix:
- ignore `__construct`
- fix static method on decorate by implements
- Fix description
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants