Codebase metrics¶
A measured snapshot of the Personal Data Vault codebase and its submodules,
counted with cloc. Charts show code lines
(blank and comment lines excluded) unless stated otherwise.
Snapshot
Measured on the 1.x branch, 2026-09-20, with cloc 2.08. 407 files,
29,881 lines of code, 15,205 comment lines,
5,939 blank (51,025 lines in total). See
Methodology to reproduce.
At a glance¶
| Code | Comment | Blank | Files | Production | Test |
|---|---|---|---|---|---|
| 29,881 | 15,205 | 5,939 | 407 | 21,872 | 8,009 |
Production vs test¶
Personal Data Vault ships 8,009 lines of test code backing 21,872 lines of production code, a 37% test-to-production ratio.
Lines by language¶
| Language | Code | Comment | Blank | Files |
|---|---|---|---|---|
| PHP | 23,821 | 14,862 | 4,597 | 287 |
| YAML | 2,479 | 256 | 170 | 81 |
| PO File | 1,648 | 12 | 766 | 11 |
| Markdown | 1,488 | 1 | 380 | 15 |
| Text | 229 | 0 | 7 | 4 |
| CSS | 90 | 60 | 16 | 4 |
| JSON | 69 | 0 | 0 | 2 |
| HTML | 19 | 0 | 0 | 1 |
| JavaScript | 19 | 13 | 2 | 1 |
| SVG | 19 | 1 | 1 | 1 |
Composition¶
Across all languages, code is 59% of the lines, comments 30%, and blank lines 12%. The comment share reflects Drupal's docblock conventions.
By submodule¶
Production (brass) and test (steel) code per submodule, largest first.
| Submodule | Production | Test | Total |
|---|---|---|---|
| pdv (core) | 15,669 | 4,452 | 20,121 |
| pdv_client | 1,748 | 1,180 | 2,928 |
| pdv_webform | 1,394 | 1,117 | 2,511 |
| pdv_server_api | 936 | 731 | 1,667 |
| pdv_consumer_console | 697 | 44 | 741 |
| pdv_audit_trail | 524 | 130 | 654 |
| pdv_eca | 164 | 108 | 272 |
| pdv_message | 166 | 84 | 250 |
| pdv_vault | 246 | 0 | 246 |
| pdv_mail | 123 | 69 | 192 |
| pdv_client_api | 132 | 48 | 180 |
| pdv_client_audit_trail | 73 | 46 | 119 |
Test suite¶
Personal Data Vault ships 85 automated test classes (459 test methods), counted by type below.
| Test type | Classes | Methods |
|---|---|---|
| Kernel | 74 | 415 |
| Unit | 9 | 35 |
| Functional | 2 | 9 |
| FunctionalJavascript | 0 | 0 |
| Total | 85 | 459 |
Architecture surface¶
What the module contains, counted across Personal Data Vault and its submodules: the Drupal building blocks (services, plugins, hooks, routes, entities) that make up its public and internal API.
| Element | Count |
|---|---|
| Services | 53 |
| Event subscribers | 7 |
| Hook implementations | 17 |
| Routes | 61 |
| Permissions | 6 |
| Forms | 46 |
| Controllers | 17 |
| Content entity types | 5 |
| Config entity types | 3 |
| Config schema types | 10 |
| Plugins | 8 |
Plugins break down by type as follows, largest first:
Methodology¶
This page is generated by
scripts/generate-metrics.php,
run from the module root after a change worth reflecting:
php scripts/generate-metrics.php
It measures the files git ls-files reports, so a checkout that has
installed vendor/, previewed the docs into site/ or pulled a
node_modules/ counts the same as the archive a release ships. This page is
left out of that list: the script writes it, and a page that counts itself
changes the tree it just measured, so no two regenerations agree. The
snapshot above names the cloc version,
because cloc counts differently from one version to the next; that is the
version to run to reproduce this page, and the version the pipeline installs.
Each file is attributed to the nearest
enclosing module (a directory with a *.info.yml); test-support modules under
a tests/ path count as their parent's test code. A file is test code when its
path contains a tests/ segment, production otherwise.
Test classes are counted by their directory under tests/src (Unit, Kernel,
Functional, FunctionalJavascript); the method column counts each test-prefixed
method, and each further one annotated @test or #[Test]. The architecture surface counts
service definitions in *.services.yml (excluding aliases), route and permission
keys in *.routing.yml and *.permissions.yml, #[Hook] attributes, plugin
classes under src/Plugin/, forms and controllers under src/Form and
src/Controller, entity-type attributes in src/Entity, and top-level types in
config/schema/*.yml, all summed across the module and its submodules.
The charts are static inline SVG generated from the measured data, so they need
no JavaScript or charting plugin. They are decorative and marked
aria-hidden: every figure one of them draws is also in the table or the
sentence beside it, so a screen reader gets the numbers rather than an image
with no name. An img role carrying no accessible name is worse than no role
at all, because it hides the labels inside the chart as well.