Cleanup phpstan baseline issues#308
Conversation
…type surface had been hiding
…match the property types they bind to.
… issue rather than dereferencing nullable getters
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## feature/psalm-to-phpstan #308 +/- ##
===========================================================
Coverage ? 17.44%
Complexity ? 1714
===========================================================
Files ? 202
Lines ? 7155
Branches ? 0
===========================================================
Hits ? 1248
Misses ? 5907
Partials ? 0
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
jeppekroghitk
left a comment
There was a problem hiding this comment.
A few comments to consider before merging. Nice job.
| { | ||
| public function getDescription(): string | ||
| { | ||
| return 'Make columns nullable on synced entities (issue/project/version/worklog) and on app-managed DateTime fields (project_billing period_start/end, service_agreement valid_from) to match PHP property types.'; |
There was a problem hiding this comment.
I don't like the idea that Claude edited this file. Description is not filled out when doctrine generates it.
There was a problem hiding this comment.
Claude only wrote the descriptions.
| { | ||
| public function getDescription(): string | ||
| { | ||
| return 'Make ManyToOne foreign keys nullable on entities whose properties are typed nullable. Aligns DB schema with PHP property types; application/validation layer still enforces required-ness on app-managed entities.'; |
There was a problem hiding this comment.
Claude only wrote the descriptions.
| if (null === $row) { | ||
| continue; | ||
| } |
There was a problem hiding this comment.
Are you sure that the calls on $row after this will not fail hard, if $row is null?
For example at $row->getNumCells().
There was a problem hiding this comment.
In essence yes:
- RowIteratorInterface::current(): ?Row — the interface contract allows null (vendor/openspout/openspout/src/Reader/RowIteratorInterface.php:15).
- CSV RowIterator implementation only returns a Row once valid() is true, and PHP's foreach checks valid() before each current() call — so in practice $row will never be null during normal
iteration (vendor/openspout/openspout/src/Reader/CSV/RowIterator.php:99-102, :73-76).
| * [PR-308](https://github.com/itk-dev/economics/pull/308) | ||
| * PHPStan baseline: 530 → 0 in `src/`, bounced to 444 after develop's test suites merged, | ||
| now 91. Items below are behavior- or schema-affecting and worth calling out. | ||
| * Migration `Version20260517131038`: 18 columns made nullable on synced entities | ||
| (`issue`, `project`, `version`, `worklog`) plus 3 DateTime fields, to match property types. | ||
| * Migration `Version20260517151632`: 11 `NOT NULL` ManyToOne FKs relaxed to `NULL`; | ||
| application-layer `#[Assert\NotNull]` / form validators still enforce required-ness. | ||
| * Replaced `?T $prop = null` with non-null defaults on 25 entity properties to satisfy | ||
| `NOT NULL` columns; `Worker`/`WorkerGroup` `__toString()` switched from `??` to `?:`. | ||
| * `ForecastReportService` rendered empty epic tags — called non-existent `Epic::getName()`; | ||
| now uses `Epic::getTitle()`. | ||
| * `SubscriptionHandlerService::getVersion()` looked up `Version` by non-existent | ||
| `versionId` field; now uses `find($versionId)`. | ||
| * `DataProviderService::setTimeSpentSeconds()` silently lost precision passing `float` to an | ||
| `int` setter; explicit `(int)` cast added. | ||
| * Report services (`ForecastReportService`, `BillableUnbilledHoursReportService`, | ||
| `InvoicingRateReportService`) now skip worklogs with null project/issue instead of crashing. | ||
| * `SubscriptionController::check()` returns HTTP 400 on null `User::getEmail()`; | ||
| `User::getUserIdentifier()` throws on empty email (Symfony requires `non-empty-string`). | ||
| * `LeantimeApiService` switched from `json_decode($json, null)` to `json_decode($json, true)`; | ||
| all `$data->property` accesses converted to array access. Wire shape unchanged. | ||
| * Removed dead code: `readonly string $id` on 3 report-data models, unreachable `break;` after | ||
| `throw`, null check on `Row` iterator, unused `$paginator` arg in `SubscriptionRepository`. | ||
| * Fixed `Epic::getIssues()` PHPDoc typo (`Collection<int, Epic>` → `Collection<int, Issue>`). | ||
|
|
There was a problem hiding this comment.
I get that this is a big PR, but the size of this entry hurts my eyes, along with the overuse of backticks.
Link to ticket
https://leantime.itkdev.dk/TimeTable/#/tickets/showTicket/7273
Description
Cleanup phpstan baseline issues.
Version20260517131038: 18 columns made nullable on synced entities(
issue,project,version,worklog) plus 3 DateTime fields, to match property types.Version20260517151632: 11NOT NULLManyToOne FKs relaxed toNULL;application-layer
#[Assert\NotNull]/ form validators still enforce required-ness.?T $prop = nullwith non-null defaults on 25 entity properties to satisfyNOT NULLcolumns;Worker/WorkerGroup__toString()switched from??to?:.ForecastReportServicerendered empty epic tags — called non-existentEpic::getName();now uses
Epic::getTitle().SubscriptionHandlerService::getVersion()looked upVersionby non-existentversionIdfield; now usesfind($versionId).DataProviderService::setTimeSpentSeconds()silently lost precision passingfloatto anintsetter; explicit(int)cast added.ForecastReportService,BillableUnbilledHoursReportService,InvoicingRateReportService) now skip worklogs with null project/issue instead of crashing.SubscriptionController::check()returns HTTP 400 on nullUser::getEmail();User::getUserIdentifier()throws on empty email (Symfony requiresnon-empty-string).LeantimeApiServiceswitched fromjson_decode($json, null)tojson_decode($json, true);all
$data->propertyaccesses converted to array access. Wire shape unchanged.readonly string $idon 3 report-data models, unreachablebreak;afterthrow, null check onRowiterator, unused$paginatorarg inSubscriptionRepository.Epic::getIssues()PHPDoc typo (Collection<int, Epic>→Collection<int, Issue>).Checklist