Overview

Packages

  • currencysymbol
  • MAbout
  • Mage
    • Admin
    • Adminhtml
    • AdminNotification
    • Api
    • Api2
    • Authorizenet
    • Backup
    • Bundle
    • Captcha
    • Catalog
    • CatalogIndex
    • CatalogInventory
    • CatalogRule
    • CatalogSearch
    • Centinel
    • Checkout
    • Cms
    • Compiler
    • Connect
    • Contacts
    • Core
    • Cron
    • CurrencySymbol
    • Customer
    • Dataflow
    • Directory
    • DirtectPost
    • Downloadable
    • Eav
    • GiftMessage
    • GoogleAnalytics
    • GoogleBase
    • GoogleCheckout
    • ImportExport
    • Index
    • Install
    • Log
    • Media
    • Newsletter
    • Oauth
    • Page
    • PageCache
    • Paygate
    • Payment
    • Paypal
    • PaypalUk
    • Persistent
    • Poll
    • ProductAlert
    • Rating
    • Reports
    • Review
    • Rss
    • Rule
    • Sales
    • SalesRule
    • Sedfriend
    • Sendfriend
    • Shipping
    • Sitemap
    • Tag
    • Tax
    • Usa
    • Weee
    • Widget
    • Wishlist
    • XmlConnect
  • None
  • Phoenix
    • Moneybookers
  • PHP
  • Zend
    • Date
    • Mime
    • XmlRpc

Classes

  • Mage_Usa_Block_Adminhtml_Dhl_Unitofmeasure
  • Mage_Usa_Helper_Data
  • Mage_Usa_Model_Shipping_Carrier_Abstract
  • Mage_Usa_Model_Shipping_Carrier_Abstract_Source_Mode
  • Mage_Usa_Model_Shipping_Carrier_Abstract_Source_Requesttype
  • Mage_Usa_Model_Shipping_Carrier_Dhl
  • Mage_Usa_Model_Shipping_Carrier_Dhl_International
  • Mage_Usa_Model_Shipping_Carrier_Dhl_International_Source_Contenttype
  • Mage_Usa_Model_Shipping_Carrier_Dhl_International_Source_Method_Abstract
  • Mage_Usa_Model_Shipping_Carrier_Dhl_International_Source_Method_Doc
  • Mage_Usa_Model_Shipping_Carrier_Dhl_International_Source_Method_Freedoc
  • Mage_Usa_Model_Shipping_Carrier_Dhl_International_Source_Method_Freenondoc
  • Mage_Usa_Model_Shipping_Carrier_Dhl_International_Source_Method_Nondoc
  • Mage_Usa_Model_Shipping_Carrier_Dhl_International_Source_Method_Size
  • Mage_Usa_Model_Shipping_Carrier_Dhl_International_Source_Method_Unitofmeasure
  • Mage_Usa_Model_Shipping_Carrier_Dhl_Label_Pdf
  • Mage_Usa_Model_Shipping_Carrier_Dhl_Label_Pdf_Page
  • Mage_Usa_Model_Shipping_Carrier_Dhl_Label_Pdf_PageBuilder
  • Mage_Usa_Model_Shipping_Carrier_Dhl_Source_Dutypaymenttype
  • Mage_Usa_Model_Shipping_Carrier_Dhl_Source_Freemethod
  • Mage_Usa_Model_Shipping_Carrier_Dhl_Source_Method
  • Mage_Usa_Model_Shipping_Carrier_Dhl_Source_Protection_Rounding
  • Mage_Usa_Model_Shipping_Carrier_Dhl_Source_Protection_Value
  • Mage_Usa_Model_Shipping_Carrier_Dhl_Source_Shipmenttype
  • Mage_Usa_Model_Shipping_Carrier_Fedex
  • Mage_Usa_Model_Shipping_Carrier_Fedex_Source_Dropoff
  • Mage_Usa_Model_Shipping_Carrier_Fedex_Source_Freemethod
  • Mage_Usa_Model_Shipping_Carrier_Fedex_Source_Method
  • Mage_Usa_Model_Shipping_Carrier_Fedex_Source_Packaging
  • Mage_Usa_Model_Shipping_Carrier_Ups
  • Mage_Usa_Model_Shipping_Carrier_Ups_Source_Container
  • Mage_Usa_Model_Shipping_Carrier_Ups_Source_DestType
  • Mage_Usa_Model_Shipping_Carrier_Ups_Source_Freemethod
  • Mage_Usa_Model_Shipping_Carrier_Ups_Source_Method
  • Mage_Usa_Model_Shipping_Carrier_Ups_Source_OriginShipment
  • Mage_Usa_Model_Shipping_Carrier_Ups_Source_Pickup
  • Mage_Usa_Model_Shipping_Carrier_Ups_Source_Type
  • Mage_Usa_Model_Shipping_Carrier_Ups_Source_Unitofmeasure
  • Mage_Usa_Model_Shipping_Carrier_Usps
  • Mage_Usa_Model_Shipping_Carrier_Usps_Source_Container
  • Mage_Usa_Model_Shipping_Carrier_Usps_Source_Freemethod
  • Mage_Usa_Model_Shipping_Carrier_Usps_Source_Machinable
  • Mage_Usa_Model_Shipping_Carrier_Usps_Source_Method
  • Mage_Usa_Model_Shipping_Carrier_Usps_Source_Size
  • Overview
  • Package
  • Class
  • Tree
   1: <?php
   2: /**
   3:  * Magento
   4:  *
   5:  * NOTICE OF LICENSE
   6:  *
   7:  * This source file is subject to the Open Software License (OSL 3.0)
   8:  * that is bundled with this package in the file LICENSE.txt.
   9:  * It is also available through the world-wide-web at this URL:
  10:  * http://opensource.org/licenses/osl-3.0.php
  11:  * If you did not receive a copy of the license and are unable to
  12:  * obtain it through the world-wide-web, please send an email
  13:  * to license@magentocommerce.com so we can send you a copy immediately.
  14:  *
  15:  * DISCLAIMER
  16:  *
  17:  * Do not edit or add to this file if you wish to upgrade Magento to newer
  18:  * versions in the future. If you wish to customize Magento for your
  19:  * needs please refer to http://www.magentocommerce.com for more information.
  20:  *
  21:  * @category    Mage
  22:  * @package     Mage_Usa
  23:  * @copyright   Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
  24:  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  25:  */
  26: 
  27: /**
  28:  * DHL International (API v1.4)
  29:  *
  30:  * @category Mage
  31:  * @package  Mage_Usa
  32:  * @author   Magento Core Team <core@magentocommerce.com>
  33:  */
  34: class Mage_Usa_Model_Shipping_Carrier_Dhl_International
  35:     extends Mage_Usa_Model_Shipping_Carrier_Abstract
  36:     implements Mage_Shipping_Model_Carrier_Interface
  37: {
  38:     /**
  39:      * Carrier Product indicator
  40:      */
  41:     const DHL_CONTENT_TYPE_DOC        = 'D';
  42:     const DHL_CONTENT_TYPE_NON_DOC    = 'N';
  43: 
  44:     /**
  45:      * Minimum allowed values for shipping package dimensions
  46:      */
  47:     const DIMENSION_MIN_CM = 3;
  48:     const DIMENSION_MIN_IN = 1;
  49: 
  50:     /**
  51:      * Container types that could be customized
  52:      *
  53:      * @var array
  54:      */
  55:     protected $_customizableContainerTypes = array(self::DHL_CONTENT_TYPE_NON_DOC);
  56: 
  57:     /**
  58:      * Code of the carrier
  59:      */
  60:     const CODE = 'dhlint';
  61: 
  62:     /**
  63:      * Rate request data
  64:      *
  65:      * @var Mage_Shipping_Model_Rate_Request|null
  66:      */
  67:     protected $_request = null;
  68: 
  69:     /**
  70:      * Raw rate request data
  71:      *
  72:      * @var Varien_Object|null
  73:      */
  74:     protected $_rawRequest = null;
  75: 
  76:     /**
  77:      * Rate result data
  78:      *
  79:      * @var Mage_Shipping_Model_Rate_Result|null
  80:      */
  81:     protected $_result = null;
  82: 
  83:     /**
  84:      * Countries parameters data
  85:      *
  86:      * @var SimpleXMLElement|null
  87:      */
  88:     protected $_countryParams = null;
  89: 
  90:     /**
  91:      * Errors placeholder
  92:      *
  93:      * @var array
  94:      */
  95:     protected $_errors = array();
  96: 
  97:     /**
  98:      * Dhl rates result
  99:      *
 100:      * @var array
 101:      */
 102:     protected $_rates = array();
 103: 
 104:     /**
 105:      * Carrier's code
 106:      *
 107:      * @var string
 108:      */
 109:     protected $_code = self::CODE;
 110: 
 111:     /**
 112:      * Free Method config path
 113:      *
 114:      * @var string
 115:      */
 116:     protected $_freeMethod = 'free_method_nondoc';
 117: 
 118:     /**
 119:      * Max weight without fee
 120:      *
 121:      * @var int
 122:      */
 123:     protected $_maxWeight = 70;
 124: 
 125:     /**
 126:      * Flag if response is for shipping label creating
 127:      *
 128:      * @var bool
 129:      */
 130:     protected $_isShippingLabelFlag = false;
 131: 
 132:     /**
 133:      * Request variables array
 134:      *
 135:      * @var array
 136:      */
 137:     protected $_requestVariables = array(
 138:         'id'                => array('code' => 'dhl_id',                'setCode' => 'id'),
 139:         'password'          => array('code' => 'dhl_password',          'setCode' => 'password'),
 140:         'account'           => array('code' => 'dhl_account',           'setCode' => 'account_nbr'),
 141:         'shipping_key'      => array('code' => 'dhl_shipping_key',      'setCode' => 'shipping_key'),
 142:         'shipping_intlkey'  => array('code' => 'dhl_shipping_intl_key', 'setCode' => 'shipping_intl_key'),
 143:         'shipment_type'     => array('code' => 'dhl_shipment_type',     'setCode' => 'shipment_type'),
 144:         'dutiable'          => array('code' => 'dhl_dutiable',          'setCode' => 'dutiable'),
 145:         'dutypaymenttype'   => array('code' => 'dhl_duty_payment_type', 'setCode' => 'duty_payment_type'),
 146:         'contentdesc'       => array('code' => 'dhl_content_desc',      'setCode' => 'content_desc')
 147:     );
 148: 
 149:     /**
 150:      * Flag that shows if shipping is domestic
 151:      *
 152:      * @var bool
 153:      */
 154:     protected $_isDomestic = false;
 155: 
 156:     /**
 157:      * Dhl International Class constructor
 158:      *
 159:      * Sets necessary data
 160:      */
 161:     protected function _construct()
 162:     {
 163:         if ($this->getConfigData('content_type') == self::DHL_CONTENT_TYPE_DOC) {
 164:             $this->_freeMethod = 'free_method_doc';
 165:         }
 166:     }
 167: 
 168:     /**
 169:      * Returns value of given variable
 170:      *
 171:      * @param mixed $origValue
 172:      * @param string $pathToValue
 173:      * @return mixed
 174:      */
 175:     protected function _getDefaultValue($origValue, $pathToValue)
 176:     {
 177:         if (!$origValue) {
 178:             $origValue = Mage::getStoreConfig(
 179:                 $pathToValue,
 180:                 $this->getStore()
 181:             );
 182:         }
 183: 
 184:         return $origValue;
 185:     }
 186: 
 187:     /**
 188:      * Collect and get rates
 189:      *
 190:      * @param Mage_Shipping_Model_Rate_Request $request
 191:      * @return bool|Mage_Shipping_Model_Rate_Result|null
 192:      */
 193:     public function collectRates(Mage_Shipping_Model_Rate_Request $request)
 194:     {
 195:         if (!$this->getConfigFlag($this->_activeFlag)) {
 196:             return false;
 197:         }
 198: 
 199:         $requestDhl     = clone $request;
 200:         $this->setStore($requestDhl->getStoreId());
 201: 
 202:         $origCompanyName = $this->_getDefaultValue(
 203:             $requestDhl->getOrigCompanyName(),
 204:             Mage_Core_Model_Store::XML_PATH_STORE_STORE_NAME
 205:         );
 206:         $origCountryId = $this->_getDefaultValue(
 207:             $requestDhl->getOrigCountryId(),
 208:             Mage_Shipping_Model_Shipping::XML_PATH_STORE_COUNTRY_ID
 209:         );
 210:         $origState = $this->_getDefaultValue(
 211:             $requestDhl->getOrigState(),
 212:             Mage_Shipping_Model_Shipping::XML_PATH_STORE_REGION_ID
 213:         );
 214:         $origCity = $this->_getDefaultValue(
 215:             $requestDhl->getOrigCity(),
 216:             Mage_Shipping_Model_Shipping::XML_PATH_STORE_CITY
 217:         );
 218:         $origPostcode = $this->_getDefaultValue(
 219:             $requestDhl->getOrigPostcode(),
 220:             Mage_Shipping_Model_Shipping::XML_PATH_STORE_ZIP
 221:         );
 222: 
 223:         $requestDhl->setOrigCompanyName($origCompanyName)
 224:             ->setCountryId($origCountryId)
 225:             ->setOrigState($origState)
 226:             ->setOrigCity($origCity)
 227:             ->setOrigPostal($origPostcode);
 228:         $this->setRequest($requestDhl);
 229: 
 230:         $this->_result = $this->_getQuotes();
 231: 
 232:         $this->_updateFreeMethodQuote($request);
 233: 
 234:         return $this->_result;
 235:     }
 236: 
 237:     /**
 238:      * Set Free Method Request
 239:      *
 240:      * @param  string $freeMethod
 241:      * @return void
 242:      */
 243:     protected function _setFreeMethodRequest($freeMethod)
 244:     {
 245:         $rawRequest = $this->_rawRequest;
 246: 
 247:         $rawRequest->setFreeMethodRequest(true);
 248:         $freeWeight = $this->getTotalNumOfBoxes($rawRequest->getFreeMethodWeight());
 249:         $rawRequest->setWeight($freeWeight);
 250:         $rawRequest->setService($freeMethod);
 251:     }
 252: 
 253:     /**
 254:      * Returns request result
 255:      *
 256:      * @return Mage_Shipping_Model_Rate_Result|null
 257:      */
 258:     public function getResult()
 259:     {
 260:         return $this->_result;
 261:     }
 262: 
 263:     protected function _addParams($requestObject)
 264:     {
 265:         $request = $this->_request;
 266:         foreach ($this->_requestVariables as $code => $objectCode) {
 267:             if ($request->getDhlId()) {
 268:                 $value = $request->getData($objectCode['code']);
 269:             } else {
 270:                 $value = $this->getConfigData($code);
 271:             }
 272:             $requestObject->setData($objectCode['setCode'], $value);
 273:         }
 274:         return $requestObject;
 275:     }
 276: 
 277:     /**
 278:      * Prepare and set request in property of current instance
 279:      *
 280:      * @param Varien_Object $request
 281:      * @return Mage_Usa_Model_Shipping_Carrier_Dhl
 282:      */
 283:     public function setRequest(Varien_Object $request)
 284:     {
 285:         $this->_request = $request;
 286:         $this->setStore($request->getStoreId());
 287: 
 288:         $requestObject = new Varien_Object();
 289: 
 290:         $requestObject->setIsGenerateLabelReturn($request->getIsGenerateLabelReturn());
 291: 
 292:         $requestObject->setStoreId($request->getStoreId());
 293: 
 294:         if ($request->getLimitMethod()) {
 295:             $requestObject->setService($request->getLimitMethod());
 296:         }
 297: 
 298:         $requestObject = $this->_addParams($requestObject);
 299: 
 300:         if ($request->getDestPostcode()) {
 301:             $requestObject->setDestPostal($request->getDestPostcode());
 302:         }
 303: 
 304:         $requestObject->setOrigCountry(
 305:                 $this->_getDefaultValue(
 306:                     $request->getOrigCountry(), Mage_Shipping_Model_Shipping::XML_PATH_STORE_COUNTRY_ID)
 307:             )
 308:             ->setOrigCountryId(
 309:                 $this->_getDefaultValue(
 310:                     $request->getOrigCountryId(), Mage_Shipping_Model_Shipping::XML_PATH_STORE_COUNTRY_ID)
 311:             );
 312: 
 313:         $shippingWeight = $request->getPackageWeight();
 314: 
 315:         $requestObject->setValue(round($request->getPackageValue(), 2))
 316:             ->setValueWithDiscount($request->getPackageValueWithDiscount())
 317:             ->setCustomsValue($request->getPackageCustomsValue())
 318:             ->setDestStreet(
 319:                 Mage::helper('core/string')->substr(str_replace("\n", '', $request->getDestStreet()), 0, 35))
 320:             ->setDestStreetLine2($request->getDestStreetLine2())
 321:             ->setDestCity($request->getDestCity())
 322:             ->setOrigCompanyName($request->getOrigCompanyName())
 323:             ->setOrigCity($request->getOrigCity())
 324:             ->setOrigPhoneNumber($request->getOrigPhoneNumber())
 325:             ->setOrigPersonName($request->getOrigPersonName())
 326:             ->setOrigEmail(Mage::getStoreConfig('trans_email/ident_general/email', $requestObject->getStoreId()))
 327:             ->setOrigCity($request->getOrigCity())
 328:             ->setOrigPostal($request->getOrigPostal())
 329:             ->setOrigStreetLine2($request->getOrigStreetLine2())
 330:             ->setDestPhoneNumber($request->getDestPhoneNumber())
 331:             ->setDestPersonName($request->getDestPersonName())
 332:             ->setDestCompanyName($request->getDestCompanyName());
 333: 
 334:         $originStreet2 = Mage::getStoreConfig(
 335:                 Mage_Shipping_Model_Shipping::XML_PATH_STORE_ADDRESS2, $requestObject->getStoreId());
 336: 
 337:         $requestObject->setOrigStreet($request->getOrigStreet() ? $request->getOrigStreet() : $originStreet2);
 338: 
 339:         if (is_numeric($request->getOrigState())) {
 340:             $requestObject->setOrigState(Mage::getModel('directory/region')->load($request->getOrigState())->getCode());
 341:         } else {
 342:             $requestObject->setOrigState($request->getOrigState());
 343:         }
 344: 
 345:         if ($request->getDestCountryId()) {
 346:             $destCountry = $request->getDestCountryId();
 347:         } else {
 348:             $destCountry = self::USA_COUNTRY_ID;
 349:         }
 350: 
 351:         // for DHL, Puerto Rico state for US will assume as Puerto Rico country
 352:         // for Puerto Rico, dhl will ship as international
 353:         if ($destCountry == self::USA_COUNTRY_ID && ($request->getDestPostcode() == '00912'
 354:                                                      || $request->getDestRegionCode() == self::PUERTORICO_COUNTRY_ID)
 355:         ) {
 356:             $destCountry = self::PUERTORICO_COUNTRY_ID;
 357:         }
 358: 
 359:         $requestObject->setDestCountryId($destCountry)
 360:             ->setDestState($request->getDestRegionCode())
 361:             ->setWeight($shippingWeight)
 362:             ->setFreeMethodWeight($request->getFreeMethodWeight())
 363:             ->setOrderShipment($request->getOrderShipment());
 364: 
 365:         if ($request->getPackageId()) {
 366:             $requestObject->setPackageId($request->getPackageId());
 367:         }
 368: 
 369:         $requestObject->setBaseSubtotalInclTax($request->getBaseSubtotalInclTax());
 370: 
 371:         $this->_rawRequest = $requestObject;
 372:         return $this;
 373:     }
 374: 
 375:     /**
 376:      * Get allowed shipping methods
 377:      *
 378:      * @return array
 379:      */
 380:     public function getAllowedMethods()
 381:     {
 382:         $contentType = $this->getConfigData('content_type');
 383:         $allowedMethods = array();
 384:         if ($this->_isDomestic) {
 385:             $allowedMethods = array_merge(explode(',', $this->getConfigData('doc_methods')),
 386:                 explode(',', $this->getConfigData('nondoc_methods'))
 387:             );
 388:         } else {
 389:             switch ($contentType) {
 390:                 case self::DHL_CONTENT_TYPE_DOC:
 391:                     $allowedMethods = explode(',', $this->getConfigData('doc_methods'));
 392:                     break;
 393:                 case self::DHL_CONTENT_TYPE_NON_DOC:
 394:                     $allowedMethods = explode(',', $this->getConfigData('nondoc_methods'));
 395:                     break;
 396:                 default:
 397:                     Mage::throwException(Mage::helper('usa')->__('Wrong Content Type.'));
 398:             }
 399:         }
 400:         $methods = array();
 401:         foreach ($allowedMethods as $method) {
 402:             $methods[$method] = $this->getDhlProductTitle($method);
 403:         }
 404:         return $methods;
 405:     }
 406: 
 407:     /**
 408:      * Get configuration data of carrier
 409:      *
 410:      * @param strin $type
 411:      * @param string $code
 412:      * @return array|bool
 413:      */
 414:     public function getCode($type, $code = '')
 415:     {
 416:         $codes = array(
 417:             'unit_of_measure'   => array(
 418:                 'L' => Mage::helper('usa')->__('Pounds'),
 419:                 'K' => Mage::helper('usa')->__('Kilograms'),
 420:             ),
 421:             'unit_of_dimension' => array(
 422:                 'I' => Mage::helper('usa')->__('Inches'),
 423:                 'C' => Mage::helper('usa')->__('Centimeters'),
 424:             ),
 425:             'unit_of_dimension_cut' => array(
 426:                 'I' => Mage::helper('usa')->__('inch'),
 427:                 'C' => Mage::helper('usa')->__('cm'),
 428:             ),
 429:             'dimensions' => array(
 430:                 'HEIGHT'    => Mage::helper('usa')->__('Height'),
 431:                 'DEPTH'     => Mage::helper('usa')->__('Depth'),
 432:                 'WIDTH'     => Mage::helper('usa')->__('Width'),
 433:             ),
 434:             'size'              => array(
 435:                 '0' => Mage::helper('usa')->__('Regular'),
 436:                 '1' => Mage::helper('usa')->__('Specific'),
 437:             ),
 438:             'dimensions_variables'  => array(
 439:                 'L'         => Zend_Measure_Weight::POUND,
 440:                 'LB'        => Zend_Measure_Weight::POUND,
 441:                 'POUND'     => Zend_Measure_Weight::POUND,
 442:                 'K'         => Zend_Measure_Weight::KILOGRAM,
 443:                 'KG'        => Zend_Measure_Weight::KILOGRAM,
 444:                 'KILOGRAM'  => Zend_Measure_Weight::KILOGRAM,
 445:                 'I'         => Zend_Measure_Length::INCH,
 446:                 'IN'        => Zend_Measure_Length::INCH,
 447:                 'INCH'      => Zend_Measure_Length::INCH,
 448:                 'C'         => Zend_Measure_Length::CENTIMETER,
 449:                 'CM'        => Zend_Measure_Length::CENTIMETER,
 450:                 'CENTIMETER'=> Zend_Measure_Length::CENTIMETER,
 451: 
 452:             )
 453:         );
 454: 
 455:         if (!isset($codes[$type])) {
 456:             return false;
 457:         } elseif ('' === $code) {
 458:             return $codes[$type];
 459:         }
 460: 
 461:         $code = strtoupper($code);
 462:         if (!isset($codes[$type][$code])) {
 463:             return false;
 464:         } else {
 465:             return $codes[$type][$code];
 466:         }
 467:     }
 468: 
 469:     /**
 470:      * Returns DHL shipment methods (depending on package content type, if necessary)
 471:      *
 472:      * @param string $doc Package content type (doc/non-doc) see DHL_CONTENT_TYPE_* constants
 473:      * @return array
 474:      */
 475:     public function getDhlProducts($doc)
 476:     {
 477:         $docType = array(
 478:             '2' => Mage::helper('usa')->__('Easy shop'),
 479:             '5' => Mage::helper('usa')->__('Sprintline'),
 480:             '6' => Mage::helper('usa')->__('Secureline'),
 481:             '7' => Mage::helper('usa')->__('Express easy'),
 482:             '9' => Mage::helper('usa')->__('Europack'),
 483:             'B' => Mage::helper('usa')->__('Break bulk express'),
 484:             'C' => Mage::helper('usa')->__('Medical express'),
 485:             'D' => Mage::helper('usa')->__('Express worldwide'), // product content code: DOX
 486:             'U' => Mage::helper('usa')->__('Express worldwide'), // product content code: ECX
 487:             'K' => Mage::helper('usa')->__('Express 9:00'),
 488:             'L' => Mage::helper('usa')->__('Express 10:30'),
 489:             'G' => Mage::helper('usa')->__('Domestic economy select'),
 490:             'W' => Mage::helper('usa')->__('Economy select'),
 491:             'I' => Mage::helper('usa')->__('Break bulk economy'),
 492:             'N' => Mage::helper('usa')->__('Domestic express'),
 493:             'O' => Mage::helper('usa')->__('Others'),
 494:             'R' => Mage::helper('usa')->__('Globalmail business'),
 495:             'S' => Mage::helper('usa')->__('Same day'),
 496:             'T' => Mage::helper('usa')->__('Express 12:00'),
 497:             'X' => Mage::helper('usa')->__('Express envelope'),
 498:         );
 499: 
 500:         $nonDocType = array(
 501:             '1' => Mage::helper('usa')->__('Customer services'),
 502:             '3' => Mage::helper('usa')->__('Easy shop'),
 503:             '4' => Mage::helper('usa')->__('Jetline'),
 504:             '8' => Mage::helper('usa')->__('Express easy'),
 505:             'P' => Mage::helper('usa')->__('Express worldwide'),
 506:             'Q' => Mage::helper('usa')->__('Medical express'),
 507:             'E' => Mage::helper('usa')->__('Express 9:00'),
 508:             'F' => Mage::helper('usa')->__('Freight worldwide'),
 509:             'H' => Mage::helper('usa')->__('Economy select'),
 510:             'J' => Mage::helper('usa')->__('Jumbo box'),
 511:             'M' => Mage::helper('usa')->__('Express 10:30'),
 512:             'V' => Mage::helper('usa')->__('Europack'),
 513:             'Y' => Mage::helper('usa')->__('Express 12:00'),
 514:         );
 515: 
 516:         if ($this->_isDomestic) {
 517:             return $docType + $nonDocType;
 518:         }
 519:         if ($doc == self::DHL_CONTENT_TYPE_DOC) {
 520:             // Documents shipping
 521:             return $docType;
 522:         } else {
 523:             // Services for shipping non-documents cargo
 524:             return $nonDocType;
 525:         }
 526:     }
 527: 
 528:     /**
 529:      * Returns title of DHL shipping method by its code
 530:      *
 531:      * @param string $code One-symbol code (see getDhlProducts())
 532:      * @return bool
 533:      */
 534:     public function getDhlProductTitle($code)
 535:     {
 536:         $contentType = $this->getConfigData('content_type');
 537:         $dhlProducts = $this->getDhlProducts($contentType);
 538:         return isset($dhlProducts[$code]) ? $dhlProducts[$code] : false;
 539:     }
 540: 
 541:     /**
 542:      * Convert item weight to needed weight based on config weight unit dimensions
 543:      *
 544:      * @param float $weight
 545:      * @param bool $maxWeight
 546:      * @param string|bool $configWeightUnit
 547:      * @return float
 548:      */
 549:     protected function _getWeight($weight, $maxWeight = false, $configWeightUnit = false)
 550:     {
 551:         if ($maxWeight) {
 552:             $configWeightUnit = Zend_Measure_Weight::KILOGRAM;
 553:         } elseif ($configWeightUnit) {
 554:             $configWeightUnit = $this->getCode('dimensions_variables', $configWeightUnit);
 555:         } else {
 556:             $configWeightUnit = $this->getCode('dimensions_variables', (string)$this->getConfigData('unit_of_measure'));
 557:         }
 558: 
 559:         $countryWeightUnit = $this->getCode('dimensions_variables', $this->_getWeightUnit());
 560: 
 561:         if ($configWeightUnit != $countryWeightUnit) {
 562:             $weight = Mage::helper('usa')->convertMeasureWeight(
 563:                 round($weight,3),
 564:                 $configWeightUnit,
 565:                 $countryWeightUnit
 566:             );
 567:         }
 568: 
 569:         return round($weight, 3);
 570:     }
 571: 
 572:     /**
 573:      * Prepare items to pieces
 574:      *
 575:      * @return array
 576:      */
 577:     protected function _getAllItems()
 578:     {
 579:         $allItems   = $this->_request->getAllItems();
 580:         $fullItems  = array();
 581: 
 582:         foreach ($allItems as $item) {
 583:             if ($item->getProductType() == Mage_Catalog_Model_Product_Type::TYPE_BUNDLE
 584:                 && $item->getProduct()->getShipmentType()
 585:             ) {
 586:                 continue;
 587:             }
 588: 
 589:             $qty            = $item->getQty();
 590:             $changeQty      = true;
 591:             $checkWeight    = true;
 592:             $decimalItems   = array();
 593: 
 594:             if ($item->getParentItem()) {
 595:                 if (!$item->getParentItem()->getProduct()->getShipmentType()) {
 596:                     continue;
 597:                 }
 598:                 $qty = $item->getIsQtyDecimal()
 599:                     ? $item->getParentItem()->getQty()
 600:                     : $item->getParentItem()->getQty() * $item->getQty();
 601:             }
 602: 
 603:             $itemWeight = $item->getWeight();
 604:             if ($item->getIsQtyDecimal() && $item->getProductType() != Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) {
 605:                 $stockItem = $item->getProduct()->getStockItem();
 606:                 if ($stockItem->getIsDecimalDivided()) {
 607:                    if ($stockItem->getEnableQtyIncrements() && $stockItem->getQtyIncrements()) {
 608:                         $itemWeight = $itemWeight * $stockItem->getQtyIncrements();
 609:                         $qty        = round(($item->getWeight() / $itemWeight) * $qty);
 610:                         $changeQty  = false;
 611:                    } else {
 612:                        $itemWeight = $this->_getWeight($itemWeight * $item->getQty());
 613:                        $maxWeight  = $this->_getWeight($this->_maxWeight, true);
 614:                        if ($itemWeight > $maxWeight) {
 615:                            $qtyItem = floor($itemWeight / $maxWeight);
 616:                            $decimalItems[] = array('weight' => $maxWeight, 'qty' => $qtyItem);
 617:                            $weightItem = Mage::helper('core')->getExactDivision($itemWeight, $maxWeight);
 618:                            if ($weightItem) {
 619:                                $decimalItems[] = array('weight' => $weightItem, 'qty' => 1);
 620:                            }
 621:                            $checkWeight = false;
 622:                        } else {
 623:                            $itemWeight = $itemWeight * $item->getQty();
 624:                        }
 625:                    }
 626:                 } else {
 627:                     $itemWeight = $itemWeight * $item->getQty();
 628:                 }
 629:             }
 630: 
 631:             if ($checkWeight && $this->_getWeight($itemWeight) > $this->_getWeight($this->_maxWeight, true)) {
 632:                 return array();
 633:             }
 634: 
 635:             if ($changeQty && !$item->getParentItem() && $item->getIsQtyDecimal()
 636:                 && $item->getProductType() != Mage_Catalog_Model_Product_Type::TYPE_BUNDLE
 637:             ) {
 638:                 $qty = 1;
 639:             }
 640: 
 641:             if (!empty($decimalItems)) {
 642:                 foreach ($decimalItems as $decimalItem) {
 643:                     $fullItems = array_merge($fullItems,
 644:                         array_fill(0, $decimalItem['qty'] * $qty, $decimalItem['weight'])
 645:                     );
 646:                 }
 647:             } else {
 648:                 $fullItems = array_merge($fullItems, array_fill(0, $qty, $this->_getWeight($itemWeight)));
 649:             }
 650:         }
 651:         sort($fullItems);
 652: 
 653:         return $fullItems;
 654:     }
 655: 
 656:     /**
 657:      * Make pieces
 658:      *
 659:      * @param SimpleXMLElement $nodeBkgDetails
 660:      * @return void
 661:      */
 662:     protected function _makePieces(SimpleXMLElement $nodeBkgDetails)
 663:     {
 664:         $divideOrderWeight = (string)$this->getConfigData('divide_order_weight');
 665:         $nodePieces = $nodeBkgDetails->addChild('Pieces', '', '');
 666:         $items = $this->_getAllItems();
 667:         $numberOfPieces = 0;
 668: 
 669:         if ($divideOrderWeight && !empty($items)) {
 670:             $maxWeight = $this->_getWeight($this->_maxWeight, true);
 671:             $sumWeight = 0;
 672: 
 673:             $reverseOrderItems = $items;
 674:             arsort($reverseOrderItems);
 675: 
 676:             foreach ($reverseOrderItems as $key => $weight) {
 677:                 if (!isset($items[$key])) {
 678:                     continue;
 679:                 }
 680:                 unset($items[$key]);
 681:                 $sumWeight = $weight;
 682:                 foreach ($items as $key => $weight) {
 683:                     if (($sumWeight + $weight) < $maxWeight) {
 684:                         unset($items[$key]);
 685:                         $sumWeight += $weight;
 686:                     } elseif (($sumWeight + $weight) > $maxWeight) {
 687:                         $numberOfPieces++;
 688:                         $nodePiece = $nodePieces->addChild('Piece', '', '');
 689:                         $nodePiece->addChild('PieceID', $numberOfPieces);
 690:                         $this->_addDimension($nodePiece);
 691:                         $nodePiece->addChild('Weight', $sumWeight);
 692:                         break;
 693:                     } else {
 694:                         unset($items[$key]);
 695:                         $numberOfPieces++;
 696:                         $sumWeight += $weight;
 697:                         $nodePiece = $nodePieces->addChild('Piece', '', '');
 698:                         $nodePiece->addChild('PieceID', $numberOfPieces);
 699:                         $this->_addDimension($nodePiece);
 700:                         $nodePiece->addChild('Weight', $sumWeight);
 701:                         $sumWeight = 0;
 702:                         break;
 703:                     }
 704:                 }
 705:             }
 706:             if ($sumWeight > 0) {
 707:                 $numberOfPieces++;
 708:                 $nodePiece = $nodePieces->addChild('Piece', '', '');
 709:                 $nodePiece->addChild('PieceID', $numberOfPieces);
 710:                 $this->_addDimension($nodePiece);
 711:                 $nodePiece->addChild('Weight', $sumWeight);
 712:             }
 713:         } else {
 714:             $nodePiece = $nodePieces->addChild('Piece', '', '');
 715:             $nodePiece->addChild('PieceID', 1);
 716:             $this->_addDimension($nodePiece);
 717:             $nodePiece->addChild('Weight', $this->_getWeight($this->_rawRequest->getWeight()));
 718:         }
 719: 
 720:         $handlingAction = $this->getConfigData('handling_action');
 721:         if ($handlingAction == Mage_Shipping_Model_Carrier_Abstract::HANDLING_ACTION_PERORDER || !$numberOfPieces) {
 722:             $numberOfPieces = 1;
 723:         }
 724:         $this->_numBoxes = $numberOfPieces;
 725:     }
 726: 
 727:     /**
 728:      * Convert item dimension to needed dimension based on config dimension unit of measure
 729:      *
 730:      * @param float $dimension
 731:      * @param string|bool $configWeightUnit
 732:      * @return float
 733:      */
 734:     protected function _getDimension($dimension, $configWeightUnit = false)
 735:     {
 736:         if (!$configWeightUnit) {
 737:             $configWeightUnit = $this->getCode('dimensions_variables', (string)$this->getConfigData('unit_of_measure'));
 738:         } else {
 739:             $configWeightUnit = $this->getCode('dimensions_variables', $configWeightUnit);
 740:         }
 741: 
 742:         if ($configWeightUnit == Zend_Measure_Weight::POUND) {
 743:             $configDimensionUnit = Zend_Measure_Length::INCH;
 744:         } else {
 745:             $configDimensionUnit = Zend_Measure_Length::CENTIMETER;
 746:         }
 747: 
 748:         $countryDimensionUnit = $this->getCode('dimensions_variables', $this->_getDimensionUnit());
 749: 
 750:         if ($configDimensionUnit != $countryDimensionUnit) {
 751:             $dimension = Mage::helper('usa')->convertMeasureDimension(
 752:                 round($dimension, 3),
 753:                 $configDimensionUnit,
 754:                 $countryDimensionUnit
 755:             );
 756:         }
 757: 
 758:         return round($dimension, 3);
 759:     }
 760: 
 761:     /**
 762:      * Add dimension to piece
 763:      *
 764:      * @param SimpleXMLElement $nodePiece
 765:      * @return void
 766:      */
 767:     protected function _addDimension($nodePiece)
 768:     {
 769:         $sizeChecker = (string)$this->getConfigData('size');
 770: 
 771:         $height = $this->_getDimension((string)$this->getConfigData('height'));
 772:         $depth = $this->_getDimension((string)$this->getConfigData('depth'));
 773:         $width = $this->_getDimension((string)$this->getConfigData('width'));
 774: 
 775:         if ($sizeChecker && $height && $depth && $width) {
 776:             $nodePiece->addChild('Height', $height);
 777:             $nodePiece->addChild('Depth', $depth);
 778:             $nodePiece->addChild('Width', $width);
 779:         }
 780:     }
 781: 
 782:     /**
 783:      * Get shipping quotes
 784:      *
 785:      * @return Mage_Core_Model_Abstract|Mage_Shipping_Model_Rate_Result
 786:      */
 787:     protected function _getQuotes()
 788:     {
 789:         $rawRequest = $this->_rawRequest;
 790:         $xmlStr = '<?xml version = "1.0" encoding = "UTF-8"?>'
 791:                 . '<p:DCTRequest xmlns:p="http://www.dhl.com" xmlns:p1="http://www.dhl.com/datatypes" '
 792:                 . 'xmlns:p2="http://www.dhl.com/DCTRequestdatatypes" '
 793:                 . 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '
 794:                 . 'xsi:schemaLocation="http://www.dhl.com DCT-req.xsd "/>';
 795:         $xml = new SimpleXMLElement($xmlStr);
 796:         $nodeGetQuote = $xml->addChild('GetQuote', '', '');
 797:         $nodeRequest = $nodeGetQuote->addChild('Request');
 798: 
 799:         $nodeServiceHeader = $nodeRequest->addChild('ServiceHeader');
 800:         $nodeServiceHeader->addChild('SiteID', (string)$this->getConfigData('id'));
 801:         $nodeServiceHeader->addChild('Password', (string)$this->getConfigData('password'));
 802: 
 803:         $nodeFrom = $nodeGetQuote->addChild('From');
 804:         $nodeFrom->addChild('CountryCode', $rawRequest->getOrigCountryId());
 805:         $nodeFrom->addChild('Postalcode', $rawRequest->getOrigPostal());
 806:         $nodeFrom->addChild('City', $rawRequest->getOrigCity());
 807: 
 808:         $nodeBkgDetails = $nodeGetQuote->addChild('BkgDetails');
 809:         $nodeBkgDetails->addChild('PaymentCountryCode', $rawRequest->getOrigCountryId());
 810:         $nodeBkgDetails->addChild('Date', Varien_Date::now(true));
 811:         $nodeBkgDetails->addChild('ReadyTime', 'PT' . (int)(string)$this->getConfigData('ready_time') . 'H00M');
 812: 
 813:         $nodeBkgDetails->addChild('DimensionUnit', $this->_getDimensionUnit());
 814:         $nodeBkgDetails->addChild('WeightUnit', $this->_getWeightUnit());
 815: 
 816:         $this->_makePieces($nodeBkgDetails);
 817: 
 818:         $nodeBkgDetails->addChild('PaymentAccountNumber', (string)$this->getConfigData('account'));
 819: 
 820:         $nodeTo = $nodeGetQuote->addChild('To');
 821:         $nodeTo->addChild('CountryCode', $rawRequest->getDestCountryId());
 822:         $nodeTo->addChild('Postalcode', $rawRequest->getDestPostal());
 823:         $nodeTo->addChild('City', $rawRequest->getDestCity());
 824: 
 825:         $this->_checkDomesticStatus($rawRequest->getOrigCountryId(), $rawRequest->getDestCountryId());
 826: 
 827:         if ($this->getConfigData('content_type') == self::DHL_CONTENT_TYPE_NON_DOC && !$this->_isDomestic) {
 828:             // IsDutiable flag and Dutiable node indicates that cargo is not a documentation
 829:             $nodeBkgDetails->addChild('IsDutiable', 'Y');
 830:             $nodeDutiable = $nodeGetQuote->addChild('Dutiable');
 831:             $baseCurrencyCode = Mage::app()->getWebsite($this->_request->getWebsiteId())->getBaseCurrencyCode();
 832:             $nodeDutiable->addChild('DeclaredCurrency', $baseCurrencyCode);
 833:             $nodeDutiable->addChild('DeclaredValue', sprintf("%.2F", $rawRequest->getValue()));
 834:         }
 835: 
 836:         $request = $xml->asXML();
 837:         $request = utf8_encode($request);
 838:         $responseBody = $this->_getCachedQuotes($request);
 839:         if ($responseBody === null) {
 840:             $debugData = array('request' => $request);
 841:             try {
 842:                 $client = new Varien_Http_Client();
 843:                 $client->setUri((string)$this->getConfigData('gateway_url'));
 844:                 $client->setConfig(array('maxredirects' => 0, 'timeout' => 30));
 845:                 $client->setRawData($request);
 846:                 $responseBody = $client->request(Varien_Http_Client::POST)->getBody();
 847:                 $debugData['result'] = $responseBody;
 848:                 $this->_setCachedQuotes($request, $responseBody);
 849:             } catch (Exception $e) {
 850:                 $this->_errors[$e->getCode()] = $e->getMessage();
 851:                 $responseBody = '';
 852:             }
 853:             $this->_debug($debugData);
 854:         }
 855: 
 856:         return $this->_parseResponse($responseBody);
 857:     }
 858: 
 859:     /**
 860:      * Parse response from DHL web service
 861:      *
 862:      * @param string $response
 863:      * @return Mage_Shipping_Model_Rate_Result
 864:      */
 865:     protected function _parseResponse($response)
 866:     {
 867:         $htmlTranslationTable = get_html_translation_table(HTML_ENTITIES);
 868:         unset($htmlTranslationTable['<'], $htmlTranslationTable['>'], $htmlTranslationTable['"']);
 869:         $response = str_replace(array_keys($htmlTranslationTable), array_values($htmlTranslationTable), $response);
 870: 
 871:         $responseError =  Mage::helper('usa')->__('The response is in wrong format.');
 872: 
 873:         if (strlen(trim($response)) > 0) {
 874:             if (strpos(trim($response), '<?xml') === 0) {
 875:                 $xml = simplexml_load_string($response);
 876:                 if (is_object($xml)) {
 877:                     if (in_array($xml->getName(), array('ErrorResponse', 'ShipmentValidateErrorResponse'))
 878:                         || isset($xml->GetQuoteResponse->Note->Condition)
 879:                     ) {
 880:                         $code = null;
 881:                         $data = null;
 882:                         if (isset($xml->Response->Status->Condition)) {
 883:                             $nodeCondition = $xml->Response->Status->Condition;
 884:                         } else {
 885:                             $nodeCondition = $xml->GetQuoteResponse->Note->Condition;
 886:                         }
 887: 
 888:                         if ($this->_isShippingLabelFlag) {
 889:                             foreach ($nodeCondition as $condition) {
 890:                                 $code = isset($condition->ConditionCode) ? (string)$condition->ConditionCode : 0;
 891:                                 $data = isset($condition->ConditionData) ? (string)$condition->ConditionData : '';
 892:                                 if (!empty($code) && !empty($data)) {
 893:                                     break;
 894:                                 }
 895:                             }
 896:                             Mage::throwException(Mage::helper('usa')->__('Error #%s : %s', trim($code), trim($data)));
 897:                         }
 898: 
 899:                         $code = isset($nodeCondition->ConditionCode) ? (string)$nodeCondition->ConditionCode : 0;
 900:                         $data = isset($nodeCondition->ConditionData) ? (string)$nodeCondition->ConditionData : '';
 901:                         $this->_errors[$code] = Mage::helper('usa')->__('Error #%s : %s', trim($code), trim($data));
 902:                     } else {
 903:                         if (isset($xml->GetQuoteResponse->BkgDetails->QtdShp)) {
 904:                             foreach ($xml->GetQuoteResponse->BkgDetails->QtdShp as $quotedShipment) {
 905:                                 $this->_addRate($quotedShipment);
 906:                             }
 907:                         } elseif (isset($xml->AirwayBillNumber)) {
 908:                             $result = new Varien_Object();
 909:                             $result->setTrackingNumber((string)$xml->AirwayBillNumber);
 910:                             try {
 911:                                 /* @var $pdf Mage_Usa_Model_Shipping_Carrier_Dhl_Label_Pdf */
 912:                                 $pdf = Mage::getModel(
 913:                                     'usa/shipping_carrier_dhl_label_pdf',
 914:                                     array('info' => $xml, 'request' => $this->_request)
 915:                                 );
 916:                                 $result->setShippingLabelContent($pdf->render());
 917:                             } catch (Exception $e) {
 918:                                 Mage::throwException(Mage::helper('usa')->__($e->getMessage()));
 919:                             }
 920:                             return $result;
 921:                         } else {
 922:                             $this->_errors[] = $responseError;
 923:                         }
 924:                     }
 925:                 }
 926:             } else {
 927:                 $this->_errors[] = $responseError;
 928:             }
 929:         } else {
 930:             $this->_errors[] = $responseError;
 931:         }
 932: 
 933:         /* @var $result Mage_Shipping_Model_Rate_Result */
 934:         $result = Mage::getModel('shipping/rate_result');
 935:         if ($this->_rates) {
 936:             foreach ($this->_rates as $rate) {
 937:                 $method = $rate['service'];
 938:                 $data = $rate['data'];
 939:                 /* @var $rate Mage_Shipping_Model_Rate_Result_Method */
 940:                 $rate = Mage::getModel('shipping/rate_result_method');
 941:                 $rate->setCarrier(self::CODE);
 942:                 $rate->setCarrierTitle($this->getConfigData('title'));
 943:                 $rate->setMethod($method);
 944:                 $rate->setMethodTitle($data['term']);
 945:                 $rate->setCost($data['price_total']);
 946:                 $rate->setPrice($data['price_total']);
 947:                 $result->append($rate);
 948:             }
 949:         } else if (!empty($this->_errors)) {
 950:             if ($this->_isShippingLabelFlag) {
 951:                 Mage::throwException($responseError);
 952:             }
 953:             return $this->_showError();
 954:         }
 955:         return $result;
 956:     }
 957: 
 958:     /**
 959:      * Add rate to DHL rates array
 960:      *
 961:      * @param SimpleXMLElement $shipmentDetails
 962:      * @return Mage_Usa_Model_Shipping_Carrier_Dhl_International
 963:      */
 964:     protected function _addRate(SimpleXMLElement $shipmentDetails)
 965:     {
 966:         if (isset($shipmentDetails->ProductShortName)
 967:             && isset($shipmentDetails->ShippingCharge)
 968:             && isset($shipmentDetails->GlobalProductCode)
 969:             && isset($shipmentDetails->CurrencyCode)
 970:             && array_key_exists((string)$shipmentDetails->GlobalProductCode, $this->getAllowedMethods())
 971:         ) {
 972:             // DHL product code, e.g. '3', 'A', 'Q', etc.
 973:             $dhlProduct             = (string)$shipmentDetails->GlobalProductCode;
 974:             $totalEstimate          = (float)(string)$shipmentDetails->ShippingCharge;
 975:             $currencyCode           = (string)$shipmentDetails->CurrencyCode;
 976:             $baseCurrencyCode       = Mage::app()->getWebsite($this->_request->getWebsiteId())->getBaseCurrencyCode();
 977:             $dhlProductDescription  = $this->getDhlProductTitle($dhlProduct);
 978: 
 979:             if ($currencyCode != $baseCurrencyCode) {
 980:                 /* @var $currency Mage_Directory_Model_Currency */
 981:                 $currency = Mage::getModel('directory/currency');
 982:                 $rates = $currency->getCurrencyRates($currencyCode, array($baseCurrencyCode));
 983:                 if (!empty($rates) && isset($rates[$baseCurrencyCode])) {
 984:                     // Convert to store display currency using store exchange rate
 985:                     $totalEstimate = $totalEstimate * $rates[$baseCurrencyCode];
 986:                 } else {
 987:                     $rates = $currency->getCurrencyRates($baseCurrencyCode, array($currencyCode));
 988:                     if (!empty($rates) && isset($rates[$currencyCode])) {
 989:                         $totalEstimate = $totalEstimate/$rates[$currencyCode];
 990:                     }
 991:                     if (!isset($rates[$currencyCode]) || !$totalEstimate) {
 992:                         $totalEstimate = false;
 993:                         $this->_errors[] = Mage::helper('usa')->__("Exchange rate %s (Base Currency) -> %s not found. DHL method %s skipped", $currencyCode, $baseCurrencyCode, $dhlProductDescription);
 994:                     }
 995:                 }
 996:             }
 997:             if ($totalEstimate) {
 998:                 $data = array('term' => $dhlProductDescription,
 999:                     'price_total' => $this->getMethodPrice($totalEstimate, $dhlProduct));
1000:                 if (!empty($this->_rates)) {
1001:                     foreach ($this->_rates as $product) {
1002:                         if ($product['data']['term'] == $data['term']
1003:                             && $product['data']['price_total'] == $data['price_total']
1004:                         ) {
1005:                             return $this;
1006:                         }
1007:                     }
1008:                 }
1009:                 $this->_rates[] = array('service' => $dhlProduct, 'data' => $data);
1010:             } else {
1011:                 $this->_errors[] = Mage::helper('usa')->__("Zero shipping charge for '%s'", $dhlProductDescription);
1012:             }
1013:         } else {
1014:             $dhlProductDescription = false;
1015:             if (isset($shipmentDetails->GlobalProductCode)) {
1016:                 $dhlProductDescription  = $this->getDhlProductTitle((string)$shipmentDetails->GlobalProductCode);
1017:             }
1018:             $dhlProductDescription = $dhlProductDescription ? $dhlProductDescription : Mage::helper('usa')->__("DHL");
1019:             $this->_errors[] = Mage::helper('usa')->__("Zero shipping charge for '%s'", $dhlProductDescription);
1020:         }
1021:         return $this;
1022:     }
1023: 
1024:     /**
1025:      * Returns dimension unit (cm or inch)
1026:      *
1027:      * @return string
1028:      */
1029:     protected function _getDimensionUnit()
1030:     {
1031:         $countryId = $this->_rawRequest->getOrigCountryId();
1032:         $measureUnit = $this->getCountryParams($countryId)->getMeasureUnit();
1033:         if (empty($measureUnit)) {
1034:             Mage::throwException(Mage::helper('usa')->__("Cannot identify measure unit for %s", $countryId));
1035:         }
1036:         return $measureUnit;
1037:     }
1038: 
1039:     /**
1040:      * Returns weight unit (kg or pound)
1041:      *
1042:      * @return string
1043:      */
1044:     protected function _getWeightUnit()
1045:     {
1046:         $countryId = $this->_rawRequest->getOrigCountryId();
1047:         $weightUnit = $this->getCountryParams($countryId)->getWeightUnit();
1048:         if (empty($weightUnit)) {
1049:             Mage::throwException(Mage::helper('usa')->__("Cannot identify weight unit for %s", $countryId));
1050:         }
1051:         return $weightUnit;
1052:     }
1053: 
1054:     /**
1055:      * Get Country Params by Country Code
1056:      *
1057:      * @param string $countryCode
1058:      * @return Varien_Object
1059:      *
1060:      * @see $countryCode ISO 3166 Codes (Countries) A2
1061:      */
1062:     protected function getCountryParams($countryCode)
1063:     {
1064:         if (empty($this->_countryParams)) {
1065:             $dhlConfigPath = Mage::getModuleDir('etc', 'Mage_Usa')  . DS . 'dhl' . DS;
1066:             $countriesXml = file_get_contents($dhlConfigPath . 'international' . DS . 'countries.xml');
1067:             $this->_countryParams = new Varien_Simplexml_Element($countriesXml);
1068:         }
1069:         if (isset($this->_countryParams->$countryCode)) {
1070:             $countryParams = new Varien_Object($this->_countryParams->$countryCode->asArray());
1071:         }
1072:         return isset($countryParams) ? $countryParams : new Varien_Object();
1073:     }
1074: 
1075:     /**
1076:      * Do shipment request to carrier web service, obtain Print Shipping Labels and process errors in response
1077:      *
1078:      * @param Varien_Object $request
1079:      * @return Varien_Object
1080:      */
1081:     protected function _doShipmentRequest(Varien_Object $request)
1082:     {
1083:         $this->_prepareShipmentRequest($request);
1084:         $this->_mapRequestToShipment($request);
1085:         $this->setRequest($request);
1086: 
1087:         return $this->_doRequest();
1088:     }
1089: 
1090:     /**
1091:      * Processing additional validation to check is carrier applicable.
1092:      *
1093:      * @param Mage_Shipping_Model_Rate_Request $request
1094:      * @return Mage_Shipping_Model_Carrier_Abstract|Mage_Shipping_Model_Rate_Result_Error|boolean
1095:      */
1096:     public function proccessAdditionalValidation(Mage_Shipping_Model_Rate_Request $request)
1097:     {
1098:         //Skip by item validation if there is no items in request
1099:         if (!count($this->getAllItems($request))) {
1100:             $this->_errors[] = Mage::helper('usa')->__('There is no items in this order');
1101:         }
1102: 
1103:         $countryParams = $this->getCountryParams(
1104:             Mage::getStoreConfig(Mage_Shipping_Model_Shipping::XML_PATH_STORE_COUNTRY_ID, $request->getStoreId())
1105:         );
1106:         if (!$countryParams->getData()) {
1107:             $this->_errors[] = Mage::helper('usa')->__('Please, specify origin country');
1108:         }
1109: 
1110:         if (!empty($this->_errors)) {
1111:             return $this->_showError();
1112:         }
1113: 
1114:         return $this;
1115:     }
1116: 
1117:     /**
1118:      * Show default error
1119:      *
1120:      * @return bool|Mage_Shipping_Model_Rate_Result_Error
1121:      */
1122:     protected function _showError()
1123:     {
1124:         $showMethod = $this->getConfigData('showmethod');
1125: 
1126:         if ($showMethod) {
1127:             /* @var $error Mage_Shipping_Model_Rate_Result_Error */
1128:             $error = Mage::getModel('shipping/rate_result_error');
1129:             $error->setCarrier(self::CODE);
1130:             $error->setCarrierTitle($this->getConfigData('title'));
1131:             $error->setErrorMessage($this->getConfigData('specificerrmsg'));
1132:             $this->_debug($this->_errors);
1133:             return $error;
1134:         } else {
1135:             return false;
1136:         }
1137:     }
1138: 
1139:     /**
1140:      * Return container types of carrier
1141:      *
1142:      * @param Varien_Object|null $params
1143:      * @return array
1144:      */
1145:     public function getContainerTypes(Varien_Object $params = null)
1146:     {
1147:         return array(
1148:             self::DHL_CONTENT_TYPE_DOC      => Mage::helper('usa')->__('Documents'),
1149:             self::DHL_CONTENT_TYPE_NON_DOC  => Mage::helper('usa')->__('Non Documents')
1150:         );
1151:     }
1152: 
1153:     /**
1154:      * Map request to shipment
1155:      *
1156:      * @param Varien_Object $request
1157:      * @return null
1158:      */
1159:     protected function _mapRequestToShipment(Varien_Object $request)
1160:     {
1161: 
1162:         $request->setOrigCountryId($request->getShipperAddressCountryCode());
1163:         $this->_rawRequest = $request;
1164:         $customsValue = 0;
1165:         $packageWeight = 0;
1166:         $packages = $request->getPackages();
1167:         foreach ($packages as &$piece) {
1168:             $params = $piece['params'];
1169:             if ($params['width'] || $params['length'] || $params['height']) {
1170:                 $minValue = $this->_getMinDimension($params['dimension_units']);
1171:                 if ($params['width'] < $minValue || $params['length'] < $minValue || $params['height'] < $minValue) {
1172:                     $message = Mage::helper('usa')->__('Height, width and length should be equal or greater than %s', $minValue);
1173:                     Mage::throwException($message);
1174:                 }
1175:             }
1176: 
1177:             $weightUnits = $piece['params']['weight_units'];
1178:             $piece['params']['height']          =  $this->_getDimension($piece['params']['height'], $weightUnits);
1179:             $piece['params']['length']          =  $this->_getDimension($piece['params']['length'], $weightUnits);
1180:             $piece['params']['width']           =  $this->_getDimension($piece['params']['width'], $weightUnits);
1181:             $piece['params']['dimension_units'] =  $this->_getDimensionUnit();
1182:             $piece['params']['weight']          =  $this->_getWeight($piece['params']['weight'], false, $weightUnits);
1183:             $piece['params']['weight_units']    =  $this->_getWeightUnit();
1184: 
1185:             $customsValue += $piece['params']['customs_value'];
1186:             $packageWeight += $piece['params']['weight'];
1187:         }
1188: 
1189:         $request->setPackages($packages)
1190:             ->setPackageWeight($packageWeight)
1191:             ->setPackageValue($customsValue)
1192:             ->setValueWithDiscount($customsValue)
1193:             ->setPackageCustomsValue($customsValue)
1194:             ->setFreeMethodWeight(0);
1195:     }
1196: 
1197:         /**
1198:          * Retrieve minimum allowed value for dimensions in given dimension unit
1199:          *
1200:          * @param string $dimensionUnit
1201:          * @return int
1202:          */
1203:         protected function _getMinDimension($dimensionUnit)
1204:         {
1205:             return $dimensionUnit == "CENTIMETER" ? self::DIMENSION_MIN_CM : self::DIMENSION_MIN_IN;
1206:         }
1207: 
1208:     /**
1209:      * Do rate request and handle errors
1210:      *
1211:      * @return Mage_Shipping_Model_Rate_Result|Varien_Object
1212:      */
1213:     protected function _doRequest()
1214:     {
1215:         $rawRequest = $this->_request;
1216: 
1217:         $originRegion = (string)$this->getCountryParams(
1218:             Mage::getStoreConfig(Mage_Shipping_Model_Shipping::XML_PATH_STORE_COUNTRY_ID, $this->getStore())
1219:         )->region;
1220: 
1221:         if (!$originRegion) {
1222:             Mage::throwException(Mage::helper('usa')->__('Wrong Region.'));
1223:         }
1224: 
1225:         if ($originRegion == 'AM') {
1226:             $originRegion = '';
1227:         }
1228: 
1229:         $xmlStr = '<?xml version="1.0" encoding="UTF-8"?>'
1230:             . '<req:ShipmentValidateRequest' . $originRegion
1231:             . ' xmlns:req="http://www.dhl.com"'
1232:             . ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
1233:             . ' xsi:schemaLocation="http://www.dhl.com ship-val-req'
1234:             . ($originRegion ? '_' . $originRegion : '') . '.xsd" />';
1235:         $xml = new SimpleXMLElement($xmlStr);
1236: 
1237:         $nodeRequest = $xml->addChild('Request', '', '');
1238:         $nodeServiceHeader = $nodeRequest->addChild('ServiceHeader');
1239:         $nodeServiceHeader->addChild('SiteID', (string)$this->getConfigData('id'));
1240:         $nodeServiceHeader->addChild('Password', (string)$this->getConfigData('password'));
1241: 
1242:         if (!$originRegion) {
1243:             $xml->addChild('RequestedPickupTime', 'N', '');
1244:         }
1245:         $xml->addChild('NewShipper', 'N', '');
1246:         $xml->addChild('LanguageCode', 'EN', '');
1247:         $xml->addChild('PiecesEnabled', 'Y', '');
1248: 
1249:         /* Billing */
1250:         $nodeBilling = $xml->addChild('Billing', '', '');
1251:         $nodeBilling->addChild('ShipperAccountNumber', (string)$this->getConfigData('account'));
1252:         /*
1253:          * Method of Payment:
1254:          * S (Shipper)
1255:          * R (Receiver)
1256:          * T (Third Party)
1257:          */
1258:         $nodeBilling->addChild('ShippingPaymentType', 'S');
1259: 
1260:         /*
1261:          * Shipment bill to account – required if Shipping PaymentType is other than 'S'
1262:          */
1263:         $nodeBilling->addChild('BillingAccountNumber', (string)$this->getConfigData('account'));
1264:         $nodeBilling->addChild('DutyPaymentType', 'S');
1265:         $nodeBilling->addChild('DutyAccountNumber', (string)$this->getConfigData('account'));
1266: 
1267:         /* Receiver */
1268:         $nodeConsignee = $xml->addChild('Consignee', '', '');
1269: 
1270:         $companyName = ($rawRequest->getRecipientContactCompanyName())
1271:             ? $rawRequest->getRecipientContactCompanyName()
1272:             : $rawRequest->getRecipientContactPersonName();
1273: 
1274:         $nodeConsignee->addChild('CompanyName', substr($companyName, 0, 35));
1275: 
1276:         $address = $rawRequest->getRecipientAddressStreet1(). ' ' . $rawRequest->getRecipientAddressStreet2();
1277:         $address = Mage::helper('core/string')->str_split($address, 35, false, true);
1278:         if (is_array($address)) {
1279:             foreach ($address as $addressLine) {
1280:                 $nodeConsignee->addChild('AddressLine', $addressLine);
1281:             }
1282:         } else {
1283:             $nodeConsignee->addChild('AddressLine', $address);
1284:         }
1285: 
1286:         $nodeConsignee->addChild('City', $rawRequest->getRecipientAddressCity());
1287:         $nodeConsignee->addChild('Division', $rawRequest->getRecipientAddressStateOrProvinceCode());
1288:         $nodeConsignee->addChild('PostalCode', $rawRequest->getRecipientAddressPostalCode());
1289:         $nodeConsignee->addChild('CountryCode', $rawRequest->getRecipientAddressCountryCode());
1290:         $nodeConsignee->addChild('CountryName',
1291:             (string)$this->getCountryParams($rawRequest->getRecipientAddressCountryCode())->name
1292:         );
1293:         $nodeContact = $nodeConsignee->addChild('Contact');
1294:         $nodeContact->addChild('PersonName', substr($rawRequest->getRecipientContactPersonName(), 0, 34));
1295:         $nodeContact->addChild('PhoneNumber', substr($rawRequest->getRecipientContactPhoneNumber(), 0, 24));
1296: 
1297:         /* Commodity
1298:          * The CommodityCode element contains commodity code for shipment contents. Its
1299:          * value should lie in between 1 to 9999.This field is mandatory.
1300:          */
1301:         $nodeCommodity = $xml->addChild('Commodity', '', '');
1302:         $nodeCommodity->addChild('CommodityCode', '1');
1303: 
1304:         $this->_checkDomesticStatus($rawRequest->getShipperAddressCountryCode(),
1305:             $rawRequest->getRecipientAddressCountryCode()
1306:         );
1307: 
1308:         /* Dutiable */
1309:         if ($this->getConfigData('content_type') == self::DHL_CONTENT_TYPE_NON_DOC && !$this->_isDomestic) {
1310:             $nodeDutiable = $xml->addChild('Dutiable', '', '');
1311:             $nodeDutiable->addChild('DeclaredValue',
1312:                 sprintf("%.2F", $rawRequest->getOrderShipment()->getOrder()->getSubtotal())
1313:             );
1314:             $baseCurrencyCode = Mage::app()->getWebsite($rawRequest->getWebsiteId())->getBaseCurrencyCode();
1315:             $nodeDutiable->addChild('DeclaredCurrency', $baseCurrencyCode);
1316:         }
1317: 
1318:         /* Reference
1319:          * This element identifies the reference information. It is an optional field in the
1320:          * shipment validation request. Only the first reference will be taken currently.
1321:          */
1322:         $nodeReference = $xml->addChild('Reference', '', '');
1323:         $nodeReference->addChild('ReferenceID', 'shipment reference');
1324:         $nodeReference->addChild('ReferenceType', 'St');
1325: 
1326:         /* Shipment Details */
1327:         $this->_shipmentDetails($xml, $rawRequest, $originRegion);
1328: 
1329:         /* Shipper */
1330:         $nodeShipper = $xml->addChild('Shipper', '', '');
1331:         $nodeShipper->addChild('ShipperID', (string)$this->getConfigData('account'));
1332:         $nodeShipper->addChild('CompanyName', $rawRequest->getShipperContactCompanyName());
1333:         $nodeShipper->addChild('RegisteredAccount', (string)$this->getConfigData('account'));
1334: 
1335:         $address = $rawRequest->getShipperAddressStreet1(). ' ' . $rawRequest->getShipperAddressStreet2();
1336:         $address = Mage::helper('core/string')->str_split($address, 35, false, true);
1337:         if (is_array($address)) {
1338:             foreach ($address as $addressLine) {
1339:                 $nodeShipper->addChild('AddressLine', $addressLine);
1340:             }
1341:         } else {
1342:             $nodeShipper->addChild('AddressLine', $address);
1343:         }
1344: 
1345:         $nodeShipper->addChild('City', $rawRequest->getShipperAddressCity());
1346:         $nodeShipper->addChild('Division', $rawRequest->getShipperAddressStateOrProvinceCode());
1347:         $nodeShipper->addChild('PostalCode', $rawRequest->getShipperAddressPostalCode());
1348:         $nodeShipper->addChild('CountryCode', $rawRequest->getShipperAddressCountryCode());
1349:         $nodeShipper->addChild('CountryName',
1350:             (string)$this->getCountryParams($rawRequest->getShipperAddressCountryCode())->name
1351:         );
1352:         $nodeContact = $nodeShipper->addChild('Contact', '', '');
1353:         $nodeContact->addChild('PersonName', substr($rawRequest->getShipperContactPersonName(), 0, 34));
1354:         $nodeContact->addChild('PhoneNumber', substr($rawRequest->getShipperContactPhoneNumber(), 0, 24));
1355: 
1356:         $request = $xml->asXML();
1357:         $request = utf8_encode($request);
1358: 
1359:         $responseBody = $this->_getCachedQuotes($request);
1360:         if ($responseBody === null) {
1361:             $debugData = array('request' => $request);
1362:             try {
1363:                 $client = new Varien_Http_Client();
1364:                 $client->setUri((string)$this->getConfigData('gateway_url'));
1365:                 $client->setConfig(array('maxredirects' => 0, 'timeout' => 30));
1366:                 $client->setRawData($request);
1367:                 $responseBody = $client->request(Varien_Http_Client::POST)->getBody();
1368:                 $debugData['result'] = $responseBody;
1369:                 $this->_setCachedQuotes($request, $responseBody);
1370:             } catch (Exception $e) {
1371:                 $this->_errors[$e->getCode()] = $e->getMessage();
1372:                 $responseBody = '';
1373:             }
1374:             $this->_debug($debugData);
1375:         }
1376:         $this->_isShippingLabelFlag = true;
1377:         return $this->_parseResponse($responseBody);
1378:     }
1379: 
1380:     /**
1381:      * Generation Shipment Details Node according to origin region
1382:      *
1383:      * @param SimpleXMLElement $xml
1384:      * @param Mage_Shipping_Model_Rate_Request $rawRequest
1385:      * @param string $originRegion
1386:      * @return void
1387:      */
1388:     protected function _shipmentDetails($xml, $rawRequest, $originRegion = '')
1389:     {
1390:         $nodeShipmentDetails = $xml->addChild('ShipmentDetails', '', '');
1391:         $nodeShipmentDetails->addChild('NumberOfPieces', count($rawRequest->getPackages()));
1392: 
1393:         if ($originRegion) {
1394:             $nodeShipmentDetails->addChild('CurrencyCode',
1395:                 Mage::app()->getWebsite($this->_request->getWebsiteId())->getBaseCurrencyCode()
1396:             );
1397:         }
1398: 
1399:         $nodePieces = $nodeShipmentDetails->addChild('Pieces', '', '');
1400: 
1401:         /*
1402:          * Package type
1403:          * EE (DHL Express Envelope), OD (Other DHL Packaging), CP (Custom Packaging)
1404:          * DC (Document), DM (Domestic), ED (Express Document), FR (Freight)
1405:          * BD (Jumbo Document), BP (Jumbo Parcel), JD (Jumbo Junior Document)
1406:          * JP (Jumbo Junior Parcel), PA (Parcel), DF (DHL Flyer)
1407:          */
1408:         $i = 0;
1409:         foreach ($rawRequest->getPackages() as $package) {
1410:             $nodePiece = $nodePieces->addChild('Piece', '', '');
1411:             $packageType = 'EE';
1412:             if ($package['params']['container'] == self::DHL_CONTENT_TYPE_NON_DOC) {
1413:                 $packageType = 'CP';
1414:             }
1415:             $nodePiece->addChild('PieceID', ++$i);
1416:             $nodePiece->addChild('PackageType', $packageType);
1417:             $nodePiece->addChild('Weight', round($package['params']['weight'],1));
1418:             $params = $package['params'];
1419:             if ($params['width'] && $params['length'] && $params['height']) {
1420:                 if (!$originRegion) {
1421:                     $nodePiece->addChild('Width', round($params['width']));
1422:                     $nodePiece->addChild('Height', round($params['height']));
1423:                     $nodePiece->addChild('Depth', round($params['length']));
1424:                 } else {
1425:                     $nodePiece->addChild('Depth', round($params['length']));
1426:                     $nodePiece->addChild('Width', round($params['width']));
1427:                     $nodePiece->addChild('Height', round($params['height']));
1428:                 }
1429:             }
1430:             $content = array();
1431:             foreach ($package['items'] as $item) {
1432:                 $content[] = $item['name'];
1433:             }
1434:             $nodePiece->addChild('PieceContents', substr(implode(',', $content), 0, 34));
1435:         }
1436: 
1437:         if (!$originRegion) {
1438:             $nodeShipmentDetails->addChild('Weight', round($rawRequest->getPackageWeight(),1));
1439: 
1440:             $nodeShipmentDetails->addChild('WeightUnit', substr($this->_getWeightUnit(),0,1));
1441: 
1442:             $nodeShipmentDetails->addChild('GlobalProductCode', $rawRequest->getShippingMethod());
1443:             $nodeShipmentDetails->addChild('LocalProductCode', $rawRequest->getShippingMethod());
1444: 
1445:             $nodeShipmentDetails->addChild('Date', Mage::getModel('core/date')->date('Y-m-d'));
1446:             $nodeShipmentDetails->addChild('Contents', 'DHL Parcel');
1447:             /*
1448:              * The DoorTo Element defines the type of delivery service that applies to the shipment.
1449:              * The valid values are DD (Door to Door), DA (Door to Airport) , AA and DC (Door to
1450:              * Door non-compliant)
1451:              */
1452:             $nodeShipmentDetails->addChild('DoorTo', 'DD');
1453:             $nodeShipmentDetails->addChild('DimensionUnit', substr($this->_getDimensionUnit(),0,1));
1454:             if ($package['params']['container'] == self::DHL_CONTENT_TYPE_NON_DOC) {
1455:                 $packageType = 'CP';
1456:             }
1457:             $nodeShipmentDetails->addChild('PackageType', $packageType);
1458:             if ($this->getConfigData('content_type') == self::DHL_CONTENT_TYPE_NON_DOC) {
1459:                 $nodeShipmentDetails->addChild('IsDutiable', 'Y');
1460:             }
1461:             $nodeShipmentDetails->addChild('CurrencyCode',
1462:                 Mage::app()->getWebsite($this->_request->getWebsiteId())->getBaseCurrencyCode()
1463:             );
1464:         } else {
1465:             if ($package['params']['container'] == self::DHL_CONTENT_TYPE_NON_DOC) {
1466:                 $packageType = 'CP';
1467:             }
1468:             $nodeShipmentDetails->addChild('PackageType', $packageType);
1469:             $nodeShipmentDetails->addChild('Weight', $rawRequest->getPackageWeight());
1470: 
1471:             $nodeShipmentDetails->addChild('DimensionUnit', substr($this->_getDimensionUnit(),0,1));
1472:             $nodeShipmentDetails->addChild('WeightUnit',  substr($this->_getWeightUnit(),0,1));
1473: 
1474:             $nodeShipmentDetails->addChild('GlobalProductCode', $rawRequest->getShippingMethod());
1475:             $nodeShipmentDetails->addChild('LocalProductCode', $rawRequest->getShippingMethod());
1476: 
1477:             /*
1478:              * The DoorTo Element defines the type of delivery service that applies to the shipment.
1479:              * The valid values are DD (Door to Door), DA (Door to Airport) , AA and DC (Door to
1480:              * Door non-compliant)
1481:              */
1482:             $nodeShipmentDetails->addChild('DoorTo', 'DD');
1483:             $nodeShipmentDetails->addChild('Date', Mage::getModel('core/date')->date('Y-m-d'));
1484:             $nodeShipmentDetails->addChild('Contents', 'DHL Parcel');
1485:         }
1486:     }
1487: 
1488:     /**
1489:      * Get tracking
1490:      *
1491:      * @param mixed $trackings
1492:      * @return mixed
1493:      */
1494:     public function getTracking($trackings)
1495:     {
1496:         if (!is_array($trackings)) {
1497:             $trackings = array($trackings);
1498:         }
1499:         $this->_getXMLTracking($trackings);
1500: 
1501:         return $this->_result;
1502:     }
1503: 
1504:     /**
1505:      * Send request for tracking
1506:      *
1507:      * @param array $trackings
1508:      * @return void
1509:      */
1510:     protected function _getXMLTracking($trackings)
1511:     {
1512:         $xmlStr = '<?xml version="1.0" encoding="UTF-8"?>'
1513:             . '<req:KnownTrackingRequest'
1514:             . ' xmlns:req="http://www.dhl.com"'
1515:             . ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
1516:             . ' xsi:schemaLocation="http://www.dhl.com TrackingRequestKnown.xsd" />';
1517: 
1518:         $xml = new SimpleXMLElement($xmlStr);
1519: 
1520:         $requestNode = $xml->addChild('Request', '', '');
1521:         $serviceHeaderNode = $requestNode->addChild('ServiceHeader', '', '');
1522:         $serviceHeaderNode->addChild('SiteID', (string)$this->getConfigData('id'));
1523:         $serviceHeaderNode->addChild('Password', (string)$this->getConfigData('password'));
1524: 
1525:         $xml->addChild('LanguageCode', 'EN', '');
1526:         foreach ($trackings as $tracking) {
1527:             $xml->addChild('AWBNumber', $tracking, '');
1528:         }
1529:         /*
1530:          * Checkpoint details selection flag
1531:          * LAST_CHECK_POINT_ONLY
1532:          * ALL_CHECK_POINTS
1533:          */
1534:         $xml->addChild('LevelOfDetails', 'ALL_CHECK_POINTS', '');
1535: 
1536:         /*
1537:          * Value that indicates for getting the tracking details with the additional
1538:          * piece details and its respective Piece Details, Piece checkpoints along with
1539:          * Shipment Details if queried.
1540:          *
1541:          * S-Only Shipment Details
1542:          * B-Both Shipment & Piece Details
1543:          * P-Only Piece Details
1544:          * Default is ā€˜S’
1545:          */
1546:         //$xml->addChild('PiecesEnabled', 'ALL_CHECK_POINTS');
1547: 
1548:         $request = $xml->asXML();
1549:         $request = utf8_encode($request);
1550: 
1551:         $responseBody = $this->_getCachedQuotes($request);
1552:         if ($responseBody === null) {
1553:             $debugData = array('request' => $request);
1554:             try {
1555:                 $client = new Varien_Http_Client();
1556:                 $client->setUri((string)$this->getConfigData('gateway_url'));
1557:                 $client->setConfig(array('maxredirects' => 0, 'timeout' => 30));
1558:                 $client->setRawData($request);
1559:                 $responseBody = $client->request(Varien_Http_Client::POST)->getBody();
1560:                 $debugData['result'] = $responseBody;
1561:                 $this->_setCachedQuotes($request, $responseBody);
1562:             } catch (Exception $e) {
1563:                 $this->_errors[$e->getCode()] = $e->getMessage();
1564:                 $responseBody = '';
1565:             }
1566:             $this->_debug($debugData);
1567:         }
1568: 
1569:         $this->_parseXmlTrackingResponse($trackings, $responseBody);
1570:     }
1571: 
1572:     /**
1573:      * Parse xml tracking response
1574:      *
1575:      * @param array $trackings
1576:      * @param string $response
1577:      * @return void
1578:      */
1579:     protected function _parseXmlTrackingResponse($trackings, $response)
1580:     {
1581:         $errorTitle = Mage::helper('usa')->__('Unable to retrieve tracking');
1582:         $resultArr = array();
1583: 
1584:         $htmlTranslationTable = get_html_translation_table(HTML_ENTITIES);
1585:         unset($htmlTranslationTable['<'], $htmlTranslationTable['>'], $htmlTranslationTable['"']);
1586:         $response = str_replace(array_keys($htmlTranslationTable), array_values($htmlTranslationTable), $response);
1587: 
1588:         if (strlen(trim($response)) > 0) {
1589:             $xml = simplexml_load_string($response);
1590:             if (!is_object($xml)) {
1591:                 $errorTitle = Mage::helper('usa')->__('Response is in the wrong format');
1592:             }
1593:             if (is_object($xml) && ((isset($xml->Response->Status->ActionStatus)
1594:                 && $xml->Response->Status->ActionStatus == 'Failure')
1595:                 || isset($xml->GetQuoteResponse->Note->Condition))
1596:             ) {
1597:                 if (isset($xml->Response->Status->Condition)) {
1598:                     $nodeCondition = $xml->Response->Status->Condition;
1599:                 }
1600: 
1601:                 $code = isset($nodeCondition->ConditionCode) ? (string)$nodeCondition->ConditionCode : 0;
1602:                 $data = isset($nodeCondition->ConditionData) ? (string)$nodeCondition->ConditionData : '';
1603:                 $this->_errors[$code] = Mage::helper('usa')->__('Error #%s : %s', $code, $data);
1604:             } elseif (is_object($xml) && is_object($xml->AWBInfo)) {
1605:                 foreach ($xml->AWBInfo as $awbinfo) {
1606:                     $awbinfoData = array();
1607:                     $trackNum = isset($awbinfo->AWBNumber) ? (string)$awbinfo->AWBNumber : '';
1608:                     if (!is_object($awbinfo) || !$awbinfo->ShipmentInfo) {
1609:                         $this->_errors[$trackNum] = Mage::helper('usa')->__('Unable to retrieve tracking');
1610:                         continue;
1611:                     }
1612:                     $shipmentInfo = $awbinfo->ShipmentInfo;
1613: 
1614:                     if ($shipmentInfo->ShipmentDesc) {
1615:                         $awbinfoData['service'] = (string)$shipmentInfo->ShipmentDesc;
1616:                     }
1617: 
1618:                     $awbinfoData['weight'] = (string)$shipmentInfo->Weight . ' ' . (string)$shipmentInfo->WeightUnit;
1619: 
1620:                     $packageProgress = array();
1621:                     if (isset($shipmentInfo->ShipmentEvent)) {
1622:                         foreach ($shipmentInfo->ShipmentEvent as $shipmentEvent) {
1623:                             $shipmentEventArray = array();
1624:                             $shipmentEventArray['activity'] = (string)$shipmentEvent->ServiceEvent->EventCode
1625:                                 . ' ' . (string)$shipmentEvent->ServiceEvent->Description;
1626:                             $shipmentEventArray['deliverydate'] = (string)$shipmentEvent->Date;
1627:                             $shipmentEventArray['deliverytime'] = (string)$shipmentEvent->Time;
1628:                             $shipmentEventArray['deliverylocation'] = (string)$shipmentEvent->ServiceArea->Description
1629:                                 . ' [' . (string)$shipmentEvent->ServiceArea->ServiceAreaCode . ']';
1630:                             $packageProgress[] = $shipmentEventArray;
1631:                         }
1632:                         $awbinfoData['progressdetail'] = $packageProgress;
1633:                     }
1634:                     $resultArr[$trackNum] = $awbinfoData;
1635:                 }
1636:             }
1637:         }
1638: 
1639:         $result = Mage::getModel('shipping/tracking_result');
1640: 
1641:         if (!empty($resultArr)) {
1642:             foreach ($resultArr as $trackNum => $data) {
1643:                 $tracking = Mage::getModel('shipping/tracking_result_status');
1644:                 $tracking->setCarrier($this->_code);
1645:                 $tracking->setCarrierTitle($this->getConfigData('title'));
1646:                 $tracking->setTracking($trackNum);
1647:                 $tracking->addData($data);
1648:                 $result->append($tracking);
1649:             }
1650:         }
1651: 
1652:         if (!empty($this->_errors) || empty($resultArr)) {
1653:             $resultArr = !empty($this->_errors) ? $this->_errors : $trackings;
1654:             foreach ($resultArr as $trackNum => $err) {
1655:                 $error = Mage::getModel('shipping/tracking_result_error');
1656:                 $error->setCarrier($this->_code);
1657:                 $error->setCarrierTitle($this->getConfigData('title'));
1658:                 $error->setTracking(!empty($this->_errors) ? $trackNum : $err);
1659:                 $error->setErrorMessage(!empty($this->_errors) ? $err : $errorTitle);
1660:                 $result->append($error);
1661:             }
1662:         }
1663: 
1664:         $this->_result = $result;
1665:     }
1666: 
1667:     /**
1668:      * Get final price for shipping method with handling fee per package
1669:      *
1670:      * @param float $cost
1671:      * @param string $handlingType
1672:      * @param float $handlingFee
1673:      * @return float
1674:      */
1675:     protected function _getPerpackagePrice($cost, $handlingType, $handlingFee)
1676:     {
1677:         if ($handlingType == Mage_Shipping_Model_Carrier_Abstract::HANDLING_TYPE_PERCENT) {
1678:             return $cost + ($cost * $this->_numBoxes * $handlingFee / 100);
1679:         }
1680: 
1681:         return $cost + $this->_numBoxes * $handlingFee;
1682:     }
1683: 
1684:     /**
1685:      * Do request to shipment
1686:      *
1687:      * @param Mage_Shipping_Model_Shipment_Request $request
1688:      * @return Varien_Object
1689:      */
1690:     public function requestToShipment(Mage_Shipping_Model_Shipment_Request $request)
1691:     {
1692:         $packages = $request->getPackages();
1693:         if (!is_array($packages) || !$packages) {
1694:             Mage::throwException(Mage::helper('usa')->__('No packages for request'));
1695:         }
1696:         $result = $this->_doShipmentRequest($request);
1697: 
1698:         $response = new Varien_Object(array(
1699:             'info' => array(array(
1700:                 'tracking_number' => $result->getTrackingNumber(),
1701:                 'label_content'   => $result->getShippingLabelContent()
1702:             ))
1703:         ));
1704: 
1705:         $request->setMasterTrackingId($result->getTrackingNumber());
1706: 
1707:         return $response;
1708:     }
1709: 
1710:     /**
1711:      * Check if shipping is domestic
1712:      *
1713:      * @param string $origCountryCode
1714:      * @param string $destCountryCode
1715:      * @return bool
1716:      */
1717:     protected function _checkDomesticStatus($origCountryCode, $destCountryCode)
1718:     {
1719:         $this->_isDomestic = false;
1720: 
1721:         $origCountry = (string)$this->getCountryParams($origCountryCode)->name;
1722:         $destCountry = (string)$this->getCountryParams($destCountryCode)->name;
1723:         $isDomestic = (string)$this->getCountryParams($destCountryCode)->domestic;
1724: 
1725:         if ($origCountry == $destCountry && $isDomestic) {
1726:             $this->_isDomestic = true;
1727:         }
1728: 
1729:         return $this->_isDomestic;
1730:     }
1731: }
1732: 
Magento 1.7.0.2 API documentation generated by ApiGen 2.8.0