Using ctools plugins to create different pdf layouts

2 minutters læsning

At Vejle Idrætshøjskole we invite the community to participate in our some of our lectures. Of course we list the lectures on our lecture webpage. The list is easily created using a custom content type and some views.

However, I also wanted to make a version which prints nicely. A pdf is still the best tool to make a layout you can depend on. So I created a layout for my lectures using TCPDF. After a while I grew tired of the layout, and created a new layout still using TCPDF. But in doing so I was thinking: maybe other people could use my layouts, or maybe one day, I will like the old layout again. Therefore I decided that the content administrator should be able to choose between the different layouts I have created.

Enter ctools plugins system

I tried creating the layout utilizing the ctools plugin system. First I needed to make my module aware of the plugins:

 * Implements hook_ctools_plugin_type().
 * Has plenty options. See ctools/help/plugins-creating.html
function vih_lectures_pdf_ctools_plugin_type() {
  $plugins['layouts'] = array(
    'use hooks' => TRUE,

  return $plugins;

 * Implements hook_ctools_plugin_directory().
function vih_lectures_pdf_ctools_plugin_directory($owner, $plugin) {
  if (($owner == 'vih_lectures_pdf') && ($plugin == 'layouts')) {
    return 'plugins/' . $plugin;

Now, the system knows, that I am utilizing the ctools plugin system. Then I put my different layouts into different folders using the same naming convention, so I could use it in my module function. The function can both output one single lecture (a custom content type), but also a collection of lectures (created by an entity reference field on another custom content type).

function vih_lectures_pdf_booklet($lecture) {
  require_once libraries_get_path('tcpdf') . '/tcpdf.php';
  global $base_url;
  $events = array();
  $layout = variable_get('vih_lectures_pdf_layout', 'portrait');
  ctools_include('Layout', 'vih_lectures_pdf', 'plugins/layouts/' . $layout);
  $class = 'VIH_Lectures_Pdf_' . ucfirst($layout);

  if ($lecture->type == 'vih_lectures') {
    foreach ($lecture->field_lectures['und'] as $key => $value) {
      $node = node_load($value['target_id']);
      if ($node) {
        $events[] = $node;
  } else {
    $events[] = $lecture;

  $pdf = new $class($events);
  $pdf->setAuthor(variable_get('site_name', "Vejle Idrætshøjskole"));
  if ($logo = file_load(variable_get('vih_lectures_pdf_logo', ''))) {

  if ($lecture->type == 'vih_lectures') {
    $file = drupal_realpath($lecture->field_picture['da'][0]['uri']);


You can basically see the rest in the module file, which is the glue in the system. There I also created a simple settings pages (which could be hugely improved to look like e.g. the apperance page, so one could see the screenshot of the layout).

You can see the entire source code for my PDFs for the lectures at github.

How do you create your different layouts when using pdf’s without overriding your previous layout on each iteration?