mirror of
https://codeberg.org/vlw/functionflags.git
synced 2025-09-13 19:03:41 +02:00
feat: add instanced methods
This commit is contained in:
parent
cb38a4007f
commit
288e8129cd
1 changed files with 84 additions and 11 deletions
|
@ -6,11 +6,65 @@
|
|||
// Limit value for debug_backtrace()
|
||||
private static $trace_limit = 5;
|
||||
|
||||
// Methods by name that can be called statically
|
||||
private static $static_public_whitelist = [
|
||||
"static_define",
|
||||
"static_isset"
|
||||
];
|
||||
|
||||
// Methods by name that can be called when instanced
|
||||
private static $inst_public_whitelist = [
|
||||
"inst_define",
|
||||
"inst_isset"
|
||||
];
|
||||
|
||||
public function __construct(string|array $flags = null) {
|
||||
// This array will contain instance defined flags
|
||||
$this->flags = [];
|
||||
|
||||
// Define flags that were initialized with this class
|
||||
if (!empty($flags)) {
|
||||
$this->inst_define($flags);
|
||||
}
|
||||
}
|
||||
|
||||
// We're using the PHP __call() and __callStatic() magic functions here in order to allow
|
||||
// methods to be called with the same name downstream. inst_define() and static_define() can
|
||||
// be called using FunctionFlags::define() and FunctionFlags->define().
|
||||
|
||||
// Call static method on this class
|
||||
public static function __callStatic(string $method, array $args): mixed {
|
||||
// Static methods use this method prefix
|
||||
$method_prefixed = "static_" . $method;
|
||||
|
||||
// Check that method exists on this class and is in whitelist of public static methods
|
||||
if (!in_array($method_prefixed, get_class_methods(__CLASS__)) && !in_array($method_prefixed, (__CLASS__)::$static_public_whitelist)) {
|
||||
throw new \BadMethodCallException("Method '${method}' does not exist");
|
||||
}
|
||||
|
||||
return (__CLASS__)::{$method_prefixed}(...$args);
|
||||
}
|
||||
|
||||
// Call instanced method on this class
|
||||
public function __call(string $method, array $args): mixed {
|
||||
// Instanced methods use this method prefix
|
||||
$method_prefixed = "inst_" . $method;
|
||||
|
||||
// Check that method exists on this class and is in whitelist of public instanced methods
|
||||
if (!in_array($method_prefixed, get_class_methods(__CLASS__)) && !in_array($method_prefixed, (__CLASS__)::$inst_public_whitelist)) {
|
||||
throw new \BadMethodCallException("Method '${method}' does not exist");
|
||||
}
|
||||
|
||||
return $this->{$method_prefixed}(...$args);
|
||||
}
|
||||
|
||||
/* ---- */
|
||||
|
||||
// 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;
|
||||
$_ENV[__CLASS__] = 1;
|
||||
}
|
||||
|
||||
// Increment counter
|
||||
|
@ -21,18 +75,18 @@
|
|||
|
||||
// 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);
|
||||
// Get call stack in reverse order
|
||||
$stack = array_reverse(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")));
|
||||
// Find first occurance of this class name in callstack
|
||||
$idx = array_search(__CLASS__, 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"];
|
||||
// Get args array from initial caller by simply stepping back one entry in the reverse array
|
||||
$args = $stack[$idx - 1]["args"];
|
||||
|
||||
// Return null if no arguments provided or not a valid int flag
|
||||
return !empty($args) && is_int(end($args)) ? end($args) : null;
|
||||
|
@ -41,7 +95,7 @@
|
|||
/* ---- */
|
||||
|
||||
// Define new constants
|
||||
public static function define(string|array $flags) {
|
||||
private static function static_define(string|array $flags) {
|
||||
// Convert to array
|
||||
$flags = is_array($flags) ? $flags : [$flags];
|
||||
|
||||
|
@ -52,8 +106,27 @@
|
|||
}
|
||||
|
||||
// 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();
|
||||
private static function static_isset(int $flag): bool|null {
|
||||
$flags = (__CLASS__)::get_flags_from_caller();
|
||||
return $flags ? $flags & $flag : null;
|
||||
}
|
||||
|
||||
/* ---- */
|
||||
|
||||
private function inst_define(string|array $flags) {
|
||||
// Convert to array
|
||||
$flags = is_array($flags) ? $flags : [$flags];
|
||||
|
||||
// Define constants
|
||||
$this::static_define($flags);
|
||||
// Append flag(s) to instance memory
|
||||
$this->flags = array_merge($this->flags, $flags);
|
||||
}
|
||||
|
||||
// Check if flag is set within instance scope
|
||||
private function inst_isset(int $flag): bool|null {
|
||||
$test = $this::static_isset($flag);
|
||||
// Filter flags that belong to this scope
|
||||
return in_array($this::static_isset($flag), $this->flags);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue