Table of Contents

Layer Boundaries and Dependencies

The intended architecture is described on Architecture Overview. This page measures what the imports actually do, and lists every place the two disagree.

1. The measured import graph

Every `use` statement that resolves to a first-party class, counted by the layer that wrote it and the layer that declares the target. 503 imports across 28 distinct layer pairs.

from \ to admin controller core dao dto handler model service validator
——————————
admin 4
controller 122 11 8 31 3
core 5 15 46 5 7
dao 25
handler 1 48
model 16
service 47 38 2 8
utility 2
validator 4

Read it as a graph and five cycles are immediately visible:

2. Which cycles are real, and which are the composition root

A cycle is only a design problem if the dependency carries *behaviour*. Most of `core`'s upward reach is concentrated in the two files whose entire job is to know about every other layer.

Edge Imports Dominant file Share
————
`core → handler` 46 `lib/core/Bootstrap.php` 98%
`core → dao` 15 `lib/core/Bootstrap.php` 47%
`core → service` 7 `lib/core/Bootstrap.php` 43%
`core → controller` 5 `lib/core/Dispatcher.php` 60%
`core → model` 5 `lib/core/AtomWriter.php` 40%
`admin → core` 4 `admin/authenticator.php` 100%

`core → handler` is not a layering defect. 45 of its 46 imports sit in `Bootstrap.php`, and `Bootstrap` is the composition root: it exists to instantiate the handler registry. Reading a cycle through the composition root is a category error.

Two upward dependencies are *not* explained that way, and are the real findings:

3. The rules the code states, and whether it keeps them

The DAO layer's own description claims: *“No HTML, no session, no superglobals.”* Measured against comment-stripped source:

Layer `$_GET` `$_POST` `$_SERVER` `$_SESSION` `$_COOKIE` `$_FILES` `$GLOBALS` Total
—————————
controller 56 398 77 261 3 48 11 854
admin 149 71 27 26 15 4 0 292
utility 7 14 107 46 18 2 20 215
core 16 0 94 32 24 0 12 178
install 9 49 41 40 0 0 0 139
tests 37 57 247 93 48 9 33 524
service 0 48 4 7 10 0 0 69
public 4 0 6 6 3 0 9 28
handler 0 0 23 0 0 0 1 24
dto 0 2 0 0 0 3 0 5
api 0 0 4 0 0 0 1 5
libroot 6 0 13 1 0 0 0 20
root 4 0 2 0 0 0 0 6
dao 0 2 0 0 0 0 0 2
model 0 0 0 0 0 0 0 0
validator 0 0 0 0 0 0 0 0

Counts are of comment-stripped source, but string literals are still counted, so treat them as *mentions* rather than proven reads.

4. Other boundaries that are declared but not enforced