Skip to content

feat(client): list, download, upload and delete record attachments - #57

Merged
pekral merged 2 commits into
masterfrom
feat/attachments
Nov 12, 2026
Merged

pekral merged 2 commits into
masterfrom
feat/attachments

Conversation

@pekral

@pekral pekral commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #31

TL;DR

Podpora příloh záznamů evidence: seznam, stažení, nahrání a smazání. Všechny čtyři operace jsem ověřil na veřejném demo serveru FlexiBee.

Změny

  • Client::getAttachments(int $id) vrací pole EvidenceResult z kolekce priloha (id, nazSoub, contentType, …).
  • Client::getAttachmentContent(int $id, int $attachmentId) vrací binární obsah přílohy. Pro neexistující přílohu vyhodí EcomailFlexibeeNoEvidenceResult.
  • Client::addAttachment(int $id, string $fileName, string $content, string $contentType) nahraje přílohu a vrátí ID nové přílohy. Název souboru se v URL kóduje.
  • Client::deleteAttachment(int $id, int $attachmentId) smaže přílohu.
  • HTTP vrstva:
    • CurlRequest má volitelné body pro binární obsah,
    • nová metoda HttpClient::send(CurlRequest, Config), na kterou deleguje stávající request(),
    • ResponseFactory vrací FlexibeeAttachmentResponse pro GET …/content se statusem 200, podobně jako u PDF.
  • Oprava z code review: ResponseFactory četla jako PDF každou odpověď, jejíž URL kdekoli obsahovala .pdf, u jakékoli metody. Nahrání přílohy faktura.pdf by tak ztratilo ID nové přílohy. Teď se PDF pozná jen u GET, jehož cesta končí na .pdf. Chyba byla už ve verzi 1.4 (u filtrů s .pdf).
  • README, CHANGELOG a UPGRADE-2.0 doplněny.

Ověření proti demo serveru

Testovací příloha byla po každém zápisu hned smazána a demo zůstalo v původním stavu.

Operace Požadavek Výsledek
Seznam GET /c/demo/cenik/code:DRÁT/prilohy.json {"winstrom":{"priloha":[{"id":"14","nazSoub":…,"contentType":…}]}}
Stažení GET …/prilohy/15/content 200, image/jpeg, binární data
Nahrání PUT …/prilohy/new/flexibee-client-test.txt s Content-Type: text/plain a Accept: application/json 201, results[0].id + Location
Smazání DELETE …/prilohy/{id}.json 200, příloha zmizela ze seznamu

Smazání přílohy dokumentace výslovně neuvádí. Vychází z obecného pravidla „mazat lze jednotlivé záznamy přes jejich detailové URL“ a na demo serveru funguje.

Zdroje

Merge danger

  • Dveře: two-way.
  • Veřejné API se jen rozšiřuje. HttpCurlBuilder::build() (interní třída) přijímá CurlRequest, uvedeno v UPGRADE-2.0.md.

Testování

  • Unit testy pro všechny vrstvy (URL, volby cURL s tělem, binární odpověď, hydrator, HttpClient::send, metody klienta). composer check prochází, pokrytí změněných řádků 58/58.
  • Ručně: addAttachment() u záznamu, getAttachments() ho musí obsahovat, getAttachmentContent() vrátí stejný obsah, deleteAttachment() ho odstraní.

Client gains getAttachments(), getAttachmentContent(), addAttachment()
and deleteAttachment() for the attachments of a record of the configured
evidence. The calls follow the FlexiBee attachment API and were checked
against the public demo server: the list is read from the "priloha"
collection, content is returned as raw bytes, an upload is a PUT of the
raw content to prilohy/new/{name} with its Content-Type (the new id comes
from results[0].id), and a delete is a DELETE of the attachment detail.

To send a raw body, CurlRequest gets an optional body, HttpClient gets
send(CurlRequest, Config) (request() delegates to it) and
HttpCurlBuilder::build() takes the CurlRequest.

Closes #31
@pekral pekral added this to the 2.0.0 milestone Nov 12, 2026
CR finding (Moderate): ResponseFactory returned FlexibeePdfResponse for
any URL containing ".pdf", for any method. Uploading an attachment named
faktura.pdf (PUT .../prilohy/new/faktura.pdf) therefore lost the JSON
result with the new attachment id, and a search filter mentioning ".pdf"
was not parsed. A response is now binary PDF only for a GET whose URL
path ends with ".pdf".
@pekral
pekral marked this pull request as ready for review November 12, 2026 15:10
@pekral

pekral commented Nov 12, 2026

Copy link
Copy Markdown
Collaborator Author

CR status — converged

Status: converged after 2 review iterations · Critical 0 · Moderate 0

Resolved items

  • Any URL containing ".pdf" was parsed as a PDF response (Moderate)
    • Why: addAttachment(…, 'faktura.pdf', …) would get a FlexibeePdfResponse instead of the JSON result and throw although the upload succeeded.
    • Reason: ResponseFactory matched .pdf anywhere in the URL, for every HTTP method.
    • Solution: PDF only for a GET whose URL path ends with .pdf; covered by three ResponseFactoryTest cases.
    • Commit: a0021e0 — fix(http): treat a response as PDF only for a GET of a .pdf path

@pekral

pekral commented Nov 12, 2026

Copy link
Copy Markdown
Collaborator Author

Code Review

Status: clean
Counts: Critical 0 · Moderate 0 · Minor 0 · Refactoring 0
Last updated: 2026-11-12T15:11:04Z (head a0021e0)
Issue tracker summary: no linked issue summary posted — #31 is the source issue


Summary: 0 Critical · 0 Moderate · 0 Minor · 0 Refactoring · assignment conformance: conformant (#31: attachments API — list, download, upload, delete — implemented and verified against the demo server) · reviewer comments: none

@pekral
pekral merged commit a4cf949 into master Nov 12, 2026
4 checks passed
@pekral
pekral deleted the feat/attachments branch November 12, 2026 15:11
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.

Přílohy

1 participant