00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 abstract class Mage_Sales_Model_Order_Pdf_Abstract extends Varien_Object
00036 {
00037 public $y;
00038
00039
00040
00041
00042
00043
00044
00045
00046 protected $_renderers = array();
00047
00048 const XML_PATH_SALES_PDF_INVOICE_PUT_ORDER_ID = 'sales_pdf/invoice/put_order_id';
00049 const XML_PATH_SALES_PDF_SHIPMENT_PUT_ORDER_ID = 'sales_pdf/shipment/put_order_id';
00050 const XML_PATH_SALES_PDF_CREDITMEMO_PUT_ORDER_ID = 'sales_pdf/creditmemo/put_order_id';
00051
00052
00053
00054
00055
00056
00057 protected $_pdf;
00058
00059
00060
00061
00062
00063
00064 abstract public function getPdf();
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 public function widthForStringUsingFontSize($string, $font, $fontSize)
00081 {
00082 $drawingString = iconv('UTF-8', 'UTF-16BE//IGNORE', $string);
00083 $characters = array();
00084 for ($i = 0; $i < strlen($drawingString); $i++) {
00085 $characters[] = (ord($drawingString[$i++]) << 8) | ord($drawingString[$i]);
00086 }
00087 $glyphs = $font->glyphNumbersForCharacters($characters);
00088 $widths = $font->widthsForGlyphs($glyphs);
00089 $stringWidth = (array_sum($widths) / $font->getUnitsPerEm()) * $fontSize;
00090 return $stringWidth;
00091
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 public function getAlignRight($string, $x, $columnWidth, Zend_Pdf_Resource_Font $font, $fontSize, $padding = 5)
00106 {
00107 $width = $this->widthForStringUsingFontSize($string, $font, $fontSize);
00108 return $x + $columnWidth - $width - $padding;
00109 }
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 public function getAlignCenter($string, $x, $columnWidth, Zend_Pdf_Resource_Font $font, $fontSize)
00122 {
00123 $width = $this->widthForStringUsingFontSize($string, $font, $fontSize);
00124 return $x + round(($columnWidth - $width) / 2);
00125 }
00126
00127 protected function insertLogo(&$page, $store = null)
00128 {
00129 $image = Mage::getStoreConfig('sales/identity/logo', $store);
00130 if ($image) {
00131 $image = Mage::getStoreConfig('system/filesystem/media', $store) . '/sales/store/logo/' . $image;
00132 if (is_file($image)) {
00133 $image = Zend_Pdf_Image::imageWithPath($image);
00134 $page->drawImage($image, 25, 800, 125, 825);
00135 }
00136 }
00137
00138 }
00139
00140 protected function insertAddress(&$page, $store = null)
00141 {
00142 $page->setFillColor(new Zend_Pdf_Color_GrayScale(0));
00143 $this->_setFontRegular($page, 5);
00144
00145 $page->setLineWidth(0.5);
00146 $page->setLineColor(new Zend_Pdf_Color_GrayScale(0.5));
00147 $page->drawLine(125, 825, 125, 790);
00148
00149 $page->setLineWidth(0);
00150 $this->y = 820;
00151 foreach (explode("\n", Mage::getStoreConfig('sales/identity/address', $store)) as $value){
00152 if ($value!=='') {
00153 $page->drawText(trim(strip_tags($value)), 130, $this->y, 'UTF-8');
00154 $this->y -=7;
00155 }
00156 }
00157
00158 }
00159
00160
00161
00162
00163
00164
00165
00166 protected function _formatAddress($address)
00167 {
00168 $return = array();
00169 foreach (split("\|", $address) as $str) {
00170 foreach (Mage::helper('core/string')->str_split($str, 65, true, true) as $part) {
00171 if (empty($part)) {
00172 continue;
00173 }
00174 $return[] = $part;
00175 }
00176 }
00177 return $return;
00178 }
00179
00180 protected function insertOrder(&$page, $order, $putOrderId = true)
00181 {
00182
00183 $page->setFillColor(new Zend_Pdf_Color_GrayScale(0.5));
00184
00185 $page->drawRectangle(25, 790, 570, 755);
00186
00187 $page->setFillColor(new Zend_Pdf_Color_GrayScale(1));
00188 $this->_setFontRegular($page);
00189
00190
00191 if ($putOrderId) {
00192 $page->drawText(Mage::helper('sales')->__('Order # ').$order->getRealOrderId(), 35, 770, 'UTF-8');
00193 }
00194
00195 $page->drawText(Mage::helper('sales')->__('Order Date: ') . Mage::helper('core')->formatDate($order->getCreatedAtStoreDate(), 'medium', false), 35, 760, 'UTF-8');
00196
00197 $page->setFillColor(new Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
00198 $page->setLineColor(new Zend_Pdf_Color_GrayScale(0.5));
00199 $page->setLineWidth(0.5);
00200 $page->drawRectangle(25, 755, 275, 730);
00201 $page->drawRectangle(275, 755, 570, 730);
00202
00203
00204
00205
00206 $billingAddress = $this->_formatAddress($order->getBillingAddress()->format('pdf'));
00207
00208
00209 $paymentInfo = Mage::helper('payment')->getInfoBlock($order->getPayment())
00210 ->setIsSecureMode(true)
00211 ->toPdf();
00212 $payment = explode('{{pdf_row_separator}}', $paymentInfo);
00213 foreach ($payment as $key=>$value){
00214 if (strip_tags(trim($value))==''){
00215 unset($payment[$key]);
00216 }
00217 }
00218 reset($payment);
00219
00220
00221 if (!$order->getIsVirtual()) {
00222
00223 $shippingAddress = $this->_formatAddress($order->getShippingAddress()->format('pdf'));
00224
00225 $shippingMethod = $order->getShippingDescription();
00226 }
00227
00228 $page->setFillColor(new Zend_Pdf_Color_GrayScale(0));
00229 $this->_setFontRegular($page);
00230 $page->drawText(Mage::helper('sales')->__('SOLD TO:'), 35, 740 , 'UTF-8');
00231
00232 if (!$order->getIsVirtual()) {
00233 $page->drawText(Mage::helper('sales')->__('SHIP TO:'), 285, 740 , 'UTF-8');
00234 }
00235 else {
00236 $page->drawText(Mage::helper('sales')->__('Payment Method:'), 285, 740 , 'UTF-8');
00237 }
00238
00239 if (!$order->getIsVirtual()) {
00240 $y = 730 - (max(count($billingAddress), count($shippingAddress)) * 10 + 5);
00241 }
00242 else {
00243 $y = 730 - (count($billingAddress) * 10 + 5);
00244 }
00245
00246 $page->setFillColor(new Zend_Pdf_Color_GrayScale(1));
00247 $page->drawRectangle(25, 730, 570, $y);
00248 $page->setFillColor(new Zend_Pdf_Color_GrayScale(0));
00249 $this->_setFontRegular($page);
00250 $this->y = 720;
00251
00252 foreach ($billingAddress as $value){
00253 if ($value!=='') {
00254 $page->drawText(strip_tags(ltrim($value)), 35, $this->y, 'UTF-8');
00255 $this->y -=10;
00256 }
00257 }
00258
00259 if (!$order->getIsVirtual()) {
00260 $this->y = 720;
00261 foreach ($shippingAddress as $value){
00262 if ($value!=='') {
00263 $page->drawText(strip_tags(ltrim($value)), 285, $this->y, 'UTF-8');
00264 $this->y -=10;
00265 }
00266
00267 }
00268
00269 $page->setFillColor(new Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
00270 $page->setLineWidth(0.5);
00271 $page->drawRectangle(25, $this->y, 275, $this->y-25);
00272 $page->drawRectangle(275, $this->y, 570, $this->y-25);
00273
00274 $this->y -=15;
00275 $this->_setFontBold($page);
00276 $page->setFillColor(new Zend_Pdf_Color_GrayScale(0));
00277 $page->drawText(Mage::helper('sales')->__('Payment Method'), 35, $this->y, 'UTF-8');
00278 $page->drawText(Mage::helper('sales')->__('Shipping Method:'), 285, $this->y , 'UTF-8');
00279
00280 $this->y -=10;
00281 $page->setFillColor(new Zend_Pdf_Color_GrayScale(1));
00282
00283 $this->_setFontRegular($page);
00284 $page->setFillColor(new Zend_Pdf_Color_GrayScale(0));
00285
00286 $paymentLeft = 35;
00287 $yPayments = $this->y - 15;
00288 }
00289 else {
00290 $yPayments = 720;
00291 $paymentLeft = 285;
00292 }
00293
00294 foreach ($payment as $value){
00295 if (trim($value)!=='') {
00296 $page->drawText(strip_tags(trim($value)), $paymentLeft, $yPayments, 'UTF-8');
00297 $yPayments -=10;
00298 }
00299 }
00300
00301 if (!$order->getIsVirtual()) {
00302 $this->y -=15;
00303
00304 $page->drawText($shippingMethod, 285, $this->y, 'UTF-8');
00305
00306 $yShipments = $this->y;
00307
00308
00309 $totalShippingChargesText = "(" . Mage::helper('sales')->__('Total Shipping Charges') . " " . $order->formatPriceTxt($order->getShippingAmount()) . ")";
00310
00311 $page->drawText($totalShippingChargesText, 285, $yShipments-7, 'UTF-8');
00312 $yShipments -=10;
00313 $tracks = $order->getTracksCollection();
00314 if (count($tracks)) {
00315 $page->setFillColor(new Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
00316 $page->setLineWidth(0.5);
00317 $page->drawRectangle(285, $yShipments, 510, $yShipments - 10);
00318 $page->drawLine(380, $yShipments, 380, $yShipments - 10);
00319
00320
00321 $this->_setFontRegular($page);
00322 $page->setFillColor(new Zend_Pdf_Color_GrayScale(0));
00323
00324 $page->drawText(Mage::helper('sales')->__('Title'), 290, $yShipments - 7, 'UTF-8');
00325 $page->drawText(Mage::helper('sales')->__('Number'), 385, $yShipments - 7, 'UTF-8');
00326
00327 $yShipments -=17;
00328 $this->_setFontRegular($page, 6);
00329 foreach ($order->getTracksCollection() as $track) {
00330
00331 $CarrierCode = $track->getCarrierCode();
00332 if ($CarrierCode!='custom')
00333 {
00334 $carrier = Mage::getSingleton('shipping/config')->getCarrierInstance($CarrierCode);
00335 $carrierTitle = $carrier->getConfigData('title');
00336 }
00337 else
00338 {
00339 $carrierTitle = Mage::helper('sales')->__('Custom Value');
00340 }
00341
00342
00343 $truncatedTitle = substr($track->getTitle(), 0, 45) . (strlen($track->getTitle()) > 45 ? '...' : '');
00344
00345 $page->drawText($truncatedTitle, 300, $yShipments , 'UTF-8');
00346 $page->drawText($track->getNumber(), 395, $yShipments , 'UTF-8');
00347 $yShipments -=7;
00348 }
00349 } else {
00350 $yShipments -= 7;
00351 }
00352
00353 $currentY = min($yPayments, $yShipments);
00354
00355
00356 $page->drawLine(25, $this->y + 15, 25, $currentY);
00357 $page->drawLine(25, $currentY, 570, $currentY);
00358 $page->drawLine(570, $currentY, 570, $this->y + 15);
00359
00360 $this->y = $currentY;
00361 $this->y -= 15;
00362 }
00363 }
00364
00365 protected function _sortTotalsList($a, $b) {
00366 if (!isset($a['sort_order']) || !isset($b['sort_order'])) {
00367 return 0;
00368 }
00369
00370 if ($a['sort_order'] == $b['sort_order']) {
00371 return 0;
00372 }
00373
00374 return ($a['sort_order'] > $b['sort_order']) ? 1 : -1;
00375 }
00376
00377 protected function _getTotalsList($source)
00378 {
00379 $totals = Mage::getConfig()->getNode('global/pdf/totals')->asArray();
00380 usort($totals, array($this, '_sortTotalsList'));
00381
00382 return $totals;
00383 }
00384
00385 protected function insertTotals($page, $source){
00386 $order = $source->getOrder();
00387
00388
00389 $totals = $this->_getTotalsList($source);
00390
00391 $lineBlock = array(
00392 'lines' => array(),
00393 'height' => 15
00394 );
00395 foreach ($totals as $total) {
00396 $amount = $source->getDataUsingMethod($total['source_field']);
00397 $displayZero = (isset($total['display_zero']) ? $total['display_zero'] : 0);
00398
00399 if ($amount != 0 || $displayZero) {
00400 $amount = $order->formatPriceTxt($amount);
00401
00402 if (isset($total['amount_prefix']) && $total['amount_prefix']) {
00403 $amount = "{$total['amount_prefix']}{$amount}";
00404 }
00405
00406 $fontSize = (isset($total['font_size']) ? $total['font_size'] : 7);
00407
00408
00409 $label = Mage::helper('sales')->__($total['title']) . ':';
00410
00411 $lineBlock['lines'][] = array(
00412 array(
00413 'text' => $label,
00414 'feed' => 475,
00415 'align' => 'right',
00416 'font_size' => $fontSize,
00417 'font' => 'bold'
00418 ),
00419 array(
00420 'text' => $amount,
00421 'feed' => 565,
00422 'align' => 'right',
00423 'font_size' => $fontSize,
00424 'font' => 'bold'
00425 ),
00426 );
00427
00428
00429
00430
00431 }
00432 }
00433
00434
00435
00436
00437 $page = $this->drawLineBlocks($page, array($lineBlock));
00438 return $page;
00439 }
00440
00441 protected function _parseItemDescription($item)
00442 {
00443 $matches = array();
00444 $description = $item->getDescription();
00445 if (preg_match_all('/<li.*?>(.*?)<\/li>/i', $description, $matches)) {
00446 return $matches[1];
00447 }
00448
00449 return array($description);
00450 }
00451
00452
00453
00454
00455
00456 protected function _beforeGetPdf() {
00457 $translate = Mage::getSingleton('core/translate');
00458
00459 $translate->setTranslateInline(false);
00460 }
00461
00462
00463
00464
00465
00466 protected function _afterGetPdf() {
00467 $translate = Mage::getSingleton('core/translate');
00468
00469 $translate->setTranslateInline(true);
00470 }
00471
00472 protected function _formatOptionValue($value, $order)
00473 {
00474 $resultValue = '';
00475 if (is_array($value)) {
00476 if (isset($value['qty'])) {
00477 $resultValue .= sprintf('%d', $value['qty']) . ' x ';
00478 }
00479
00480 $resultValue .= $value['title'];
00481
00482 if (isset($value['price'])) {
00483 $resultValue .= " " . $order->formatPrice($value['price']);
00484 }
00485 return $resultValue;
00486 } else {
00487 return $value;
00488 }
00489 }
00490
00491 protected function _initRenderer($type)
00492 {
00493 $node = Mage::getConfig()->getNode('global/pdf/'.$type);
00494 foreach ($node->children() as $renderer) {
00495 $this->_renderers[$renderer->getName()] = array(
00496 'model' => (string)$renderer,
00497 'renderer' => null
00498 );
00499 }
00500 }
00501
00502
00503
00504
00505
00506
00507
00508 protected function _getRenderer($type)
00509 {
00510 if (!isset($this->_renderers[$type])) {
00511 $type = 'default';
00512 }
00513
00514 if (!isset($this->_renderers[$type])) {
00515 Mage::throwException(Mage::helper('sales')->__('Invalid renderer model'));
00516 }
00517
00518 if (is_null($this->_renderers[$type]['renderer'])) {
00519 $this->_renderers[$type]['renderer'] = Mage::getSingleton($this->_renderers[$type]['model']);
00520 }
00521
00522 return $this->_renderers[$type]['renderer'];
00523 }
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533 public function getRenderer($type)
00534 {
00535 return $this->_getRenderer($type);
00536 }
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546 protected function _drawItem(Varien_Object $item, Zend_Pdf_Page $page, Mage_Sales_Model_Order $order)
00547 {
00548 $type = $item->getOrderItem()->getProductType();
00549 $renderer = $this->_getRenderer($type);
00550 $renderer->setOrder($order);
00551 $renderer->setItem($item);
00552 $renderer->setPdf($this);
00553 $renderer->setPage($page);
00554 $renderer->setRenderedModel($this);
00555
00556 $renderer->draw();
00557
00558 return $renderer->getPage();
00559 }
00560
00561 protected function _setFontRegular($object, $size = 7)
00562 {
00563 $font = Zend_Pdf_Font::fontWithPath(Mage::getBaseDir() . '/lib/LinLibertineFont/LinLibertineC_Re-2.8.0.ttf');
00564 $object->setFont($font, $size);
00565 return $font;
00566 }
00567
00568 protected function _setFontBold($object, $size = 7)
00569 {
00570 $font = Zend_Pdf_Font::fontWithPath(Mage::getBaseDir() . '/lib/LinLibertineFont/LinLibertine_Bd-2.8.1.ttf');
00571 $object->setFont($font, $size);
00572 return $font;
00573 }
00574
00575 protected function _setFontItalic($object, $size = 7)
00576 {
00577 $font = Zend_Pdf_Font::fontWithPath(Mage::getBaseDir() . '/lib/LinLibertineFont/LinLibertine_It-2.8.2.ttf');
00578 $object->setFont($font, $size);
00579 return $font;
00580 }
00581
00582
00583
00584
00585
00586
00587
00588 protected function _setPdf(Zend_Pdf $pdf)
00589 {
00590 $this->_pdf = $pdf;
00591 return $this;
00592 }
00593
00594
00595
00596
00597
00598
00599
00600 protected function _getPdf()
00601 {
00602 if (!$this->_pdf instanceof Zend_Pdf) {
00603 Mage::throwException(Mage::helper('sales')->__('Please define PDF object before using'));
00604 }
00605
00606 return $this->_pdf;
00607 }
00608
00609
00610
00611
00612
00613
00614
00615 public function newPage(array $settings = array())
00616 {
00617 $pageSize = !empty($settings['page_size']) ? $settings['page_size'] : Zend_Pdf_Page::SIZE_A4;
00618 $page = $this->_getPdf()->newPage($pageSize);
00619 $this->_getPdf()->pages[] = $page;
00620 $this->y = 800;
00621
00622 return $page;
00623 }
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650 public function drawLineBlocks(Zend_Pdf_Page $page, array $draw, array $pageSettings = array())
00651 {
00652 foreach ($draw as $itemsProp) {
00653 if (!isset($itemsProp['lines']) || !is_array($itemsProp['lines'])) {
00654 Mage::throwException(Mage::helper('sales')->__('Invalid draw line data. Please define "lines" array'));
00655 }
00656 $lines = $itemsProp['lines'];
00657 $height = isset($itemsProp['height']) ? $itemsProp['height'] : 10;
00658
00659 if (empty($itemsProp['shift'])) {
00660 $shift = 0;
00661 foreach ($lines as $line) {
00662 $maxHeight = 0;
00663 foreach ($line as $column) {
00664 $lineSpacing = !empty($column['height']) ? $column['height'] : $height;
00665 if (!is_array($column['text'])) {
00666 $column['text'] = array($column['text']);
00667 }
00668 $top = 0;
00669 foreach ($column['text'] as $part) {
00670 $top += $lineSpacing;
00671 }
00672
00673 $maxHeight = $top > $maxHeight ? $top : $maxHeight;
00674 }
00675 $shift += $maxHeight;
00676 }
00677 $itemsProp['shift'] = $shift;
00678 }
00679
00680 if ($this->y - $itemsProp['shift'] < 15) {
00681 $page = $this->newPage($pageSettings);
00682 }
00683
00684 foreach ($lines as $line) {
00685 $maxHeight = 0;
00686 foreach ($line as $column) {
00687 $fontSize = empty($column['font_size']) ? 7 : $column['font_size'];
00688 if (!empty($column['font_file'])) {
00689 $font = Zend_Pdf_Font::fontWithPath($column['font_file']);
00690 $page->setFont($font);
00691 }
00692 else {
00693 $fontStyle = empty($column['font']) ? 'regular' : $column['font'];
00694 switch ($fontStyle) {
00695 case 'bold':
00696 $font = $this->_setFontBold($page, $fontSize);
00697 break;
00698 case 'italic':
00699 $font = $this->_setFontItalic($page, $fontSize);
00700 break;
00701 default:
00702 $font = $this->_setFontRegular($page, $fontSize);
00703 break;
00704 }
00705 }
00706
00707 if (!is_array($column['text'])) {
00708 $column['text'] = array($column['text']);
00709 }
00710
00711 $lineSpacing = !empty($column['height']) ? $column['height'] : $height;
00712 $top = 0;
00713 foreach ($column['text'] as $part) {
00714 $feed = $column['feed'];
00715 $textAlign = empty($column['align']) ? 'left' : $column['align'];
00716 $width = empty($column['width']) ? 0 : $column['width'];
00717 switch ($textAlign) {
00718 case 'right':
00719 if ($width) {
00720 $feed = $this->getAlignRight($part, $feed, $width, $font, $fontSize);
00721 }
00722 else {
00723 $feed = $feed - $this->widthForStringUsingFontSize($part, $font, $fontSize);
00724 }
00725 break;
00726 case 'center':
00727 if ($width) {
00728 $feed = $this->getAlignCenter($part, $feed, $width, $font, $fontSize);
00729 }
00730 break;
00731 }
00732 $page->drawText($part, $feed, $this->y-$top, 'UTF-8');
00733 $top += $lineSpacing;
00734 }
00735
00736 $maxHeight = $top > $maxHeight ? $top : $maxHeight;
00737 }
00738 $this->y -= $maxHeight;
00739 }
00740 }
00741
00742 return $page;
00743 }
00744 }