Skip to content

Commit

Permalink
Improvements to AppHome surface and added tapIf()
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremeamia committed Jun 18, 2021
1 parent 5e482db commit 814d090
Show file tree
Hide file tree
Showing 8 changed files with 279 additions and 76 deletions.
13 changes: 12 additions & 1 deletion src/Blocks/Virtual/VirtualBlock.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@

namespace SlackPhp\BlockKit\Blocks\Virtual;

use Iterator;
use IteratorAggregate;
use SlackPhp\BlockKit\Blocks\BlockElement;
use SlackPhp\BlockKit\HydrationData;
use SlackPhp\BlockKit\HydrationException;

/**
* An encapsulation of multiple blocks acting as one virtual element.
*
* @implements IteratorAggregate<BlockElement>
*/
abstract class VirtualBlock extends BlockElement
abstract class VirtualBlock extends BlockElement implements IteratorAggregate
{
/** @var int */
private $index = 1;
Expand Down Expand Up @@ -70,6 +74,13 @@ public function getBlocks(): array
return $this->blocks;
}

public function getIterator(): Iterator
{
foreach ($this->getBlocks() as $block) {
yield $block;
}
}

public function validate(): void
{
foreach ($this->blocks as $block) {
Expand Down
30 changes: 30 additions & 0 deletions src/Element.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ final public function setExtra(string $key, $value): self
}

/**
* Allows you to "tap" into the fluent syntax with a callable.
*
* $element = Elem::new()
* ->foo('bar')
* ->tap(function (Elem $elem) {
* $elem->newSubElem()->fizz('buzz');
* });
*
* @param callable $tap
* @return static
*/
Expand All @@ -75,6 +83,28 @@ final public function tap(callable $tap): self
return $this;
}

/**
* Allows you to "tap" into the fluent syntax with a callable, if the condition is met.
*
* $element = Elem::new()
* ->foo('bar')
* ->tapIf($needsSubElem, function (Elem $elem) {
* $elem->newSubElem()->fizz('buzz');
* });
*
* @param bool $condition
* @param callable $tap
* @return static
*/
final public function tapIf(bool $condition, callable $tap): self
{
if ($condition) {
$tap($this);
}

return $this;
}

/**
* @throws Exception if the block kit item is invalid (e.g., missing data).
*/
Expand Down
4 changes: 2 additions & 2 deletions src/Surfaces/AppHome.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*
* @see https://api.slack.com/surfaces
*/
class AppHome extends Surface
class AppHome extends View
{
// No additions to base Surface functionality.
// No additions to base View and Surface functionality.
}
65 changes: 1 addition & 64 deletions src/Surfaces/Modal.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace SlackPhp\BlockKit\Surfaces;

use SlackPhp\BlockKit\{
Blocks\Input,
Exception,
HydrationData,
Partials\PlainText,
Expand All @@ -18,7 +17,7 @@
*
* @see https://api.slack.com/surfaces
*/
class Modal extends Surface
class Modal extends View
{
private const MAX_LENGTH_TITLE = 24;

Expand All @@ -31,15 +30,6 @@ class Modal extends Surface
/** @var PlainText */
private $close;

/** @var string */
private $privateMetadata;

/** @var string */
private $callbackId;

/** @var string */
private $externalId;

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

Expand Down Expand Up @@ -82,27 +72,6 @@ public function close(string $close): self
return $this->setClose(new PlainText($close));
}

public function externalId(string $externalId): self
{
$this->externalId = $externalId;

return $this;
}

public function callbackId(string $callbackId): self
{
$this->callbackId = $callbackId;

return $this;
}

public function privateMetadata(string $privateMetadata): self
{
$this->privateMetadata = $privateMetadata;

return $this;
}

public function clearOnClose(bool $clearOnClose): self
{
$this->clearOnClose = $clearOnClose;
Expand All @@ -117,14 +86,6 @@ public function notifyOnClose(bool $notifyOnClose): self
return $this;
}

public function newInput(?string $blockId = null): Input
{
$block = new Input($blockId);
$this->add($block);

return $block;
}

public function validate(): void
{
parent::validate();
Expand Down Expand Up @@ -160,18 +121,6 @@ public function toArray(): array
$data['close'] = $this->close->toArray();
}

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

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

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

if (!empty($this->clearOnClose)) {
$data['clear_on_close'] = $this->clearOnClose;
}
Expand Down Expand Up @@ -199,18 +148,6 @@ protected function hydrate(HydrationData $data): void
$this->setClose(PlainText::fromArray($data->useElement('close')));
}

if ($data->has('external_id')) {
$this->externalId($data->useValue('external_id'));
}

if ($data->has('callback_id')) {
$this->callbackId($data->useValue('callback_id'));
}

if ($data->has('private_metadata')) {
$this->privateMetadata($data->useValue('private_metadata'));
}

if ($data->has('clear_on_close')) {
$this->clearOnClose($data->useValue('clear_on_close'));
}
Expand Down
31 changes: 22 additions & 9 deletions src/Surfaces/Surface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,7 @@

namespace SlackPhp\BlockKit\Surfaces;

use SlackPhp\BlockKit\Blocks\{
Actions,
BlockElement,
Context,
Divider,
Header,
Image,
Section,
};
use SlackPhp\BlockKit\Blocks\{Actions, BlockElement, Context, Divider, Header, Image, Input, Section};
use SlackPhp\BlockKit\Blocks\Virtual\{VirtualBlock, TwoColumnTable};
use SlackPhp\BlockKit\{
Exception,
Expand Down Expand Up @@ -49,6 +41,19 @@ public function add(BlockElement $block): self
return $this;
}

/**
* @param iterable|BlockElement[] $blocks
* @return static
*/
public function blocks(iterable $blocks): self
{
foreach ($blocks as $block) {
$this->add($block);
}

return $this;
}

/**
* @return BlockElement[]
*/
Expand Down Expand Up @@ -116,6 +121,14 @@ public function newImage(?string $blockId = null): Image
return $block;
}

public function newInput(?string $blockId = null): Input
{
$block = new Input($blockId);
$this->add($block);

return $block;
}

/**
* @param string|null $blockId
* @return Section
Expand Down
111 changes: 111 additions & 0 deletions src/Surfaces/View.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php

declare(strict_types=1);

namespace SlackPhp\BlockKit\Surfaces;

use SlackPhp\BlockKit\HydrationData;

use function base64_encode;
use function http_build_query;

/**
* View represents the commonalities between the Modal and App Home surfaces.
*
* Modal and App Home surfaces are sometimes collectively called "views" in Slack documentation and APIs.
*/
abstract class View extends Surface
{
/** @var string */
private $callbackId;

/** @var string */
private $externalId;

/** @var string */
private $privateMetadata;

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

return $this;
}

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

return $this;
}

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

return $this;
}

/**
* Encodes the provided associative array of data into a string for `private_metadata`.
*
* Note: Can be decoded using `base64_decode()` and `parse_str()`.
*
* @param array $data
* @return static
*/
public function encodePrivateMetadata(array $data): self
{
return $this->privateMetadata(base64_encode(http_build_query($data)));
}

public function toArray(): array
{
$data = [];

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

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

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

$data += parent::toArray();

return $data;
}

protected function hydrate(HydrationData $data): void
{
if ($data->has('callback_id')) {
$this->callbackId($data->useValue('callback_id'));
}

if ($data->has('external_id')) {
$this->externalId($data->useValue('external_id'));
}

if ($data->has('private_metadata')) {
$this->privateMetadata($data->useValue('private_metadata'));
}

parent::hydrate($data);
}
}
21 changes: 21 additions & 0 deletions tests/ElementTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,27 @@ public function testCanTapIntoElementForChaining()
]);
}

public function testCanConditionallyTapIntoElementForChaining()
{
$callable = function (Element $e) {
$e->setExtra('fizz', 'buzz');
};
$tappedElement = $this->getMockElement()->tapIf(true, $callable);
$untappedElement = $this->getMockElement()->tapIf(false, $callable);

$this->assertInstanceOf(Element::class, $tappedElement);
$this->assertInstanceOf(Element::class, $untappedElement);
$this->assertJsonData($tappedElement, [
'type' => 'mock',
'text' => 'foo',
'fizz' => 'buzz',
]);
$this->assertJsonData($untappedElement, [
'type' => 'mock',
'text' => 'foo',
]);
}

private function getMockElement(bool $valid = true): Element
{
return new class ($valid) extends Element {
Expand Down
Loading

0 comments on commit 814d090

Please sign in to comment.