From bc6d4096b8b98981e641740c6442560bbdc89551 Mon Sep 17 00:00:00 2001
From: Robert Allerstorfer <roball@405360.no-reply.drupal.org>
Date: Sat, 24 Oct 2015 11:06:46 +0200
Subject: [PATCH] #2237193: Allow multiple PDF templates

---
 modules/commerce_billy_pdf/README.txt              | 19 +++++++-
 .../commerce_billy_pdf.admin.inc                   | 20 ++++++---
 .../commerce_billy_pdf/commerce_billy_pdf.api.php  | 52 ++++++++++++++++++++++
 .../commerce_billy_pdf/commerce_billy_pdf.install  | 35 +++++++++++++--
 .../commerce_billy_pdf/commerce_billy_pdf.module   | 35 +++++++++++++--
 5 files changed, 146 insertions(+), 15 deletions(-)
 create mode 100644 modules/commerce_billy_pdf/commerce_billy_pdf.api.php

diff --git a/modules/commerce_billy_pdf/README.txt b/modules/commerce_billy_pdf/README.txt
index cedbc40..9c75eb4 100644
--- a/modules/commerce_billy_pdf/README.txt
+++ b/modules/commerce_billy_pdf/README.txt
@@ -27,9 +27,26 @@ To check if everything is at the right place, you should find
 
 Administration
 **************
-Got to: Store > Configuration > Billy invoice settings > PDF settings
+Go to: Store > Configuration > Billy invoice settings > PDF
         (/admin/commerce/config/billy-invoice/pdf)
 
+Hooks
+*****
+
+Advanced users may want to take advantage of the hooks provided by the Commerce
+Billy PDF module. There are two hooks intended to be used together in your own
+custom module, to allow multiple PDF templates. Per default (without
+implementing these hooks by other modules), only one PDF template (the default
+one) can be configured (at the tab "Store > Configuration > Billy invoice
+settings > PDF"). By implementing the provided hooks, you can add one or more
+additional sub tab(s) to that tab, each representing a custom PDF template.
+Which of the custom PDF templates should be applied to a given order can be
+specified based on properties of the $order object, for example by the type of
+a line item within the order. 
+
+See inside the file "commerce_billy_pdf.api.php" how to implement the provided
+hooks.
+
 
 Troubles
 ********
diff --git a/modules/commerce_billy_pdf/commerce_billy_pdf.admin.inc b/modules/commerce_billy_pdf/commerce_billy_pdf.admin.inc
index 0aabb85..28baedb 100644
--- a/modules/commerce_billy_pdf/commerce_billy_pdf.admin.inc
+++ b/modules/commerce_billy_pdf/commerce_billy_pdf.admin.inc
@@ -7,10 +7,14 @@
 
 /**
  * Admin settings form for invoice pdf.
+ *
+ * @param string $template_name
+ *   The name of the PDF template that may have been defined by other modules.
+ *   Defaults to "default" if no other module has defined a PDF template.
  */
-function commerce_billy_pdf_admin_form($form, &$form_state) {
+function commerce_billy_pdf_admin_form($form, &$form_state, $template_name) {
 
-  $settings = variable_get('commerce_billy_pdf_text_settings', array());
+  $settings = variable_get('commerce_billy_pdf_text_settings_' . $template_name, array());
 
   $form['commerce_billy_pdf_settings'] = array(
     '#tree' => TRUE,
@@ -47,12 +51,12 @@ function commerce_billy_pdf_admin_form($form, &$form_state) {
   $form['commerce_billy_pdf_logo'] = array(
     '#type' => 'textfield',
     '#title' => t('Logo'),
-    '#default_value' => variable_get('commerce_billy_pdf_logo', 'misc/druplicon.png'),
+    '#default_value' => variable_get('commerce_billy_pdf_logo_' . $template_name, 'misc/druplicon.png'),
     '#required' => TRUE,
     '#description' => t('Path to invoice logo.'),
   );
 
-  $css_files = variable_get('commerce_billy_pdf_css_files', array(drupal_get_path('module', 'commerce_billy_pdf') . '/css/pdf.css'));
+  $css_files = variable_get('commerce_billy_pdf_css_files_' . $template_name, array(drupal_get_path('module', 'commerce_billy_pdf') . '/css/pdf.css'));
   $default_value = "";
   foreach ($css_files as $file) {
     $default_value .= $file . "\n";
@@ -66,6 +70,7 @@ function commerce_billy_pdf_admin_form($form, &$form_state) {
   );
 
   $form = system_settings_form($form);
+  $form_state['commerce_billy_pdf_template_name'] = $template_name;
   // Use custom submit handler.
   $form['#submit'] = array('commerce_billy_pdf_admin_form_submit');
   return $form;
@@ -76,10 +81,11 @@ function commerce_billy_pdf_admin_form($form, &$form_state) {
  */
 function commerce_billy_pdf_admin_form_submit($form, $form_state) {
   $settings = array();
+  $template_name = $form_state['commerce_billy_pdf_template_name'];
   foreach ($form_state['values']['commerce_billy_pdf_settings'] as $key => $value) {
     $settings[$key] = $value;
   }
-  variable_set('commerce_billy_pdf_text_settings', $settings);
+  variable_set('commerce_billy_pdf_text_settings_' . $template_name, $settings);
 
   $css_files = array();
   foreach (explode("\n", $form_state['values']['commerce_billy_pdf_css_files']) as $file) {
@@ -88,8 +94,8 @@ function commerce_billy_pdf_admin_form_submit($form, $form_state) {
       $css_files[] = $file;
     }
   }
-  variable_set('commerce_billy_pdf_css_files', $css_files);
+  variable_set('commerce_billy_pdf_css_files_' . $template_name, $css_files);
 
-  variable_set('commerce_billy_pdf_logo', $form_state['values']['commerce_billy_pdf_logo']);
+  variable_set('commerce_billy_pdf_logo_' . $template_name, $form_state['values']['commerce_billy_pdf_logo']);
   drupal_set_message(t('The configuration options have been saved.'));
 }
diff --git a/modules/commerce_billy_pdf/commerce_billy_pdf.api.php b/modules/commerce_billy_pdf/commerce_billy_pdf.api.php
new file mode 100644
index 0000000..bae9918
--- /dev/null
+++ b/modules/commerce_billy_pdf/commerce_billy_pdf.api.php
@@ -0,0 +1,52 @@
+<?php
+
+/**
+ * @file
+ * Hooks provided by the Commerce Billy PDF module.
+ */
+
+/**
+ * Defines a custom PDF template.
+ *
+ * @return array
+ *   An array of PDF template info arrays keyed by the 'name' string. PDF
+ *   template info arrays are associative arrays containing the following keys:
+ *   - name: string containing the machine-name of the PDF template; should
+ *     only include lowercase letters, numbers, -, and _. Must differ from
+ *     'default'.
+ *   - title: the translatable name of the PDF template, used in the
+ *     administrative interface.
+ */
+function hook_commerce_billy_pdf_templates() {
+  $templates = array();
+
+  $templates['my_template'] = array(
+    'name' => 'my_template',
+    'title' => t('My template'),
+  );
+
+  return $templates;
+}
+
+/**
+ * Specifies the PDF template name to be used for a given order.
+ *
+ * @param object $order
+ *   The order the PDF invoice should be generated for.
+ *
+ * @return string
+ *   The PDF template name string defined in
+ *   hook_commerce_billy_pdf_templates().
+ */
+function hook_commerce_billy_pdf_get_order_template($order) {
+  $template_name = 'default';
+
+  $line_item_id_0 = $order->commerce_line_items['und'][0]['line_item_id'];
+  $line_item_0 = commerce_line_item_load($line_item_id_0);
+  if ($line_item_0->type == 'my_line_item_type') {
+    // We checked for the type of the order's first line item.
+    $template_name = 'my_template';
+  }
+
+  return $template_name;
+}
diff --git a/modules/commerce_billy_pdf/commerce_billy_pdf.install b/modules/commerce_billy_pdf/commerce_billy_pdf.install
index e18642f..94a004e 100644
--- a/modules/commerce_billy_pdf/commerce_billy_pdf.install
+++ b/modules/commerce_billy_pdf/commerce_billy_pdf.install
@@ -10,21 +10,50 @@
  */
 function commerce_billy_pdf_enable() {
   // Init some defaults.
-  $settings = array(
+  $commerce_billy_pdf_text_settings = array(
     'invoice_header' => 'My company<br/>Street 123, State<br/>United States',
     'invoice_location' => 'Location',
     'invoice_text' => '',
     'invoice_footer' => 'My company, Street 123, State, United States',
   );
-  variable_set('commerce_billy_pdf_text_settings', $settings);
+  variable_set(
+    'commerce_billy_pdf_text_settings_default',
+    variable_get('commerce_billy_pdf_text_settings_default', $commerce_billy_pdf_text_settings)
+  );
 }
 
-
 /**
  * Implements hook_uninstall().
  */
 function commerce_billy_pdf_uninstall() {
+  _commerce_billy_pdf_delete_variables();
+}
+
+/**
+ * Helper function to delete all variables that we might have set.
+ */
+function _commerce_billy_pdf_delete_variables() {
+  global $conf;
+  $variables = array();
+  foreach (array_keys($conf) as $key) {
+    if (preg_match('/^commerce_billy_pdf_.+/', $key)) {
+      array_push($variables, $key);
+    }
+  }
+  foreach ($variables as $variable) {
+    variable_del($variable);
+  }
+}
+
+/**
+ * Rename all default variables set by 7.x-1.0 or earlier.
+ */
+function commerce_billy_pdf_update_7100() {
+  variable_set('commerce_billy_pdf_text_settings_default', variable_get('commerce_billy_pdf_text_settings'));
   variable_del('commerce_billy_pdf_text_settings');
+  variable_set('commerce_billy_pdf_logo_default', variable_get('commerce_billy_pdf_logo'));
   variable_del('commerce_billy_pdf_logo');
+  variable_set('commerce_billy_pdf_css_files_default', variable_get('commerce_billy_pdf_css_files'));
   variable_del('commerce_billy_pdf_css_files');
+  return array();
 }
diff --git a/modules/commerce_billy_pdf/commerce_billy_pdf.module b/modules/commerce_billy_pdf/commerce_billy_pdf.module
index bb9a13d..92f84b2 100644
--- a/modules/commerce_billy_pdf/commerce_billy_pdf.module
+++ b/modules/commerce_billy_pdf/commerce_billy_pdf.module
@@ -20,11 +20,31 @@ function commerce_billy_pdf_menu() {
   $items['admin/commerce/config/billy-invoice/pdf'] = array(
     'title' => 'PDF',
     'page callback' => 'drupal_get_form',
-    'page arguments' => array('commerce_billy_pdf_admin_form'),
+    'page arguments' => array('commerce_billy_pdf_admin_form', 'default'),
     'access arguments' => array('configure order settings'),
     'type' => MENU_LOCAL_TASK,
     'file' => 'commerce_billy_pdf.admin.inc',
   );
+  $items['admin/commerce/config/billy-invoice/pdf/default'] = array(
+    'title' => 'Default',
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+    'weight' => -10,
+  );
+
+  // Allow other modules to define PDF templates:
+  $templates = module_invoke_all('commerce_billy_pdf_templates');
+  // Create a menu item for each template:
+  foreach ($templates as $template) {
+    $items['admin/commerce/config/billy-invoice/pdf/' . $template['name']] = array(
+      'title' => $template['title'],
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('commerce_billy_pdf_admin_form', 5),
+      'access arguments' => array('configure order settings'),
+      'type' => MENU_LOCAL_TASK,
+      'file' => 'commerce_billy_pdf.admin.inc',
+    );
+  }
+
   $items['admin/commerce/orders/%commerce_order/pdf-invoice'] = array(
     'title' => 'Invoice (PDF)',
     'page callback' => 'commerce_billy_pdf',
@@ -35,6 +55,7 @@ function commerce_billy_pdf_menu() {
     'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
     'weight' => 10,
   );
+
   return $items;
 }
 
@@ -148,13 +169,17 @@ function commerce_billy_pdf_html($orders) {
     $orders = array($orders);
   }
   foreach ($orders as $order) {
+    // Allow other modules to specify a template name for a given order:
+    $template_names = module_invoke_all('commerce_billy_pdf_get_order_template', $order);
+    $template_name = empty($template_names) ? 'default' : reset($template_names);
+
     $vars['viewed_orders'][] = entity_view('commerce_order', array($order->order_id => $order), 'pdf', NULL, TRUE);
     // Add a credit memo.
     if ($order->status == 'canceled') {
       $vars['viewed_orders'][] = entity_view('commerce_order', array($order->order_id => $order), 'canceled', NULL, TRUE);
     }
   }
-  $css_files = variable_get('commerce_billy_pdf_css_files', array(drupal_get_path('module', 'commerce_billy_pdf') . '/css/pdf.css'));
+  $css_files = variable_get('commerce_billy_pdf_css_files_' . $template_name, array(drupal_get_path('module', 'commerce_billy_pdf') . '/css/pdf.css'));
   $vars['inline_css'] = "";
   foreach ($css_files as $file) {
     $vars['inline_css'] .= file_get_contents($file);
@@ -168,7 +193,9 @@ function commerce_billy_pdf_html($orders) {
  */
 function commerce_billy_pdf_commerce_order_view($order, $view_mode) {
   // Add content variables for the PDF generation.
-  $settings = variable_get('commerce_billy_pdf_text_settings', array());
+  $template_names = module_invoke_all('commerce_billy_pdf_get_order_template', $order);
+  $template_name = empty($template_names) ? 'default' : reset($template_names);
+  $settings = variable_get('commerce_billy_pdf_text_settings_' . $template_name, array());
   $custom_date_format = !empty($settings['invoice_date_format']) ? $settings['invoice_date_format'] : 'Y-m-d';
   if ($view_mode == "pdf" || $view_mode == 'canceled') {
     $order->content['invoice_footer'] = array(
@@ -198,7 +225,7 @@ function commerce_billy_pdf_commerce_order_view($order, $view_mode) {
       '#markup' => t('Order No.: @id', array('@id' => $order->order_id)),
     );
     $order->content['invoice_logo'] = array(
-      '#value' => variable_get('commerce_billy_pdf_logo', 'misc/druplicon.png'),
+      '#value' => variable_get('commerce_billy_pdf_logo_' . $template_name, 'misc/druplicon.png'),
     );
   }
 }
-- 
1.9.5

