Skip to content

Commit

Permalink
Adds support for "filter" to conversation menu/multi-menu
Browse files Browse the repository at this point in the history
Also improves Element::fromJson with exception throwing
  • Loading branch information
jeremeamia committed Dec 3, 2020
1 parent 6e1f7ee commit eed9f7f
Show file tree
Hide file tree
Showing 9 changed files with 336 additions and 4 deletions.
9 changes: 8 additions & 1 deletion src/Element.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Jeremeamia\Slack\BlockKit;

use JsonSerializable;
use Throwable;

abstract class Element implements JsonSerializable
{
Expand Down Expand Up @@ -120,7 +121,13 @@ public function jsonSerialize()
*/
final public static function fromJson(string $json)
{
return static::fromArray(json_decode($json, true));
try {
$data = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
} catch (Throwable $err) {
throw new HydrationException('JSON error (%s) hydrating %s', [$err->getMessage(), static::class], $err);
}

return static::fromArray($data);
}

/**
Expand Down
43 changes: 42 additions & 1 deletion src/Inputs/SelectMenus/ConversationSelectMenu.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Jeremeamia\Slack\BlockKit\Inputs\SelectMenus;

use Jeremeamia\Slack\BlockKit\HydrationData;
use Jeremeamia\Slack\BlockKit\Partials\Filter;

class ConversationSelectMenu extends SelectMenu
{
Expand All @@ -17,6 +18,9 @@ class ConversationSelectMenu extends SelectMenu
/** @var bool */
private $defaultToCurrentConversation;

/** @var Filter */
private $filter;

/**
* @param string $initialConversation
* @return static
Expand Down Expand Up @@ -50,7 +54,36 @@ public function defaultToCurrentConversation(bool $enabled): self
return $this;
}

// @TODO: filter - https://api.slack.com/reference/block-kit/block-elements#conversation_select
/**
* @param Filter $filter
* @return static
*/
public function setFilter(Filter $filter): self
{
$this->filter = $filter->setParent($this);

return $this;
}

/**
* @return Filter
*/
public function newFilter(): Filter
{
$filter = Filter::new();
$this->setFilter($filter);

return $filter;
}

public function validate(): void
{
parent::validate();

if (!empty($this->filter)) {
$this->filter->validate();
}
}

/**
* @return array
Expand All @@ -71,6 +104,10 @@ public function toArray(): array
$data['default_to_current_conversation'] = $this->defaultToCurrentConversation;
}

if (!empty($this->filter)) {
$data['filter'] = $this->filter->toArray();
}

return $data;
}

Expand All @@ -88,6 +125,10 @@ protected function hydrate(HydrationData $data): void
$this->defaultToCurrentConversation($data->useValue('default_to_current_conversation'));
}

if ($data->has('filter')) {
$this->setFilter(Filter::fromArray($data->useElement('filter')));
}

parent::hydrate($data);
}
}
43 changes: 42 additions & 1 deletion src/Inputs/SelectMenus/MultiConversationSelectMenu.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Jeremeamia\Slack\BlockKit\Inputs\SelectMenus;

use Jeremeamia\Slack\BlockKit\HydrationData;
use Jeremeamia\Slack\BlockKit\Partials\Filter;

class MultiConversationSelectMenu extends MultiSelectMenu
{
Expand All @@ -14,6 +15,9 @@ class MultiConversationSelectMenu extends MultiSelectMenu
/** @var bool */
private $defaultToCurrentConversation;

/** @var Filter */
private $filter;

/**
* @param string[] $initialConversations
* @return static
Expand All @@ -36,7 +40,36 @@ public function defaultToCurrentConversation(bool $enabled): self
return $this;
}

// @TODO: filter - https://api.slack.com/reference/block-kit/block-elements#conversation_select
/**
* @param Filter $filter
* @return static
*/
public function setFilter(Filter $filter): self
{
$this->filter = $filter->setParent($this);

return $this;
}

/**
* @return Filter
*/
public function newFilter(): Filter
{
$filter = Filter::new();
$this->setFilter($filter);

return $filter;
}

public function validate(): void
{
parent::validate();

if (!empty($this->filter)) {
$this->filter->validate();
}
}

/**
* @return array
Expand All @@ -53,6 +86,10 @@ public function toArray(): array
$data['default_to_current_conversation'] = $this->defaultToCurrentConversation;
}

if (!empty($this->filter)) {
$data['filter'] = $this->filter->toArray();
}

return $data;
}

Expand All @@ -66,6 +103,10 @@ protected function hydrate(HydrationData $data): void
$this->defaultToCurrentConversation($data->useValue('default_to_current_conversation'));
}

if ($data->has('filter')) {
$this->setFilter(Filter::fromArray($data->useElement('filter')));
}

parent::hydrate($data);
}
}
146 changes: 146 additions & 0 deletions src/Partials/Filter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
<?php

declare(strict_types=1);

namespace Jeremeamia\Slack\BlockKit\Partials;

use Jeremeamia\Slack\BlockKit\{Element, Exception, HydrationData};

class Filter extends Element
{
private const CONVERSATION_TYPE_IM = 'im';
private const CONVERSATION_TYPE_MPIM = 'mpim';
private const CONVERSATION_TYPE_PRIVATE = 'private';
private const CONVERSATION_TYPE_PUBLIC = 'public';

/** @var string[]|array */
private $include = [];

/** @var bool */
private $excludeExternalSharedChannels;

/** @var bool */
private $excludeBotUsers;

/**
* @param string $conversationType
* @return static
*/
public function includeType(string $conversationType): self
{
$this->include[] = $conversationType;

return $this;
}

/**
* @param string[] $conversationTypes
* @return static
*/
public function includeTypes(array $conversationTypes): self
{
$this->include = $conversationTypes;

return $this;
}

/**
* @return static
*/
public function includeIm(): self
{
return $this->includeType(self::CONVERSATION_TYPE_IM);
}

/**
* @return static
*/
public function includeMpim(): self
{
return $this->includeType(self::CONVERSATION_TYPE_MPIM);
}

/**
* @return static
*/
public function includePrivate(): self
{
return $this->includeType(self::CONVERSATION_TYPE_PRIVATE);
}

/**
* @return static
*/
public function includePublic(): self
{
return $this->includeType(self::CONVERSATION_TYPE_PUBLIC);
}

/**
* @param bool $excludeBotUsers
* @return static
*/
public function excludeBotUsers(bool $excludeBotUsers): self
{
$this->excludeBotUsers = $excludeBotUsers;

return $this;
}

/**
* @param bool $excludeExternalSharedChannels
* @return static
*/
public function excludeExternalSharedChannels(bool $excludeExternalSharedChannels): self
{
$this->excludeExternalSharedChannels = $excludeExternalSharedChannels;

return $this;
}

public function validate(): void
{
if (empty($this->include) && !isset($this->excludeExternalSharedChannels) && !isset($this->excludeBotUsers)) {
throw new Exception('Filter must have at least one property set');
}
}

/**
* @return array
*/
public function toArray(): array
{
$data = parent::toArray();

if (!empty($this->include)) {
$data['include'] = $this->include;
}

if (isset($this->excludeExternalSharedChannels)) {
$data['exclude_external_shared_channels'] = $this->excludeExternalSharedChannels;
}

if (isset($this->excludeBotUsers)) {
$data['exclude_bot_users'] = $this->excludeBotUsers;
}

return $data;
}

protected function hydrate(HydrationData $data): void
{
if ($data->has('include')) {
$this->includeTypes($data->useArray('include'));
}

if ($data->has('exclude_external_shared_channels')) {
$this->excludeExternalSharedChannels($data->useValue('exclude_external_shared_channels'));
}

if ($data->has('exclude_bot_users')) {
$this->excludeBotUsers($data->useValue('exclude_bot_users'));
}

parent::hydrate($data);
}
}
3 changes: 3 additions & 0 deletions src/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ abstract class Type
// Partials
public const CONFIRM = 'confirm';
public const FIELDS = 'fields';
public const FILTER = 'filter';
public const MRKDWNTEXT = 'mrkdwn';
public const OPTION = 'option';
public const OPTION_GROUP = 'option_group';
Expand Down Expand Up @@ -161,6 +162,7 @@ abstract class Type
self::ATTACHMENT,
self::CONFIRM,
self::FIELDS,
self::FILTER,
self::MESSAGE,
self::OPTION,
self::OPTION_GROUP,
Expand Down Expand Up @@ -212,6 +214,7 @@ abstract class Type
// Partials
Partials\Confirm::class => self::CONFIRM,
Partials\Fields::class => self::FIELDS,
Partials\Filter::class => self::FILTER,
Partials\MrkdwnText::class => self::MRKDWNTEXT,
Partials\Option::class => self::OPTION,
Partials\OptionGroup::class => self::OPTION_GROUP,
Expand Down
20 changes: 19 additions & 1 deletion tests/ElementTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
namespace Jeremeamia\Slack\BlockKit\Tests;

use Jeremeamia\Slack\BlockKit\Blocks\Section;
use Jeremeamia\Slack\BlockKit\{Element, Exception, Type};
use Jeremeamia\Slack\BlockKit\{
Element,
Exception,
HydrationException,
Type,
};
use Jeremeamia\Slack\BlockKit\Surfaces\Modal;

/**
Expand Down Expand Up @@ -153,4 +158,17 @@ public function testHydration()
$afterJson = $modal->toJson();
$this->assertJsonStringEqualsJsonString($beforeJson, $afterJson);
}

public function testFromJsonThrowsExceptionOnBadJson()
{
$this->expectException(HydrationException::class);
Modal::fromJson('{"foo":"Bar",}');
}

public function testCanExportToJsonWithPrettyPrint()
{
$element = $this->getMockElement();
$json = $element->toJson(true);
$this->assertStringContainsString("\n", $json);
}
}
Loading

0 comments on commit eed9f7f

Please sign in to comment.