From 32a5d7f05a688551f72fa8576d92fb84f2a23ac8 Mon Sep 17 00:00:00 2001 From: Deon George Date: Wed, 24 Aug 2022 17:32:05 +1000 Subject: [PATCH] Added Blocks/Elements/MultiExternalSelect, ViewSubmission enhancements and Options/Base updates --- .../Blocks/Elements/MultiExternalSelect.php | 93 +++++++++++++++++++ src/Interactive/ViewSubmission.php | 34 ++----- src/Listeners/BlockSuggestionListener.php | 27 ++++++ src/Options/Base.php | 30 +++++- 4 files changed, 156 insertions(+), 28 deletions(-) create mode 100644 src/Blockkit/Blocks/Elements/MultiExternalSelect.php create mode 100644 src/Listeners/BlockSuggestionListener.php diff --git a/src/Blockkit/Blocks/Elements/MultiExternalSelect.php b/src/Blockkit/Blocks/Elements/MultiExternalSelect.php new file mode 100644 index 0000000..beb5808 --- /dev/null +++ b/src/Blockkit/Blocks/Elements/MultiExternalSelect.php @@ -0,0 +1,93 @@ + 255, + 'placeholder' => 150, + ]; + + private const MAX_OPTIONS = 100; + + // @todo option_group? (double check it is applicable to this item) + + /** + * @param Text $placeholder + * @param string $action_id + * @throws Exception + * @todo We dont handle option_groups yet. + */ + public function __construct(Text $placeholder,string $action_id) + { + parent::__construct(); + + // Defaults + $this->type = 'multi_external_select'; + + if ($placeholder->type != 'plain_text') + throw new Exception(sprintf('Text must be plain_text not %s',$placeholder->type)); + + if (strlen($placeholder->text) > self::LIMITS['placeholder']) + throw new Exception(sprintf('Text must be %d chars or less',self::LIMITS['placeholder'])); + + $this->placeholder = $placeholder; + + $this->action_id = $this->validate('action_id',$action_id); + } + + public static function item(Text $placeholder,string $action_id): self + { + return new self($placeholder,$action_id); + } + + /* OPTIONAL ITEMS */ + + public function confirm(Confirm $confirm): self + { + $this->confirm = $confirm; + + return $this; + } + + // @note only 1 element in a view can have this set to true + public function focus_on_load(bool $bool): self + { + $this->focus_on_load = $bool; + + return $this; + } + + public function initial_options(Collection $array=NULL): self + { + $this->initial_options = $array->map(function($item) { return ['text'=>['type'=>'plain_text','text'=>$item->name],'value'=>(string)$item->value]; }); + + return $this; + } + + public function min_query_length(int $int): self + { + if ($int < 1) + throw new Exception('Minimum 1 options must be configured'); + + $this->max_selected_items = $int; + + return $this; + } + + public function max_selected_items(int $int): self + { + if ($int < 1) + throw new Exception('Minimum 1 options must be configured'); + + $this->max_selected_items = $int; + + return $this; + } +} \ No newline at end of file diff --git a/src/Interactive/ViewSubmission.php b/src/Interactive/ViewSubmission.php index ee21f36..bc89a8f 100644 --- a/src/Interactive/ViewSubmission.php +++ b/src/Interactive/ViewSubmission.php @@ -24,12 +24,18 @@ class ViewSubmission extends Base public function __get($key) { switch ($key) { + case 'blocks': + return collect(object_get($this->_data,'view.'.$key)); + case 'callback_id': return object_get($this->_data,'view.'.$key); case 'meta': return object_get($this->_data,'view.private_metadata'); + case 'state': + return collect(object_get($this->_data,'view.'.$key.'.values')); + case 'view_id': return object_get($this->_data,'view.id'); @@ -68,33 +74,11 @@ class ViewSubmission extends Base Log::notice(sprintf('%s:Unhandled ACTION [%s]',self::LOGKEY,$action),['m'=>__METHOD__]); } - return new Modal(new Team); + return new Modal; } - protected function blocks(): Collection + public function value(string $block_id,string $action_id): ?string { - $result = collect(); - - foreach (object_get($this->_data,'view.blocks',[]) as $id=>$block) { - switch (object_get($block,'type')) { - case 'input': - $result->put($block->element->action_id,$block->block_id); - break; - - case 'section': - $result->put($block->block_id,$id); - break; - } - } - - return $result; - } - - public function value(string $block_id): ?string - { - $key = Arr::get($this->blocks(),$block_id); - - // Return the state value, or the original block value - return object_get($this->_data,'view.state.values.'.$key.'.'.$block_id.'.value') ?: object_get(Arr::get(object_get($this->_data,'view.blocks'),$key),'text.text',''); + return object_get($this->state->get($block_id),$action_id.'.value'); } } \ No newline at end of file diff --git a/src/Listeners/BlockSuggestionListener.php b/src/Listeners/BlockSuggestionListener.php new file mode 100644 index 0000000..c9217f0 --- /dev/null +++ b/src/Listeners/BlockSuggestionListener.php @@ -0,0 +1,27 @@ +callback_id,$event->user_id,$event->team_id),['e'=>$event]); + } +} \ No newline at end of file diff --git a/src/Options/Base.php b/src/Options/Base.php index 1b0d753..34c448f 100644 --- a/src/Options/Base.php +++ b/src/Options/Base.php @@ -2,20 +2,23 @@ namespace Slack\Options; -use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; + use Slack\Base as SlackBase; +use Slack\Message; abstract class Base extends SlackBase { + private const LOGKEY = 'SOb'; + // Does the event respond with a reply to the HTTP request, or via a post with a trigger // Child class should have a respond() function. // (There should be a local implementation of the child class should respondNow = TRUE) - public $respondNow = TRUE; + public $respondNow = FALSE; public function __construct(array $request) { - Log::info(sprintf('SOb:Slack INTERACTIVE MESSAGE Initialised [%s]',get_class($this)),['m'=>__METHOD__]); + Log::info(sprintf('%s:Slack INTERACTIVE MESSAGE Initialised [%s]',self::LOGKEY,get_class($this)),['m'=>__METHOD__]); // Our data is in a payload value parent::__construct($request); @@ -50,4 +53,25 @@ abstract class Base extends SlackBase return object_get($this->_data,$key); } } + + /** + * Interactive messages can return their output in the incoming HTTP post + * + * @return Message + * @throws \Exception + */ + public function respond(): Message + { + Log::info(sprintf('%s:Interactive Option - Callback [%s] Name [%s] Value [%s]',self::LOGKEY,$this->callback_id,$this->name,$this->value),['m'=>__METHOD__]); + + if (preg_match('/^(.*)\|([0-9]+)/',$this->callback_id)) { + [$action,$id] = explode('|',$this->callback_id,2); + + } else { + // If we get here, its an action that we dont know about. + Log::notice(sprintf('%s:Unhandled CALLBACK [%s]',self::LOGKEY,$this->callback_id),['m'=>__METHOD__]); + } + + return Message::blank(); + } } \ No newline at end of file