JWTRefreshTokenBundle: Error in RefreshTokenManager - Support for doctrine/common +3.0

Since Doctrine Common 3.0, Common was split into smaller packages.

Actually in RefreshTokenManager you inject Doctrine\Common\Persistence\ObjectManager in constructor.

Since Doctrine Common 3.0, Doctrine\Common\Persistence\ObjectManager became Doctrine\Persistence\ObjectManager.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 30
  • Comments: 25 (7 by maintainers)

Commits related to this issue

Most upvoted comments

Hello. Faced the same problem, my solution is:

    gesdinet.jwtrefreshtoken.refresh_token_manager:
        class: App\Doctrine\RefreshTokenManager
        public: true
        arguments: [ '@doctrine.orm.default_entity_manager', 'Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken']
<?php
namespace App\Doctrine;

use Doctrine\Persistence\ObjectManager;
use Doctrine\ORM\EntityManagerInterface;
use Gesdinet\JWTRefreshTokenBundle\Entity\RefreshTokenRepository;
use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenManager as BaseRefreshTokenManager;
use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenInterface;

class RefreshTokenManager extends BaseRefreshTokenManager
{
    /**
     * @var EntityManagerInterface
     */
    protected $objectManager;
    
    /**
     * @var string
     */
    protected $class;
    
    /**
     * @var RefreshTokenRepository
     */
    protected $repository;
    
    /**
     * Constructor.
     *
     * @param ObjectManager $om
     * @param string        $class
     */
    public function __construct(ObjectManager $om, $class)
    {
        $this->objectManager = $om;
        $this->repository = $om->getRepository($class);
        $metadata = $om->getClassMetadata($class);
        $this->class = $metadata->getName();
    }
    
    /**
     * @param string $refreshToken
     *
     * @return RefreshTokenInterface
     */
    public function get($refreshToken)
    {
        return $this->repository->findOneBy(array('refreshToken' => $refreshToken));
    }
    
    /**
     * @param string $username
     *
     * @return RefreshTokenInterface
     */
    public function getLastFromUsername($username)
    {
        return $this->repository->findOneBy(array('username' => $username), array('valid' => 'DESC'));
    }
    
    /**
     * @param RefreshTokenInterface $refreshToken
     * @param bool|true             $andFlush
     */
    public function save(RefreshTokenInterface $refreshToken, $andFlush = true)
    {
        $this->objectManager->persist($refreshToken);
        
        if ($andFlush) {
            $this->objectManager->flush();
        }
    }
    
    /**
     * @param RefreshTokenInterface $refreshToken
     * @param bool                  $andFlush
     */
    public function delete(RefreshTokenInterface $refreshToken, $andFlush = true)
    {
        $this->objectManager->remove($refreshToken);
        
        if ($andFlush) {
            $this->objectManager->flush();
        }
    }
    
    /**
     * @param \DateTime $datetime
     * @param bool      $andFlush
     *
     * @return RefreshTokenInterface[]
     */
    public function revokeAllInvalid($datetime = null, $andFlush = true)
    {
        $invalidTokens = $this->repository->findInvalid($datetime);
        
        foreach ($invalidTokens as $invalidToken) {
            $this->objectManager->remove($invalidToken);
        }
        
        if ($andFlush) {
            $this->objectManager->flush();
        }
        
        return $invalidTokens;
    }
    
    /**
     * Returns the RefreshToken fully qualified class name.
     *
     * @return string
     */
    public function getClass()
    {
        return $this->class;
    }
}

Hello @markitosgv

There are 5 PR to address this issue:

Could you merge one of theses please ?


And if you don’t have time for this, this not a big deal. But Could you give write permissions to someone else? πŸ™πŸΌ

Have a nice day

A simpler approach until this is fixed upstream:

override the service:

    gesdinet.jwtrefreshtoken.refresh_token_manager:
      class:  App\Doctrine\RefreshTokenManager
      public: true
      arguments: [ '@gesdinet.jwtrefreshtoken.object_manager', '%gesdinet.jwtrefreshtoken.refresh_token.class%' ]

and on the class just override the contructor

<?php

namespace App\Doctrine;

use Doctrine\Persistence\ObjectManager;

class RefreshTokenManager extends \Gesdinet\JWTRefreshTokenBundle\Doctrine\RefreshTokenManager
{
    public function __construct(ObjectManager $om, $class)
    {
        $this->objectManager = $om;
        $this->repository = $om->getRepository($class);
        $metadata = $om->getClassMetadata($class);
        $this->class = $metadata->getName();
    }
}

Adding the relevant error for the people coming from google:

Argument 1 passed to Gesdinet\\JWTRefreshTokenBundle\\Doctrine\\RefreshTokenManager::__construct() must be an instance of Doctrine\\Common\\Persistence\\ObjectManager, instance of Doctrine\\ORM\\EntityManager given, called in \getGesdinet_Jwtrefreshtoken_RefreshTokenManagerService.php on line 24

Solved in v0.10.0, please confirm that!

Any idea when this will be fixed?

I hope that this gets merged soon πŸ˜‰ For the ones using PHPStan (based on @byhaskell):

<?php

declare(strict_types=1);

namespace App\Doctrine;

use Doctrine\Persistence\ObjectManager;
use Gesdinet\JWTRefreshTokenBundle\Entity\RefreshTokenRepository;
use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenInterface;
use Gesdinet\JWTRefreshTokenBundle\Model\RefreshTokenManager as BaseRefreshTokenManager;

/**
 * Class RefreshTokenManager.
 */
class RefreshTokenManager extends BaseRefreshTokenManager
{
    protected ObjectManager $objectManager;

    /**
     * @var class-string<mixed>
     */
    protected string $class;

    protected RefreshTokenRepository $repository;

    /**
     * Constructor.
     *
     * @param class-string<mixed> $class
     */
    public function __construct(ObjectManager $om, $class)
    {
        $this->objectManager = $om;

        $repo = $om->getRepository($class);
        assert($repo instanceof RefreshTokenRepository);
        $this->repository = $repo;

        $metadata = $om->getClassMetadata($class);

        /** @var class-string<mixed> $classString */
        $classString = $metadata->getName();
        $this->class = $classString;
    }

    /**
     * @param string $refreshToken
     *
     * @return ?RefreshTokenInterface
     */
    public function get($refreshToken): ?RefreshTokenInterface
    {
        $refreshToken = $this->repository->findOneBy(['refreshToken' => $refreshToken]);
        if ($refreshToken instanceof RefreshTokenInterface) {
            return $refreshToken;
        } else {
            return null;
        }
    }

    /**
     * @param string $username
     *
     * @return RefreshTokenInterface
     */
    public function getLastFromUsername($username): ?RefreshTokenInterface
    {
        $refreshToken = $this->repository->findOneBy(['username' => $username], ['valid' => 'DESC']);

        if ($refreshToken instanceof RefreshTokenInterface) {
            return $refreshToken;
        } else {
            return null;
        }
    }

    /**
     * @param bool|true $andFlush
     */
    public function save(RefreshTokenInterface $refreshToken, $andFlush = true): void
    {
        $this->objectManager->persist($refreshToken);

        if ($andFlush) {
            $this->objectManager->flush();
        }
    }

    /**
     * @param bool $andFlush
     */
    public function delete(RefreshTokenInterface $refreshToken, $andFlush = true): void
    {
        $this->objectManager->remove($refreshToken);

        if ($andFlush) {
            $this->objectManager->flush();
        }
    }

    /**
     * @param \DateTime $datetime
     * @param bool      $andFlush
     *
     * @return RefreshTokenInterface[]
     */
    public function revokeAllInvalid(?\DateTimeInterface $datetime = null, $andFlush = true)
    {
        /* @phpstan-ignore-next-line */
        $invalidTokens = $this->repository->findInvalid($datetime);

        foreach ($invalidTokens as $invalidToken) {
            $this->objectManager->remove($invalidToken);
        }

        if ($andFlush) {
            $this->objectManager->flush();
        }

        return $invalidTokens;
    }

    /**
     * Returns the RefreshToken fully qualified class name.
     *
     * @return string
     */
    public function getClass()
    {
        return $this->class;
    }
}

@acasademont your shorter solution works like charm, thanks and kudos!

I can confirm that the solution provided by @byhaskell works out of the box. Thanks !

Thank You @byhaskell . Added the config to services in config/services.yaml and it worked like a charm.