System brix:papilio

For the most up-to-date documentation, please visit

brix:papilio is built on a LAMP-stack and uses PDFlib+PDI as its primary rendering engine.


  • PHP 7.x
  • MySQL 5.5 or higher (with ONLY_FULL_GROUP_BY disabled)
  • PDFlib+PDI 9.x
  • PHP Modules: rewrite, php-gd, php-pear, php-imagick, php-xml, php-zip, php-mbstring, php-curl, php-soap, php-imagick, php-ldap (optional)
  • Tools: graphviz, ghostscript, exiftool


Create once, use everywhere. This credo is the basis for most objects and their relations. For example, the client has a logo, so there's exactly one logo element, which then gets used on all templates that should have a logo. When you have to update the logo, you only do that once, and it's updated everywhere. The same goes for fonts, colors, text styles, relations and so on.

Furthermore, the system is inherently multi-lingual and multi-color-spaced, i.e. a slogan will be different depending on the language, but it is still just one element. Or the CMYK logo is usually a different vector file than the RGB one, but it is also just one element.


A template is simply an aggregation of elements that get placed at certain coordinates on a canvas. By itself it doesn't do much, except define the properties of the canvas and how a user can order it (such as output format, delivery and controlling).


An element is an isolateable component of your layout. It could be a logo, an address block or a heading. All of these get broken out into their own element, so they can be reused and reassembled later on. An element has three fundamental properties:

  • Input Type: What the user sees, e.g. a text field or a dropdown.
  • Output Type: What gets rendered onto the PDF, e.g. text or an image.
  • Style: Defines the basic behaviour of the element, e.g. its fit method or text style.

Text Groups

A special kind of element that allows you to combine multiple elements into a single block of text. For example, an address block consists of multiple input fields (name, street, ZIP/city, phone, mobile etc.), but should be rendered into one block of text like:

ZIP City
T: Phone, M: Mobile

But it is more than just an aggregator, it can also assemble the texts in a sensible manner. In our example, the user might not want to publish his mobile phone number and leaves the input field empty. The text group detects this and also removes the , M: that came before the mobile, as it is no longer needed and hence renders to:

ZIP City
T: Phone

In the UI, this is represented with lines - when the center element disappears or is empty, the entire line it not rendered:

Text Group UI


Probably the most powerful feature of brix:papilio - it allows you to dynamically update the layout, update dropdowns or make entire sections of your layout disappear.

Value Relations

Another motivation to use relations is consistency. For example some subtitles may not make sense depending on the title you chose. For example, the title "Merry Christmas" may be combined with the subtitle "and a happy new year", but not with "may the force be with you". To ensure this, you can simply create a value relation title->subtitle to restrict what's available in the second dropdown.

Visibility Relations

If you have several variants of a layout, you don't have to create a new template for each variant - you can just use relations. For example, your flyer may have one or two contacts on it, and the layout changes based on the space that is available as a consequence. Since a picture says more than a thousand words, here's an example: Relations example This is a single template, with the options "show portrait photo" and "second address" toggled on/off. Note how it doesn't just make elements disappear - in the last one it rearranges the layout to make space for the two photos.


The application largely follows the MVC pattern:

  • Model with ReadBean ORM and Model_-Classes
  • View rendered by Smarty and uses jQuery
  • Controller triggered by a dynamic dispatcher


One notable exception to this are the jFormer forms, which are created in the controllers themselves.

Access Control

In order to protect certain areas from unauthorized access, ACLs are used. There are quite a few predefined and named ACLs, which should cover most use cases. But you can also add custom ACLs for special cases.

ROLE create Orders approve Orders editUser Orders layout Orders print Orders edit Users switch User edit Editable Elements edit Templates edit Clients edit Divisions edit Labels view System view Statistics edit Visible Elements edit User Groups translate Orders
SUPERADMIN 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
ADMIN 1 1 1 0 0 1 1 1 0 0 1 1 0 1 1 1 0
CONTROLLER 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
USER 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
PRINT_OPERATOR 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
GRAPHIC_ARTIST 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
LAYOUTER 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0
GROUP_ADMIN 1 1 1 0 0 1 1 1 0 0 0 1 0 1 0 0 0


Additionally, brix:papilio is a multi-tennant system. This means that all top-level objects also store their client ID along with the other properties. This filter is applied throughout the system in order to separate the tennants. Only superadmins and users with the "switch client" flag (this may be useful for print operators) are able to switch clients.


Orders use the following state machine (note that an order can have multiple states):