Skip to content

Sample Guide

The samples/ directory is both a runnable example collection and a map of the engine's public capabilities.

The canonical L/C/B/S path is the complete public learning path. Current entry points, templates/outputs, ownership descriptions, and package status are recorded in the sample registry. Legacy examples are maintained only as internal regression fixtures outside the public samples/ tree.

Canonical Learn path

The twelve canonical samples complete the Learn path. L01–L03 keep document structure in LibreOffice and use PHP to supply data. L04–L06 retain a LibreOffice-authored shell/insertion point while PHP generates native ODT subtrees or image resources where that is the appropriate owner. L07 adds native generated tables; L08 adapts substantial controlled HTML into editable ODT elements. L09–L10 address native Writer-authored structures; L11 inspects the original template contract without producing an output document; L12 populates a Writer-authored named table while preserving Writer ownership.

ID Sample Learn about
L01 Variables & Filters assign() and filters, including ODT line breaks
L02 Conditions if, elseif, else, and ifnot
L03 Repeating Content assignRepeating() and foreach
L04 Rich Content RichText and Paragraph: PHP-generated native paragraphs and inline content
L05 Lists Native ODT lists, with numbered steps and a nested bullet-list hierarchy
L06 Images Image ownership choices: replace a template frame or insert an ImageElement
L07 Tables RichTable and RichTableCell: PHP-generated native editable table structure
L08 HTML Import HtmlImporter: substantial controlled HTML translated into native ODT elements
L09 Native Objects Addressable native structures: bounded bookmark/Section mutation plus typed table/frame addressing
L10 Writer User Fields String User Field binding: bind a template-owned document-global field
L11 Template Inspection TemplateContract: source-oriented bindings, controls, native objects, dependencies and capabilities
L12 Writer Table Population Populate a Writer-authored named table while preserving native headers, kept rows, structure and formatting

Canonical capability samples

The capability layer adds native ODF behavior above the Learn path.

ID Sample Additional capability
C01 Page & Flow Layout Paragraph-flow intent with Writer-owned page/master-page structure; Writer computes pagination
C02 Advanced Table Layout Whole-table geometry, relative column proportions, row geometry, and separate vertical/horizontal alignment
C03 Frame Layout Shared frame-layout semantics for floating and as-character text/image elements
C04 Declarative Structured Collections Direct Phase-D execution of Writer-authored nested Sections with template-shaped data
C05 Mapping & Automation Explicit mapping, concrete preflight, and common atomic Phase-E execution

Canonical builder samples

Builder samples demonstrate programmatic construction of substantial editable ODT documents or template candidates with the structured PHP API. They differ from Learn samples, which teach focused vocabulary; Capability samples, which demonstrate larger engine/ODF behaviors; and Professional Showcases, which demonstrate final composition with stable visual ownership in LibreOffice.

ID Sample Builder lesson
B01 Invoice Template Builder PHP constructs a credible editable invoice/template candidate with semantic paragraph styles, native tab stops, deliberate RichTable composition, and visible template syntax for later Writer refinement
B02 Professional Report Builder PHP composes a fictional multi-page annual report from existing RichText, tables, images, page-flow, and frame-layout capabilities

A Builder sample is a distinct ownership lesson rather than a promise of a matching showcase. B01 and B02 demonstrate substantial PHP-owned construction; S01b and S03/S03-B demonstrate the current professional Writer/template-owned showcase path.

Samples as architectural teaching material

The public sample suite is designed for both human readers and AI coding agents. Samples should not merely prove that an API call works; they should make the engine's intended solution patterns visible. Learn samples introduce focused vocabulary, capability samples demonstrate larger behaviors, Builder samples demonstrate structured programmatic document/template construction, and professional showcases demonstrate how to compose capabilities into credible editable documents with the intended LibreOffice/PHP ownership boundary.

For a professional showcase, correctness therefore has four dimensions: idiomatic public-API usage for developers, a clear ownership boundary for LibreOffice template authors, professional rendered output for end users, and code/structure that an AI coding agent can use as reliable architectural precedent. Existing strong examples should be reused as references rather than reimplemented in a weaker form.

Professional showcase samples

ID Sample Ownership lesson
S01b Professional CV · Structured Template LibreOffice owns the CV page design and native Section structure; PHP supplies collections, replaces the authored image resource, and owns bounded RichText sidebar regions
S03 Structured Professional Report One Writer-authored report template supports bounded native-object updates while preserving template-owned layout
S03-B Structured Professional Report · Alternative Composition The same Writer-authored report template produces a substantially different composition through native targets, table population, and Section cloning

C04 and C05 intentionally take different data paths: C04 passes values already named like the template's dependencies to executeDeclarative(); C05 maps application-shaped names through MappingDefinition, preflights them, and then uses atomic automate(). L06 intentionally shows two ownership models, not two interchangeable APIs: replaceImageByName() replaces image content at a frame authored in LibreOffice; ImageElement creates a new frame/resource as part of the PHP generated subtree. setImage() remains a placeholder-oriented convenience path documented with the image APIs, not a third equal model in this sample.

Run a sample

From the repository root after Composer installation, run a canonical sample:

php samples/sample_L01_variables_filters.php

Generated documents are normally written below:

samples/output/

Open the resulting .odt file in LibreOffice to verify both structure and visual behavior.

Visual regression workflow

For changes that affect rendered ODT output, automated PHPUnit and integration tests are necessary but are not sufficient for visual approval. Use the repository renderer after generating the ODT through the normal sample or CLI path:

tools/visual-regression/render-odt.sh path/to/document.odt

The renderer performs:

ODT → LibreOffice (headless) → PDF → pdftoppm → PNG

Inspect the actual rendered PNG files before issuing a Visual GO. Visual review means checking the complete rendered output against the intended sample semantics and, where available, a known-good baseline—not only confirming that the feature changed in the current slice is visible. The sample code and its corresponding LibreOffice template are authoritative evidence for those semantics. A report, successful XML or ZIP validation, automated tests, or merely opening or generating the ODT does not substitute for inspection.

Project visual-regression artifacts belong under tmp/visual-regression/; do not use system /tmp for them. Visual-regression work must preserve unrelated local artifacts in the primary checkout and must not clean, reset, restore, regenerate, or delete them.

If LibreOffice cannot execute in an agent or sandbox environment, report the visual check as BLOCKED BY ENVIRONMENT, not PASS or FAIL. The ODT may then be rendered from a working local environment with the same repository tool; the resulting PNG files remain the evidence for visual review.

Samples and templates belong together

Canonical samples that use a LibreOffice template keep that template in:

samples/templates/

For example:

samples/sample_L08_html_import.php
samples/templates/template_L08_html_import.odt

Read both sides when learning a feature. The PHP file shows what the application supplies; the ODT template shows what remains the responsibility of LibreOffice.

That distinction is central to the engine's design.

Learning by feature

For template language, start with L01–L03 and the Template Language documentation.

For programmatic content, start with L04–L08. Historical specialized examples remain internal regression fixtures and are not part of the public sample path.

For addressable native ODT structures, start with L09 Native Objects and Named Sections.

For Writer User Fields, start with L10. The canonical L10 template is self-contained and Composer-distributed.

For template inspection, start with L11.

For tables, start with L07 for content and C02 for advanced geometry.

For HTML, use L08 for general and table import.

For images, start with L06.

For frame layout, use C03. For integrated mapping and automation, use C05.

Historical CV architecture evidence

The historical CV experiments demonstrated PHP-owned generated regions and Writer-owned native Section collections. They are no longer public entry points. The canonical professional CV is S01b, which deliberately combines the established ownership lessons: Writer owns stable page design, Frames, styles and repeatable Sections; PHP supplies application data and only bounded generated regions where PHP genuinely owns the structure.

Use Building Complex Documents when studying the historical generated-region pattern and Named Sections for the native structured-template pattern.

Verification samples

The project also has integration tests that execute important public samples. This is deliberate: samples are user-facing code and should not silently drift away from the public API.

When changing a public sample, run the normal test suite in addition to opening the generated document in LibreOffice.

A practical rule

Do not copy the largest sample when a smaller one demonstrates the feature you need.

A useful progression is:

small API sample
      ↓
feature guide
      ↓
choose the ownership model
      ↓
L01–L12: focused vocabulary
then C01–C05: capabilities
then B01/B02 or S01b/S03/S03-B according to ownership

This keeps application rendering code understandable and makes ODT-specific problems much easier to isolate.