Jump to content

Converting an enumerator to an integer


NotionCommotion

Recommended Posts

The following Doctrine method throws error Warning: Object of class App\\Entity\AccessControl\Acl\PermissionEnum could not be converted to int

namespace Doctrine\DBAL\Types;
class SmallIntType extends Type implements PhpIntegerMappingType
{
    ...
	public function convertToPHPValue($value, AbstractPlatform $platform)
    {
        return $value === null ? null : (int) $value;
    }
    ...
}

PermissionEnum is a backed integer enum.

enum PermissionEnum: int
{
    case public     = 0b00;
    case owner      = 0b01;
    case restrict   = 0b10;
    case extra      = 0b11; 
}

Similar to the __toString() magic method, is there a way to change my PermissionEnum so when type casted as an integer, returns an integer?

Supplementary info below if of interest

 While outside of the scope of this question, the following added lines of code were added by Doctrine's latest commit and if removed, the issue goes away.  PermissionEnum is used by class Permission which in turn is converted to an integer when saving the the database.

namespace Doctrine\ORM\Query;
class SqlWalker implements TreeWalker
{
    public function walkSelectExpression($selectExpression)
    {
		...
                    if (! empty($mapping['enumType'])) {
                        $this->rsm->addEnumResult($columnAlias, $mapping['enumType']);
                    }
		...
	}
}

 

namespace App\Doctrine\Types;

use App\Entity\AccessControl\Acl\Permission;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\ConversionException;
use Doctrine\DBAL\Types\Type;

final class PermissionType extends Type
{
    private const PERMISSION = 'permission';

    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform): string
    {
        return $platform->getSmallIntTypeDeclarationSQL($fieldDeclaration);
    }

    public function convertToPHPValue($value, AbstractPlatform $platform): mixed
    {
        if (null === $value) {
            return null;
        }

        if (\is_int($value)) {
            return Permission::createFromValue($value);
        }

        throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['int', 'null']);
    }

    public function convertToDatabaseValue($value, AbstractPlatform $platform): mixed
    {
        if (null === $value) {
            return null;
        }

        if ($value instanceof Permission) {
            return $value->getValue();
        }

        throw ConversionException::conversionFailedInvalidType($value, $this->getName(), [Permission::class, 'null']);
    }

    public function requiresSQLCommentHint(AbstractPlatform $platform): bool
    {
        return true;
    }

    public function getName(): string
    {
        return self::PERMISSION;
    }
}

 

class Permission
{
    private const READ      = 0b0000000011;
    private const CREATE    = 0b0000001100;
    private const MODIFY    = 0b0000110000;
    private const DELETE    = 0b0011000000;
    private const COWORKER  = 0b0100000000; // Not currently used.
    private const OWNER     = 0b1000000000; // Not currently used.

    public function __construct(
        private ?PermissionEnum $read=null,
        private ?PermissionEnum $create=null,
        private ?PermissionEnum $modify=null,
        private ?PermissionEnum $delete=null,
        private ?bool $restrictToOwner=null,
        private ?bool $coworkers=null
    ) {
    }

    public function getValue(): ?int
    {
        if($this->hasNullValue()) {
            throw new Exception('Permission has NULL values.');
        }
        $rs = $this->read->value | $this->create->value << 2 | $this->modify->value << 4 | $this->delete->value << 6;
        $rs = $this->coworkers ? $rs | self::COWORKER : $rs & ~self::COWORKER;

        return $this->restrictToOwner ? $rs | self::OWNER : $rs & ~self::OWNER;
    }
}

 

Link to comment
Share on other sites

1 hour ago, NotionCommotion said:

Similar to the __toString() magic method, is there a way to change my PermissionEnum so when type casted as an integer, returns an integer?

As far as I am aware, no.  If you want the numeric value, you access the ->value property. 

I believe what you'll have to do is change your doctrine configuration to not use a generic small int type and instead use specific PermissionEnum type.

Link to comment
Share on other sites

5 minutes ago, NotionCommotion said:

this is what you meant by doctrine configuration, right?

It's unclear to me whether you'd modify that or add a new type since your Permission vs PermissionEnum is confusing to me.  I've not used Enums personally yet, so I was unsure if Doctrine had generic support for them or not.  From that bug report, it looks like it does and you might just need to downgrade for a bit and wait for the fix to get released.

 

Link to comment
Share on other sites

2 hours ago, kicken said:

It's unclear to me whether you'd modify that or add a new type since your Permission vs PermissionEnum is confusing to me.  I've not used Enums personally yet, so I was unsure if Doctrine had generic support for them or not.  From that bug report, it looks like it does and you might just need to downgrade for a bit and wait for the fix to get released.

Yeah, the Permission vs PermissionEnum thing kind of confusing to me as well!  Yes, Doctrine has generic support for them.  Will downgrade and wait it out.  Thanks

PS.  I had tried to throw an __isString() in my enum, but evidently doing so is a no-no.  Guess an __isInt() is a bit too niche and I understand why it doesn't exist.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.