Readiness¶
An honest checklist of what a core proposal would need. Re-checked on
25 October 2026 against 2.x commit 4239582, tag 2.1.0-beta2.
Items that were not re-run say so. Each item is marked done or
open, with the file, command or link that shows it. Most items are
open. The concerns page argues that the design fits the
questions raised in core; this page is about whether the code is ready,
and it is not yet. The 25 October check is written up in
Findings.
Summary¶
| # | Item | Status |
|---|---|---|
| 1 | Unit tests of kit output cover every kit | open |
| 2 | Test suite runs on the current Drupal test stack | done |
| 3 | Functional tests (form submission, AJAX, nesting) | open |
| 4 | Known bugs found while writing these docs are fixed | open |
| 5 | Drupal coding standards | open |
| 6 | Static analysis (phpstan) baseline | open |
| 7 | Stable releases of the module and its dependencies | open |
| 8 | PHP / Drupal version matrix tested | open |
| 9 | Documented API and BC promise | open |
| 10 | Dependency on kits and formfactory resolved |
open |
| 11 | No PHP references in kit output | done |
| 12 | Output is a plain render array that works with existing forms | done |
| 13 | Memory and time cost measured | done |
| 14 | Developer documentation | done |
Details¶
1. Unit tests of kit output: open¶
tests/ has 38 test files. 37 are kit tests. CoreVersionRequirementTest
checks formfactorykits.info.yml. The Drupal 12 run on 24 October 2026
executed 203 tests. Count the files with:
find tests -name '*Test.php' | wc -l # 38
grep -rhE 'function test' tests also matches the commented-out
testCreateTabsWithOtherKits(), so that count is one higher than the
executed suite.
These concrete kit classes have no test class:
TableRowKit, TabKit, OptionKit, TaxonomyTermAutoCompleteKit,
TaxonomyTermSelectKit, UploadValidatorKit, FileSizeUploadValidatorKit,
ImageExtensionUploadValidatorKit, ImageResolutionUploadValidatorKit,
ExampleKit, ItemKit, TemplateKit. FileKitTest constructs
FileSizeUploadValidatorKit and ImageExtensionUploadValidatorKit.
ImageResolutionUploadValidatorKit is only imported, and UploadValidatorKit
has no test reference. TextFieldKit and TextAreaKit have test classes.
A test of
tabs with child kits is commented out in
tests/src/Unit/Kits/Container/Tabs/VerticalTabsKitTest.php.
No coverage percentage has been measured: on 25 October 2026 neither host
PHP nor the PHP 8.5 test image provided PCOV or Xdebug. The module's own
core-merge issue #3562924 sets
"90%+ Test Coverage" as a remaining task.
2. Test suite runs on the current test stack: done¶
KitTestBase no longer overrides assertEquals(), and phpunit.xml no
longer uses <listeners> or <filter>. On 24 October 2026 the unit suite
ran on Drupal 12.0.0-beta2, PHP 8.5.12, PHPUnit 12.5.40, and printed
OK (203 tests, 204 assertions). That does not cover Drupal 10.2 or 11,
and there is still no CI. See item 8.
3. Functional tests: open¶
There are no kernel, functional or JavaScript tests. Nothing in the repository submits a form built with kits, rebuilds it through AJAX, or reads it back from the form cache. The claim that kits avoid the failure in #3539320 rests on the output being a plain array (item 11), not on a test.
4. Known bugs: open¶
Found while writing these docs, each reproduced by running the code:
| Bug | Where | Effect |
|---|---|---|
file() calls an unimported class |
src/Services/FormFactoryKitsService.php, file() |
Fixed in 2.1.0-beta2. file() returns ManagedFileKit::create(...). |
| Legacy upload validator keys | src/Kits/Field/Media/ManagedFile/UploadValidators/*.php (CALLBACK constants) |
#upload_validators uses file_validate_* names; Drupal 11's FileValidator expects constraint plugin IDs such as FileSizeLimit. See File and image kits. |
| Building is not idempotent | Drupal\kits\Kit::getChildrenArray() (dependency) |
A second getArray() / getForm() on the same kit tree repeats parent IDs in #parents (['outer', 'outer']). |
#parents of nested children |
FormFactoryKit::getArray() with Kit::getChildrenArray() |
Children of a DetailsKit get #parents = ancestor IDs only, without their own key, so siblings appear to share one value path. Needs a functional test (item 3) to confirm the effect on submitted values. |
| FormFactory keeps state between loads | FormFactoryService (dependency drupal/formfactory 2.1.0-beta3) |
load() still does not reset the service's kit list, so a second form built in the same request also gets the first form's kits. getForm() no longer throws when no kit has been appended: $form is initialized to [] (0971922). |
| Getters typed too narrowly | ClassAttributeTrait::getClasses(), DescriptionTrait::getDescription() |
Return NULL where the declared type does not allow it, so calling them before a value is set throws TypeError. |
TaxonomyTermAutoCompleteKit::setVocabulary() |
src/Kits/Field/Entity/TaxonomyTermAutoCompleteKit.php |
Writes #vid, which entity_autocomplete ignores; it does not limit the vocabulary. |
5. Drupal coding standards: open¶
vendor/bin/phpcs --standard=Drupal,DrupalPractice \
--extensions=php,module,inc,install,yml src formfactorykits.info.yml formfactorykits.services.yml
Measured on 4 October 2026 and not re-run on 25 October 2026: with drupal/coder (PHP_CodeSniffer 3.13.6) this reports 2,203 errors and 9 warnings in 76 files; phpcbf can fix 2,106 of them automatically. Most are formatting (the code uses 4-space indentation, Drupal uses 2).
6. Static analysis: open¶
There is no phpstan.neon or baseline in the repository, so no phpstan level
is claimed. The implicit-nullable parameters named here on 4 October 2026
are gone. On 25 October 2026 this command printed nothing:
grep -rnE '[(,] *(string|int|array) \$[A-Za-z]+ = NULL' src
7. Stable releases: open¶
The module's latest tag is 2.1.0-beta2 (git tag). There is no alpha tag.
#3562924 still lists an "Alpha release"
as a remaining task. The tags that exist are betas. The dependency chain is
also beta: drupal/formfactory ^2.1@beta (composer.json). The releases
checked on 25 October 2026 are formfactory 2.1.0-beta3, kits
2.0.0-beta5, and query 2.0.0-beta7.
8. Version matrix: open¶
formfactorykits.info.yml declares core_version_requirement: ^10.2 || ^11 || ^12.
The code needs PHP 8.0 features (union and static return types, match,
named arguments), and Drupal 10.2 itself requires PHP 8.1. There is no CI
configuration in the repository. The unit suite has been run on Drupal
12.0.0-beta2 (item 2). Drupal 10.2 and 11 were not re-run on 25 October
2026. The benchmark ran on PHP 8.3 only and was not repeated for this check.
9. API and BC promise: open¶
There is no documented backwards-compatibility policy, no @api or
@internal markers, and public properties such as $isChildrenGrouped and
OptionsTrait::$options are part of the de facto API. A core proposal would
need to decide what is public before anything else.
10. Dependencies: open¶
The module depends on kits:kits and formfactory:formfactory
(formfactorykits.info.yml), and through them on query. Core cannot depend
on contributed modules, so this must be resolved first. See the
merge path for options.
11. No PHP references in kit output: done¶
grep -rn '&\$' src prints only the two core method signatures in
FormObjectBase. See Concerns.
12. Plain arrays and existing forms: done¶
FormFactoryKit::getArray() returns a new array, and
FormFactoryService::getForm() adds kits to the array passed to load().
See Concepts and
Altering any $form array.
13. Cost measured: done¶
Benchmarks measure A (bare arrays), B (the #3525331 wrappers, on a patched core) and C (kits). Against B (28 October 2026), kits retain about 38% less memory, with about 18% higher peak; build time was lower on 500 fields and within noise on 5,000 fields. Against bare arrays every object layer costs more, kits included. Whether that cost is acceptable is for reviewers to judge.
14. Documentation: done¶
This site, including a reference page for every kit and trait. It is hand-written; keeping it in step with the code is a maintenance task of its own.