Issue #3620326: Read the house once per page, open an add form in one place, and name only what exists
An audit before the next release, over performance, security, Drupal standards, documentation, translations and duplication.
Clean, and recorded so the next audit starts from it
- No N+1 on the booking path. Every per-iteration read found sits on a cache fill or an admin screen; the seat map's own path is already cached above the loop.
- Security: no interpolated SQL, no superglobals, no
unserialize/eval, no dynamict(). Every route in all 14 routing files carries an access requirement. - Standards: no deprecated core APIs. Every static
\Drupal::call is in an entity or a render element, which core builds rather than the container, and each says so in place. - Translations: 1974 strings extracted, every one translated, 7 documented exceptions.
- Config schema: every module shipping config ships schema.
- Accessibility: seats on the plan are real buttons with a label apiece, areas carry
role=group, decorative SVG isaria-hidden. - Release metadata: all 42 info files at
^11.3 || ^12.
Performance: five loops that read once per turn
Each asked the database once per iteration where one read does. None of them is on the request a booker waits for, which is worth stating plainly because the seat map looks like it should be:
VenueMapBuilder::getAreaSections()loaded a section per area, so sixteen areas cost sixteen reads.getSettledState()above it is cached per slot, content language and booking channel, so this runs on a cache fill, not per booking.- The venue-scoped widget loaded every option separately: a read per row of a select on an admin form.
ConfigurationAreaControllerread a grade per admin table row.BookingResourceType::calculateDependencies()read a message per attached id, on config save.- The demo controller read a booking per id.
Each now reads what it needs in one go, and the detector that found them reports none. These are real reductions on the paths they sit on, not a fix to booking latency.
Duplication: nine routes, one add form
Nine routes spelled out the same five lines to open an add form for a child of the thing being looked at. The storage and form-builder plumbing moves into AddChildFormTrait; the type created and the fields naming the parent stay at the call site, where a reader can see them. VenueInventoryController's own venue helper goes through it too.
Documentation: two names that do not exist
The no-code page said the example's CheckoutController "is gone", which is history rather than a description. The resource type design described the world before its own change in the present tense, down to a literal gateway string that appears nowhere in the code now.
Not done, on purpose
A clone detector reported 20 groups, but it blinds string literals: the save() and inventory-controller groups differ only in their messages and routes, and collapsing those would trade obvious methods for indirection. Two other detectors were discarded as artefacts rather than reported: a functional test never names the class it exercises, and a service-usage check collapsed its own haystack with sort -u.