. namespace core_ai; use core_ai\form\action_settings_form; use Spatie\Cloneable\Cloneable; /** * Class provider. * * @package core_ai * @copyright 2024 Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ abstract class provider { use Cloneable; /** @var string $provider The provider used to make this instance */ public readonly string $provider; /** @var array The configuration for this instance. */ public readonly array $config; /** @var array The action specific settings for this instance. */ public readonly array $actionconfig; /** * Create a new provider. * * @param bool $enabled Whether the gateway is enabled * @param string $name The name of the provider config. * @param string $config The configuration for this instance. * @param string $actionconfig The action specific settings for this instance. * @param int|null $id The id of the provider in the database. */ public function __construct( /** @var bool Whether the gateway is enabled */ public readonly bool $enabled, /** @var string The name of the provider config. */ public string $name, string $config, string $actionconfig = '', /** @var null|int The ID of the provider in the database, or null if it has not been persisted yet. */ public readonly ?int $id = null, ) { $this->provider = strstr(get_class($this), '\\', true); $this->config = json_decode($config, true); if ($actionconfig == '') { $this->actionconfig = static::initialise_action_settings(); } else { $this->actionconfig = json_decode($actionconfig, true); } } /** * Get the actions that this provider supports. * * Returns an array of action class names. * * @return array An array of action class names. */ abstract public static function get_action_list(): array; /** * Initialise the action settings array. * * @return array The initialised action settings. */ public static function initialise_action_settings(): array { $actions = static::get_action_list(); $actionconfig = []; foreach ($actions as $action) { $actionconfig[$action] = [ 'enabled' => true, 'settings' => static::get_action_setting_defaults($action), ]; } return $actionconfig; } /** * Given an action class name, return an array of sub actions * that this provider supports. * * @param string $classname The action class name. * @return array An array of supported sub actions. */ public function get_sub_actions(string $classname): array { return []; } /** * Get the name of the provider. * * @return string The name of the provider. */ public function get_name(): string { return \core\component::get_component_from_classname(get_class($this)); } /** * Get any action settings for this provider. * * @param string $action The action class name. * @param array $customdata The customdata for the form. * @return action_settings_form|bool The settings form for this action or false in no settings. */ public static function get_action_settings( string $action, array $customdata = [], ): action_settings_form|bool { return false; } /** * Get the default settings for an action. * * @param string $action The action class name. * @return array The default settings for the action. */ public static function get_action_setting_defaults(string $action): array { return []; } /** * Check if the request is allowed by the rate limiter. * * @param aiactions\base $action The action to check. * @return array|bool True on success, array of error details on failure. */ public function is_request_allowed(aiactions\base $action): array|bool { $ratelimiter = \core\di::get(rate_limiter::class); $component = \core\component::get_component_from_classname(get_class($this)); // Check the user rate limit. if (isset($this->config['enableuserratelimit']) && $this->config['enableuserratelimit']) { if (!$ratelimiter->check_user_rate_limit( component: $component, ratelimit: $this->config['userratelimit'], userid: $action->get_configuration('userid') )) { return [ 'success' => false, 'errorcode' => 429, 'errormessage' => 'User rate limit exceeded', ]; } } // Check the global rate limit. if (isset($this->config['enableglobalratelimit']) && $this->config['enableglobalratelimit']) { if (!$ratelimiter->check_global_rate_limit( component: $component, ratelimit: $this->config['globalratelimit'] )) { return [ 'success' => false, 'errorcode' => 429, 'errormessage' => 'Global rate limit exceeded', ]; } } return true; } /** * Check if a provider has the minimal configuration to work. * * @return bool Return true if configured. */ public function is_provider_configured(): bool { return false; } /** * Convert this object to a stdClass, suitable for saving to the database. * * @return \stdClass */ public function to_record(): \stdClass { return (object) [ 'id' => $this->id, 'name' => $this->name, 'provider' => get_class($this), 'enabled' => $this->enabled, 'config' => json_encode($this->config), 'actionconfig' => json_encode($this->actionconfig), ]; } }