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
}
}
Related
I am programmatically loading a block inside Magento admin controller like this
`$block = $this->getLayout()->createBlock('core/text')->setText('<script type="text/javascript" ></script>');`
Now, instead of setText, I would like to use setTemplate method. I have created a temlplate file in this directory design/adminhtml/default/default/product/productcrop.phtml
How should I load it,i.e.,what would be the argument inside setTemplate method?
I tried this way: ->setTemplate('adminhtml/product_productcrop.phtml'). But it doesn't seems to be working.
The whole controller code is:
<?php
class Homeliv_Leadsadmin_Adminhtml_ProductController extends Mage_Adminhtml_Controller_Action {
public function indexAction() {
$this->loadLayout()->_setActiveMenu('leadsadmin/product');
$this->_addContent($this->getLayout()->createBlock('leadsadmin/adminhtml_product'));
$this->renderLayout();
}
public function editAction() {
$product_id = $this->getRequest()->getParam('id');
$full_product = Mage::getModel('catalog/product')->load($product_id);
$productMediaConfig = Mage::getModel('catalog/product_media_config');
//$baseImageUrl = $productMediaConfig->getMediaUrl($full_product->getImage());
//$thumbImageUrl = $productMediaConfig->getMediaUrl($full_product->getThumbnail());
$smallImage = $productMediaConfig->getMediaUrl($full_product->getSmallImage());
$this->loadLayout();
//$this->_title($this->__("Product"));
/* $block = $this->getLayout()->createBlock('core/text')->setText('<script type="text/javascript" src="'.Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB).'media/leadsadmin/product_crop.js'.'"></script>');
$this->_addJs($block);
$this->_addLeft($this->getLayout()
->createBlock('core/text')
->setText('<h1>Image</h1><img src="'.$smallImage.'"/>'));
$block = $this->getLayout()
->createBlock('core/text')
->setText('<h1>Main Block</h1>');
$this->_addContent($block);*/
$block = $this->getLayout()->createBlock('core/template')-> setTemplate('product/productcrop.phtml')->toHtml();
$this->_addContent($block);
//$this->getLayout()->createBlock('leadsadmin/adminhtml_product')->setTemplate('product/productcrop.phtml')->toHtml();
//$this->getLayout()->createBlock('core/text')->setText('<div>ssxsxsx</div>');
$this->renderLayout();
//var_dump(Mage::getSingleton('core/layout')->getUpdate()->getHandles());
//die();
//$this->loadLayout()->_setActiveMenu('leadsadmin/product');
//$this->_addContent($this->getLayout()->createBlock('leadsadmin/adminhtml_product'));
//$this->renderLayout();
}
}
for the template you have. you template path will be to set template product/productcrop.phtml
$block = $this->getLayout()
->createBlock('core/template')
->setTemplate('product/productcrop.phtml');
$this->getLayout()->getBlock('content')->append($block);
Is it possible to send two email in magento on order with different template, please tell how, or any extension available?
Sorry, my solution not very clear sometimes.
For test purposes I created new template, based on existing 'New order' in System / Email Templates.
Then create system.xml file where we can add new fields with template selectors:
<?xml version="1.0"?>
<config>
<sections>
<sales_email>
<groups>
<order>
<fields>
<template2>
<label>222 New Order Confirmation Template</label>
<frontend_type>select</frontend_type>
<source_model>adminhtml/system_config_source_email_template</source_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>
</template2>
<guest_template2 translate="label">
<label>222 New Order Confirmation Template for Guest</label>
<frontend_type>select</frontend_type>
<source_model>adminhtml/system_config_source_email_template</source_model>
<sort_order>4</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</guest_template2>
</fields>
</order>
</groups>
</sales_email>
</sections>
</config>
As you can see we created two new fields template2 and guest_template2.
Then create your own new model, which extends !!!NOT REWRITES!!! Mage_Sales_Model_Order
Add there two new constants
class Vendor_Somemodule_Model_Order extends Mage_Sales_Model_Order
{
const XML_PATH_EMAIL_TEMPLATE = 'sales_email/order/template2';
const XML_PATH_EMAIL_GUEST_TEMPLATE = 'sales_email/order/guest_template2';
and copy-paste method sendNewOrderEmail(). In this method remove two rows at the bottom
$this->setEmailSent(true);
$this->_getResource()->saveAttribute($this, 'email_sent');
And your result will be:
public function sendNewOrderEmail()
{
$storeId = $this->getStore()->getId();
if (!Mage::helper('sales')->canSendNewOrderEmail($storeId)) {
return $this;
}
$emailSentAttributeValue = $this->load($this->getId())->getData('email_sent');
$this->setEmailSent((bool)$emailSentAttributeValue);
if ($this->getEmailSent()) {
return $this;
}
// Get the destination email addresses to send copies to
$copyTo = $this->_getEmails(self::XML_PATH_EMAIL_COPY_TO);
$copyMethod = Mage::getStoreConfig(self::XML_PATH_EMAIL_COPY_METHOD, $storeId);
// Start store emulation process
$appEmulation = Mage::getSingleton('core/app_emulation');
$initialEnvironmentInfo = $appEmulation->startEnvironmentEmulation($storeId);
try {
// Retrieve specified view block from appropriate design package (depends on emulated store)
$paymentBlock = Mage::helper('payment')->getInfoBlock($this->getPayment())
->setIsSecureMode(true);
$paymentBlock->getMethod()->setStore($storeId);
$paymentBlockHtml = $paymentBlock->toHtml();
} catch (Exception $exception) {
// Stop store emulation process
$appEmulation->stopEnvironmentEmulation($initialEnvironmentInfo);
throw $exception;
}
// Stop store emulation process
$appEmulation->stopEnvironmentEmulation($initialEnvironmentInfo);
// Retrieve corresponding email template id and customer name
if ($this->getCustomerIsGuest()) {
$templateId = Mage::getStoreConfig(self::XML_PATH_EMAIL_GUEST_TEMPLATE, $storeId);
$customerName = $this->getBillingAddress()->getName();
} else {
$templateId = Mage::getStoreConfig(self::XML_PATH_EMAIL_TEMPLATE, $storeId);
$customerName = $this->getCustomerName();
}
$mailer = Mage::getModel('core/email_template_mailer');
$emailInfo = Mage::getModel('core/email_info');
$emailInfo->addTo($this->getCustomerEmail(), $customerName);
if ($copyTo && $copyMethod == 'bcc') {
// Add bcc to customer email
foreach ($copyTo as $email) {
$emailInfo->addBcc($email);
}
}
$mailer->addEmailInfo($emailInfo);
// Email copies are sent as separated emails if their copy method is 'copy'
if ($copyTo && $copyMethod == 'copy') {
foreach ($copyTo as $email) {
$emailInfo = Mage::getModel('core/email_info');
$emailInfo->addTo($email);
$mailer->addEmailInfo($emailInfo);
}
}
// Set all required params and send emails
$mailer->setSender(Mage::getStoreConfig(self::XML_PATH_EMAIL_IDENTITY, $storeId));
$mailer->setStoreId($storeId);
$mailer->setTemplateId($templateId);
$mailer->setTemplateParams(array(
'order' => $this,
'billing' => $this->getBillingAddress(),
'payment_html' => $paymentBlockHtml
)
);
$mailer->send();
return $this;
}
Then you just need to call this method before magento call this method itself after order placed.
put in config.xml following:
<global>
<models>
<somemodule>
<class>Vendor_Somemodule_Model</class>
</somemodule>
</models>
<events>
<checkout_type_onepage_save_order_after>
<observers>
<send_duplicate_email>
<type>singleton</type>
<class>somemodule/observer</class>
<method>saveDuplicateEmail</method>
</send_duplicate_email>
</observers>
</checkout_type_onepage_save_order_after>
</events>
</global>
and create necessary observer:
class Vendor_Somemodule_Model_Observer
{
public function saveDuplicateEmail($observer)
{
$orderId = $observer->getOrder()->getId();
$order = Mage::getModel('somemodule/order')->load($orderId);
$order->sendNewOrderEmail();
}
}
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();
}
}
}
I have a custom module with optional text fields (shown via the standard text field option in system.xml). What I'd like to do is to show 1 mandatory text field and have a button that says something like [+ Add Field]. When that button is pressed, another text field is added. I'd like to do this for up to 10 total text fields (max). Can someone help me to accomplish this or point me to a nice tutorial on how to do this?
EDIT 7/10/12 # 11:30AM
I've been working on this and so far I can get the text fields to show up. However I have a few issues...
When pressing the "Save Config" button, none of the values entered in these dynamically created textfields actually save.
Is there a way to limit how many text fields actually save?
I'm unsure of the correct way to retrieve the text field(s) data. This is mostly due to the fact that I cannot save the values...(I will add another update after #1 is fixed if I need help with this...)
My System.xml file has this in it (directly related to this)..
<labels translate="label">
<label>This is some label</label>
<comment>This is some comment.</comment>
<tooltip><![CDATA[This is some tooltip]]></tooltip>
<frontend_type>text</frontend_type>
<frontend_model>Company_Namespace/adminhtml_textfields</frontend_model>
<backend_model>adminhtml/system_config_backend_serialized</backend_model>
<sort_order>50</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>0</show_in_store>
</labels>
My custom Textfields.php (frontend_model) file contents:
<?php
class Company_Namespace_Block_Adminhtml_Textfields extends Mage_Adminhtml_Block_System_Config_Form_Field
{
protected $_addRowButtonHtml = array();
protected $_removeRowButtonHtml = array();
protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
{
$this->setElement($element);
$html = '<div id="code_label_textfields_template" style="display:none">';
$html .= $this->_getRowTemplateHtml();
$html .= '</div>';
$html .= '<ul id="code_label_textfields_container">';
if ($this->_getValue('method')) {
foreach ($this->_getValue('method') as $i=>$f) {
if ($i) {
$html .= $this->_getRowTemplateHtml($i);
}
}
}
$html .= '</ul>';
$html .= $this->_getAddRowButtonHtml('code_label_textfields_container', 'code_label_textfields_template', $this->__('Button Label Here'));
return $html;
}
protected function _getRowTemplateHtml()
{
$html = '<li>';
$html .= '<div style="margin:5px 0 10px;">';
$html .= '<input class="input-text" name="'.$this->getElement()->getName().'" value="'.$this->_getValue('price/'.$i).'" '.$this->_getDisabled().'/> ';
$html .= $this->_getRemoveRowButtonHtml();
$html .= '</div>';
$html .= '</li>';
return $html;
}
protected function _getDisabled()
{
return $this->getElement()->getDisabled() ? ' disabled' : '';
}
protected function _getValue($key)
{
return $this->getElement()->getData('value/'.$key);
}
protected function _getSelected($key, $value)
{
return $this->getElement()->getData('value/'.$key)==$value ? 'selected="selected"' : '';
}
protected function _getAddRowButtonHtml($container, $template, $title='Add')
{
if (!isset($this->_addRowButtonHtml[$container])) {
$this->_addRowButtonHtml[$container] = $this->getLayout()->createBlock('adminhtml/widget_button')
->setType('button')
->setClass('add '.$this->_getDisabled())
->setLabel($this->__($title))
//$this->__('Add')
->setOnClick("Element.insert($('".$container."'), {bottom: $('".$template."').innerHTML})")
->setDisabled($this->_getDisabled())
->toHtml();
}
return $this->_addRowButtonHtml[$container];
}
protected function _getRemoveRowButtonHtml($selector='li', $title='Remove')
{
if (!$this->_removeRowButtonHtml) {
$this->_removeRowButtonHtml = $this->getLayout()->createBlock('adminhtml/widget_button')
->setType('button')
->setClass('delete v-middle '.$this->_getDisabled())
->setLabel($this->__($title))
//$this->__('Remove')
->setOnClick("Element.remove($(this).up('".$selector."'))")
->setDisabled($this->_getDisabled())
->toHtml();
}
return $this->_removeRowButtonHtml;
}
}
What am I missing, especially for saving values???
Refer to the system.xml and the Mage_GoogleCheckout_Block_Adminhtml_Shipping_Merchant block for an example. It's a little convoluted, but it works. You can see this in the Merchant Calculated settings in Google Checkout.
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.