cruxinator/php-bitmask

PHP Bitmask implementation

0.2.0 2023-09-16 06:46 UTC

This package is auto-updated.

Last update: 2024-04-19 10:46:23 UTC


README

Build Status Scrutinizer Code Quality Coverage Status Latest Stable Version Latest Unstable Version Total Downloads Monthly Downloads Daily Downloads

Why?

First, and mainly, myclabs/php-enum is restricted and can't be composited (Enum::FOO() | Enum::BAR() doesn't work too well).

Using a Bitmask instead of an integer provides the following advantages:

  • You can type-hint: function setAction(Bitmask $action) {;
  • You can enrich the Bitmask with methods (e.g. format, parse, …);
  • You can extend the Bitmask to add new values (make your enum final to prevent it);
  • You can get a list of all the possible values (see below);
  • A Bitmask can many enums in a single value.

This Bitmask class is not intended to replace enums, but only to be used when it makes sense.

Installation

composer require cruxinator/php-bitmask

Declaration

use Cruxinator\BitMask\BitMask ;

class UserStatus extends BitMask
{

const Registered = 1; // BIT #1 of $flags has the value 1

const Active = 2; // BIT #2 of $flags has the value 2

const Member = 4; // BIT #3 of $flags has the value 4

const Admin = 8; // BIT #4 of $flags has the value 8

}

Usage

$status = UserStatus::Registered();

// or with a dynamic key:
$status = UserStatus::$key();
// or with a dynamic value:
$status = new UserStatus($value);

// values can then be checked
if ($status->isActive()){
// ...
}

// individuals flags can later toggled ON
$status->setActive(true);
// or off
$status->setActive(false);

As you can see, methods are automatically implemented to provide quick access to a Bitmask value.

One advantage over using class constants is to be able to type-hint Bitmap values:

function setStatus(UserStatus $action) {
    // ...
}

Documentation

  • __construct() The constructor checks that the value can be composed from the enum;
  • __toString() You can echo $myValue, it will display the bitmask value (in an array style format of Boolean)
  • getValue() Returns the current value of the Bitmask
  • getKey() Returns a key arrat of the current composite parts of the Bitmask
  • equals() Tests whether Bitmask instances are equal (returns true if enum values are equal, false otherwise)

Static methods:

  • toArray() Returns all possible values as an array (constant name in key, constant value in value)
  • keys() Returns the names (keys) of all constants in the Enum class
  • values() Returns instances of the Enum class of all Enum constants (constant name in key, Enum instance in value)
  • isValid() Check if tested value is valid on enum set
  • isValidKey() Check if tested key is valid on enum set
  • search() Return key for searched value

dynamic methods

class UserStatus extends BitMask
{
    private const Registered = 1;
    private const Active = 2;
}

// Static method:
$status = UserStatus::Registered();
$status = UserStatus::Active();

// instance methods
$status->isRegistered();
$status->isActive();
$status->setRegistered($bool);
$status->setActive($bool);

Static method helpers are implemented using __callStatic() and __call().

If you care about IDE autocompletion, you can either implement the static methods yourself:

class UserStatus extends BitMask
{
    private const Registered = 1;

    /**
     * @return UserStatus
     */
    public static function Registered() {
        return new UserStatus(self::Registered);
    }
    /**
     * @return bool
     */
    public function isRegistered(){
        return $this->isFlagSet(self::Registered);
    }
    /**
     * @param bool $flag
     * @return self
     */
    public function setRegistered(bool $flag){
        return $this->setFlag(self::Registered, $flag);
    }
}

Or you can use phpdoc (this is supported in PhpStorm for example):

/**
 * @method static UserStatus Registered()
 * @method bool isRegistered()
 * @method UserStatus setRegistered(bool)
 */
class UserStatus extends Bitmask
{
    private const Registered = 1;
}

Related projects