Magento, Extending Order Grid using XML markup method, select options issue - magento

I am looking for some an example of how to populate a select option header in Magento order grid. The following is creating the new column rendering the data and outputting a select menu in the column header. The issue is the options are not being created in the select menu.
<layout>
<!-- main layout definition that adds the column -->
<add_order_grid_column_handle>
<reference name="sales_order.grid">
<action method="addColumnAfter">
<columnId>customer_country_id</columnId>
<arguments module="ordermanager" translate="header">
<header>Shipping Country</header>
<index>customer_country_id</index>
<type>options</type>
<sortable>true</sortable>
<options>Flipmedia_AddShippingCountryColumn_Adminhtml_Block_Widget_Grid_Column_Renderer_Country</options>
<renderer>Flipmedia_AddShippingCountryColumn_Adminhtml_Block_Widget_Grid_Column_Renderer_Country</renderer>
</arguments>
<after>status</after>
</action>
</reference>
</add_order_grid_column_handle>
<!-- order grid action -->
<adminhtml_sales_order_grid>
<!-- apply the layout handle defined above -->
<update handle="add_order_grid_column_handle" />
</adminhtml_sales_order_grid>
<!-- order grid view action -->
<adminhtml_sales_order_index>
<!-- apply the layout handle defined above -->
<update handle="add_order_grid_column_handle" />
</adminhtml_sales_order_index>
</layout>
class Flipmedia_AddShippingCountryColumn_Adminhtml_Block_Widget_Grid_Column_Renderer_Country extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract {
private static $_countryList = array();
public function options(Varien_Object $row) {
if (count(self::$_countryList) == 0) {
$countries = Mage::getResourceModel('directory/country_collection')
->loadData()
->toOptionArray(false);
foreach ($countries as $country) {
self::$_countryList[$country['value']] = $country['label'];
}
}
return self::$_countryList;
}
public function render(Varien_Object $row){
$value = $this->_getValue($row);
$_countryList = $this->options();
return isset($_countryList[$value]) ? $_countryList[$value] : false;
}
}

I believe the issue is with your <options> element, if you override the sales order grid by rewriting it, you have to specify a static function for the options. I've had a look around and it looks like you need to change the way you invoke this.
Instead of using the <options> element, can you try a <filter> element like
<filter>Flipmedia_AddShippingCountryColumn_Adminhtml_Block_Widget_Grid_Column_Filter_Country</filter>
Note the new class, it should extend Mage_Adminhtml_Block_Widget_Grid_Column_Filter_Select like this...check out the magento svn as a reference.
class Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Config_Grid_Filter_Inventory extends Mage_Adminhtml_Block_Widget_Grid_Column_Filter_Select
{
protected function _getOptions()
{
// return an array of options
return array(
array(
'value' => '',
'label' => ''
));
}
}

Related

How to display payment method and application in order view Magento 2 Admin?

I want to display application_no if payment method is FN in order details page.
I have created a block.
class Custom extends \Magento\Framework\View\Element\Template
{
public function __construct(
\Magento\Framework\View\Element\Template\Context $context,
array $data = []
) {
parent::__construct($context, $data);
}
}
Also, I have created a sales_order_view.xml to display my application_no (Tested it with static value and working fine).
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="left">
<referenceContainer name="payment_additional_info">
<block class="Limesharp\FinanceNow\Block\Adminhtml\Order\View\Custom" name="sales_order_view_custom" template="order/view/custom.phtml" />
</referenceContainer>
</referenceContainer>
</body>
</page>
Here is my view file -
FN: <?php echo $block->getOrder(); ?>
Now I wanna pass application_no(custom column already in sales_order table) and payment_method. How can I pass this information from block to view of current order and display it conditionally?

Magento 2 use custom block in extended template

I want to use a block in order to get some data in a template, but it's not working.
Here is my block
class Question extends \Magento\Framework\View\Element\AbstractBlock
{
protected $customerSession;
public function __construct(
Template\Context $context,
\Magento\Customer\Model\Session $customerSession
)
{
$this->customerSession = $customerSession;
parent::__construct($context);
}
public function test()
{
return "OK";
//return $this->customerSession->getCustomer()->getId();
}
}
And this is my catalog_product_view.xml
<?xml version="1.0"?>
<page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="product.info.details">
<block class="Magento\Catalog\Block\Product\View" name="question.tab" as="question" template="Semaine2_TP::product/delivery_info.phtml" group="detailed_info" >
<arguments>
<argument translate="true" name="title" xsi:type="string">Questions</argument>
</arguments>
<block name="question" class="Semaine2\TP\Block\Question" cacheable="false" template="Semaine2_TP::question/info.phtml" group="detailed_info"/>
</block>
</referenceBlock>
</body>
</page>
But with this, only the delivery_info.phtml is printed, and the info.phtml seems to be ignored.
Actually what I would like to be able to do is to use my test function from the block inside my delivery_info.phtml in order to get an action target URL for example or to get the customer if he is logged in.
But when I call $block in my phtml he always seems to search into the Magento\Catalog\Block\Product\View which is normal I guess.
New to magento 2 and no idea how to deal with this. Thanks for your assistance.
The right way is to use Magento View Models instead of Block classes to separate business logic
https://devdocs.magento.com/guides/v2.3/extension-dev-guide/view-models.html
catalog_product_view.xml:
<referenceBlock name="product.info.details">
<block name="question.tab" as="question" template="Semaine2_TP::product/delivery_info.phtml" group="detailed_info" >
<arguments>
<argument translate="true" name="title" xsi:type="string">Questions</argument>
</arguments>
<block name="question" cacheable="false" template="Semaine2_TP::question/info.phtml" group="detailed_info">
<arguments>
<argument name="view_model" xsi:type="object">Semaine2\TP\ViewModel\Question</argument>
</arguments>
</block>
</block>
</referenceBlock>
app/code/Semaine2/TP/ViewModel/Question.php:
<?php
namespace Semaine2\TP\ViewModel;
use Magento\Framework\Registry;
use Magento\Catalog\Model\Product;
use Magento\Framework\View\Element\Block\ArgumentInterface;
/**
* Class Question.
*/
class Question implements ArgumentInterface
{
/**
* #var Registry
*/
private $registry;
/**
* #var Product
*/
private $product;
/**
* #param Registry $registry
*/
public function __construct(
Registry $registry
) {
$this->registry = $registry;
}
/**
* Get current product.
*
* #return Product
*/
public function getProduct(): Product
{
if ($this->product === null) {
$this->product = $this->registry->registry('current_product');
}
return $this->product;
}
}
Are you calling $block->getChildHtml() in your delivery_info.phtml file?
Since you have a custom block and template, I think you need to explicitly call a toHtml for your block. You can also pass in your custom block name to the function, if not I believe all child block HTMLs will be printed.
I was extending the wrong Block.
The block need to extends use Magento\Catalog\Block\Product\View;
Sadly this magento native block is using deprecated arguments, but I think we can't escape from this if we want to be able to call the construct.

magento attributes filter only in last (level 3) category

I have category hierarchy up to level 3. ex,
Root Category
Category 1
Category 1.1
Category 1.1.1
Category 1.1.2
Category 1.1.3
Category 1.2
Category 1.2.1
Category 1.2.2
Category 1.2.3
Category 1.3
Category 2
. . .
. . .
. . .
Question
While browsing categories in layered navigation, the product's attribute's filters are displaying in all layers but i want to attribute filter in only last category (eg. 3rd level category). How to do that
Note: I have searched it a lot but on one question of magento meta, one answer was altering css to hide filters in particular page. but i want to do it on higher level ( without css and if possible then php hacks).
If you need to display layered navigation in level-3 only, you need to set a condition inside the template that render layered navigation block.
Layered navigation block is rendering by the template app/design/frontend/<your_package>/<your_theme>/template/catalog/layer/view.phtml. You have to modify the content as shown below
<?php
if(Mage::registry('current_category')->getData('level')== 4):
?>
<?php
/**
* Content in the template comes here :)
*
* Add content in this file, inside this condition
*/
?>
<?php endif; ?>
What we are done here is, we get the current category level using the method Mage::registry('current_category') and check whether it is level-4. If yes renders the content. else it will not.
Note : What you have described as level-3 in your context is actually level-4. That is because, magento counts root-category as level-1
Thats it. That will do the trick. Enjoy coding. Let me know if you have any doubts.
EDIT
So you need to display category navigation in all category levels, but need to show other filter attributes in level-4 only. If that is the case, let us implement it.
As I already stated, app/design/frontend/<your_package>/<your_theme>/template/catalog/layer/view.phtml is the starting point of layered navigation blocks. In that file you can see that, it invokes below method
<?php $_filters = $this->getFilters() ?>
to show the layered navigation content. This method is defined in Mage_Catalog_Block_Layer_View class and the file is in the location app/code/core/Mage/Catalog/Block/Layer/View.php. Let us analyze this method.
public function getFilters()
{
$filters = array();
if ($categoryFilter = $this->_getCategoryFilter()) {
$filters[] = $categoryFilter;
}
$filterableAttributes = $this->_getFilterableAttributes();
foreach ($filterableAttributes as $attribute) {
$filters[] = $this->getChild($attribute->getAttributeCode() . '_filter');
}
return $filters;
}
Here you can see that, when we call this method, it returns an array, i e $filters. Again you can see that, category-filter and attributes-filter are storing in $filters separately. So we are lucky. What we need to do is, include the attribute-filters to $filters array only when we are standing in level-4. You can easily achieve this by changing code in this format.
public function getFilters()
{
$filters = array();
if ($categoryFilter = $this->_getCategoryFilter()) {
$filters[] = $categoryFilter;
}
$current_layer = Mage::registry('current_category')->getData('level');
if($current_layer == 4) {
$filterableAttributes = $this->_getFilterableAttributes();
foreach ($filterableAttributes as $attribute) {
$filters[] = $this->getChild($attribute->getAttributeCode() . '_filter');
}
}
return $filters;
}
Thats it. you are done. But its not a good practice to change a core files. So in order to keep core files untouched, let us create a tiny module that overwrites this class. You just need only 3 files in your module.
config.xml
Location :app/code/local/Programmerrkt/Layerednav/etc/config.xml
<config>
<modules>
<Programmerrkt_Layerednav>
<version>0.1.0</version>
</Programmerrkt_Layerednav>
</modules>
<global>
<blocks>
<!-- rewrites Mage_Catalog_Block_Layer_View -->
<catalog>
<rewrite>
<layer_view>Programmerrkt_Layerednav_Block_Layer_View</layer_view>
</rewrite>
</catalog>
</blocks>
</global>
</config>
config.xml tells to magento that I am going to overwrite the core block Mage_Catalog_Block_Layer_View.
Programmerrkt_Layerednav.xml
Location :app/etc/modules/Programmerrkt_Layerednav.xml
<config>
<modules>
<Programmerrkt_Layerednav>
<active>true</active>
<codePool>local</codePool>
</Programmerrkt_Layerednav>
</modules>
</config>
This file activates our module.
View.php
Location : app/code/local/Programmerrkt/Layerednav/Block/Layer/View.php
<?php
class Programmerrkt_Layerednav_Block_Layer_View extends Mage_Catalog_Block_Layer_View {
/**
* Get all layer filters
*
* This method Overwrites getFilter() method of class Mage_Catalog_Block_Layer_View
*
* Adds attribute filter only when category leve is 4
*
* #return array
*/
public function getFilters()
{
$filters = array();
if ($categoryFilter = $this->_getCategoryFilter()) {
$filters[] = $categoryFilter;
}
$current_layer = Mage::registry('current_category')->getData('level');
if($current_layer == 4) {
$filterableAttributes = $this->_getFilterableAttributes();
foreach ($filterableAttributes as $attribute) {
$filters[] = $this->getChild($attribute->getAttributeCode() . '_filter');
}
}
return $filters;
}
}
This will overwrite the core class.
Now clear the cache and reload the pages. Check whether it worked or not. Remember that you need to remove all changes that you made to the file view.phtml
Thanks

Magento One-Page checkout mod

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.

Magento: which block is unsing in Mage_Adminhtml_Catalog_ProductController?

The main aim is to find where to generate left tag block for new product page. And to modify it.
To get it I'm trying to understand which block is running in case the product is new?
In this code I print out name block.
class Mage_Adminhtml_Catalog_ProductController extends Mage_Adminhtml_Controller_Action
{
//...
/**
* Create new product page
*/
public function newAction()
{
//...
$this->loadLayout(array(
'default',
strtolower($this->getFullActionName()),
'adminhtml_catalog_product_'.$product->getTypeId() . $_additionalLayoutPart
));
// echo adminhtml_catalog_product_new
echo 'adminhtml_catalog_product_'.$product->getTypeId() . $_additionalLayoutPart;
//...
}
//...
}
Find out this block in catalog.xml:
<adminhtml_catalog_product_new>
<update handle="editor"/>
<!-- ... -->
<reference name="left">
<block type="adminhtml/catalog_product_edit_tabs" name="product_tabs"></block>
</reference>
<!-- ... -->
</adminhtml_catalog_product_new>
In the following step I found block model:
class Mage_Adminhtml_Block_Catalog_Category_Tabs extends Mage_Adminhtml_Block_Widget_Tabs { /**
* Initialize Tabs
*
*/
public function __construct()
{
die("debug label");
//....
}
// ...
}
refresh page and ... nothing happaned.
It seems there is not block that we're searching for...which one then?
Firstly, the layout xml says adminhtml/catalog_product_edit_tabs, then it is Mage_Adminhtml_Block_Catalog_Product_Edit_Tabs you should be looking for, not Mage_Adminhtml_Block_Catalog_Category_Tabs.
Secondly, I think it is Mage_Adminhtml_Block_Catalog_Product_Edit_Tabs_Configurable which controls the tabs if you are creating a new configurable product.

Resources