Hello guys,
This is a great requirement to have a print link on the product detail( product view) page in magento commerce. I am writing this content for version 1.4.0.1.
The content is not short or easy, I am only writing the steps to accomplish this task and hope the viewers of this site could get a solution.
The content has been divided into four steps and is explained step by step.
Step1. How to start?
The print is a command much like viewing a product detail and each command is controlled through “controllers” which is available into “module/…/action”.
Here for product view,
module = catalog
… = product
action = viewAction
So in case of Print command these should be
module = catalog
… = product
and action = print
In “/app/code/core/Mage/Catalog/controllers/ProductController.php” create a new funtion “printAction()”. To create this function simply copy the function “viewAction()” and rename it and modify the line
“Mage:dispatchEvent(‘catalog_controller_product_view’,…)” to “Mage:dispatchEvent(‘catalog_controller_product_print’,…)”
/**
* Print product action function
in “app\code\core\Mage\Catalog\controllers\ProductController.php
*/
public function printAction()
{
if ($product = $this->_initProduct()) {
Mage::dispatchEvent(‘catalog_controller_product_print’, array(‘product’=>$product));
if ($this->getRequest()->getParam(‘options’)) {
$notice = $product->getTypeInstance(true)->getSpecifyOptionMessage();
Mage::getSingleton(‘catalog/session’)->addNotice($notice);
}
Mage::getSingleton(‘catalog/session’)->setLastViewedProductId($product->getId());
Mage::getModel(‘catalog/design’)->applyDesign($product, Mage_Catalog_Model_Design::APPLY_FOR_PRODUCT);
$this->_initProductLayout($product);
$this->_initLayoutMessages(‘catalog/session’);
$this->_initLayoutMessages(‘tag/session’);
$this->_initLayoutMessages(‘checkout/session’);
$this->renderLayout();
}
else {
if (isset($_GET['store']) && !$this->getResponse()->isRedirect()) {
$this->_redirect(”);
} elseif (!$this->getResponse()->isRedirect()) {
$this->_forward(‘noRoute’);
}
}
}
Step2. Creating link for print
Actually the real link (URL) for product view page is “/index.php/catalog/product/view/id/$id/category/$category”.
And the content on print page of product is much like the content on product view page and we can get easily these contents from allready available for product view page so we will keep the print link as “/index.php/catalog/product/print/id/$id”.
No need to add category and its id.
Put this code anywhere you want better in product view template file which is “/view.phtml”.
<a href=”<?php echo $this->getBaseurl();?>catalog/product/print/id/<?php echo $this->getProduct()->getId();?> target=”_blank”>Print Product Detail</a>
Step3. Create a block file for print
Create a block file(.php) file. Copy View.php and rename it to Print.php and change the class name to “Mage_catalog_Block_Product_Print” and do nothing.
/**
* Product Print block
*
* @category Mage
* @package Mage_Catalog
* @module Catalog
*/
class Mage_Catalog_Block_Product_Print extends Mage_Catalog_Block_Product_Abstract
{
/**
* Add meta information from product to head block
*
* @return Mage_Catalog_Block_Product_Print
*/
protected function _prepareLayout()
{
$this->getLayout()->createBlock(‘catalog/breadcrumbs’);
$headBlock = $this->getLayout()->getBlock(‘head’);
if ($headBlock) {
$product = $this->getProduct();
$title = $product->getMetaTitle();
if ($title) {
$headBlock->setTitle($title);
}
$keyword = $product->getMetaKeyword();
$currentCategory = Mage::registry(‘current_category’);
if ($keyword) {
$headBlock->setKeywords($keyword);
} elseif($currentCategory) {
$headBlock->setKeywords($product->getName());
}
$description = $product->getMetaDescription();
if ($description) {
$headBlock->setDescription( ($description) );
} else {
$headBlock->setDescription($product->getDescription());
}
if ($this->helper(‘catalog/product’)->canUseCanonicalTag()) {
$params = array(‘_ignore_category’=>true);
$headBlock->addLinkRel(‘canonical’, $product->getUrlModel()->getUrl($product, $params));
}
}
return parent::_prepareLayout();
}
/**
* Retrieve current product model
*
* @return Mage_Catalog_Model_Product
*/
public function getProduct()
{
if (!Mage::registry(‘product’) && $this->getProductId()) {
$product = Mage::getModel(‘catalog/product’)->load($this->getProductId());
Mage::register(‘product’, $product);
}
return Mage::registry(‘product’);
}
/**
* Check if product can be emailed to friend
*
* @return bool
*/
public function canEmailToFriend()
{
$sendToFriendModel = Mage::registry(‘send_to_friend_model’);
return $sendToFriendModel && $sendToFriendModel->canEmailToFriend();
}
/**
in “app\code\core\Mage\Catalog\Block\Product\Print.php”
* Retrieve url for direct adding product to cart
*
* @param Mage_Catalog_Model_Product $product
* @param array $additional
* @return string
*/
public function getAddToCartUrl($product, $additional = array())
{
if ($this->getRequest()->getParam(‘wishlist_next’)){
$additional['wishlist_next'] = 1;
}
return $this->helper(‘checkout/cart’)->getAddUrl($product, $additional);
}
/**
* Get JSON encripted configuration array which can be used for JS dynamic
* price calculation depending on product options
*
* @return string
*/
public function getJsonConfig()
{
$config = array();
if (!$this->hasOptions()) {
return Mage::helper(‘core’)->jsonEncode($config);
}
$_request = Mage::getSingleton(‘tax/calculation’)->getRateRequest(false, false, false);
$_request->setProductClassId($this->getProduct()->getTaxClassId());
$defaultTax = Mage::getSingleton(‘tax/calculation’)->getRate($_request);
$_request = Mage::getSingleton(‘tax/calculation’)->getRateRequest();
$_request->setProductClassId($this->getProduct()->getTaxClassId());
$currentTax = Mage::getSingleton(‘tax/calculation’)->getRate($_request);
$_regularPrice = $this->getProduct()->getPrice();
$_finalPrice = $this->getProduct()->getFinalPrice();
$_priceInclTax = Mage::helper(‘tax’)->getPrice($this->getProduct(), $_finalPrice, true);
$_priceExclTax = Mage::helper(‘tax’)->getPrice($this->getProduct(), $_finalPrice);
$config = array(
‘productId’ => $this->getProduct()->getId(),
‘priceFormat’ => Mage::app()->getLocale()->getJsPriceFormat(),
‘includeTax’ => Mage::helper(‘tax’)->priceIncludesTax() ? ‘true’ : ‘false’,
‘showIncludeTax’ => Mage::helper(‘tax’)->displayPriceIncludingTax(),
‘showBothPrices’ => Mage::helper(‘tax’)->displayBothPrices(),
‘productPrice’ => Mage::helper(‘core’)->currency($_finalPrice, false, false),
‘productOldPrice’ => Mage::helper(‘core’)->currency($_regularPrice, false, false),
‘skipCalculate’ => ($_priceExclTax != $_priceInclTax ? 0 : 1),
‘defaultTax’ => $defaultTax,
‘currentTax’ => $currentTax,
‘idSuffix’ => ‘_clone’,
‘oldPlusDisposition’ => 0,
‘plusDisposition’ => 0,
‘oldMinusDisposition’ => 0,
‘minusDisposition’ => 0,
);
$responseObject = new Varien_Object();
Mage::dispatchEvent(‘catalog_product_view_config’, array(‘response_object’=>$responseObject));
if (is_array($responseObject->getAdditionalOptions())) {
foreach ($responseObject->getAdditionalOptions() as $option=>$value) {
$config[$option] = $value;
}
}
return Mage::helper(‘core’)->jsonEncode($config);
}
/**
* Return true if product has options
*
* @return bool
*/
public function hasOptions()
{
if ($this->getProduct()->getTypeInstance(true)->hasOptions($this->getProduct())) {
return true;
}
return false;
}
/**
* Check if product has required options
*
* @return bool
*/
public function hasRequiredOptions()
{
return $this->getProduct()->getTypeInstance(true)->hasRequiredOptions($this->getProduct());
}
}
Step4. Front Design
a) Layout (layout/catalog.xml)
Copy the layout of product view and paste it under and then change the head tag “catalog_product_view” to “catalog_product_print”. Set template to “page/print_product.phtml”. And in reference, where ‘name=”content”‘ set block type to “catalog/product_print” and set template to “catalog/product/print.phtml”
To create print_product.phtml copy print.phtml from review block and paste it into “template/page/” folder.
<!–
Product Print in catalog.xml
–>
<catalog_product_print translate=”label”>
<label>Catalog Product View (Any)</label>
<!– Mage_Catalog –>
<reference name=”root”>
<action method=”setTemplate”><template>page/print.phtml</template></action>
</reference>
<reference name=”head”>
<action method=”addJs”><script>varien/product.js</script></action>
<action method=”addItem”><type>js_css</type><name>calendar/calendar-win2k-1.css</name><params/><!–<if/><condition>can_load_calendar_js</condition>–></action>
<action method=”addItem”><type>js</type><name>calendar/calendar.js</name><!–<params/><if/><condition>can_load_calendar_js</condition>–></action>
<action method=”addItem”><type>js</type><name>calendar/calendar-setup.js</name><!–<params/><if/><condition>can_load_calendar_js</condition>–></action>
</reference>
<reference name=”content”>
<block type=”catalog/product_print” name=”product.info” template=”catalog/product/print.phtml”>
<!–
<action method=”addReviewSummaryTemplate”><type>default</type><template>review/helper/summary.phtml</template></action>
<action method=”addReviewSummaryTemplate”><type>short</type><template>review/helper/summary_short.phtml</template></action>
<action method=”addReviewSummaryTemplate”><type>…</type><template>…</template></action>
–>
<block type=”catalog/product_view_media” name=”product.info.media” as=”media” template=”catalog/product/view/media.phtml”/>
<block type=”core/text_list” name=”alert.urls” as=”alert_urls” translate=”label”>
<label>Alert Urls</label>
</block>
<action method=”setTierPriceTemplate”><template>catalog/product/view/tierprices.phtml</template></action>
<block type=”catalog/product_list_upsell” name=”product.info.upsell” as=”upsell_products” template=”catalog/product/list/upsell.phtml”>
<action method=”setColumnCount”><columns>4</columns></action>
<action method=”setItemLimit”><type>upsell</type><limit>4</limit></action>
</block>
<block type=”catalog/product_view_additional” name=”product.info.additional” as=”product_additional_data” />
<block type=”catalog/product_view_description” name=”product.description” as=”description” template=”catalog/product/view/description.phtml”/>
<block type=”catalog/product_view_attributes” name=”product.attributes” as=”additional” template=”catalog/product/view/attributes.phtml”/>
<block type=”catalog/product_view” name=”product.info.addto” as=”addto” template=”catalog/product/view/addto.phtml”/>
<block type=”catalog/product_view” name=”product.info.addtocart” as=”addtocart” template=”catalog/product/view/addtocart.phtml”/>
<block type=”catalog/product_view” name=”product.info.options.wrapper” as=”product_options_wrapper” template=”catalog/product/view/options/wrapper.phtml” translate=”label”>
<label>Info Column Options Wrapper</label>
<block type=”core/template” name=”options_js” template=”catalog/product/view/options/js.phtml”/>
<block type=”catalog/product_view_options” name=”product.info.options” as=”product_options” template=”catalog/product/view/options.phtml”>
<action method=”addOptionRenderer”><type>text</type><block>catalog/product_view_options_type_text</block><template>catalog/product/view/options/type/text.phtml</template></action>
<action method=”addOptionRenderer”><type>file</type><block>catalog/product_view_options_type_file</block><template>catalog/product/view/options/type/file.phtml</template></action>
<action method=”addOptionRenderer”><type>select</type><block>catalog/product_view_options_type_select</block><template>catalog/product/view/options/type/select.phtml</template></action>
<action method=”addOptionRenderer”><type>date</type><block>catalog/product_view_options_type_date</block><template>catalog/product/view/options/type/date.phtml</template></action>
</block>
<block type=”core/html_calendar” name=”html_calendar” as=”html_calendar” template=”page/js/calendar.phtml”/>
</block>
<block type=”catalog/product_view” name=”product.info.options.wrapper.bottom” as=”product_options_wrapper_bottom” template=”catalog/product/view/options/wrapper/bottom.phtml” translate=”label”>
<label>Bottom Block Options Wrapper</label>
<action method=”insert”><block>product.tierprices</block></action>
<block type=”catalog/product_view” name=”product.clone_prices” as=”prices” template=”catalog/product/view/price_clone.phtml”/>
<action method=”append”><block>product.info.addtocart</block></action>
</block>
<block type=”core/template_facade” name=”product.info.container1″ as=”container1″>
<action method=”setDataByKey”><key>alias_in_layout</key><value>container1</value></action>
<action method=”setDataByKeyFromRegistry”><key>options_container</key><key_in_registry>product</key_in_registry></action>
<action method=”append”><block>product.info.options.wrapper</block></action>
<action method=”append”><block>product.info.options.wrapper.bottom</block></action>
</block>
<block type=”core/template_facade” name=”product.info.container2″ as=”container2″>
<action method=”setDataByKey”><key>alias_in_layout</key><value>container2</value></action>
<action method=”setDataByKeyFromRegistry”><key>options_container</key><key_in_registry>product</key_in_registry></action>
<action method=”append”><block>product.info.options.wrapper</block></action>
<action method=”append”><block>product.info.options.wrapper.bottom</block></action>
</block>
<action method=”unsetCallChild”><child>container1</child><call>ifEquals</call><if>0</if><key>alias_in_layout</key><key>options_container</key></action>
<action method=”unsetCallChild”><child>container2</child><call>ifEquals</call><if>0</if><key>alias_in_layout</key><key>options_container</key></action>
</block>
</reference>
<reference name=”right”>
<block type=”catalog/product_list_related” name=”catalog.product.related” before=”-” template=”catalog/product/list/related.phtml”/>
</reference>
</catalog_product_print>
/* product_print.phtml*/
<?php
/**
* Template for Mage_Page_Block_Html
*/
?>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” xml:lang=”<?php echo $this->getLang() ?>” lang=”<?php echo $this->getLang() ?>”>
<head>
<?php echo $this->getChildHtml(‘head’) ?>
</head>
<body>
<div>
<div>
<img src=”<?php echo $this->getPrintLogoUrl() ? $this->getPrintLogoUrl() : $this->getSkinUrl(‘images/logo_print.gif’) ?>” alt=”" />
<?php if ($this->getPrintLogoText()):?>
<address><?php echo nl2br($this->htmlEscape($this->getPrintLogoText())) ?></address>
<?php endif;?>
</div>
<?php echo $this->getChildHtml(‘content’) ?>
<div>
<button type=”button” title=”<?php echo $this->__(‘Close Window’) ?>” onclick=”window.close();”><span><span><?php echo $this->__(‘Close Window’) ?></span></span></button>
</div>
<?php echo $this->getAbsoluteFooter() ?>
</div>
</body>
</html>
b) Desing
Copy “view.phtml” from “/app/desing/frontend/base/default/template/catalog/product/” and paste into the same folder and rename it “print.phtml”.
/**
* Product print template
*
* @see Mage_Catalog_Block_Product_Print
* @see Mage_Review_Block_Product_Print
*/
?>
<?php
$_helper = $this->helper(‘catalog/output’);
$_product = $this->getProduct();
?>
<script type=”text/javascript”>
var optionsPrice = new Product.OptionsPrice(<?php echo $this->getJsonConfig() ?>);
</script>
<div id=”messages_product_view”><?php echo $this->getMessagesBlock()->getGroupedHtml() ?></div>
<div>
<div>
<form action=”<?php echo $this->getAddToCartUrl($_product) ?>” method=”post” id=”product_addtocart_form”<?php if($_product->getOptions()): ?> enctype=”multipart/form-data”<?php endif; ?>>
<div>
<input type=”hidden” name=”product” value=”<?php echo $_product->getId() ?>” />
<input type=”hidden” name=”related_product” id=”related-products-field” value=”" />
</div>
<div>
<div>
<h1><?php echo $_helper->productAttribute($_product, $_product->getName(), ‘name’) ?></h1>
</div>
<?php if ($this->canEmailToFriend()): ?>
<p><a href=”<?php echo $this->helper(‘catalog/product’)->getEmailToFriendUrl($_product) ?>”><?php echo $this->__(‘Email to a Friend’) ?></a></p>
<?php endif; ?>
<?php echo $this->getReviewsSummaryHtml($_product, false, true)?>
<?php echo $this->getChildHtml(‘alert_urls’) ?>
<?php echo $this->getChildHtml(‘product_type_data’) ?>
<?php echo $this->getTierPriceHtml() ?>
<?php if (!$this->hasOptions()):?>
<div>
<?php if($_product->isSaleable()): ?>
<?php echo $this->getChildHtml(‘addtocart’) ?>
<?php if( $this->helper(‘wishlist’)->isAllow() || $_compareUrl=$this->helper(‘catalog/product_compare’)->getAddUrl($_product)): ?>
<span><?php echo $this->__(‘OR’) ?></span>
<?php endif; ?>
<?php endif; ?>
<?php echo $this->getChildHtml(‘addto’) ?>
</div>
<?php else:?>
<?php echo $this->getChildHtml(‘addto’) ?>
<?php endif; ?>
<?php if ($_product->getShortDescription()):?>
<div>
<h2><?php echo $this->__(‘Quick Overview’) ?></h2>
<div><?php echo $_helper->productAttribute($_product, nl2br($_product->getShortDescription()), ‘short_description’) ?></div>
</div>
<?php endif;?>
<?php echo $this->getChildHtml(‘other’);?>
<?php if ($_product->isSaleable() && $this->hasOptions()):?>
<?php echo $this->getChildChildHtml(‘container1′, ”, true, true) ?>
<?php endif;?>
</div>
<div>
<?php echo $this->getChildHtml(‘media’) ?>
</div>
<div></div>
<?php if ($_product->isSaleable() && $this->hasOptions()):?>
<?php echo $this->getChildChildHtml(‘container2′, ”, true, true) ?>
<?php endif;?>
</form>
<script type=”text/javascript”>
//<![CDATA[
var productAddToCartForm = new VarienForm('product_addtocart_form');
productAddToCartForm.submit = function(){
if (this.validator.validate()) {
this.form.submit();
}
}.bind(productAddToCartForm);
//]]>
</script>
</div>
<div>
<?php echo $this->getChildHtml(‘description’) ?>
<?php echo $this->getChildHtml(‘additional’) ?>
<?php echo $this->getChildHtml(‘upsell_products’) ?>
<?php echo $this->getChildHtml(‘product_additional_data’) ?>
<?php echo $this->getProductId();?>
</div>
</div>
Make sure you have made backup of your magento project.