Trying get dynamic content hole-punched through Magento's Full Page Cache - caching

I am using Magento Enterprise 1.10.1.1 and need to get some dynamic content on our product pages. I am inserting the current time in a block to quickly see if it is working, but can't seem to get through full page cache.
I have tried a variety of implementations found here:
http://tweetorials.tumblr.com/post/10160075026/ee-full-page-cache-hole-punching
http://oggettoweb.com/blog/customizations-compatible-magento-full-page-cache/
http://magentophp.blogspot.com/2011/02/magento-enterprise-full-page-caching.html
Any solutions, thoughts, comments, advice is welcome.
here is my code:
app/code/local/Fido/Example/etc/config.xml
<?xml version="1.0"?>
<config>
<modules>
<Fido_Example>
<version>0.1.0</version>
</Fido_Example>
</modules>
<global>
<blocks>
<fido_example>
<class>Fido_Example_Block</class>
</fido_example>
</blocks>
</global>
</config>
app/code/local/Fido/Example/etc/cache.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<placeholders>
<fido_example>
<block>fido_example/view</block>
<name>example</name>
<placeholder>CACHE_TEST</placeholder>
<container>Fido_Example_Model_Container_Cachetest</container>
<cache_lifetime>86400</cache_lifetime>
</fido_example>
</placeholders>
</config>
app/code/local/Fido/Example/Block/View.php
<?php
class Fido_Example_Block_View extends Mage_Core_Block_Template
{
private $message;
private $att;
protected function createMessage($msg) {
$this->message = $msg;
}
public function receiveMessage() {
if($this->message != '') {
return $this->message;
}
else {
$this->createMessage('Hello World');
return $this->message;
}
}
protected function _toHtml() {
$html = parent::_toHtml();
if($this->att = $this->getMyCustom() && $this->getMyCustom() != '') {
$html .= '<br />'.$this->att;
}
else {
$now = date('m-d-Y h:i:s A');
$html .= $now;
$html .= '<br />' ;
}
return $html;
}
}
app/code/local/Fido/Example/Model/Container/Cachetest.php
<?php
class Fido_Example_Model_Container_Cachetest extends Enterprise_PageCache_Model_Container_Abstract {
protected function _getCacheId()
{
return 'HOMEPAGE_PRODUCTS' . md5($this->_placeholder->getAttribute('cache_id') . $this->_getIdentifier());
}
protected function _renderBlock()
{
$blockClass = $this->_placeholder->getAttribute('block');
$template = $this->_placeholder->getAttribute('template');
$block = new $blockClass;
$block->setTemplate($template);
return $block->toHtml();
}
protected function _saveCache($data, $id, $tags = array(), $lifetime = null) { return false; }
}
app/design/frontend/enterprise/[mytheme]/template/example/view.phtml
<?php echo $this->receiveMessage() ?>
snippet from app/design/frontend/enterprise/[mytheme]/layout/catalog.xml
<reference name="content">
<block type="catalog/product_view" name="product.info" template="catalog/product/view.phtml">
<block type="fido_example/view" name="product.info.example" as="example" template="example/view.phtml" />

The <name> in the cache.xml must match your blocks full name in the layout, not the alias, e.g. <name>product.info.example</name>
Also, _getIdentifier() isn't implemented on Enterprise_PageCache_Model_Container_Abstract, just remove it from the string returned by your _getCacheId().
If you need to add some variants, implement _getIdentifier() to return a session id or whatever you need.

Related

Magento - pass a variable from Controller to checkout temaplte

I've read the other posts about this subject and tried loads of things but cant get a Variable from my controller file to the Checkout. I have very little experience with creating modules so followed a guide to create the following
app ▸ code ▸ local ▸ Creare ▸ AgeRestricted ▸ etc ▸ config.xml
<?xml version="1.0"?>
<config>
<modules>
<Creare_AgeRestricted>
<version>0.1.0</version>
</Creare_AgeRestricted>
</modules>
<global>
<events>
<payment_method_is_active>
<observers>
<age_restricted>
<type>singleton</type>
<class>AgeRestricted/observer</class>
<method>AgeRestricted</method>
</age_restricted>
</observers>
</payment_method_is_active>
</events>
<models>
<AgeRestricted>
<class>Creare_AgeRestricted_Model</class>
<resourceModel>agerestricted_mysql4</resourceModel>
</AgeRestricted>
</models>
<sales>
<quote>
<item>
<product_attributes>
<age_restricted/>
</product_attributes>
</item>
</quote>
</sales>
</global>
</config>
Macintosh HD ▸ WWW-local ▸ dexam ▸ htdocs_live ▸ app ▸ code ▸ local ▸ Creare ▸ AgeRestricted ▸ Model ▸ Observer.php
<?php
class Creare_AgeRestricted_Model_Observer
{
public function AgeRestricted(Varien_Event_Observer $observer)
{
Mage::register('feedback', $AgeRestricted);
$event = $observer->getEvent();
$method = $event->getMethodInstance();
$result = $event->getResult();
$AgeRestricted = false;
foreach (Mage::getSingleton('checkout/cart')->getQuote()->getAllVisibleItems() as $item)
{
if($item->getProduct()->getAgeRestricted()){
$AgeRestricted = true;
}
}
}
}
Notice I added the line:
Mage::register('feedback', $AgeRestricted);
then im trying to call this with:
echo Mage::registry('feedback');
in file:
app/design/frontend/dexam/default/template/checkout/onepage/payment.phtml
but it displays nothing at all. I've tested the location in payment.phtml is working.. my test text appears but 'feedback' is not calling the $AgeRestricted.
I tried echo $AgeRestricted; in my controller, which echo'd lots of '1's at the top of my screen so I can see the variable contains the true value.
How can I call $AgeRestricted in payment.phtml?
Many thanks!!
Daz
<?php
class Creare_AgeRestricted_Model_Observer
{
public function AgeRestricted(Varien_Event_Observer $observer)
{
$event = $observer->getEvent();
$method = $event->getMethodInstance();
$result = $event->getResult();
$AgeRestricted = false;
foreach (Mage::getSingleton('checkout/cart')->getQuote()->getAllVisibleItems() as $item)
{
if($item->getProduct()->getAgeRestricted()){
$AgeRestricted = true;
}
}
if(!Mage::register('feedback')){
Mage::register('feedback', $AgeRestricted); // put this line here after all processing
}
}
}
Hope this will help you out
You can use magento checkout sessions to set the value from the observer to payment file
<?php
class Creare_AgeRestricted_Model_Observer
{
public function AgeRestricted(Varien_Event_Observer $observer)
{
$event = $observer->getEvent();
$method = $event->getMethodInstance();
$result = $event->getResult();
$AgeRestricted = false;
foreach (Mage::getSingleton('checkout/cart')->getQuote()->getAllVisibleItems() as $item)
{
if($item->getProduct()->getAgeRestricted()){
$AgeRestricted = true;
}
}
if($AgeRestricted){
Mage::getSingleton('checkout/session')->setRestictedAge($AgeRestricted);
}
}
}
In your payment.phtml
<?php $session = Mage::getSingleton('checkout/session');?>
<?php echo $session->getRestrictedAge();?>

Magento payment method with form fields. Error: Cannot retrieve the payment method model object

I am creating a module for a new payment gateway (Pay On Account) that has a form field in the checkout (Only shows if user is logged in and has an account).
Mostly everything is working: The form field is captured correctly at checkout and saved in the sales_flat_order & sales_flat_quote tables.
The order code is being recorded correctly in the tables also (payonaccount)
The issue is when I try to view the order in the admin I get the following error:
Cannot retrieve the payment method model object.
Other SO answers mentioning I should correct the payment type in the DB don't work (as the payment type is correct)
Here is my code (all of it! Sorry but thanks!):
File structure:
app\code\local\Sulman\PayOnAccount\Block\Form\Payonaccount.php
<?php
class Sulman_PayOnAccount_Block_Form_Payonaccount extends Mage_Payment_Block_Form
{
protected function _construct()
{
parent::_construct();
$this->setTemplate('payment/form/payonaccount.phtml');
}
}
app\code\local\Sulman\PayOnAccount\Block\Info\Payonaccount.php
<?php
class Sulman_PayOnAccount_Block_Info_Payonaccount extends Mage_Payment_Block_Form
{
protected function _construct()
{
parent::_construct();
$this->setTemplate('payment/info/payonaccount.phtml');
}
public function getMethod()
{
return parent::getMethod();
}
}
app\code\local\Sulman\PayOnAccount\etc\config.xml
<?xml version="1.0"?>
<config>
<modules>
<Sulman_PayOnAccount>
<version>0.1.0</version>
</Sulman_PayOnAccount>
</modules>
<global>
<blocks>
<payonaccount>
<class>Sulman_PayOnAccount_Block</class>
</payonaccount>
</blocks>
<models>
<payonaccount>
<class>Sulman_PayOnAccount_Model</class>
</payonaccount>
</models>
<helpers>
<payonaccount>
<class>Sulman_PayOnAccount_Helper</class>
</payonaccount>
</helpers>
<payment>
<groups>
<payonaccount>PayOnAccount</payonaccount>
</groups>
</payment>
<!-- define install scripts -->
<resources>
<payonaccount_setup>
<setup>
<module>Sulman_PayOnAccount</module>
</setup>
<connection>
<use>core_setup</use>
</connection>
</payonaccount_setup>
</resources>
<fieldsets>
<sales_convert_quote_payment>
<poa_ponumber>
<to_order_payment>*</to_order_payment>
</poa_ponumber>
</sales_convert_quote_payment>
<sales_convert_quote_payment>
<poa_ponumber>
<to_order_payment>*</to_order_payment>
</poa_ponumber>
</sales_convert_quote_payment>
<sales_convert_quote>
<poa_ponumber>
<to_order>*</to_order>
</poa_ponumber>
</sales_convert_quote>
</fieldsets>
</global>
<default>
<payment>
<payonaccount>
<model>payonaccount/payonaccount</model>
<active>1</active>
<order_status>pending</order_status>
<title>Pay On Account</title>
<payment_action>sale</payment_action>
<allowspecific>0</allowspecific>
<sort_order>1</sort_order>
</payonaccount>
</payment>
</default>
</config>
app\code\local\Sulman\PayOnAccount\Model\Payonaccount.php
<?php
class Sulman_PayOnAccount_Model_Payonaccount extends Mage_Payment_Model_Method_Abstract
{
protected $_code = 'payonaccount';
protected $_formBlockType = 'payonaccount/form_payonaccount';
protected $_infoBlockType = 'payonaccount/info_payonaccount';
public function isAvailable($quote = null) {
$isLoggedIn = Mage::helper('customer')->isLoggedIn();
$canPayOnAccount = false;
if(Mage::getSingleton('customer/session')->isLoggedIn()) {
$customerData = Mage::getSingleton('customer/session')->getCustomer();
$customerObj = Mage::getModel('customer/customer')->load($customerData->getId());
$hasAccount = $customerObj->getData('has_account'); // 1 = No, 2 = Yes
if( is_null($hasAccount) OR $hasAccount == 1){
$canPayOnAccount = false;
} elseif($hasAccount == 2){
$canPayOnAccount = true;
}
}
return parent::isAvailable($quote) && $canPayOnAccount;
}
public function assignData($data)
{
if (!($data instanceof Varien_Object)) {
$data = new Varien_Object($data);
}
Mage::log("getPoaPonumber: ".$data->getPoaPonumber(), null, 'sulman.log');
$this->getInfoInstance()->setPoaPonumber($data->getPoaPonumber());
return $this;
}
}
app\code\local\Sulman\PayOnAccount\sql\payonaccount_setup\mysql4-install-0.1.0.php
<?php
$installer = $this;
$installer->startSetup();
$installer->run("
ALTER TABLE `{$installer->getTable('sales/quote')}` ADD `poa_ponumber` VARCHAR( 255 ) NOT NULL ;
ALTER TABLE `{$installer->getTable('sales/order')}` ADD `poa_ponumber` VARCHAR( 255 ) NOT NULL ;
");
$installer->endSetup();
app\design\adminhtml\default\default\template\payment\info\payonaccount.phtml
<?php
echo $this->getMethod();
?>
<p><?php //echo $this->escapeHtml($this->getMethod()->getTitle()) ?></p>
app\design\frontend\cmtgroup\default\template\payment\form\payonaccount.phtml
<ul class="form-list" id="payment_form_<?php echo $this->getMethodCode() ?>" style="display:none;">
<li>
<label for="poa_ponumber" class="required"><em>*</em><?php echo $this->__('Purchase Order Number') ?></label>
<div class="input-box">
<input type="text" id="poa_ponumber" name="payment[poa_ponumber]" title="<?php echo $this->__('Purchase Order Number') ?>" class="input-text" value="<?php echo $this->escapeHtml($this->getInfoData('poa_ponumber')) ?>" />
</div>
</li>
</ul>
If I try and load the order elsewhere and get the poa_number like so:
$_order->getPoaNumber();
It doesn't return anything.
Any ideas? Thanks.
Ok so I have solved this... I added an observer on the sales_order_save_after event that gets the payment info and records the poa_ponumber against the order like so:
public function saveBefore(Varien_Event_Observer $observer){
// get the quote of the order so we can get the quote payment type poa_ponumber
$order = $observer->getEvent()->getOrder();
$quote = Mage::getModel('sales/quote')->loadByIdWithoutStore($order->getQuoteId());
$poaponumber = $quote->getPayment()->getPoaPonumber();
$order->setPoaPonumber($poaponumber);
}
This saves the poa_ponumber to the flat order table and can then be easily extracted the normal way: $_order->getPoaPonumber();
I'm sure this isn't quite the right way but it works.
Please check exist $_code in your payment method model.
You can refer :
Mage_Payment_Model_Method_Abstract
Line : 343
public function getCode()
{
if (empty($this->_code)) {
Mage::throwException(Mage::helper('payment')->__('Cannot retrieve the payment method code.'));
}
return $this->_code;
}

Magento payment method according to product options

I need to perform the next action when a customer is making the purchase of products:
If there is a product with custom options to display only a method of payment and if no other method.
how to do this ... I'm going crazy
thanks
You can do this event observer
create an extension under app/code/local
Bh_ZeroSubtotalpaymentmethod_Model
File of extension are config.xml under
app/code/local/Bh/ZeroSubtotalpaymentmethod/etc
and it code is
<?xml version="1.0" ?>
<config>
<modules>
<Bh_ZeroSubtotalpaymentmethod>
<version>1.0.1</version>
</Bh_ZeroSubtotalpaymentmethod>
</modules>
<global>
<models>
<zerosubtotalpaymentmethod>
<class>Bh_ZeroSubtotalpaymentmethod_Model</class>
</zerosubtotalpaymentmethod>
</models>
</global>
<frontend>
<events>
<payment_method_is_active>
<observers>
<paymentfilter_payment_method_is_active>
<type>singleton</type>
<class>zerosubtotalpaymentmethod/observer</class>
<method>filterpaymentmethod</method>
</paymentfilter_payment_method_is_active>
</observers>
</payment_method_is_active>
</events>
</frontend>
</config>
and Observer file code
is
<?php
class Bh_ZeroSubtotalpaymentmethod_Model_Observer {
public function filterpaymentmethod(Varien_Event_Observer $observer) {
/* call get payment method */
$method = $observer->getEvent()->getMethodInstance();
if($method->getCode()=='paypal_standard')
{ $quote = $observer->getEvent()->getQuote();
if($this->checkcustomoption()==true){
$result = $observer->getEvent()->getResult();
$result->isAvailable = false;
}
return;
}
if($method->getCode()=='free'){
$quote = $observer->getEvent()->getQuote();
if($this->checkcustomoption()==false){
$result = $observer->getEvent()->getResult();
$result->isAvailable = false;
return;
}
}
return;
}
public function checkcustomoption(){
//To get your cart object (in session) :
$quote = Mage::getSingleton('checkout/session')->getQuote();
//Then, to get the list of items in the cart :
$cartItems = $quote->getAllVisibleItems();
//Then, to get the count for each item :
foreach ($cartItems as $item)
{ // check $item->getProduct() give cart item
$item->getProduct();
if(your_logic_match){
return true;
break;
}
}
retrun false;
}
}
?>
for check and custom option used https://magento.stackexchange.com/questions/17867/get-custom-option-price-in-order blog Gavin answer

Magento. Rewrite save for admin custom field

I created new field and included it into system.xml (Pin_Init_Block_Adminhtml_System_Robots)
Show i controled by _getElementHtml or render.
How i can catch save?
<?php
class Pin_Init_Block_Adminhtml_System_Robots extends Mage_Adminhtml_Block_System_Config_Form_Field
{
protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
{
//self::__writeRobots($element->getEscapedValue());
$html = '<textarea id="'.$element->getHtmlId().'" name="'.$element->getName()
.'" '.$element->serialize($element->getHtmlAttributes()).'>'.self::__readRobots().'</textarea>'."\n";
$html.= $element->getAfterElementHtml();
return $html;
}
protected function __readRobots( )
{
$file = fopen( Mage::getBaseDir().'/robots.txt', "r");
if(!$file) return $this->content;
$content = '';
while (!feof($file)):
$content .= fgets($file);
endwhile;
fclose($file);
return $content;
}
protected function __writeRobots( $content )
{
$file = #fopen( Mage::getBaseDir().'/robots.txt', 'w');
#fwrite($file, "$content");
}
protected function _beforeSave()
{
self::__writeRobots('text1');
}
protected function _afterSave ()
{
self::__writeRobots('text1');
}
}
?>
File: /app/code/community/Pin/Init/Block/Adminhtml/System
XML:
<robots translate="label">
<label>Robots.txt</label>
<comment></comment>
<frontend_type>text</frontend_type>
<frontend_model>init/adminhtml_system_robots</frontend_model>
<sort_order>3</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</robots>
You can specify to your element a backend_model then implement in that model the methods _afterSave and _beforeSave.
You can use as an example the web/unsecure/base_url element. It is defined in app/code/core/Mage/Core/etc/system.xml and has the backend model adminhtml/system_config_backend_baseurl.
That is equivalent to the class Mage_Adminhtml_Model_System_Config_Backend_Baseurl.
See what happens in there.
UPDATE
Make your config look like this:
<robots translate="label">
<label>Robots.txt</label>
<comment></comment>
<frontend_type>text</frontend_type>
<frontend_model>init/adminhtml_system_robots</frontend_model>
<backend_model>init/adminhtml_system_backend_robots</backend_model><!-- add this line -->
<sort_order>3</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</robots>
Now create the following class (put it in the proper file):
<?php
class Pin_Init_Block_Adminhtml_System_Backend_Robots extends Mage_Core_Model_Config_Data{
protected function _beforeSave()
{
//this is called before the value is saved
$value = $this->getValue();//this is how you can get the value
//do your magic with $value
}
protected function _afterSave()
{
//this is called after the value is saved
$value = $this->getValue();//this is how you can get the value
//do your magic with $value
}
}

Remove telephone as required field on shipping but not billing Magento

How do I make the telephone field not required on shipping but have it required on billing in onepage checkout?
I have followed many forums that point to the below method but this disables the required element on both billing and shipping?
http://swarminglabs.com/magento-making-the-telephone-field-not-required-at-checkout/#comment-2687
I do not know any extension that would allow this. If you want to make it work you should work with Mage_Customer_Model_Form. During checkout process magento calls validateData() method of this model. This method is defined in Mage_Eav_Model_Form. You need to rewrite another model, namely Mage_Sales_Model_Quote_Address as its parent Mage_Customer_Model_Address_Abstract has a valid() method that checks if telephone is not emtpy. So, assuming you have removed is_required and validation_rules for this attribute
in a module etc/config.xml
<config>
<global>
<models>
<customer>
<rewrite>
<form>YourNamespace_YourModule_Model_Customer_Form</form>
</rewrite>
</customer>
<sales>
<rewrite>
<quote_address>YourNamespace_YourModule_Model_Quote_Address</quote_address>
</rewrite>
</sales>
</models>
</global>
</config>
in YourNamespace/YourModule/Model/Customer/Form.php
class YourNamespace_YourModule_Model_Customer_Form extends Mage_Customer_Model_Form {
public function validateData(array $data) {
//perform parent validation
$result = parent::validateData($data);
//checking billing address; perform additional validation
if ($this->getEntity()->getAddressType() == Mage_Sales_Model_Quote_Address::TYPE_BILLING) {
$valid = $this->_validatePhoneForBilling($data);
if ($result !== true && $valid !== true) {
$result[] = $valid;
}
elseif ($result === true && $valid !== true) {
$result = $valid;
}
}
return $result;
}
protected function _validatePhoneForBilling($data) {
$errors = array();
if (empty($data['telephone'])) {
$attribute = $this->getAttribute('telephone');
$label = Mage::helper('eav')->__($attribute->getStoreLabel());
$errors[] = Mage::helper('eav')->__('"%s" is a required value.', $label);
}
if (empty($errors)) {
return true;
}
return $errors;
}
}
in YourNamespace/YourModule/Model/Quote/Address.php
class YourNamespace_YourModule_Model_Quote_Address extends Mage_Sales_Model_Quote_Address {
public function validate() {
if ($this->getAddressType() == self::TYPE_SHIPPING) {
$result = parent::validate();
$errorMsg = Mage::helper('customer')->__('Please enter the telephone number.');
if (is_array($result) && in_array($errorMsg, $result)) {
$result = array_diff($result, array($errorMsg));
}
if (empty($result)) {
return true;
}
return $result;
}
else {
return parent::validate();
}
}
}

Resources