Skip to content

Extension points

phil/doctrine-behaviours

The library declares no service: an application registers the listeners it wants on its entity manager — see Integration. What it implements is the interfaces its entities take on, and who is acting.

Contract\BlameResolver

Phil\DoctrineBehaviours\Contract\BlameResolver — who is acting now, given to BlameListener.

MethodContract
current(): ?stringA stable name of the user of the request, job or command, or null when nobody is known — then nothing is written

FixedBlame names always the same one, or nobody: for imports, commands and tests. A resolver of the application's own names users by an identifier that is not personal information where it can, since the name is copied into every blamed row — see Timestamps and blame.

Contract\OwnerResolver

Phil\DoctrineBehaviours\Contract\OwnerResolver, who new records belong to, given to OwnerListener.

MethodContract
current(): ?OwnerIdThe stable identifier of the owner, or null when nobody is known; then nothing is written

FixedOwner names always the same one, or nobody. See Owner.

Contract\VersionRestoreGuard

Phil\DoctrineBehaviours\Contract\VersionRestoreGuard, the right to go back to a past version, given to Versions.

MethodContract
check(Versionable $entity, int $number): voidThrows when the right is missing; VersionRestoreDenied, or an exception of the application's own

AllowVersionRestore lets everyone, RefuseVersionRestore no one. See Versions.

The sluggers

SlugListener takes the Sluggers of phil/slug: a slugger named or decorated there applies here, and Sluggable::sluggerName() picks one for an entity. See Slug.

The entity interfaces

An entity takes on a behaviour by implementing its interface, by hand or with the trait that maps its columns.

InterfaceTraitWhat the listener calls
Contract\TimestampableTimestampableEntitystampCreated(), stampUpdated()
Contract\BlameableBlameableEntityblameCreated(), blameUpdated()
Contract\SoftDeletableSoftDeletableEntitymarkDeleted(); restore() is the application's to call — see Soft delete
Contract\TreeNodeTreeNodeEntityplaceInTree() — see Trees
Contract\DeactivatableDeactivatableEntitystampDeactivated(); deactivate() and reactivate() are the application's to call — see Deactivation
Contract\OwnableOwnableEntityclaimOwner(); transferOwner() is the application's to call — see Owner
Contract\PublishablePublishableEntitymarkPublished(), markUnpublished(); the workflow moves the state — see Publication
Contract\PositionablePositionableEntityplaceAt(); positionGroup() names the group — see Position
Contract\SluggableSluggableEntity, ScopedSluggableEntityassignSlug(); slugScope() names the scope — see Slug
Contract\Translatable—newTranslation(); translationClass() and translatedFields() name the rest — see Translation
Contract\TranslationTranslationEntitytranslatable(), locale() — see Translation
Contract\VersionableVersionableEntityforkVersion(); Versions freezes — see Versions
Contract\DatedIdentifiableDatedIdentifierEntityassignDatedId() — see Dated identifier

An entity that implements an interface by hand keeps the columns and names of its own; the listeners read and write through the methods only.

Listeners and the filter

PointHow
The timeThe PSR-20 clock given to TimestampListener and SoftDeleteListener: stamps are in UTC
Which behaviours runOnly the listeners registered: each stands alone
Seeing deleted rowsSoftDeletedFilter, under SoftDeletedFilter::NAME, disabled for the queries that need them
Seeing deactivated rowsDeactivatedFilter, under DeactivatedFilter::NAME, disabled for the queries that need them
Erasing a user's nameBlameEraser::find() and replace(), over every blamed table
Erasing an ownerOwnerEraser::find() and replace(), over every owned table
The locales servedThe FallbackChain the application gives Translations, from the DeclaredLocales of phil/locale-dimensions
The publication workflowPublicationWorkflow's places and transitions, or a workflow of the application's own with those three places