Skip to content

Feature/initial implementation - #6

Merged
sitepark-veltrup merged 56 commits into
mainfrom
feature/initial-implementation
Sep 29, 2026
Merged

sitepark-veltrup merged 56 commits into
mainfrom
feature/initial-implementation

Conversation

@sitepark-veltrup

Copy link
Copy Markdown
Member

@codecov

codecov Bot commented Sep 25, 2024

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

@sitepark-schaeper sitepark-schaeper left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First of all - I had to finish this up since it's getting late and github unfortunatly does not save pending comments. So some methods might not have gotten the attention they deserve, but with the rather architectual concerns I address here I think it's not worth investing too much time in these smaller chunks before those are settled.
With that out of the way, I wrote some (unstructured) thoughts down that I had while reading through your code and would like to discuss them with you:

I've ignored the translations so far, but is the .translation-cach directory intended to be checked in?

Why are Layouts Elements?

The names of email specific classes are a bit wordy in my opinon. For example, Dto/Email/EmailHtmlMessageRendererResult could just be Dto/Email/RenderingResult, right?

A few classes here include the term Model, which I don't quite understand what it means in this context. May it just be a Dto?

There are a lot of mutable properties in the Dtos which I did not find why. Do we really need to expose these (and if so, can we properly differentiate them)?

We might have gone a little bit overboard with the array typing here. It's really hard to review it and figure out what is a class, what is just an array structure and which of their properties are actually gurantieed to be typed as defined and which might not. As such I did "skip" some of the implementations (like FormDataModelFactory) because I did not have the time to comprehend them. I feel like this complexity and mental overhead is not neccessary and we could just type out most of these as classes.
This also applies to all the $options (for which it is also difficult to figure out what exactly is beeing configured and from where). I get that it's hard to declare these but having it as just array<string, mixed> but checking for explicit values seems like a red flag.

Another reoccuring theme seem to be nullable array types. I don't think there is a reason for an array that is allowed to be empty to also be nullable. an alternative would be something like ?non-empty-array<string, string> but that is even less intuitive.

Then there are classes with comments saying "not yet implemented". I get that creating them helps development but do they need to be checked in?

Lastly a couple of class comments could be nice. For example the Constraint interface might profit from a small sentence explaining what it is, why it exists and what it's used for. To be clear - I don't want to be pedantic and don't think it's too big of a deal, I just think someone that does not happen to have the context could have a hard time figuring this out where all it takes are 20ish words.

Comment thread .github/workflows/verify.yml Outdated
Comment thread src/Dto/FormSubmission.php Outdated
Comment thread src/Processor/EmailSender.php Outdated
Comment thread src/Processor/EmailSender.php Outdated
Comment thread src/Processor/EmailSender.php
Comment thread src/Service/FormDataModelFactory.php Outdated
Comment thread src/Service/FormReader.php Outdated
Comment thread src/Service/JsonSchemaValidator.php Outdated
Comment thread src/Service/JsonSchemaValidator/DataUrlConstraint.php
Comment thread src/Service/Platform.php Outdated
@sitepark-veltrup

Copy link
Copy Markdown
Member Author

Why are Layouts Elements?

https://jsonforms.io/docs/uischema/layouts#elements

Layouts can be nested.

Layouts have an elements attribute in which further layouts or controls can be contained. Both are elements of the elements list.

sitepark-veltrup and others added 24 commits January 29, 2025 15:11
Brings the branch to the tooling state of the other atoolo packages:
phpstan 2.2.14, composer-normalize 2.53.0, phpunit 10.5.64 and
php-cs-fixer 3.95.26, phplint via composer instead of phive, the php
range >=8.1 <8.6.0 verified by both phpcs.compatibilitycheck.xml and the
CI matrix.

Conflicts resolved:
- composer.json keeps this branch's 24 dependencies and takes the wider
  php range; analyse:phplint now calls ./vendor/bin/phplint
- composer.lock stays untracked, as it is on this branch - a bundle
  resolves fresh, and main tracking it was the outlier
- the tool configurations take main's state

Three findings that only phpstan 2 reports are fixed along the way, in
LabelTranslator and EmailSender. The 16 findings that were already there
under phpstan 1.12 are untouched - they are this branch's own and want a
separate look.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
phpstan reported 16 findings on this branch, unnoticed because CI calls
it with "|| true". Most of them trace back to two wrong type
declarations rather than to the code:

- @phpstan-type DelivererConfig was missing a comma after "showEmpty:
  bool", so the parser stopped there and the whole "selectable" key was
  lost from the type. That is why EmailSender's isset() on it was
  reported as impossible.
- Both DelivererModel and DelivererConfig described "selectable" as a
  single entry, while transformProcessorConfig() builds a map of
  selection key to config and appends to selectable[$key]['to'].
  EmailSender's own @PARAM shape did not list the key at all.

The remaining ones are narrowings where a decoded structure meets a
typed signature, plus the redundant "?? ''" fallbacks on an address
"name" that the shape declares as required.

One finding pointed at a real gap: the JsonSchema alias had no
"deliverer" member although FormDataModelFactory::control() reads it,
which made the flag permanently false and the deliverer variable dead.

No behaviour changes; the 126 tests pass unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ut value

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The shared factory service kept the traversal state between create() and
the reader callbacks. The state now lives in a FormDataModelCollector
that is created per call. FromReaderHandler is renamed to
FormReaderHandler.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SpamDetector was a no-op processor, the MJML renderer had no templates
and Role was never populated. They can come back once implemented.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rename EmailHtmlMessageRendererResult to EmailMessageRendererResult to
match EmailMessageRenderer, drop the lookup of the removed subject
property and document the league/csv exception explicitly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The current date is taken from ClockInterface, the array/object
conversions are plain JSON round trips where they are needed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sitepark-veltrup

sitepark-veltrup commented Sep 29, 2026 •

Copy link
Copy Markdown
Member Author

@sitepark-schaeper thanks for the thorough review. Here is where the general points from your review stand:

  • .translation-cache: intended. It is the hash cache of the automatic translation, so unchanged labels are not translated again.
  • Layouts as Elements: this follows the JSON Forms spec, where layouts are UI schema elements themselves and can be nested.
  • Wordy names: EmailHtmlMessageRendererResult is now EmailMessageRendererResult, matching EmailMessageRenderer (fef5c37).
  • "Model": it means the template model passed to Twig, so I kept the term.
  • Mutable DTO properties: the UISchema DTOs are readonly now (7177311). FormSubmission::$approved stays mutable, see the thread on SubmitProcessor.
  • Array typing / $options: agreed, but replacing the array shapes with classes is too big for this PR. Tracked in Replace array shapes with typed classes #18.
  • Nullable arrays: FormDefinition::$processors is no longer nullable. $data and $messages stay nullable, because the definition is serialized with SKIP_NULL_VALUES, and [] would change the JSON the frontend receives.
  • "Not yet implemented" classes: removed SpamDetector, the MJML renderer and Role (c9edc5a).
  • Class comments: added for Constraint, SubmitProcessor, FormReader and FormReaderHandler (171f503).

@sitepark-veltrup
sitepark-veltrup merged commit 0bd0060 into main Sep 29, 2026
7 checks passed
@sitepark-veltrup
sitepark-veltrup deleted the feature/initial-implementation branch September 29, 2026 07:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants