|
@@ -2,7 +2,7 @@ Read this when adding or changing a discoverable PHP plugin, permission, or menu
|
|
|
|
|
|
|
|
# Add or Change a Plugin
|
|
# Add or Change a Plugin
|
|
|
|
|
|
|
|
-1. **Use the discovery convention.** Create a directory below `src/` with an initializer named after the directory. Its namespace must follow the path and the class must extend `PluginStrategy`.
|
|
|
|
|
|
|
+1. **Use the discovery convention.** Create a directory below `src/Modules/` with an initializer named after the directory. Its namespace must follow the path and the class must extend `PluginStrategy`.
|
|
|
```php
|
|
```php
|
|
|
namespace Modules\Example;
|
|
namespace Modules\Example;
|
|
|
|
|
|
|
@@ -15,14 +15,15 @@ Read this when adding or changing a discoverable PHP plugin, permission, or menu
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
```
|
|
```
|
|
|
-2. **Keep plugin construction safe at boot.** `ApplicationComposition` instantiates every valid plugin after `System`; configuration, database, and framework globals are then available.
|
|
|
|
|
-3. **Use persistent numeric permission IDs.** Use the existing catalog ID defined by the subsystem, such as permission ID `2` for Inventory Monitor. Permission ID `1` is reserved for administrator authorization.
|
|
|
|
|
-4. **Register menu entries through `AddMenuItem()`.** Use a numeric `permissionId` for protected entries. The method publishes entries only when the restored user has the required permission.
|
|
|
|
|
|
|
+2. **Always define a constructor.** The `PluginStrategy` base constructor throws an exception, so every plugin must declare its own `__construct()`, even if empty (see the example above).
|
|
|
|
|
+3. **Keep plugin construction safe at boot.** `ApplicationComposition` instantiates every valid plugin after `System`; configuration, database, and framework globals are then available.
|
|
|
|
|
+4. **Use persistent numeric permission IDs.** Use the existing catalog ID defined by the subsystem, such as permission ID `2` for Inventory Monitor. Permission ID `1` is reserved for administrator authorization.
|
|
|
|
|
+5. **Register menu entries through `AddMenuItem()`.** Use a numeric `permissionId` for protected entries. The method publishes entries only when the restored user has the required permission.
|
|
|
```php
|
|
```php
|
|
|
$this->AddMenuItem('Inventory Monitor', ['url' => 'inventory', 'permissionId' => 2]);
|
|
$this->AddMenuItem('Inventory Monitor', ['url' => 'inventory', 'permissionId' => 2]);
|
|
|
```
|
|
```
|
|
|
-5. **For API behavior, add routes in `Core\Api\Api`, not in the new plugin.** Follow [add-api-endpoint.md](add-api-endpoint.md).
|
|
|
|
|
-6. **For an interactive page, add a matching React route and ensure the navigation URL resolves under the application base path.** The implemented Inventory Monitor page uses `/inventory`; frontend route guards are not a substitute for API authorization.
|
|
|
|
|
-7. **Update documentation.** Add the subsystem to [module index](../module-index.md); create a domain spec only if it introduces a non-obvious data model and business contracts.
|
|
|
|
|
|
|
+6. **For API behavior, add routes in `Core\Api\Api`, not in the new plugin.** Follow [add-api-endpoint.md](add-api-endpoint.md).
|
|
|
|
|
+7. **For an interactive page, add a matching React route and ensure the navigation URL resolves under the application base path.** The implemented Inventory Monitor page uses `/inventory`; frontend route guards are not a substitute for API authorization.
|
|
|
|
|
+8. **Update documentation.** Add the subsystem to [module index](../module-index.md); create a domain spec only if it introduces a non-obvious data model and business contracts.
|
|
|
|
|
|
|
|
See [backend conventions](../conventions-backend.md) and [file structure](../file-structure.md).
|
|
See [backend conventions](../conventions-backend.md) and [file structure](../file-structure.md).
|