How to use DoctrineExtensions Blameable from the command line?

688 views Asked by At

I am using DoctrineExtensions Blameable to store the user who created an entity, and when making a HTTP request with JWTs, all is working as desired.

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;

#[ORM\Entity]
class Foo
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(type: Types::INTEGER)]
    private int $id;
    
    #[ORM\ManyToOne(targetEntity: UserInterface::class)]
    #[Gedmo\Blameable(on: 'create')]
    private ?UserInterface $createBy = null;

    #[ORM\Column(type: 'text')]
    private $name;

    public function getId():int
    {
        return $this->id;
    }

    public function getCreateBy(): ?UserInterface
    {
        return $this->createBy;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }
}

Now, instead of making a HTTP request to a webserver, I wish to use a command line to create an entity.

My first attempt was to manually create a token with the appropriate user, however, was not successful.

I next tried to set the user on the BlameableListener, and bin/console debug:event-dispatcher shows me Stof\DoctrineExtensionsBundle\EventListener\BlameListener::onKernelRequest(), but I don't know how to access the listener in order to call the setUserValue() method.

How can DoctrineExtensions Blameable be used from the command line?

<?php

namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

final class AddFoo extends Command
{
    protected static $defaultName = 'app:add-user';

    public function __construct(private EntityManagerInterface $entityManager, private TokenStorageInterface $tokenStorage)
    {
        parent::__construct();
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        // Get user input
        
        $superUser = $this->getSuperUser($superUserEmail, $superUserPassword);

        // Somehow I need to let Blamable know the "logged on" user.
        
        // Option 1.  Fake the token.
        $token = new UsernamePasswordToken($superUser, 'main', $superUser->getRoles());
        // Maybe need to authenticate token?
        $this->tokenStorage->setToken($token);

        // Option 2.  Somehow call Gedmo\Blameable\BlameableListener::setUserValue($superUser);

        $newEntity = $this->createNewFoo($fooName);

        $this->entityManager->persist($newEntity)
        $this->entityManager->flush()
        return Command::SUCCESS;
    }
}

POTENTIAL ANSWER - Don't know if the following is the best approach but seems to work.

services:
    App\Command\AddFoo:
        arguments:
            $blameableListener: '@stof_doctrine_extensions.listener.blameable'
1

There are 1 answers

0
user1032531 On

Add the following to config.service.yaml.

services:
    App\Command\AddFoo:
        arguments:
            $blameableListener: '@stof_doctrine_extensions.listener.blameable'

And then within AddFoo.php...

<?php

declare(strict_types=1);

namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Gedmo\Blameable\BlameableListener;

final class AddFoo extends Command
{
    protected static $defaultName = 'app:add-foo';

    public function __construct(private BlameableListener $blameableListener)
    {
        parent::__construct();
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        // ...
        $this->blameableListener->setUserValue($this->getUserFromEmailAndPassword());
        // ..
    }
}