Skip to content

Commit

Permalink
feat: Define persistent menu at menu file
Browse files Browse the repository at this point in the history
Define persisten menu at `routes/menu.php`.

Like define routes, we can easy to setup multiple level menu.

[docs](https://github.com/CasperLaiTW/laravel-fb-messenger/wiki/Commands#fbmenus)
  • Loading branch information
CasperLaiTW committed Apr 22, 2017
1 parent 87c6480 commit 552c162
Show file tree
Hide file tree
Showing 14 changed files with 425 additions and 278 deletions.
22 changes: 1 addition & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ In your `config/app.php` add `Casperlaitw\LaravelFbMessenger\LaravelFbMessenger

### Publish Configuration
```shell
php artisan vendor:publish --provider="Casperlaitw\LaravelFbMessenger\LaravelFbMessengerServiceProvider"
php artisan vendor:publish --provider="Casperlaitw\LaravelFbMessenger\LaravelFbMessengerServiceProvider" --tag="config"
```

## Configuration
Expand Down Expand Up @@ -61,26 +61,6 @@ MESSENGER_APP_TOKEN="Page Access Token"
...
```

### Auto Typing

![Typing](https://cdn.rawgit.com/CasperLaiTW/laravel-fb-messenger/master/docs/images/typing.png)

Auto typing is enabled by default.

If you don't want to enable, set `auto_typing` to `false`

```php
return [
'verify_token' => env('MESSENGER_VERIFY_TOKEN'),
'app_token' => env('MESSENGER_APP_TOKEN'),
'auto_typing' => false, // disabled
'handlers' => [App\YourHandler::class],
'postbacks' => [
App\StartupPostback::class,
],
];
```

### Custom Url
If you want to custom url, replace `/webhook` to you want.

Expand Down
2 changes: 2 additions & 0 deletions config/menu.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?php

142 changes: 15 additions & 127 deletions src/Commands/PersistentMenuCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
*/

namespace Casperlaitw\LaravelFbMessenger\Commands;

use Casperlaitw\LaravelFbMessenger\Exceptions\NotOptionsException;
use Casperlaitw\LaravelFbMessenger\Exceptions\OptionNotComparedException;
use Casperlaitw\LaravelFbMessenger\Messages\Button;
use Casperlaitw\LaravelFbMessenger\Contracts\Bot;
use Casperlaitw\LaravelFbMessenger\Contracts\CommandHandler;
use Casperlaitw\LaravelFbMessenger\Facades\MessengerMenu;
use Casperlaitw\LaravelFbMessenger\Messages\PersistentMenuMessage;
use Casperlaitw\LaravelFbMessenger\PersistentMenu\Menu;
use Illuminate\Contracts\Config\Repository;

/**
* Class PersistentMenuCommand
Expand All @@ -23,8 +24,7 @@ class PersistentMenuCommand extends BaseCommand
*
* @var string
*/
protected $signature = 'fb:menus {--type=* : Menu type} {--name=* : Menu name} '.
'{--url=* : Menu url or payload} {--d | delete : Delete the menus}';
protected $signature = 'fb:menus {--d | delete : Delete the menus} {--r | read : Delete the menus}';

/**
* The console command description.
Expand All @@ -33,141 +33,29 @@ class PersistentMenuCommand extends BaseCommand
*/
protected $description = 'Set menus';

/**
* @var array
*/
private $typeList = [Button::TYPE_POSTBACK, Button::TYPE_WEB];

/**
* @var array
*/
private $buttons = [];

/**
* @var array
*/
private $types = [];

/**
* @var array
*/
private $names = [];

/**
* @var array
*/
private $urls = [];

/**
* Execute command
*/
public function handle()
{
// If delete is true, skip to check or valid options.
if ($this->option('delete')) {
$this->send();
return;
}
$this->types = $this->option('type');
$this->names = $this->option('name');
$this->urls = $this->option('url');

try {
if (!$this->valid()) {
return;
}
} catch (OptionNotComparedException $ex) {
$this->error('The options did not compare.');
return;
} catch (NotOptionsException $ex) {
$this->interactiveMode();
}

$this->createButton();
$this->send();
}
$persistentMenuMessage = new PersistentMenuMessage(MessengerMenu::getMenus());

/**
* Send to api
*/
private function send()
{
$persistent = new PersistentMenuMessage($this->buttons);
if ($this->option('delete')) {
$persistent->useDelete();
$persistentMenuMessage->useDelete();
}
$this->comment($this->handler->send($persistent)->getResponse());
}

/**
* Valid persistent menu's params
*
* @return bool
* @throws NotOptionsException
* @throws OptionNotComparedException
*/
private function valid()
{
if (count($this->types) === 0 && count($this->names) === 0 && count($this->urls) === 0) {
throw new NotOptionsException;
if ($this->option('read')) {
$persistentMenuMessage->useGet();
}
if (count($this->types) !== count($this->names) || count($this->names) !== count($this->urls)) {
throw new OptionNotComparedException;
}
if (count($this->types) > 5) {
$this->error('The menu buttons is limitd to 5');
return false;
}
foreach ($this->types as $type) {
if (!str_contains($type, $this->typeList)) {
$this->error("Please check type, type only {$this->getTypeListToString()}");
return false;
}
}
return true;
}

/**
* Create message buttons
*/
private function createButton()
{
foreach ($this->types as $key => $type) {
$this->buttons[] =new Button($type, $this->names[$key], $this->urls[$key]);
if ($persistentMenuMessage->getCurlType() === Bot::TYPE_POST && MessengerMenu::isEmpty()) {
$this->warn('Menu tree is empty.');
return;
}
}

/**
* Work on interactive mode
*/
private function interactiveMode()
{
$exit = !$this->option('quiet');
$count = 0;
while ($exit) {
if ($count === 5) {
$this->comment('The menu buttons is limitd to 5');
return;
}

$this->types[] = $this->anticipate(
"Input your menu button type [{$this->getTypeListToString()}]",
$this->typeList
);
$this->names[] = $this->ask('Input your menu name');
$this->urls[] = $this->ask('Input your url or postback');
$exit = $this->choice('Do you add more menu button?', ['No', 'Yes']) === 'No' ? false : true;
$count = count($this->types);
$this->comment("You are creating buttons ({$count}/5)");
}
}
$response = $this->handler->send($persistentMenuMessage)->getResponse();

/**
* Type List to string
* @return string
*/
private function getTypeListToString()
{
return implode('|', $this->typeList);
$this->comment($this->option('read') ? json_encode($response) : $response);
}
}
23 changes: 23 additions & 0 deletions src/Facades/MessengerMenu.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Casperlaitw\LaravelFbMessenger\Facades;

use Illuminate\Support\Facades\Facade;

/**
* Class MessengerMenu
* @package Casperlaitw\LaravelFbMessenger\Facades
* @codeCoverageIgnore
*/
class MessengerMenu extends Facade
{
/**
* The name of the binding in the IoC container.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return 'fbMenu';
}
}
14 changes: 14 additions & 0 deletions src/LaravelFbMessengerServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Casperlaitw\LaravelFbMessenger\Commands\PersistentMenuCommand;
use Casperlaitw\LaravelFbMessenger\Contracts\Debug\Debug;
use Casperlaitw\LaravelFbMessenger\Contracts\Debug\Handler;
use Casperlaitw\LaravelFbMessenger\Providers\MenuServiceProvider;
use Casperlaitw\LaravelFbMessenger\Providers\RouteServiceProvider;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Illuminate\Support\ServiceProvider;
Expand All @@ -24,6 +25,13 @@ class LaravelFbMessengerServiceProvider extends ServiceProvider
*/
protected $configPath = __DIR__ . '/../config/fb-messenger.php';

/**
* Menu path
*
* @var string
*/
protected $menuPath = __DIR__ . '/../config/menu.php';

/**
* Perform post-registration booting of services.
*
Expand All @@ -34,6 +42,11 @@ public function boot()
$this->publishes([
$this->configPath => $this->app->configPath().'/fb-messenger.php',
], 'config');

$this->publishes([
$this->menuPath => $this->app->basePath().'/routes/menu.php',
], 'menu');

$this->loadViewsFrom(__DIR__ . '/../resources/views', 'laravel-fb-messenger');
$this->publishes([__DIR__.'/../public' => $this->app->basePath().'/public/vendor'], 'public');

Expand All @@ -54,6 +67,7 @@ public function register()
{
$this->mergeConfigFrom($this->configPath, 'fb-messenger');
$this->app->register(RouteServiceProvider::class);
$this->app->register(MenuServiceProvider::class);
$this->app->singleton(Debug::class, Debug::class);
$this->registerCommands();
}
Expand Down
32 changes: 21 additions & 11 deletions src/Messages/PersistentMenuMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace Casperlaitw\LaravelFbMessenger\Messages;

use Casperlaitw\LaravelFbMessenger\Contracts\Bot;
use Casperlaitw\LaravelFbMessenger\Contracts\Messages\Message;
use Casperlaitw\LaravelFbMessenger\Contracts\Messages\ProfileInterface;
use Casperlaitw\LaravelFbMessenger\Contracts\RequestType;
Expand All @@ -20,19 +21,19 @@ class PersistentMenuMessage extends Message implements ProfileInterface
use RequestType;

/**
* @var
* @var array
*/
private $buttons;
private $menus;

/**
* PersistentMenuMessage constructor.
*
* @param $buttons
* @param $menus
*/
public function __construct($buttons = [])
public function __construct($menus = [])
{
parent::__construct(null);
$this->buttons = $buttons;
$this->menus = $menus;
}

/**
Expand All @@ -41,13 +42,22 @@ public function __construct($buttons = [])
*/
public function toData()
{
$buttons = collect($this->buttons);
if ($this->type === Bot::TYPE_DELETE) {
return [
'fields' => [
'persistent_menu',
],
];
}

if ($this->type === Bot::TYPE_GET) {
return [
'fields' => 'persistent_menu',
];
}

return [
'setting_type' => 'call_to_actions',
'thread_state' => 'existing_thread',
'call_to_actions' => $buttons->map(function (Button $item) {
return $item->toData();
})->toArray(),
'persistent_menu' => $this->menus,
];
}
}

0 comments on commit 552c162

Please sign in to comment.