path().'/'.$path; } /** * Get module */ function module(string $moduleName): ModuleContract { return modular()->module($moduleName); } /** * Modules * * @return Collection */ function modules(bool $withDisabled = false): Collection { return $withDisabled ? modular()->allModules() : modular()->modules(); } /** * Empty module */ function emptyModule(): ModuleContract { return modular()->emptyModule(); } /** * Module exists */ function module_exists(string $moduleName): bool { return modular()->moduleExists($moduleName); } /** * Create an anonymous dynamic object with both properties and callable methods. * * You can define any mix of: * - scalar or object properties * - closures (which become methods bound to $this) * * Example: * ```php * $user = emptyClass( * name: 'Ali', * greet: fn(): string => "Hello, {$this->name}", * setName: fn(string $n): void => $this->name = $n, * ); * * echo $user->greet(); // Hello, Ali * $user->setName('Ahmet'); * echo $user->greet(); // Hello, Ahmet * ``` * * @template T of object * * @param mixed ...$arguments Key-value pairs (property name => value or Closure) * @return T Anonymous class instance exposing dynamic properties/methods. */ function emptyClass(mixed ...$arguments): object { /** @var T */ return new class($arguments) { /** * Internal data store. * * @var array */ private array $data = []; /** * Constructor that sets up dynamic properties and binds closures. * * @param array $props */ public function __construct(array $props) { foreach ($props as $key => $value) { if ($value instanceof Closure) { /** @var Closure $value */ $value = $value->bindTo($this, self::class); } $this->data[$key] = $value; } } /** * Magic getter. * * @return mixed|null */ public function __get(string $key): mixed { return $this->data[$key] ?? null; } /** * Magic setter. */ public function __set(string $key, mixed $value): void { $this->data[$key] = $value; } /** * Magic isset. */ public function __isset(string $key): bool { return isset($this->data[$key]); } /** * Magic method caller — invokes stored closures as methods. * * @param array $args * * @throws BadMethodCallException if the method does not exist or is not callable. */ public function __call(string $method, array $args): mixed { $callable = $this->data[$method] ?? null; if ($callable instanceof Closure) { return $callable(...$args); } throw new BadMethodCallException(sprintf( 'Method %s() does not exist on %s.', $method, self::class )); } }; }