codekandis/phlags

`codekandis/phlags` introduces the possibility to use flagable enums in PHP.

4.0.0 2024-05-16 22:39 UTC

This package is auto-updated.

Last update: 2024-05-16 22:50:05 UTC


README

Version License Minimum PHP Version Code Coverage

With Phlags you can declare flagable enums to provide types with varying and multiple states. While depending on binary operations Phlags provides high performance and reliabilty.

Index

Installation

Install the latest version with

$ composer require codekandis/phlags

How to use

Example: Simple permissions in a file system

Declaration

Declare a class extending the flagable base class AbstractFlagable.

class Permissions extends AbstractFlagable
{
    public const int READ    = 1;
    public const int WRITE   = 2;
    public const int EXECUTE = 4;
}

General Hints

In the context of manipulating the flagable the following values are supposed to be equal and can similarly passed to all methods of the flagable.

1
Permissions::READ
new Permissions( 1 )
new Permissions( Permission::READ )
new Permissions( 'READ' );

In the other hand the type restriction of PHP does not allow any combination of an integer value with a string with a flagable.

new Permission( 1 | 'READ' | new Permissions( READ ) )

Instantiation

You can easily instantiate your flagable in different ways.

// with the default flag 'Permissions::NONE' (inherited from `FlagableInterface::NONE`)
$permissions = new Permissions();

// with a single flag
$permissions = new Permissions( Permissions::READ );

// with multiple flags
$permissions = new Permissions( Permissions::READ | Permissions::WRITE );

// with another flagable
$permissions = new Permissions( new Permissions( Permissions::READ ) );

// with string representations
$permissions = new ( 'READ' );
$permissions = new ( 'READ|WRITE' );
$permissions = new ( 'READ|WRITE|EXECUTE' );

// with mixed string representations
$permissions = new ( '1' );
$permissions = new ( '1|2' );
$permissions = new ( '1|WRITE|4' );

Reading

You can read the value of the flagable in 2 different ways.

$permissions = new Permissions( Permissions::READ );
echo $permissions->getValue();  // 1
echo $permissions();            // 1

Determination

You can determine if one or more specific flags have been set.

$permissions = new Permissions( Permissions::READ | Permissions::WRITE );
$permissions->has( Permissions::READ );     // true
$permissions->has( Permissions::WRITE );    // true
$permissions->has( Permissions::EXECUTE );  // false

Manipulation

You can set, unset and switch flags.

$permissions = new Permissions();
$permissions->set( Permissions::READ );
$permissions->unset( Permissions::READ );
$permissions->switch( Permissions::READ );
$permissions->has( Permissions::READ );     // true

Fluent Manipulation

The base class AbstractFlagable implements the fluent interface. So the manipulation of the flagable can be chained.

$permissions = new Permissions();
$permissions->set( Permissions::READ )
            ->unset( Permissions::READ )
            ->switch( Permissions::READ )
            ->has( Permissions::READ );    // true

String Representation

A flagable can stringified in different ways with different outputs.

$permissions = new Permissions();
(string)$permissions->getValue();  // 0
(string)$permissions();            // 0
(string)$permissions;              // NONE
$permissions->__toString();        // NONE

$permissions = new Permissions( PERMISSIONS::READ | PERMISSIONS::EXECUTE );
(string)$permissions->getValue();  // 5
(string)$permissions();            // 5
(string)$permissions;              // READ|EXECUTE
$permissions->__toString();        // READ|EXECUTE

Traitful Extensions

To keep the simplicity and performance Phlags provides Traitful Extensions. Instead of implementing a complex and heavyweight inheritance you can combine the extensions of your choice into the flagable of your needs.

class Permissions extends AbstractFlagable SomeTraitfulInterface
{
    use SomeTraitfulExtension;

    public const int READ    = 1;
    public const int WRITE   = 2;
    public const int EXECUTE = 4;
}

Conditional Manipulation

ConditionalManipulationExtension

The Conditional Manipulation provides you with methods to set, unset and switch a flag value while a passed statement must evaluate to true.

$pathToFile = '/some-random-file.txt';
$permissions = new Permissions();
$permissions->ifSet( Permissions::DIRECTORY, is_dir( $pathToFile ) );
$permissions->has( Permissions::DIRECTORY );  // false

$pathToFile = '/some-random-directory';
$permissions = new Permissions();
$permissions->ifSet( Permissions::DIRECTORY, is_dir( $pathToDirectory ) );
$permissions->has( Permissions::DIRECTORY );  // true

Validation

Flagables

While instantiating your very first flagable your flagable has to pass a one-time validation.

  • all declared constants are an unsigned integer
  • all constants are a power of 2
  • there is no duplicates of any of the constant values
  • there is no missing values, e. g. a flagable with a flags set 1, 2, 8 ist invalid, while the flag 4 is missing

If the flagable does not pass the validation an InvalidFlagableException will be thrown and you can retreive an array of detailed error messages of the validation.

try
{
    $permissions = new Permissions();
}
catch ( InvalidFlagableException $e )
{
    $errorMessages = $e->getErrorMessages();
}

Values

A flag value passed to the methods of the flagable has to pass a validation on every method call.

  • it is an unsigned integer less or equal than the maximum value of the called flagable
  • it is a string representation of a flagable with an identic type as the type of the called flagable
  • it is a flagable with an identic type as the type of the called flagable
  • it does not exceeds the maximum flag value of the called flagable

If the value does not pass the validation an InvalidValueException will be thrown and you can retreive an array of detailed error messages of the validation.

try
{
    $permissions->set( $value );
}
catch ( InvalidValueException $e )
{
    $errorMessages = $e->getErrorMessages();
}