DynamicAccess.php

<?php

namespace Phad\Integration;

/**
 * A base class for access controls that allows all READ operations, no WRITE (*insert/update/delete*) operations, and returns false for `user_has_role()`.
 *
 */
class DynamicAccess implements \Phad\AccessInterface {

    /** callable for `item_initialized()` */
    public $item_initialized;
    /** callable for `call()`. This is only called if `call_handlers[]` does not have a matching handler. */
    public $call;
    /** callable for `can_read_row()` */
    public $can_read_row;
    /** callable for `can_read_row()` */
    public $user_has_role;
    /** Array of call handlers. Key is the `what` in `call:what`, and value is a callable with the same method signature as call() */
    public array $call_handlers = [];
    
    /**
     * Does nothing unless you set a custom handler
     */
    public function item_initialized(object $ItemInfo): void {
        if (isset($this->item_initialized))($this->item_initialized)($ItemInfo);
    }


    /**
     * When `call:something` is added to the `access` attribute of a node, this method is called and must return true or false.
     *
     * @param $caller \Phad\Caller tells you where `call()` is being called from, like did_delete() or can_submit(), etc.
     * @param $what string the thing being called - the string to the right of the colon. In `call:something`, this would be `"something"`
     *
     * @return false unless you set a custom call handler
     *
     */
    public function call(\Phad\Caller $caller, string $what, ?object $ItemInfo, ...$args): bool {
        if (isset($this->call_handlers[$what]))return ($this->call_handlers[$what])($caller,$what,$ItemInfo,...$args);
        else if (isset($this->call))return ($this->call)($caller,$what,$ItemInfo,...$args);
        return false;
    }

    /**
     * When a template's data is being loaded, either via a query (*default*) or a custom data_loader, every row is passed to this method. For each row that returns `true`, it will be included in the final resultset. 
     *
     * If data is passed to your template (*rather than loaded by the template*), then this method will not be called.
     * @return true unless you set a custom can_read_row handler
     */
    public function can_read_row(array $ItemRow, object $ItemInfo, string $ItemName): bool {
        if (isset($this->can_read_row))return ($this->can_read_row)($ItemRow, $ItemInfo, $ItemName);

        return true;
    }



    /**
     * Check if the currently logged-in user has the given role. You may use this to check multiple roles, like `role:a&b&c` or you can use multiple separate role checks like `role:a;role:b;role:c`
     *
     * @param $role string There is no required format for `$role`. In access declarations like `role:whatever`, `$role` is whatever's to the right of the colon.
     *
     * @return false unless you set a custom user_has_role handler
     */
    public function user_has_role(string $role): bool {
        if (isset($this->user_has_role))return ($this->user_has_role)($role);

        return false;
    }
}