First off, I must apologize for my lack of knowledge on the subject. I'm still new to Magento, and with the information I've come across, I should've been able to get this working. I started off here. I'm able to get the Ajax method to make a call, but I'm getting a blank 2column-left.phtml as my output (So I'm seeing the header, left column, blank main column, and footer). I have my files set up as so:
app/local/MyModule/Featured/Block/Featured.php
<?php
class MyModule_Featured_Block_Featured extends Mage_Core_Block_Template
{
public function __construct()
{
$this->_controller = 'featured';
$this->_blockGroup = 'featured';
parent::__construct();
}
}
?>
app/local/MyModule/Featured/controllers/FeaturedController.php
<?php
class MyModule_Featured_FeaturedController extends Mage_Core_Controller_Front_Action
{
public function displayAction()
{
$this->loadLayout()->renderLayout();
}
}
?>
app/local/MyModule/Featured/etc/config.xml
<config>
<modules>
<MyModule_Featured>
<version>0.1.0</version>
</MyModule_Featured>
</modules>
<frontend>
<routers>
<featured>
<use>standard</use>
<args>
<module>MyModule_Featured</module>
<frontName>featured</frontName>
</args>
</featured>
</routers>
</frontend>
</config>
app/design/frontend/default/myLayout/layout/local.xml
<config>
<featured_featured_display>
<block type="module/block" name="root" output="toHtml" template="catalog/product/featured.phtml" />
</featured_featured_display>
</config>
Ajax Code on Homepage custom phtml:
var url = "<?php echo $this->getUrl('featured/featured/display') ;?>";
jQuery(document).ready(function() {
jQuery('#featured-products').load(url);
});
I believe the layout file's root node should be <layout> and not <config>.
P.S.
If you wanted to do without jQuery - to avoid bloat - Magento already has Prototype as standard and can do exactly the same.
var url = "<?php echo $this->getUrl('featured/featured/display') ?>";
document.observer('dom:loaded', function(){
new Ajax.Updater('featured-products', url);
});
Load layout includes the default handle normally, so my guess is that your assignment has no effect because there is a root note being loaded already. Try removing the root node first, and then add it back as your only node.
Related
I am overriding the Mage_Core_Model_Encryption in my module to override hash, getHash, and validateHash methods.
Since urls in the admin side of things use hashing as well, I am overriding the Mage_Adminhtml_Model_Url getSecretKey method so that it will use (faster) md5 hashing in the urls.
The problem I have noticed is that when I clear my cache (config only is enabled) and load the admin/index my encyptor is not registered. It takes until the third request for it to be seen.
I have debugging statements in Mycompany_Encryption_Adminhtml_Url which show that it is immediately loaded with the module. After clearing my cache, I can see my debug statements are working.
When I use the following statement:
var_dump('Class name: '.get_class(Mage::helper('core')->getEncryptor() ) );
I see returned to admin/index (upon refreshing the page) that the class name is Mage_Core_Model_Encryption, then on the third refresh it shows me my class, Mycompany_Encryption_Model_Encryption.
Why does this take three requests? I have been searching all over and haven't found/figured out the problem yet. By all appearances, I have this configured correctly ( and have experimented with a bunch of alternatives).
Can anyone help me solve this issue?
(Below are config, Url class, and Encryption class snippets). Big thanks in advance for any help.
Update, am using modman, here is my modman too:
# Modman file allows Modman to generate links in Magento.
code app/code/local/Mycompany/Encryption/
Mycompany_Encryption.xml app/etc/modules/Mycompany_Encryption.xml
Here is my config:
<config>
<modules>
<Mycompany_Encryption>
<version>0.1</version>
<depends>
<Mage_Core />
</depends>
</Mycompany_Encryption>
</modules>
<phpunit>
<suite>
<modules>
<Mycompany_Encryption />
</modules>
</suite>
</phpunit>
<global>
<helpers>
<core>
<encryption_model>
<class>Mycompany_Encryption_Model_Encryption</class>
</encryption_model>
</core>
</helpers>
<models>
<mycompany_encryption>
<class>Mycompany_Encryption_Model</class>
</mycompany_encryption>
<core>
<rewrite>
<encryption>Mycompany_Encryption_Model_Encryption</encryption>
</rewrite>
</core>
<adminhtml>
<rewrite>
<url>Mycompany_Encryption_Model_Adminhtml_Url</url>
</rewrite>
</adminhtml>
</models>
</global>
</config>
Url class:
class Mycompany_Encryption_Model_Adminhtml_Url extends Mage_Adminhtml_Model_Url
{
/**
* Generate secret key for controller and action based on form key
*
* #param string $controller Controller name
* #param string $action Action name
* #return string
*/
public function getSecretKey($controller = null, $action = null)
{
$salt = Mage::getSingleton('core/session')->getFormKey();
$p = explode('/', trim($this->getRequest()->getOriginalPathInfo(), '/'));
if (!$controller) {
var_dump('Not Controller');
$controller = !empty($p[1]) ? $p[1] : $this->getRequest()->getControllerName();
}
if (!$action) {
var_dump('Not Action');
$action = !empty($p[2]) ? $p[2] : $this->getRequest()->getActionName();
}
$secret = $controller . $action . $salt;
// Here are my debug statements showing when class/method become available.
var_dump('Method exists: '.method_exists(Mage::helper('core')->getEncryptor(), 'urlHash'));
var_dump('Class name: '.get_class(Mage::helper('core')->getEncryptor() ) );
/* This is what I want to return - but sends error 500 until instantiated. */
//return Mage::helper('core')->getEncryptor()->urlHash($secret);
return false;
}
}
Encryption class:
class Mycompany_Encryption_Model_Encryption extends Mage_Core_Model_Encryption
{
public function hash($data)
{
return password_hash($data, PASSWORD_BCRYPT);
}
public function validateHash($password, $hash)
{
return password_verify($password, $hash);
}
public function getHash($value)
{
return $this->hash($value);
}
public function urlHash($value)
{
return md5($value);
}
}
Using the n98-magerun tool, I was able to config:dump and search for the global/helpers/core node.
With the above configuration, I was getting this badly formed config dump:
$ n98-magerun config:dump |cat |grep -A1 -B2 encryption_model
<helpers>
<core>
<encryption_model>Mage_Core_Model_Encryption<class>Mycompany_Encryption_Model_Encryption</class></encryption_model>
</core>
It appears to clear up if I remove the <class> tags in my config.xml:
<helpers>
...
<core>
<!-- Class tags were surrounding my encryption_model value before -->
<encryption_model>Mycompany_Encryption_Model_Encryption</encryption_model>
</core>
...
</helpers>
With this change, I clear cache and get a better config dump:
$ n98-magerun cache:clean config
config cache cleaned
$ n98-magerun config:dump |cat |grep -A1 -B2 encryption_model
<helpers>
<core>
<encryption_model>Mycompany_Encryption_Model_Encryption</encryption_model>
</core>
Please comment with a doc link or provide info if you know why this was happening! Thanks!
I'm pretty new to Magento, and having problems trying to set a custom shipping method programmatically. I'm converting an xml from a thrid party into an order, and everything else (that I've worked on so far) is working fine. Also I'm having problems spelling "programmatically" but I won't ask for you help with that.
I set up my custom shipping method as follows:
To activate the shipping module in
app/etc/modules/Extension_Shipping.xml
<?xml version=
"1.0"?>
<config>
<modules>
<Extension_Shipping>
<active>true</active>
<codePool>local</codePool>
<depends>
<Mage_Shipping/>
</depends>
</Extension_Shipping>
</modules>
</config>
then to configure it in
app/code/local/Extension/Shipping/etc/config.xml
<?xml version=
"1.0" ?>
<config>
<modules>
<Extension_Shipping>
<version>0.1.0</version>
</Extension_Shipping>
</modules>
<global>
<models>
<extension_shipping>
<class>Extension_Shipping_Model</class>
</extension_shipping>
</models>
</global>
<default>
<carriers>
<extension_myrate>
<active>1</active>
<model>extension_shipping/carrier_myrate</model>
<title>Extension Shipping</title>
<name>Default Rate</name>
</extension_myrate>
</carriers>
</default>
</config>
then to add the class in
app/code/local/Extension/Shipping/Model/Carrier/MyRate.php
<?php
class Extension_Shipping_Model_Carrier_MyRate
extends Mage_Shipping_Model_Carrier_Abstract
implements Mage_Shipping_Model_Carrier_Interface
{
protected $_code = 'extension_myrate';
protected $_isFixed = true;
public function collectRates(Mage_Shipping_Model_Rate_Request
$request)
{
if (!$this->getConfigFlag('active')) {
return false;
}
$result = Mage::getModel('shipping/rate_result');
$method = Mage::getModel('shipping/rate_result_method');
$method->setCarrier('extension_myrate');
$method->setCarrierTitle($this->getConfigData('title'));
$method->setMethod('extension_myrate');
$method->setMethodTitle($this->getConfigData('name'));
$method->setPrice(5);
$method->setCost(2);
$result->append($method);
return $result;
}
public function getAllowedMethods()
{
return array('extension_myrate' => $this->getConfigData('name'));
}
}
Basically I followed http://www.magentotricks.com/creating-a-customer-magento-shipping-method/
I thought it all worked fine, as the shipping method now shows up in the checkout screen, and can be set both by customers or in the admin "create new order." However, I'm not able to set it programmatically.
In my controller I'm trying to set the shipping method using the code
$shippingAddress = $quote->getShippingAddress()->addData($addressData);
$shippingAddress->setCollectShippingRates(true)->collectShippingRates()
->setShippingMethod('extension_myrate')
->setPaymentMethod('checkmo');
To add to my confusion, it worked once. but only once out of quite a few test orders. changing the "setShippingMethod" to "freeshipping_freeshipping" or "flatrate_flatrate" makes it update the shipping to those correctly. because of that and because I'm new and still having problems with the file structure, I'm guessing my problem is with setShippingMethod('extension_myrate') but I'm not entirely sure. Any advice would be helpful and appreciated.
Im trying to call an Observer after the order has been created, and AFTER payment has been captured.
So far I've tried;
checkout_submit_all_after,
sales_order_payment_place_end,
sales_order_place_after,
sales_order_payment_pay,
sales_order_payment_capture,
sales_order_payment_transaction_save_after
Just to name the main ones.
I've also logged all Event Dispaches inside dispatchEvent() but found nothing that stands out and is only fired when i need it.
the issue i'm having is that the status of the order is always ether 'Payment Pending' or something that predated this; meaning that i don't know whether the order will fail or succeed.
My aim, is to fire a function only on successful orders.
thanks.
after much more testing i found the following Observer to do the trick;
checkout_onepage_controller_success_action
This returns just the order id, so;
$order_id = $observer->getData('order_ids');
$order = Mage::getModel('sales/order')->load($order_id);
and you see that the order status is 'processing' and the payment is aproved (or not).
1 ) here is custom config.xml for call observer file
<?xml version="1.0"?>
<config>
<modules>
<Namespace_Modulename>
<version>0.1.0</version>
</Namespace_Modulename>
</modules>
<frontend>
<events>
<checkout_submit_all_after>
<observers>
<Namespace_Modulename_Customevent>
<type>singleton</type>
<class>Namespace_Modulename_Model_Observer</class>
<method>customFunction</method>
</Namespace_Modulename_Customevent>
</observers>
</checkout_submit_all_after>
</events>
</frontend>
</config>
2 ) create observer.php file inside your module/Model directory and paste this code
<?php
class Namespace_Modulename_Model_Observer
{
public function customFunction(Varien_Event_Observer $observer)
{
$order = $observer->getEvent()->getOrder();
//here you can add your custom code
}
}
please try this.. sure it will help you !
I have also tried all event but didn't get success. Then I moved to override Mage OnePageController and called my custom function. Below is the code to override onestep checkout.
app\etc\modules\Namespace_Module.xml
<Namespace_Checkout>
<active>true</active>
<codePool>local</codePool>
</Namespace_Checkout>
app\code\local\Namespace\Checkout\etc\config.xml
<?xml version="1.0"?>
<config>
<modules>
<Namespace_Checkout>
<version>0.1.0</version>
</Namespace_Checkout>
</modules>
<frontend>
<routers>
<checkout>
<args>
<modules>
<Namespace_Checkout before="Mage_OneStepCheckout">Namespace_Checkout</Namespace_Checkout>
</modules>
</args>
</checkout>
</routers>
</frontend>
</config>
app\code\local\Namespace\Checkout\controllers\OnepageController.php
<?php
require_once 'Mage/Checkout/controllers/OnepageController.php';
class Namespace_Checkout_OnepageController extends Mage_Checkout_OnepageController{
public function successAction(){
$session = $this->getOnepage()->getCheckout();
if (!$session->getLastSuccessQuoteId()) {
$this->_redirect('checkout/cart');
return;
}
$lastQuoteId = $session->getLastQuoteId();
$lastOrderId = $session->getLastOrderId();
$lastRecurringProfiles = $session->getLastRecurringProfileIds();
if (!$lastQuoteId || (!$lastOrderId && empty($lastRecurringProfiles))) {
$this->_redirect('checkout/cart');
return;
}
$this->customFunction(); // Custom function to call
$session->clear();
$this->loadLayout();
$this->_initLayoutMessages('checkout/session');
Mage::dispatchEvent('checkout_onepage_controller_success_action', array('order_ids' => array($lastOrderId)));
$this->renderLayout();
}
function customFunction(){
// This function is calling before clearing order session
//Here you can put all your custom code
}
}
?>
In the above controller, I have added customFunction() wher you can put your custom code.
Hope it will help you!
I'm trying to create my first Magento extension and I'm stuck at the first step already.
When adding {{block type="rick_printer/print" text="Hello world"}} to a CMS page or block, I want "Hello world" to be displayed.
Unfortunately nothing happens. Here's my code:
app\code\local\Rick\Printer\etc\config.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<Rick_Printer>
<version>0.0.1</version>
</Rick_Printer>
</modules>
<global>
<blocks>
<rick_printer>
<class>Rick_Printer_Block_Print</class>
</rick_printer>
</blocks>
</global>
</config>
app\etc\modules\Rick_Printer.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<Rick_Printer>
<active>true</active>
<codePool>local</codePool>
</Rick_Printer>
</modules>
</config>
app\code\local\Rick\Printer\Block\Print.php
class Rick_Printer_Block_Print extends Mage_Core_Block_Abstract
{
protected function _construct()
{
$this->setTemplate('rick/printer/view.phtml');
parent::_construct();
}
public function printIt()
{
$text = $this->getText();
if (!$text) {
$msg = "Please provide a text!";
echo $msg;
return array();
}
return $text;
}
}
app\design\frontend\default\default\template\rick\printer\print.phtml
<?php
$text = $this->spinIt();
echo $text;
?>
I know the code is ugly and I'm probably doing it all wrong.
Any help is highly appreciated!
Thanks
Update: After applying the fix from Vinai's answer my app\code\local\Rick\Printer\etc\config.xml looks now like this:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<Rick_Printer>
<version>0.0.1</version>
</Rick_Printer>
</modules>
<global>
<blocks>
<rick_printer>
<class>Rick_Printer_Block</class>
</rick_printer>
</blocks>
</global>
</config>
and I'm getting the following error message when accessing the CMS page (which doesn't show):
class Rick_Printer_Block_Print extends Mage_Core_Block_Abstract
{
protected function _construct()
{
$this->setTemplate('rick/printer/view.phtml');
parent::_construct();
}
public function printIt()
{
$text = $this->getText();
if (!$text) {
$msg = "Please provide a text!";
echo $msg; return array();
}
return $text;
}
}
Fatal error: Class 'Rick_Printer_Block_Print' not found in /home/www/xyz/htdocs/app/code/core/Mage/Core/Model/Layout.php on line 491
First, your block class prefix is wrong. Despite the node name being <class>, what you are actually specifying is a class prefix.
Another way to look at it is that this node declares the directory, in which the blocks for the module are located.
The correct way is
<!-- language: xml -->
<global>
<blocks>
<rick_printer>
<class>Rick_Printer_Block</class>
</rick_printer>
</blocks>
</global>
Second, in your template you are calling $this->spinIt(); instead of $this->printIt();.
Just a typo...
Otherwise the code looks okay.
UPDATE
The error message indicates a file system path to class name mismatch. Check the casing and for typos.
Also, since you want your block to render a template, you want to extend Rick_Printer_Block_Print from Mage_Core_Block_Template instead of the _Abstract block class.
I have created a module to add a discount code to the customers cart if they are either a new customer or have not ordered in the last 24 hours, it is for a company supplying lunch for their employees and they receive a subsidiary each day to use of £3.00.
So I have:
app/code/local/Brave/Subsidary/controllers/CartControlller.php
<?php
require_once Mage::getModuleDir('controllers', 'Mage_Checkout').DS.'CartController.php';
class Brave_Subsidary_CartController extends Mage_Checkout_CartController {
const DISCOUNTCODE = 'BCOMSTAFF';
public function addAction() {
parent::addAction();
$this->autoApplySubsidaryDiscount();
}
public function indexAction() {
parent::addAction();
$this->autoApplySubsidaryDiscount();
}
public function autoApplySubsidaryDiscount() {
$customer = Mage::getSingleton('customer/session')->getCustomer();
$orders = Mage::getResourceModel('sales/order_collection')
->addFieldToSelect('*')
->addFieldToFilter('customer_id', $customer->getId());
if(!$orders->getSize()) {
// New Customer...
$this->applyDiscountCoupon();
} else {
// Check last order date
$orderCollection = Mage::getModel('sales/order')->getCollection()
->addFilter('customer_id', $customer->getId())
->setOrder('created_at', Varien_Data_Collection_Db::SORT_ORDER_DESC);
$newestOrder = $orderCollection->getFirstItem();
$dateToday = Mage::getModel('core/date')->timestamp(time());
$lastOrderDate = Mage::getModel('core/date')->timestamp(strtotime($newestOrder->getData('created_at')));
// only apply if last order was more than 24hrs ago..
if( $dateToday > $lastOrderDate ) {
$this->applyDiscountCoupon();
}
}
}
public function applyDiscountCoupon() {
Mage::getSingleton("checkout/session")->setData("coupon_code",self::DISCOUNTCODE);
Mage::getSingleton('checkout/cart')->getQuote()->setCouponCode(self::DISCOUNTCODE)->save();
}
}
?>
app/code/local/Brave/Subsidary/etc/config.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<Brave_Subsidary>
<version>0.1.0</version>
</Brave_Subsidary>
</modules>
<frontend>
<routers>
<checkout>
<use>standard</use>
<args>
<modules>
<Brave_Subsidary before="Mage_Checkout">Brave_Subsidary</Brave_Subsidary>
</modules>
</args>
</checkout>
</routers>
</frontend>
</config>
Then my module file:
app/etc/modules/Brave_Subsidary.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<Brave_Subsidary>
<active>true</active>
<codePool>local</codePool>
</Brave_Subsidary>
</modules>
</config>
The problem is that I am getting a redirect loop on the cart page or from adding an item to the cart, this is probably a real simple issue but trying to Google anything related this is a real needle in a haystack!
The error FireFox tells me is:
Firefox has detected that the server is redirecting the request for this address in a way that will never complete.
The problem is:
You are calling parent:addAction() which redirects back to indexAction which is your indexAction which calles parent:addAction again...thus the redirect loop.
Bad code:
public function indexAction() {
parent::addAction();
$this->autoApplySubsidaryDiscount();
}
You must not call addAction in your above seen custom indexAction!
Solution:
Remove
public function indexAction() {
parent::addAction();
$this->autoApplySubsidaryDiscount();
}
Change
public function addAction() {
$this->autoApplySubsidaryDiscount();
parent::addAction();
}
Done.
But better instead rewriting the controller would be to use an observer...but thats another thread i guess :)