Design pattern catalogue
This catalogue is for developers who extend Exponential or change its kernel. It lists every abstraction the code uses, where it is, and how a new implementation is plugged in, so that new code follows the patterns that are already there instead of inventing new ones. It is generated from the source code, so it is complete and current for the code it was built from; the rules that recognize each pattern are heuristic and are explained below.
Runnable examples of most of these extension points: Examples and the cookbook.
The rules the code follows: Standards and Kernel architecture.
In numbers
| Instances (all categories) | 6206 |
| Classes, interfaces, traits and enums | 3516 (3419 classes, 96 interfaces, 1 trait) |
| ... with at least one pattern | 2871 |
| Module views | 532 |
| Policy functions | 260 |
| Fetch functions | 316 |
| Template operators | 255 |
| Cronjob parts | 49 |
| Event hooks | 99 |
| INI plugin points | 842 |
| Source files read | 4512 PHP, 577 INI |
| Areas | 155 |
The patterns
| Pattern | Group | Instances | Recognized by |
|---|---|---|---|
| Active Record (eZPersistentObject) | Data access | 234 | Extends eZPersistentObject, directly or through a parent class. |
| Datatype (Strategy for content fields) | Plugins | 54 | Extends eZDataType, directly or through a parent class. |
| Workflow event type (Command, plugin) | Plugins | 15 | Extends eZWorkflowEventType. |
| Template operator (Interpreter plugin) | Plugins | 338 | Registered in an eztemplateautoload.php ($eZTemplateOperatorArray[]), or has operatorList() and modify(). |
| Template function (Interpreter plugin) | Plugins | 45 | Registered in an eztemplateautoload.php ($eZTemplateFunctionArray[]), or has functionList() and process(). |
| Fetch function (Query Object, Facade) | Plugins | 354 | An entry of a module's function_definition.php, or a class named *FunctionCollection. |
| Module view (Page Controller) | Request handling | 993 | An entry of $ViewList in a module.php, or a class that extends ModuleView or Page (the runnable form of a view). |
| Policy function (access control) | Request handling | 260 | An entry of $FunctionList in a module.php. |
| Front Controller | Request handling | 10 | The kernel classes ezpKernel, ezpKernelWeb, ezpKernelTreeMenu, ezpKernelRest, eZModule and their kind. |
| Command (console, scripts, cronjobs) | Request handling | 247 | Extends Command, CronjobPart or Runnable (the runnable console commands and cronjob parts), or a cronjobs/*.php file. |
| Singleton / instance() | Creation | 77 | Has a static instance() or getInstance() method. |
| Factory and static factory methods | Creation | 443 | Class name ends in Factory, or has static create(), from(), factory(), make*() methods, or creates new self/new static in a static method. |
| Builder | Creation | 10 | Class name contains Builder or Generator. |
| Registry | Structure | 39 | Class name contains Registry, or has static register*() methods. |
| Strategy / handler | Behavior | 382 | Class name ends in Handler, Backend, Driver, Transport, Engine or Strategy, or implements an interface whose name does. |
| Template Method / abstract base class | Behavior | 69 | An abstract class with both abstract and concrete methods. |
| Interface (contract) | Structure | 96 | Every interface. |
| Observer / listener / event | Behavior | 10 | Class name contains Listener, Observer or Subscriber, or has attach()/notify()/addListener() methods; every ezpEvent notify()/filter() call (see the hooks page). |
| Event hook (ezpEvent) | Behavior | 99 | A call of ezpEvent::getInstance()-›notify( 'EVENT' ) or -›filter( 'EVENT' ). |
| Adapter / bridge / wrapper | Structure | 6 | Class name contains Adapter, Bridge, Wrapper or Proxy. |
| Facade / service | Structure | 40 | Class name ends in Facade, Service, Manager, API or Api. |
| Decorator / filter | Structure | 64 | Class name contains Decorator or Filter. |
| Chain of Responsibility | Behavior | 19 | Class name contains LoginHandler, Chain, Pipeline, Middleware, Router or Matcher. |
| Iterator | Behavior | 16 | Implements Iterator, IteratorAggregate or ArrayAccess. |
| Value object / struct | Structure | 106 | Class name ends in Struct, Value, Result, Item, Info or Definition and the class has few methods, or extends ezcBaseStruct. |
| Exception hierarchy | Structure | 73 | Extends Exception, an *Exception class or Error. |
| Trait (mixin) | Structure | 1 | Every trait. |
| Utility (static helper) | Structure | 730 | A concrete class whose methods are all static (at least two). |
| INI plugin point (extension point) | Plugins | 1376 | A setting of a settings/*.ini file (or an extension's) whose value is the name of a class of the catalogue. |
The areas
One page per part of the code base: every class with its patterns, and the views, functions, operators and plugin points defined there.
What was read
The git-tracked PHP and INI files below kernel/, lib/ and extension/ of the Exponential repository (tests and vendor/ directories left out), and these extensions:
| Extension | Source |
|---|---|
AdminAid | its own repository |
autorss | Composer package |
bccie | Composer package |
bcgooglesitemaps | Composer package |
bcwebsitestatistics | Composer package |
birthday | Composer package |
cjw_newsletter | Composer package |
cjw_themes_jumper | its own repository |
cjw_tmv | its own repository |
enhancedezbinaryfile | Composer package |
enhancedselection2 | Composer package |
exp_adminui | its own repository |
exp_enhanced_link | Composer package |
exp_oe_tiptap | its own repository |
expai | its own repository |
expchangeclass | its own repository |
exphelpsite | shipped with the kernel |
expimageeditor | shipped with the kernel |
explayouts | its own repository |
explayouts_api | its own repository |
explayouts_content_browser | its own repository |
explayouts_content_browser_core | its own repository |
explayouts_content_browser_ui | its own repository |
explayouts_core | its own repository |
explayouts_relation_list_query | its own repository |
explayouts_site_api | its own repository |
explayouts_standard | its own repository |
explayouts_tags_query | its own repository |
explayouts_ui | its own repository |
explayouts_ui_api | its own repository |
expquery_translator | its own repository |
expqueue | its own repository |
expservices | shipped with the kernel |
expsite_api | its own repository |
expsite_app | its own repository |
expsite_core | its own repository |
expsite_data_media | its own repository |
expsite_installer | its own repository |
expui | its own repository |
ezauthorize | Composer package |
ezautosave | Composer package |
ezdemo | Composer package |
ezfind | its own repository |
ezflow | Composer package |
ezformtoken | shipped with the kernel |
ezgmaplocation | Composer package |
ezie | Composer package |
ezjscore | shipped with the kernel |
ezmbpaex | Composer package |
ezmultiupload | Composer package |
ezodf | Composer package |
ezoe | shipped with the kernel |
ezoracle | its own repository |
ezownerchange | its own repository |
ezpaypal | Composer package |
ezpm | Composer package |
ezpostgresqlcluster | Composer package |
ezprestapi | Composer package |
ezprestapiprovider | Composer package |
ezssp | Composer package |
ezstarrating | Composer package |
eztags | Composer package |
ezupdate | Composer package |
ezurlmultisite | its own repository |
ezwebin | Composer package |
ezwt | Composer package |
git_manager | Composer package |
hcaptcha | Composer package |
ngclasslist | Composer package |
nxc_powercontent | Composer package |
owsimpleoperator | Composer package |
powercontent | its own repository |
recaptcha | Composer package |
sevenx_authentication_2fa | its own repository |
sevenx_dse | its own repository |
sevenx_themes_media | its own repository |
sevenx_themes_simple | Composer package |
sevenx_themes_super | Composer package |
sqliimport | its own repository |
str_replace | Composer package |
swark | Composer package |
syndication | Composer package |
xrowextract | Composer package |
xrowmetadata | Composer package |
An extension is read when it is a git repository of its own below extension/ whose origin is a se7enxweb repository, or a Composer package of se7enxweb installed there; private extensions and site settings are never read. A site that has other extensions installed gets a larger catalogue when it runs the generator.
How the catalogue is built
Run in the installation root (no database, nothing is loaded or executed; PHP's tokenizer reads the files):
php bin/php/exppatterncatalogue.php # report which pages would change
php bin/php/exppatterncatalogue.php --write # write doc/eng-us/standards/patterns/
php bin/php/exppatterncatalogue.php --check # exit 1 when the pages are out of dateThe output depends only on the source: no dates, no commit ids, everything sorted, so a second run on the same code writes the same bytes. Commit the pages with the code change that changes them.
Each category has a rule (the table above and each pattern's page). A class can match several categories. The rules use the class's name, its parent classes and interfaces (followed through the whole code base), its methods (static, abstract) and the registration files of the kernel: module.php (views and policy functions), function_definition.php (fetch functions), eztemplateautoload.php (template operators and functions), cronjobs/ directories, ezpEvent calls and INI settings whose value is a class name. Names are a heuristic: a class called ...Manager is listed as a facade or service even when it is something else, and a pattern implemented without the usual names is missed. Descriptions are the first sentence of each class's doc comment.
Note
The catalogue describes the code as it is, including inherited code. It is not a list of recommendations: for new code, follow the layering and naming rules.