Rework BlockKit to include validation on size and counts
This commit is contained in:
parent
b20d7e2988
commit
b2cd5c7d46
@ -24,7 +24,7 @@ use Slack\Response\User as ResponseUser;
|
||||
use Slack\Response\Team as ResponseTeam;
|
||||
use Slack\Response\Test;
|
||||
|
||||
class API
|
||||
final class API
|
||||
{
|
||||
private const LOGKEY = 'API';
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace Slack;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
@ -9,7 +10,7 @@ use Illuminate\Support\Collection;
|
||||
*
|
||||
* @package Slack
|
||||
*/
|
||||
class BlockKit implements \JsonSerializable
|
||||
abstract class BlockKit implements \JsonSerializable
|
||||
{
|
||||
protected Collection $_data;
|
||||
|
||||
@ -18,6 +19,14 @@ class BlockKit implements \JsonSerializable
|
||||
$this->_data = collect();
|
||||
}
|
||||
|
||||
public function __get($key) {
|
||||
return $this->_data->get($key);
|
||||
}
|
||||
|
||||
public function __set(string $key,$value) {
|
||||
return $this->_data->put($key,$value);
|
||||
}
|
||||
|
||||
public function count()
|
||||
{
|
||||
return $this->_data->count();
|
||||
@ -27,4 +36,12 @@ class BlockKit implements \JsonSerializable
|
||||
{
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
protected function validate(string $key,$value)
|
||||
{
|
||||
if (Arr::get(static::LIMITS,$key) && (strlen($value) > static::LIMITS[$key]))
|
||||
throw new Exception(sprintf('%s must be %d chars or less for buttons %s',$key,self::LIMITS[$key],get_class($this)));
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit;
|
||||
|
||||
use Slack\BlockKit;
|
||||
use Slack\Blockkit\Blocks\TextEmoji;
|
||||
|
||||
/**
|
||||
* This class creates a slack actions used in BlockKit Actions
|
||||
* @todo Still needed?
|
||||
*/
|
||||
class BlockAction extends BlockKit
|
||||
{
|
||||
/**
|
||||
* Add a block button
|
||||
*
|
||||
* @param string $text
|
||||
* @param string $action
|
||||
* @param string $value
|
||||
* @param string $style
|
||||
* @return BlockAction
|
||||
* @throws \Exception
|
||||
* @deprecated Move to Blocks/Button?
|
||||
*/
|
||||
public function addButton(TextEmoji $text,string $action,string $value,string $style=''): self
|
||||
{
|
||||
if ($style AND ! in_array($style,['primary','danger']))
|
||||
abort('Invalid style: '.$style);
|
||||
|
||||
$this->_data->put('type','button');
|
||||
$this->_data->put('action_id',$action);
|
||||
$this->_data->put('text',$text);
|
||||
$this->_data->put('value',$value);
|
||||
|
||||
if ($style)
|
||||
$this->_data->put('style',$style);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -2,350 +2,8 @@
|
||||
|
||||
namespace Slack\Blockkit;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Slack\BlockKit;
|
||||
use Slack\Exceptions\SlackException;
|
||||
use Slack\Blockkit\Blocks\{Button,Text,TextEmoji};
|
||||
|
||||
/**
|
||||
* Class Blockkit Block
|
||||
* Represents a list of Blockit blocks
|
||||
*
|
||||
* @package Slack\Blockkit
|
||||
*/
|
||||
class Blocks extends BlockKit
|
||||
abstract class Blocks extends BlockKit
|
||||
{
|
||||
/**
|
||||
* Actions
|
||||
*
|
||||
* @param array $items
|
||||
* @return Blocks
|
||||
*/
|
||||
private function actions(array $items): self
|
||||
{
|
||||
$this->_data->push(array_merge(['type'=>'actions'],$items));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add actions block
|
||||
*
|
||||
* @param Collection $elements
|
||||
* @return Blocks
|
||||
*/
|
||||
public function addActionElements(Collection $elements): self
|
||||
{
|
||||
$this->actions(['elements'=>$elements]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add context items
|
||||
*
|
||||
* @param Collection $items
|
||||
* @return Blocks
|
||||
*/
|
||||
public function addContextElements(Collection $items): self
|
||||
{
|
||||
return $this->context(['elements'=>$items]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a bock divider
|
||||
*
|
||||
* @returns Blocks
|
||||
*/
|
||||
public function addDivider(): self
|
||||
{
|
||||
$this->_data->push(['type'=>'divider']);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a block header
|
||||
*
|
||||
* @param string $text
|
||||
* @return Blocks
|
||||
*/
|
||||
public function addHeader(string $text): self
|
||||
{
|
||||
$this->_data->push(['type'=>'header','text'=>TextEmoji::item($text,TRUE)]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $options
|
||||
* @param string $action_id
|
||||
* @return Collection
|
||||
* @todo To Check
|
||||
*/
|
||||
public function addOverflow(Collection $options,string $action_id): Collection
|
||||
{
|
||||
return collect([
|
||||
'type'=>'overflow',
|
||||
'options'=>$options,
|
||||
'action_id'=>$action_id,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a section with accessories
|
||||
*
|
||||
* @param Text $text
|
||||
* @param Button $accessory
|
||||
* @return Blocks
|
||||
*/
|
||||
public function addSectionAccessoryButton(Text $text,Button $accessory): self
|
||||
{
|
||||
return $this->section([
|
||||
'text'=>$text,
|
||||
'accessory'=>$accessory,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Text $label
|
||||
* @param string $action
|
||||
* @param Collection $options
|
||||
* @param string|null $default
|
||||
* @return Blocks
|
||||
* @deprecated
|
||||
* @todo Look at addSectionAccessory
|
||||
*/
|
||||
public function addSelect(Text $label,string $action,Collection $options,string $default=NULL): self
|
||||
{
|
||||
$this->_data->put('type','section');
|
||||
$this->_data->put('text',$label);
|
||||
|
||||
// Accessories
|
||||
$x = collect();
|
||||
$x->put('action_id',$action);
|
||||
$x->put('type','static_select');
|
||||
$x->put('options',$options->map(function ($item) {
|
||||
if (is_array($item))
|
||||
$item = (object)$item;
|
||||
|
||||
return [
|
||||
'text'=>[
|
||||
'type'=>'plain_text',
|
||||
'text'=>(string)$item->name,
|
||||
],
|
||||
'value'=>(string)($item->value ?: $item->id)
|
||||
];
|
||||
}));
|
||||
|
||||
if ($default) {
|
||||
$choice = $options->filter(function($item) use ($default) {
|
||||
if (is_array($item))
|
||||
$item = (object)$item;
|
||||
|
||||
return ($item->value == $default) ? $item : NULL;
|
||||
})->filter()->pop();
|
||||
|
||||
if ($choice) {
|
||||
$x->put('initial_option',[
|
||||
'text'=>TextEmoji::item($choice['name']),
|
||||
'value'=>(string)$choice['value']
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->_data->put('accessory',$x);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a section with fields
|
||||
* @param Collection $items
|
||||
* @return Blocks
|
||||
*/
|
||||
public function addSectionFields(Collection $items): self
|
||||
{
|
||||
return $this->section(['fields'=>$items]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a multiselect that queries back to the server for values
|
||||
*
|
||||
* @param Text $label
|
||||
* @param string $action
|
||||
* @return Blocks
|
||||
* @todo To Change - and rename addSectionMultiSelectInput()
|
||||
* @deprecated
|
||||
*/
|
||||
public function addMultiSelectInput(Text $label,string $action): self
|
||||
{
|
||||
$this->_data->put('type','section');
|
||||
$this->_data->put('text',$label);
|
||||
$this->_data->put('accessory',[
|
||||
'action_id'=>$action,
|
||||
'type'=>'multi_external_select',
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a section with a multi select list
|
||||
*
|
||||
* @param Text $label
|
||||
* @param string $action
|
||||
* @param Collection $options
|
||||
* @param Collection|null $selected
|
||||
* @param int|null $maximum
|
||||
* @return Blocks
|
||||
* @throws \Exception
|
||||
* @note Slack only allows 100 items
|
||||
*/
|
||||
public function addSectionMultiSelectStaticInput(Text $label,string $action,Collection $options,Collection $selected=NULL,int $maximum=NULL): self
|
||||
{
|
||||
if ($options->count() > 100)
|
||||
throw new SlackException('Selection list cannot have more than 100 items.');
|
||||
|
||||
$x = collect();
|
||||
$x->put('action_id',$action);
|
||||
$x->put('type','multi_static_select');
|
||||
$x->put('options',$options->transform(function ($item) {
|
||||
return ['text'=>TextEmoji::item($item->name),'value'=>(string)$item->id];
|
||||
}));
|
||||
|
||||
if ($selected and $selected->count())
|
||||
$x->put('initial_options',$selected->transform(function ($item) {
|
||||
return ['text'=>TextEmoji::item($item->name),'value'=>(string)$item->id];
|
||||
}));
|
||||
|
||||
if ($maximum)
|
||||
$x->put('max_selected_items',$maximum);
|
||||
|
||||
return $this->section([
|
||||
'text' => $label,
|
||||
'accessory' => $x
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a section with just text
|
||||
*
|
||||
* @param Text $text
|
||||
* @return Blocks
|
||||
*/
|
||||
public function addSectionText(Text $text): self
|
||||
{
|
||||
return $this->section(['text'=>$text]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a spacer line
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addSpacer(): self
|
||||
{
|
||||
return $this->section(['text'=>Text::item(' ')]);
|
||||
}
|
||||
|
||||
/**
|
||||
* A context block
|
||||
*
|
||||
* @param array $items
|
||||
* @return Blocks
|
||||
*/
|
||||
private function context(array $items): self
|
||||
{
|
||||
$this->_data->push(array_merge(['type'=>'context'],$items));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the input dialog
|
||||
*
|
||||
* @param string $label
|
||||
* @param string $action
|
||||
* @param int $minlength
|
||||
* @param string $placeholder
|
||||
* @param bool $multiline
|
||||
* @param string $hint
|
||||
* @param string $initial
|
||||
* @return $this
|
||||
* @throws \Exception
|
||||
* @deprecated - to optimize
|
||||
*/
|
||||
protected function input(string $label,string $action,int $minlength,string $placeholder='',bool $multiline=FALSE,string $hint='',string $initial='')
|
||||
{
|
||||
$this->_data->put('type','input');
|
||||
$this->_data->put('element',[
|
||||
'type'=>'plain_text_input',
|
||||
'action_id'=>$action,
|
||||
'placeholder'=>$this->text($placeholder ?: ' ','plain_text'),
|
||||
'multiline'=>$multiline,
|
||||
'min_length'=>$minlength,
|
||||
'initial_value'=>$initial,
|
||||
]);
|
||||
$this->_data->put('label',[
|
||||
'type'=>'plain_text',
|
||||
'text'=>$label,
|
||||
'emoji'=>true,
|
||||
]);
|
||||
$this->_data->put('optional',$minlength ? FALSE : TRUE);
|
||||
|
||||
if ($hint)
|
||||
$this->_data->put('hint',$this->text($hint,'plain_text'));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A section block
|
||||
*
|
||||
* @param array $items
|
||||
* @return Blocks
|
||||
*/
|
||||
private function section(array $items): self
|
||||
{
|
||||
$this->_data->push(array_merge(['type'=>'section'],$items));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a single-line input dialog
|
||||
*
|
||||
* @param string $label
|
||||
* @param string $action
|
||||
* @param string $placeholder
|
||||
* @param int $minlength
|
||||
* @param string $hint
|
||||
* @param string $initial
|
||||
* @return Blocks
|
||||
* @throws \Exception
|
||||
* @deprecated - to optimize
|
||||
*/
|
||||
public function addSingleLineInput(string $label,string $action,string $placeholder='',int $minlength=5,string $hint='',string $initial=''): self
|
||||
{
|
||||
return $this->input($label,$action,$minlength,$placeholder,FALSE,$hint,$initial);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a multi-line input dialog
|
||||
*
|
||||
* @param string $label
|
||||
* @param string $action
|
||||
* @param string $placeholder
|
||||
* @param int $minlength
|
||||
* @param string $hint
|
||||
* @param string $initial
|
||||
* @return Blocks
|
||||
* @throws \Exception
|
||||
* @deprecated - to optimize
|
||||
*/
|
||||
public function addMultiLineInput(string $label,string $action,string $placeholder='',int $minlength=20,string $hint='',string $initial=''): self
|
||||
{
|
||||
return $this->input($label,$action,$minlength,$placeholder,TRUE,$hint,$initial);
|
||||
}
|
||||
}
|
54
src/Blockkit/Blocks/Actions.php
Normal file
54
src/Blockkit/Blocks/Actions.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit\Blocks;
|
||||
|
||||
use \Exception;
|
||||
use Illuminate\Support\Collection;
|
||||
use Slack\Blockkit\Blocks;
|
||||
use Slack\Blockkit\Blocks\Elements\Text;
|
||||
use Slack\Blockkit\Element;
|
||||
|
||||
final class Actions extends Blocks
|
||||
{
|
||||
protected const LIMITS = [
|
||||
'block_id' => 255, // @todo Should be unique for each message
|
||||
];
|
||||
|
||||
private const MAX_ELEMENTS = 5;
|
||||
|
||||
/**
|
||||
* @param Text $text
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// Defaults
|
||||
$this->type = 'actions';
|
||||
}
|
||||
|
||||
public static function item(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
/* OPTIONAL ITEMS */
|
||||
|
||||
public function block_id(string $string): self
|
||||
{
|
||||
$this->block_id = $this->validate('block_id',$string);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function elements(Collection $collection): self
|
||||
{
|
||||
if (count($collection) > self::MAX_ELEMENTS)
|
||||
throw new Exception(sprintf('Can only have maximum %d elements',self::MAX_ELEMENTS));
|
||||
|
||||
$this->elements = $collection;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit\Blocks;
|
||||
|
||||
final class Button
|
||||
{
|
||||
public string $type;
|
||||
public TextEmoji $text;
|
||||
public string $value;
|
||||
public string $url;
|
||||
public string $action_id;
|
||||
public string $style;
|
||||
|
||||
public function __construct(TextEmoji $text,string $value,string $action_id,string $url=NULL,string $style=NULL)
|
||||
{
|
||||
$this->type = 'button';
|
||||
$this->text = $text;
|
||||
$this->value = $value ?: '-';
|
||||
$this->action_id = $action_id;
|
||||
if ($url)
|
||||
$this->url = $url;
|
||||
if ($style)
|
||||
$this->style = $style;
|
||||
}
|
||||
|
||||
public static function item(TextEmoji $text,string $value,string $action_id,string $url=NULL,string $style=NULL): self
|
||||
{
|
||||
return new self($text,$value,$action_id,$url,$style);
|
||||
}
|
||||
}
|
48
src/Blockkit/Blocks/Context.php
Normal file
48
src/Blockkit/Blocks/Context.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit\Blocks;
|
||||
|
||||
use \Exception;
|
||||
use Illuminate\Support\Collection;
|
||||
use Slack\Blockkit\Blocks;
|
||||
|
||||
final class Context extends Blocks
|
||||
{
|
||||
protected const LIMITS = [
|
||||
'block_id' => 255, // @todo Should be unique for each message
|
||||
];
|
||||
|
||||
private const MAX_ELEMENTS = 10;
|
||||
|
||||
/**
|
||||
* @param Collection $collection
|
||||
* @throws Exception
|
||||
* @todo Collection can only be image or text elements
|
||||
*/
|
||||
public function __construct(Collection $collection)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// Defaults
|
||||
$this->type = 'context';
|
||||
|
||||
if (count($collection) > self::MAX_ELEMENTS)
|
||||
throw new Exception(sprintf('Can only have maximum %d elements',self::MAX_ELEMENTS));
|
||||
|
||||
$this->elements = $collection;
|
||||
}
|
||||
|
||||
public static function item(Collection $collection): self
|
||||
{
|
||||
return new self($collection);
|
||||
}
|
||||
|
||||
/* OPTIONAL ITEMS */
|
||||
|
||||
public function block_id(string $string): self
|
||||
{
|
||||
$this->block_id = $this->validate('block_id',$string);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
40
src/Blockkit/Blocks/Divider.php
Normal file
40
src/Blockkit/Blocks/Divider.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit\Blocks;
|
||||
|
||||
use \Exception;
|
||||
use Slack\Blockkit\Blocks;
|
||||
use Slack\Blockkit\Blocks\Elements\Text;
|
||||
|
||||
final class Divider extends Blocks
|
||||
{
|
||||
protected const LIMITS = [
|
||||
'block_id' => 255, // @todo Should be unique for each message
|
||||
];
|
||||
|
||||
/**
|
||||
* @param Text|NULL $text
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// Defaults
|
||||
$this->type = 'divider';
|
||||
}
|
||||
|
||||
public static function item(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
/* OPTIONAL ITEMS */
|
||||
|
||||
public function block_id(string $string): self
|
||||
{
|
||||
$this->block_id = $this->validate('block_id',$string);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
67
src/Blockkit/Blocks/Elements/Button.php
Normal file
67
src/Blockkit/Blocks/Elements/Button.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit\Blocks\Elements;
|
||||
|
||||
use \Exception;
|
||||
use Slack\BlockKit;
|
||||
use Slack\Blockkit\Element;
|
||||
|
||||
final class Button extends Element
|
||||
{
|
||||
protected const LIMITS = [
|
||||
'action_id' => 255,
|
||||
'text' => 75,
|
||||
'url' => 3000,
|
||||
'value' => 2000,
|
||||
];
|
||||
|
||||
public function __construct(Text $text,string $value,string $action_id)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// Defaults
|
||||
$this->type = 'button';
|
||||
|
||||
if ($text->type != 'plain_text')
|
||||
throw new Exception(sprintf('Text must be plain_text not %s',$text->type));
|
||||
|
||||
if (strlen($text->text) > self::LIMITS['text'])
|
||||
throw new Exception(sprintf('Text must be %d chars or less',self::LIMITS['text']));
|
||||
|
||||
$this->text = $text;
|
||||
|
||||
$this->value = $this->validate('value',$value);
|
||||
$this->action_id = $this->validate('action_id',$action_id);
|
||||
}
|
||||
|
||||
public static function item(Text $text,string $value,string $action_id): self
|
||||
{
|
||||
return new self($text,$value,$action_id);
|
||||
}
|
||||
|
||||
/* OPTIONAL ITEMS */
|
||||
|
||||
public function confirm(Confirm $confirm): self
|
||||
{
|
||||
$this->confirm = $confirm;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function style(string $string): self
|
||||
{
|
||||
if (! in_array($string,['default','primary','danger']))
|
||||
throw new Exception(sprintf('Unknown style %s',$string));
|
||||
|
||||
$this->style = $string;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function url(string $string): self
|
||||
{
|
||||
$this->url = $this->validate('url',$string);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
20
src/Blockkit/Blocks/Elements/Confirm.php
Normal file
20
src/Blockkit/Blocks/Elements/Confirm.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit\Blocks\Elements;
|
||||
|
||||
use \Exception;
|
||||
use Slack\BlockKit;
|
||||
use Slack\Blockkit\Element;
|
||||
|
||||
final class Confirm extends Element
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
abort(500,'Not Implememted');
|
||||
}
|
||||
|
||||
public static function item(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
}
|
97
src/Blockkit/Blocks/Elements/MultiStaticSelect.php
Normal file
97
src/Blockkit/Blocks/Elements/MultiStaticSelect.php
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit\Blocks\Elements;
|
||||
|
||||
use \Exception;
|
||||
use Illuminate\Support\Collection;
|
||||
use Slack\BlockKit\Blocks;
|
||||
use Slack\Blockkit\Element;
|
||||
|
||||
final class MultiStaticSelect extends Element
|
||||
{
|
||||
protected const LIMITS = [
|
||||
'action_id' => 255,
|
||||
'placeholder' => 150,
|
||||
];
|
||||
|
||||
private const MAX_OPTIONS = 100;
|
||||
|
||||
/**
|
||||
* @param Text $placeholder
|
||||
* @param string $action_id
|
||||
* @param Collection $options
|
||||
* @throws Exception
|
||||
* @todo We dont handle option_groups yet.
|
||||
*/
|
||||
public function __construct(Text $placeholder,string $action_id,Collection $options)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// Defaults
|
||||
$this->type = 'multi_static_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);
|
||||
|
||||
if (count($options) > self::MAX_OPTIONS)
|
||||
throw new Exception(sprintf('Can only have maximum %d options',self::MAX_OPTIONS));
|
||||
|
||||
$this->options = $options->transform(function($item) {
|
||||
return ['text'=>Text::item($item->name,'plain_text'),'value'=>(string)$item->id];
|
||||
});
|
||||
}
|
||||
|
||||
public static function item(Text $placeholder,string $action_id,Collection $options): self
|
||||
{
|
||||
return new self($placeholder,$action_id,$options);
|
||||
}
|
||||
|
||||
/* OPTIONAL ITEMS */
|
||||
|
||||
public function confirm(Confirm $confirm): self
|
||||
{
|
||||
$this->confirm = $confirm;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function focus_on_load(bool $bool): self
|
||||
{
|
||||
$this->focus_on_load = $bool ? 'true' : 'false';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function initial_options(Collection $collection): self
|
||||
{
|
||||
// No initial options.
|
||||
if (! count($collection))
|
||||
return $this;
|
||||
|
||||
if (count($collection) > self::MAX_OPTIONS)
|
||||
throw new Exception(sprintf('Can only have maximum %d options',self::MAX_OPTIONS));
|
||||
|
||||
$this->initial_options = $collection->transform(function($item) {
|
||||
return ['text'=>Text::item($item->name,'plain_text'),'value'=>(string)$item->id];
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
57
src/Blockkit/Blocks/Elements/Options.php
Normal file
57
src/Blockkit/Blocks/Elements/Options.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit\Blocks\Elements;
|
||||
|
||||
use \Exception;
|
||||
use Slack\BlockKit;
|
||||
use Slack\Blockkit\Element;
|
||||
|
||||
/**
|
||||
* @note Overflow, select, and multi-select menus can only use plain_text objects,
|
||||
* while radio buttons and checkboxes can use mrkdwn text objects
|
||||
*/
|
||||
final class Options extends Element
|
||||
{
|
||||
protected const LIMITS = [
|
||||
'description' => 75,
|
||||
'text' => 75,
|
||||
'value' => 75,
|
||||
'url' => 3000,
|
||||
];
|
||||
|
||||
public function __construct(Text $text,string $value)
|
||||
{
|
||||
if (strlen($text->text) > self::LIMITS['text'])
|
||||
throw new Exception(sprintf('Text must be %d chars or less',self::LIMITS['text']));
|
||||
|
||||
$this->text = $text;
|
||||
$this->value = $this->validate('value',$value);
|
||||
}
|
||||
|
||||
public static function item(Text $text,string $value): self
|
||||
{
|
||||
return new self($text,$value);
|
||||
}
|
||||
|
||||
/* OPTIONAL ITEMS */
|
||||
|
||||
public function description(Text $text): self
|
||||
{
|
||||
if ($text->type != 'plain_text')
|
||||
throw new Exception(sprintf('Text must be plain_text not %s',$text->type));
|
||||
|
||||
if (strlen($text->text) > self::LIMITS['description'])
|
||||
throw new Exception(sprintf('Text must be %d chars or less',self::LIMITS['description']));
|
||||
|
||||
$this->description = $text;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function url(string $string): self
|
||||
{
|
||||
$this->url = $this->validate('url',$string);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
47
src/Blockkit/Blocks/Elements/Text.php
Normal file
47
src/Blockkit/Blocks/Elements/Text.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit\Blocks\Elements;
|
||||
|
||||
use \Exception;
|
||||
use Slack\BlockKit;
|
||||
use Slack\Blockkit\Element;
|
||||
|
||||
final class Text extends Element
|
||||
{
|
||||
private const TYPES = ['mrkdwn','plain_text'];
|
||||
|
||||
public function __construct(string $text,string $type)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
if (! in_array($type,self::TYPES))
|
||||
throw new Exception(sprintf('Type [%s] not valid',$type));
|
||||
|
||||
$this->type = $type;
|
||||
$this->text = $text;
|
||||
}
|
||||
|
||||
public static function item(string $text,string $type='mrkdwn'): self
|
||||
{
|
||||
return new self($text,$type);
|
||||
}
|
||||
|
||||
/* OPTIONAL ITEMS */
|
||||
|
||||
public function emoji(bool $bool): self
|
||||
{
|
||||
if ($x=$this->type != 'plain_text')
|
||||
throw new Exception(sprintf('Cannnot use emoji when type is [%s]',$x));
|
||||
|
||||
$this->emoji = $bool ? 'true' : 'false';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function verbatim(bool $bool): self
|
||||
{
|
||||
$this->verbatim = $bool ? 'true' : 'false';
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
49
src/Blockkit/Blocks/Header.php
Normal file
49
src/Blockkit/Blocks/Header.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit\Blocks;
|
||||
|
||||
use \Exception;
|
||||
use Slack\Blockkit\Blocks;
|
||||
use Slack\Blockkit\Blocks\Elements\Text;
|
||||
|
||||
final class Header extends Blocks
|
||||
{
|
||||
protected const LIMITS = [
|
||||
'block_id' => 255, // @todo Should be unique for each message
|
||||
'text' => 150,
|
||||
];
|
||||
|
||||
/**
|
||||
* @param Text $text
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct(Text $text)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// Defaults
|
||||
$this->type = 'header';
|
||||
|
||||
if ($text->type != 'plain_text')
|
||||
throw new Exception(sprintf('Text must be plain_text not %s',$text->type));
|
||||
|
||||
if (strlen($text->text) > self::LIMITS['text'])
|
||||
throw new Exception(sprintf('Text must be %d chars or less',self::LIMITS['text']));
|
||||
|
||||
$this->text = $text;
|
||||
}
|
||||
|
||||
public static function item(Text $text): self
|
||||
{
|
||||
return new self($text);
|
||||
}
|
||||
|
||||
/* OPTIONAL ITEMS */
|
||||
|
||||
public function block_id(string $string): self
|
||||
{
|
||||
$this->block_id = $this->validate('block_id',$string);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit\Blocks;
|
||||
|
||||
use Slack\Blockkit\Input\Element;
|
||||
|
||||
final class Input
|
||||
{
|
||||
public string $type;
|
||||
public Element $element;
|
||||
public TextEmoji $label;
|
||||
|
||||
public function __construct(Element $element,TextEmoji $label)
|
||||
{
|
||||
$this->type = 'input';
|
||||
$this->element = $element;
|
||||
$this->label = $label;
|
||||
}
|
||||
|
||||
public static function item(Element $element,TextEmoji $label): self
|
||||
{
|
||||
return new self($element,$label);
|
||||
}
|
||||
}
|
80
src/Blockkit/Blocks/Section.php
Normal file
80
src/Blockkit/Blocks/Section.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit\Blocks;
|
||||
|
||||
use \Exception;
|
||||
use Illuminate\Support\Collection;
|
||||
use Slack\Blockkit\{Blocks,Element};
|
||||
use Slack\BLockKit\Blocks\Elements\Text;
|
||||
|
||||
final class Section extends Blocks
|
||||
{
|
||||
protected const LIMITS = [
|
||||
'block_id' => 255, // @todo Should be unique for each message
|
||||
'text' => 3000,
|
||||
];
|
||||
|
||||
private const MAX_FIELDS = 10;
|
||||
private const MAX_FIELDS_TEXT = 2000;
|
||||
|
||||
/**
|
||||
* @param Text|NULL $text not required if fields is provided
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct(Text $text=NULL)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// Defaults
|
||||
$this->type = 'section';
|
||||
|
||||
if ($text) {
|
||||
if (strlen($text->text) > self::LIMITS['text'])
|
||||
throw new Exception(sprintf('Text must be %d chars or less',self::LIMITS['text']));
|
||||
|
||||
$this->text = $text;
|
||||
}
|
||||
}
|
||||
|
||||
public static function item(Text $text=NULL): self
|
||||
{
|
||||
return new self($text);
|
||||
}
|
||||
|
||||
public function jsonSerialize()
|
||||
{
|
||||
if (! $this->text && ! $this->fields)
|
||||
throw new Exception('Must define text or fields');
|
||||
|
||||
return parent::jsonSerialize();
|
||||
}
|
||||
|
||||
/* OPTIONAL ITEMS */
|
||||
|
||||
public function accessory(Element $object): self
|
||||
{
|
||||
$this->accessory = $object;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function block_id(string $string): self
|
||||
{
|
||||
$this->block_id = $this->validate('block_id',$string);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function fields(Collection $collection): self
|
||||
{
|
||||
if (count($collection) > self::MAX_FIELDS)
|
||||
throw new Exception(sprintf('Can only have maximum %d fields',self::MAX_FIELDS));
|
||||
|
||||
if ($collection->map(function($item) { return strlen($item->text); })->max() > self::MAX_FIELDS_TEXT)
|
||||
throw new Exception(sprintf('The maximum size of text in a field is %d',self::MAX_FIELDS_TEXT));
|
||||
|
||||
$this->fields = $collection;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit\Blocks;
|
||||
|
||||
final class Text
|
||||
{
|
||||
public string $type;
|
||||
public string $text;
|
||||
|
||||
public function __construct(string $text,string $type='mrkdwn')
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->text = $text;
|
||||
}
|
||||
|
||||
public static function item(string $text,string $type='mrkdwn'): self
|
||||
{
|
||||
return new self($text,$type);
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit\Blocks;
|
||||
|
||||
final class TextEmoji
|
||||
{
|
||||
public bool $emoji;
|
||||
public string $text;
|
||||
public string $type;
|
||||
|
||||
public function __construct(string $text,bool $emoji=TRUE)
|
||||
{
|
||||
$this->emoji = $emoji;
|
||||
$this->text = $text;
|
||||
$this->type = 'plain_text';
|
||||
}
|
||||
|
||||
public static function item(string $text,bool $emoji=TRUE): self
|
||||
{
|
||||
return new self($text,$emoji);
|
||||
}
|
||||
}
|
9
src/Blockkit/Element.php
Normal file
9
src/Blockkit/Element.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit;
|
||||
|
||||
use Slack\BlockKit;
|
||||
|
||||
abstract class Element extends BlockKit
|
||||
{
|
||||
}
|
@ -2,30 +2,68 @@
|
||||
|
||||
namespace Slack\Blockkit;
|
||||
|
||||
use \Exception;
|
||||
use Slack\BlockKit;
|
||||
use Slack\Blockkit\Blocks\TextEmoji;
|
||||
use Slack\Blockkit\Blocks\Divider;
|
||||
use Slack\Blockkit\Blocks\Elements\Text;
|
||||
use Slack\Blockkit\Blocks\Section;
|
||||
|
||||
/**
|
||||
* This class creates a slack Modal Response
|
||||
*/
|
||||
class Modal extends BlockKit
|
||||
final class Modal extends BlockKit
|
||||
{
|
||||
protected const LIMITS = [
|
||||
'callback_id' => 255,
|
||||
'close' => 24,
|
||||
'private_metadata' => 3000,
|
||||
'text' => 24,
|
||||
];
|
||||
|
||||
private const MAX_BLOCKS = 100;
|
||||
|
||||
private $action = NULL;
|
||||
|
||||
public function __construct(TextEmoji $title)
|
||||
public function __construct(Text $title=NULL,string $type='modal')
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->_data->put('type','modal');
|
||||
$this->_data->put('title',$title);
|
||||
if (! in_array($type,['modal','home']))
|
||||
throw new Exception(sprintf('Unknown type %s',$type));
|
||||
|
||||
if ($type != 'modal' && $title)
|
||||
throw new Exception(sprintf('Titles are not required for %s',$type));
|
||||
|
||||
if ($title) {
|
||||
if ($title->type != 'plain_text')
|
||||
throw new Exception(sprintf('Text must be plain_text not %s',$title->type));
|
||||
|
||||
if (strlen($title->text) > self::LIMITS['text'])
|
||||
throw new Exception(sprintf('Text must be %d chars or less',self::LIMITS['text']));
|
||||
|
||||
$this->title = $title;
|
||||
}
|
||||
|
||||
/*
|
||||
public function action(string $action)
|
||||
{
|
||||
$this->action = $action;
|
||||
$this->type = $type;
|
||||
|
||||
$this->blocks = collect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a block to this modal
|
||||
*
|
||||
* @param BlockKit $block
|
||||
* @return $this
|
||||
*/
|
||||
public function addBlock(Blocks $block): self
|
||||
{
|
||||
$this->blocks->push($block);
|
||||
|
||||
if ($x=$this->blocks->count() > self::MAX_BLOCKS)
|
||||
throw new Exception(sprintf('Modal can only have %d blocks',self::MAX_BLOCKS));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The data that will be returned when converted to JSON.
|
||||
@ -37,18 +75,133 @@ class Modal extends BlockKit
|
||||
return ['response_action'=>'clear'];
|
||||
|
||||
case 'update':
|
||||
return ['response_action'=>'update','view'=>$this->_data];
|
||||
return ['response_action'=>'update','view'=>parent::jsonSerialize()];
|
||||
|
||||
default:
|
||||
return $this->_data;
|
||||
return parent::jsonSerialize();
|
||||
}
|
||||
}
|
||||
|
||||
/* OPTIONAL ITEMS */
|
||||
|
||||
public function action(string $string)
|
||||
{
|
||||
if (! in_array($string,['clear','update']))
|
||||
throw new Exception(sprintf('Unknown action %s',$string));
|
||||
|
||||
$this->action = $string;
|
||||
}
|
||||
|
||||
public function clear_on_close(bool $bool): self
|
||||
{
|
||||
if ($this->type != 'modal')
|
||||
throw new Exception(sprintf('clear_on_close is not required for %s',$type));
|
||||
|
||||
$this->clear_on_close = $bool ? 'true' : 'false';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function callback_id(string $string): self
|
||||
{
|
||||
$this->callback_id = $this->validate('callback_id',$string);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function close(Text $text): self
|
||||
{
|
||||
if ($this->type != 'modal')
|
||||
throw new Exception(sprintf('Close is not required for %s',$type));
|
||||
|
||||
if ($text->type != 'plain_text')
|
||||
throw new Exception(sprintf('Text must be plain_text not %s',$text->type));
|
||||
|
||||
if (strlen($text->text) > self::LIMITS['close'])
|
||||
throw new Exception(sprintf('Text must be %d chars or less',self::LIMITS['close']));
|
||||
|
||||
$this->close = $text;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
// This is a helper method
|
||||
public function divider(): self
|
||||
{
|
||||
$this->blocks->push(Divider::item());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @return $this
|
||||
* @note A custom identifier that must be unique for all views on a per-team basis.
|
||||
*/
|
||||
public function external_id(string $string): self
|
||||
{
|
||||
$this->external_id = $string;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function notify_on_close(bool $bool): self
|
||||
{
|
||||
if ($this->type != 'modal')
|
||||
throw new Exception(sprintf('notify_on_close is not required for %s',$type));
|
||||
|
||||
$this->notify_on_close = $bool ? 'true' : 'false';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function private_metadata(string $string): self
|
||||
{
|
||||
$this->private_metadata = $this->validate('private_metadata',$string);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
// This is a helper method
|
||||
public function spacer(): self
|
||||
{
|
||||
$this->blocks->push(Section::item(Text::item(' ')));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function submit(Text $text): self
|
||||
{
|
||||
if ($this->type != 'modal')
|
||||
throw new Exception(sprintf('Submit is not required for %s',$type));
|
||||
|
||||
if ($text->type != 'plain_text')
|
||||
throw new Exception(sprintf('Text must be plain_text not %s',$text->type));
|
||||
|
||||
if (strlen($text->text) > self::LIMITS['submit'])
|
||||
throw new Exception(sprintf('Text must be %d chars or less',self::LIMITS['submit']));
|
||||
|
||||
$this->submit = $text;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function submit_disabled(bool $bool): self
|
||||
{
|
||||
if ($this->type != 'modal')
|
||||
throw new Exception(sprintf('submit_disabled is not required for %s',$type));
|
||||
|
||||
$this->submit_disabled = $bool ? 'true' : 'false';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a block to the modal
|
||||
*
|
||||
* @param Blocks $blocks
|
||||
* @return $this
|
||||
* @deprecated use addBlock() instead
|
||||
*/
|
||||
public function setBlocks(Blocks $blocks): self
|
||||
{
|
||||
@ -56,58 +209,4 @@ class Modal extends BlockKit
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setCallback(string $id): self
|
||||
{
|
||||
$this->_data->put('callback_id',$id);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/*
|
||||
public function close(string $text='Cancel'): self
|
||||
{
|
||||
$this->_data->put('close',
|
||||
[
|
||||
'type'=>'plain_text',
|
||||
'text'=>$text,
|
||||
'emoji'=>true,
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function meta(string $id): self
|
||||
{
|
||||
$this->_data->put('private_metadata',$id);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function notifyClose(): self
|
||||
{
|
||||
$this->_data->put('notify_on_close',TRUE);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function private(array $data): self
|
||||
{
|
||||
$this->_data->put('private_metadata',json_encode($data));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function submit(string $text='Submit'): self
|
||||
{
|
||||
$this->_data->put('submit',
|
||||
[
|
||||
'type'=>'plain_text',
|
||||
'text'=>$text,
|
||||
'emoji'=>true,
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
*/
|
||||
}
|
@ -60,10 +60,12 @@ abstract class Base extends SlackBase
|
||||
if (! $this->channel() || ! $this->channel()->active) {
|
||||
$blocks = new Blocks;
|
||||
|
||||
$blocks->addHeader(':robot_face: Bot not in this channel');
|
||||
$blocks->addSectionText(Blocks\Text::item(sprintf('Please add %s to this channel and try this again.',$this->team()->bot->name ?: 'the BOT')));
|
||||
|
||||
$o->setAttachments((new Message\Attachments())->setBlocks($blocks)->setColor('#ff0000'));
|
||||
$o->addAttachment(
|
||||
Message\Attachment::item()
|
||||
->title(':robot_face: Bot not in this channel')
|
||||
->text(sprintf('Please add %s to this channel and try this again.',$this->team()->bot->name ?: 'the BOT'))
|
||||
->color('#ff0000')
|
||||
);
|
||||
}
|
||||
|
||||
return $o->isEmpty() ? NULL : $o;
|
||||
|
@ -3,7 +3,6 @@
|
||||
namespace Slack\Command;
|
||||
|
||||
use Slack\Message;
|
||||
use Slack\Message\Attachments;
|
||||
|
||||
class Help extends Base
|
||||
{
|
||||
@ -13,12 +12,13 @@ class Help extends Base
|
||||
{
|
||||
$o = new Message;
|
||||
|
||||
$o->setText('Hi, I am a *NEW* Bot');
|
||||
$o->text('Hi, I am a *NEW* Bot');
|
||||
|
||||
// Version
|
||||
$a = new Attachments;
|
||||
$a->addField('Version',config('app.version','unknown'),TRUE);
|
||||
$o->setAttachments($a);
|
||||
$o->addAttachment(
|
||||
Message\Attachment::item()
|
||||
->addField('Version',config('app.version','unknown'),TRUE)
|
||||
);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ final class Unknown extends Base
|
||||
{
|
||||
$o = new Message;
|
||||
|
||||
$o->setText(sprintf('I didnt understand your command "%s". You might like to try `%s help` instead.',$this->command,$this->slashcommand));
|
||||
$o->text(sprintf('I didnt understand your command "%s". You might like to try `%s help` instead.',$this->command,$this->slashcommand));
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
@ -3,7 +3,8 @@
|
||||
namespace App\Listeners;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Slack\Blockkit\Blocks;
|
||||
use Slack\Blockkit\Blocks\Elements\Text;
|
||||
use Slack\Blockkit\Blocks\{Header,Section};
|
||||
use Slack\Blockkit\Modal;
|
||||
use Slack\Interactive\Shortcut;
|
||||
use Slack\Message;
|
||||
@ -25,13 +26,15 @@ class ShortcutListener //implements ShouldQueue
|
||||
public function handle(Shortcut $event): Message
|
||||
{
|
||||
if (! $event->channel() || ! $event->channel()->active) {
|
||||
$modal = new Modal(Blocks\TextEmoji::item(config('app.name')));
|
||||
$modal = new Modal(Text::item(config('app.name'),'plain_text'));
|
||||
$blocks = new Blocks;
|
||||
|
||||
$blocks->addHeader(':robot_face: Bot not in this channel');
|
||||
$blocks->addSectionText(Blocks\Text::item('Please add the BOT to this channel and try this again.'));
|
||||
|
||||
$modal->setBlocks($blocks);
|
||||
$modal->addBlock(
|
||||
Header::item(Text::item(':robot_face: Bot not in this channel','plain_text'))
|
||||
)
|
||||
->addBlock(
|
||||
Section::item(Text::item('Please add the BOT to this channel and try this again.'))
|
||||
);
|
||||
|
||||
try {
|
||||
$event->team()->slackAPI()->viewOpen($event->trigger_id,json_encode($modal));
|
||||
|
326
src/Message.php
326
src/Message.php
@ -5,23 +5,28 @@ namespace Slack;
|
||||
use Carbon\Carbon;
|
||||
use Carbon\CarbonInterface;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Slack\Blockkit\Blocks;
|
||||
use Slack\Blockkit\Blocks\Context;
|
||||
use Slack\Blockkit\Blocks\Elements\Text;
|
||||
use Slack\Exceptions\SlackException;
|
||||
use Slack\Jobs\DeleteChat;
|
||||
use Slack\Message\Attachments;
|
||||
use Slack\Message\Attachment;
|
||||
use Slack\Models\{Channel,User};
|
||||
use Slack\Response\Generic;
|
||||
|
||||
/**
|
||||
* This class is used when composing a message to send to Slack.
|
||||
*/
|
||||
class Message implements \JsonSerializable
|
||||
final class Message extends BlockKit
|
||||
{
|
||||
protected const LOGKEY = 'SM-';
|
||||
|
||||
private const MAX_ATTACHMENTS = 20;
|
||||
|
||||
private Model $o;
|
||||
private Blocks $blocks;
|
||||
private ?Carbon $selfdestruct = NULL;
|
||||
|
||||
/**
|
||||
@ -32,7 +37,7 @@ class Message implements \JsonSerializable
|
||||
*/
|
||||
public function __construct(Model $o=NULL)
|
||||
{
|
||||
$this->_data = collect();
|
||||
parent::__construct();
|
||||
|
||||
if ($o) {
|
||||
// Message is to a channel
|
||||
@ -49,10 +54,10 @@ class Message implements \JsonSerializable
|
||||
|
||||
$this->o = $o;
|
||||
}
|
||||
|
||||
$this->blocks = new Blocks;
|
||||
}
|
||||
|
||||
/* HELPER METHODS */
|
||||
|
||||
/**
|
||||
* Add a block to the message
|
||||
*
|
||||
@ -60,9 +65,25 @@ class Message implements \JsonSerializable
|
||||
* @return Message
|
||||
* @todo to test
|
||||
*/
|
||||
public function addBlock(Blocks $blocks): self
|
||||
public function addAttachment(Attachment $attachment): self
|
||||
{
|
||||
$this->blocks = $blocks;
|
||||
if (! Arr::get($this->_data,'attachments'))
|
||||
$this->attachments = collect();
|
||||
|
||||
$this->attachments->push($attachment);
|
||||
|
||||
if (count($this->attachments) > self::MAX_ATTACHMENTS)
|
||||
throw new Exception(sprintf('Messages should not have more than %d attachments',self::MAX_ATTACHMENTS));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addBlock(Blocks $block): self
|
||||
{
|
||||
if (! Arr::get($this->_data,'blocks'))
|
||||
$this->blocks = collect();
|
||||
|
||||
$this->blocks->push($block);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -75,21 +96,10 @@ class Message implements \JsonSerializable
|
||||
public function blank(): self
|
||||
{
|
||||
$this->_data = collect();
|
||||
$this->blocks = new Blocks;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/*
|
||||
* @todo This doesnt appear to work
|
||||
public function ephemeral(): self
|
||||
{
|
||||
$this->_data->put('ephemeral',TRUE);
|
||||
|
||||
return $this;
|
||||
}
|
||||
*/
|
||||
|
||||
public function forgetTS(): self
|
||||
{
|
||||
$this->_data->forget('ts');
|
||||
@ -112,11 +122,8 @@ class Message implements \JsonSerializable
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
if ($this->blocks->count())
|
||||
$this->_data->put('blocks',$this->blocks);
|
||||
|
||||
// For interactive messages that generate a dialog, we need to return NULL
|
||||
return $this->_data->count() ? $this->_data : NULL;
|
||||
return $this->_data->count() ? parent::jsonSerialize() : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -134,7 +141,7 @@ class Message implements \JsonSerializable
|
||||
if ($this->_data->has('ephemeral'))
|
||||
abort('500','Cannot post ephemeral messages.');
|
||||
|
||||
if ($this->blocks->count() && $this->_data->get('attachments'))
|
||||
if ($this->_data->get('blocks') && $this->_data->get('attachments'))
|
||||
throw new SlackException('Message cannot have blocks and attachments.');
|
||||
|
||||
$api = $this->o->team->slackAPI();
|
||||
@ -150,42 +157,6 @@ class Message implements \JsonSerializable
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule a message
|
||||
*
|
||||
* @param Carbon $time
|
||||
* @return Generic
|
||||
*/
|
||||
public function schedule(Carbon $time): Generic
|
||||
{
|
||||
$this->_data->put('post_at',$time->timestamp);
|
||||
|
||||
$api = $this->o->team->slackAPI();
|
||||
$response = $this->_data->has('ts') ? $api->updateMessage($this) : $api->scheduleMessage($this);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function setReplace(bool $replace=TRUE): self
|
||||
{
|
||||
$this->_data->put('replace_original',$replace ? 'true' : 'false');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* To slack from rendering URLs in the message
|
||||
*
|
||||
* @param bool $unfurl
|
||||
* @return $this
|
||||
*/
|
||||
public function setUnfurlLinks(bool $unfurl): self
|
||||
{
|
||||
$this->_data->put('unfurl_links',$unfurl ? 'true' : 'false');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Post a message to slack using the respond_url
|
||||
*
|
||||
@ -228,6 +199,22 @@ class Message implements \JsonSerializable
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule a message
|
||||
*
|
||||
* @param Carbon $time
|
||||
* @return Generic
|
||||
*/
|
||||
public function schedule(Carbon $time): Generic
|
||||
{
|
||||
$this->_data->put('post_at',$time->timestamp);
|
||||
|
||||
$api = $this->o->team->slackAPI();
|
||||
$response = $this->_data->has('ts') ? $api->updateMessage($this) : $api->scheduleMessage($this);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the message self destruct
|
||||
*
|
||||
@ -236,21 +223,161 @@ class Message implements \JsonSerializable
|
||||
*/
|
||||
public function selfdestruct(Carbon $time): self
|
||||
{
|
||||
$this->blocks->addContextElements(collect([
|
||||
Blocks\Text::item(sprintf('This message will self destruct in %s...',$time->diffForHumans(Carbon::now(),['syntax' => CarbonInterface::DIFF_RELATIVE_TO_NOW])))
|
||||
]));
|
||||
$this->addBlock(
|
||||
Context::item(collect([
|
||||
Text::item(sprintf('This message will self destruct in %s...',$time->diffForHumans(Carbon::now(),['syntax' => CarbonInterface::DIFF_RELATIVE_TO_NOW])))
|
||||
]))
|
||||
);
|
||||
|
||||
$this->selfdestruct = $time;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an attachment to a message
|
||||
* Set our channel
|
||||
*
|
||||
* @param Attachments $attachments
|
||||
* @param Channel $o
|
||||
* @return Message
|
||||
*/
|
||||
public function setAttachments(Attachments $attachments): self
|
||||
public function setChannel(Channel $o): self
|
||||
{
|
||||
$this->channel = $o->channel_id;
|
||||
$this->o = $o;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set our channel
|
||||
*
|
||||
* @param User $o
|
||||
* @return Message
|
||||
*/
|
||||
public function setUser(User $o): self
|
||||
{
|
||||
$this->channel = $o->user_id;
|
||||
$this->o = $o;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/* CONFIGURATION METHODS */
|
||||
|
||||
/**
|
||||
* @return Message
|
||||
* @todo - Check this is a valid option
|
||||
*/
|
||||
public function ephemeral(): self
|
||||
{
|
||||
$this->ephemeral = 'true';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the icon next to the message
|
||||
*
|
||||
* @param string $icon
|
||||
* @return Message
|
||||
* @deprecated
|
||||
*/
|
||||
public function icon_emoji(string $icon): self
|
||||
{
|
||||
$this->icon_emoji = $icon;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Option groups are used by the interactive Options controller and hold no other attributes
|
||||
*
|
||||
* @param Collection $collection
|
||||
* @return Message
|
||||
* @todo - Check this is a valid option
|
||||
*/
|
||||
public function option_groups(Collection $collection): self
|
||||
{
|
||||
$this->option_groups = $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Message
|
||||
* @todo - Check this is a valid option
|
||||
*/
|
||||
public function replace_original(bool $bool=TRUE): self
|
||||
{
|
||||
$this->replace_original = $bool ? 'true' : 'false';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Message text
|
||||
*
|
||||
* @param string $string
|
||||
* @return Message
|
||||
*/
|
||||
public function text(string $string): self
|
||||
{
|
||||
$this->text = $string;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the thread timestamp, used when adding a threaded response
|
||||
*
|
||||
* @param string $string
|
||||
* @return Message
|
||||
*/
|
||||
public function thread_ts(string $string): self
|
||||
{
|
||||
$this->thread_ts = $string;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the timestamp, used when replacing messages
|
||||
*
|
||||
* @param string $string
|
||||
* @return Message
|
||||
*/
|
||||
public function ts(string $string): self
|
||||
{
|
||||
$this->ts = $string;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* To slack from rendering URLs in the message
|
||||
*
|
||||
* @param bool $bool
|
||||
* @return $this
|
||||
*/
|
||||
public function unfurl_links(bool $bool): self
|
||||
{
|
||||
$this->unfurl_links = $bool ? 'true' : 'false';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function username(string $user): self
|
||||
{
|
||||
$this->username = $user;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an attachment to a message
|
||||
*
|
||||
* @param Attachment $attachments
|
||||
* @return Message
|
||||
* @deprecated use addAttachment()
|
||||
*/
|
||||
public function setAttachments(Attachment $attachments): self
|
||||
{
|
||||
$this->_data->put('attachments',[$attachments]);
|
||||
|
||||
@ -263,6 +390,7 @@ class Message implements \JsonSerializable
|
||||
* @param Blocks $blocks
|
||||
* @return Message
|
||||
* @throws \Exception
|
||||
* @deprecated use addBlocks()
|
||||
*/
|
||||
public function setBlocks(Blocks $blocks): self
|
||||
{
|
||||
@ -274,55 +402,16 @@ class Message implements \JsonSerializable
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set our channel
|
||||
*
|
||||
* @param Channel $o
|
||||
* @return Message
|
||||
*/
|
||||
public function setChannel(Channel $o): self
|
||||
{
|
||||
$this->_data->put('channel',$o->channel_id);
|
||||
$this->o = $o;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the icon next to the message
|
||||
*
|
||||
* @param string $icon
|
||||
* @return Message
|
||||
* @deprecated
|
||||
*/
|
||||
public function setIcon(string $icon): self
|
||||
{
|
||||
$this->_data->put('icon_emoji',$icon);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Option groups are used by the interactive Options controller and hold no other attributes
|
||||
*
|
||||
* @param array $array
|
||||
* @return void
|
||||
*/
|
||||
public function setOptionGroup(array $array): void
|
||||
{
|
||||
$this->_data = collect(); // @todo Why are clearing our data?
|
||||
$this->_data->put('option_groups',$array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Message text
|
||||
*
|
||||
* @param string $string
|
||||
* @return Message
|
||||
* @deprecated use text()
|
||||
*/
|
||||
public function setText(string $string): self
|
||||
{
|
||||
$this->_data->put('text',$string);
|
||||
$this->text = $string;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -332,6 +421,7 @@ class Message implements \JsonSerializable
|
||||
*
|
||||
* @param string $string
|
||||
* @return Message
|
||||
* @deprecated use ts()
|
||||
*/
|
||||
public function setTS(string $string): self
|
||||
{
|
||||
@ -345,6 +435,7 @@ class Message implements \JsonSerializable
|
||||
*
|
||||
* @param string $string
|
||||
* @return Message
|
||||
* @deprecated use thead_ts()
|
||||
*/
|
||||
public function setThreadTS(string $string): self
|
||||
{
|
||||
@ -352,25 +443,4 @@ class Message implements \JsonSerializable
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set our channel
|
||||
*
|
||||
* @param User $o
|
||||
* @return Message
|
||||
*/
|
||||
public function setUser(User $o): self
|
||||
{
|
||||
$this->_data->put('channel',$o->user_id);
|
||||
$this->o = $o;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setUserName(string $user): self
|
||||
{
|
||||
$this->_data->put('username',$user);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
168
src/Message/Attachment.php
Normal file
168
src/Message/Attachment.php
Normal file
@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Message;
|
||||
|
||||
use \Exception;
|
||||
use Illuminate\Support\Arr;
|
||||
use Slack\BlockKit;
|
||||
use Slack\Blockkit\Blocks;
|
||||
|
||||
final class Attachment extends BlockKit
|
||||
{
|
||||
protected const LIMITS = [
|
||||
'footer' => 300,
|
||||
];
|
||||
|
||||
/**
|
||||
* @param Text $text
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public static function item(): self
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
|
||||
/* OPTIONAL ITEMS */
|
||||
|
||||
/**
|
||||
* @note These are now legacy - use blocks instead
|
||||
* @note more information on this available https://api.slack.com/legacy/interactive-message-field-guide
|
||||
*/
|
||||
public function addAction(string $name,string $text,string $type,string $value,string $style=NULL,array $confirm=NULL): self
|
||||
{
|
||||
if (! Arr::get($this->_data,'actions')) {
|
||||
$this->actions = collect();
|
||||
$this->attachment_type = 'default';
|
||||
}
|
||||
|
||||
$action = ['name'=>$name,'text'=>$text,'type'=>$type,'value'=>$value];
|
||||
if ($style)
|
||||
$action['style'] = $style;
|
||||
|
||||
// Confirm dialog is an array of 'title','text','ok_text','dismiss_text'
|
||||
if ($confirm)
|
||||
$action['confirm'] = $confirm;
|
||||
|
||||
$this->actions->push();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addBlock(Blocks $block): self
|
||||
{
|
||||
if (! Arr::get($this->_data,'blocks'))
|
||||
$this->blocks = collect();
|
||||
|
||||
$this->blocks->push($block);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addField(string $title,string $value,bool $short): self
|
||||
{
|
||||
if (! Arr::get($this->_data,'fields'))
|
||||
$this->fields = collect();
|
||||
|
||||
$this->fields->push(['title'=>$title,'value'=>$value,'short'=>$short ? 'true' : 'false']);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @return $this
|
||||
* @note Can either be one of good (green), warning (yellow), danger (red), or any hex color code (eg. #439FE0)
|
||||
*/
|
||||
public function color(string $string): self
|
||||
{
|
||||
$this->color = $string;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @return $this
|
||||
* @note Appears to be only used with actions
|
||||
*/
|
||||
public function callback_id(string $string): self
|
||||
{
|
||||
$this->callback_id = $string;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function fallback(string $string): self
|
||||
{
|
||||
$this->fallback = $string;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function footer(string $string): self
|
||||
{
|
||||
$this->footer = $this->validate('footer',$string);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function footer_icon(string $string): self
|
||||
{
|
||||
$this->footer_icon = $string;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set where markdown should be parsed by slack
|
||||
*
|
||||
* @param array $array
|
||||
*/
|
||||
public function mrkdwn_in(array $array): self
|
||||
{
|
||||
// @todo Add array check to make sure it has valid items
|
||||
$this->mrkdwn_in = $array;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function pretext(string $string): self
|
||||
{
|
||||
$this->pretext = $string;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function text(string $string): self
|
||||
{
|
||||
$this->text = $string;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function title(string $string): self
|
||||
{
|
||||
$this->title = $string;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function title_link(string $string): self
|
||||
{
|
||||
$this->title_link = $string;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function ts(string $string): self
|
||||
{
|
||||
$this->ts = $string;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -1,133 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Message;
|
||||
|
||||
/**
|
||||
* Class MessageAttachmentAction - Slack Message Attachments Actions
|
||||
* Represents an Single Action for a Slack Message Attachment
|
||||
*
|
||||
* @package Slack\Message
|
||||
*/
|
||||
class AttachmentAction implements \JsonSerializable
|
||||
{
|
||||
private $_data;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->_data = collect();
|
||||
}
|
||||
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
public function minSize(int $int): self
|
||||
{
|
||||
$this->_data->put('min_query_length',$int);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a confirmation diaglog when this action is selected
|
||||
*
|
||||
* @param string $title
|
||||
* @param string $text
|
||||
* @param string $ok_text
|
||||
* @param string $dismiss_text
|
||||
* @return $this
|
||||
*/
|
||||
public function setConfirm(string $title,string $text,string $ok_text,string $dismiss_text): self
|
||||
{
|
||||
$this->_data->put('confirm',[
|
||||
'title'=>$title,
|
||||
'text'=>$text,
|
||||
'ok_text'=>$ok_text,
|
||||
'dismiss_text'=>$dismiss_text
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the action
|
||||
*
|
||||
* @param string $string
|
||||
* @return $this
|
||||
*/
|
||||
public function setName(string $string): self
|
||||
{
|
||||
$this->_data->put('name',$string);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the text displayed in the action
|
||||
*
|
||||
* @param string $type
|
||||
* @return $this
|
||||
*/
|
||||
public function setStyle(string $style): self
|
||||
{
|
||||
if (! in_array($style,['danger','primary']))
|
||||
abort(500,'Style not supported: '.$style);
|
||||
|
||||
$this->_data->put('style',$style);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the text displayed in the action
|
||||
*
|
||||
* @param string $string
|
||||
* @return $this
|
||||
*/
|
||||
public function setText(string $string): self
|
||||
{
|
||||
$this->_data->put('text',$string);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the text displayed in the action
|
||||
*
|
||||
* @param string $type
|
||||
* @return $this
|
||||
*/
|
||||
public function setType(string $type): self
|
||||
{
|
||||
if (! in_array($type,['button','select']))
|
||||
abort(500,'Type not supported: '.$type);
|
||||
|
||||
$this->_data->put('type',$type);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value for the action
|
||||
*
|
||||
* @param string $string
|
||||
* @return $this
|
||||
*/
|
||||
public function setValue(string $string): self
|
||||
{
|
||||
$this->_data->put('value',$string);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function source(string $string): self
|
||||
{
|
||||
if (! in_array($string,['external']))
|
||||
abort(500,'Dont know how to handle: '.$string);
|
||||
|
||||
$this->_data->put('data_source',$string);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -1,227 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Message;
|
||||
|
||||
use Slack\BlockKit;
|
||||
use Slack\Blockkit\BlockAction;
|
||||
use Slack\Blockkit\Blocks;
|
||||
|
||||
/**
|
||||
* Class MessageAttachment - Slack Message Attachments
|
||||
* Represents an Single Attachment that can be added to a Message
|
||||
*
|
||||
* @package Slack\Message
|
||||
*/
|
||||
class Attachments implements \JsonSerializable
|
||||
{
|
||||
private $_data;
|
||||
private $actions;
|
||||
//private $blocks;
|
||||
private $blockactions;
|
||||
|
||||
// @todo To rework
|
||||
public function __construct()
|
||||
{
|
||||
$this->actions = collect();
|
||||
//$this->blocks = collect();
|
||||
$this->blockactions = collect();
|
||||
$this->_data = collect();
|
||||
}
|
||||
|
||||
// @todo To rework
|
||||
|
||||
public function jsonSerialize()
|
||||
{
|
||||
/*
|
||||
if ($this->actions->count() AND ! $this->_data->has('callback_id'))
|
||||
abort(500,'Actions without a callback ID');
|
||||
|
||||
if ($this->blockactions->count()) {
|
||||
$x = collect();
|
||||
$x->put('type','actions');
|
||||
$x->put('elements',$this->blockactions);
|
||||
|
||||
$this->blocks->push($x);
|
||||
|
||||
// Empty out our blockactions, incase we are converted to json a second time.
|
||||
$this->blockactions = collect();
|
||||
}
|
||||
|
||||
if ($this->actions->count())
|
||||
$this->_data->put('actions',$this->actions);
|
||||
|
||||
if ($this->blocks->count())
|
||||
$this->_data->put('blocks',$this->blocks);
|
||||
*/
|
||||
|
||||
return $this->_data;
|
||||
}
|
||||
/**
|
||||
* Add an attachment to a message
|
||||
*
|
||||
* @param AttachmentAction $action
|
||||
* @return Attachment
|
||||
* @todo To rework
|
||||
*/
|
||||
public function addAction(AttachmentAction $action): self
|
||||
{
|
||||
$this->actions->push($action);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a block to message
|
||||
*
|
||||
* @param BlockKit $block
|
||||
* @return Attachment
|
||||
* @deprecated
|
||||
*/
|
||||
public function addBlock(BlockKit $block): self
|
||||
{
|
||||
$this->blocks->push($block);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a BlockAction to a Block
|
||||
*
|
||||
* @param BlockAction $action
|
||||
* @return $this
|
||||
* @todo To rework
|
||||
*/
|
||||
public function addBlockAction(BlockAction $action): self
|
||||
{
|
||||
$this->blockactions->push($action);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
//* @todo To rework
|
||||
|
||||
public function addField(string $title,string $value,bool $short): self
|
||||
{
|
||||
if (! $this->_data->has('fields'))
|
||||
$this->_data->put('fields',collect());
|
||||
|
||||
$this->_data->get('fields')->push([
|
||||
'title'=>$title,
|
||||
'value'=>$value,
|
||||
'short'=>$short
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* Set where markdown should be parsed by slack
|
||||
*
|
||||
* @param array $array
|
||||
* @return $this
|
||||
* @todo To rework
|
||||
*/
|
||||
public function markdownIn(array $array): self
|
||||
{
|
||||
// @todo Add array check to make sure it has valid items
|
||||
$this->_data->put('mrkdown_in',$array);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the attachment color (on the left of the attachment)
|
||||
*
|
||||
* @param string $string
|
||||
* @return $this
|
||||
* @todo To rework
|
||||
*/
|
||||
public function setCallbackID(string $string): self
|
||||
{
|
||||
$this->_data->put('callback_id',$string);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a blocks to the message attachment
|
||||
*
|
||||
* @param Blocks $blocks
|
||||
* @return self
|
||||
*/
|
||||
public function setBlocks(Blocks $blocks): self
|
||||
{
|
||||
$this->_data->put('blocks',$blocks);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the attachment color (on the left of the attachment)
|
||||
*
|
||||
* @param string $string
|
||||
* @return $this
|
||||
* @todo To rework
|
||||
*/
|
||||
public function setColor(string $string): self
|
||||
{
|
||||
$this->_data->put('color',$string);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the text used in the attachments footer
|
||||
*
|
||||
* @param string $string
|
||||
* @return $this
|
||||
* @todo To rework
|
||||
*/
|
||||
public function setFooter(string $string): self
|
||||
{
|
||||
$this->_data->put('footer',$string);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the pre-text, displayed after the title.
|
||||
*
|
||||
* @param string $string
|
||||
* @return $this
|
||||
* @todo To rework
|
||||
*/
|
||||
public function setPretext(string $string): self
|
||||
{
|
||||
$this->_data->put('pretext',$string);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the text used in the attachment
|
||||
*
|
||||
* @param string $string
|
||||
* @return $this
|
||||
* @todo To rework
|
||||
*/
|
||||
public function setText(string $string): self
|
||||
{
|
||||
$this->_data->put('text',$string);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Title used in the attachment
|
||||
*
|
||||
* @param string $string
|
||||
* @return $this
|
||||
* @todo To rework
|
||||
*/
|
||||
public function setTitle(string $string): self
|
||||
{
|
||||
$this->_data->put('title',$string);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user