mirror of
https://codeberg.org/vlw/functionflags.git
synced 2025-09-13 19:03:41 +02:00
initial code commit
This commit is contained in:
parent
ca16497b80
commit
4663cf90e4
4 changed files with 215 additions and 0 deletions
48
.gitignore
vendored
Normal file
48
.gitignore
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
# Bootstrapping #
|
||||
#################
|
||||
/node_modules
|
||||
/public/hot
|
||||
/public/storage
|
||||
/storage/*.key
|
||||
/vendor
|
||||
.env
|
||||
.env.backup
|
||||
.phpunit.result.cache
|
||||
Homestead.json
|
||||
Homestead.yaml
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
|
||||
# OS generated files #
|
||||
######################
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
Icon?
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
.directory
|
||||
|
||||
# Tool specific files #
|
||||
#######################
|
||||
# vim
|
||||
*~
|
||||
*.swp
|
||||
*.swo
|
||||
# sublime text & textmate
|
||||
*.sublime-*
|
||||
*.stTheme.cache
|
||||
*.tmlanguage.cache
|
||||
*.tmPreferences.cache
|
||||
# Eclipse
|
||||
.settings/*
|
||||
# JetBrains, aka PHPStorm, IntelliJ IDEA
|
||||
.idea/*
|
||||
# NetBeans
|
||||
nbproject/*
|
||||
# Visual Studio Code
|
||||
.vscode
|
||||
# Sass preprocessor
|
||||
.sass-cache/
|
92
README.md
Normal file
92
README.md
Normal file
|
@ -0,0 +1,92 @@
|
|||
# FunctionFlags
|
||||
|
||||
A library that aims to make it a bit easier to use PHP constants as function/method flags.
|
||||
|
||||
Flags can be defined and checked globally by calling `FunctionFlags`'s static methods.
|
||||
```php
|
||||
use FunctionFlags/FunctionFlags
|
||||
|
||||
// Define global flags for use anywhere for this runtime
|
||||
FunctionFlags::define([
|
||||
"MY_FLAG",
|
||||
"OTHER_FLAG"
|
||||
]);
|
||||
|
||||
// Returns true if MY_FLAG is passed
|
||||
function foo(int $flags = null): bool {
|
||||
return FunctionFlags::isset(MY_FLAG);
|
||||
}
|
||||
|
||||
foo(MY_FLAG); // true
|
||||
foo(OTHER_FLAG|MY_FLAG); // true
|
||||
foo(OTHER_FLAG); // false
|
||||
foo(); // false
|
||||
```
|
||||
|
||||
Flags can also be scoped to a class by creating a new `FunctionFlags` instance. Only flags defined in this instance will be matched
|
||||
```php
|
||||
use FunctionFlags/FunctionFlags
|
||||
|
||||
$my_flag = new FunctionFlags("MY_FLAG");
|
||||
$other_flag = new FunctionFlags("OTHER_FLAG");
|
||||
|
||||
// Returns true if MY_FLAG is passed and present in $my_flag
|
||||
function foo(int $flags = null): bool {
|
||||
return $my_flag->isset(MY_FLAG);
|
||||
}
|
||||
|
||||
foo(MY_FLAG); // true
|
||||
foo(OTHER_FLAG|MY_FLAG); // true
|
||||
foo(OTHER_FLAG); // false
|
||||
foo(); // false
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
Requires PHP 8.1 or newer
|
||||
|
||||
1. **Install composer package**
|
||||
```
|
||||
composer require victorwesterlund/functionflags
|
||||
```
|
||||
|
||||
2. **Include FunctionFlags in your project**
|
||||
```php
|
||||
use FunctionFlags/FunctionFlags
|
||||
```
|
||||
|
||||
3. **Define some flags** (Using static approach for demo)
|
||||
```php
|
||||
FunctionFlags::define([
|
||||
"MY_FLAG",
|
||||
"OTHER_FLAG"
|
||||
]);
|
||||
```
|
||||
|
||||
4. **Add a function which accepts flags**
|
||||
```php
|
||||
// 1. If your function takes more than 1 argument. The "flags" variable MUST be the last.
|
||||
// 2. It's recommended to make your "flags" variable default to some value if empty to make flags optional.
|
||||
function foo($bar = null, int $flags = null): bool {
|
||||
return FunctionFlags::isset(MY_FLAG);
|
||||
}
|
||||
```
|
||||
|
||||
5. **Use flags in function calls**
|
||||
```php
|
||||
// Your function can now accept flags. One or many using the Union operator `|`
|
||||
foo("hello world", OTHER_FLAG|MY_FLAG);
|
||||
```
|
||||
|
||||
## Methods
|
||||
|
||||
Static|Description
|
||||
--|--
|
||||
`FunctionFlags::define(string\|array)`|Flag(s) to define as string or array of string. This method must be called before using the flag(s).
|
||||
`FunctionFlags::isset(constant)`|The constant you wish to check is set on your function or method call.
|
||||
|
||||
Instanced|Description
|
||||
--|--
|
||||
`new FunctionFlags(string\|array\|null)`|Flag(s) to define as string or array of string. This method must be called before using the flag(s).
|
||||
`FunctionFlags->define(string\|array)`|Flag(s) to define as string or array of string. This method must be called before using the flag(s).
|
||||
`FunctionFlags->isset(constant)`|The constant you wish to check is set on your function or method call.
|
19
composer.json
Normal file
19
composer.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "victorwesterlund/functionflags",
|
||||
"description": "An attempt to tame PHP constants for use as function/method flags",
|
||||
"type": "library",
|
||||
"license": "GPL-3.0-only",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Victor Westerlund",
|
||||
"email": "victor.vesterlund@gmail.com"
|
||||
}
|
||||
],
|
||||
"minimum-stability": "dev",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FunctionFlags\\": "src/FunctionFlags/"
|
||||
}
|
||||
},
|
||||
"require": {}
|
||||
}
|
56
src/FunctionFlags/FunctionFlags.php
Normal file
56
src/FunctionFlags/FunctionFlags.php
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
class FunctionFlags {
|
||||
// Limit value for debug_backtrace()
|
||||
private static $trace_limit = 5;
|
||||
|
||||
// Reserve a constant address space
|
||||
private static function addr_reserve(): int {
|
||||
// Set initial value when first flag is defined
|
||||
if (empty($_ENV[__CLASS__])) {
|
||||
$_ENV[__CLASS__] = 0;
|
||||
}
|
||||
|
||||
// Increment counter
|
||||
$_ENV[__CLASS__]++;
|
||||
// Return counter as power of 2
|
||||
return $_ENV[__CLASS__] ** 2;
|
||||
}
|
||||
|
||||
// Get flags from caller closest to this method on the call stack
|
||||
private static function get_flags_from_caller(): int|null {
|
||||
// Get call stack
|
||||
$stack = debug_backtrace(0, (__CLASS__)::$trace_limit);
|
||||
|
||||
// Extract class names from callstack in reverse order and find the first occurance of this class in the backtrace
|
||||
$idx = array_search(__CLASS__, array_reverse(array_column($stack, "class")));
|
||||
// Failed to locate this class in a full backtrace
|
||||
if ($idx === false) {
|
||||
throw new Exception("Failed to retrieve flags from initator callable");
|
||||
}
|
||||
|
||||
// Get args array from stack entry by index
|
||||
$args = $stack[$idx]["args"];
|
||||
|
||||
return !empty($args) ? end($args) : null;
|
||||
}
|
||||
|
||||
/* ---- */
|
||||
|
||||
// Define new constants
|
||||
public static function define(string|array $flags) {
|
||||
// Convert to array
|
||||
$flags = is_array($flags) ? $flags : [$flags];
|
||||
|
||||
// Define constant for each flag with unique address
|
||||
foreach ($flags as $flag) {
|
||||
define($flag, (__CLASS__)::addr_reserve());
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a flag is set with bitwise AND of all flags
|
||||
public static function isset(int $flag): bool|null {
|
||||
$flags = FunctionFlags::get_flags_from_caller();
|
||||
return $flags ? $flags & $flag : null;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue