Skip to main content

Word Developer guide

This module adds the ability to upload Word templates, parse them, and convert them

Installation

To install this module:

composer require qore/templates-extended
php artisan vendor:publish --tag=qore.templates-extended.db
php artisan vendor:publish --tag=qore.templates-extended.frontend

Optionally, publish the config:

php artisan vendor:publish --tag=qore.templates-extended.config

Make sure to migrate.

php artisan tenants:migrate

The WordTemplateResource will be registered by default. You can add this to your menu:

if (module_is_active('qore/templates-extended')) {
$tab->addResourceMenuItem(resource(WordTemplateResource::class));
}

This module also comes with a generic Templates page, where you have a shortcut to

  • Word templates
  • Twig templates
  • Mail templates
  • Template builder (todo)
if (module_is_active('qore/templates-extended')) {
$tab->addMenuItem(
'Sjablonen',
'/document-layouts',
['settings management'],
function(MenuItem $item) {
$item->setIcon('integration_instructions');
}
);
}

LibreOffice & Toolbox

After activating this module, you can go to the settings page and determine what driver you would like to use for converting files. Converting a Word template to other file types like PDF, PNG etc. will require the software LibreOffice:

  • Toolbox API (recommended for development). LibreOffice will be installed elsewhere (currently: https://toolbox.qlic.nl), see also: https://github.com/baaskoen/toolbox.
  • Local LibreOffice installation. You will be required to install the software and point the correct path to the soffice binary in config/templates.php (if you have published it). By default it will use your .env: LIBREOFFICE_BINARY='/Applications/LibreOffice.app/Contents/MacOS/soffice'

Usage

This module uses PHPWord to modify & parse Word files. Make sure to read their docs if you're not sure how to add something.

Setting up your resource

Every WordTemplate is linked to one of your resources, in order to retrieve its available tags and mapping for conversion, you need to add the following interface to your resource:

class TicketResource extends QoreResource implements ResourceExportsToWord

Next, you need to determine what tags will be available in the word template:

public function getWordTags(): array
{
return (new DefaultResourceWordTags($this, [
'ticket_name' => 'Ticket title',
'ticket_category' => 'Ticket category',
]))->toArray();
}

You can also just return a key => value pair array. The reason why a class is given here, is to also append your resource fields as tags.

Finally, you will need to map your given tags to values, and also do additional parsing if needed:

   public function exportToWord(WordExport $export): WordExport
{
/** @var Ticket $model */
$model = $export->getModel();

$export->setVariables([
'ticket_name' => $model->name,
'ticket_category' => ucfirst($model->category)
]);

$export->renderWordTags('ticket_name', 'ticket_category');

return $export;
}

Working with tables

When dealing with for example invoices or quotations, you often have repeatable rows inside tables like invoice lines.

In order to make this work, you should define some tags, and mark them as repeatable like this:

public function getWordTags(): array
{
return (new DefaultResourceWordTags($this, [
'table_1_row_number' => 'Row number for first table rows (repeated)',
'table_1_message_id' => 'Ticket message ID for first table rows (repeated)',
'table_1_message_description' => 'Ticket message description for first table rows (repeated)',
]))->toArray();
}
public function exportToWord(WordExport $export): WordExport
{
/** @var Ticket $model */
$model = $export->getModel();

$processor = $export->getProcessor();

if (in_array('table_1_row_number', $processor->getVariables())) {
$processor->cloneRow('table_1_row_number', $model->ticketMessages->count());

$counter = 1;

foreach ($model->ticketMessages as $message) {
$processor->setValue('table_1_row_number#' . $counter, $counter);
$processor->setValue('table_1_message_id#' . $counter, $message->id);
$processor->setValue('table_1_message_description#' . $counter, $message->description);
$counter++;
}
}

return $export;
}

Appending Images

You can also append images with the processor:

public function exportToWord(WordExport $export): WordExport
{
/** @var Ticket $model */
$model = $export->getModel();

$processor = $export->getProcessor();

$processor->setImageValue('signature', [
'path' => $model->getFirstMediaPath(),
'width' => 300,
'height' => 300
]);

//
}

Appending HTML

Similar to appending images, you can also append HTML:

public function exportToWord(WordExport $export): WordExport
{
/** @var Ticket $model */
$model = $export->getModel();

$processor = $export->getProcessor();

$this->processor->setHtmlBlockValue(
'my_html',
'<h1>Hello world</h1>'
);

//
}

Creating Global tags

The config/templates.php adds some tags that can be used in every Word template (like ${PAGE_BREAK}).

You can append your own Global tag here, by creating a class that extends GlobalTag:

<?php

class AddressBlock extends GlobalTag
{
public function description(): string
{
return __('My description');
}

public function tag(): string
{
return 'MY_TAG';
}

public function run(WordExport $export): void
{
while (in_array($this->tag(), $export->getProcessor()->getVariables())) {
$block = new TextRun();
$block->addText('Hello world');
$block->addTextBreak();

$export->getProcessor()->setComplexValue($this->tag(), $block);
}
}
}

Upgrade Guide

To upgrade this module:

composer update qore/templates-extended

If you need to upgrade migrations or Vue components:

php artisan vendor:publish --tag=qore.templates-extended.db --force
php artisan vendor:publish --tag=qore.templates-extended.frontend --force