meius / flag-forge
FlagForge is a lightweight, high-performance library for bitwise enumerations. It offers intuitive tools to create, combine, and verify flags for efficient management of Boolean states in applications—ideal for access control, configuration options, and scenarios demanding compact storage and fast p
Fund package maintenance!
Buy Me A Coffee
Requires
- php: >=8.1
Requires (Dev)
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^10
- squizlabs/php_codesniffer: ^3.0
This package is auto-updated.
Last update: 2025-06-12 15:45:00 UTC
README
Table of Contents
- Overview
- Requirements
- Getting Started
- Installation
- Usage
- Database Integration Example
- API Reference
- Support
- License
Overview
The meius/flag-forge
package provides an intuitive API for defining and managing bitwise enumerations in PHP. By
assigning power-of-two values to each flag, the package allows you to combine multiple flags using bitwise operators and
efficiently check individual flags using simple methods.
Requirements
- PHP >= 8.1
Getting Started
To get started with the meius/flag-forge
package, follow the installation instructions below and check out the usage
examples.
Installation
- Install the package via Composer:
composer require meius/flag-forge
Usage
Below is an example enum and how to work with the FlagManager.
enum Permission: int implements Bitwiseable { case SendMessages = 1 << 0; // 1 case DeleteMessages = 1 << 1; // 2 case AddUsers = 1 << 2; // 4 case RemoveUsers = 1 << 3; // 8 case PinMessages = 1 << 4; // 16 case ManageChat = 1 << 5; // 32 case ManageModerators = 1 << 6; // 64 }
Working with FlagManager
use Meius\FlagForge\FlagManager; $manager = new FlagManager(); $manager->getMask(); // Initial mask: 0 // ---------------------------------------------------------------------- // ADD FLAGS // ---------------------------------------------------------------------- $manager->add(Permission::SendMessages) // - The bit corresponding to SendMessages is not set, so it gets added. ->add(Permission::AddUsers) // - The bit for AddUsers is not set, so it is added. ->add(Permission::AddUsers) // - Already set. ->add(Permission::PinMessages) // - The bit for PinMessages is not set, so it is added. ->getMask(); // Expected mask: 21 (SendMessages=1, AddUsers=4, PinMessages=16: 1+4+16=21) // ---------------------------------------------------------------------- // COMBINE FLAGS // ---------------------------------------------------------------------- $manager->combine( Permission::SendMessages, // Already set. Permission::DeleteMessages, // Not set; will be added. Permission::AddUsers // Already set. )->getMask(); // Expected mask: 23 (SendMessages=1, DeleteMessages=2, AddUsers=4, PinMessages=16: 21+2=23) // ---------------------------------------------------------------------- // REMOVE FLAGS // ---------------------------------------------------------------------- $manager->remove(Permission::AddUsers) // - Remove AddUsers: bit is set, so it will be removed. ->remove(Permission::ManageModerators) // - Remove ManageModerators: bit is not set, so nothing changes. ->getMask(); // Expected mask: 19 // ---------------------------------------------------------------------- // TOGGLE FLAGS // ---------------------------------------------------------------------- $manager->toggle( Permission::SendMessages, // Bit is set; toggled off. Permission::DeleteMessages, // Bit is set; toggled off. Permission::AddUsers, // Bit is not set; toggled on. Permission::RemoveUsers // Bit is not set; toggled on. )->getMask(); // Expected mask: 28 // ---------------------------------------------------------------------- // CHECK FLAGS // ---------------------------------------------------------------------- $manager->has(Permission::SendMessages); // false $manager->has(Permission::AddUsers); // true $manager->doesntHave(Permission::SendMessages); // true $manager->doesntHave(Permission::AddUsers); // false // ---------------------------------------------------------------------- // ITERATE OVER ACTIVE FLAGS // ---------------------------------------------------------------------- foreach ($manager as $flag) { /** * Example output: * Active flag: AddUsers (4) * Active flag: RemoveUsers (8) * Active flag: PinMessages (16) */ echo "Active flag: " . $flag->name . " (" . $flag->value . ")" . PHP_EOL; } // ---------------------------------------------------------------------- // CLEAR FLAGS // ---------------------------------------------------------------------- $manager->clear(); // Expected mask: 0
Database Integration Example
FlagForge can be easily integrated with a database. The following example demonstrates how to store and retrieve a flag mask using PDO.
Database Schema and Usage Example
The following section describes the chat_user
table schema used to store user permissions as a bitmask,
provides a few sample records, and shows an example of how to query the database to check a specific permission.
Table Schema: chat_user
Column | Data Type | Constraints | Description |
---|---|---|---|
id | UUID | PRIMARY KEY | Unique identifier for the record. |
chat_id | UUID | FOREIGN KEY, NOT NULL | Identifier of the chat. |
user_id | UUID | FOREIGN KEY, NOT NULL | Identifier of the user. |
permissions | UNSIGNED TINYINT | NOT NULL, DEFAULT (17) | Bitmask representing user permissions. |
Sample Records
Below are a few example rows inserted into the chat_user
table:
id | chat_id | user_id | permissions |
---|---|---|---|
11111111-1111-1111-1111-111111111111 | chat-1234 | user-1234 | 21 |
22222222-2222-2222-2222-222222222222 | chat-1234 | user-5678 | 23 |
33333333-3333-3333-3333-333333333333 | chat-4321 | user-9876 | 5 |
Example Query: Checking a Specific Permission
Suppose you want to check if a specific user in a chat has the "SendMessages" permission.
Assume that the SendMessages
permission corresponds to the bit value 1
(i.e. 1 << 0
).
The following SQL query uses the bitwise AND operator to verify that the permission bit is set:
SELECT * FROM chat_user WHERE chat_id = :chat_id AND user_id = :user_id AND (permissions & :flag) = :flag;
Example PHP Code Using PDO
Below is an example of how you might execute the above query using a PDO instance (assumed to be available as $pdo
):
use Meius\FlagForge\FlagManager; /** * @var PDO $pdo * @var FlagManager $manager * @var string $chatId Chat ID to query. * @var string $userId User ID to query. */ $manager->add(Permission::SendMessages); // Prepare the SQL statement $stmt = $pdo->prepare(' SELECT * FROM chat_user WHERE chat_id = :chat_id AND user_id = :user_id AND (permissions & :flag) = :flag '); // Execute the query with the parameters $stmt->execute([ ':chat_id' => $chatId, ':user_id' => $userId, ':flag' => $manager, ]); // Fetch the result $result = $stmt->fetch(PDO::FETCH_ASSOC); if ($result) { echo "User has the SendMessages permission."; } else { echo "User does NOT have the SendMessages permission."; }
API Reference
FlagManager
add(Bitwiseable $flag): self
— Adds a flag to the current mask.remove(Bitwiseable $flag): self
— Removes a flag from the current mask.combine(Bitwiseable ...$flags): self
— Combines multiple flags into the current mask.toggle(Bitwiseable ...$flags): self
— Toggles specified flags.clear(): self
— Clears all flags in the current mask.has(Bitwiseable $flag): bool
— Checks if the specified flag is present.doesntHave(Bitwiseable $flag): bool
— Checks if the specified flag is not present.getMask(): int
— Returns the current mask value.toArray(): array
— Returns an array representation of the current mask.
Support
For support, please open an issue on the GitHub repository.
Contributing
We welcome contributions to the meius/flag-forge
library. To contribute, follow these steps:
- Fork the Repository: Fork the repository on GitHub and clone it to your local machine.
- Create a Branch: Create a new branch for your feature or bugfix.
- Write Tests: Write tests to cover your changes.
- Run Tests: Ensure all tests pass by running
phpunit
. - Submit a Pull Request: Submit a pull request with a clear description of your changes.
For more details, refer to the CONTRIBUTING.md file.
License
This package is open-sourced software licensed under the MIT license.