-
Notifications
You must be signed in to change notification settings - Fork 36
Docs ‐ State
USSD state help as create pages for users and exaluate the input they choose after.
You just need to run the following command to create a new USSD State.
php artisan ussd:state AvailableCountriesState
If the state should be the first state, you can use the init option
php artisan ussd:state WelcomeState --init
If the state should be a continuing state, you can use the cont option. Continue state is used to resume uncompleted USSD state by first asking the user if they want to continue an old session or start a new one.
php artisan ussd:state WouldYouLikeToContinueState --cont
Ask how the user if they will like to continue and specify which decision should be used to validate the input.
<?php
namespace App\Ussd\States;
use Sparors\Ussd\Contracts\ContinueState;
use Sparors\Ussd\Contracts\Decision;
use Sparors\Ussd\Decisions\Equal;
use Sparors\Ussd\Menu;
class WouldYouLikeToContinueState implements ContinueState
{
public function render(): Menu
{
return Menu::build()->text('Enter 1 to continue or any key start over');
}
public function confirm(): Decision
{
return new Equal(1);
}
}
States should have a render function that returns a USSD menu.
You can use Transition
attributes to indicate the transitioning from one state to the other. Transition
attributes allows you to define a callback that should be run before performing the transitioning.
<?php
namespace App\Ussd\States;
use App\Models\Customer;
use Sparors\Ussd\Attributes\Transition;
use Sparors\Ussd\Contracts\State;
use Sparors\Ussd\Decisions\Equal;
use Sparors\Ussd\Decisions\Fallback;
use Sparors\Ussd\Menu;
use Sparors\Ussd\Record;
#[Transition(to: RegisterState::class, match: new Equal(1), callback: [self::class, 'callback'])]
#[Transition(to: HelplineState::class, match: new Fallback())]
class WelcomeState implements State
{
public function render(): Menu
{
return Menu::build()
->line('Banc')
->listing([
'Register',
'Helpline',
])
->text('Powered by Sparors');
}
public function callback(Record $record): void
{
$details = Customer::query()
->where('phone_number', $context->get('phone_number'))
->latest()
->first();
$record->set('details', $details);
}
}
You can use Paginate
attributes to paginate a very long list of items that would not fit on a page. Paginate is actually just transition, back to the same state.
<?php
namespace App\Ussd\States;
use App\Models\Customer;
use Sparors\Ussd\Attributes\Paginate;
use Sparors\Ussd\Contracts\State;
use Sparors\Ussd\Decisions\Equal;
use Sparors\Ussd\Decisions\Fallback;
use Sparors\Ussd\Menu;
use Sparors\Ussd\Context;
use Sparors\Ussd\Record;
#[Paginate(next: new Equal('#'), previous: new Equal('0'), callback: [self::class, 'callback'])]
#[Transition(to: HelplineState::class, match: new Fallback())]
class AvailableCountriesState implements State
{
public function render(Record $record): Menu
{
$page = $record->get('countries_page', 1);
return Menu::build()
->line('Banc')
->listing([
'Angola',
'Algeria',
'Cameroon',
'DR Congo',
'Ghana',
'Egypt',
'Kenya',
'Uganda',
'Zimbabwe',
], page: $page, perPage: 3)
->text('Powered by Sparors');
}
public function callback(Context $context, Record $record): void
{
$page = $record->get('countries_page', 1);
if ('#' === $context->input()) {
$record->set('countries_page', $page + 1);
} else {
$record->set('countries_page', $page - 1);
}
}
}
Pagination is common for USSD application so there are inbuilt helper traits to help make it simple.
<?php
namespace App\Ussd\States;
use App\Models\Customer;
use Sparors\Ussd\Attributes\Paginate;
use Sparors\Ussd\Contracts\State;
use Sparors\Ussd\Decisions\Equal;
use Sparors\Ussd\Decisions\Fallback;
use Sparors\Ussd\Menu;
use Sparors\Ussd\Record;
use Sparors\Ussd\Traits\WithPagination;
#[Paginate(next: new Equal('#'), previous: new Equal('0'))]
#[Transition(to: HelplineState::class, match: new Fallback())]
class AvailableCountriesState implements State
{
use WithPagination;
public function render(Record $record): Menu
{
$page = $record->get('countries_page', 1);
return Menu::build()
->when($this->isFirstPage(), fn (Menu $menu) => $menu->line('Banc'))
->listing($this->getItems(), page: $this->currentPage(), perPage: $this->perPage())
->when($this->hasPreviousPage(), fn (Menu $menu) => $menu->line('0. Previous Page'))
->when($this->hasNextPage(), fn (Menu $menu) => $menu->line('#. Next Page'))
->when($this->isLastPage(), fn (Menu $menu) => $menu->line('Powered by Sparors'));
}
public function getItems(): array
{
return [
'Angola',
'Algeria',
'Cameroon',
'DR Congo',
'Ghana',
'Egypt',
'Kenya',
'Uganda',
'Zimbabwe',
];
}
public function perPage(): int
{
return 3;
}
}
You can use Truncate
attributes to limit the number of characters that should be return to the USSD application. This helps ensure your USSD application is in conformity with the character limit of your USSD Provider. This is very useful for dynamic content where you can not be certain on the total characters.
<?php
namespace App\Ussd\States;
use App\Models\Customer;
use Sparors\Ussd\Attributes\Transition;
use Sparors\Ussd\Contracts\State;
use Sparors\Ussd\Decisions\Equal;
use Sparors\Ussd\Decisions\Fallback;
use Sparors\Ussd\Menu;
use Sparors\Ussd\Record;
#[Transition(to: RegisterState::class, match: new Equal(1))]
#[Truncate(limit: 80, end: '#. More.', more: new Equal('#'))]
class DetailsState implements State
{
public function render(Record $record): Menu
{
return Menu::build()
->line('Banc')
->format('Name: %s', $record->name)
->lineBreak()
->line('Your post')
->line($record->get('post'))
->text('Powered by Sparors');
}
}
To indicate that a USSD application should Terminate, use the Terminate
attribute.
<?php
namespace App\Ussd\States;
use Sparors\Ussd\Attributes\Terminate;
use Sparors\Ussd\Contracts\State;
use Sparors\Ussd\Menu;
#[Terminate]
class HelplineState implements State
{
public function render(): Menu
{
return Menu::build()
->line('Helpline')
->listing([
'email: info@banc.co',
'phone: +233 241 122 333'
]);
}
}