I am trying to figure out what the following function is checking:
<?php if ($this->getCanViewOrder() && $this->getCanPrintOrder()) :?>
<?php echo $this->__('<strong>Click here to print</strong> an invoice or a copy of your order confirmation.', $this->getPrintUrl()) ?>
In the success.phtml file in Magento the "Click here to print" link doesn't show anymore on the thank you page. Where is this function located?
Update: I revised this answer greatly after doing a bit more research.
For the record, it looks like getCanPrintOrder is one of Magento's magic methods for getting object data. You'd set its value with setCanPrintOrder, and if you haven't called that before, getCanPrintOrder will just return null. You could also set it by calling setData('can_print_order').
It looks like the only place it's being set is in the Onepage checkout success block, Mage_Checkout_Block_Onepage_Success, in the _prepareLastOrder method:
protected function _prepareLastOrder()
{
$orderId = Mage::getSingleton('checkout/session')->getLastOrderId();
if ($orderId) {
$order = Mage::getModel('sales/order')->load($orderId);
if ($order->getId()) {
$isVisible = !in_array($order->getState(),
Mage::getSingleton('sales/order_config')->getInvisibleOnFrontStates());
$this->addData(array(
'is_order_visible' => $isVisible,
'view_order_id' => $this->getUrl('sales/order/view/', array('order_id' => $orderId)),
'print_url' => $this->getUrl('sales/order/print', array('order_id'=> $orderId)),
'can_print_order' => $isVisible,
'can_view_order' => Mage::getSingleton('customer/session')->isLoggedIn() && $isVisible,
'order_id' => $order->getIncrementId(),
));
}
}
}
Which is called from the _beforeToHtml method, which would be called when that page is rendered.
Pulling the string a bit further, we see that the can_print_order is determined by the $isVisible variable, and that's set by this line:
$isVisible = !in_array($order->getState(),
Mage::getSingleton('sales/order_config')->getInvisibleOnFrontStates());
It's checking if the order state is one of the states that are visible on front. These are ultimately set in the config.xml file for the core Magento sales module.
<config>
<global>
<sales>
<order>
<states>
<new translate="label">
<label>New</label>
<statuses>
<pending default="1"/>
</statuses>
<visible_on_front>1</visible_on_front>
</new>
...
</states>
</order>
</sales>
</global>
</config>
All of the states are visible_on_front by default, so unless you've changed them, or something has overridden them, that shouldn't be your problem. I'd double-check this by dumping the value of getCanPrintOrder in success.phtml.
A hacky workaround would be overriding the template file and adding
$this->setCanPrintOrder(true);
$this->setCanViewOrder(true);
Anywhere above the if condition. Or just removing the checks altogether.
Related
I am working in a Magento site, Requirement is when user comes to the site user should be redirect to login page,
Without visit any product page.
After register he will be able to view the products,
I have already tried but not getting any solution yet.
Anyone can help me on this?
You can simply use free available extension on magento connect. I used this extension for my store http://www.magentocommerce.com/magento-connect/login-check.html
It is free and doing job nice.
You can try the following approach as described here. Since posting single link answers is not recommended, here is what you need to do.
You need to create an observer for the event controller_action_predispatch for frontend. You can do that in a custom module. Let's call that module Easylife_Restrict.
You will need the following files:
app/etc/modules/Easylife_Restrict.xml - the declaration file.
<?xml version="1.0"?>
<config>
<modules>
<Easylife_Restrict>
<codePool>local</codePool>
<active>true</active>
<depends>
<Mage_Customer />
</depends>
</Easylife_Restrict>
</modules>
</config>
app/code/local/Easylife/Restrict/etc/config.xml - the configuration file
<?xml version="1.0"?>
<config>
<modules>
<Easylife_Restrict>
<version>1.0.0</version>
</Easylife_Restrict>
</modules>
<global>
<models>
<easylife_restrict>
<class>Easylife_Restrict_Model</class>
</easylife_restrict>
</models>
</global>
<frontend>
<events>
<controller_action_predispatch>
<observers>
<easylife_restrict>
<class>easylife_restrict/observer</class>
<method>redirectNotLogged</method>
</easylife_restrict>
</observers>
</controller_action_predispatch>
</events>
</frontend>
</config>
app/code/local/Easylife/Restrict/Model/Observer.php - the module observer - this is where the magic happens:
<?php
class Easylife_Restrict_Model_Observer{
public function redirectNotLogged(Varien_Event_Observer $observer)
{
//get the current request action
$action = strtolower(Mage::app()->getRequest()->getActionName());
//get the current request controller
$controller = strtolower(Mage::app()->getRequest()->getControllerName());
//a list of allowed actions for the not logged in user
$openActions = array(
'create',
'createpost',
'login',
'loginpost',
'logoutsuccess',
'forgotpassword',
'forgotpasswordpost',
'resetpassword',
'resetpasswordpost',
'confirm',
'confirmation'
);
//if the controller is the customer account controller and the action is allowed for everyone just do nothing.
if ($controller == 'account' && in_array($action, $openActions)) {
return $this; //if in allowed actions do nothing.
}
//if the user is not logged in redirect to the login page
if(! Mage::helper('customer')->isLoggedIn()){
Mage::app()->getFrontController()->getResponse()->setRedirect(Mage::getUrl('customer/account/login'));
}
}
}
Clear the cache and give it a try.
Please use this
Step 1: Go to Admin => System => Configuration => Customer Configuration => Login Options => "Redirect Customer to Account Dashboard after Logging in" set it "No".
Step 2: If you're using a module page then you've the controller Action method like:
public function indexAction()
{
// use here to restrict the page //
if(!Mage::helper('customer')->isLoggedIn()){
Mage::getSingleton('customer/session')->setBeforeAuthUrl('Restricted Page Url');
$this->_redirect('customer/account/login');
}
// End your addition //
$this->loadLayout();
$this->renderLayout();
}
you can use one of this code to redirect:
Mage::getSingleton('customer/session')->setBeforeAuthUrl('Restricted Page Url');
$this->_redirect('customer/account/login');
OR
$this->_redirect('customer/account/login/referer/'.Mage::helper('core')->urlEncode('Restricted Page Url'));
Step 3: (optional) If you're using a cms page then follow this step:
In your admin CMS section include a phtml page and write the below code at the top of the page:
if(!Mage::helper('customer')->isLoggedIn()){
Mage::getSingleton('customer/session')->setBeforeAuthUrl('Restricted Page Url');
$this->_redirect('customer/account/login');
}
>> Now if you want to use the login url inside a page with referer url follow this:
<?php $referer = Mage::helper('core')->urlEncode(Mage::helper('core/url')->getCurrentUrl()); ?>
Login
I think it will solve your problem
Hi I hope you can help me with this. I'm new in Magento and I'm trying to implement the same functionality discussed in this thread
Magento hide navigation menu item from guest.
The only thing I haven't figured out yet is how to create a navigation block in the first place or create custom links in the top menu.
I have been trying to follow the method described in the link below but I'm not sure which config.xml and observer file I should modify in order to get this work
http://inchoo.net/ecommerce/adding-links-to-the-top-menu-in-magento/comment-page-1/#comment-71252
Could somebody please provides me with some guidance?
Your question is not clear. I assumes that, you want to add new menu in header and you want to show it only when user is logged in. Based on that assumption, let us start to create a custom module. (Tutorial that you point out is referencing your own module and not to any other existing module). Let us create a module with name Mysite_Addmenu
First you need to configure your module. For that create a file in
Location : app/code/core/local/Mysite/Addmenu/etc/config.xml
<config>
<modules>
<Mysite_Addmenu>
<version>0.1.0</version>
</Mysite_Addmenu>
</modules>
<frontend>
<events>
<page_block_html_topmenu_gethtml_before>
<observers>
<add_top_menu>
<type>singleton</type>
<class>addmenu/observer</class>
<method>addToTopmenu</method>
</add_top_menu>
</observers>
</page_block_html_topmenu_gethtml_before>
</events>
</frontend>
<global>
<models>
<addmenu>
<class>Mysite_Addmenu_Model</class>
</addmenu>
</models>
</global>
</config>
As you can see it has two section. One section defines the observer part and other section defines its model part. In model, you are going to define your observer.
Now let us make magento knows about our module.For this you need to add this file in the given location
Location:app/etc/modules/Mysite_Addmenu.xml
<config>
<modules>
<Mysite_Addmenu>
<active>true</active>
<codePool>local</codePool>
</Mysite_Addmenu>
</modules>
</config>
Now its time to define our observer.Let us do that
Location : app/code/local/Mysite/Addmenu/Model/Observer.php
<?php
class Mysite_Addmenu_Model_Observer
{
public function addToTopmenu(Varien_Event_Observer $observer)
{
if(Mage::getSingleton('customer/session')->isLoggedIn())
{
$menu = $observer->getMenu();
$tree = $menu->getTree();
$node = new Varien_Data_Tree_Node(array(
'name' => 'Newmenu',
'id' => 'newmenu',
'url' => Mage::getUrl().'newmenu', // point somewhere
), 'id', $tree, $menu);
$menu->addChild($node);
// Children menu items
$collection = Mage::getResourceModel('catalog/category_collection')
->setStore(Mage::app()->getStore())
->addIsActiveFilter()
->addNameToResult()
->setPageSize(3);
foreach ($collection as $category) {
$tree = $node->getTree();
$data = array(
'name' => $category->getName(),
'id' => 'category-node-'.$category->getId(),
'url' => $category->getUrl(),
);
$subNode = new Varien_Data_Tree_Node($data, 'id', $tree, $node);
$node->addChild($subNode);
}
}
}
}
What observer does : Observer checks whether a user is exist or not. If not, it will not create a menu. If a user is already logged in, then the menu will appear.
I have used same code in referenced tutorial. You can make your own changes to submenu part. Display it as you desire. Hope it will help you.
This is what I understand by your question here Magento hide navigation menu item from guest.
so you need to follow the steps
step 1: Need to create observer by using event page_block_html_topmenu_gethtml_before
you will find lots of article to create an observer as you added
http://inchoo.net/ecommerce/adding-links-to-the-top-menu-in-magento/comment-page-1/
and update the code with below
$subNode = new Varien_Data_Tree_Node($data, 'id', $tree, $node);
// here added the condition to check the customer is logged in or not then only show the menu
if(Mage::getSingleton('customer/session')->isLoggedIn())
{
$node->addChild($subNode);
}
I'm writing a new shipping method for a customer; I've got the shipping calculations going great, and they appear in the 'shipping method' step - however, I want to:
a) Force the 'Shipping Information' tab to open after the user hits the billing.save() triggered by the continue button in the first (billing) tab, even if they select ship to billing address; and
b) Add options for 'receipted delivery', 'transport assurance' and 'tail-truck pickup' in the shipping information tab - which will be taken in to account when re-calculating the shipping quote.
In part b) I assume I override the shipping.phtml template with an xml config file in /layout, and then look for those added post fields in the collectRates() method.
Thanks in advance!
As for part a) you will need to overwrite the controller Mage_Checkout_OnepageController. To do so create your own module (I assume you know how to do this) and in the app/code/local/YourModule/etc/config.xml you should have this part:
<config>
...
<frontend>
<routers>
<checkout>
<args>
<modules>
<YourModule_Checkout before="Mage_Checkout">YourModule_Checkout</YourModule_Checkout>
</modules>
</args>
</checkout>
</routers>
</frontend>
</config>
then in app/code/local/YourModule/controllers/OnepageController.php you want to overwrite the behavior, so when you click the save billing button, you will always land on the shipping page.
include_once("Mage/Checkout/controllers/OnepageController.php");
class YourModule_Checkout_OnepageController extends Mage_Checkout_OnepageController
{
public function saveBillingAction()
{
if ($this->_expireAjax()) {
return;
}
if ($this->getRequest()->isPost()) {
$data = $this->getRequest()->getPost('billing', array());
$customerAddressId = $this->getRequest()->getPost('billing_address_id', false);
if (isset($data['email'])) {
$data['email'] = trim($data['email']);
}
$result = $this->getOnepage()->saveBilling($data, $customerAddressId);
if (!isset($result['error'])) {
/* check quote for virtual */
if ($this->getOnepage()->getQuote()->isVirtual()) {
$result['goto_section'] = 'payment';
$result['update_section'] = array(
'name' => 'payment-method',
'html' => $this->_getPaymentMethodsHtml()
);
} else { // Removed elseif block here which usually skips over shipping if you selected to use the same address as in billing
$result['goto_section'] = 'shipping';
}
}
$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
}
}
}
Then for part b) you have two options. Either as you pointed out you use the XML layout system to set a different template for the shipping.phtml:
<checkout_onepage_index>
<reference name="checkout.onepage.shipping">
<action method="setTemplate">
<new>my_shipping.phtml</new>
</action>
</reference>
</checkout_onepage_index>
or even easier, you overwritte the shipping.phtml template using your custom design folder.
To evaluate your custom data, the model Mage_Checkout_Model_Type_Onepage processes the data in the saveShipping() method, so I guess this would be a good point to look for implementing your custom logic.
Hi
I have assigned 20 products to a category called Phone, I would like to create a module to retrieve these products and displayed as a list format. Could someone tell me how to do this?
thanks
To create a widget (which you can insert via the cms) that uses a category to do something, begin by creating a standard module structure with:
/Block
/etc
/Helper
/Model
Note that in my code samples and filenames below you will need to replace [Namespace], [Module], and [module] with the appropriate namespace and module that you want to use. Case is important!
Begin by creating app/code/local/[Namespace]/[Module]/etc/config.xml
<?xml version="1.0"?>
<config>
<modules>
<[Namespace]_[Module]>
<version>0.0.1</version>
</[Namespace]_[Module]>
</modules>
<global>
<helpers>
<[module]>
<class>[Namespace]_[Module]_Helper</class>
</[module]>
</helpers>
<blocks>
<[module]>
<class>[Namespace]_[Module]_Block</class>
</[module]>
</blocks>
<models>
<[module]>
<class>[Namespace]_[Module]_Model</class>
</[module]>
</models>
</global>
</config>
Then create a app/code/local/[Namespace]/[Module]/etc/widget.xml This widget includes a setting called "selected_category"
<?xml version="1.0"?>
<widgets>
<[module]_category type="[module]/category">
<name>[Module]: Category</name>
<description type="desc">Adds a [module] for a category.</description>
<parameters>
<selected_category>
<label>Categories</label>
<visible>1</visible>
<required>1</required>
<type>select</type>
<source_model>[module]/catopt</source_model>
</selected_category>
</parameters>
</[module]_category>
</widgets>
Then the obligatory Helper file in app/code/local/[Namespace]/[Module]/Helper/Data.php
<?php
class [Namespace]_[Module]_Helper_Data extends Mage_Core_Helper_Abstract
{
}
Then a model to allow the user to select the category in the widget dialog box. This goes in app/code/local/[Namespace]/[Module]/Model/Catopt.php
<?php
class [Namespace]_[Module]_Model_Catopt
{
public function toOptionArray()
{
$category = Mage::getModel('catalog/category');
$tree = $category->getTreeModel();
$tree->load();
$ids = $tree->getCollection()->getAllIds();
$arr = array();
if ($ids){
foreach ($ids as $id){
$cat = Mage::getModel('catalog/category');
$cat->load($id);
array_push($arr, array('value' => $id, 'label' => $cat->getName().' ('.$cat->getProductCount().')'));
}
}
uasort($arr, array($this, 'labelsort'));
return $arr;
}
function labelsort($a, $b){
if ( $a['label'] == $b['label'] )
return 0;
else if ( $a['label'] < $b['label'] )
return -1;
else
return 1;
}
}
Finally on the module side of things a block which goes in app/code/local/[Namespace]/[Module]/Block/Category.php This block is using a custom .phtml file for it's display but you can change that to use anything else you might need to show by changing the type of block and input to setTemplate.
<?php
class [Namespace]_[Module]_Block_Category
extends Mage_Core_Block_Template
implements Mage_Widget_Block_Interface
{
/**
* A model to serialize attributes
* #var Varien_Object
*/
protected $_serializer = null;
/**
* Initialization
*/
protected function _construct()
{
$this->_serializer = new Varien_Object();
$this->setTemplate('[module]/[module].phtml');
parent::_construct();
}
public function getCategory(){
return $this->getData('selected_category');
}
}
Don't forget to add a module install file under /app/etc/modules/[Namespace]_[Module].xml like this
<?xml version="1.0"?>
<config>
<modules>
<[Namespace]_[Module]>
<active>true</active>
<codePool>local</codePool>
<depends>
<Mage_Cms />
</depends>
</[Namespace]_[Module]>
</modules>
</config>
Lastly you need to create a template file to display the block content. This will go under /app/design/frontend/default/default/template/[module]/[module].phtml
This .phtml file can use $this->getCategory() to get the category and go from there. You can easily customize the block included in these samples to display the default magento product list grids instead of using a custom .phtml file.
No need to create a module. just place this in a block in your layout: It will show all the products linked to the specified category (id=XXX).
<!-- Show all products linked to this category -->
<block type="catalog/product_list" name="best_sellers" template="catalog/product/list.phtml">
<action method="setCategoryId">
<category_id>XXX</category_id>
</action>
</block>
Update:
You can create a module that overide the "Mage_Catalog_Block_Product_List", and add a method to limit a certain number of products.
1- Create "app/code/local/[Namespace]/Catalog/etc/config.xml" and put this in it:
<config>
<modules>
<[Namespace]_Catalog>
<version>0.1.0</version>
</[Namespace]_Catalog>
</modules>
<global>
<blocks>
<catalog>
<rewrite>
<product_list>[Namespace]_Catalog_Block_Product_List</product_list>
</rewrite>
</catalog>
</blocks>
</global>
</config>
2- Override the Block by creating the class: "app/code/local/[Namespace]/Catalog/Block/Product/List.php"
class [Namespace]_Catalog_Block_Product_List extends Mage_Catalog_Block_Product_List
{
/**
* Default number of product to show.
*
* #var int default = 5
*/
private $_productCount = 5;
/**
* Initialize the number of product to show.
*
* #param int $count
* #return Mage_Catalog_Block_Product_List
*/
public function setProductCount($count)
{
$this->_productCount = intval($count);
return $this;
}
/**
* Get the number of product to show.
*
* #return int
*/
public function getProductCount()
{
return $this->_productCount;
}
}
3- Overide your theme to add the product limit feature:
copy "app/design/frontend/default/default/template/catalog/product/list.phtml" to "app/design/frontend/default/[your_theme]/template/catalog/product/list.phtml"
// Insert between the foreachs and <li> for the list mode and grid mode
<?php if($_iterator < $this->getProductCount()) : ?>
...
// Insert between the foreachs and <li> for the list mode and grid mode
<?php endif; ?>
4- In the home page content tab, add this line where you want it:
// category_id = Procucts linked to this category
// product_count = Maximum number of product
{{block type="catalog/product_list" category_id="7" product_count="3" template="catalog/product/list.phtml"}}
Hope this help someone.
Thanks for the informative post. For those of you who are not so fluent in PHP but landed on this page because you were looking for a solution to display a product name list from a given category I managed to find a solution by simply modifying someone else's template file. For this solution I found the best suited extension was:
http://www.cubewebsites.com/blog/magento/extensions/freebie-magento-featured-products-widget-version-2/
(find the latest version on github: https://github.com/cubewebsites/Cube-Category-Featured-Products/tags).
After logging in and out and clearing the cache I was able to insert the widget into a static block and modify the .phtml file used to produce the custom view that I wanted.
The widget looked like this when inserted:
{{widget type="categoryfeatured/list" template="categoryfeatured/block.phtml" categories="118" num_products="10" products_per_row="1" product_type="all"}}.
I simply opened
app/design/frontend/base/default/template/categoryfeatured/block.phtml
copied it's contents and created a new .phtml file called category_product_listing.phtml
and then pointed the widget instance to the new .phtml file as follows:
{{widget type="categoryfeatured/list" template="categoryfeatured/category_product_listing.phtml" categories="118" num_products="10" products_per_row="1" product_type="all"}}.
I then went through this .phtml file with my basic understanding of PHP and removed all items like images, add to cart buttons, reviews, etc. until I was left with just the basic linked product title as well as the category title left intact.
I hope this helps someone as I spent hours trying to figure this out.
As stated in the subject, I am trying to add a date field with its date picker in the System > Configuration area for a custom module (thus using etc/system.xml).
I tried to get inspiration from the thread below :
Magento - Add a button to system.xml with method attached to it
but no success.
I'm sure this is a question of creating the right block or method to create a custom html field but I cannot read thru the Magento Matrix :)
I am stuck at the step where I need to code the class (Datefield.php):
<?php
class Namespace_Module_Block_Datefield extends Mage_Adminhtml_Block_System_Config_Form_Field {
protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element) {
// ----> Am I wrong in calling ..._Abstract? Should I call Varien_Data_Form_Element_Date? I've tried but no success either...
$this->setElement($element);
$html = // ------------------> what to put here? Call a block or some other method?
->setFormat('d-m-Y')
->setLabel($this->__('Choose date'))
->toHtml();
return $html;
}
}
?>
Do you have a trick on how to do that ?
Thanks a lot.
Hervé
EDIT 02/19/2014: added validation
I found what I think is a more elegant way of doing this. Actually, satrun77 methods is ok but we must place a file in Varien/Data/Form/Element/ which can be overwritten if someone else working on the project unluckily uses the same file/class name. Moreover, this method places the file in the module directories which is, I think, better than distributing files all over the directory tree.
In system.xml:
<?xml version="1.0" encoding="UTF-8"?>
<config>
....
<fields>
...
<run translate="label">
<label>Date</label>
<frontend_type>text</frontend_type> <!-- Use text instead of "myDateSelection" -->
<frontend_model>module/adminhtml_system_config_date</frontend_model> <!-- Call a module specific renderer model -->
<sort_order>20</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<validate>required-entry</validate> <!-- Optional -->
<show_in_store>1</show_in_store>
</run>
</fields>
...
</config>
Create a new file :
app/code/[local, community]/Namespace/Module/Block/Adminhtml/System/Config/Date
with the content below:
class Namespace_Module_Block_Adminhtml_System_Config_Date extends Mage_Adminhtml_Block_System_Config_Form_Field
{
protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
{
$date = new Varien_Data_Form_Element_Date;
$format = Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT);
$data = array(
'name' => $element->getName(),
'html_id' => $element->getId(),
'image' => $this->getSkinUrl('images/grid-cal.gif'),
);
$date->setData($data);
$date->setValue($element->getValue(), $format);
$date->setFormat(Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT));
$date->setClass($element->getFieldConfig()->validate->asArray());
$date->setForm($element->getForm());
return $date->getElementHtml();
}
}
Create class file in app/code/local/Varien/Data/Form/Element/. Make sure the file name is prefixed with something that identify your module (this is just to differentiate your custom code from Magneto core files)
class Varien_Data_Form_Element_MyDateSelection extends Varien_Data_Form_Element_Date
{
public function getElementHtml()
{
// define image url
$this->setImage(Mage::getDesign()->getSkinUrl('images/grid-cal.gif'));
// define date format
$this->setFormat('yyyy-MM-dd');
return parent::getElementHtml();
}
}
Inside your module system.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
....
<fields>
...
<run translate="label">
<label>Run now</label>
<frontend_type>myDateSelection</frontend_type>
<sort_order>20</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</run>
</fields>
...
</config>
Placing custom code inside lib/ folder or app/Mage/Core/ folder is not the best way to create custom code for Magento. These folders are for core code and not custom code.
This approach creates the least amount of code and does not change any of the core files. So, there isn't any harm from having extra file inside the lib/ folder. But you need to remember that you have extra file for your module in the lib/.
Hope this helps