/app/code/core/Mage/Sales/Model/Order/Pdf/Abstract.php
PHP | 757 lines | 482 code | 96 blank | 179 comment | 55 complexity | dd5baf6c684656aae6023809b3ad4c89 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-2.1, GPL-2.0, WTFPL
- <?php
- /**
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Open Software License (OSL 3.0)
- * that is bundled with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/osl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magentocommerce.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magentocommerce.com for more information.
- *
- * @category Mage
- * @package Mage_Sales
- * @copyright Copyright (c) 2010 Magento Inc. (http://www.magentocommerce.com)
- * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
- */
- /**
- * Sales Order PDF abstract model
- *
- * @category Mage
- * @package Mage_Sales
- * @author Magento Core Team <core@magentocommerce.com>
- */
- abstract class Mage_Sales_Model_Order_Pdf_Abstract extends Varien_Object
- {
- public $y;
- /**
- * Item renderers with render type key
- *
- * model => the model name
- * renderer => the renderer model
- *
- * @var array
- */
- protected $_renderers = array();
- const XML_PATH_SALES_PDF_INVOICE_PUT_ORDER_ID = 'sales_pdf/invoice/put_order_id';
- const XML_PATH_SALES_PDF_SHIPMENT_PUT_ORDER_ID = 'sales_pdf/shipment/put_order_id';
- const XML_PATH_SALES_PDF_CREDITMEMO_PUT_ORDER_ID = 'sales_pdf/creditmemo/put_order_id';
- /**
- * Zend PDF object
- *
- * @var Zend_Pdf
- */
- protected $_pdf;
- protected $_defaultTotalModel = 'sales/order_pdf_total_default';
- /**
- * Retrieve PDF
- *
- * @return Zend_Pdf
- */
- abstract public function getPdf();
- /**
- * Returns the total width in points of the string using the specified font and
- * size.
- *
- * This is not the most efficient way to perform this calculation. I'm
- * concentrating optimization efforts on the upcoming layout manager class.
- * Similar calculations exist inside the layout manager class, but widths are
- * generally calculated only after determining line fragments.
- *
- * @param string $string
- * @param Zend_Pdf_Resource_Font $font
- * @param float $fontSize Font size in points
- * @return float
- */
- public function widthForStringUsingFontSize($string, $font, $fontSize)
- {
- $drawingString = '"libiconv"' == ICONV_IMPL ? iconv('UTF-8', 'UTF-16BE//IGNORE', $string) : @iconv('UTF-8', 'UTF-16BE', $string);
- $characters = array();
- for ($i = 0; $i < strlen($drawingString); $i++) {
- $characters[] = (ord($drawingString[$i++]) << 8) | ord($drawingString[$i]);
- }
- $glyphs = $font->glyphNumbersForCharacters($characters);
- $widths = $font->widthsForGlyphs($glyphs);
- $stringWidth = (array_sum($widths) / $font->getUnitsPerEm()) * $fontSize;
- return $stringWidth;
- }
- /**
- * Calculate coordinates to draw something in a column aligned to the right
- *
- * @param string $string
- * @param int $x
- * @param int $columnWidth
- * @param Zend_Pdf_Resource_Font $font
- * @param int $fontSize
- * @param int $padding
- * @return int
- */
- public function getAlignRight($string, $x, $columnWidth, Zend_Pdf_Resource_Font $font, $fontSize, $padding = 5)
- {
- $width = $this->widthForStringUsingFontSize($string, $font, $fontSize);
- return $x + $columnWidth - $width - $padding;
- }
- /**
- * Calculate coordinates to draw something in a column aligned to the center
- *
- * @param string $string
- * @param int $x
- * @param int $columnWidth
- * @param Zend_Pdf_Resource_Font $font
- * @param int $fontSize
- * @return int
- */
- public function getAlignCenter($string, $x, $columnWidth, Zend_Pdf_Resource_Font $font, $fontSize)
- {
- $width = $this->widthForStringUsingFontSize($string, $font, $fontSize);
- return $x + round(($columnWidth - $width) / 2);
- }
- protected function insertLogo(&$page, $store = null)
- {
- $image = Mage::getStoreConfig('sales/identity/logo', $store);
- if ($image) {
- $image = Mage::getStoreConfig('system/filesystem/media', $store) . '/sales/store/logo/' . $image;
- if (is_file($image)) {
- $image = Zend_Pdf_Image::imageWithPath($image);
- $page->drawImage($image, 25, 800, 125, 825);
- }
- }
- //return $page;
- }
- protected function insertAddress(&$page, $store = null)
- {
- $page->setFillColor(new Zend_Pdf_Color_GrayScale(0));
- $this->_setFontRegular($page, 5);
- $page->setLineWidth(0.5);
- $page->setLineColor(new Zend_Pdf_Color_GrayScale(0.5));
- $page->drawLine(125, 825, 125, 790);
- $page->setLineWidth(0);
- $this->y = 820;
- foreach (explode("\n", Mage::getStoreConfig('sales/identity/address', $store)) as $value){
- if ($value!=='') {
- $page->drawText(trim(strip_tags($value)), 130, $this->y, 'UTF-8');
- $this->y -=7;
- }
- }
- //return $page;
- }
- /**
- * Format address
- *
- * @param string $address
- * @return array
- */
- protected function _formatAddress($address)
- {
- $return = array();
- foreach (explode('|', $address) as $str) {
- foreach (Mage::helper('core/string')->str_split($str, 65, true, true) as $part) {
- if (empty($part)) {
- continue;
- }
- $return[] = $part;
- }
- }
- return $return;
- }
- protected function insertOrder(&$page, $obj, $putOrderId = true)
- {
- if ($obj instanceof Mage_Sales_Model_Order) {
- $shipment = null;
- $order = $obj;
- } elseif ($obj instanceof Mage_Sales_Model_Order_Shipment) {
- $shipment = $obj;
- $order = $shipment->getOrder();
- }
- /* @var $order Mage_Sales_Model_Order */
- $page->setFillColor(new Zend_Pdf_Color_GrayScale(0.5));
- $page->drawRectangle(25, 790, 570, 755);
- $page->setFillColor(new Zend_Pdf_Color_GrayScale(1));
- $this->_setFontRegular($page);
- if ($putOrderId) {
- $page->drawText(Mage::helper('sales')->__('Order # ').$order->getRealOrderId(), 35, 770, 'UTF-8');
- }
- //$page->drawText(Mage::helper('sales')->__('Order Date: ') . date( 'D M j Y', strtotime( $order->getCreatedAt() ) ), 35, 760, 'UTF-8');
- $page->drawText(Mage::helper('sales')->__('Order Date: ') . Mage::helper('core')->formatDate($order->getCreatedAtStoreDate(), 'medium', false), 35, 760, 'UTF-8');
- $page->setFillColor(new Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
- $page->setLineColor(new Zend_Pdf_Color_GrayScale(0.5));
- $page->setLineWidth(0.5);
- $page->drawRectangle(25, 755, 275, 730);
- $page->drawRectangle(275, 755, 570, 730);
- /* Calculate blocks info */
- /* Billing Address */
- $billingAddress = $this->_formatAddress($order->getBillingAddress()->format('pdf'));
- /* Payment */
- $paymentInfo = Mage::helper('payment')->getInfoBlock($order->getPayment())
- ->setIsSecureMode(true)
- ->toPdf();
- $payment = explode('{{pdf_row_separator}}', $paymentInfo);
- foreach ($payment as $key=>$value){
- if (strip_tags(trim($value))==''){
- unset($payment[$key]);
- }
- }
- reset($payment);
- /* Shipping Address and Method */
- if (!$order->getIsVirtual()) {
- /* Shipping Address */
- $shippingAddress = $this->_formatAddress($order->getShippingAddress()->format('pdf'));
- $shippingMethod = $order->getShippingDescription();
- }
- $page->setFillColor(new Zend_Pdf_Color_GrayScale(0));
- $this->_setFontRegular($page);
- $page->drawText(Mage::helper('sales')->__('SOLD TO:'), 35, 740 , 'UTF-8');
- if (!$order->getIsVirtual()) {
- $page->drawText(Mage::helper('sales')->__('SHIP TO:'), 285, 740 , 'UTF-8');
- }
- else {
- $page->drawText(Mage::helper('sales')->__('Payment Method:'), 285, 740 , 'UTF-8');
- }
- if (!$order->getIsVirtual()) {
- $y = 730 - (max(count($billingAddress), count($shippingAddress)) * 10 + 5);
- }
- else {
- $y = 730 - (count($billingAddress) * 10 + 5);
- }
- $page->setFillColor(new Zend_Pdf_Color_GrayScale(1));
- $page->drawRectangle(25, 730, 570, $y);
- $page->setFillColor(new Zend_Pdf_Color_GrayScale(0));
- $this->_setFontRegular($page);
- $this->y = 720;
- foreach ($billingAddress as $value){
- if ($value!=='') {
- $page->drawText(strip_tags(ltrim($value)), 35, $this->y, 'UTF-8');
- $this->y -=10;
- }
- }
- if (!$order->getIsVirtual()) {
- $this->y = 720;
- foreach ($shippingAddress as $value){
- if ($value!=='') {
- $page->drawText(strip_tags(ltrim($value)), 285, $this->y, 'UTF-8');
- $this->y -=10;
- }
- }
- $page->setFillColor(new Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
- $page->setLineWidth(0.5);
- $page->drawRectangle(25, $this->y, 275, $this->y-25);
- $page->drawRectangle(275, $this->y, 570, $this->y-25);
- $this->y -=15;
- $this->_setFontBold($page);
- $page->setFillColor(new Zend_Pdf_Color_GrayScale(0));
- $page->drawText(Mage::helper('sales')->__('Payment Method'), 35, $this->y, 'UTF-8');
- $page->drawText(Mage::helper('sales')->__('Shipping Method:'), 285, $this->y , 'UTF-8');
- $this->y -=10;
- $page->setFillColor(new Zend_Pdf_Color_GrayScale(1));
- $this->_setFontRegular($page);
- $page->setFillColor(new Zend_Pdf_Color_GrayScale(0));
- $paymentLeft = 35;
- $yPayments = $this->y - 15;
- }
- else {
- $yPayments = 720;
- $paymentLeft = 285;
- }
- foreach ($payment as $value){
- if (trim($value)!=='') {
- $page->drawText(strip_tags(trim($value)), $paymentLeft, $yPayments, 'UTF-8');
- $yPayments -=10;
- }
- }
- if (!$order->getIsVirtual()) {
- $this->y -=15;
- $page->drawText($shippingMethod, 285, $this->y, 'UTF-8');
- $yShipments = $this->y;
- $totalShippingChargesText = "(" . Mage::helper('sales')->__('Total Shipping Charges') . " " . $order->formatPriceTxt($order->getShippingAmount()) . ")";
- $page->drawText($totalShippingChargesText, 285, $yShipments-7, 'UTF-8');
- $yShipments -=10;
- $tracks = array();
- if ($shipment) {
- $tracks = $shipment->getAllTracks();
- }
- if (count($tracks)) {
- $page->setFillColor(new Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
- $page->setLineWidth(0.5);
- $page->drawRectangle(285, $yShipments, 510, $yShipments - 10);
- $page->drawLine(380, $yShipments, 380, $yShipments - 10);
- //$page->drawLine(510, $yShipments, 510, $yShipments - 10);
- $this->_setFontRegular($page);
- $page->setFillColor(new Zend_Pdf_Color_GrayScale(0));
- //$page->drawText(Mage::helper('sales')->__('Carrier'), 290, $yShipments - 7 , 'UTF-8');
- $page->drawText(Mage::helper('sales')->__('Title'), 290, $yShipments - 7, 'UTF-8');
- $page->drawText(Mage::helper('sales')->__('Number'), 385, $yShipments - 7, 'UTF-8');
- $yShipments -=17;
- $this->_setFontRegular($page, 6);
- foreach ($tracks as $track) {
- $CarrierCode = $track->getCarrierCode();
- if ($CarrierCode!='custom')
- {
- $carrier = Mage::getSingleton('shipping/config')->getCarrierInstance($CarrierCode);
- $carrierTitle = $carrier->getConfigData('title');
- }
- else
- {
- $carrierTitle = Mage::helper('sales')->__('Custom Value');
- }
- //$truncatedCarrierTitle = substr($carrierTitle, 0, 35) . (strlen($carrierTitle) > 35 ? '...' : '');
- $truncatedTitle = substr($track->getTitle(), 0, 45) . (strlen($track->getTitle()) > 45 ? '...' : '');
- //$page->drawText($truncatedCarrierTitle, 285, $yShipments , 'UTF-8');
- $page->drawText($truncatedTitle, 300, $yShipments , 'UTF-8');
- $page->drawText($track->getNumber(), 395, $yShipments , 'UTF-8');
- $yShipments -=7;
- }
- } else {
- $yShipments -= 7;
- }
- $currentY = min($yPayments, $yShipments);
- // replacement of Shipments-Payments rectangle block
- $page->drawLine(25, $this->y + 15, 25, $currentY);
- $page->drawLine(25, $currentY, 570, $currentY);
- $page->drawLine(570, $currentY, 570, $this->y + 15);
- $this->y = $currentY;
- $this->y -= 15;
- }
- }
- protected function _sortTotalsList($a, $b) {
- if (!isset($a['sort_order']) || !isset($b['sort_order'])) {
- return 0;
- }
- if ($a['sort_order'] == $b['sort_order']) {
- return 0;
- }
- return ($a['sort_order'] > $b['sort_order']) ? 1 : -1;
- }
- protected function _getTotalsList($source)
- {
- $totals = Mage::getConfig()->getNode('global/pdf/totals')->asArray();
- usort($totals, array($this, '_sortTotalsList'));
- $totalModels = array();
- foreach ($totals as $index => $totalInfo) {
- if (!empty($totalInfo['model'])) {
- $totalModel = Mage::getModel($totalInfo['model']);
- if ($totalModel instanceof Mage_Sales_Model_Order_Pdf_Total_Default) {
- $totalInfo['model'] = $totalModel;
- } else {
- Mage::throwException(
- Mage::helper('sales')->__('PDF total model should extend Mage_Sales_Model_Order_Pdf_Total_Default')
- );
- }
- } else {
- $totalModel = Mage::getModel($this->_defaultTotalModel);
- }
- $totalModel->setData($totalInfo);
- $totalModels[] = $totalModel;
- }
- return $totalModels;
- }
- protected function insertTotals($page, $source){
- $order = $source->getOrder();
- $totals = $this->_getTotalsList($source);
- $lineBlock = array(
- 'lines' => array(),
- 'height' => 15
- );
- foreach ($totals as $total) {
- $total->setOrder($order)
- ->setSource($source);
- if ($total->canDisplay()) {
- foreach ($total->getTotalsForDisplay() as $totalData) {
- $lineBlock['lines'][] = array(
- array(
- 'text' => $totalData['label'],
- 'feed' => 475,
- 'align' => 'right',
- 'font_size' => $totalData['font_size'],
- 'font' => 'bold'
- ),
- array(
- 'text' => $totalData['amount'],
- 'feed' => 565,
- 'align' => 'right',
- 'font_size' => $totalData['font_size'],
- 'font' => 'bold'
- ),
- );
- }
- }
- }
- $page = $this->drawLineBlocks($page, array($lineBlock));
- return $page;
- }
- protected function _parseItemDescription($item)
- {
- $matches = array();
- $description = $item->getDescription();
- if (preg_match_all('/<li.*?>(.*?)<\/li>/i', $description, $matches)) {
- return $matches[1];
- }
- return array($description);
- }
- /**
- * Before getPdf processing
- *
- */
- protected function _beforeGetPdf() {
- $translate = Mage::getSingleton('core/translate');
- /* @var $translate Mage_Core_Model_Translate */
- $translate->setTranslateInline(false);
- }
- /**
- * After getPdf processing
- *
- */
- protected function _afterGetPdf() {
- $translate = Mage::getSingleton('core/translate');
- /* @var $translate Mage_Core_Model_Translate */
- $translate->setTranslateInline(true);
- }
- protected function _formatOptionValue($value, $order)
- {
- $resultValue = '';
- if (is_array($value)) {
- if (isset($value['qty'])) {
- $resultValue .= sprintf('%d', $value['qty']) . ' x ';
- }
- $resultValue .= $value['title'];
- if (isset($value['price'])) {
- $resultValue .= " " . $order->formatPrice($value['price']);
- }
- return $resultValue;
- } else {
- return $value;
- }
- }
- protected function _initRenderer($type)
- {
- $node = Mage::getConfig()->getNode('global/pdf/'.$type);
- foreach ($node->children() as $renderer) {
- $this->_renderers[$renderer->getName()] = array(
- 'model' => (string)$renderer,
- 'renderer' => null
- );
- }
- }
- /**
- * Retrieve renderer model
- *
- * @throws Mage_Core_Exception
- * @return Mage_Sales_Model_Order_Pdf_Items_Abstract
- */
- protected function _getRenderer($type)
- {
- if (!isset($this->_renderers[$type])) {
- $type = 'default';
- }
- if (!isset($this->_renderers[$type])) {
- Mage::throwException(Mage::helper('sales')->__('Invalid renderer model'));
- }
- if (is_null($this->_renderers[$type]['renderer'])) {
- $this->_renderers[$type]['renderer'] = Mage::getSingleton($this->_renderers[$type]['model']);
- }
- return $this->_renderers[$type]['renderer'];
- }
- /**
- * Public method of protected @see _getRenderer()
- *
- * Retrieve renderer model
- *
- * @param string $type
- * @return Mage_Sales_Model_Order_Pdf_Items_Abstract
- */
- public function getRenderer($type)
- {
- return $this->_getRenderer($type);
- }
- /**
- * Draw Item process
- *
- * @param Varien_Object $item
- * @param Zend_Pdf_Page $page
- * @param Mage_Sales_Model_Order $order
- * @return Zend_Pdf_Page
- */
- protected function _drawItem(Varien_Object $item, Zend_Pdf_Page $page, Mage_Sales_Model_Order $order)
- {
- $type = $item->getOrderItem()->getProductType();
- $renderer = $this->_getRenderer($type);
- $renderer->setOrder($order);
- $renderer->setItem($item);
- $renderer->setPdf($this);
- $renderer->setPage($page);
- $renderer->setRenderedModel($this);
- $renderer->draw();
- return $renderer->getPage();
- }
- protected function _setFontRegular($object, $size = 7)
- {
- $font = Zend_Pdf_Font::fontWithPath(Mage::getBaseDir() . '/lib/LinLibertineFont/LinLibertineC_Re-2.8.0.ttf');
- $object->setFont($font, $size);
- return $font;
- }
- protected function _setFontBold($object, $size = 7)
- {
- $font = Zend_Pdf_Font::fontWithPath(Mage::getBaseDir() . '/lib/LinLibertineFont/LinLibertine_Bd-2.8.1.ttf');
- $object->setFont($font, $size);
- return $font;
- }
- protected function _setFontItalic($object, $size = 7)
- {
- $font = Zend_Pdf_Font::fontWithPath(Mage::getBaseDir() . '/lib/LinLibertineFont/LinLibertine_It-2.8.2.ttf');
- $object->setFont($font, $size);
- return $font;
- }
- /**
- * Set PDF object
- *
- * @param Zend_Pdf $pdf
- * @return Mage_Sales_Model_Order_Pdf_Abstract
- */
- protected function _setPdf(Zend_Pdf $pdf)
- {
- $this->_pdf = $pdf;
- return $this;
- }
- /**
- * Retrieve PDF object
- *
- * @throws Mage_Core_Exception
- * @return Zend_Pdf
- */
- protected function _getPdf()
- {
- if (!$this->_pdf instanceof Zend_Pdf) {
- Mage::throwException(Mage::helper('sales')->__('Please define PDF object before using.'));
- }
- return $this->_pdf;
- }
- /**
- * Create new page and assign to PDF object
- *
- * @param array $settings
- * @return Zend_Pdf_Page
- */
- public function newPage(array $settings = array())
- {
- $pageSize = !empty($settings['page_size']) ? $settings['page_size'] : Zend_Pdf_Page::SIZE_A4;
- $page = $this->_getPdf()->newPage($pageSize);
- $this->_getPdf()->pages[] = $page;
- $this->y = 800;
- return $page;
- }
- /**
- * Draw lines
- *
- * draw items array format:
- * lines array;array of line blocks (required)
- * shift int; full line height (optional)
- * height int;line spacing (default 10)
- *
- * line block has line columns array
- *
- * column array format
- * text string|array; draw text (required)
- * feed int; x position (required)
- * font string; font style, optional: bold, italic, regular
- * font_file string; path to font file (optional for use your custom font)
- * font_size int; font size (default 7)
- * align string; text align (also see feed parametr), optional left, right
- * height int;line spacing (default 10)
- *
- * @param Zend_Pdf_Page $page
- * @param array $draw
- * @param array $pageSettings
- * @throws Mage_Core_Exception
- * @return Zend_Pdf_Page
- */
- public function drawLineBlocks(Zend_Pdf_Page $page, array $draw, array $pageSettings = array())
- {
- foreach ($draw as $itemsProp) {
- if (!isset($itemsProp['lines']) || !is_array($itemsProp['lines'])) {
- Mage::throwException(Mage::helper('sales')->__('Invalid draw line data. Please define "lines" array.'));
- }
- $lines = $itemsProp['lines'];
- $height = isset($itemsProp['height']) ? $itemsProp['height'] : 10;
- if (empty($itemsProp['shift'])) {
- $shift = 0;
- foreach ($lines as $line) {
- $maxHeight = 0;
- foreach ($line as $column) {
- $lineSpacing = !empty($column['height']) ? $column['height'] : $height;
- if (!is_array($column['text'])) {
- $column['text'] = array($column['text']);
- }
- $top = 0;
- foreach ($column['text'] as $part) {
- $top += $lineSpacing;
- }
- $maxHeight = $top > $maxHeight ? $top : $maxHeight;
- }
- $shift += $maxHeight;
- }
- $itemsProp['shift'] = $shift;
- }
- if ($this->y - $itemsProp['shift'] < 15) {
- $page = $this->newPage($pageSettings);
- }
- foreach ($lines as $line) {
- $maxHeight = 0;
- foreach ($line as $column) {
- $fontSize = empty($column['font_size']) ? 7 : $column['font_size'];
- if (!empty($column['font_file'])) {
- $font = Zend_Pdf_Font::fontWithPath($column['font_file']);
- $page->setFont($font, $fontSize);
- }
- else {
- $fontStyle = empty($column['font']) ? 'regular' : $column['font'];
- switch ($fontStyle) {
- case 'bold':
- $font = $this->_setFontBold($page, $fontSize);
- break;
- case 'italic':
- $font = $this->_setFontItalic($page, $fontSize);
- break;
- default:
- $font = $this->_setFontRegular($page, $fontSize);
- break;
- }
- }
- if (!is_array($column['text'])) {
- $column['text'] = array($column['text']);
- }
- $lineSpacing = !empty($column['height']) ? $column['height'] : $height;
- $top = 0;
- foreach ($column['text'] as $part) {
- $feed = $column['feed'];
- $textAlign = empty($column['align']) ? 'left' : $column['align'];
- $width = empty($column['width']) ? 0 : $column['width'];
- switch ($textAlign) {
- case 'right':
- if ($width) {
- $feed = $this->getAlignRight($part, $feed, $width, $font, $fontSize);
- }
- else {
- $feed = $feed - $this->widthForStringUsingFontSize($part, $font, $fontSize);
- }
- break;
- case 'center':
- if ($width) {
- $feed = $this->getAlignCenter($part, $feed, $width, $font, $fontSize);
- }
- break;
- }
- $page->drawText($part, $feed, $this->y-$top, 'UTF-8');
- $top += $lineSpacing;
- }
- $maxHeight = $top > $maxHeight ? $top : $maxHeight;
- }
- $this->y -= $maxHeight;
- }
- }
- return $page;
- }
- }