Jump to content
  • Checkout
  • Login
  • Get in touch

osCommerce

The e-commerce.

Shipping Add-On Update (Canada)


Dnj1964

Recommended Posts

Trying to update a Canada post shipping add-on https://apps.oscommerce.com/7hk8T&canada-post-rest-rate-service-oscommerce

 

Warning: constant(): Couldn't find constant CANADA_POST_Array in /includes/modules/shipping/canadapost.php on line 508

 

function get_multioption_canadapost_xml($values) 
{
	 if (tep_not_null($values)) {
		 $values_array = explode(',', $values);
		 foreach ($values_array as $key => $_method) {
		   if ($_method == '--none--') {
			 $method = $_method;
		   } else {
			 $method = constant('CANADA_POST_' .get_canada_post_service_code($_method));
		   }
		   $readable_values_array[] = $method;
		 }
		 $readable_values = implode(', ', $readable_values_array);
		 return $readable_values;
	 } else {
	   return '';
	 }
}
function get_canada_post_service_code($key)
{
	$km = str_replace('.','_',trim($key));
	 if(substr($km,0,2)=='D_')
		$km = 'DOM_'.substr($km,2);
	 else if(substr($km,0,2)=='U_')
		$km = 'USA_'.substr($km,2);
	 else if(substr($km,0,2)=='I_')
		$km = 'INT_'.substr($km,2);
	return $km;
}
  
function canadapost_cfg_select_multioption($select_array, $key_value, $key = '') 
{
	for ($i=0; $i<sizeof($select_array); $i++) {
	  $name = (($key) ? 'configuration[' . $key . '][]' : 'configuration_value');
	  $string .= '<br><input type="checkbox" name="' . $name . '" value="' . $select_array[$i] . '"';
	  $key_values = explode( ", ", $key_value);
	  if ( in_array($select_array[$i], $key_values) ) $string .= ' CHECKED';
	  $string .= '> ' . constant('CANADA_POST_' . get_canada_post_service_code($select_array[$i]));
	} 
	$string .= '<input type="hidden" name="' . $name . '" value="--none--">';
	return $string;
}	
?>

Read a post from 2008 where the same function was used.

Solution was:

Quote

SOLUTION. I just did an install of this module and ran into the same issue. The problem is that the code is expecting a definition for --none-- and there isnt any.

 

If you add this definition to the language file you will no longer get these warnings.

 

Goto: /includes/languages/english/modules/shipping/upsxml.php

Add: define('UPSXML_--none--', 'None');

So tried adding define('CANADA_POST_--none--', 'None'); to /includes/languages/english/modules/shipping/canadapost.php

Thinking that the warning would also disappear.

No such luck.

 

 

Plus just started testing and now get:

Shipping is currently not available for the selected shipping address. Please select or create a new shipping address to use with your purchase.

 

 

 

 

 

Link to comment
Share on other sites

Warning gone.

 

But no shipping. Shipping set to Canada only, and testing with a Canadian address

 

Shipping is currently not available for the selected shipping address. Please select or create a new shipping address to use with your purchase.

Link to comment
Share on other sites

What am I Missing....???????

Updated the deprecated $HTTP_POST_VARS   to   $_POST      &      $HTTP_GET_VARS   to   $_GET

Updated 'FILENAME.... .    to    'actual-filename.php'

Updates DIR_WS_INCLUDES   to   'includes/.....     or DIR_WS_IMAGES   to   'images/.....

/admin/modules.php

<?php
/*
  $Id$

  osCommerce, Open Source E-Commerce Solutions
  http://www.oscommerce.com

  Copyright (c) 2010 osCommerce

  Released under the GNU General Public License
*/

  require('includes/application_top.php');

  $set = (isset($_GET['set']) ? $_GET['set'] : '');

  $modules = $cfgModules->getAll();

  if (empty($set) || !$cfgModules->exists($set)) {
    $set = $modules[0]['code'];
  }

  $module_type = $cfgModules->get($set, 'code');
  $module_directory = $cfgModules->get($set, 'directory');
  $module_language_directory = $cfgModules->get($set, 'language_directory');
  $module_key = $cfgModules->get($set, 'key');;
  define('HEADING_TITLE', $cfgModules->get($set, 'title'));
  $template_integration = $cfgModules->get($set, 'template_integration');

  $action = (isset($_GET['action']) ? $_GET['action'] : '');

  if (tep_not_null($action)) {
    switch ($action) {
      case 'save':
        reset($_POST['configuration']);
        while (list($key, $value) = each($_POST['configuration'])) {
		  if (is_array($value) ) {
             $value = implode( ", ", $value);
		     $value = preg_replace ("/, --none--/", "", $value);
		  }
		  tep_db_query("update " . TABLE_CONFIGURATION . " set configuration_value = '" . $value . "' where configuration_key = '" . $key . "'");
        }
        tep_redirect(tep_href_link('modules.php', 'set=' . $set . '&module=' . $_GET['module']));
        break;
      case 'install':
      case 'remove':
        $file_extension = substr($PHP_SELF, strrpos($PHP_SELF, '.'));
        $class = basename($_GET['module']);
        if (file_exists($module_directory . $class . $file_extension)) {
          include($module_directory . $class . $file_extension);
          $module = new $class;
          if ($action == 'install') {
            $module->install();

            $modules_installed = explode(';', constant($module_key));
            $modules_installed[] = $class . $file_extension;
            tep_db_query("update " . TABLE_CONFIGURATION . " set configuration_value = '" . implode(';', $modules_installed) . "' where configuration_key = '" . $module_key . "'");
            tep_redirect(tep_href_link('modules.php', 'set=' . $set . '&module=' . $class));
          } elseif ($action == 'remove') {
            $module->remove();

            $modules_installed = explode(';', constant($module_key));
            unset($modules_installed[array_search($class . $file_extension, $modules_installed)]);
            tep_db_query("update " . TABLE_CONFIGURATION . " set configuration_value = '" . implode(';', $modules_installed) . "' where configuration_key = '" . $module_key . "'");
            tep_redirect(tep_href_link('modules.php', 'set=' . $set));
          }
        }
        tep_redirect(tep_href_link('modules.php', 'set=' . $set . '&module=' . $class));
        break;
    }
  }

  require('includes/template_top.php');

  $modules_installed = (defined($module_key) ? explode(';', constant($module_key)) : array());
  $new_modules_counter = 0;

  $file_extension = substr($PHP_SELF, strrpos($PHP_SELF, '.'));
  $directory_array = array();
  if ($dir = @dir($module_directory)) {
    while ($file = $dir->read()) {
      if (!is_dir($module_directory . $file)) {
        if (substr($file, strrpos($file, '.')) == $file_extension) {
          if (isset($_GET['list']) && ($_GET['list'] = 'new')) {
            if (!in_array($file, $modules_installed)) {
              $directory_array[] = $file;
            }
          } else {
            if (in_array($file, $modules_installed)) {
              $directory_array[] = $file;
            } else {
              $new_modules_counter++;
            }
          }
        }
      }
    }
    sort($directory_array);
    $dir->close();
  }
?>

    <table border="0" width="100%" cellspacing="0" cellpadding="2">
      <tr>
        <td width="100%"><table border="0" width="100%" cellspacing="0" cellpadding="0">
          <tr>
            <td class="pageHeading"><?php echo HEADING_TITLE; ?></td>
            <td class="pageHeading" align="right"><?php echo tep_draw_separator('pixel_trans.gif', HEADING_IMAGE_WIDTH, HEADING_IMAGE_HEIGHT); ?></td>
<?php
  if (isset($_GET['list'])) {
    echo '            <td class="smallText" align="right">' . tep_draw_button(IMAGE_BACK, 'triangle-1-w', tep_href_link('modules.php', 'set=' . $set)) . '</td>';
  } else {
    echo '            <td class="smallText" align="right">' . tep_draw_button(IMAGE_MODULE_INSTALL . ' (' . $new_modules_counter . ')', 'plus', tep_href_link('modules.php', 'set=' . $set . '&list=new')) . '</td>';
  }
?>
          </tr>
        </table></td>
      </tr>
      <tr>
        <td><table border="0" width="100%" cellspacing="0" cellpadding="0">
          <tr>
            <td valign="top"><table border="0" width="100%" cellspacing="0" cellpadding="2">
              <tr class="dataTableHeadingRow">
                <td class="dataTableHeadingContent"><?php echo TABLE_HEADING_MODULES; ?></td>
                <td class="dataTableHeadingContent" align="right"><?php echo TABLE_HEADING_SORT_ORDER; ?></td>
                <td class="dataTableHeadingContent" align="right"><?php echo TABLE_HEADING_ACTION; ?>&nbsp;</td>
              </tr>
<?php
  $installed_modules = array();
  for ($i=0, $n=sizeof($directory_array); $i<$n; $i++) {
    $file = $directory_array[$i];

    include($module_language_directory . $language . '/modules/' . $module_type . '/' . $file);
    include($module_directory . $file);

    $class = substr($file, 0, strrpos($file, '.'));
    if (tep_class_exists($class)) {
      $module = new $class;
      if ($module->check() > 0) {
        if (($module->sort_order > 0) && !isset($installed_modules[$module->sort_order])) {
          $installed_modules[$module->sort_order] = $file;
        } else {
          $installed_modules[] = $file;
        }
      }

      if ((!isset($_GET['module']) || (isset($_GET['module']) && ($_GET['module'] == $class))) && !isset($mInfo)) {
        $module_info = array('code' => $module->code,
                             'title' => $module->title,
                             'description' => $module->description,
                             'status' => $module->check(),
                             'signature' => (isset($module->signature) ? $module->signature : null),
                             'api_version' => (isset($module->api_version) ? $module->api_version : null));

        $module_keys = $module->keys();

        $keys_extra = array();
        for ($j=0, $k=sizeof($module_keys); $j<$k; $j++) {
          $key_value_query = tep_db_query("select configuration_title, configuration_value, configuration_description, use_function, set_function from " . TABLE_CONFIGURATION . " where configuration_key = '" . $module_keys[$j] . "'");
          $key_value = tep_db_fetch_array($key_value_query);

          $keys_extra[$module_keys[$j]]['title'] = $key_value['configuration_title'];
          $keys_extra[$module_keys[$j]]['value'] = $key_value['configuration_value'];
          $keys_extra[$module_keys[$j]]['description'] = $key_value['configuration_description'];
          $keys_extra[$module_keys[$j]]['use_function'] = $key_value['use_function'];
          $keys_extra[$module_keys[$j]]['set_function'] = $key_value['set_function'];
        }

        $module_info['keys'] = $keys_extra;

        $mInfo = new objectInfo($module_info);
      }

      if (isset($mInfo) && is_object($mInfo) && ($class == $mInfo->code) ) {
        if ($module->check() > 0) {
          echo '              <tr id="defaultSelected" class="dataTableRowSelected" onmouseover="rowOverEffect(this)" onmouseout="rowOutEffect(this)" onclick="document.location.href=\'' . tep_href_link('modules.php', 'set=' . $set . '&module=' . $class . '&action=edit') . '\'">' . "\n";
        } else {
          echo '              <tr id="defaultSelected" class="dataTableRowSelected" onmouseover="rowOverEffect(this)" onmouseout="rowOutEffect(this)">' . "\n";
        }
      } else {
        echo '              <tr class="dataTableRow" onmouseover="rowOverEffect(this)" onmouseout="rowOutEffect(this)" onclick="document.location.href=\'' . tep_href_link('modules.php', 'set=' . $set . (isset($_GET['list']) ? '&list=new' : '') . '&module=' . $class) . '\'">' . "\n";
      }
?>
                <td class="dataTableContent"><?php echo $module->title; ?></td>
                <td class="dataTableContent" align="right"><?php if (is_numeric($module->sort_order)) echo $module->sort_order; ?></td>
                <td class="dataTableContent" align="right"><?php if (isset($mInfo) && is_object($mInfo) && ($class == $mInfo->code) ) { echo tep_image('images/icon_arrow_right.gif'); } else { echo '<a href="' . tep_href_link('modules.php', 'set=' . $set . (isset($_GET['list']) ? '&list=new' : '') . '&module=' . $class) . '">' . tep_image('images/icon_info.gif', IMAGE_ICON_INFO) . '</a>'; } ?>&nbsp;</td>
              </tr>
<?php
    }
  }

  if (!isset($_GET['list'])) {
    ksort($installed_modules);
    $check_query = tep_db_query("select configuration_value from " . TABLE_CONFIGURATION . " where configuration_key = '" . $module_key . "'");
    if (tep_db_num_rows($check_query)) {
      $check = tep_db_fetch_array($check_query);
      if ($check['configuration_value'] != implode(';', $installed_modules)) {
        tep_db_query("update " . TABLE_CONFIGURATION . " set configuration_value = '" . implode(';', $installed_modules) . "', last_modified = now() where configuration_key = '" . $module_key . "'");
      }
    } else {
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Installed Modules', '" . $module_key . "', '" . implode(';', $installed_modules) . "', 'This is automatically updated. No need to edit.', '6', '0', now())");
    }

    if ($template_integration == true) {
      $check_query = tep_db_query("select configuration_value from " . TABLE_CONFIGURATION . " where configuration_key = 'TEMPLATE_BLOCK_GROUPS'");
      if (tep_db_num_rows($check_query)) {
        $check = tep_db_fetch_array($check_query);
        $tbgroups_array = explode(';', $check['configuration_value']);
        if (!in_array($module_type, $tbgroups_array)) {
          $tbgroups_array[] = $module_type;
          sort($tbgroups_array);
          tep_db_query("update " . TABLE_CONFIGURATION . " set configuration_value = '" . implode(';', $tbgroups_array) . "', last_modified = now() where configuration_key = 'TEMPLATE_BLOCK_GROUPS'");
        }
      } else {
        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Installed Template Block Groups', 'TEMPLATE_BLOCK_GROUPS', '" . $module_type . "', 'This is automatically updated. No need to edit.', '6', '0', now())");
      }
    }
  }
?>
              <tr>
                <td colspan="3" class="smallText"><?php echo TEXT_MODULE_DIRECTORY . ' ' . $module_directory; ?></td>
              </tr>
            </table></td>
<?php
  $heading = array();
  $contents = array();

  switch ($action) {
    case 'edit':
      $keys = '';
      reset($mInfo->keys);
      while (list($key, $value) = each($mInfo->keys)) {
        $keys .= '<strong>' . $value['title'] . '</strong><br />' . $value['description'] . '<br />';

        if ($value['set_function']) {
          eval('$keys .= ' . $value['set_function'] . "'" . $value['value'] . "', '" . $key . "');");
        } else {
          $keys .= tep_draw_input_field('configuration[' . $key . ']', $value['value']);
        }
        $keys .= '<br /><br />';
      }
      $keys = substr($keys, 0, strrpos($keys, '<br /><br />'));

      $heading[] = array('text' => '<strong>' . $mInfo->title . '</strong>');

      $contents = array('form' => tep_draw_form('modules', 'modules.php', 'set=' . $set . '&module=' . $_GET['module'] . '&action=save'));
      $contents[] = array('text' => $keys);
      $contents[] = array('align' => 'center', 'text' => '<br />' . tep_draw_button(IMAGE_SAVE, 'disk', null, 'primary') . tep_draw_button(IMAGE_CANCEL, 'close', tep_href_link('modules.php', 'set=' . $set . '&module=' . $_GET['module'])));
      break;
    default:
      $heading[] = array('text' => '<strong>' . $mInfo->title . '</strong>');

      if ($mInfo->status == '1') {
        $keys = '';
        reset($mInfo->keys);
        while (list(, $value) = each($mInfo->keys)) {
          $keys .= '<strong>' . $value['title'] . '</strong><br />';
          if ($value['use_function']) {
            $use_function = $value['use_function'];
            if (preg_match('/->/', $use_function)) {
              $class_method = explode('->', $use_function);
              if (!isset(${$class_method[0]}) || !is_object(${$class_method[0]})) {
                include('includes/classes' . $class_method[0] . '.php');
                ${$class_method[0]} = new $class_method[0]();
              }
              $keys .= tep_call_function($class_method[1], $value['value'], ${$class_method[0]});
            } else {
              $keys .= tep_call_function($use_function, $value['value']);
            }
          } else {
            $keys .= $value['value'];
          }
          $keys .= '<br /><br />';
        }
        $keys = substr($keys, 0, strrpos($keys, '<br /><br />'));

        $contents[] = array('align' => 'center', 'text' => tep_draw_button(IMAGE_EDIT, 'document', tep_href_link('modules.php', 'set=' . $set . (isset($_GET['module']) ? '&module=' . $_GET['module'] : '') . '&action=edit')) . tep_draw_button(IMAGE_MODULE_REMOVE, 'minus', tep_href_link('modules.php', 'set=' . $set . '&module=' . $mInfo->code . '&action=remove')));

        if (isset($mInfo->signature) && (list($scode, $smodule, $sversion, $soscversion) = explode('|', $mInfo->signature))) {
          $contents[] = array('text' => '<br />' . tep_image('images/icon_info.gif', IMAGE_ICON_INFO) . '&nbsp;<strong>' . TEXT_INFO_VERSION . '</strong> ' . $sversion . ' (<a href="http://sig.oscommerce.com/' . $mInfo->signature . '" target="_blank">' . TEXT_INFO_ONLINE_STATUS . '</a>)');
        }

        if (isset($mInfo->api_version)) {
          $contents[] = array('text' => tep_image('images/icon_info.gif', IMAGE_ICON_INFO) . '&nbsp;<strong>' . TEXT_INFO_API_VERSION . '</strong> ' . $mInfo->api_version);
        }

        $contents[] = array('text' => '<br />' . $mInfo->description);
        $contents[] = array('text' => '<br />' . $keys);
      } elseif (isset($_GET['list']) && ($_GET['list'] == 'new')) {
        if (isset($mInfo)) {
          $contents[] = array('align' => 'center', 'text' => tep_draw_button(IMAGE_MODULE_INSTALL, 'plus', tep_href_link('modules.php', 'set=' . $set . '&module=' . $mInfo->code . '&action=install')));

          if (isset($mInfo->signature) && (list($scode, $smodule, $sversion, $soscversion) = explode('|', $mInfo->signature))) {
            $contents[] = array('text' => '<br />' . tep_image('images/icon_info.gif', IMAGE_ICON_INFO) . '&nbsp;<strong>' . TEXT_INFO_VERSION . '</strong> ' . $sversion . ' (<a href="http://sig.oscommerce.com/' . $mInfo->signature . '" target="_blank">' . TEXT_INFO_ONLINE_STATUS . '</a>)');
          }

          if (isset($mInfo->api_version)) {
            $contents[] = array('text' => tep_image('images/icon_info.gif', IMAGE_ICON_INFO) . '&nbsp;<strong>' . TEXT_INFO_API_VERSION . '</strong> ' . $mInfo->api_version);
          }

          $contents[] = array('text' => '<br />' . $mInfo->description);
        }
      }
      break;
  }

  if ( (tep_not_null($heading)) && (tep_not_null($contents)) ) {
    echo '            <td width="25%" valign="top">' . "\n";

    $box = new box;
    echo $box->infoBox($heading, $contents);

    echo '            </td>' . "\n";
  }
?>
          </tr>
        </table></td>
      </tr>
    </table>

<?php
  require('includes/template_bottom.php');
  require('includes/application_bottom.php');
?>

 

/admin/packaging.php

<?php
/*
    $Id: packaging.php, v1.02 2019 Exp $
    
    Copyright (c) Oscommerce
*/

require('includes/application_top.php');
require('classes/currencies.php');
$currencies = new currencies();
require('includes/template_top.php');
?>


<!-- body //-->
<table border="0" width="100%" cellspacing="2" cellpadding="2">
  <tr>
     <td class="pageHeading">
	  <?php echo HEADING_TITLE; ?>
	  <table border="0" width="100%" cellspacing="0" cellpadding="0">
                  <tr>
                    <td class="dataTableContent" width="75%" valign="top">
<?php
$activeid = $_GET['id'];

//********** New Package
if(($_POST['name'] != "" && $_POST["action"] == "newpackage") || ($_POST['id'] != "" && $_POST["action"] == "updatepackage")) {
    if (number_format(trim($_POST['length']), 2, '.', '') <= 0) {
        $error = MIN_LENGTH_NOT_MET;
    } else if (number_format(trim($_POST['width']), 2, '.', '') <= 0) {
        $error = MIN_WIDTH_NOT_MET;
    } else if (number_format(trim($_POST['height']), 2, '.', '') <= 0) {
        $error = MIN_HEIGHT_NOT_MET;
    } else if (number_format(trim($_POST['empty_weight']), 2, '.', '') < 0) {	
        $error = MIN_EMPTY_WEIGHT_NOT_MET;
    } else if (number_format(trim($_POST['max_weight']), 2, '.', '') < 0) {	
        $error = MIN_MAX_WEIGHT_NOT_MET;
    } else {
        $sql_data_array = array(
            'package_name' => $_POST['name'],
            'package_description' => $_POST['description'],
            'package_length' => $_POST['length'],
            'package_width' => $_POST['width'],
            'package_height' => $_POST['height'],
            'package_empty_weight' => $_POST['empty_weight'],
            'package_max_weight' => $_POST['max_weight'],
            'package_cost' => $_POST['cost']
        );
        if ($_POST["action"] == "newpackage") {
            tep_db_perform(TABLE_PACKAGING, $sql_data_array);
        } else {
            tep_db_perform(TABLE_PACKAGING, $sql_data_array, "update", "package_id = '" . $_POST['id'] . "'");
        }
    }
}

//********** Delete Package
if($_POST['id'] != "" && $_POST["action"] == "deletepackage") {
    tep_db_query("delete from " . TABLE_PACKAGING . " where package_id = '" . $_POST['id'] . "'");
}

// ********* Display Packages
DisplayPackages($activeid, $error);
switch ($_GET['action']) {
    case "shownewpackageform":
    showNewPackageForm();
    break;
    case "showupdatepackageform":
    showUpdatePackageForm();
    break;
    case "showconfirmdeletepackageform":
    showConfirmDeletePackageForm();
    break;
    case "":
    default:
    showPackageInfoForm();
    break;
}

//*******************
function getPackages() {
    $packages = array();
    $packages_query = tep_db_query("select * from " . TABLE_PACKAGING . " order by package_cost;");
    while ($package = tep_db_fetch_array($packages_query)) {
        $packages[] = array(
            'id' => $package['package_id'],
            'name' => $package['package_name'],
            'description' => $package['package_description'],
            'length' => $package['package_length'],
            'width' => $package['package_width'],
            'height' => $package['package_height'],
            'empty_weight' => $package['package_empty_weight'],
            'max_weight' => $package['package_max_weight'],
            'cost' => $package['package_cost']
        );
    }
    return $packages;
}

//************************  DisplayPackages()
// shows the main menu, lists the admins
function DisplayPackages($activeid,$error) {
?>

    <table border="0" width="100%" cellspacing="0" cellpadding="2" width="100%">
      <tr class="dataTableHeadingRow">
        <td class="dataTableHeadingContent"><?php echo HEADING_NAME; ?></td>
        <td class="dataTableHeadingContent" align="left"><?php echo HEADING_DESCRIPTION; ?></td>
        <td class="dataTableHeadingContent" align="center"><?php echo HEADING_LENGTH; ?></td>
        <td class="dataTableHeadingContent" align="center"><?php echo HEADING_WIDTH; ?></td>
        <td class="dataTableHeadingContent" align="center"><?php echo HEADING_HEIGHT; ?></td>
        <td class="dataTableHeadingContent" align="center"><?php echo HEADING_EMPTY_WEIGHT; ?></td>
        <td class="dataTableHeadingContent" align="center"><?php echo HEADING_MAX_WEIGHT; ?></td>
        <td class="dataTableHeadingContent" align="center"><?php echo HEADING_COST; ?></td>
        <td class="dataTableHeadingContent" align="left"><?php echo HEADING_ACTION; ?></td>
      </tr>

    <?php
    $packages = getPackages();
    if (count($packages) == 0) {
        echo                         '<tr><td colspan="8">' . NO_PACKAGES_DEFINED . '</td></tr>';
    }
    if ($error != "") {
        echo '<SPAN class="errorText">'.$error.'</SPAN>';
    }
    for ($i = 0; $i < count($packages); $i++) {
        if (($_GET["action"] != "shownewpackageform") && ($error == "")) {
            if ($activeid == "") {
                $activeid = $packages[0]['id'];
            }
        }
        if ($activeid == $packages[$i]['id']) {
            echo '<tr class="dataTableRowSelected" onmouseover="this.style.cursor=\'hand\'" onclick="document.location.href=\'' . tep_href_link('packaging.php', 'id=' . $packages[$i]['id'] ).'\'">' . "\n";
        } else {
            echo '<tr class="dataTableRow" onmouseover="this.className=\'dataTableRowOver\';this.style.cursor=\'hand\'" onmouseout="this.className=\'dataTableRow\'" onclick="document.location.href=\'' . tep_href_link('packaging.php', 'id=' .$packages[$i]['id'] ). '\'">' . "\n";
        }
        echo '<td class="dataTableContent" align="left"><br>' . $packages[$i]['name'] . '</td>';
        echo '<td class="dataTableContent" align="left"><br>' . $packages[$i]['description'] . '</td>';
        echo '<td class="dataTableContent" align="center"><br>' . $packages[$i]['length'] . '</td>';
        echo '<td class="dataTableContent" align="center"><br>' . $packages[$i]['width'] . '</td>';
        echo '<td class="dataTableContent" align="center"><br>' . $packages[$i]['height'] . '</td>';
        echo '<td class="dataTableContent" align="center"><br>' . $packages[$i]['empty_weight'] . '</td>';
        echo '<td class="dataTableContent" align="center"><br>' . $packages[$i]['max_weight'] . '</td>';
        echo '<td class="dataTableContent" align="center"><br>' . $packages[$i]['cost'] . '</td>';

        if ($activeid == $packages[$i]['id'] ) { 
            echo '<td>' . tep_image('images/icon_arrow_right.gif', ''); 
        } else { 
            echo '<td><a href="' . tep_href_link('packaging.php', 'id=' . $packages[$i]['id'] ). '">' . tep_image('images/icon_info.gif', ICON_INFO) . '</a>'; 
        }
    }
    echo '</td></tr></table><br>'."\n";
	
    echo tep_draw_button(NEW_PACKAGE, 'plus', tep_href_link('packaging.php', 'action=shownewpackageform'));//'<a href="' . tep_href_link( 'packaging.php' , 'action=shownewpackageform') .  '">'.tep_image_button('button_new_package.gif', 'New Package').'</a>&nbsp;';
    if ($activeid == "") {
        $activeid = $packages[0]['id'];
        }
    echo tep_draw_button(IMAGE_EDIT, 'pencil', tep_href_link('packaging.php', 'action=showupdatepackageform&id='.$activeid));//'<a href="' . tep_href_link( 'packaging.php' , 'action=showupdatepackageform&id='.$activeid.'') . '">'.tep_image_button('button_edit.gif', IMAGE_EDIT).'ddd</a>&nbsp;' ;	 
    echo tep_draw_button(HEADING_DELETE, 'close', tep_href_link('packaging.php', 'action=showconfirmdeletepackageform&id='.$activeid));//'<a href="' . tep_href_link( 'packaging.php' , 'action=showconfirmdeletepackageform&id='.$activeid.'') . '">'.tep_image_button('button_delete.gif', IMAGE_DELETE).'</a>' ;
   echo '</td><td class="infoBoxContent" valign="top">'."\n";
}

//******************************   showNewPackageForm()
// Show the form to create a new package
function showNewPackageForm() {
    $packages = getPackages();
    $cost = 0;
    for ($i = 0; $i < count($packages); $i++) {
        if ($packages[$i]['cost'] > $cost) {
            $cost = $packages[$i]['cost'] + 1;
        }
    }

    echo "<table cellspacing='0' width='100%' cellpadding='0'><tr>\n";
    echo "<td colspan='2' class='infoBoxHeading'>". CREATE_NEW_PACKAGE."</td></tr></table>\n";
    echo tep_draw_form("newpackage", 'packaging.php');
    echo tep_draw_hidden_field("action", "newpackage");
    echo '<table><tr><td class="infoBoxContent"><strong>'.HEADING_NAME.'</strong></td></tr><tr><td class="infoBoxContent">'.HEADING_NAME_TEXT.'</td></tr><tr><td class="infoBoxContent">'.tep_draw_input_field("name").'</td></tr>'."\n";
    echo '<tr><td class="infoBoxContent"><strong>'.HEADING_DESCRIPTION.'</strong></td></tr><tr><td class="infoBoxContent">'.HEADING_DESCRIPTION_TEXT.'</td></tr><tr><td class="infoBoxContent">'.tep_draw_input_field("description").'</td></tr>'."\n";
    echo '<tr><td class="infoBoxContent"><strong>'.HEADING_LENGTH.'</strong></td></tr><tr><td class="infoBoxContent">'.HEADING_LENGTH_TEXT.'</td></tr><tr><td class="infoBoxContent">'.tep_draw_input_field("length").'</td></tr>'."\n";
    echo '<tr><td class="infoBoxContent"><strong>'.HEADING_WIDTH.'</strong></td></tr><tr><td class="infoBoxContent">'.HEADING_WIDTH_TEXT.'</td></tr><tr><td class="infoBoxContent">'.tep_draw_input_field("width").'</td></tr>'."\n";
    echo '<tr><td class="infoBoxContent"><strong>'.HEADING_HEIGHT.'</strong></td></tr><tr><td class="infoBoxContent">'.HEADING_HEIGHT_TEXT.'</td></tr><tr><td class="infoBoxContent">'.tep_draw_input_field("height").'</td></tr>'."\n";
    echo '<tr><td class="infoBoxContent"><strong>'.HEADING_EMPTY_WEIGHT.'</strong></td></tr><tr><td class="infoBoxContent">'.HEADING_EMPTY_WEIGHT_TEXT.'</td></tr><tr><td class="infoBoxContent">'.tep_draw_input_field("empty_weight").'</td></tr>'."\n";
    echo '<tr><td class="infoBoxContent"><strong>'.HEADING_MAX_WEIGHT.'</strong></td></tr><tr><td class="infoBoxContent">'.HEADING_MAX_WEIGHT_TEXT.'</td></tr><tr><td class="infoBoxContent">'.tep_draw_input_field("max_weight").'</td></tr>'."\n";
    echo '<tr><td class="infoBoxContent"><strong>'.HEADING_COST.'</strong></td></tr><tr><td class="infoBoxContent">'.HEADING_COST_TEXT.'</td></tr><tr><td class="infoBoxContent">'.tep_draw_input_field("cost", $cost).'</td></tr>';
    echo '<tr><td colspan="2">'.tep_draw_button(IMAGE_SAVE, 'disk', null, 'primary'); //tep_image_submit('button_update.gif', 'Save these values as a new package.') ;
   // echo '&nbsp;&nbsp;'.tep_draw_button(IMAGE_CANCEL, 'trash', null, 'primary'); //<a href="' . tep_href_link( 'packaging.php' ) . '">'.tep_image_button('button_cancel.gif', IMAGE_CANCEL) .'</A>' ;	 
    echo "</td></tr></table>" ;
    echo ("</form>");
}

//******************************   showUpdatePackageForm()
// Show the form to update a package
function showUpdatePackageForm() {
    $packages = getPackages();
    $activepackage = $packages[0];
    if ($_GET['id'] != "") {
        for ($i = 0; $i < count($packages); $i++) {
            if ($_GET['id'] == $packages[$i]['id']) {
                $activepackage = $packages[$i];
            }
        }
    }
    echo "<table cellspacing='0' width='100%' cellpadding='0'> <tr><td colspan='2' class='infoBoxHeading'>". UPDATE_PACKAGE."</td></tr></table>\n";
    echo tep_draw_form("updatepackage", 'packaging.php', 'id='.$activepackage['id'], 'post');
    echo tep_draw_hidden_field("action", "updatepackage");
    echo tep_draw_hidden_field("id", $activepackage['id']);
    echo '<table><tr><td class="infoBoxContent"><strong>'.HEADING_NAME.'</strong></td></tr><tr><td class="infoBoxContent">'.HEADING_NAME_TEXT.'</td></tr><tr><td class="infoBoxContent">'.tep_draw_input_field("name", $activepackage['name']).'</td></tr>'."\n";
    echo '<tr><td class="infoBoxContent"><strong>'.HEADING_DESCRIPTION.'</strong></td></tr><tr><td class="infoBoxContent">'.HEADING_DESCRIPTION_TEXT.'</td></tr><tr><td class="infoBoxContent">'.tep_draw_input_field("description", $activepackage['description']).'</td></tr>'."\n";
    echo '<tr><td class="infoBoxContent"><strong>'.HEADING_LENGTH.'</strong></td></tr><tr><td class="infoBoxContent">'.HEADING_LENGTH_TEXT.'</td></tr><tr><td class="infoBoxContent">'.tep_draw_input_field("length", $activepackage['length']).'</td></tr>'."\n";
    echo '<tr><td class="infoBoxContent"><strong>'.HEADING_WIDTH.'</strong></td></tr><tr><td class="infoBoxContent">'.HEADING_WIDTH_TEXT.'</td></tr><tr><td class="infoBoxContent">'.tep_draw_input_field("width", $activepackage['width']).'</td></tr>'."\n";
    echo '<tr><td class="infoBoxContent"><strong>'.HEADING_HEIGHT.'</strong></td></tr><tr><td class="infoBoxContent">'.HEADING_HEIGHT_TEXT.'</td></tr><tr><td class="infoBoxContent">'.tep_draw_input_field("height", $activepackage['height']).'</td></tr>'."\n";
    echo '<tr><td class="infoBoxContent"><strong>'.HEADING_EMPTY_WEIGHT.'</strong></td></tr><tr><td class="infoBoxContent">'.HEADING_EMPTY_WEIGHT_TEXT.'</td></tr><tr><td class="infoBoxContent">'.tep_draw_input_field("empty_weight", $activepackage['empty_weight']).'</td></tr>'."\n";
    echo '<tr><td class="infoBoxContent"><strong>'.HEADING_MAX_WEIGHT.'</strong></td></tr><tr><td class="infoBoxContent">'.HEADING_MAX_WEIGHT_TEXT.'</td></tr><tr><td class="infoBoxContent">'.tep_draw_input_field("max_weight", $activepackage['max_weight']).'</td></tr>'."\n";
    echo '<tr><td class="infoBoxContent"><strong>'.HEADING_COST.'</strong></td></tr><tr><td class="infoBoxContent">'.HEADING_COST_TEXT.'</td></tr><tr><td class="infoBoxContent">'.tep_draw_input_field("cost", $activepackage['cost']).'</td></tr>';
    echo '<tr><td colspan="2">'.tep_draw_button(IMAGE_SAVE, 'disk', null, 'primary');// tep_image_submit('button_update.gif', 'Update the package with these values.') ;
    //echo '&nbsp;&nbsp;'.tep_draw_button(IMAGE_CANCEL, 'trash', null, 'primary');//<a href="' . tep_href_link( 'packaging.php','id='.$activepackage['id'] ) . '">'.tep_image_button('button_cancel.gif', IMAGE_CANCEL) .'</a>'."\n";	 
    echo "</td></tr></table>\n" ;
    echo ("</form>\n");
}

//*************************** showConfirmDeletePackageForm()
// Shows the form to confirm package deletion
function showConfirmDeletePackageForm() {
    $packages = getPackages();
    $package_name = "";
    for ($i = 0; $i < count($packages); $i++) {
        if ($packages[$i]['id'] == $_GET['id']) {
            $package_name = $packages[$i]['name'];
        }
    }
    echo "<table cellspacing='0' width='100%' cellpadding='0'> <tr><td colspan='2' class='infoBoxHeading'>". DELETE_PACKAGE."</td></tr></table>";
    echo tep_draw_form("confirmDeletePackage", 'packaging.php');
    echo tep_draw_hidden_field("action", "deletepackage");
    echo tep_draw_hidden_field("id", $_GET['id']);
    echo '<table cellpadding="5"><tr><td class="infoBoxContent">'.CONFIRM_DELETE.'</td></tr>' ;
    echo "<tr><td>".$package_name."</td></td>";
    echo "<tr><td>";
//    echo '<a href="' . tep_href_link( 'packaging.php' ) . '">'.tep_image_button('button_confirm.gif', IMAGE_CONFIRM) .'</a>' ;
    //tep_draw_button(IMAGE_EDIT, 'pencil', tep_href_link('packaging.php', 'action=showupdatepackageform&id='.$activeid))
	echo tep_draw_button(IMAGE_CONFIRM, 'close', null, 'primary'); 
	//echo tep_image_submit('button_confirm.gif', IMAGE_CONFIRM) ;	 
    echo '&nbsp;&nbsp;'.tep_draw_button(HEADING_CANCEL, 'arrowreturn-1-w', tep_href_link('packaging.php'));//<a href="' . tep_href_link( 'packaging.php' ) . '">'.tep_image_button('button_cancel.gif', IMAGE_CANCEL) .'</a>' ;	 
    echo '</td></tr></table>'."\n";
    echo '</form>'."\n";
}

//************************  ShowPackageInfo()
// Shows the info a package
function showPackageInfoForm() {
    $packages = getPackages();
    $activepackage = $packages[0];
    $activeid = $_GET["id"];
    if ($activeid != "") {
        for ($i = 0; $i < count($packages); $i++) {
            if ($activeid == $packages[$i]['id']) {
                $activepackage = $packages[$i];
            }
        }
    }
    if ($error != "") {
        echo '<SPAN class="errorText">'.$error.'</SPAN>';
    }

    echo "<table cellspacing='0' width='100%' cellpadding='0'><tr>\n<td colspan='2' class='infoBoxHeading'><strong>". HEADING_INFO ."</strong></td></tr></table>\n";
    if (count($packages) != 0) {
        echo '<table>'."\n";
        echo '<tr><td class="infoBoxContent"><strong>'.    HEADING_NAME    .'</strong></td></tr><tr><td class="infoBoxContent">'.$activepackage['name'].'</td></tr>'."\n";
        echo '<tr><td class="infoBoxContent"><strong>'. HEADING_DESCRIPTION.'</strong></td></tr><tr><td class="infoBoxContent">'.$activepackage['description'].'</td></tr>'."\n";
        echo '<tr><td class="infoBoxContent"><strong>'.   HEADING_LENGTH   .'</strong></td></tr><tr><td class="infoBoxContent">'.$activepackage['length'].'</td></tr>'."\n";
        echo '<tr><td class="infoBoxContent"><strong>'.   HEADING_WIDTH    .'</strong></td></tr><tr><td class="infoBoxContent">'.$activepackage['width'].'</td></tr>'."\n";
        echo '<tr><td class="infoBoxContent"><strong>'.   HEADING_HEIGHT   .'</strong></td></tr><tr><td class="infoBoxContent">'.$activepackage['height'].'</td></tr>'."\n";
        echo '<tr><td class="infoBoxContent"><strong>'.HEADING_EMPTY_WEIGHT.'</strong></td></tr><tr><td class="infoBoxContent">'.$activepackage['empty_weight'].'</td></tr>'."\n";
        echo '<tr><td class="infoBoxContent"><strong>'. HEADING_MAX_WEIGHT .'</strong></td></tr><tr><td class="infoBoxContent">'.$activepackage['max_weight'].'</td></tr>'."\n";
        echo '<tr><td class="infoBoxContent"><strong>'.    HEADING_COST    .'</strong></td></tr><tr><td class="infoBoxContent">'.$activepackage['cost'].'</td></tr>'."\n";
        echo "</table>\n";
    }
    echo "";
}
?>
        </td>
      </tr>
    </table> 
  </td>
<!-- body_text_eof //--></tr>
<!-- body_eof //-->

<!-- footer //-->
<?php require('includes/footer.php'); ?>
<!-- footer_eof //-->
<br>

<?php
  require('includes/template_bottom.php');
  require('includes/application_bottom.php');
?>

 

\includes\classes\packing.php

<?php
/*
  $Id: packaging.php, v1.0 Exp $

  osCommerce, Open Source E-Commerce Solutions
  http://www.oscommerce.com

  Copyright (c) 2019 osCommerce

  Released under the GNU General Public License
  Adapted from the UPSXML contribution
  
  dimensions support = 0: no dimensions support
  dimensions support = 1: ready-to-ship support only
  dimensions support = 2: full dimensions support
*/

  class packing {
    var $item, $totalWeight, $items_qty;

    function packing() {
    global $shipping_weight, $shipping_num_boxes, $total_weight, $boxcount, $cart, $order;

        $this->unit_weight = SHIPPING_UNIT_WEIGHT;
        $this->unit_length = SHIPPING_UNIT_LENGTH;
        $this->items_qty = 0;
        $this->totalWeight = 0;
        $this->item = array();

        
        if (defined('SHIPPING_DIMENSIONS_SUPPORT') && SHIPPING_DIMENSIONS_SUPPORT == 'Ready-to-ship only') {
          $this->dimensions_support = 1;
        } elseif (defined('SHIPPING_DIMENSIONS_SUPPORT') && SHIPPING_DIMENSIONS_SUPPORT == 'With product dimensions') {
          $this->dimensions_support = 2;
        } else {
          $this->dimensions_support = 0;
        }

        if (defined('SHIPPING_STORE_BOXES_USED') && SHIPPING_STORE_BOXES_USED == 'true') {
          $this->store_boxes_used = 1; 
        } else {
          $this->store_boxes_used = 0;
        }
        
        if (method_exists($cart, 'get_products_for_packaging') ) {
          $productsArray = $cart->get_products_for_packaging();
        } else {
          $productsArray = $cart->get_products();
        }
        if ($this->dimensions_support > 0) {
          $productsArray = $this->more_dimensions_to_productsArray($productsArray);
          // debug only
          // echo '<pre>Products to pack:<br>';
          // print_r($productsArray);
         // exit; 
        } 

        if ($this->dimensions_support == 2) {
            // sort $productsArray according to ready-to-ship (first) and not-ready-to-ship (last)
            usort($productsArray, ready_to_shipCmp);
            // Use packing algorithm to return the number of boxes we'll ship
            $boxesToShip = $this->packProducts($productsArray);
            /* echo '<pre>Boxes to ship:<br>';
             print_r($boxesToShip);
             exit; */
            if ($this->store_boxes_used == 1) {
            $storeBoxesToShip = base64_encode(serialize($boxesToShip));
            $storeQueryArray = array('date' => 'now()', 'customers_id' => $_SESSION['customer_id'], 'boxes' => $storeBoxesToShip);
            tep_db_perform(TABLE_UPS_BOXES_USED, $storeQueryArray);
            }
            // Quote for the number of boxes
            for ($i = 0; $i < count($boxesToShip); $i++) {
                $this->_addItem($boxesToShip[$i]['length'], $boxesToShip[$i]['width'], $boxesToShip[$i]['height'], $boxesToShip[$i]['current_weight'], $boxesToShip[$i]['price']);
                $this->totalWeight += $boxesToShip[$i]['current_weight'];
            }
        } elseif ($this->dimensions_support == 1) {
            $this->totalWeight = 0;
            $total_non_ready_to_ship_weight = 0;
            $total_non_ready_to_ship_value = 0;
            // sort $productsArray according to ready-to-ship (first) and not-ready-to-ship (last)
            usort($productsArray, ready_to_shipCmp);
            $non_ready_to_shipArray = array();
            // walk through the productsArray, separate the items ready-to-ship and add them to
            // the items (boxes) list, add the weight to the totalWeight
            // and add the other items to a separate array
            for ($i = 0; $i < count($productsArray); $i++) {
                if ($productsArray[$i]['ready_to_ship'] == '1') {
                    for ($z = 0 ; $z < $productsArray[$i]['quantity']; $z++) {
                        $this->_addItem($productsArray[$i]['length'], $productsArray[$i]['width'], $productsArray[$i]['height'], $productsArray[$i]['weight'], $productsArray[$i]['final_price']);
                        $this->totalWeight += $productsArray[$i]['weight'];
                    } // end for ($z = 0 ; $z < $productsArray[$i]['quantity']; $z++)
                } // end if($productsArray['ready_to_ship'] == '1')
                else {
                    $non_ready_to_shipArray[] = $productsArray[$i];
                }
            } // end for ($i = 0; $i < count($productsArray); $i++)
            // Ready_to_ship items out of the way, now assess remaining weight and remaining value of products

            for ($x = 0 ; $x < count($non_ready_to_shipArray) ; $x++) {
                $total_non_ready_to_ship_weight += ($non_ready_to_shipArray[$x]['weight'] * $non_ready_to_shipArray[$x]['quantity']);
                $total_non_ready_to_ship_value += ($non_ready_to_shipArray[$x]['final_price'] * $non_ready_to_shipArray[$x]['quantity']);
            } // end for ($x = 0 ; count($non_ready_to_shipArray) ; $x++)
      
            if (tep_not_null($non_ready_to_shipArray)) {
                // adapted code from includes/classes/shipping.php
                $shipping_non_ready_to_ship_boxes = 1;
                $shipping_non_ready_to_ship_weight = $total_non_ready_to_ship_weight;
                if (SHIPPING_BOX_WEIGHT >= $total_non_ready_to_ship_weight*SHIPPING_BOX_PADDING/100) {
                  $total_non_ready_to_ship_weight = $total_non_ready_to_ship_weight+SHIPPING_BOX_WEIGHT;
                } else {
                  $total_non_ready_to_ship_weight += $total_non_ready_to_ship_weight*SHIPPING_BOX_PADDING/100;
                }
                if ($total_non_ready_to_ship_weight > SHIPPING_MAX_WEIGHT) { // Split into many boxes
                    $shipping_non_ready_to_ship_boxes = ceil($total_non_ready_to_ship_weight/SHIPPING_MAX_WEIGHT);
                    $shipping_non_ready_to_ship_weight = round($total_non_ready_to_ship_weight/$shipping_non_ready_to_ship_boxes,1);
                }
                // end adapted code from includes/classes/shipping.php
                // weight and number of boxes of non-ready-to-ship is determined, now add them to the items list
                for ($y = 0; $y < $shipping_non_ready_to_ship_boxes ; $y++) {
                    $this->_addItem(0, 0, 0, $shipping_non_ready_to_ship_weight, number_format(($total_non_ready_to_ship_value/$shipping_non_ready_to_ship_boxes), 2, '.', ''));
                    $this->totalWeight += $shipping_non_ready_to_ship_weight;
                } // end for ($y = 0; $y < $shipping_non_ready_to_ship_boxes ; $y++)
            } // end if (tep_not_null($non_ready_to_shipArray))
       } // if/else ($this->dimensions_support == '#')
    } // end function packing($dimensions_support = '0')
    
    //********************************************
    function _addItem($length, $width, $height, $weight, $price = 0 ) {
        // Add box or item to shipment list. Round weights to 1 decimal places.
        if ((float)$weight < 1.0) {
            $weight = 1;
        } else {
            $weight = round($weight, 1);
        }
        $index = $this->items_qty;
        $this->item[$index]['item_length'] = ($length ? (string)$length : '0' );
        $this->item[$index]['item_width'] = ($width ? (string)$width : '0' );
        $this->item[$index]['item_height'] = ($height ? (string)$height : '0' );
        $this->item[$index]['item_weight'] = ($weight ? (string)$weight : '0' );
        $this->item[$index]['item_price'] = $price;
        $this->items_qty++;
    }

    //********************
    function getPackagesByVol() {
        $packages = array();
        $packages_query = tep_db_query("select *, (package_length * package_width * package_height) as volume from " . TABLE_PACKAGING . " order by volume");
        $counter = 0;
        while ($package = tep_db_fetch_array($packages_query)) {
            $packages[] = array(
            'id' => $package['package_id'],
            'name' => $package['package_name'],
            'description' => $package['package_description'],
            'length' => $package['package_length'],
            'width' => $package['package_width'],
            'height' => $package['package_height'],
            'empty_weight' => $package['package_empty_weight'],
            'max_weight' => $package['package_max_weight'],
            'volume' => $package['volume']);
// sort dimensions from low to high, used in the function fitsInBox
            $dimensions = array($package['package_length'], $package['package_width'], $package['package_height']);
            sort($dimensions);
              foreach($dimensions as $key => $value) {
                if ($key == 0 ) { $packages[$counter]['x'] = $value; }
                if ($key == 1 ) { $packages[$counter]['y'] = $value; }
                if ($key == 2 ) { $packages[$counter]['z'] = $value; }
              }
            $counter++;
        }
        return $packages;
    }

    //********************************
    function packProducts($productsArray) {
        $definedPackages = $this->getPackagesByVol();
        $emptyBoxesArray = array();
        for ($i = 0; $i < count($definedPackages); $i++) {
            $definedBox = $definedPackages[$i];
            $definedBox['remaining_volume'] = $definedBox['volume'];
            $definedBox['current_weight'] = $definedBox['empty_weight'];
            $emptyBoxesArray[] = $definedBox;
        }
          if (count($emptyBoxesArray) == 0) {
             print("ERROR: No boxes to ship unpackaged product<br />\n");
             break;
          }

        $packedBoxesArray = array();
        $currentBox = NULL;
        $index_of_largest_box = count($emptyBoxesArray)-1;
        // Get the product array and expand multiple qty items.
        $productsRemaining = array();
        for ($i = 0; $i < count($productsArray); $i++) {
          $product = $productsArray[$i];
            // sanity checks on the product, no need for ready-to-ship items
            if ((int)$product['ready_to_ship'] == 0) {
              $product['ready_to_ship'] = '1';
                 for ($x = 0; $x <= $index_of_largest_box; $x++) {
                   if ($this->fitsInBox($product, $emptyBoxesArray[$x])) {
                     $product['ready_to_ship'] = '0';
                     $product['largest_box_it_will_fit'] = $x;
                   } 
                 } // end for ($x = 0; $x <= $index_of_largest_box; $x++) 
            } // end if ((int)$product['ready_to_ship'] == 0)

            for ($j = 0; $j < $productsArray[$i]['quantity']; $j++) {
                $productsRemaining[] = $product;
            }
        } // end for ($i = 0; $i < count($productsArray); $i++)
        // make sure the products that did not fit the largest box and are now set as ready-to-ship
        // are out of the way as soon as possible
        usort($productsRemaining, ready_to_shipCmp);
        // Worst case, you'll need as many boxes as products ordered
        $index_of_largest_box_to_use = count($emptyBoxesArray) -1;
        while (count($productsRemaining)) {
            // Immediately set aside products that are already packed and ready.
            if ($productsRemaining[0]['ready_to_ship'] == '1') {
                $packedBoxesArray[] = array (
                'length' => $productsRemaining[0]['length'],
                'width' => $productsRemaining[0]['width'],
                'height' => $productsRemaining[0]['height'],
                'current_weight' => $productsRemaining[0]['weight'],
                'price' => $productsRemaining[0]['final_price']);
                $productsRemaining = array_slice($productsRemaining, 1);
                continue;
            }
            // Cycle through boxes, increasing box size if all doesn't fit
            // but if the remaining products only fit in a box of smaller size, use that one to pack it away
            for ($b = 0; $b < count($emptyBoxesArray) && tep_not_null($productsRemaining); $b++) {
                $result = $this->fitProductsInBox($productsRemaining, $emptyBoxesArray[$b], $packedBoxesArray, $b, $index_of_largest_box_to_use);
                $packedBoxesArray = $result['packed_boxes'];
                $productsRemaining = $result['remaining'];
                if (isset($result['index_of_largest_box_to_use']) && $result['index_of_largest_box_to_use'] >= 0 ) {
                  $index_of_largest_box_to_use = $result['index_of_largest_box_to_use'];
                }
            }
        } // end while

        return $packedBoxesArray;
    }

    //*****************************
    function fitsInBox($product, $box) {
        if ($product['x'] > $box['x'] || $product['y'] > $box['y'] || $product['z'] > $box['z']) {
            return false;
        } 

        if ($product['volume'] <= $box['remaining_volume']) {
            if ($box['max_weight'] == 0 || ($box['current_weight'] + $product['weight'] <= $box['max_weight'])) {
                return true;
            }
        }
        return false;
    }

    //***********************************
    function putProductInBox($product, $box) {
        $box['remaining_volume'] -= $product['volume'];
        $box['products'][] = $product;
        $box['current_weight'] += $product['weight'];
        $box['price'] += $product['final_price'];
        return $box;
    } 
    //*********************    
    function fitProductsInBox($productsRemaining, $emptyBox, $packedBoxesArray, $box_no, $index_of_largest_box) { 
        $currentBox = $emptyBox;
        $productsRemainingSkipped = array();
        $productsRemainingNotSkipped = array();
        $largest_box_in_skipped_products = -1;
        // keep apart products that will not fit this box anyway
        for ($p = 0; $p < count($productsRemaining); $p++) {
          if ($productsRemaining[$p]['largest_box_it_will_fit'] < $box_no) {
            $productsRemainingSkipped[] = $productsRemaining[$p];
            // check on skipped products: if they will not fit in the largest box
            // the $index_of_largest_box should be the one they *will* fit
            // otherwise the packing algorithm gets stuck in a loop
            if ($productsRemaining[$p]['largest_box_it_will_fit'] > $largest_box_in_skipped_products) {
              $largest_box_in_skipped_products = $productsRemaining[$p]['largest_box_it_will_fit'];
            }
          } else {
            $productsRemainingNotSkipped[] = $productsRemaining[$p];
          }
        }

        unset($productsRemaining);
        $productsRemaining = $productsRemainingNotSkipped;
        unset($productsRemainingNotSkipped);
        if (count($productsRemaining) == 0) {
          // products remaining are the ones that will not fit this box (productsRemaimingSkipped)
            $result_array = array('remaining' => $productsRemainingSkipped, 'box_no' => $box_no, 'packed_boxes' => $packedBoxesArray, 'index_of_largest_box_to_use' => $largest_box_in_skipped_products);
            return ($result_array);
        }

        //Try to fit each product that can fit in box
        for ($p = 0; $p < count($productsRemaining); $p++) {
            if ($this->fitsInBox($productsRemaining[$p], $currentBox)) {
                //It fits. Put it in the box.
                $currentBox = $this->putProductInBox($productsRemaining[$p], $currentBox);
                if ($p == count($productsRemaining) - 1) {
                    $packedBoxesArray[] = $currentBox;
                    $productsRemaining = array_slice($productsRemaining, $p + 1);
                    $productsRemaining = array_merge($productsRemaining, $productsRemainingSkipped);

                    $result_array = array('remaining' => $productsRemaining, 'box_no' => $box_no, 'packed_boxes' => $packedBoxesArray);
                    return ($result_array);
                }
            } else {
                if ($box_no == $index_of_largest_box) {
                    //We're at the largest box already, and it's full. Keep what we've packed so far and get another box.
                    $packedBoxesArray[] = $currentBox;
                    $productsRemaining = array_slice($productsRemaining, $p);
                    $productsRemaining = array_merge($productsRemaining, $productsRemainingSkipped);
                    $result_array = array('remaining' => $productsRemaining, 'box_no' => $box_no, 'packed_boxes' => $packedBoxesArray);
                    return ($result_array);
                }
                // Not all of them fit. Stop packing remaining products and try next box.
                $productsRemaining = array_merge($productsRemaining, $productsRemainingSkipped);
                $result_array = array('remaining' => $productsRemaining, 'box_no' => $box_no, 'packed_boxes' => $packedBoxesArray);
                return ($result_array);
            } // end else
        } // end for ($p = 0; $p < count($productsRemaining); $p++)
    } // end function fitProductsInBox
    
// ******************************
  function more_dimensions_to_productsArray($productsArray) {
    $counter = 0;
      foreach ($productsArray as $key => $product) {
        // in case by accident or by choice length, width or height is not set
        // we will estimate it by using a set density and the product['weight'] variable
        // will only be used in the check for whether it fits the largest box
        // after that it will already be set, if product['weight'] is set at least
        if ($product['length'] == 0 || $product['width'] == 0 || $product['height'] == 0) {
            $density = 0.7;
            if ($this->unit_length == 'CM') {
                $product['length']=$product['width']=$product['height']= round(10*(pow($product['weight']/$density, 1/3)),1);
            } else {
                // non-metric: inches and pounds
                $product['length']=$product['width']=$product['height']= round(pow($product['weight']*27.67/$density, 1/3),1);
            }
        } // end if ($product['length'] == 0 || $product['width'] == 0 etc.
// sort dimensions from low to high, used in the function fitsInBox
        $dimensions = array($product['length'], $product['width'], $product['height']);
        sort($dimensions);
          foreach($dimensions as $key => $value) {
            if ($key == 0 ) { $productsArray[$counter]['x'] = $value; }
            if ($key == 1 ) { $productsArray[$counter]['y'] = $value; }
            if ($key == 2 ) { $productsArray[$counter]['z'] = $value; }
           }
        $productsArray[$counter]['volume'] = $product['length'] * $product['width'] * $product['height'];
        $counter++;
  } // end foreach ($productsArray as $key => $product)
    return($productsArray);
  }

  function getPackedBoxes() {
    return $this->item;
  }

  function getTotalWeight() {
    return $this->totalWeight;
  }

  function getNumberOfBoxes() {
    return $this->items_qty;
  }

  } // end class packing
// ******************************
function ready_to_shipCmp( $a, $b) {
    if ( $a['ready_to_ship'] == $b['ready_to_ship'] )
    return 0;
    if ( $a['ready_to_ship'] > $b['ready_to_ship'] )
    return -1;
    return 1;
}
?>

 

\includes\modules\shipping\canadapost.php

<?php
/*
    $Id: canadapost.php v0.1 2019 Exp $
*/

class canadapost {
    var $code, $title, $description, $icon, $enabled, $types, $boxcount;

    //***************
    function canadapost() {
        global $order, $packing;
        $this->code = 'canadapost';
        $this->title = MODULE_SHIPPING_CANADA_POST_TEXT_TITLE;
        $this->description = MODULE_SHIPPING_CANADA_POST_TEXT_DESCRIPTION;
        $this->sort_order = MODULE_SHIPPING_CANADA_POST_SORT_ORDER;
        $this->icon = 'icons/shipping_canadapost_small.gif';
        $this->tax_class = MODULE_SHIPPING_CANADA_POST_TAX_CLASS;
        $this->enabled = ((MODULE_SHIPPING_CANADA_POST_STATUS == 'True') ? true : false);
        $this->access_username = MODULE_SHIPPING_CANADA_POST_USERNAME;
        $this->access_password = MODULE_SHIPPING_CANADA_POST_PASSWORD;
        $this->access_customer_number = MODULE_SHIPPING_CANADA_POST_CUSTOMER_NUMBER;
		$this->timeout = '60';
		$this->quotetype = MODULE_SHIPPING_CANADA_POST_QUOTE_TYPE;
		$this->contract_id = MODULE_SHIPPING_CANADA_POST_CONTRACT_ID;
        $this->origin_postalcode = MODULE_SHIPPING_CANADA_POST_POSTALCODE;
		$this->use_insurance =((MODULE_SHIPPING_CANADA_POST_INSURE == 'True') ? true : false);
		$sdate = MODULE_SHIPPING_CANADA_POST_TURNAROUNDTIME;
		$this->turnaround = date('Y-m-d', strtotime( '+'.$sdate.' day' ) );
        $this->handling_fee = MODULE_SHIPPING_CANADA_POST_HANDLING;
		$this->handling_type = MODULE_SHIPPING_CANADA_POST_HANDLING_TYPE;
		
//calculate turnaround time
		

// the variables for unit weight, unit length, and dimensions support were moved to
// shop admin -> Configuration -> Shipping/Packaging in
// Run the configuration_shipping.sql to add these to your configuration
        if (defined('SHIPPING_UNIT_WEIGHT')) {
          $this->unit_weight = SHIPPING_UNIT_WEIGHT;
        } else {
// for those who will undoubtedly forget or not know how to run the configuration_shipping.sql
// we will set the default to pounds (LBS) and inches (IN)
          $this->unit_weight = 'LBS';
        }
        if (defined('SHIPPING_UNIT_LENGTH')) {
          $this->unit_length = SHIPPING_UNIT_LENGTH;
        } else {
          $this->unit_length = 'IN';
        }
		
        if (defined('SHIPPING_DIMENSIONS_SUPPORT') && SHIPPING_DIMENSIONS_SUPPORT == 'Ready-to-ship only') {
          $this->dimensions_support = 1;
        } elseif (defined('SHIPPING_DIMENSIONS_SUPPORT') && SHIPPING_DIMENSIONS_SUPPORT == 'With product dimensions') {
          $this->dimensions_support = 2;
        } else {
          $this->dimensions_support = 0;
        }
        $this->protocol = 'https';
        $this->host = ((MODULE_SHIPPING_CANADA_POST_MODE == 'Test') ? 'ct.soa-gw.canadapost.ca' : 'soa-gw.canadapost.ca');
        $this->port = '443';
        $this->path = '/rs/ship/price';

        $this->items_qty = 0;

        // insurance addition
        $this->insure_package = false;
        if (MODULE_SHIPPING_CANADA_POST_INSURE == 'True') { 
          $this->insure_package = true;
        }
        // end insurance addition
        $this->pkgvalue = ceil($order->info['subtotal']); // is divided by number of boxes later
		
	if ( ($this->enabled == true) && ((int)MODULE_SHIPPING_FEDEX_WEB_SERVICES_ZONE > 0) ) {
      $check_flag = false;
      $check_query = tep_db_query ("select zone_id from " . TABLE_ZONES_TO_GEO_ZONES . " where geo_zone_id = '" . MODULE_SHIPPING_FEDEX_WEB_SERVICES_ZONE . "' and zone_country_id = '" . $order->delivery['country']['id'] . "' order by zone_id");
      while( $check = tep_db_fetch_array($check_query)) {
        if ($check ['zone_id'] < 1) {
          $check_flag = true;
          break;
        } elseif ($check ['zone_id'] == $order->delivery['zone_id']) {
          $check_flag = true;
          break;
        }
        $check->MoveNext();
      }

      if ($check_flag == false) {
        $this->enabled = false;
      }
    }

    } // end function upsxml

    //**************
    function check() {
        if (!isset($this->_check)) {
            $check_query = tep_db_query("select configuration_value from " . TABLE_CONFIGURATION . " where configuration_key = 'MODULE_SHIPPING_CANADA_POST_STATUS'");
            $this->_check = tep_db_num_rows($check_query);
        }
        return $this->_check;
    }

    //****************
    function remove() {
        tep_db_query("delete from " . TABLE_CONFIGURATION . " where configuration_key in ('" . implode("', '", $this->keys()) . "')");
    }

    function install() {
        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Enable Canada Post Shipping Service(REST)', 'MODULE_SHIPPING_CANADA_POST_STATUS', 'True', 'Do you want to offer Canada Post shipping?', '6', '0', 'tep_cfg_select_option(array(\'True\', \'False\'), ', now())");

        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Canada Post Customer Number', 'MODULE_SHIPPING_CANADA_POST_CUSTOMER_NUMBER', '', 'Enter the Your Canada Post Customer Number.', '6', '1', now())");

        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Canada Post API Username', 'MODULE_SHIPPING_CANADA_POST_USERNAME', '', 'Enter your Canada Post (API Keys) username.', '6', '2', now())");

        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Canada Post API Password', 'MODULE_SHIPPING_CANADA_POST_PASSWORD', '', 'Enter your Canada Post (API Keys) password.', '6', '3', now())");

        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Canada Post Contract ID', 'MODULE_SHIPPING_CANADA_POST_CONTRACT_ID', '', 'Enter your Canada Post contract id (for commercial/contracted rates only).', '6', '4', now())");

        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Canada Post Quote Type', 'MODULE_SHIPPING_CANADA_POST_QUOTE_TYPE', 'commercial', 'Either commercial (for the contract holder) or counter (regular price for consumers)', '6', '5', 'tep_cfg_select_option(array(\'commercial\', \'counter\'), ', now())");
 
        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Enable Insurance', 'MODULE_SHIPPING_CANADA_POST_INSURE', 'True', 'Do you want to insure packages shipped by Canada Post?', '6', '6', 'tep_cfg_select_option(array(\'True\', \'False\'), ', now())");

        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Origin City', 'MODULE_SHIPPING_CANADA_POST_CITY', '', 'Enter the name of the origin city.', '6', '7', now())");

        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Origin State/Province', 'MODULE_SHIPPING_CANADA_POST_STATEPROV', '', 'Enter the two-letter code for your origin state/province.', '6', '8', now())");

        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Origin Country', 'MODULE_SHIPPING_CANADA_POST_COUNTRY', '', 'Enter the two-letter code for your origin country.', '6', '9', now())");

        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Origin Zip/Postal Code', 'MODULE_SHIPPING_CANADA_POST_POSTALCODE', '', 'Enter your origin zip/postalcode (from which the parcel will be sent).', '6', '10', now())");

        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Test or Production Mode', 'MODULE_SHIPPING_CANADA_POST_MODE', 'Test', 'Use this module in Test  or Production mode? <br /><br />Your API Keys username and password are different in Test and Production mode', '6', '11', 'tep_cfg_select_option(array(\'Test\', \'Production\'), ', now())");

        tep_db_query("insert into " . TABLE_CONFIGURATION . " ( configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, use_function, set_function, date_added) values ('Disallowed Shipping Methods', 'MODULE_SHIPPING_CANADA_POST_TYPES', '', 'Select the Canada Post services <span style=\'color: red; font-weight: bold\'>not</span> to be offered.', '6', '12', 'get_multioption_canadapost_xml',  'canadapost_cfg_select_multioption(array(\'D.RP\',\'D.EP\',\'D.XP\',\'D.XP.CERT\',\'D.PC\',\'D.LIB\',\'U.EP\',\'U.PW.ENV\',\'U.PW.PAK\',\'U.PW.PARCEL\',\'U.SP.AIR\',\'U.SP.SURF\',\'U.XP\',\'I.XP\',\'I.IP.AIR\',\'I.IP.SURF\',\'I.PW.ENV\', \'I.PW.PAK\',\'I.PW.PARCEL\',\'I.SP.AIR\',\'I.SP.SURF\'),',  now())");


        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Handling Type', 'MODULE_SHIPPING_CANADA_POST_HANDLING_TYPE', 'Flat Fee', 'Handling type for this shipping method.', '6', '13', 'tep_cfg_select_option(array(\'Flat Fee\', \'Percentage\'), ', now())");

        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Handling Fee', 'MODULE_SHIPPING_CANADA_POST_HANDLING', '0', 'Handling fee for this shipping method.', '6', '14', now())");

        tep_db_query ("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, use_function, set_function, date_added) values ('Shipping Zone', 'MODULE_SHIPPING_CANADA_POST_ZONE', '0', 'If a zone is selected, only enable this shipping method for that zone.', '6', '98', 'tep_get_zone_class_title', 'tep_cfg_pull_down_zone_classes(', now())");

        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, use_function, set_function, date_added) values ('Tax Class', 'MODULE_SHIPPING_CANADA_POST_TAX_CLASS', '0', 'Use the following tax class on the shipping fee.', '6', '15', 'tep_get_tax_class_title', 'tep_cfg_pull_down_tax_classes(', now())");

        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Sort order of display.', 'MODULE_SHIPPING_CANADA_POST_SORT_ORDER', '0', 'Sort order of display. Lowest is displayed first.', '6', '16', now())");

        // add key for enabling email error messages
        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Email Canada Post errors', 'MODULE_SHIPPING_CANADA_POST_EMAIL_ERRORS', 'Yes', 'Do you want to receive Canada Post errors by email?', '6', '17', 'tep_cfg_select_option(array(\'Yes\', \'No\'), ', now())");
		
		tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Enter Turn Around Time', 'MODULE_SHIPPING_CANADA_POST_TURNAROUNDTIME', '1', 'Turn Around Time (days)', '6', '0', now())");
		}

    //*************
    function keys() {
        return array('MODULE_SHIPPING_CANADA_POST_STATUS','MODULE_SHIPPING_CANADA_POST_CUSTOMER_NUMBER','MODULE_SHIPPING_CANADA_POST_USERNAME',
'MODULE_SHIPPING_CANADA_POST_PASSWORD','MODULE_SHIPPING_CANADA_POST_CONTRACT_ID','MODULE_SHIPPING_CANADA_POST_QUOTE_TYPE',
'MODULE_SHIPPING_CANADA_POST_INSURE','MODULE_SHIPPING_CANADA_POST_CITY','MODULE_SHIPPING_CANADA_POST_STATEPROV','MODULE_SHIPPING_CANADA_POST_COUNTRY',
'MODULE_SHIPPING_CANADA_POST_POSTALCODE','MODULE_SHIPPING_CANADA_POST_MODE','MODULE_SHIPPING_CANADA_POST_TYPES','MODULE_SHIPPING_CANADA_POST_HANDLING_TYPE',
'MODULE_SHIPPING_CANADA_POST_HANDLING','MODULE_SHIPPING_CANADA_POST_ZONE','MODULE_SHIPPING_CANADA_POST_TAX_CLASS','MODULE_SHIPPING_CANADA_POST_SORT_ORDER','MODULE_SHIPPING_CANADA_POST_EMAIL_ERRORS', 'MODULE_SHIPPING_CANADA_POST_TURNAROUNDTIME');
    }

//**********************************************
    function _canadaPostOrigin($city, $stateprov, $country, $postal){
        $this->_canadaPostOriginCity = $city;
        $this->_canadaPostOriginStateProv = $stateprov;
        $this->_canadaPostOriginCountryCode = $country;
        $postal = str_replace(' ', '', $postal);
        if ($country == 'US') {
            $this->_canadaPostOriginPostalCode = substr($postal, 0, 5);
        } else {
            $this->_canadaPostOriginPostalCode = strtoupper($postal);
        }
    }

    //**********************************************
    function _canadaPostDest($city, $stateprov, $country, $postal) {
        $this->_canadaPostDestCity = $city;
        $this->_canadaPostDestStateProv = $stateprov;
        $this->_canadaPostDestCountryCode = $country;
        $postal = str_replace(' ', '', $postal);
        if ($country == 'US') {
            $this->_canadaPostDestPostalCode = substr($postal, 0, 5);
        } else if ($country == 'BR') {
            $this->_canadaPostDestPostalCode = substr($postal, 0, 5);
        } else if( $country == 'CA') {
            $this->_canadaPostDestPostalCode = strtoupper($postal);
        } else {
			$this->_canadaPostDestPostalCode = $postal;
		}
    }
	//********************************************
    function _addItem($length, $width, $height, $weight, $price = 0 ) {
        // Add box or item to shipment list. Round weights to 1 decimal places.
        if ((float)$weight < 1.0) {
            $weight = 1;
        } else {
            $weight = round($weight, 3);
        }
        $index = $this->items_qty;
        $this->item_length[$index] = ($length ? (string)round((float)$length,1) : '0' );
        $this->item_width[$index] = ($width ? (string)round((float)$width,1) : '0' );
        $this->item_height[$index] = ($height ? (string)round((float)$height,1) : '0' );
        $this->item_weight[$index] = ($weight ? (string)round((float)$weight,1) : '0' );
        $this->item_price[$index] = $price;
        $this->items_qty++;
    }

/***************************************************************************************************************************************************************/
    // class methods
    function quote($method = '') {
        global $_POST, $order, $shipping_weight, $shipping_num_boxes, $total_weight, $boxcount, $cart, $packing;

        $state = $order->delivery['state'];
        $zone_query = tep_db_query("select zone_code from " . TABLE_ZONES . " where zone_name = '" .  tep_db_input($order->delivery['state']) . "' and zone_country_id = '" . $order->delivery['country']['id'] . "'");
        if (tep_db_num_rows($zone_query)) {
            $zone = tep_db_fetch_array($zone_query);
            $state = $zone['zone_code'];
        }
        $this->_canadaPostOrigin(MODULE_SHIPPING_CANADA_POST_CITY, MODULE_SHIPPING_CANADA_POST_STATEPROV, MODULE_SHIPPING_CANADA_POST_COUNTRY, MODULE_SHIPPING_CANADA_POST_POSTALCODE);
        $this->_canadaPostDest($order->delivery['city'], $state, $order->delivery['country']['iso_code_2'], $order->delivery['postcode']);
        
// the check on $packing being an object will puzzle people who do things wrong (no changes when 
// you enable dimensional support without changing checkout_shipping.php) but better be safe
        if ($this->dimensions_support > 0 && is_object($packing)) {
          $boxValue = 0;
          $totalWeight = $packing->getTotalWeight();
          $boxesToShip = $packing->getPackedBoxes();
          for ($i = 0; $i < count($boxesToShip); $i++) {
            $this->_addItem($boxesToShip[$i]['item_length'], $boxesToShip[$i]['item_width'], $boxesToShip[$i]['item_height'], $boxesToShip[$i]['item_weight'], $boxesToShip[$i]['item_price']);
          } // end for ($i = 0; $i < count($boxesToShip); $i++)
        } else {
            // The old method. Let osCommerce tell us how many boxes, plus the weight of each (or total? - might be sw/num boxes)
          $this->items_qty = 0; //reset quantities
// $this->pkgvalue has been set as order subtotal around line 108, it will cause overcharging
// of insurance if not divided by the number of boxes
          for ($i = 0; $i < $shipping_num_boxes; $i++) {
            $this->_addItem(0, 0, 0, $shipping_weight, number_format(($this->pkgvalue/$shipping_num_boxes), 2, '.', ''));
          }
        }

        $canadaPostQuote = $this->_canadaPostGetQuote();
		
        if ((is_array($canadaPostQuote)) && (sizeof($canadaPostQuote) > 0)) {
            $this->quotes = array('id' => $this->code, 'module' => $this->title);
            usort($canadaPostQuote, array($this, "rate_sort_func"));
           
            $methods = array();

            for ($i=0; $i < sizeof($canadaPostQuote); $i++) {
                //list($type, $cost) = each($canadaPostQuote[$i]);
				$basetype = $canadaPostQuote[$i]['service-code'];
				$cost = $canadaPostQuote[$i]['base'];
				$type = $canadaPostQuote[$i]['service-name'];
				$ddate = $canadaPostQuote[$i]['expected-delivery-date'];

                if ($this->exclude_choices($basetype)) continue;
				if ( $method == '' || $method == $basetype ) {
				$_type = $type;

				// changed to make handling percentage based
				if ($this->handling_type == "Percentage") {
					if ($_type) $methods[] = array('id' => $basetype, 'title' => $_type. ', '. $ddate, 'cost' => ((($this->handling_fee * $cost)/100) + $cost));
				} else {
					if ($_type) $methods[] = array('id' => $basetype, 'title' => $_type. ', '. $ddate, 'cost' => ($this->handling_fee + $cost));
				}
			  }	
            }
            if ($this->tax_class > 0) {
                $this->quotes['tax'] = tep_get_tax_rate($this->tax_class, $order->delivery['country']['id'], $order->delivery['zone_id']);
            }
            $this->quotes['methods'] = $methods;
        } else {
            if ( $canadaPostQuote != false ) {
                $errmsg = $canadaPostQuote;
            } else {
                $errmsg = MODULE_SHIPPING_CANADAPOST_TEXT_UNKNOWN_ERROR;
            }
            $errmsg .= '<br>'. STORE_NAME.' via <a href="mailto:'.STORE_OWNER_EMAIL_ADDRESS.'"><u>Email</u></a>.';
            $this->quotes = array('module' => $this->title, 'error' => $errmsg);
        }
        if (tep_not_null($this->icon)) {
            $this->quotes['icon'] = tep_image($this->icon);
        }

        return $this->quotes;
    }

	//*********************
    function _canadaPostGetQuote() {
		//need to loop throught all items or packages
		$capost= array();
		
		//first item/package
		for ($i=0; $i<sizeof($this->item_width); $i++) {
    		$xmlRequest = $this->_GetRequestXml(0);
			$result = $this->_post($xmlRequest);
			if($result===false) return false;
			$box = $this->_parseResult($result);
			if($box===false) return false;
			for($i3=0; $i3 < sizeof($box);$i3++) {
			   $merge = true;	
			   for($i2=0; $i2 < sizeof($capost);$i2++) {
				 if (strcmp($capost[$i2]['service-code'],$box[$i3]['service-code'])==0)
				 {
					$capost[$i2]['base'] += $box[$i3]['base'];
					$merge=false;
					break;
				 }
			   }	
			   if($merge) $capost[] = array('service-name'=>$box[$i3]['service-name'],'base'=>$box[$i3]['base'],'service-code' => $box[$i3]['service-code'],'expected-delivery-date'=> $box[$i3]['expected-delivery-date']);
			}
		}
		//					print_r($aryProducts);
				

        return $capost;
    }
     //*****************************
    function _parseResult($xmlResult) {
        $aryProducts = false;
        $upstemp = array();
		$priceQuotes = $xmlResult->{'price-quotes'}->children('http://www.canadapost.ca/ws/ship/rate');
		if ( $priceQuotes->{'price-quote'} ) {
			$aryProducts=array();
			foreach ( $priceQuotes as $priceQuote ) {
				$title  =(string) $priceQuote->{'service-name'};
				$code  = (string)$priceQuote->{'service-code'};
				$charge = (float) $priceQuote->{'price-details'}->{'base'};
				$ddate = (string) $priceQuote->{'service-standard'}->{'expected-delivery-date'}; //2011-09-21*/
				$aryProducts[] = array('service-name'=>$title,'base'=>$charge,'service-code' => $code,'expected-delivery-date'=> $ddate);
			}
		}
		
		//		print_r($aryProducts);
				
        return $aryProducts;
    }
    
    //******************************************************************
    function _post($xmlRequest) {
        $url = $this->protocol."://".$this->host.":".$this->port.$this->path;

		$curl = curl_init($url); // Create REST Request
		curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
		curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
		curl_setopt($curl, CURLOPT_CAINFO, realpath(dirname($argv[0])) . '/includes/modules/shipping/canadapost/cacert.pem'); // Signer Certificate in PEM format
		curl_setopt($curl, CURLOPT_POST, true);
		curl_setopt($curl, CURLOPT_POSTFIELDS, $xmlRequest);
		curl_setopt($curl, CURLOPT_TIMEOUT, (int)$this->timeout);
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
		curl_setopt($curl, CURLOPT_USERPWD, $this->access_username . ':' . $this->access_password);
		curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/vnd.cpc.ship.rate+xml', 'Accept: application/vnd.cpc.ship.rate+xml'));
		$curl_response = curl_exec($curl); // Execute REST Request
		
	//	echo $curl_response; 
	
		// send email if enabled in the admin section
		if (curl_errno($curl) && $this->email_errors) {
			$error_from_curl = sprintf('Error [%d]: %s', curl_errno($curl), curl_error($curl));
			error_log("Error from cURL: " . $error_from_curl . " experienced by customer with id " . $_SESSION['customer_id'] . " on " . date('Y-m-d H:i:s'), 1, STORE_OWNER_EMAIL_ADDRESS);
		}
		
		curl_close ($curl);
	
		libxml_use_internal_errors(true);
		
		$xml = simplexml_load_string('<root>' . preg_replace('/<\?xml.*\?>/','',$curl_response) . '</root>');
		if (!$xml) {
			$error_from_curl = 'Failed loading XML' . "\n". $curl_response . "\n";
			if($this->email_errors) error_log("Error from cURL: " . $error_from_curl . " experienced by customer with id " . $_SESSION['customer_id'] . " on " . date('Y-m-d H:i:s'), 1, STORE_OWNER_EMAIL_ADDRESS);
		} else {
			if ($xml->{'price-quotes'} ) {
				return $xml;
			}
			if ($xml->{'messages'} ) {					
				$messages = $xml->{'messages'}->children('http://www.canadapost.ca/ws/messages');		
				$error_from_curl='';
				foreach ( $messages as $message ) {
					$error_from_curl .= 'Error Code: ' . $message->code . "\n";
					$error_from_curl .= 'Error Msg: ' . $message->description . "\n\n";
				}
				if($this->email_errors) error_log("Error from cURL: " . $error_from_curl . " experienced by customer with id " . $_SESSION['customer_id'] . " on " . date('Y-m-d H:i:s'), 1, STORE_OWNER_EMAIL_ADDRESS);
			}
		}
		return false;
  }

 //  ***************************
  function exclude_choices($type) {
  	
	if(substr($type,0,4)=='DOM.')
		$type = 'D.'.substr($type,4);
	 else if(substr($type,0,4)=='USA.')
		$type = 'U.'.substr($type,4);
	 else if(substr($type,0,4)=='INT.')
		$type = 'I.'.substr($type,4);
	
    $disallowed_types = explode(",", MODULE_SHIPPING_CANADA_POST_TYPES);
    
    for ($za = 0; $za < count ($disallowed_types); $za++ ) {
      // when no disallowed types are present, --none-- is in the db but causes an error because --none-- is
      // not added as a define
      if ($disallowed_types[$za] == '--none--' ) continue; 
        if ($type == trim($disallowed_types[$za])) {
            return true;
        } // end if ($type_root == constant(trim($disallowed_types[$za]))).
    }
    // if the type is not disallowed:
    return false;
  }
// Next function used for sorting the shipping quotes on rate: low to high is default.
  function rate_sort_func ($a, $b) {
    
   $av = array_values($a);
   $av = $av[0];
   $bv = array_values($b);
   $bv = $bv[0];

//  return ($av == $bv) ? 0 : (($av < $bv) ? 1 : -1); // for having the high rates first
   return ($av == $bv) ? 0 : (($av > $bv) ? 1 : -1); // low rates first
  
  }
  
  function _GetRequestXml($index)
  {
	//http://www.canadapost.ca/cpo/mc/business/productsservices/developers/services/rating/getrates/default.jsf
	//The weight of the parcel in kilograms.
	//Details of the parcel dimensions in centimeters.

	$weight = $this->item_weight[$index];
	$price = round($this->item_price[$index],2);
	$width = $this->item_weight[$index];
	$height = $this->item_height[$index];
	$length = $this->item_length[$index];
	
	 if($this->unit_weight == 'LBS') {
	 	//change to kilograms
	 	$weight = round($weight/2.2,3);
     }
    if($this->unit_length == 'IN') {
		//change to centimeters 	  
		$width = round($width * 2.54,1);
		$height = round($height * 2.54,1);
		$length = round($length * 2.54,1);
	}
		  
	$xmlRequest ="<?xml version=\"1.0\" encoding=\"UTF-8\"?>
	<mailing-scenario xmlns=\"http://www.canadapost.ca/ws/ship/rate\">
	  <customer-number>$this->access_customer_number</customer-number>
	  <quote-type>$this->quotetype</quote-type>";
	if($this->contract_id) {
	   $xmlRequest .= "<contract-id>$this->contract_id</contract-id>";	
	}  
	$xmlRequest .= "<expected-mailing-date>$this->turnaround</expected-mailing-date>";
	
	if (($this->use_insurance) && ($price>0)) {
		$xmlRequest .= "<options><option>
			  <option-code>COV</option-code>
			  <option-amount>$price</option-amount>
			</option>
		</options>";
	}
	$xmlRequest .= "  <parcel-characteristics>
		<weight>$weight</weight>";
	if (($this->dimensions_support>0) && ($width>0)	 && ($height>0)	 && ($length>0)) {
	   $xmlRequest .= "<dimensions><length>$length</length>
	   	<width>$width</width>
		<height>$height</height>
	   </dimensions>";
	}
	$xmlRequest .= "</parcel-characteristics>
	  <origin-postal-code>$this->_canadaPostOriginPostalCode</origin-postal-code>
	  <destination>";
	  if($this->_canadaPostDestCountryCode=='CA') {
		$xmlRequest .="<domestic>
		  <postal-code>$this->_canadaPostDestPostalCode</postal-code>
		</domestic>";
	  } else if($this->_canadaPostDestCountryCode=='US') {
		$xmlRequest .="<united-states>
		  <zip-code>$this->_canadaPostDestPostalCode</zip-code>
		</united-states>";
	  } else {
		$xmlRequest .="<international>
		  <country-code>$this->_canadaPostDestCountryCode</country-code>
		</international>";
	  }
	$xmlRequest .="  </destination>
	</mailing-scenario>";
	//echo $xmlRequest;
	return $xmlRequest;
  } //end of function _GetRequestXml
} //end of class canadapost
function get_multioption_canadapost_xml($values) 
{
	 if (tep_not_null($values)) {
		 $values_array = explode(',', $values);
		 foreach ($values_array as $key => $_method) {
		   if ($_method == '--none--') {
			 $method = $_method;
		   } else {
			 $method = constant('CANADA_POST_' .get_canada_post_service_code($_method));
		   }
		   $readable_values_array[] = $method;
		 }
		 $readable_values = implode(', ', $readable_values_array);
		 return $readable_values;
	 } else {
	   return '';
	 }
}
function get_canada_post_service_code($key)
{
	$km = str_replace('.','_',trim($key));
	 if(substr($km,0,2)=='D_')
		$km = 'DOM_'.substr($km,2);
	 else if(substr($km,0,2)=='U_')
		$km = 'USA_'.substr($km,2);
	 else if(substr($km,0,2)=='I_')
		$km = 'INT_'.substr($km,2);
	return $km;
}
  
function canadapost_cfg_select_multioption($select_array, $key_value, $key = '') 
{
	for ($i=0; $i<sizeof($select_array); $i++) {
	  $name = (($key) ? 'configuration[' . $key . '][]' : 'configuration_value');
	  $string .= '<br><input type="checkbox" name="' . $name . '" value="' . $select_array[$i] . '"';
	  $key_values = explode( ", ", $key_value);
	  if ( in_array($select_array[$i], $key_values) ) $string .= ' CHECKED';
	  $string .= '> ' . constant('CANADA_POST_' . get_canada_post_service_code($select_array[$i]));
	} 
	$string .= '<input type="hidden" name="' . $name . '" value="--none--">';
	return $string;
}	
?>

Other files are mods to /admin/categories.php

Add code for defines....

 

 

Link to comment
Share on other sites

<script type="text/javascript" src="ext/responsivemenu/js/responsivemultimenu-LANGUAGE_CODE.js"></script>

Loading failed for the <script> with source “http://www.naughtypleasures.ca/ext/responsivemenu/js/responsivemultimenu-LANGUAGE_CODE.js”. checkout_shipping_address.php:216:1

 

JcM Categories Navbar 1.3 CE by - JcMagpie

\includes\modules\navbar_modules\templates\tpl_nb_horizontal_multi_menu.php

<script type="text/javascript" src="ext/responsivemenu/js/responsivemultimenu-<?php echo LANGUAGE_CODE; ?>.js"></script>

Only using 1 language so no big deal changing to 

<script type="text/javascript" src="ext/responsivemenu/js/responsivemultimenu-en.js"></script>

Making the above change makes it worse - ReferenceError: jQuery is not defined

 

 

Guessing this error is why I have no Canada Post Shipping showing, and why it says can't ship that address.

ReferenceError: $ is not defined[Learn More] checkout_shipping_address.php:574:5

 

Link to comment
Share on other sites

Logging out gives the same problem

Loading failed for the <script> with source “http://www.naughtypleasures.ca/ext/responsivemenu/js/responsivemultimenu-LANGUAGE_CODE.js”.

And another ReferenceError: $ is not defined

<script>
    $('ul.nav li.dropdown').hover(function() {

 

Checked the test site and these errors are not present.

Link to comment
Share on other sites

I will PM you.

 

ReferenceError: $ is not defined[Learn More] index.php:572:5
        <anonymous> http://www.naughtypleasures.ca/index.php:572

<script>
    $('ul.nav li.dropdown').hover(function() {
  $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeIn(500);
}, function() {
  $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeOut(500);
});
</script>

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...