commit b48881a8a4f0df13dbcbcf7f980c6aad6cd145e1 Author: Llewellyn van der Merwe Date: Fri Jun 28 04:10:38 2024 +0200 First release diff --git a/README.md b/README.md new file mode 100644 index 0000000..f47bf70 --- /dev/null +++ b/README.md @@ -0,0 +1,74 @@ +# Vdm Openai (1.0.0) + +VDM OpenAi Library + +## Details + +- Packager: [OctoPower v2.0](https://git.vdm.dev/octoleo/octopower) +- Author: [Llewellyn van der Merwe](https://io.vdm.dev) +- Creation Date: June 2024 + +### Installation via Composer + +Setup this registry in your `~/.composer/config.json` file: +``` +{ + "repositories": [{ + "type": "composer", + "url": "https://git.vdm.dev/api/packages/joomla/composer" + } + ] +} +``` + +To install the package using Composer, run the following command: +``` +composer require vdm/openai:1.0.0 +``` + +## Joomla Framework Dependencies + +>We have added the following framework classes to the required list of this Composer package. + +- Joomla/DI "^3.0" + - [VastDevelopmentMethod\Openai\Joomla\Openai\Factory](src/VastDevelopmentMethod/Openai/Joomla/Openai/Factory.php) + - [VastDevelopmentMethod\Openai\Joomla\Abstraction\Factory](src/VastDevelopmentMethod/Openai/Joomla/Abstraction/Factory.php) + - [VastDevelopmentMethod\Openai\Joomla\Interfaces\FactoryInterface](src/VastDevelopmentMethod/Openai/Joomla/Interfaces/FactoryInterface.php) + - [VastDevelopmentMethod\Openai\Joomla\Openai\Service\Api](src/VastDevelopmentMethod/Openai/Joomla/Openai/Service/Api.php) + - [VastDevelopmentMethod\Openai\Joomla\Openai\Audio](src/VastDevelopmentMethod/Openai/Joomla/Openai/Audio.php) + - [VastDevelopmentMethod\Openai\Joomla\Openai\Abstraction\Api](src/VastDevelopmentMethod/Openai/Joomla/Openai/Abstraction/Api.php) + - [VastDevelopmentMethod\Openai\Joomla\Openai\Service\Utilities](src/VastDevelopmentMethod/Openai/Joomla/Openai/Service/Utilities.php) +- Joomla/Filter "^3.0" + - [VastDevelopmentMethod\Openai\Joomla\Utilities\StringHelper](src/VastDevelopmentMethod/Openai/Joomla/Utilities/StringHelper.php) +- Joomla/Input "^3.0" + - [VastDevelopmentMethod\Openai\Joomla\Utilities\Component\Helper](src/VastDevelopmentMethod/Openai/Joomla/Utilities/Component/Helper.php) + - [VastDevelopmentMethod\Openai\Joomla\Utilities\String\NamespaceHelper](src/VastDevelopmentMethod/Openai/Joomla/Utilities/String/NamespaceHelper.php) +- Joomla/Registry "^3.0" + - [VastDevelopmentMethod\Openai\Joomla\Openai\Utilities\Http](src/VastDevelopmentMethod/Openai/Joomla/Openai/Utilities/Http.php) + - [VastDevelopmentMethod\Openai\Joomla\Utilities\Component\Helper](src/VastDevelopmentMethod/Openai/Joomla/Utilities/Component/Helper.php) + - [VastDevelopmentMethod\Openai\Joomla\Utilities\String\NamespaceHelper](src/VastDevelopmentMethod/Openai/Joomla/Utilities/String/NamespaceHelper.php) +- Joomla/Uri "^3.0" + - [VastDevelopmentMethod\Openai\Joomla\Openai\Utilities\Uri](src/VastDevelopmentMethod/Openai/Joomla/Openai/Utilities/Uri.php) + + +## Joomla CMS Dependencies + +- Joomla\CMS\Component\ComponentHelper + - [VastDevelopmentMethod\Openai\Joomla\Utilities\Component\Helper](src/VastDevelopmentMethod/Openai/Joomla/Utilities/Component/Helper.php) + - [VastDevelopmentMethod\Openai\Joomla\Utilities\String\NamespaceHelper](src/VastDevelopmentMethod/Openai/Joomla/Utilities/String/NamespaceHelper.php) +- Joomla\CMS\Factory + - [VastDevelopmentMethod\Openai\Joomla\Utilities\Component\Helper](src/VastDevelopmentMethod/Openai/Joomla/Utilities/Component/Helper.php) + - [VastDevelopmentMethod\Openai\Joomla\Utilities\String\NamespaceHelper](src/VastDevelopmentMethod/Openai/Joomla/Utilities/String/NamespaceHelper.php) + - [VastDevelopmentMethod\Openai\Joomla\Utilities\GetHelper](src/VastDevelopmentMethod/Openai/Joomla/Utilities/GetHelper.php) +- Joomla\CMS\Http\Http + - [VastDevelopmentMethod\Openai\Joomla\Openai\Utilities\Http](src/VastDevelopmentMethod/Openai/Joomla/Openai/Utilities/Http.php) +- Joomla\CMS\Http\Response + - [VastDevelopmentMethod\Openai\Joomla\Openai\Utilities\Response](src/VastDevelopmentMethod/Openai/Joomla/Openai/Utilities/Response.php) + - [VastDevelopmentMethod\Openai\Joomla\Utilities\JsonHelper](src/VastDevelopmentMethod/Openai/Joomla/Utilities/JsonHelper.php) +- Joomla\CMS\Language\Language + - [VastDevelopmentMethod\Openai\Joomla\Utilities\StringHelper](src/VastDevelopmentMethod/Openai/Joomla/Utilities/StringHelper.php) + + +### License +> GNU General Public License version 2 or later + diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..d2044ab --- /dev/null +++ b/composer.json @@ -0,0 +1,32 @@ +{ + "name": "vdm/openai", + "type": "library", + "description": "VDM OpenAi Library", + "homepage": "https://git.vdm.dev/joomla/vdm-openai", + "license": "GNU General Public License version 2 or later", + "require": { + "php": "^8.1.0", + "Joomla/DI": "^3.0", + "Joomla/Filter": "^3.0", + "Joomla/Input": "^3.0", + "Joomla/Registry": "^3.0", + "Joomla/Uri": "^3.0" + }, + "autoload": { + "psr-4": { + "VastDevelopmentMethod\\Openai\\": "src/VastDevelopmentMethod/Openai" + } + }, + "keywords": [ + "VDM", + "OpenAi", + "SuperPower" + ], + "authors": [ + { + "name": "Llewellyn van der Merwe", + "email": "joomla@vdm.io", + "homepage": "https://io.vdm.dev" + } + ] +} diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Abstraction/Factory.php b/src/VastDevelopmentMethod/Openai/Joomla/Abstraction/Factory.php new file mode 100644 index 0000000..dcb198e --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Abstraction/Factory.php @@ -0,0 +1,83 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Abstraction; + + +use Joomla\DI\Container; +use VastDevelopmentMethod\Openai\Joomla\Interfaces\FactoryInterface; + + +/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** + ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** + ** + ** In realms of code where purists frown, the anti-pattern wears a crown, + ** A paradox of chaos bright, where complex paths lose all its slight. + ** For in its tangled, wild embrace, lies raw creativity's face, + ** No rigid forms, no strict decree, just boundless, daring artistry. + ** In flaws, we find the freedom's key, where messy code and brilliance spree, + ** A dance of thought, unchained, unbound, in anti-pattern, beauty's found. + ** + ** Perfect Paradox and True Nature of the Anti-Pattern by ChatGPT + ** + ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** + ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** + ** + ** @since 0.0.0 + **/ +abstract class Factory implements FactoryInterface +{ + /** + * Global Package Container + * + * @var Container|null + * @since 0.0.0 + **/ + protected static ?Container $container = null; + + /** + * Get any class from the package container + * + * @param string $key The container class key + * + * @return Mixed + * @since 0.0.0 + */ + public static function _($key) + { + return static::getContainer()->get($key); + } + + /** + * Get the global package container + * + * @return Container + * @since 0.0.0 + */ + public static function getContainer(): Container + { + if (!static::$container) + { + static::$container = static::createContainer(); + } + + return static::$container; + } + + /** + * Create a container object + * + * @return Container + * @since 0.0.0 + */ + abstract protected static function createContainer(): Container; +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Interfaces/FactoryInterface.php b/src/VastDevelopmentMethod/Openai/Joomla/Interfaces/FactoryInterface.php new file mode 100644 index 0000000..55c2fb8 --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Interfaces/FactoryInterface.php @@ -0,0 +1,43 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Interfaces; + + +use Joomla\DI\Container; + + +/** + * The Container Factory Interface + * + * @since 0.0.0 + */ +interface FactoryInterface +{ + /** + * Get any class from the container + * + * @param string $key The container class key + * + * @return Mixed + * @since 0.0.0 + */ + public static function _(string $key); + + /** + * Get the global container + * + * @return Container + * @since 0.0.0 + */ + public static function getContainer(): Container; +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Openai/Abstraction/Api.php b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Abstraction/Api.php new file mode 100644 index 0000000..2e2e8b5 --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Abstraction/Api.php @@ -0,0 +1,67 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Openai\Abstraction; + + +use VastDevelopmentMethod\Openai\Joomla\Openai\Utilities\Http; +use VastDevelopmentMethod\Openai\Joomla\Openai\Utilities\Uri; +use VastDevelopmentMethod\Openai\Joomla\Openai\Utilities\Response; + + +/** + * The Openai Api + * + * @since 3.2.0 + */ +abstract class Api +{ + /** + * The Http class + * + * @var Http + * @since 3.2.0 + */ + protected Http $http; + + /** + * The Uri class + * + * @var Uri + * @since 3.2.0 + */ + protected Uri $uri; + + /** + * The Response class + * + * @var Response + * @since 3.2.0 + */ + protected Response $response; + + /** + * Constructor. + * + * @param Http $http The http class. + * @param Uri $uri The uri class. + * @param Response $response The response class. + * + * @since 3.2.0 + **/ + public function __construct(Http $http, Uri $uri, Response $response) + { + $this->http = $http; + $this->uri = $uri; + $this->response = $response; + } +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Openai/Audio.php b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Audio.php new file mode 100644 index 0000000..18d1516 --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Audio.php @@ -0,0 +1,138 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Openai; + + +use VastDevelopmentMethod\Openai\Joomla\Openai\Abstraction\Api; + + +/** + * The Openai Audio + * + * @since 3.2.0 + */ +class Audio extends Api +{ + /** + * Transcribes audio into the input language. + * API Ref: https://platform.openai.com/docs/api-reference/audio/create + * + * @param string $file The audio file to transcribe. Formats: mp3, mp4, mpeg, mpga, m4a, wav, or webm (required). + * @param string|null $prompt An optional text to guide the model's style (optional). + * @param string|null $responseFormat The format of the transcript output. Options: json, text, srt, verbose_json, or vtt (optional). + * @param float|null $temperature The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic (optional). + * @param string|null $language The language of the input audio (optional). + * @param string $model ID of the model to use. Only "whisper-1" is currently available. + * + * @return object|null + * @since 3.2.0 + **/ + public function transcribe( + string $file, + ?string $prompt = null, + ?string $responseFormat = null, + ?float $temperature = null, + ?string $language = null, + string $model = 'whisper-1' + ): ?object + { + // Build the request path. + $path = "/audio/transcriptions"; + + // Set the request data. + $data = new \stdClass(); + $data->file = $file; + + if ($prompt !== null) + { + $data->prompt = $prompt; + } + + if ($responseFormat !== null) + { + $data->response_format = $responseFormat; + } + + if ($temperature !== null) + { + $data->temperature = $temperature; + } + + if ($language !== null) + { + $data->language = $language; + } + + $data->model = $model; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data), ['Content-Type' => 'multipart/form-data'] + ) + ); + } + + /** + * Translate an audio file into English. + * API Ref: https://platform.openai.com/docs/api-reference/audio/create + * + * @param string $file The the audio file. Formats: mp3, mp4, mpeg, mpga, m4a, wav, or webm (required). + * @param string|null $prompt An optional text to guide the model's style or continue a previous audio segment. The prompt should be in English (optional). + * @param string|null $responseFormat The format of the transcript output. Options: json, text, srt, verbose_json, or vtt (optional). + * @param float|null $temperature The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic (optional). + * @param string $model ID of the model to use. Only "whisper-1" is currently available. + * + * @return object|null + * @since 3.2.0 + **/ + public function translation( + string $file, + ?string $prompt = null, + ?string $responseFormat = null, + ?float $temperature = null, + string $model = 'whisper-1' + ): ?object + { + // Build the request path. + $path = "/audio/translations"; + + // Set the data. + $data = new \stdClass(); + $data->file = $file; + + if ($prompt !== null) + { + $data->prompt = $prompt; + } + + if ($responseFormat !== null) + { + $data->response_format = $responseFormat; + } + + if ($temperature !== null) + { + $data->temperature = $temperature; + } + + $data->model = $model; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data), ['Content-Type' => 'multipart/form-data'] + ) + ); + } +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Openai/Chat.php b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Chat.php new file mode 100644 index 0000000..40310ba --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Chat.php @@ -0,0 +1,142 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Openai; + + +use VastDevelopmentMethod\Openai\Joomla\Openai\Abstraction\Api; + + +/** + * The Openai Chat + * + * @since 3.2.0 + */ +class Chat extends Api +{ + /** + * Create a chat completion with the OpenAI API. + * API Ref: https://platform.openai.com/docs/api-reference/chat/create + * + * @param string $model The model to use for completion. + * @param array $messages A list of messages describing the conversation so far. + * + * Each item in the array is an object with the following: + * - role (string) Required + * The role of the author of this message. + * One of system, user, or assistant. + * - content (string) Required + * The contents of the message. + * - name (string) Optional + * The name of the author of this message. + * May contain a-z, A-Z, 0-9, and underscores, + * with a maximum length of 64 characters. + * + * @param int|null $maxTokens Maximum number of tokens to generate (optional). + * @param float|null $temperature The sampling temperature to use (optional). + * @param float|null $topP The nucleus sampling parameter (optional). + * @param int|null $n The number of chat completion choices to generate (optional). + * @param bool|null $stream Partial message deltas (optional). + * @param mixed|null $stop Sequences where the API will stop generating tokens (optional). + * @param float|null $presencePenalty Penalty for new tokens based on whether they appear in the text (optional). + * @param float|null $frequencyPenalty Penalty for new tokens based on their frequency in the text (optional). + * @param array|null $logitBias Modify the likelihood of specified tokens appearing (optional). + * @param string|null $user A unique identifier representing the end-user (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $model, + array $messages, + ?int $maxTokens = null, + ?float $temperature = null, + ?float $topP = null, + ?int $n = null, + ?bool $stream = null, + $stop = null, + ?float $presencePenalty = null, + ?float $frequencyPenalty = null, + ?array $logitBias = null, + ?string $user = null + ): ?object + { + // Build the request path. + $path = "/chat/completions"; + + // Set the request data. + $data = new \stdClass(); + $data->model = $model; + $data->messages = $messages; + + if ($maxTokens !== null) + { + $data->max_tokens = $maxTokens; + } + + if ($temperature !== null) + { + $data->temperature = $temperature; + } + + if ($topP !== null) + { + $data->top_p = $topP; + } + + if ($n !== null) + { + $data->n = $n; + } + + if ($stream !== null) + { + $data->stream = $stream; + } + + if ($stop !== null) + { + $data->stop = $stop; + } + + if ($presencePenalty !== null) + { + $data->presence_penalty = $presencePenalty; + } + + if ($frequencyPenalty !== null) + { + $data->frequency_penalty = $frequencyPenalty; + } + + if ($logitBias !== null) + { + $data->logit_bias = new \stdClass(); + foreach ($logitBias as $key => $val) + { + $data->logit_bias->$key = $val; + } + } + + if ($user !== null) + { + $data->user = $user; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Openai/Completions.php b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Completions.php new file mode 100644 index 0000000..8d667d2 --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Completions.php @@ -0,0 +1,158 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Openai; + + +use VastDevelopmentMethod\Openai\Joomla\Openai\Abstraction\Api; + + +/** + * The Openai Completions + * + * @since 3.2.0 + */ +class Completions extends Api +{ + /** + * Create a completion using the OpenAI API. + * API Ref: https://platform.openai.com/docs/api-reference/completions + * + * @param string $model The ID of the model to use. + * @param string|array $prompt The prompt(s) to generate completions for. + * @param int|null $maxTokens The maximum number of tokens to generate (optional). + * @param float|null $temperature The sampling temperature to use (optional). + * @param string $suffix The suffix that comes after a completion of inserted text. (optional). + * @param float|null $topP The top_p value for nucleus sampling (optional). + * @param int|null $n How many completions to generate (optional). + * @param bool|null $stream Whether to stream back partial progress (optional). + * @param int|null $logprobs Include the log probabilities on the most likely tokens (optional). + * @param bool|null $echo Echo back the prompt in addition to the completion (optional). + * @param string|null $stop Up to 4 sequences where the API will stop generating (optional). + * @param float|null $presencePenalty The presence penalty to use (optional). + * @param float|null $frequencyPenalty The frequency penalty to use (optional). + * @param int|null $bestOf Generates best_of completions server-side (optional). + * @param array|null $logitBias Modify the likelihood of specified tokens (optional). + * @param string|null $user A unique identifier representing your end-user (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $model, + $prompt, + ?int $maxTokens = null, + ?string $suffix = null, + ?float $temperature = null, + ?float $topP = null, + ?int $n = null, + ?bool $stream = null, + ?int $logprobs = null, + ?bool $echo = null, + $stop = null, + ?float $presencePenalty = null, + ?float $frequencyPenalty = null, + ?int $bestOf = null, + ?array $logitBias = null, + ?string $user = null + ): ?object + { + // Build the request path. + $path = "/completions"; + + // Set the completion data. + $data = new \stdClass(); + $data->model = $model; + $data->prompt = $prompt; + + if ($maxTokens !== null) + { + $data->max_tokens = $maxTokens; + } + + if ($temperature !== null) + { + $data->temperature = $temperature; + } + + if ($suffix !== null) + { + $data->suffix = $suffix; + } + + if ($topP !== null) + { + $data->top_p = $topP; + } + + if ($n !== null) + { + $data->n = $n; + } + + if ($stream !== null) + { + $data->stream = $stream; + } + + if ($logprobs !== null) + { + $data->logprobs = $logprobs; + } + + if ($echo !== null) + { + $data->echo = $echo; + } + + if ($stop !== null) + { + $data->stop = $stop; + } + + if ($presencePenalty !== null) + { + $data->presence_penalty = $presencePenalty; + } + + if ($frequencyPenalty !== null) + { + $data->frequency_penalty = $frequencyPenalty; + } + + if ($bestOf !== null) + { + $data->best_of = $bestOf; + } + + if ($logitBias !== null) + { + $data->logit_bias = new \stdClass(); + foreach ($logitBias as $key => $val) + { + $data->logit_bias->$key = $val; + } + } + + if ($user !== null) + { + $data->user = $user; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Openai/Edits.php b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Edits.php new file mode 100644 index 0000000..023d72d --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Edits.php @@ -0,0 +1,84 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Openai; + + +use VastDevelopmentMethod\Openai\Joomla\Openai\Abstraction\Api; + + +/** + * The Openai Edits + * + * @since 3.2.0 + */ +class Edits extends Api +{ + /** + * Create a new edit using OpenAI Edit API. + * API Ref: https://platform.openai.com/docs/api-reference/edits + * + * @param string $model The model to use. + * @param string $instruction The instruction for the edit. + * @param string|null $input The input text (optional). + * @param int|null $n How many edits to generate (optional). + * @param float|null $temperature The sampling temperature (optional). + * @param float|null $topP Nucleus sampling parameter (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $model, + string $instruction, + ?string $input = null, + ?int $n = null, + ?float $temperature = null, + ?float $topP = null + ): ?object + { + // Build the request path. + $path = "/edits"; + + // Set the data. + $data = new \stdClass(); + $data->model = $model; + $data->instruction = $instruction; + + if ($input !== null) + { + $data->input = $input; + } + + if ($n !== null) + { + $data->n = $n; + } + + if ($temperature !== null) + { + $data->temperature = $temperature; + } + + if ($topP !== null) + { + $data->top_p = $topP; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Openai/Embeddings.php b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Embeddings.php new file mode 100644 index 0000000..acd5943 --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Embeddings.php @@ -0,0 +1,63 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Openai; + + +use VastDevelopmentMethod\Openai\Joomla\Openai\Abstraction\Api; + + +/** + * The Openai Embeddings + * + * @since 3.2.0 + */ +class Embeddings extends Api +{ + /** + * Create an embedding of a given input. + * API Ref: https://platform.openai.com/docs/api-reference/embeddings + * + * @param string $model The ID of the model to use. + * @param mixed $input The input text to get embeddings for, encoded as a string or array of tokens. + * @param string|null $user A unique identifier representing your end-user (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function create( + string $model, + $input, + ?string $user = null + ): ?object + { + // Build the request path. + $path = "/embeddings"; + + // Set the request data. + $data = new \stdClass(); + $data->model = $model; + $data->input = $input; + + if ($user !== null) + { + $data->user = $user; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Openai/Factory.php b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Factory.php new file mode 100644 index 0000000..bcb7642 --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Factory.php @@ -0,0 +1,42 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Openai; + + +use Joomla\DI\Container; +use VastDevelopmentMethod\Openai\Joomla\Openai\Service\Api; +use VastDevelopmentMethod\Openai\Joomla\Openai\Service\Utilities; +use VastDevelopmentMethod\Openai\Joomla\Interfaces\FactoryInterface; +use VastDevelopmentMethod\Openai\Joomla\Abstraction\Factory as ExtendingFactory; + + +/** + * Openai Factory + * + * @since 3.2.0 + */ +abstract class Factory extends ExtendingFactory implements FactoryInterface +{ + /** + * Create a container object + * + * @return Container + * @since 3.2.0 + */ + protected static function createContainer(): Container + { + return (new Container()) + ->registerServiceProvider(new Utilities()) + ->registerServiceProvider(new Api()); + } +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Openai/Files.php b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Files.php new file mode 100644 index 0000000..63fbaeb --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Files.php @@ -0,0 +1,140 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Openai; + + +use VastDevelopmentMethod\Openai\Joomla\Openai\Abstraction\Api; + + +/** + * The Openai Files + * + * @since 3.2.0 + */ +class Files extends Api +{ + /** + * Fetches a list of files belonging to the user's organization. + * API Ref: https://platform.openai.com/docs/api-reference/files/list + * + * @return object|null The response from the OpenAI API, or null if an error occurred. + * @since 3.2.0 + */ + public function list(): ?object + { + // Build the request path. + $path = "/files"; + + // Prepare the URI. + $uri = $this->uri->get($path); + + // Send the GET request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * Upload a file that contains document(s) to be used across various endpoints/features. + * API Ref: https://platform.openai.com/docs/api-reference/files/upload + * + * @param string $file The file to upload. + * @param string $purpose The intended purpose of the uploaded documents. + * + * @return object|null + * @since 3.2.0 + **/ + public function upload(string $file, string $purpose): ?object + { + // Build the request path. + $path = "/files"; + + // Set the request data. + $data = new \stdClass(); + $data->file = $file; + $data->purpose = $purpose; + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } + + /** + * Returns information about a specific file. + * API Ref: https://platform.openai.com/docs/api-reference/files/retrieve + * + * @param string $fileID The file id to retrieve info + * + * @return object|null + * @since 3.2.0 + **/ + public function info(string $fileID): ?object + { + // Build the request path. + $path = "/files/{$fileID}"; + + // Send the post request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Retrieve a specific file content. + * API Ref: https://platform.openai.com/docs/api-reference/files/retrieve-content + * + * @param string $fileID The file id to retrieve content + * + * @return mixed + * @since 3.2.0 + **/ + public function content(string $fileID) + { + // Build the request path. + $path = "/files/{$fileID}/content"; + + // Send the post request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } + + /** + * Delete a file. + * API Ref: https://platform.openai.com/docs/api-reference/files/delete + * + * @param string $fileID The file id to delete + * + * @return object|null + * @since 3.2.0 + **/ + public function delete(string $fileID): ?object + { + // Build the request path. + $path = "/files/{$fileID}"; + + // Send the post request. + return $this->response->get( + $this->http->delete( + $this->uri->get($path) + ) + ); + } +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Openai/FineTunes.php b/src/VastDevelopmentMethod/Openai/Joomla/Openai/FineTunes.php new file mode 100644 index 0000000..28a1c64 --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Openai/FineTunes.php @@ -0,0 +1,50 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Openai; + + +use VastDevelopmentMethod\Openai\Joomla\Openai\Abstraction\Api; + + +/** + * The Openai Fine Tunes + * + * @since 3.2.0 + */ +class FineTunes extends Api +{ + /** + * List your organization's fine-tuning jobs + * API Ref: https://platform.openai.com/docs/api-reference/fine-tunes/list + * + * @return object|null The response from the OpenAI API, or null if an error occurred. + * @since 3.2.0 + */ + public function list(): ?object + { + // Build the request path. + $path = "/fine-tunes"; + + // Prepare the URI. + $uri = $this->uri->get($path); + + // Send the GET request. + return $this->response->get( + $this->http->get($uri) + ); + } + + /** + * More to follow: https://platform.openai.com/docs/api-reference/fine-tunes + **/ +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Openai/Images.php b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Images.php new file mode 100644 index 0000000..7c196d9 --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Images.php @@ -0,0 +1,203 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Openai; + + +use VastDevelopmentMethod\Openai\Joomla\Openai\Abstraction\Api; + + +/** + * The Openai Images + * + * @since 3.2.0 + */ +class Images extends Api +{ + /** + * Generate an image given a text prompt. + * API Ref: https://platform.openai.com/docs/api-reference/images/create + * + * @param string $prompt The text description of the desired image(s). + * @param string|null $size The size of the generated images (optional). + * @param string|null $responseFormat The format in which the images are returned (optional). + * @param int|null $n The number of images to generate (optional). + * @param string|null $user A unique identifier representing the end-user (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function generate( + string $prompt, + ?string $size = null, + ?string $responseFormat = null, + ?int $n = null, + ?string $user = null + ): ?object + { + // Build the request path. + $path = "/images/generations"; + + // Set the request data. + $data = new \stdClass(); + $data->prompt = $prompt; + + if ($size !== null) + { + $data->size = $size; + } + + if ($responseFormat !== null) + { + $data->response_format = $responseFormat; + } + + if ($n !== null) + { + $data->n = $n; + } + + if ($user !== null) + { + $data->user = $user; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } + + /** + * Create an image edit with extended options. + * API Ref: https://platform.openai.com/docs/api-reference/images/create-edit + * + * @param string $image The original image to edit. Must be a valid PNG file, less than 4MB, and square. + * @param string|null $mask An additional image for editing (optional). + * @param string $prompt A text description of the desired image(s). + * @param string|null $size The size of the generated images (optional). + * @param string|null $responseFormat The format in which the images are returned (optional). + * @param int|null $n The number of images to generate (optional). + * @param string|null $user A unique identifier representing your end-user (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function edit( + string $image, + string $prompt, + ?string $mask = null, + ?string $size = null, + ?string $responseFormat = null, + ?int $n = null, + ?string $user = null + ): ?object + { + // Build the request path. + $path = "/images/edits"; + + // Set the image edit data. + $data = new \stdClass(); + $data->image = $image; + $data->prompt = $prompt; + + if ($mask !== null) + { + $data->mask = $mask; + } + + if ($size !== null) + { + $data->size = $size; + } + + if ($responseFormat !== null) + { + $data->response_format = $responseFormat; + } + + if ($n !== null) + { + $data->n = $n; + } + + if ($user !== null) + { + $data->user = $user; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } + + /** + * Create a variation of a given image. + * API Ref: https://platform.openai.com/docs/api-reference/images/create-variation + * + * @param string $image The image to use as the basis for the variation(s). + * @param string|null $size The size of the generated images (optional). + * @param string|null $responseFormat The format in which the generated images are returned (optional). + * @param int|null $n The number of images to generate (optional). + * @param string|null $user A unique identifier representing your end-user (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function variation( + string $image, + ?string $size = null, + ?string $responseFormat = null, + ?int $n = null, + ?string $user = null + ): ?object + { + // Build the request path. + $path = "/images/variations"; + + // Set the image variation data. + $data = new \stdClass(); + $data->image = $image; + + if ($size !== null) + { + $data->size = $size; + } + + if ($responseFormat !== null) + { + $data->response_format = $responseFormat; + } + + if ($n !== null) + { + $data->n = $n; + } + + if ($user !== null) + { + $data->user = $user; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Openai/Models.php b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Models.php new file mode 100644 index 0000000..c8b8683 --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Models.php @@ -0,0 +1,44 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Openai; + + +use VastDevelopmentMethod\Openai\Joomla\Openai\Abstraction\Api; + + +/** + * The Openai Models + * + * @since 3.2.0 + */ +class Models extends Api +{ + /** + * List the available models from OpenAI API. + * + * @return object|null + * @since 3.2.0 + **/ + public function list(): ?object + { + // Build the request path. + $path = "/models"; + + // Send the get request. + return $this->response->get( + $this->http->get( + $this->uri->get($path) + ) + ); + } +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Openai/Moderate.php b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Moderate.php new file mode 100644 index 0000000..56114e4 --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Moderate.php @@ -0,0 +1,60 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Openai; + + +use VastDevelopmentMethod\Openai\Joomla\Openai\Abstraction\Api; + + +/** + * The Openai Moderate + * + * @since 3.2.0 + */ +class Moderate extends Api +{ + /** + * Classify if text violates OpenAI's Content Policy. + * API Ref: https://platform.openai.com/docs/api-reference/moderations/create + * + * @param string|array $input The input text to classify. + * @param string|null $model The moderation model (optional). + * + * @return object|null + * @since 3.2.0 + **/ + public function text( + $input, + ?string $model = null + ): ?object + { + // Build the request path. + $path = "/moderations"; + + // Set the moderation data. + $data = new \stdClass(); + $data->input = $input; + + if ($model !== null) + { + $data->model = $model; + } + + // Send the post request. + return $this->response->get( + $this->http->post( + $this->uri->get($path), json_encode($data) + ) + ); + } +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Openai/Service/Api.php b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Service/Api.php new file mode 100644 index 0000000..cb80759 --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Service/Api.php @@ -0,0 +1,247 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Openai\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VastDevelopmentMethod\Openai\Joomla\Openai\Audio; +use VastDevelopmentMethod\Openai\Joomla\Openai\Chat; +use VastDevelopmentMethod\Openai\Joomla\Openai\Completions; +use VastDevelopmentMethod\Openai\Joomla\Openai\Edits; +use VastDevelopmentMethod\Openai\Joomla\Openai\Embeddings; +use VastDevelopmentMethod\Openai\Joomla\Openai\Files; +use VastDevelopmentMethod\Openai\Joomla\Openai\FineTunes; +use VastDevelopmentMethod\Openai\Joomla\Openai\Images; +use VastDevelopmentMethod\Openai\Joomla\Openai\Models; +use VastDevelopmentMethod\Openai\Joomla\Openai\Moderate; + + +/** + * The Openai Api Service + * + * @since 3.2.0 + */ +class Api implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 3.2.0 + */ + public function register(Container $container) + { + $container->alias(Audio::class, 'Openai.Audio') + ->share('Openai.Audio', [$this, 'getAudio'], true); + + $container->alias(Chat::class, 'Openai.Chat') + ->share('Openai.Chat', [$this, 'getChat'], true); + + $container->alias(Completions::class, 'Openai.Completions') + ->share('Openai.Completions', [$this, 'getCompletions'], true); + + $container->alias(Edits::class, 'Openai.Edits') + ->share('Openai.Edits', [$this, 'getEdits'], true); + + $container->alias(Embeddings::class, 'Openai.Embeddings') + ->share('Openai.Embeddings', [$this, 'getEmbeddings'], true); + + $container->alias(Files::class, 'Openai.Files') + ->share('Openai.Files', [$this, 'getFiles'], true); + + $container->alias(FineTunes::class, 'Openai.FineTunes') + ->share('Openai.FineTunes', [$this, 'getFineTunes'], true); + + $container->alias(Images::class, 'Openai.Images') + ->share('Openai.Images', [$this, 'getImages'], true); + + $container->alias(Models::class, 'Openai.Models') + ->share('Openai.Models', [$this, 'getModels'], true); + + $container->alias(Moderate::class, 'Openai.Moderate') + ->share('Openai.Moderate', [$this, 'getModerate'], true); + } + + /** + * Get the Audio class + * + * @param Container $container The DI container. + * + * @return Audio + * @since 3.2.0 + */ + public function getAudio(Container $container): Audio + { + return new Audio( + $container->get('Openai.Utilities.Http'), + $container->get('Openai.Utilities.Uri'), + $container->get('Openai.Utilities.Response') + ); + } + + /** + * Get the Chat class + * + * @param Container $container The DI container. + * + * @return Chat + * @since 3.2.0 + */ + public function getChat(Container $container): Chat + { + return new Chat( + $container->get('Openai.Utilities.Http'), + $container->get('Openai.Utilities.Uri'), + $container->get('Openai.Utilities.Response') + ); + } + + /** + * Get the Completions class + * + * @param Container $container The DI container. + * + * @return Completions + * @since 3.2.0 + */ + public function getCompletions(Container $container): Completions + { + return new Completions( + $container->get('Openai.Utilities.Http'), + $container->get('Openai.Utilities.Uri'), + $container->get('Openai.Utilities.Response') + ); + } + + /** + * Get the Edits class + * + * @param Container $container The DI container. + * + * @return Edits + * @since 3.2.0 + */ + public function getEdits(Container $container): Edits + { + return new Edits( + $container->get('Openai.Utilities.Http'), + $container->get('Openai.Utilities.Uri'), + $container->get('Openai.Utilities.Response') + ); + } + + /** + * Get the Embeddings class + * + * @param Container $container The DI container. + * + * @return Embeddings + * @since 3.2.0 + */ + public function getEmbeddings(Container $container): Embeddings + { + return new Embeddings( + $container->get('Openai.Utilities.Http'), + $container->get('Openai.Utilities.Uri'), + $container->get('Openai.Utilities.Response') + ); + } + + /** + * Get the Files class + * + * @param Container $container The DI container. + * + * @return Files + * @since 3.2.0 + */ + public function getFiles(Container $container): Files + { + return new Files( + $container->get('Openai.Utilities.Http'), + $container->get('Openai.Utilities.Uri'), + $container->get('Openai.Utilities.Response') + ); + } + + /** + * Get the FineTunes class + * + * @param Container $container The DI container. + * + * @return FineTunes + * @since 3.2.0 + */ + public function getFineTunes(Container $container): FineTunes + { + return new FineTunes( + $container->get('Openai.Utilities.Http'), + $container->get('Openai.Utilities.Uri'), + $container->get('Openai.Utilities.Response') + ); + } + + /** + * Get the Images class + * + * @param Container $container The DI container. + * + * @return Images + * @since 3.2.0 + */ + public function getImages(Container $container): Images + { + return new Images( + $container->get('Openai.Utilities.Http'), + $container->get('Openai.Utilities.Uri'), + $container->get('Openai.Utilities.Response') + ); + } + + /** + * Get the Models class + * + * @param Container $container The DI container. + * + * @return Models + * @since 3.2.0 + */ + public function getModels(Container $container): Models + { + return new Models( + $container->get('Openai.Utilities.Http'), + $container->get('Openai.Utilities.Uri'), + $container->get('Openai.Utilities.Response') + ); + } + + /** + * Get the Moderate class + * + * @param Container $container The DI container. + * + * @return Moderate + * @since 3.2.0 + */ + public function getModerate(Container $container): Moderate + { + return new Moderate( + $container->get('Openai.Utilities.Http'), + $container->get('Openai.Utilities.Uri'), + $container->get('Openai.Utilities.Response') + ); + } +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Openai/Service/Utilities.php b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Service/Utilities.php new file mode 100644 index 0000000..128c8c3 --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Service/Utilities.php @@ -0,0 +1,113 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Openai\Service; + + +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; +use VastDevelopmentMethod\Openai\Joomla\Openai\Utilities\Uri; +use VastDevelopmentMethod\Openai\Joomla\Openai\Utilities\Response; +use VastDevelopmentMethod\Openai\Joomla\Openai\Utilities\Http; +use VastDevelopmentMethod\Openai\Joomla\Utilities\Component\Helper; + + +/** + * The Openai Utilities Service + * + * @since 3.2.0 + */ +class Utilities implements ServiceProviderInterface +{ + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * @since 3.2.0 + */ + public function register(Container $container) + { + $container->alias(Uri::class, 'Openai.Utilities.Uri') + ->share('Openai.Utilities.Uri', [$this, 'getUri'], true); + + $container->alias(Response::class, 'Openai.Utilities.Response') + ->share('Openai.Utilities.Response', [$this, 'getResponse'], true); + + $container->alias(Http::class, 'Openai.Utilities.Http') + ->share('Openai.Utilities.Http', [$this, 'getHttp'], true); + } + + /** + * Get the Uri class + * + * @param Container $container The DI container. + * + * @return Uri + * @since 3.2.0 + */ + public function getUri(Container $container): Uri + { + return new Uri(); + } + + /** + * Get the Response class + * + * @param Container $container The DI container. + * + * @return Response + * @since 3.2.0 + */ + public function getResponse(Container $container): Response + { + return new Response(); + } + + /** + * Get the Http class + * + * @param Container $container The DI container. + * + * @return Http + * @since 3.2.0 + */ + public function getHttp(Container $container): Http + { + $openai_token = null; + $openai_org_token = null; + if (Helper::getParams()->get('enable_open_ai') == 1) + { + $openai_token = Helper::getParams()->get('openai_token'); + if (Helper::getParams()->get('enable_open_ai_org') == 1) + { + $openai_org_token = Helper::getParams()->get('openai_org_token'); + } + + if ($openai_token === 'secret') + { + $openai_token = null; + } + + if ($openai_org_token === 'secret') + { + $openai_org_token = null; + } + } + + return new Http( + $openai_token, + $openai_org_token + ); + } +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Openai/Utilities/Http.php b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Utilities/Http.php new file mode 100644 index 0000000..0eb5b27 --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Utilities/Http.php @@ -0,0 +1,139 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Openai\Utilities; + + +use Joomla\CMS\Http\Http as JoomlaHttp; +use Joomla\Registry\Registry; + + +/** + * The Openai Http + * + * @since 3.2.0 + */ +final class Http extends JoomlaHttp +{ + /** + * The default Header + * + * @var array + * @since 3.2.0 + */ + protected array $defaultHeaders = ['Content-Type' => 'application/json']; + + /** + * Constructor. + * + * @param string|null $token The Openai API token. + * @param string|null $orgToken The Openai API Organization token. + * + * @since 3.2.0 + * @throws \InvalidArgumentException + **/ + public function __construct(?string $token, ?string $orgToken = null) + { + // add the token if given + if (is_string($token)) + { + $this->defaultHeaders['Authorization'] = 'Bearer ' . $token; + } + + // add the organization token if given + if (is_string($orgToken)) + { + $this->defaultHeaders['OpenAI-Organization'] = $orgToken; + } + + // setup config + $config = [ + 'userAgent' => 'JoomlaOpenai/3.0', + 'headers' => $this->defaultHeaders + ]; + + $options = new Registry($config); + + // run parent constructor + parent::__construct($options); + } + + /** + * Change the Tokens. + * + * @param string|null $token The Openai API token. + * @param string|null $orgToken The Openai API Organization token. + * + * @since 3.2.0 + **/ + public function setTokens(?string $token = null, ?string $orgToken = null) + { + // get the current headers + $this->defaultHeaders = (array) $this->getOption('headers', + $this->defaultHeaders + ); + + // add the token if given + if (is_string($token)) + { + $this->defaultHeaders['Authorization'] = 'Bearer ' . $token; + } + + // add the organization token if given + if (is_string($orgToken)) + { + $this->defaultHeaders['OpenAI-Organization'] = $orgToken; + } + + $this->setOption('headers', $this->defaultHeaders); + } + + /** + * Change the User Token. + * + * @param string $token The API token. + * + * @since 3.2.0 + **/ + public function setToken(string $token) + { + // get the current headers + $this->defaultHeaders = (array) $this->getOption('headers', + $this->defaultHeaders + ); + + // add the token + $this->defaultHeaders['Authorization'] = 'Bearer ' . $token; + + $this->setOption('headers', $this->defaultHeaders); + } + + /** + * Change the Organization Token. + * + * @param string $token The Organization API token. + * + * @since 3.2.0 + **/ + public function setOrgToken(string $token) + { + // get the current headers + $this->defaultHeaders = (array) $this->getOption('headers', + $this->defaultHeader + ); + + // add the token + $this->defaultHeaders['OpenAI-Organization'] = $token; + + $this->setOption('headers', $this->defaultHeaders); + } +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Openai/Utilities/Response.php b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Utilities/Response.php new file mode 100644 index 0000000..fa43e48 --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Utilities/Response.php @@ -0,0 +1,141 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Openai\Utilities; + + +use Joomla\CMS\Http\Response as JoomlaResponse; +use VastDevelopmentMethod\Openai\Joomla\Utilities\JsonHelper; +use VastDevelopmentMethod\Openai\Joomla\Utilities\StringHelper; + + +/** + * The Openai Response + * + * @since 3.2.0 + */ +final class Response +{ + /** + * Process the response and decode it. + * + * @param JoomlaResponse $response The response. + * @param integer $expectedCode The expected "good" code. + * @param mixed $default The default if body not have length + * + * @return mixed + * + * @since 3.2.0 + * @throws \DomainException + **/ + public function get($response, int $expectedCode = 200, $default = null) + { + // Validate the response code. + if ($response->code != $expectedCode) + { + // Decode the error response and throw an exception. + $message = $this->error($response); + + // Throw an exception with the OpenAI error message and code. + throw new \DomainException($message, $response->code); + } + + return $this->body($response, $default); + } + + /** + * Process the response and decode it. (when we have multiple success codes) + * + * @param JoomlaResponse $response The response. + * @param array [$expectedCode => $default] The expected "good" code. and The default if body not have length + * + * @return mixed + * + * @since 3.2.0 + * @throws \DomainException + **/ + public function get_($response, array $validate = [200 => null]) + { + // Validate the response code. + if (!isset($validate[$response->code])) + { + // Decode the error response and throw an exception. + $message = $this->error($response); + + // Throw an exception with the OpenAI error message and code. + throw new \DomainException($message, $response->code); + + } + + return $this->body($response, $validate[$response->code]); + } + + /** + * Return the body from the response + * + * @param JoomlaResponse $response The response. + * @param mixed $default The default if body not have length + * + * @return mixed + * @since 3.2.0 + **/ + protected function body($response, $default = null) + { + $body = $response->body ?? null; + // check that we have a body + if (StringHelper::check($body)) + { + if (JsonHelper::check($body)) + { + $body = json_decode((string) $body); + } + + return $body; + } + + return $default; + } + + /** + * Get the error message from the OpenAI API response + * + * @param JoomlaResponse $response The response. + * + * @return string + * @since 3.2.0 + **/ + protected function error($response): string + { + // do we have a json string + if (isset($response->body) && JsonHelper::check($response->body)) + { + $error = json_decode($response->body); + } + else + { + return 'Invalid or empty response body.'; + } + + // check if OpenAI returned an error object + if (isset($error->error)) + { + // error object found, extract message and code + $errorMessage = isset($error->error->message) ? $error->error->message : 'Unknown error.'; + $errorCode = isset($error->error->code) ? $error->error->code : 'Unknown error code.'; + + // return formatted error message + return 'OpenAI Error: ' . $errorMessage . ' Code: ' . $errorCode; + } + + return 'No error information found in response.'; + } +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Openai/Utilities/Uri.php b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Utilities/Uri.php new file mode 100644 index 0000000..2e1dbbc --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Openai/Utilities/Uri.php @@ -0,0 +1,115 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Openai\Utilities; + + +use Joomla\Uri\Uri as JoomlaUri; + + +/** + * The Openai Uri + * + * @since 3.2.0 + */ +final class Uri +{ + /** + * The api version + * + * @var string + * @since 3.2.0 + */ + private string $version; + + /** + * The api URL + * + * @var string + * @since 3.2.0 + */ + private string $url; + + /** + * Constructor + * + * @param string $url URL to the openai system + * example: https://api.openai.com + * @param string $version Version to the openai system + * + * @since 3.2.0 + **/ + public function __construct( + string $url = 'https://api.openai.com', + string $version = 'v1') + { + // set the API details + $this->setUrl($url); + $this->setVersion($version); + } + + /** + * Method to build and return a full request URL for the request. This method will + * add appropriate pagination details if necessary and also prepend the API url + * to have a complete URL for the request. + * + * @param string $path URL to inflect + * + * @return JoomlaUri + * @since 3.2.0 + **/ + public function get(string $path): JoomlaUri + { + // Get a new Uri object focusing the api url and given path. + $uri = new JoomlaUri($this->api() . $path); + + return $uri; + } + + /** + * Get the full API URL + * + * @return string + * @since 3.2.0 + **/ + public function api(): string + { + return $this->url . '/' . $this->version; + } + + /** + * Set the URL of the API + * + * @param string $url URL to your openai system + * example: https://api.openai.com + * + * @return void + * @since 3.2.0 + **/ + private function setUrl(string $url) + { + return $this->url = $url; + } + + /** + * Set the version of the API + * + * @param string $version version to your openai API + * + * @return void + * @since 3.2.0 + **/ + private function setVersion($version) + { + return $this->version = $version; + } +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Utilities/ArrayHelper.php b/src/VastDevelopmentMethod/Openai/Joomla/Utilities/ArrayHelper.php new file mode 100644 index 0000000..054daa8 --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Utilities/ArrayHelper.php @@ -0,0 +1,107 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Utilities; + + +/** + * Some array tricks helper + * + * @since 3.0.9 + */ +abstract class ArrayHelper +{ + /** + * Check if have an array with a length + * + * @input array The array to check + * + * @returns int|false number of items in array on success + * + * @since 3.2.0 + */ + public static function check($array, $removeEmptyString = false) + { + if (is_array($array) && ($nr = count((array) $array)) > 0) + { + // also make sure the empty strings are removed + if ($removeEmptyString) + { + $array = array_filter($array); + + if ($array === []) + { + return false; + } + + return count($array); + } + + return $nr; + } + + return false; + } + + /** + * Merge an array of array's + * + * @input array The arrays you would like to merge + * + * @returns array|null merged array on success + * + * @since 3.0.9 + */ + public static function merge($arrays): ?array + { + if(self::check($arrays)) + { + $merged = []; + foreach ($arrays as $array) + { + if (self::check($array)) + { + $merged = array_merge($merged, $array); + } + } + return $merged; + } + return null; + } + + /** + * Check if arrays intersect + * + * @input array The first array + * @input array The second array + * + * @returns bool true if intersect else false + * + * @since 3.1.1 + */ + public static function intersect($a_array, $b_array): bool + { + // flip the second array + $b_array = array_flip($b_array); + + // loop the first array + foreach ($a_array as $v) + { + if (isset($b_array[$v])) + { + return true; + } + } + return false; + } + +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Utilities/Component/Helper.php b/src/VastDevelopmentMethod/Openai/Joomla/Utilities/Component/Helper.php new file mode 100644 index 0000000..b23dd1b --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Utilities/Component/Helper.php @@ -0,0 +1,296 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Utilities\Component; + + +use Joomla\CMS\Factory; +use Joomla\CMS\Component\ComponentHelper; +use Joomla\Input\Input; +use Joomla\Registry\Registry; +use VastDevelopmentMethod\Openai\Joomla\Utilities\String\NamespaceHelper; + + +/** + * Some component helper + * + * @since 3.0.11 + */ +abstract class Helper +{ + /** + * The current option + * + * @var string|null + * @since 3.0.11 + */ + public static ?string $option = null; + + /** + * The component manifest list cache + * + * @var array + * @since 3.2.0 + */ + public static array $manifest = []; + + /** + * The component params list cache + * + * @var Registry[] + * @since 3.0.11 + */ + protected static array $params = []; + + /** + * Gets the parameter object for the component + * + * @param string|null $option The option for the component. + * + * @return Registry A Registry object. + * @see Registry + * @since 3.0.11 + */ + public static function getParams(?string $option = null): Registry + { + // check that we have an option + if (empty($option)) + { + $option = self::getOption(); + } + + // get global value + if (!isset(self::$params[$option]) || !self::$params[$option] instanceof Registry) + { + self::$params[$option] = ComponentHelper::getParams($option); + } + + return self::$params[$option]; + } + + /** + * Set the component option + * + * @param string|null $option The option + * + * @return void + * @since 3.2.0 + */ + public static function setOption(?string $option): void + { + self::$option = $option; + } + + /** + * Get the component option + * + * @param string|null $default The default return value if none is found + * + * @return string|null A component option + * @since 3.0.11 + */ + public static function getOption(?string $default = 'empty'): ?string + { + if (empty(self::$option)) + { + // get the option from the url input + self::$option = (new Input)->getString('option', null); + } + + if (empty(self::$option)) + { + $app = Factory::getApplication(); + + // Check if the getInput method exists in the application object + if (method_exists($app, 'getInput')) + { + // get the option from the application + self::$option = $app->getInput()->getCmd('option', $default); + } + else + { + // Use the default value if getInput method does not exist + self::$option = $default; + } + } + + return self::$option; + } + + /** + * Gets the component code name + * + * @param string|null $option The option for the component. + * @param string|null $default The default return value if none is found + * + * @return string|null A component code name + * @since 3.0.11 + */ + public static function getCode(?string $option = null, ?string $default = null): ?string + { + // check that we have an option + if (empty($option)) + { + $option = self::getOption(); + } + // option with com_ + if (is_string($option) && strpos($option, 'com_') === 0) + { + return strtolower(trim(substr($option, 4))); + } + + return $default; + } + + /** + * Gets the component abstract helper class + * + * @param string|null $option The option for the component. + * @param string|null $default The default return value if none is found + * + * @return string|null A component helper name + * + * @since 3.0.11 + */ + public static function get(?string $option = null, ?string $default = null): ?string + { + // check that we have an option + // and get the code name from it + if (($code_name = self::getCode($option, null)) !== null) + { + // we build the helper class name + $helper_name = '\\' . \ucfirst($code_name) . 'Helper'; + + // check if class exist + if (class_exists($helper_name)) + { + return $helper_name; + } + + // try loading namespace + if (($namespace = self::getNamespace($option)) !== null) + { + $name = \ucfirst($code_name) . 'Helper'; + $namespace_helper = '\\' . $namespace . '\Administrator\Helper\\' . NamespaceHelper::safeSegment($name); // TODO target site or admin locations not just admin... + if (class_exists($namespace_helper)) + { + return $namespace_helper; + } + } + } + + return $default; + } + + /** + * Gets the component namespace if set + * + * @param string|null $option The option for the component. + * @param string|null $default The default return value if none is found + * + * @return string|null A component namespace + * + * @since 3.0.11 + */ + public static function getNamespace(?string $option = null): ?string + { + $manifest = self::getManifest($option); + + return $manifest->namespace ?? null; + } + + /** + * Gets the component abstract helper class + * + * @param string|null $option The option for the component. + * @param string|null $default The default return value if none is found + * + * @return object|null A component helper name + * + * @since 3.0.11 + */ + public static function getManifest(?string $option = null): ?object + { + if ($option === null + && ($option = self::getOption($option)) === null) + { + return null; + } + + // get global manifest_cache values + if (!isset(self::$manifest[$option])) + { + $db = Factory::getDbo(); + $query = $db->getQuery(true); + + $query->select($db->quoteName('manifest_cache')) + ->from($db->quoteName('#__extensions')) + ->where($db->quoteName('type') . ' = ' . $db->quote('component')) + ->where($db->quoteName('element') . ' LIKE ' . $db->quote($option)); + + $db->setQuery($query); + + try { + $manifest = $db->loadResult(); + self::$manifest[$option] = json_decode($manifest); + } catch (\Exception $e) { + // Handle the database error appropriately. + self::$manifest[$option] = null; + } + } + + return self::$manifest[$option]; + } + + /** + * Check if the helper class of this component has a method + * + * @param string $method The method name to search for + * @param string|null $option The option for the component. + * + * @return bool true if method exist + * + * @since 3.0.11 + */ + public static function methodExists(string $method, ?string $option = null): bool + { + // get the helper class + return ($helper = self::get($option, null)) !== null && + method_exists($helper, $method); + } + + /** + * Check if the helper class of this component has a method, and call it with the arguments + * + * @param string $method The method name to search for + * @param array $arguments The arguments for function. + * @param string|null $option The option for the component. + * + * @return mixed return whatever the method returns or null + * @since 3.2.0 + */ + public static function _(string $method, array $arguments = [], ?string $option = null) + { + // get the helper class + if (($helper = self::get($option, null)) !== null && + method_exists($helper, $method)) + { + // we know this is not ideal... + // so we need to move these + // functions to their own classes + return call_user_func_array([$helper, $method], $arguments); + } + + return null; + } + +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Utilities/GetHelper.php b/src/VastDevelopmentMethod/Openai/Joomla/Utilities/GetHelper.php new file mode 100644 index 0000000..fd9b5b5 --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Utilities/GetHelper.php @@ -0,0 +1,258 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Utilities; + + +use Joomla\CMS\Factory; +use VastDevelopmentMethod\Openai\Joomla\Utilities\Component\Helper; +use VastDevelopmentMethod\Openai\Joomla\Data\Factory as Data; + + +/** + * Some easy get... + * + * @since 3.0.9 + */ +abstract class GetHelper +{ + /** + * Get a Variable + * + * @param string|null $table The table from which to get the variable + * @param mixed $where The value where + * @param string $whereString The target/field string where/name + * @param string $what The return field + * @param string $operator The operator between $whereString/field and $where/value + * @param string $main The component in which the table is found + * + * @return mixed string/int/float + * @since 3.0.9 + * + * @deprecated 5.1 Use Data::_('Load')->table($table)->value(...) + */ + public static function var(?string $table = null, $where = null, + string $whereString = 'user', string $what = 'id', + string $operator = '=', ?string $main = null) + { + if(empty($where)) + { + $where = Factory::getUser()->id; + } + + if(empty($main)) + { + $main = Helper::getCode(); + } + + // Get a db connection. + $db = Factory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + $query->select($db->quoteName(array($what))); + + if (empty($table)) + { + $query->from($db->quoteName('#__' . $main)); + } + else + { + $query->from($db->quoteName('#__' . $main . '_' . $table)); + } + + if (is_numeric($where)) + { + $query->where($db->quoteName($whereString) . ' ' . $operator . ' ' . (int) $where); + } + elseif (is_string($where)) + { + $query->where($db->quoteName($whereString) . ' ' . $operator . ' ' . $db->quote((string)$where)); + } + else + { + return false; + } + + $db->setQuery($query); + $db->execute(); + + if ($db->getNumRows()) + { + return $db->loadResult(); + } + + return false; + } + + /** + * Get array of variables + * + * @param string|null $table The table from which to get the variables + * @param mixed $where The value where + * @param string $whereString The target/field string where/name + * @param string $what The return field + * @param string $operator The operator between $whereString/field and $where/value + * @param string $main The component in which the table is found + * @param bool $unique The switch to return a unique array + * + * @return array|null + * @since 3.0.9 + * + * @deprecated 5.1 Use Data::_('Load')->table($table)->values(...) + */ + public static function vars(?string $table = null, $where = null, + string $whereString = 'user', string $what = 'id', string $operator = 'IN', + ?string $main = null, bool $unique = true): ?array + { + if(empty($where)) + { + $where = Factory::getUser()->id; + } + + if($main === null) + { + $main = Helper::getCode(); + } + + if (!ArrayHelper::check($where) && $where > 0) + { + $where = [$where]; + } + + if (ArrayHelper::check($where)) + { + // prep main <-- why? well if $main='' is empty then $table can be categories or users + if (StringHelper::check($main)) + { + $main = '_' . ltrim($main, '_'); + } + + // Get a db connection. + $db = Factory::getDbo(); + + // Create a new query object. + $query = $db->getQuery(true); + $query->select($db->quoteName(array($what))); + + if (empty($table)) + { + $query->from($db->quoteName('#__' . $main)); + } + else + { + $query->from($db->quoteName('#_' . $main . '_' . $table)); + } + + // add strings to array search + if ('IN_STRINGS' === $operator || 'NOT IN_STRINGS' === $operator) + { + $query->where($db->quoteName($whereString) . ' ' . str_replace('_STRINGS', '', $operator) . ' ("' . implode('","', $where) . '")'); + } + else + { + $query->where($db->quoteName($whereString) . ' ' . $operator . ' (' . implode(',', $where) . ')'); + } + + $db->setQuery($query); + $db->execute(); + + if ($db->getNumRows()) + { + if ($unique) + { + return array_unique($db->loadColumn()); + } + return $db->loadColumn(); + } + } + + return null; + } + + /** + * get all strings between two other strings + * + * @param string $content The content to search + * @param string $start The starting value + * @param string $end The ending value + * + * @return array|null On success + * @since 3.0.9 + */ + public static function allBetween(string $content, string $start, string $end): ?array + { + // reset bucket + $bucket = []; + for ($i = 0; ; $i++) + { + // search for string + $found = self::between($content, $start, $end); + + if (StringHelper::check($found)) + { + // add to bucket + $bucket[] = $found; + + // build removal string + $remove = $start . $found . $end; + + // remove from content + $content = str_replace($remove, '', $content); + } + else + { + break; + } + + // safety catch + if ($i == 500) + { + break; + } + } + + // only return unique array of values + if (ArrayHelper::check($bucket)) + { + return array_unique($bucket); + } + + return null; + } + + /** + * get a string between two other strings + * + * @param string $content The content to search + * @param string $start The starting value + * @param string $end The ending value + * @param string $default The default value if none found + * + * @return string On success / empty string on failure + * @since 3.0.9 + */ + public static function between(string $content, string $start, string $end, string $default = ''): string + { + $array = explode($start, $content); + if (isset($array[1]) && strpos($array[1], $end) !== false) + { + $array = explode($end, $array[1]); + + // return string found between + return $array[0]; + } + + return $default; + } + +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Utilities/JsonHelper.php b/src/VastDevelopmentMethod/Openai/Joomla/Utilities/JsonHelper.php new file mode 100644 index 0000000..ac633b7 --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Utilities/JsonHelper.php @@ -0,0 +1,101 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Utilities; + + +/** + * The json checker + * + * @since 3.0.9 + */ +abstract class JsonHelper +{ + /** + * Check if you have a json string + * + * @input string $string The json string to check + * + * @returns bool true on success + * + * @since 3.0.9 + */ + public static function check($string): bool + { + if (StringHelper::check($string)) + { + json_decode((string) $string); + return (json_last_error() === JSON_ERROR_NONE); + } + + return false; + } + + /** + * Convert a json object to a string + * + * @input string $value The json string to convert + * + * @returns a string + * + * @since 3.0.9 + */ + public static function string($value, $separator = ", ", $table = null, $id = 'id', $name = 'name') + { + // do some table foot work + $external = false; + if (is_string($table) && strpos((string) $table, '#__') !== false) + { + $external = true; + $table = str_replace('#__', '', (string) $table); + } + + // check if string is JSON + $result = json_decode((string) $value, true); + if (json_last_error() === JSON_ERROR_NONE) + { + // is JSON + if (ArrayHelper::check($result)) + { + if (StringHelper::check($table)) + { + $names = []; + foreach ($result as $val) + { + if ($external) + { + if ($_name = GetHelper::var(null, $val, $id, $name, '=', $table)) + { + $names[] = $_name; + } + } + else + { + if ($_name = GetHelper::var($table, $val, $id, $name)) + { + $names[] = $_name; + } + } + } + if (ArrayHelper::check($names)) + { + return (string) implode($separator, $names); + } + } + return (string) implode($separator, $result); + } + return (string) json_decode((string) $value); + } + return $value; + } + +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Utilities/String/NamespaceHelper.php b/src/VastDevelopmentMethod/Openai/Joomla/Utilities/String/NamespaceHelper.php new file mode 100644 index 0000000..10d1b63 --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Utilities/String/NamespaceHelper.php @@ -0,0 +1,78 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Utilities\String; + + +use VastDevelopmentMethod\Openai\Joomla\Utilities\StringHelper; + + +/** + * Control the naming of a namespace helper + * + * @since 3.0.9 + */ +abstract class NamespaceHelper +{ + /** + * Making namespace safe + * + * @param string $string The namespace string you would like to make safe + * + * @return string on success + * @since 3.0.9 + */ + public static function safe(string $string): string + { + // Remove leading and trailing backslashes + $string = trim($string, '\\'); + + // Split the string into namespace segments + $segments = explode('\\', $string); + + // make each segment safe + $segments = array_map([self::class, 'safeSegment'], $segments); + + // Join the namespace segments back together + return implode('\\', $segments); + } + + /** + * Making one namespace segment safe + * + * @param string $string The namespace segment string you would like to make safe + * + * @return string on success + * @since 3.0.9 + */ + public static function safeSegment(string $string): string + { + // Check if segment starts with a number + if (preg_match("/^\d/", $string)) + { + // Extract the starting number(s) + preg_match("/^\d+/", $string, $matches); + + if (isset($matches[0])) + { + $numberWord = StringHelper::numbers($matches[0]); + $string = str_replace($matches[0], $numberWord, $string); + } + } + + // Transliterate string TODO: look again as this makes it lowercase + // $segment = StringHelper::transliterate($segment); + + // Make sure segment only contains valid characters + return preg_replace("/[^A-Za-z0-9]/", '', $string); + } +} + diff --git a/src/VastDevelopmentMethod/Openai/Joomla/Utilities/StringHelper.php b/src/VastDevelopmentMethod/Openai/Joomla/Utilities/StringHelper.php new file mode 100644 index 0000000..b72ea19 --- /dev/null +++ b/src/VastDevelopmentMethod/Openai/Joomla/Utilities/StringHelper.php @@ -0,0 +1,416 @@ + + * @git VDM OpenAi Library + * @copyright Copyright (C) 2015 Vast Development Method. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace VastDevelopmentMethod\Openai\Joomla\Utilities; + + +use Joomla\Filter\InputFilter; +use Joomla\CMS\Language\Language; +use VastDevelopmentMethod\Openai\Joomla\Utilities\Component\Helper; + + +/** + * Some string tricks + * + * @since 3.0.9 + */ +abstract class StringHelper +{ + /** + * The Main Active Language + * + * @var string + * + * @since 3.0.9 + */ + public static $langTag; + + /** + * Check if we have a string with a length + * + * @input string $string The string to check + * + * @returns bool true on success + * + * @since 3.0.9 + */ + public static function check($string): bool + { + return is_string($string) && strlen($string) > 0; + } + + /** + * Shorten a string + * + * @input string The sting that you would like to shorten + * + * @returns string on success + * + * @since 3.2.0 + */ + public static function shorten($string, $length = 40, $addTip = true) + { + if (self::check($string)) + { + $initial = strlen((string) $string); + $words = preg_split('/([\s\n\r]+)/', (string) $string, -1, PREG_SPLIT_DELIM_CAPTURE); + $words_count = count((array)$words); + + $word_length = 0; + $last_word = 0; + for (; $last_word < $words_count; ++$last_word) + { + $word_length += strlen($words[$last_word]); + if ($word_length > $length) + { + break; + } + } + + $newString = implode(array_slice($words, 0, $last_word)); + $final = strlen($newString); + if ($initial !== $final && $addTip) + { + $title = self::shorten($string, 400 , false); + return '' . trim($newString) . '...'; + } + elseif ($initial !== $final && !$addTip) + { + return trim($newString) . '...'; + } + } + return $string; + } + + /** + * Making strings safe (various ways) + * + * @input string The you would like to make safe + * + * @returns string on success + * + * @since 3.0.9 + */ + public static function safe($string, $type = 'L', $spacer = '_', $replaceNumbers = true, $keepOnlyCharacters = true) + { + if ($replaceNumbers === true) + { + // remove all numbers and replace with English text version (works well only up to millions) + $string = self::numbers($string); + } + // 0nly continue if we have a string + if (self::check($string)) + { + // create file name without the extension that is safe + if ($type === 'filename') + { + // make sure VDM is not in the string + $string = str_replace('VDM', 'vDm', (string) $string); + // Remove anything which isn't a word, whitespace, number + // or any of the following caracters -_() + // If you don't need to handle multi-byte characters + // you can use preg_replace rather than mb_ereg_replace + // Thanks @Ɓukasz Rysiak! + // $string = mb_ereg_replace("([^\w\s\d\-_\(\)])", '', $string); + $string = preg_replace("([^\w\s\d\-_\(\)])", '', $string); + + // http://stackoverflow.com/a/2021729/1429677 + return preg_replace('/\s+/', ' ', (string) $string); + } + // remove all other characters + $string = trim((string) $string); + $string = preg_replace('/'.$spacer.'+/', ' ', $string); + $string = preg_replace('/\s+/', ' ', $string); + // Transliterate string + $string = self::transliterate($string); + // remove all and keep only characters + if ($keepOnlyCharacters) + { + $string = preg_replace("/[^A-Za-z ]/", '', (string) $string); + } + // keep both numbers and characters + else + { + $string = preg_replace("/[^A-Za-z0-9 ]/", '', (string) $string); + } + // select final adaptations + if ($type === 'L' || $type === 'strtolower') + { + // replace white space with underscore + $string = preg_replace('/\s+/', (string) $spacer, (string) $string); + // default is to return lower + return strtolower($string); + } + elseif ($type === 'W') + { + // return a string with all first letter of each word uppercase(no underscore) + return ucwords(strtolower($string)); + } + elseif ($type === 'w' || $type === 'word') + { + // return a string with all lowercase(no underscore) + return strtolower($string); + } + elseif ($type === 'Ww' || $type === 'Word') + { + // return a string with first letter of the first word uppercase and all the rest lowercase(no underscore) + return ucfirst(strtolower($string)); + } + elseif ($type === 'WW' || $type === 'WORD') + { + // return a string with all the uppercase(no underscore) + return strtoupper($string); + } + elseif ($type === 'U' || $type === 'strtoupper') + { + // replace white space with underscore + $string = preg_replace('/\s+/', (string) $spacer, $string); + // return all upper + return strtoupper($string); + } + elseif ($type === 'F' || $type === 'ucfirst') + { + // replace white space with underscore + $string = preg_replace('/\s+/', (string) $spacer, $string); + // return with first character to upper + return ucfirst(strtolower($string)); + } + elseif ($type === 'cA' || $type === 'cAmel' || $type === 'camelcase') + { + // convert all words to first letter uppercase + $string = ucwords(strtolower($string)); + // remove white space + $string = preg_replace('/\s+/', '', $string); + // now return first letter lowercase + return lcfirst($string); + } + // return string + return $string; + } + // not a string + return ''; + } + + /** + * Convert none English strings to code usable string + * + * @input an string + * + * @returns a string + * + * @since 3.0.9 + */ + public static function transliterate($string) + { + // set tag only once + if (!self::check(self::$langTag)) + { + // get global value + self::$langTag = Helper::getParams()->get('language', 'en-GB'); + } + + // Transliterate on the language requested + $lang = Language::getInstance(self::$langTag); + + return $lang->transliterate($string); + } + + /** + * make sure a string is HTML save + * + * @input an html string + * + * @returns a string + * + * @since 3.0.9 + */ + public static function html($var, $charset = 'UTF-8', $shorten = false, $length = 40, $addTip = true) + { + if (self::check($var)) + { + $filter = new InputFilter(); + $string = $filter->clean( + html_entity_decode( + htmlentities( + (string) $var, + ENT_COMPAT, + $charset + ) + ), + 'HTML' + ); + if ($shorten) + { + return self::shorten($string, $length, $addTip); + } + return $string; + } + else + { + return ''; + } + } + + /** + * Convert all int in a string to an English word string + * + * @input an string with numbers + * + * @returns a string + * + * @since 3.0.9 + */ + public static function numbers($string) + { + // set numbers array + $numbers = []; + $search_replace= []; + + // first get all numbers + preg_match_all('!\d+!', (string) $string, $numbers); + + // check if we have any numbers + if (isset($numbers[0]) && ArrayHelper::check($numbers[0])) + { + foreach ($numbers[0] as $number) + { + $search_replace[$number] = self::number((int)$number); + } + + // now replace numbers in string + $string = str_replace(array_keys($search_replace), array_values($search_replace), (string) $string); + + // check if we missed any, strange if we did. + return self::numbers($string); + } + + // return the string with no numbers remaining. + return $string; + } + + /** + * Convert an integer into an English word string + * Thanks to Tom Nicholson + * + * @input an int + * @returns a string + * + * @since 3.0.9 + */ + public static function number($x) + { + $nwords = array( "zero", "one", "two", "three", "four", "five", "six", "seven", + "eight", "nine", "ten", "eleven", "twelve", "thirteen", + "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", + "nineteen", "twenty", 30 => "thirty", 40 => "forty", + 50 => "fifty", 60 => "sixty", 70 => "seventy", 80 => "eighty", + 90 => "ninety" ); + + if(!is_numeric($x)) + { + $w = $x; + } + elseif(fmod($x, 1) != 0) + { + $w = $x; + } + else + { + if($x < 0) + { + $w = 'minus '; + $x = -$x; + } + else + { + $w = ''; + // ... now $x is a non-negative integer. + } + + if($x < 21) // 0 to 20 + { + $w .= $nwords[$x]; + } + elseif($x < 100) // 21 to 99 + { + $w .= $nwords[10 * floor($x/10)]; + $r = fmod($x, 10); + if($r > 0) + { + $w .= ' ' . $nwords[$r]; + } + } + elseif($x < 1000) // 100 to 999 + { + $w .= $nwords[floor($x/100)] .' hundred'; + $r = fmod($x, 100); + if($r > 0) + { + $w .= ' and '. self::number($r); + } + } + elseif($x < 1000000) // 1000 to 999999 + { + $w .= self::number(floor($x/1000)) .' thousand'; + $r = fmod($x, 1000); + if($r > 0) + { + $w .= ' '; + if($r < 100) + { + $w .= 'and '; + } + $w .= self::number($r); + } + } + else // millions + { + $w .= self::number(floor($x/1000000)) .' million'; + $r = fmod($x, 1000000); + if($r > 0) + { + $w .= ' '; + if($r < 100) + { + $w .= 'and '; + } + $w .= self::number($r); + } + } + } + return $w; + } + + /** + * Random Key + * + * @input int $size The size of the random string + * + * @returns a string + * @since 3.0.9 + */ + public static function random(int $size): string + { + $bag = "abcefghijknopqrstuwxyzABCDDEFGHIJKLLMMNOPQRSTUVVWXYZabcddefghijkllmmnopqrstuvvwxyzABCEFGHIJKNOPQRSTUWXYZ"; + $key = []; + $bagsize = strlen($bag) - 1; + + for ($i = 0; $i < $size; $i++) + { + $get = rand(0, $bagsize); + $key[] = $bag[$get]; + } + + return implode($key); + } + +} +