jonasarts/opentbs-bundle
Symfony bundle integrating OpenTBS for generating Office documents such as DOCX, XLSX, PPTX, ODT, ODS, and ODP from templates. Merge data into templates using TinyButStrong-style tags for dynamic reports, invoices, and exports.
Architecture fit. Assess the package by role, not by name. jonasarts/opentbs-bundle is a Symfony bundle — a bundle class, DI service wiring, and a Configuration.php tree — and none of that loads in Laravel. As a dependency it fails fit outright. As a capability reference it fits well: the underlying engine (OpenTBS, a TinyButStrong plugin) merges data into .docx/.xlsx/.pptx/.odt by treating the Office file as a ZIP of XML and substituting tags ([var.name], [b.block]…[b.block] loops, [var.img;ope=addpic], conditionals). That is a "template is the layout spec" architecture, which is the right model when business users (finance, legal, ops) own the document layout and engineering owns only the data contract. It is a better architectural fit than programmatic PhpWord/PhpSpreadsheet construction for invoice/statement/contract generation, and it removes the need for a headless LibreOffice sidecar for Office formats.
Integration feasibility. High, but not via this package. The bundle's value-add is container wiring we do not need; the integration work is a ~50-line Laravel service provider that binds clsOpenTBS as a scoped instance (TBS is stateful — do not share it across queue workers or Octane requests), sets a temp/cache dir, loads a template, merges a data array, and returns a string or writes to a Storage disk. The library's legacy ergonomics (global-ish config, non-PSR naming, Show() terminating into file/download/string modes) are a wrinkle, not a blocker. Budget half a day for the wrapper, and materially more for template authoring, golden-file tests, and output validation — that is where the real effort lives.
Technical risk. High, and it is dominated by vendor, security, and correctness risk rather than raw technical difficulty:
Score: 0, opportunity 20.2. No evidence of production use. Treat the bundle as unmaintained by default; treat the upstream engine as small-team but real.onload handlers and parameter modifiers that can reach PHP and the filesystem. User-uploaded templates must never be rendered. This is the single most important product decision in the integration and belongs in the design review, not the code review.ext-zip must exist in every worker image.fullCalcOnLoad is set. Pivot tables, some charts and conditional formats, and content-control-heavy DOCX are known rough edges.composer.json on a wrapper can block a PHP upgrade even when the engine itself is fine.Key questions.
[client.name] tag?Recommendation: reject the bundle as a dependency; adopt tinybutstrong/opentbs directly behind an in-house Laravel wrapper. Treat the bundle as a reference implementation for the wrapper pattern, not as a candidate for the dependency graph.
Stack fit. Build a Laravel service provider that registers clsOpenTBS as a scoped binding, plus a DocumentRenderer contract (render(string $templatePath, array $data): string), a TemplateRepository resolving versioned templates from resources/templates in dev and object storage in production, and a config file for temp dir, output mode, and a hard allowlist of template sources. Do not attempt to shim the Symfony bundle through an emulation layer — that adds a maintenance surface for zero capability.
Migration path. Migrate template families, not codebases. If documents are currently built with PhpWord/PhpSpreadsheet, those remain the better tool for fully programmatic, data-dense output; OpenTBS wins where a designed template exists. If documents are currently generated by shelling out to headless LibreOffice, OpenTBS is a clear upgrade — faster, no container sidecar, no font-rendering drift. Keep PDF conversion explicitly out of scope for the first release; it is a separate decision (LibreOffice or a SaaS converter) and OpenTBS does not do it.
Compatibility. Pin the upstream library to an exact version. Verify PHP 8.2/8.3 and ext-zip in every worker image, and audit for PHP 8.4 deprecations if that upgrade is on the roadmap. The control that makes an unpinned upstream tolerable is a golden-file suite: fixture template + fixture data → assert the output ZIP opens, XML is well-formed, and no unresolved [...] tags remain. That suite runs in CI on every dependency bump and every template change.
Sequencing.
template_version column on generated documents for auditability.Maintenance. We own the wrapper, the golden-file suite, and the template library. Upstream is a small project; budget for occasional manual patches and a possible fork if it stalls. Because we do not depend on the bundle, its maintenance status is not our problem. The real ongoing load is template churn — business users will request edits, and every edit must re-run the golden tests. Treat template changes with the same change-control discipline as code.
Support. No community to lean on: 0 stars and 0 dependents means no Stack Overflow corpus, no issue history, no third-party tutorials. Internal documentation of the TBS syntax and the supported tag subset is mandatory, not optional. Whoever supports generated documents must be able to answer "why is this field blank" without upstream help. Plan for a short internal runbook and a named owner.
Scaling. CPU- and memory-bound, horizontally scalable with queue workers; no shared state, so concurrency is fine provided each render uses its own temp directory. Memory is the constraint: template size + embedded images + loop cardinality. A 10k-row XLSX loop with images will exhaust PHP memory before it exhausts CPU. Set explicit memory_limit per queue, cap loop sizes at the application layer, and configure the temp dir explicitly rather than trusting defaults in a container with a read-only filesystem.
Failure modes. The dangerous failures are silent: unreplaced tags shipped to a customer, stale Excel formula values, a corrupted ZIP that Word "repairs" on open, and partial writes on timeout. Mitigate with pre-completion output assertions (tag scan, ZIP validity, XML well-formedness), atomic write-then-rename to storage, idempotent retries, and a template_version audit trail. Loud failures — missing template, bad data key, memory exhaustion — are cheap by comparison. The catastrophic tail risk is a template-injection incident via an untrusted upload; the allowlist is the control, and it should be enforced in code, not in policy documents.
Ramp-up. Low for the wrapper, moderate for TBS syntax. A developer is productive with [var], [b.] blocks, and image/conditional modifiers in roughly a day; the conceptual shift — "the template is the layout spec" — is absorbed quickly. The larger ramp is organizational: teaching template authors the supported tag subset, the review workflow, and the boundary that templates are never uploaded by end users. Net profile: small, contained, and reversible if the spike fails — which is exactly what a capability with this dependency profile should look like before it reaches production.
How can I help you explore Laravel packages today?