I am working on modifying the order confirmation e-mail to make printable tags for the customer, using the notifiers to avoid editing order.php. (I had previously edited the order.php subject-creation code for admin e-mails to give more useful information on the order content.) My site is www.nyfaeriefest.com, still on v1.5.0, upgraded many times (from v1.3.small?) since 2008. The only relevant parts for this function are order.php and the observer/notifier system.

I believe I have correctly written the files for using the attribute output to create extra text blocks that customers can print out and bring for ready-made car and tent tags when they arrive at the festival; but there are a few items I am not certain about.

PHP Code:
<?php
/**
 * File contains the car & tent tag building code for confirmation e-mail
 *
 * //@package classes
 * @copyright Copyright 2017 Glenn J. Herbert (gjh42)
 * @copyright Copyright 2003-2007 Zen Cart Development Team
 * @license http://www.zen-cart.com/license/2_0.txt GNU Public License V2.0
 * @version $Id: order_tag_builder.php 2017-03-19 gjh42 $
 */
 
/*order.php line 795ff
          $sql_data_array = array('orders_id' => $zf_insert_id,
                                  ...
                                  'products_options' => $attributes_values->fields['products_options_name'],
                                  'products_options_values' => $this->products[$i]['attributes'][$j]['value'],
                                  ...
                                  'products_prid' => $this->products[$i]['id']
                                  );

          zen_db_perform(TABLE_ORDERS_PRODUCTS_ATTRIBUTES, $sql_data_array);
//called from order class (order.php) by
          $zco_notifier->notify('NOTIFY_ORDER_DURING_CREATE_ADDED_ATTRIBUTE_LINE_ITEM', $sql_data_array);
 */
class orderTagBuilder extends base {
  function 
__construct() {
    global 
$zco_notifier;
    
$zco_notifier->attach($this, array('NOTIFY_ORDER_DURING_CREATE_ADDED_ATTRIBUTE_LINE_ITEM','NOTIFY_ORDER_DURING_CREATE_ADD_PRODUCTS'));
    
//-------------------------to build tag info---------------------------------------to add tag text to content
  
}
/**
   * Update Method
   * Called by observed class when any of our notifiable events occur
   * @param object $class
   * @param string $eventID
*/
  
function update(&$class$eventID$paramsArray = array()) {
    if(!
is_array($tag_info)) global $tag_info = array();
    if(!isset(
$tag_qty)) global $tag_qty 0;
    if(
$eventID == 'NOTIFY_ORDER_DURING_CREATE_ADDED_ATTRIBUTE_LINE_ITEM') {
      if(
in_array($sql_data_array[products_prid, array[7,15,17,18,24,25],true) {//process tag info
        
if(!isset(tag_qty)) $tag_qty 0;
        if(!
is_array($tag_info)) $tag_info = array;
        if(
$sql_data_array[products_options] == 'Name') {
          
$tag_info[$tag_qty] .= '<br /><strong>-----------------------------------<br />' $sql_data_array[products_options_value] . '</strong><br />';
          
$tag_qty++;
        }
        if(
in_array($sql_data_array[products_options], array['Dates','Onsite phone','Vehicle','Zone preference']) {
          
$tag_info[$tag_qty] .= $sql_data_array[products_options] . ': <strong>' $sql_data_array[products_options_value] . '</strong><br />';
        }
      }
    }
  }
//end build tag info

/* called by notify end of product attributes:
    $zco_notifier->notify('NOTIFY_ORDER_DURING_CREATE_ADD_PRODUCTS', $custom_insertable_text);
/* START: ADD MY CUSTOM DETAILS
 * 1. calculate/prepare custom information to be added to this product entry in order-confirmation.
 * 2. Add that data to the $this->products_ordered_attributes variable, using this sort of format:
 *      $this->products_ordered_attributes .=  {INSERT CUSTOM INFORMATION HERE};
 */
  
if ($eventID == 'NOTIFY_ORDER_DURING_CREATE_ADD_PRODUCTS') {
    if(
is_array($tag_info)) {//add tags if they exist
      
foreach($tag_info[] as $tag_qty,$tag_text) {
        
$custom_insertable_text .= '<br /><br /><br />';
        if(
strpos($tag_text,'Vehicle') /== false) {//add car tag
          
$custom_insertable_text .= '
<br /><br /><br /><h2><strong>------------------------------------------<br />CAR TAG</strong></h2><br />' 
$tag_text '<br /><br /><br />';
        }
        
//add tent tag
        
$custom_insertable_text .= '
<h2><strong>------------------------------------------<br />TENT TAG</strong></h2><br />' 
$tag_text '<br /><br /><br />';
      }
    }
    
$this->products_ordered_attributes .=  $custom_insertable_text;//can i do this here?
    
unset $tag_info$tag_qty;//in case the customer wants to make another order
  
}//end add tag text to content
}
//eof
PHP Code:
<?php
/*
 * //@package autoloaders (In includes/auto_loaders)
 * @copyright Copyright 2017 Glenn J. Herbert (gjh42)
 * @license http://www.zen-cart.com/license/2_0.txt GNU Public License V2.0
 * @version $Id: config.orderTagBuilder.php 2017-03-19 gjh42 $
 */

$autoLoadConfig[10][] = array('autoType'=>'class',
                              
'loadFile'=>'observers/orderTagBuilder.php');
$autoLoadConfig[90][] = array('autoType'=>'classInstantiate',
                              
'className'=>'orderTagBuilder',
                              
'objectName'=>'orderTagBuilder');
/*Note: 10 has been chosen to cause the observer class to be loaded before the session is started. 
Note: 90 has been chosen as the offset since the observer needs to attach to the $SESSION['cart?order?'] class, which is instantiated at offset 80??. 
*/
//eof
The code will have to run the tag item code half a dozen separate times for each person in the order, so it needs to remember its previous state.
if(!is_array($tag_info)) global $tag_info = array();
if(!isset($tag_qty)) global $tag_qty = 0;
is intended to do this; is this a good way? Any drawbacks?

Will
$zco_notifier->attach($this, array('NOTIFY_ORDER_...
correctly connect to order.php? This the first time I have actually tried the observer/notifier system. I would have done so in previous mods, but what I needed to do previously required changing stock behavior, not adding new behavior.

Order.php has notes about using $custom_insertable_text to return such info, but there is no active code in place to append it without editing order.php. I would have no issue with doing that as I have already done so for another purpose, but if it can be avoided, so much the better. Can I update $this->products_ordered_attributes in the observer, or do I have to go back to order.php to do it?

I will get a testbed set up to try this out, but can't do it right now, so am hoping for some expert guidance in the meantime.