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