Events, extension points and plugins
This page is for engineers who need to change what Exponential does without changing its code. Nearly every part of the kernel is pluggable through a setting that names a class; the in-process event bus adds hooks at fixed points of a request. The full list is Extension points at a glance and the registered points are documented in RAD extension points.
Contents
- The order of preference
- The event bus: ezpEvent
- Handlers named in settings
- Replacing a view or a module
- The last resort: a kernel override
- Rules for listeners and plugins
The order of preference
- A setting. Many behaviors are switches or lists already; check the shipped
settings/*.inifirst. - A template override for presentation (The template engine and the design chain).
- A registered extension point: a datatype, workflow event, operator, fetch function, handler or event listener.
- A replaced view or module, through
[RunnableSettings]or an extension module override. - A kernel class override, only when nothing above fits.
The event bus: ezpEvent
ezpEvent::getInstance() (kernel/private/classes/ezpevent.php) offers two calls:
| Call | Use |
|---|---|
notify( $name, $params ) | tell listeners that something happened |
filter( $name, $value ) | let listeners change a value and return it |
Global listeners are configured in site.ini [Event] Listeners[]=<event>@<callback>. Events the kernel emits include:
| Event | When |
|---|---|
request/preinput, request/input | at the start of the dispatch loop |
response/preoutput, response/output | output filters, before the response is sent |
content/cache, content/cache/all, content/class/cache | content view caches are cleared |
image/removeAliases | image variations are removed |
content/edit/access, content/download/access, collaboration/item/access | access filters that can refuse |
runnable/<kind>/before, runnable/<kind>/after | around class-based views, commands and cronjob parts |
The file marks ezpEvent as private API that may change; extensions rely on it nonetheless, so changes to it are
treated as compatibility-relevant (Events and filters).
Handlers named in settings
| Extension point | Setting | Guide |
|---|---|---|
| Datatypes | content.ini [DataTypeSettings] | Custom datatypes |
| Workflow event types | workflow.ini [EventSettings] | Writing a workflow event type |
| Template operators and functions | site.ini [TemplateSettings] ExtensionAutoloadPath[] | Template operators |
| Fetch functions | the module's function_definition.php | Writing a fetch function |
| Cronjob parts | cronjob.ini | Writing a cronjob part |
| Notification handlers | notification.ini | Notifications and mail |
| Content limitation handlers | see the feature page | Content limitation handlers |
| Cluster file handler | file.ini [ClusteringSettings] FileHandler | Scaling and clustering |
| Any handler named by a setting | the pattern | Handlers named by settings |
Replacing a view or a module
- A class-based view can be replaced through
site.ini [RunnableSettings] Implementation[]. - A whole kernel module can be replaced by an extension's module of the same name (Extension module override).
The last resort: a kernel override
A kernel class override replaces a kernel class with a copy in an extension. Every update of the kernel can then break your copy silently, so it needs a test and a note in your upgrade checklist (Kernel overrides, the last resort).
Rules for listeners and plugins
- Registrations must be idempotent. Under Velocity a listener attached once per request in a long-lived worker accumulates (Concurrency, statics and long-lived processes).
- Listener names should be
Class::methodstrings so they can be configured. - A new class named in a shipped setting should be guarded with
class_exists()where the kernel loads it. - Access decisions go through the access filters, never through a check of a user id.
Related pages
- Kernel, lib and extensions: the layering
- Extending without forking
- Design pattern catalogue
- Free documentation: this page is free to copy, translate and improve under the GNU FDL 1.3.
Become an Exponential Partner
Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster.