|
| 1 | +--- |
| 2 | +name: plugin-hook |
| 3 | +description: Adds a new event hook to the MyAdmin NoVNC plugin system. Registers the hook in `getHooks()` and implements the corresponding static handler method on `Plugin` in `src/Plugin.php`. Use when user says 'add hook', 'register event', 'handle event', or needs to respond to a new MyAdmin event. Do NOT use for modifying `getMenu()` or `getRequirements()` — those have dedicated patterns. |
| 4 | +--- |
| 5 | +# plugin-hook |
| 6 | + |
| 7 | +## Critical |
| 8 | + |
| 9 | +- All handler methods MUST be `public static` — never instance methods. |
| 10 | +- The `$event` parameter MUST be typed as `\Symfony\Component\EventDispatcher\GenericEvent`. |
| 11 | +- Use `__CLASS__` (not `self::class`) as the callable class reference in `getHooks()` — matches existing code. |
| 12 | +- Use tabs for indentation throughout `src/Plugin.php`. |
| 13 | +- Never remove or alter existing hooks in `getHooks()` — only add new entries. |
| 14 | + |
| 15 | +## Instructions |
| 16 | + |
| 17 | +1. **Identify the event name and handler method name.** |
| 18 | + Confirm the MyAdmin event string (e.g., `'system.settings'`, `'ui.menu'`) and choose a `camelCase` method name for the handler (e.g., `handleVncConnect`). Verify no method of that name already exists in `src/Plugin.php` before proceeding. |
| 19 | + |
| 20 | +2. **Register the hook in `getHooks()`.** |
| 21 | + Open `src/Plugin.php` and add an entry to the returned array: |
| 22 | + ```php |
| 23 | + public static function getHooks() |
| 24 | + { |
| 25 | + return [ |
| 26 | + 'your.event.name' => [__CLASS__, 'yourHandlerMethod'], |
| 27 | + ]; |
| 28 | + } |
| 29 | + ``` |
| 30 | + If active hooks are currently commented out (e.g., `//`), add your entry as a live line — do not uncomment unrelated hooks. |
| 31 | + |
| 32 | +3. **Implement the handler method.** |
| 33 | + Add the static method immediately after `getSettings()`, following this exact signature and doc-block pattern from the existing handlers: |
| 34 | + ```php |
| 35 | + /** |
| 36 | + * @param \Symfony\Component\EventDispatcher\GenericEvent $event |
| 37 | + */ |
| 38 | + public static function yourHandlerMethod(GenericEvent $event) |
| 39 | + { |
| 40 | + $subject = $event->getSubject(); |
| 41 | + // handler logic here |
| 42 | + } |
| 43 | + ``` |
| 44 | + Use `$event->getSubject()` to get the payload object. No return value is needed (handlers are void). |
| 45 | + |
| 46 | +4. **Add a PHPUnit test for the new hook.** |
| 47 | + Open `tests/PluginTest.php` and add two tests: |
| 48 | + - Assert `getHooks()` contains the new event key pointing to `[Plugin::class, 'yourHandlerMethod']`. |
| 49 | + - Assert the handler method is public and static via `ReflectionClass`. |
| 50 | + Follow the doc-block style already in `PluginTest.php`. |
| 51 | + |
| 52 | +5. **Run tests to verify.** |
| 53 | + ```bash |
| 54 | + vendor/bin/phpunit |
| 55 | + ``` |
| 56 | + All existing tests must still pass. The new tests must pass too. |
| 57 | + |
| 58 | +## Examples |
| 59 | + |
| 60 | +**User says:** "Add a hook for the `system.novnc_connect` event that logs the connection subject." |
| 61 | + |
| 62 | +**Actions taken:** |
| 63 | + |
| 64 | +`getHooks()` updated: |
| 65 | +```php |
| 66 | +public static function getHooks() |
| 67 | +{ |
| 68 | + return [ |
| 69 | + 'system.novnc_connect' => [__CLASS__, 'handleNovncConnect'], |
| 70 | + ]; |
| 71 | +} |
| 72 | +``` |
| 73 | + |
| 74 | +New method added after `getSettings()`: |
| 75 | +```php |
| 76 | +/** |
| 77 | + * @param \Symfony\Component\EventDispatcher\GenericEvent $event |
| 78 | + */ |
| 79 | +public static function handleNovncConnect(GenericEvent $event) |
| 80 | +{ |
| 81 | + $subject = $event->getSubject(); |
| 82 | + // connection handling logic |
| 83 | +} |
| 84 | +``` |
| 85 | + |
| 86 | +Test added to `tests/PluginTest.php`: |
| 87 | +```php |
| 88 | +public function testGetHooksContainsNovncConnect(): void |
| 89 | +{ |
| 90 | + $hooks = Plugin::getHooks(); |
| 91 | + $this->assertArrayHasKey('system.novnc_connect', $hooks); |
| 92 | + $this->assertSame([Plugin::class, 'handleNovncConnect'], $hooks['system.novnc_connect']); |
| 93 | +} |
| 94 | + |
| 95 | +public function testHandleNovncConnectIsStatic(): void |
| 96 | +{ |
| 97 | + $reflection = new ReflectionClass(Plugin::class); |
| 98 | + $method = $reflection->getMethod('handleNovncConnect'); |
| 99 | + $this->assertTrue($method->isStatic()); |
| 100 | + $this->assertTrue($method->isPublic()); |
| 101 | +} |
| 102 | +``` |
| 103 | + |
| 104 | +**Result:** `vendor/bin/phpunit` passes with all tests green. |
| 105 | + |
| 106 | +## Common Issues |
| 107 | + |
| 108 | +- **`Call to undefined method` at runtime:** The method name in `getHooks()` must exactly match the implemented method name — PHP is case-sensitive for string-based callables. |
| 109 | +- **`testPublicMethodCount` fails (expected 5, got 6):** The existing test in `PluginTest.php:410` asserts exactly 5 own public methods. Update that assertion to reflect the new count after adding your handler. |
| 110 | +- **`GenericEvent` not found / class not imported:** Confirm `use Symfony\Component\EventDispatcher\GenericEvent;` is at the top of `src/Plugin.php` — it is already present in the existing file. |
| 111 | +- **Indentation inconsistency causes CS failures:** `src/Plugin.php` uses tabs. If your editor inserts spaces, the `.scrutinizer.yml` coding-style check will fail. Run `make php-cs-fixer` (from the parent MyAdmin project) or manually verify tabs are used. |
| 112 | +- **Hook never fires:** Confirm the event string matches exactly what the MyAdmin framework dispatches — check `include/config/hooks.json` in the parent project for the authoritative event name list. |
0 commit comments