Skip to content

Fix TypeError when hydrating time_unit on ticket articles - #196

Merged
derpixler merged 5 commits into
zammad:developfrom
jorisdrenth:master
Nov 10, 2026
Merged

derpixler merged 5 commits into
zammad:developfrom
jorisdrenth:master

Conversation

@jorisdrenth

@jorisdrenth jorisdrenth commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

When we switched on time accounting in Zammad settings, our implementation gave an error:

TypeError
ZammadAPIClient\Endpoints\TicketArticles\TicketArticleDTO::__construct(): Argument #21 ($time_unit) must be of type ?float, string given, called in /var/www/html/vendor/zammad/zammad-api-client-php/src/Core/Repository/DtoHydrator.php on line 63

I found Zammad stores time_unit as a decimal column, which the API returns as a JSON string (e.g. "15.0"). DtoHydrator::coerce() had no branch for float, so the raw string was passed into TicketArticleDTO's ?float $time_unit parameter.

The existing unit test used a native float (5.5), so it didn't catch this.

Changes:

  • Add Cast::floatOrNull(): returns a float for numeric values (including numeric strings), null otherwise.
  • Add a float branch to DtoHydrator::coerce(), mirroring int: nullable parameters use Cast::floatOrNull(), non-nullable ones use a new requireFloat() that throws a RuntimeException when the field is missing or not numeric.
  • Add unit tests in TicketArticleDTOTest for time_unit as a decimal string, fractional string, integer string, integer, float, null, and a missing key.

Summary by CodeRabbit

  • Improvements
    • Numeric values in ticket data are now consistently handled as decimals, while missing or null values remain null when allowed.
    • Required decimal fields now reject missing or nonnumeric values with an error.

@coderabbitai

coderabbitai Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review: 1

  • main

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 5d60897d-4eeb-474f-9da6-886e12178670

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review

No actionable comments were generated in the recent review.

Walkthrough

The change adds Cast::floatOrNull and updates DtoHydrator::coerce to handle float constructor parameters. Nullable parameters use nullable conversion; non-nullable parameters use requireFloat, which throws when the value is absent or not numeric. Tests cover numeric strings, integers, floats, explicit null, and missing time_unit values.

Merge Risk: Minimal · up to 2086a

Numeric time values are converted during hydration. No material merge-readiness risk was identified.

Pre-merge checks: Passed 5

Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly identifies the main change: fixing a TypeError when hydrating the ticket article's time_unit field.
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 3 functions across 4 files.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

Recent review info

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 6e2e5a6a-e75a-4ef1-835b-2b420e3c9fc7
Commits

Reviewing files that changed from the base of the PR and between d41885c and 2086a02.

Files selected for processing: 3

  • src/Core/Cast.php
  • test/Unit/Core/DtoHydratorTest.php
  • test/Unit/DTOs/TicketArticleDTOTest.php
Files skipped from review as they are similar to previous changes: 1

  • src/Core/Cast.php

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

@derpixler
derpixler self-requested a review November 10, 2026 09:50

@derpixler derpixler left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hi @jorisdrenth, thanks for the fix and the clear write-up. Good catch that the old test used a native float.

Just the few inline comments left to address, then it's good to go.

Comment thread src/Core/Cast.php Resolved
Comment thread src/Core/Repository/DtoHydrator.php Resolved
Comment thread test/Unit/DTOs/TicketArticleDTOTest.php Resolved
@derpixler
derpixler changed the base branch from master to develop November 10, 2026 13:43
@derpixler
derpixler merged commit 6b1af06 into zammad:develop Nov 10, 2026
20 checks passed
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