Skip to content

Commit

Permalink
Merge pull request #144 from hotwired-laravel/tm/custom-action-broadc…
Browse files Browse the repository at this point in the history
…asts

Allow custom action broadcasts
  • Loading branch information
tonysm authored Mar 27, 2024
2 parents 4b1180e + 4e48a72 commit c824787
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 14 deletions.
7 changes: 6 additions & 1 deletion src/Broadcasting/PendingBroadcast.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,12 @@ public function toOthers(bool $toOthers = true): self

public function partial(?string $partial, array $data = []): self
{
return $this->rendering(new Rendering($partial, $data));
return $this->view($partial, $data);
}

public function view(?string $view, array $data = []): self
{
return $this->rendering(new Rendering($view, $data));
}

public function content($content)
Expand Down
2 changes: 1 addition & 1 deletion src/Commands/TurboInstallCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ private function updateImportmapsDependencies(): void
private function jsDependencies(): array
{
return [
'@hotwired/turbo' => '^8.0.3',
'@hotwired/turbo' => '^8.0.4',
'laravel-echo' => '^1.15.0',
'pusher-js' => '^8.0.1',
];
Expand Down
26 changes: 14 additions & 12 deletions src/Models/Broadcasts.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public function broadcastInsert(): PendingBroadcast
return $this->broadcastActionTo(
$this->broadcastDefaultStreamables(inserting: true),
$action,
Rendering::forModel($this),
rendering: Rendering::forModel($this),
);
}

Expand Down Expand Up @@ -126,58 +126,60 @@ public function broadcastRefresh(): PendingBroadcast

public function broadcastAppendTo($streamable): PendingBroadcast
{
return $this->broadcastActionTo($streamable, 'append', Rendering::forModel($this));
return $this->broadcastActionTo($streamable, 'append', rendering: Rendering::forModel($this));
}

public function broadcastPrependTo($streamable): PendingBroadcast
{
return $this->broadcastActionTo($streamable, 'prepend', Rendering::forModel($this));
return $this->broadcastActionTo($streamable, 'prepend', rendering: Rendering::forModel($this));
}

public function broadcastBeforeTo($streamable, string $target): PendingBroadcast
{
return $this->broadcastActionTo($streamable, 'before', Rendering::forModel($this), $target);
return $this->broadcastActionTo($streamable, 'before', $target, rendering: Rendering::forModel($this));
}

public function broadcastAfterTo($streamable, string $target): PendingBroadcast
{
return $this->broadcastActionTo($streamable, 'after', Rendering::forModel($this), $target);
return $this->broadcastActionTo($streamable, 'after', $target, rendering: Rendering::forModel($this));
}

public function broadcastReplaceTo($streamable): PendingBroadcast
{
return $this->broadcastActionTo($streamable, 'replace', Rendering::forModel($this));
return $this->broadcastActionTo($streamable, 'replace', rendering: Rendering::forModel($this));
}

public function broadcastUpdateTo($streamable): PendingBroadcast
{
return $this->broadcastActionTo($streamable, 'update', Rendering::forModel($this));
return $this->broadcastActionTo($streamable, 'update', rendering: Rendering::forModel($this));
}

public function broadcastRemoveTo($streamable): PendingBroadcast
{
return $this->broadcastActionTo($streamable, 'remove', Rendering::empty());
return $this->broadcastActionTo($streamable, 'remove', rendering: Rendering::empty());
}

public function broadcastRefreshTo($streamable): PendingBroadcast
{
return TurboStream::broadcastRefresh($this->toChannels(Collection::wrap($streamable)))
->cancelIf(fn () => static::isIgnoringTurboStreamBroadcasts());
return TurboStream::broadcastRefresh(
$this->toChannels(Collection::wrap($streamable))
)->cancelIf(fn () => static::isIgnoringTurboStreamBroadcasts());
}

public function asTurboStreamBroadcastingChannel()
{
return $this->toChannels(Collection::wrap($this->broadcastDefaultStreamables($this->wasRecentlyCreated)));
}

protected function broadcastActionTo($streamables, string $action, Rendering $rendering, ?string $target = null): PendingBroadcast
public function broadcastActionTo($streamables, string $action, ?string $target = null, array $attributes = [], ?Rendering $rendering = null): PendingBroadcast
{
return TurboStream::broadcastAction(
action: $action,
target: $target ?: $this->broadcastDefaultTarget($action),
targets: null,
channel: $this->toChannels(Collection::wrap($streamables)),
content: $rendering,
attributes: $attributes,
content: $rendering ?? Rendering::empty(),
)->cancelIf(static::isIgnoringTurboStreamBroadcasts());
}

Expand Down
49 changes: 49 additions & 0 deletions tests/Models/BroadcastsModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -718,4 +718,53 @@ public function can_disable_auto_broadcasts()
return true;
}, times: 1);
}

/** @test */
public function broadcasts_with_extra_attributes_to_turbo_stream()
{
TurboStream::fake();

/** @var Board $board */
$board = Board::withoutTurboStreamBroadcasts(fn () => Board::create(['name' => 'Hello World']));

$board->broadcastActionTo(
$channel = 'messages',
$action = 'test',
attributes: $attributes = ['data-foo' => 'bar'],
);

TurboStream::assertBroadcasted(function (PendingBroadcast $turboStream) use ($channel, $action, $attributes) {
$this->assertEquals("private-{$channel}", $turboStream->channels[0]->name);
$this->assertEquals($action, $turboStream->action);
$this->assertEquals($attributes, $turboStream->attributes);

return true;
});
}

/** @test */
public function broadcasts_with_extra_attributes_to_turbo_stream_with_rendering()
{
TurboStream::fake();

/** @var Board $board */
$board = Board::withoutTurboStreamBroadcasts(fn () => Board::create(['name' => 'Hello World']));

$board->broadcastActionTo(
$channel = 'messages',
$action = 'test',
attributes: $attributes = ['data-foo' => 'bar'],
)->view('boards.partials.board', [
'board' => $board,
]);

TurboStream::assertBroadcasted(function (PendingBroadcast $turboStream) use ($channel, $action, $attributes) {
$this->assertEquals("private-{$channel}", $turboStream->channels[0]->name);
$this->assertEquals($action, $turboStream->action);
$this->assertEquals($attributes, $turboStream->attributes);
$this->assertStringContainsString('Hello World', $turboStream->render());

return true;
});
}
}
1 change: 1 addition & 0 deletions workbench/resources/views/boards/partials/board.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div id="@domid($board)">{{ $board->name }}</div>

0 comments on commit c824787

Please sign in to comment.