Important

We are updating the images for OroCommerce version 6.1 to align with the latest changes in the back-office design. During this transition, some images may still show older versions. Thank you for your patience as we work to update all visuals to reflect these changes.

Architecture Details 

The bundle is designed to be flexible and extensible, allowing developers to integrate additional PDF generation engines in the future.

Glossary 

  • PDF builder factory - a factory that creates the appropriate PDF builder for the specified PDF options preset.

  • PDF builder - a builder that collects the PDF options to generate a PDF file.

  • PDF options preset - a string that denotes a set of options to be stored in the PDF options DTO.

  • PDF options - a DTO that contains the options for generating a PDF file that will to be passed to the PDF engine.

  • PDF options configurator - a configurator that configures the PDF options via the OptionsResolver.

  • PDF template - a model that contains the Twig template (path or template wrapper) and context (variables).

  • PDF template asset - a model that represents an asset (e.g. image, CSS, JS) that is used in the PDF template.

  • PDF template renderer - a service that renders a PDF template via own Twig environment.

  • PDF engine - an engine that is responsible for generating the PDF file by interacting with the configured engine.

  • PDF file - a model that represents the actual PDF file generated by the engine.

  • PDF document operator registry - a registry that retrieves the appropriate PDF document operator for the specified entity class and PDF document generation mode.

  • PDF document generation mode - a mode that defines how the PDF document is generated, e.g. instant or deferred.

  • PDF document operator - an operator that is responsible for generating PDF documents for a specific entity class.

  • PDF document demand - a DTO that contains the necessary information to create a PDF document.

  • PDF document - an entity that represents the PDF document created by the PDF document operator.

  • PDF document factory - a factory that creates the PDF document based on the provided PDF document demand.

  • PDF document resolver - a resolver that ensures the PDF document is up-to-date, e.g. generates the PDF file if it is missing.

  • PDF document generator - a generator that is responsible for generating the PDF file for specific PDF document type, i.e. using the specified Twig templates, payload and PDF options preset.

  • PDF document type - a string that represents the type of the PDF document, i.e., e.g. us_standard_invoice, eu_standard_invoice, etc. In other words, it allows to generate different PDF documents using different PDF document generators that enclose their own logic for generating PDF files for specific PDF document types.

  • PDF document template - a PDF template that is used to generate the PDF file for the PDF document.

  • PDF document template provider - a provider that retrieves the appropriate PDF document template for the specified PDF document type.

  • PDF document state - a string that represents the state of the PDF document, e.g. new, pending, resolved, etc.

PDF Document Flow 

The PDF document generation flow starts with the PDF document operator registry \Oro\Bundle\PdfGeneratorBundle\PdfDocument\Operator\PdfDocumentOperatorRegistry that has the following methods:

  • getOperator(string $entityClass, string $pdfGenerationMode): PdfDocumentOperatorInterface - retrieves the PDF document operator for the specified entity class and PDF document generation mode. Falls back to the default operator if no specific operator is found.

  • hasOperator(string $entityClass, string $pdfGenerationMode): bool - checks if a PDF document operator exists for the specified entity class and PDF document generation mode.

PDF document generation mode is expected to be a constant from the \Oro\Bundle\PdfGeneratorBundle\PdfDocument\PdfDocumentGenerationMode class, which defines the following modes of PDF generation:

  • instant - PDF documents are generated immediately.

  • deferred - PDF documents are generated when explicitly requested, e.g., via controller.

PDF document operator is responsible for generating PDF documents for a specific entity class. The operators are collected in the registry by the service container tag oro_pdf_generator.pdf_document.operator.

Out-of-the-box, the PDF document operator is implemented by \Oro\Bundle\PdfGeneratorBundle\PdfDocument\Operator\GenericPdfDocumentOperator that has the following methods:

  • createPdfDocument(AbstractPdfDocumentDemand $pdfDocumentDemand): AbstractPdfDocument - creates a PDF document based on the provided PDF document demand.

  • updatePdfDocument(AbstractPdfDocument $pdfDocument): void - re-generates the PDF file for the existing PDF document.

  • isResolvedPdfDocument(AbstractPdfDocument $pdfDocument): bool - checks if the PDF document is resolved (e.g., the PDF file is generated).

  • resolvePdfDocument(AbstractPdfDocument $pdfDocument): void - resolves the PDF document to ensure it is up-to-date, e.g. generates the PDF file if it is missing.

  • deletePdfDocument(AbstractPdfDocument $pdfDocument): void - deletes the PDF document.

Hint

You can create your own PDF document operator by creating a new class that implements \Oro\Bundle\PdfGeneratorBundle\PdfDocument\Operator\PdfDocumentOperatorInterface and registering it as a service with the tag oro_pdf_generator.pdf_document.operator.

PDF document demand is a DTO that contains the necessary information to create a PDF document. Out-of-the-box, the bundle provides the generic PDF document demand \Oro\Bundle\PdfGeneratorBundle\PdfDocument\Demand\GenericPdfDocumentDemand that can be used to create any PDF document.

PDF document is represented by entity \Oro\Bundle\PdfGeneratorBundle\Entity\PdfDocument that contains the PDF file and metadata about how it was generated. The properties of the PDF document are:

  • id - the identifier of the PDF document.

  • uuid - the universally unique identifier (UUID), e.g., to identify the document in a URL.

  • pdfDocumentName - the name of the PDF document (e.g., order-0101). To be used in the file name.

  • pdfDocumentType - the type of the PDF document, e.g., us_standard_invoice, eu_standard_invoice, etc. It is used to group the documents by type.

  • pdfDocumentFile - the actual PDF file, reference to the \Oro\Bundle\AttachmentBundle\Entity\File entity.

  • sourceEntityClass - the fully qualified class name of the entity for which the PDF document was generated.

  • sourceEntityId - the identifier of the entity for which the PDF document was generated.

  • pdfDocumentPayload - the payload that was used to generate the PDF document, serialized as JSON. It can contain additional data that was used during the PDF generation, e.g., customer notes, etc.

  • pdfOptionsPreset - the PDF options preset that were used to generate the PDF document, e.g. default.

  • pdfDocumentState - the PDF document state, e.g., resolved, pending, etc. It is used to track the state of the PDF document and its generation process.

  • pdfDocumentGenerationMode - the PDF document generation mode, e.g., instant, deferred.

Under the hood, the GenericPdfDocumentOperator delegates the responsibility to the PDF document factory and the PDF document resolver.

PDF document factory is implemented by the \Oro\Bundle\PdfGeneratorBundle\PdfDocument\Factory\GenericPdfDocumentFactory and is responsible for creating the PDF document based on the provided PDF document demand.

Hint

You can alter the creation process by creating listeners for the \Oro\Bundle\PdfGeneratorBundle\Event\BeforePdfDocumentCreatedEvent or \Oro\Bundle\PdfGeneratorBundle\Event\AfterPdfDocumentCreatedEvent events.

PDF document resolver is responsible for resolving the PDF document to ensure it is up-to-date with desired PDF document state, i.e, it. generates the PDF file if it is missing. The bundle provides two resolvers out-of-the-box:

  • \Oro\Bundle\PdfGeneratorBundle\PdfDocument\Resolver\DeferredPdfDocumentResolver - resolves the PDF document when explicitly requested, e.g., via controller.

  • \Oro\Bundle\PdfGeneratorBundle\PdfDocument\Resolver\InstantPdfDocumentResolver - resolves the PDF document immediately when it is created

Hint

You can alter the resolution process by creating listeners for the \Oro\Bundle\PdfGeneratorBundle\Event\BeforePdfDocumentResolvedEvent or \Oro\Bundle\PdfGeneratorBundle\Event\AfterPdfDocumentResolvedEvent events. In case you need more control over the resolution process, you can create your own PDF document resolver by creating a new class that implements the \Oro\Bundle\PdfGeneratorBundle\PdfDocument\Resolver\PdfDocumentResolverInterface and registering it as a service with the tag oro_pdf_generator.pdf_document.resolver.

PDF document state represents the state of the PDF document. States available out-of-the-box are listed in the``OroBundlePdfGeneratorBundlePdfDocumentPdfDocumentState`` class:

  • new - the initial state of the PDF document when it is created.

  • pending - the state when the PDF file is waiting to be resolved.

  • deferred - the state when the PDF file is not yet generated and waits for the explicit request to generate it.

  • in_progress - the state when the PDF file is being generated.

  • resolved - the state when the PDF file is successfully generated and available for download.

  • failed - the state when the PDF file generation failed.

Under the hood, the InstantPdfDocumentResolver delegates the PDF file generation to the PDF document generator. After the PDF file is generated, it sets it to the PDF document and updates its state to resolved. If the generation fails, it sets the state to failed.

Out-of-the-box the PDF document generator is implemented by \Oro\Bundle\PdfGeneratorBundle\PdfDocument\Generator\PdfDocumentGeneratorComposite that is a composite of inner generators that implement the \Oro\Bundle\PdfGeneratorBundle\PdfDocument\Generator\PdfDocumentGeneratorInterface and collected by the service container tag oro_pdf_generator.pdf_document.generator.

The bundle provides a generic generator \Oro\Bundle\PdfGeneratorBundle\PdfDocument\Generator\GenericPdfDocumentGenerator that retrieves the appropriate PDF document templates from PDF document template provider. It is suitable for cases that do not require a complex logic.

Hint

You can change the generation process by creating a listener for the \Oro\Bundle\PdfGeneratorBundle\Event\BeforePdfDocumentGeneratedEvent event. This event is dispatched before the PDF document is generated and allows you to modify the PDF document payload. If you need more control over the generation process, you can create your own PDF document generator by creating a new class that implements the \Oro\Bundle\PdfGeneratorBundle\PdfDocument\Generator\PdfDocumentGeneratorInterface and registering it as a service with the tag oro_pdf_generator.pdf_document.generator.

PDF document template provider is implemented by \Oro\Bundle\PdfGeneratorBundle\PdfDocument\PdfTemplate\PdfDocumentTemplateProviderComposite that is a composite of inner providers that implement the \Oro\Bundle\PdfGeneratorBundle\PdfDocument\PdfTemplate\PdfDocumentTemplateProviderInterface and are collected by the service container tag oro_pdf_generator.pdf_document.pdf_template.provider.

Out-of-the-box, the bundle provides the following template providers:

  • \Oro\Bundle\PdfGeneratorBundle\PdfDocument\PdfTemplate\GenericPdfDocumentTemplateProvider - returns static template paths pre-configured via constructor for the specified PDF document type.

  • \Oro\Bundle\PdfGeneratorBundle\PdfDocument\PdfTemplate\LayoutThemeAwarePdfDocumentTemplateProvider - returns the template paths based on the current layout theme for the specified PDF document type. It is suitable for cases when you want to have different templates for different layout themes.

PDF File Flow 

The PDF file flow starts with the PDF builder factory \Oro\Bundle\PdfGeneratorBundle\PdfBuilder\PdfBuilderFactory responsible for creating the appropriate PDF builder for the specified PDF options preset.

PDF builder is responsible for collecting the PDF options to generate a PDF file, then it delegates the generation to the configured PDF engine.

Out-of-the-box, the bundle provides the generic PDF builder \Oro\Bundle\PdfGeneratorBundle\PdfBuilder\GenericPdfBuilder that can be used to create any PDF file.

PDF options preset is a string that denotes a set of options to be stored in the PDF options DTO. The available presets that come standard are defined in the \Oro\Bundle\PdfGeneratorBundle\PdfOptionsPreset\PdfOptionsPreset class. Currently, the only available preset is default.

PDF options is a DTO that contains the settings for generating a PDF file to be passed to the PDF engine. It is implemented by \Oro\Bundle\PdfGeneratorBundle\PdfOptions\PdfOptions class out-of-the-box. The PDF options may include parameters, such as page size, margins, engine-specific settings like API URL, binary path, etc.

PDF options DTO is configured by the PDF options configurator that actually makes use of the \Symfony\Component\OptionsResolver\OptionsResolver. The options are resolved in the PDF builder before being passed to the configured PDF engine.

Hint

PDF options DTO becomes immutable after getting resolved. The last chance to alter it is to create a listener for the \Oro\Bundle\PdfGeneratorBundle\Event\BeforePdfOptionsResolvedEvent event.

The default preset declares the options common for all engines. It is configured by the \Oro\Bundle\PdfGeneratorBundle\PdfOptionsPreset\DefaultPdfOptionsPresetConfigurator that configures the following options:

  • content - the main content template, required.

  • header - the header template, optional.

  • footer - the footer template, optional.

  • assets - the list of assets to be included during generation PDF generation, optional. Should contain all assets that appear in the the main template. Filled automatically from the PDF template assets collector - \Oro\Bundle\PdfGeneratorBundle\PdfTemplateRenderer\AssetsCollector\PdfTemplateAssetsCollector.

  • page_width - the width of the page, optional. Defaults to the corresponding setting of the PDF engine. For the Gotenberg engine, it is 8.5in, the width of a Letter format.

  • page_height - the height of the page, optional. Defaults to the corresponding setting of the PDF engine. For the Gotenberg engine, it is 11in, the height of a Letter format.

  • margin_top - the top margin of the page, optional. Defaults to the corresponding setting of the PDF engine. For the Gotenberg engine, it is 0.39in.

  • margin_right - the right margin of the page, optional. Defaults to the corresponding setting of the PDF engine. For the Gotenberg engine, it is 0.39in.

  • margin_bottom - the bottom margin of the page, optional. Defaults to the corresponding setting of the PDF engine. For the Gotenberg engine, it is 0.39in.

  • margin_left - the left margin of the page, optional. Defaults to the corresponding setting of the PDF engine. For the Gotenberg engine, it is 0.39in.

  • landscape - whether the page should be in landscape orientation, optional. Defaults to false.

  • scale - the scale of the page, optional. Defaults to 1.0.

  • custom_options - additional custom options that can be used by the PDF engine, optional. For the Gotenberg engine, it is an array of options that are passed directly to the ChromiumPdf builder.

Hint

You can create your own PDF options preset by creating a new class that implements the \Oro\Bundle\PdfGeneratorBundle\PdfOptionsPreset\PdfOptionsPresetConfiguratorInterface and registering it as a service with the tag oro_pdf_generator.pdf_options_preset_configurator.

PDF engine is responsible for generating the PDF file by interacting with the configured engine. The bundle provides the Gotenberg engine out-of-the-box, which is implemented by the \Oro\Bundle\PdfGeneratorBundle\PdfEngine\GotenbergPdfEngine class. It uses the Gotenberg API to generate the PDF file based on the provided PDF options.

GotenbergPdfEngine makes use of PDF template renderer to render the PDF templates before sending them to Gotenberg API. You can find more details about how PDF templates are rendered in the PDF Template Renderer section of the documentation.

Hint

You can implement your own PDF engine by creating a new class that implements the \Oro\Bundle\PdfGeneratorBundle\PdfEngine\PdfEngineInterface and registering it as a service with the tag oro_pdf_generator.pdf_engine.

PDF file is a model that represents the actual PDF file generated by the engine. Out-of-the-box, it is represented by the \Oro\Bundle\PdfGeneratorBundle\PdfFile\PdfFile class that can work both with the file path and the file content (stream).

To store the generated PDF in an entity, a \Oro\Bundle\AttachmentBundle\Entity\File entity can be created from a PDF file using the \Oro\Bundle\PdfGeneratorBundle\PdfFile\Factory\FileEntityFromPdfFileFactory factory.