v0.2.0 (7/N): make:bridge:event maker
Implements PLAN.md §8's third makers-table row. Single-command path
from a PHP domain event to a QML signal-handler:
- src/Event/<Name>Event.php — readonly value object stub
- src/EventSubscriber/<Name>Subscriber.php — listens to the event,
republishes via PublisherInterface on app://event/<kebab-name>
with op:"event"
- {qml_path}/<Name>EventHandler.qml — MercureClient bound to the
topic, re-emits the envelope's data as a typed signal
Stub uses an `array $payload` field so the user can substitute typed
properties for whatever shape they need. Subscriber example uses the
PublisherInterface contract from chunk 1; QML stub uses MercureClient
+ BackendConnection both already shipping.
Wired into services.yaml's when@dev block (autoconfigure picks up
maker.command tag, same pattern as existing BridgeResourceMaker /
BridgeWindowMaker). Three new snapshot baselines plus a snapshot
runner extension exercising the new maker against the same Todo /
TodoCompleted naming the existing baselines use.
End-to-end verified locally: maker output matches baselines, dev
container compiles, listing make:bridge:* shows the new command.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
21
framework/php/tests/snapshot/TodoCompletedEvent.php
Normal file
21
framework/php/tests/snapshot/TodoCompletedEvent.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Event;
|
||||
|
||||
/**
|
||||
* Domain event published on `app://event/todo-completed` by
|
||||
* TodoCompletedSubscriber.
|
||||
*
|
||||
* Auto-generated stub — replace the `payload` field with typed
|
||||
* properties matching the event you actually fire.
|
||||
*/
|
||||
final readonly class TodoCompletedEvent
|
||||
{
|
||||
public function __construct(
|
||||
/** @var array<string, mixed> */
|
||||
public array $payload = [],
|
||||
) {
|
||||
}
|
||||
}
|
||||
31
framework/php/tests/snapshot/TodoCompletedEventHandler.qml
Normal file
31
framework/php/tests/snapshot/TodoCompletedEventHandler.qml
Normal file
@@ -0,0 +1,31 @@
|
||||
// Auto-generated by `bin/console make:bridge:event TodoCompleted`.
|
||||
// Listens for `app://event/todo-completed` envelopes published by
|
||||
// TodoCompletedSubscriber and re-emits them as a typed QML signal.
|
||||
//
|
||||
// Drop into a parent component and connect:
|
||||
//
|
||||
// TodoCompletedEventHandler {
|
||||
// onTodoCompleted: function(payload) { console.log("hi", payload) }
|
||||
// }
|
||||
|
||||
import QtQuick
|
||||
import PhpQml.Bridge
|
||||
|
||||
Item {
|
||||
id: handler
|
||||
|
||||
/** Emitted when the bridge publishes app://event/todo-completed. */
|
||||
signal todoCompleted(var payload)
|
||||
|
||||
MercureClient {
|
||||
baseUrl: BackendConnection.url
|
||||
token: BackendConnection.token
|
||||
topics: ["app://event/todo-completed"]
|
||||
|
||||
onUpdate: function(topic, envelope) {
|
||||
if (topic === "app://event/todo-completed") {
|
||||
handler.todoCompleted(envelope.data)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
framework/php/tests/snapshot/TodoCompletedSubscriber.php
Normal file
37
framework/php/tests/snapshot/TodoCompletedSubscriber.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\EventSubscriber;
|
||||
|
||||
use App\Event\TodoCompletedEvent;
|
||||
use PhpQml\Bridge\PublisherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Republishes TodoCompletedEvent on `app://event/todo-completed`.
|
||||
* Auto-generated alongside the event class — wire `payload` to whatever
|
||||
* shape you want QML clients to receive in the envelope's `data` field.
|
||||
*/
|
||||
final readonly class TodoCompletedSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public function __construct(
|
||||
private PublisherInterface $publisher,
|
||||
) {
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
TodoCompletedEvent::class => 'onTodoCompleted',
|
||||
];
|
||||
}
|
||||
|
||||
public function onTodoCompleted(TodoCompletedEvent $event): void
|
||||
{
|
||||
$this->publisher->publish('app://event/todo-completed', [
|
||||
'op' => 'event',
|
||||
'data' => $event->payload,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -50,13 +50,17 @@ clear_outputs
|
||||
( cd "$APP/symfony" \
|
||||
&& bin/console make:bridge:resource Todo --no-interaction >/dev/null \
|
||||
&& bin/console make:bridge:command MarkAllDone --no-interaction >/dev/null \
|
||||
&& bin/console make:bridge:window Todo --no-interaction >/dev/null )
|
||||
&& bin/console make:bridge:window Todo --no-interaction >/dev/null \
|
||||
&& bin/console make:bridge:event TodoCompleted --no-interaction >/dev/null )
|
||||
|
||||
check "$APP/symfony/src/Entity/Todo.php" "$SCRIPT_DIR/Todo.php"
|
||||
check "$APP/symfony/src/Controller/TodoController.php" "$SCRIPT_DIR/TodoController.php"
|
||||
check "$APP/qml/TodoList.qml" "$SCRIPT_DIR/TodoList.qml"
|
||||
check "$APP/symfony/src/Controller/MarkAllDoneController.php" "$SCRIPT_DIR/MarkAllDoneController.php"
|
||||
check "$APP/qml/TodoWindow.qml" "$SCRIPT_DIR/TodoWindow.qml"
|
||||
check "$APP/symfony/src/Entity/Todo.php" "$SCRIPT_DIR/Todo.php"
|
||||
check "$APP/symfony/src/Controller/TodoController.php" "$SCRIPT_DIR/TodoController.php"
|
||||
check "$APP/qml/TodoList.qml" "$SCRIPT_DIR/TodoList.qml"
|
||||
check "$APP/symfony/src/Controller/MarkAllDoneController.php" "$SCRIPT_DIR/MarkAllDoneController.php"
|
||||
check "$APP/qml/TodoWindow.qml" "$SCRIPT_DIR/TodoWindow.qml"
|
||||
check "$APP/symfony/src/Event/TodoCompletedEvent.php" "$SCRIPT_DIR/TodoCompletedEvent.php"
|
||||
check "$APP/symfony/src/EventSubscriber/TodoCompletedSubscriber.php" "$SCRIPT_DIR/TodoCompletedSubscriber.php"
|
||||
check "$APP/qml/TodoCompletedEventHandler.qml" "$SCRIPT_DIR/TodoCompletedEventHandler.qml"
|
||||
|
||||
# ── Mode 2: --with-dto (re-runs make:bridge:resource only) ────────────
|
||||
# The entity + QML output is byte-identical between modes; only the
|
||||
|
||||
Reference in New Issue
Block a user