Skip to content

Fix date-filtered general statistics with DBAL 4 - #2240

Merged
melroy89 merged 3 commits into
mainfrom
fix/stats-general-immutable-date
Oct 6, 2026
Merged

melroy89 merged 3 commits into
mainfrom
fix/stats-general-immutable-date

Conversation

@melroy89

@melroy89 melroy89 commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

Summary

Selecting a period on /stats/general/{period} throws an HTTP 500 because VoteRepository::count() binds a DateTimeImmutable as Doctrine's mutable datetime type. Bind it as datetime_immutable to match the method signature and allow period-filtered general statistics to load.

Additional information

The regression test uses DBAL's real statement type conversion with a mocked database driver. It covers dated and all-time counts, with and without federated users, across all five vote/favourite tables. Both dated cases reproduced the reported InvalidType exception before the fix.

Validation:

  • vendor/bin/phpunit --no-configuration --bootstrap vendor/autoload.php tests/Unit/Repository/VoteRepositoryTest.php: 4 tests passed, 130 assertions.
  • I also tested it locally now on my dev server

Related issues

Fixes #2239

@melroy89 melroy89 added bug Something isn't working backend Backend related issues and pull requests labels Oct 6, 2026
@melroy89 melroy89 added this to the v1.10.0 milestone Oct 6, 2026
@blued-gear

Copy link
Copy Markdown
Collaborator

With a quick search I found more such instances. Please run a search (for example text search in all files with 'datetime') and check if the type of the bound param mismatches. Same issue might be on some function signatures which get called with data from entities.

@melroy89

melroy89 commented Oct 6, 2026

Copy link
Copy Markdown
Member Author

With a quick search I found more such instances. Please run a search (for example text search in all files with 'datetime') and check if the type of the bound param mismatches. Same issue might be on some function signatures which get called with data from entities.

In PHP you have two kinds of data objects, namely DateTime and DateTimeimmutable. This was the Immutable variant.. so in VoteRepository::count() we needed to use datetime_immutable here, since it expects a DateTimeImmutable object. I couldn't find any other place in the code that is wrong.

@melroy89

melroy89 commented Oct 6, 2026

Copy link
Copy Markdown
Member Author

Following up on the suggestion to check other date-type mismatches: I found no additional immutable dates bound as mutable in the audited paths. The eight remaining explicit datetime bindings receive mutable DateTime objects, and the ORM/native-query helpers correctly select immutable types for immutable dates.

I did find a separate issue in EditedAtTrait::getEditedAt(): $editedAt is nullable and defaults to null, but the getter declares a non-nullable \DateTimeImmutable return. Calling it on unedited content reproduces TypeError: Return value must be of type DateTimeImmutable, null returned. The return type should be ?\DateTimeImmutable to match the property and database mapping.

I found no current callers in the application or templates, so this is a dormant defect rather than another confirmed HTTP 500 path. It is distinct from the DBAL binding fixed here and can be addressed separately.

Validation: the existing regression tests and temporary DBAL conversion checks passed (8 tests, 211 assertions).

@melroy89
melroy89 merged commit 06376bb into main Oct 6, 2026
8 of 9 checks passed
@melroy89
melroy89 deleted the fix/stats-general-immutable-date branch October 6, 2026 21:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend Backend related issues and pull requests bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

500 on /stats/general/{period}: DateTimeImmutable bound as 'datetime' in VoteRepository::count()

2 participants