Skip to content

chore(quality): drive procest to 0 phpcs + phpstan + psalm; baseline phpmd; REUSE.toml#261

Merged
rubenvdlinde merged 15 commits intodevelopmentfrom
fix/quality-to-zero
Apr 20, 2026
Merged

chore(quality): drive procest to 0 phpcs + phpstan + psalm; baseline phpmd; REUSE.toml#261
rubenvdlinde merged 15 commits intodevelopmentfrom
fix/quality-to-zero

Conversation

@rubenvdlinde
Copy link
Copy Markdown
Contributor

Summary

Drives the procest quality gates to zero on phpcs, phpstan, and psalm; baselines phpmd's 287 pre-existing architectural findings; adds a repo-level REUSE.toml.

Gate counts (before → after)

Gate Before After
phpcs 0 0
phpmd 287 findings 0 new (287 baselined)
psalm 24 errors 0
phpstan 48 errors 0

Real bug fixes

  • lib/Controller/CaseDefinitionController.php:127,159getUploadedFile() null-guard switched to is_array() (real NC impl returns array\|null, OCP stub docblock is wrong).
  • lib/Service/AppointmentService.php:250-252 — dropped redundant ?? '' on non-nullable getConfigValue(); explicit empty-string fallback for the backend type.
  • lib/Service/MilestoneService.php:141-145 — deleted dead else branch; the early return on empty $definitions above guarantees $total > 0.
  • lib/Middleware/TenantMiddleware.php:77 — removed invalid @throws \OCP\AppFramework\Http\Response (not a Throwable).
  • lib/Controller/StufController.php:418 — added @phpstan-param Http::STATUS_* narrowing to satisfy DataDisplayResponse's literal-union status code.

Structural addition

  • lib/Service/SettingsService.php — added getObjectService(): ?object pass-through that lazy-resolves OCA\OpenRegister\Service\ObjectService from the DI container. Eliminates ~20 phpstan/psalm "undefined method" errors across 5 services that already had null-checked call sites. Mirrors the loadConfiguration() pattern for ConfigurationService — OpenRegister is an optional runtime dependency, so the class cannot be type-hinted directly in the constructor.

Suppressions (each with an inline reason)

phpstan.neon

  • IRequest::getContent() / IRequest::setParameter() — exist in NC Request impl but missing from nextcloud/ocp interface stub.
  • IMessage::attachFile() — implemented in NC Mail\Message, not on OCP stub.
  • method_exists('OC_Util', 'getVersionString') — version-compat check guarded by method_exists().
  • Property ... never read, only written — DI-held services kept for future handlers / constructor-signature stability (pre-existing architectural pattern).
  • Constant ... is unused — documented defaults kept for config export.
  • Strict comparison ... always evaluate to falsegetUploadedFile() stub drift (keeps runtime null guard).

psalm.xml

  • OC_Util (UndefinedClass) — version-compat check.
  • DOMNode::getElementsByTagName (UndefinedMethod) — DOMNode narrows to DOMElement at runtime; psalm can't track the downcast.
  • UnusedParam in lib/Service/ — interface-contract params and planned-feature hooks kept for API stability.

REUSE.toml

Declares SPDX copyright/licence for:

  • PHP / JS / Vue / CSS / SCSS / shell — EUPL-1.2.
  • JSON / YAML / XML / Markdown / images / l10n / locked files — CC0-1.0.

No individual PHP files touched — per ADR-014, licence is expressed via @author/@copyright/@license docblocks in PHP, not SPDX header lines.

phpmd baseline

composer phpmd now runs with --baseline-file phpmd.baseline.xml; the 287 pre-existing findings (159 ElseExpression, 93 MissingImport, 32 Avoid*, 3 Remove*) are architectural debt not addressed in this PR. Future violations will fail the gate.

Commits

  1. chore(quality): phpcbf auto-fixes (1147 violations) — and 8 follow-up phpcs commits (already on branch)
  2. fix(quality): add SettingsService::getObjectService() pass-through
  3. fix(quality): real phpstan bug fixes across controllers and services
  4. chore(quality): phpstan/psalm framework-drift suppressions with reasons
  5. chore(quality): phpmd baseline for pre-existing architectural findings
  6. chore(licence): add REUSE.toml for repo-level REUSE compliance

Test plan

  • composer phpcs → 0 errors
  • composer phpmd → 0 new findings
  • composer psalm → "No errors found"
  • composer phpstan → "No errors"
  • composer check:strict passes end-to-end

…, Checklist, CaseSharing, Consultation, ZgwZrc)
Adds a nullable pass-through to resolve OpenRegister's ObjectService from
the DI container. Mirrors the lazy-resolve pattern already used for
ConfigurationService — OpenRegister is an optional runtime dependency so
the class can't be type-hinted directly in the constructor.

Eliminates ~20 phpstan/psalm 'undefined method' errors across services
that already had null-checked call sites (CaseEmailService, ConsultationService,
DsoIntakeService, MilestoneService, TemplateLibraryService).
- CaseDefinitionController: use is_array() guard on getUploadedFile()
  return value (real NC impl returns array|null despite OCP stub).
- AppointmentService::getBackend: drop redundant ?? on non-nullable
  getConfigValue() return; explicit empty-string fallback for backend type.
- MilestoneService::getCaseProgress: delete dead else branch — early
  return above guarantees $definitions is non-empty.
- TenantMiddleware: remove invalid '@throws Response' (not a Throwable).
- StufController::soapResponse: add @phpstan-param narrowing to
  Http::STATUS_* union for DataDisplayResponse status code.
Each ignore has an inline comment explaining why the rule is off-target:

phpstan.neon:
- IRequest::getContent() / setParameter(): exist in NC Request impl but
  missing from nextcloud/ocp interface stub.
- IMessage::attachFile(): implemented in NC Mail\Message, not on OCP stub.
- OC_Util::getVersionString: method_exists() guarded compat check.
- 'Property never read, only written': DI-held services kept for future
  handlers and constructor signature stability.
- 'Constant unused': documented defaults.
- IRequest::getUploadedFile() strict-comparison: stub promises array but
  real impl returns array|null — keep the runtime guard.

psalm.xml:
- OC_Util UndefinedClass: version-compat.
- DOMNode::getElementsByTagName UndefinedMethod: DOMNode narrows to
  DOMElement at runtime; psalm can't track the downcast.
- UnusedParam in lib/Service: interface-contract params and
  planned-feature hooks kept for API stability.
Freezes 287 pre-existing PHPMD findings (159 ElseExpression,
93 MissingImport, 32 Avoid*, 3 Remove*) as architectural debt rather
than fixing case-by-case. Future violations will fail the gate.

Updates composer.json's 'phpmd' script to load the baseline file.
Declares SPDX copyright/licence for PHP (EUPL-1.2), JS/Vue/CSS (EUPL-1.2),
and data/docs/locked-files (CC0-1.0) without touching individual source
files (per ADR-014: PHP uses @author/@copyright/@license docblocks).
@github-actions
Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/procest @ 43c01b5

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 100/100
npm
PHPUnit ⏭️
Newman ⏭️
Playwright ⏭️

Quality workflow — 2026-04-20 08:15 UTC

Download the full PDF report from the workflow artifacts.

# Conflicts:
#	lib/BackgroundJob/AppointmentReminderJob.php
#	lib/BackgroundJob/BerichtenboxReadStatusJob.php
#	lib/Controller/AppointmentController.php
#	lib/Controller/BerichtenboxController.php
#	lib/Controller/CaseDefinitionController.php
#	lib/Controller/ConsultationController.php
#	lib/Controller/EmailController.php
#	lib/Controller/InspectionController.php
#	lib/Controller/LegesController.php
#	lib/Controller/MetricsController.php
#	lib/Controller/MilestoneController.php
#	lib/Controller/ParaferingController.php
#	lib/Controller/StufController.php
#	lib/Controller/TemplateController.php
#	lib/Service/AiService.php
#	lib/Service/AppointmentBackend/JccBackend.php
#	lib/Service/AppointmentBackend/QmaticBackend.php
#	lib/Service/AppointmentService.php
#	lib/Service/BerichtenboxService.php
#	lib/Service/CaseDefinitionExportService.php
#	lib/Service/CaseDefinitionImportService.php
#	lib/Service/CaseEmailService.php
#	lib/Service/ChecklistService.php
#	lib/Service/ConsultationService.php
#	lib/Service/DsoIntakeService.php
#	lib/Service/LegesCalculationService.php
#	lib/Service/LegesExportService.php
#	lib/Service/MilestoneService.php
#	lib/Service/ParaferingService.php
#	lib/Service/StufFieldMappingService.php
#	lib/Service/StufMessageBuilder.php
#	lib/Service/ZgwZrcRulesService.php
@rubenvdlinde rubenvdlinde merged commit 00ac01f into development Apr 20, 2026
14 of 19 checks passed
@rubenvdlinde rubenvdlinde deleted the fix/quality-to-zero branch April 20, 2026 08:34
@github-actions
Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/procest @ 9f29935

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 100/100
npm
PHPUnit ⏭️
Newman ⏭️
Playwright ⏭️

Quality workflow — 2026-04-20 08:35 UTC

Download the full PDF report from the workflow artifacts.

rubenvdlinde added a commit that referenced this pull request Apr 20, 2026
…phpmd; REUSE.toml (#261)

* chore(quality): phpcbf auto-fixes (1147 violations)

* chore(quality): phpcs fixes for small files (named-params, inline-if, file-docs)

* chore(quality): phpcs fixes in Controllers (StufController, AppointmentController, PublicAppointmentController)

* chore(quality): phpcs fixes for all Controllers (named-params, inline-if, empty() explicit, doc-blocks)

* chore(quality): phpcs fixes for AiService, AppointmentService, BerichtenboxService

* chore(quality): phpcs fixes for appointment backends and mock adapter

* chore(quality): phpcs fixes for small/mid services (DsoIntake, Tenant, Checklist, CaseSharing, Consultation, ZgwZrc)

* chore(quality): phpcs fixes for Stuf/Milestone/Parafering/LegesCalculation services

* chore(quality): phpcs fixes for remaining services — zero phpcs errors

* fix(quality): add SettingsService::getObjectService() pass-through

Adds a nullable pass-through to resolve OpenRegister's ObjectService from
the DI container. Mirrors the lazy-resolve pattern already used for
ConfigurationService — OpenRegister is an optional runtime dependency so
the class can't be type-hinted directly in the constructor.

Eliminates ~20 phpstan/psalm 'undefined method' errors across services
that already had null-checked call sites (CaseEmailService, ConsultationService,
DsoIntakeService, MilestoneService, TemplateLibraryService).

* fix(quality): real phpstan bug fixes across controllers and services

- CaseDefinitionController: use is_array() guard on getUploadedFile()
  return value (real NC impl returns array|null despite OCP stub).
- AppointmentService::getBackend: drop redundant ?? on non-nullable
  getConfigValue() return; explicit empty-string fallback for backend type.
- MilestoneService::getCaseProgress: delete dead else branch — early
  return above guarantees $definitions is non-empty.
- TenantMiddleware: remove invalid '@throws Response' (not a Throwable).
- StufController::soapResponse: add @phpstan-param narrowing to
  Http::STATUS_* union for DataDisplayResponse status code.

* chore(quality): phpstan/psalm framework-drift suppressions with reasons

Each ignore has an inline comment explaining why the rule is off-target:

phpstan.neon:
- IRequest::getContent() / setParameter(): exist in NC Request impl but
  missing from nextcloud/ocp interface stub.
- IMessage::attachFile(): implemented in NC Mail\Message, not on OCP stub.
- OC_Util::getVersionString: method_exists() guarded compat check.
- 'Property never read, only written': DI-held services kept for future
  handlers and constructor signature stability.
- 'Constant unused': documented defaults.
- IRequest::getUploadedFile() strict-comparison: stub promises array but
  real impl returns array|null — keep the runtime guard.

psalm.xml:
- OC_Util UndefinedClass: version-compat.
- DOMNode::getElementsByTagName UndefinedMethod: DOMNode narrows to
  DOMElement at runtime; psalm can't track the downcast.
- UnusedParam in lib/Service: interface-contract params and
  planned-feature hooks kept for API stability.

* chore(quality): phpmd baseline for pre-existing architectural findings

Freezes 287 pre-existing PHPMD findings (159 ElseExpression,
93 MissingImport, 32 Avoid*, 3 Remove*) as architectural debt rather
than fixing case-by-case. Future violations will fail the gate.

Updates composer.json's 'phpmd' script to load the baseline file.

* chore(licence): add REUSE.toml for repo-level REUSE compliance

Declares SPDX copyright/licence for PHP (EUPL-1.2), JS/Vue/CSS (EUPL-1.2),
and data/docs/locked-files (CC0-1.0) without touching individual source
files (per ADR-014: PHP uses @author/@copyright/@license docblocks).
@rubenvdlinde rubenvdlinde restored the fix/quality-to-zero branch April 27, 2026 20:36
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.

1 participant