diff --git a/changelog.md b/changelog.md index 4776739..29d7dfb 100644 --- a/changelog.md +++ b/changelog.md @@ -4,6 +4,27 @@ All notable changes to `laravel Ussd` will be documented in this file. ## [Unreleased] +## [v3.0.0-beta.1] - 2024-01-21 +### Removed +- Removed machine in favor of USSD facade. + +### Changed +- Changed state interface. +- Changed record implementation and public apis. +- Changed config variables + +### Added +- Added `Transition`, `Paginate`, `Truncate` and `Terminate` Attributes. +- Added Custom Exception Handling. +- Added command to create responses, exception handlers and decisions. +- Added decision classes for navigating USSD menus. +- Added testing utility to Ussd Facade. +- Added pagination utility. +- Added resumability of timed-out sessions. +- Added interfaces for decision, exception handler, response, initial state and initial action. +- Added support for dependency injection. +- Added USSD context. + ## [v2.5.0] - 2022-06-19 ### Added - Add configuring USSDs using decorator pattern. @@ -17,13 +38,11 @@ All notable changes to `laravel Ussd` will be documented in this file. - Clean up ## [v2.4.0] - 2022-02-22 - ### Added - Add Laravel 9 support - Add PHP 8.1 support ## [v2.3.1] - 2021-10-15 - ### Fixed - Coding style @@ -50,6 +69,7 @@ All notable changes to `laravel Ussd` will be documented in this file. - Artisan command to create action class - increment method to records - decrement method to records + ### Changed - config file class namespace split to action and state namespace - Updated changelog @@ -82,7 +102,8 @@ All notable changes to `laravel Ussd` will be documented in this file. - Ussd config to allow developers customize behaviour - Ussd service Provider class to allow laravel know how to integrate the package -[Unreleased]: ../../compare/v2.5.0...HEAD +[Unreleased]: ../../compare/v3.0.0-beta.1...HEAD +[v3.0.0-beta.1]: ../../compare/v2.5.0...v3.0.0-beta.1 [v2.5.0]: ../../compare/v2.4.2...v2.5.0 [v2.4.2]: ../../compare/v2.4.1...v2.4.2 [v2.4.1]: ../../compare/v2.4.0...v2.4.1 diff --git a/contributing.md b/contributing.md index 0802c88..c452b78 100644 --- a/contributing.md +++ b/contributing.md @@ -6,7 +6,6 @@ Contributions are accepted via Pull Requests on [Github](https://github.com/spar # Things you could do If you want to contribute but do not know where to start, this list provides some starting points. -- Set up TravisCI - Write a comprehensive ReadMe ## Pull Requests diff --git a/me.md b/me.md deleted file mode 100644 index 7de1c4f..0000000 --- a/me.md +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Laravel Ussd - * - * Build Ussd (Unstructured Supplementary Service Data) applications with Laravel without breaking a sweat. - * - * @package Laravel Ussd - * @version 3.0.0 - * @author Sparors - * @link https://sparors.github.io/ussd-docs/ - * - * @see https://packagist.org/packages/sparors/laravel-ussd - * @see https://travis-ci.com/sparors/laravel-ussd - * - * @license MIT - */ -# Laravel Ussd - -[![Latest Version on Packagist][ico-version]][link-packagist] -[![Total Downloads][ico-downloads]][link-downloads] -[![Build Status][ico-travis]][link-travis] - -Build Ussd (Unstructured Supplementary Service Data) applications with Laravel without breaking a sweat. - -## Installation - -You can install the package via composer: diff --git a/readme.md b/readme.md index 400867e..e155d5a 100644 --- a/readme.md +++ b/readme.md @@ -116,7 +116,7 @@ class GoodByeState implements State } ``` -Due to some limitation with PHP 8.0, you can not pass class instance to attributes. So to other come this limitation, you can pass an array with the full class path as the first element and the rest should be argument required. eg. +Due to some limitation with PHP 8.0, you can not pass class instance to attributes. So to overcome this limitation, you can pass an array with the full class path as the first element and the rest should be argument required. eg. ``` php context = $context; + + return $this; + } + + public function useConfigurator(Configurator|string $configurator): static + { + if (is_string($configurator) && class_exists($configurator)) { + $configurator = App::make($configurator); + } + + throw_unless( + $configurator instanceof Configurator, + InvalidConfiguratorException::class, + $configurator::class + ); + + $configurator->configure($this); + + return $this; + } + + public function useInitialState(InitialAction|InitialState|string $initialState): static + { + if (is_string($initialState) && class_exists($initialState)) { + $initialState = App::make($initialState); + } + + throw_unless( + $initialState instanceof InitialState || $initialState instanceof InitialAction, + InvalidInitialStateException::class, + $initialState::class + ); + + $this->initialState = $initialState; + + return $this; + } + + public function useContinuingState( + int $continuingMode, + null|DateInterval|DateTimeInterface|int $continuingTtl, + null|ContinueState|string $continuingState = null + ): static { + if (is_string($continuingState) && class_exists($continuingState)) { + $continuingState = App::make($continuingState); + } + + throw_unless( + in_array($continuingMode, [ContinuingMode::START, ContinuingMode::CONTINUE, ContinuingMode::CONFIRM], true), + InvalidContinuingModeException::class, + $continuingMode + ); + + $this->continuingMode = $continuingMode; + $this->continuingTtl = $continuingTtl; + + if (ContinuingMode::CONFIRM === $continuingMode) { + throw_unless( + $continuingState instanceof ContinueState, + InvalidContinueStateException::class, + isset($continuingState) ? $continuingState::class : null + ); + } + + $this->continuingState = $continuingState; + + return $this; + } + + public function useResponse(Closure|Response|string $response): static + { + if (is_string($response) && class_exists($response)) { + $response = App::make($response); + } + + throw_unless( + $response instanceof Response || $response instanceof Closure, + InvalidResponseException::class, + $response::class + ); + + $this->response = $response; + + return $this; + } + + public function useExceptionHandler(Closure|ExceptionHandler|string $exceptionHandler): static + { + if (is_string($exceptionHandler) && class_exists($exceptionHandler)) { + $exceptionHandler = App::make($exceptionHandler); + } + + throw_unless( + $exceptionHandler instanceof ExceptionHandler || $exceptionHandler instanceof Closure, + InvalidExceptionHandlerException::class, + $exceptionHandler::class + ); + + $this->exceptionHandler = $exceptionHandler; + + return $this; + } + + public function useStore(string $storeName): static + { + $this->storeName = $storeName; + + return $this; + } +} diff --git a/src/Ussd.php b/src/Ussd.php index 4e2c667..f8882e1 100644 --- a/src/Ussd.php +++ b/src/Ussd.php @@ -14,7 +14,6 @@ use Sparors\Ussd\Attributes\Transition; use Sparors\Ussd\Attributes\Truncate; use Sparors\Ussd\Contracts\Action; -use Sparors\Ussd\Contracts\Configurator; use Sparors\Ussd\Contracts\ContinueState; use Sparors\Ussd\Contracts\ExceptionHandler; use Sparors\Ussd\Contracts\InitialAction; @@ -22,22 +21,19 @@ use Sparors\Ussd\Contracts\Response; use Sparors\Ussd\Contracts\State; use Sparors\Ussd\Exceptions\ActiveStateNotFoundException; -use Sparors\Ussd\Exceptions\InvalidConfiguratorException; use Sparors\Ussd\Exceptions\InvalidContinueStateException; -use Sparors\Ussd\Exceptions\InvalidContinuingModeException; -use Sparors\Ussd\Exceptions\InvalidExceptionHandlerException; -use Sparors\Ussd\Exceptions\InvalidInitialStateException; -use Sparors\Ussd\Exceptions\InvalidResponseException; use Sparors\Ussd\Exceptions\InvalidStateException; use Sparors\Ussd\Exceptions\NextStateNotFoundException; use Sparors\Ussd\Exceptions\NoInitialStateProvided; use Sparors\Ussd\Tests\PendingTest; use Sparors\Ussd\Traits\Conditionable; +use Sparors\Ussd\Traits\UssdBuilder; use Sparors\Ussd\Traits\WithPagination; class Ussd { use Conditionable; + use UssdBuilder; private const INIT = '__init__'; private const HEAL = '__heal__'; @@ -87,119 +83,6 @@ public static function test( return new PendingTest($initialState, $continuingMode, $continuingTtl, $continuingState); } - public function useContext(Context $context): static - { - $this->context = $context; - - return $this; - } - - public function useConfigurator(Configurator|string $configurator): static - { - if (is_string($configurator) && class_exists($configurator)) { - $configurator = App::make($configurator); - } - - throw_unless( - $configurator instanceof Configurator, - InvalidConfiguratorException::class, - $configurator::class - ); - - $configurator->configure($this); - - return $this; - } - - public function useInitialState(InitialAction|InitialState|string $initialState): static - { - if (is_string($initialState) && class_exists($initialState)) { - $initialState = App::make($initialState); - } - - throw_unless( - $initialState instanceof InitialState || $initialState instanceof InitialAction, - InvalidInitialStateException::class, - $initialState::class - ); - - $this->initialState = $initialState; - - return $this; - } - - public function useContinuingState( - int $continuingMode, - null|DateInterval|DateTimeInterface|int $continuingTtl, - null|ContinueState|string $continuingState = null - ): static { - if (is_string($continuingState) && class_exists($continuingState)) { - $continuingState = App::make($continuingState); - } - - throw_unless( - in_array($continuingMode, [ContinuingMode::START, ContinuingMode::CONTINUE, ContinuingMode::CONFIRM], true), - InvalidContinuingModeException::class, - $continuingMode - ); - - $this->continuingMode = $continuingMode; - $this->continuingTtl = $continuingTtl; - - if (ContinuingMode::CONFIRM === $continuingMode) { - throw_unless( - $continuingState instanceof ContinueState, - InvalidContinueStateException::class, - isset($continuingState) ? $continuingState::class : null - ); - } - - $this->continuingState = $continuingState; - - return $this; - } - - public function useResponse(Closure|Response|string $response): static - { - if (is_string($response) && class_exists($response)) { - $response = App::make($response); - } - - throw_unless( - $response instanceof Response || $response instanceof Closure, - InvalidResponseException::class, - $response::class - ); - - $this->response = $response; - - return $this; - } - - public function useExceptionHandler(Closure|ExceptionHandler|string $exceptionHandler): static - { - if (is_string($exceptionHandler) && class_exists($exceptionHandler)) { - $exceptionHandler = App::make($exceptionHandler); - } - - throw_unless( - $exceptionHandler instanceof ExceptionHandler || $exceptionHandler instanceof Closure, - InvalidExceptionHandlerException::class, - $exceptionHandler::class - ); - - $this->exceptionHandler = $exceptionHandler; - - return $this; - } - - public function useStore(string $storeName): static - { - $this->storeName = $storeName; - - return $this; - } - public function run(): mixed { try {