Magento: which block is unsing in Mage_Adminhtml_Catalog_ProductController? - magento

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.

Related

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, Extending Order Grid using XML markup method, select options issue

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' => ''
));
}
}

use case for getProductAdditionalInformationBlock in magento

I'd like to put some additional info under each item in the cart. I have this info already saved in table "sales_flat_quote_item" in "additional_info" field. So the question is only how to show it globally at all places where the items are shown.
I saw in several places under item name there is a structure like this:
<?php if ($addtInfoBlock = $this->getProductAdditionalInformationBlock()):?>
<?php echo $addtInfoBlock->setItem($_item)->toHtml() ?>
<?php endif;?>
For example in this files:
/app/design/frontend/base/default/template/checkout/cart/item/default.phtml
/app/design/frontend/base/default/template/checkout/onepage/review/item.phtml
So I suppose this is the place I should use for such task.
What I figured out is that:
I have to add my own block definition to for example:
<checkout_cart_index>
<block type="core/text_list" name="additional.product.info" translate="label">
<label>Additional Product Info</label>
<block type="various/itemrendererdefault" name="glass.additional" as="glass" template="checkout/cart/glass_additional.phtml"/>
</block>
</checkout_cart_index>
This is no problem so far. My class is loaded
class Site1_Various_Block_Itemrendererdefault extends Mage_Core_Block_Template {
public function setItem(Varien_Object $item) {
$this->setData('item', $item);
return $this;
}
public function getItem() {
return $this->_getData('item');
}
}
and the template checkout/cart/glass_additional.phtml is called.
But inside the template I have no idea how to get the info about what $item should I process. I tried:
$_item = $this->getItem();
print_r($_item);
$_item = $this->getData();
print_r($_item);
but it returns nothing.
So my question is: How to get $item data inside my template.
Can I access the data set in?
...
$addtInfoBlock->setItem($_item)->toHtml();
...
Krystian, the OP, already self-answered his question.
Quote:
I just solved the issue by setting my block as "additional.product.info"
<checkout_cart_index>
<block type="various/itemrendererdefault" name="additional.product.info" translate="label" template="checkout/cart/glass_additional.phtml"></block>
</checkout_cart_index>
Note: It's absolutely OK to self-answer your own question. Please just post it as an real answer, but not in a question or comment. Posting as real answer helps to keep the "Unanswered" list more clear (avoids making other people wasting their time).
I think to get the item instance you have to try this:
class Site1_Various_Block_Itemrendererdefault extends Mage_Core_Block_Template {
public function setItem(Varien_Object $item) {
$this->setData('item', $item);
return $this;
}
public function getItem() {
$parent = $this->getParentBlock();
if ($parent) {
$item = $parent->getItem();
}
}
}
Thanks !
I was having issues with this as well until I used a block type of core/template and a call to getParentBlock() in my custom template file. This might work for any custom block type but I didn't test.
In your layout/local.xml file:
<checkout_cart_index>
<reference name="additional.product.info">
<block type="core/template" name="additional.product.info.your_template" as="your_template" template="checkout/cart/item/your-template.phtml"/>
</reference>
</checkout_cart_index>
The $addtInfoBlock->setItem($_item)is called on the additional.product.info block, which would be the parent of any blocks you add underneath it. Because of this, you can call $this->getParentBlock() in your template to get access to it's data.
So now, in your checkout/cart/item/your-template.phtml:
$_item = $this->getParentBlock()->getItem();
/* get access to all product attributes, with a performance hit. */
$_product = $_item->getProduct()->load();
/* Some product attributes */
echo $_product->getName();
echo $_product->getSku();

Display Tiered Pricing on the Cart page

If Im on this page:
http:///checkout/cart/
With products in my cart I would like to display the tiered pricing, the same that is shown on the item page, if available.
My attempt was add
<checkout_cart_index>
<block type="catalog/product_view" name="product.tierprices" as="tierprices" template="catalog/product/view/tierprices.phtml"/>
</checkout_cart_index>
to my xml file and add
<?php echo $this->getChildHtml('tierprices') ?>
to
\app\design\frontend\enterprise\<mytemplate>\template\checkout\cart\item\default.phtml
Doesn’t do anything - any further suggestions?
It seems impossible to easily change layout. You need to modify item renderer and add tier price displaying manually. To fetch list of available tier prices you need to get price model. You can get it from product model
$product->getPriceModel()
or if don't have product model try the following code
Mage::getSingleton('catalog/product_type')->priceFactory($productTypeId)
Quote item contains product type information.
When you have price model just call method getTierPrice() to get all tier prices as array.
$priceModel->getTierPrice()
You could edit the .phtml file and adding the $this->getTierPrices($_product);//or$this->getTierPrices($_item); if you simply want to display the tier prices of products.
Do note that the getTierPrices() only works when being on the product list or product view page, so you would need to copy the getTierPrices() method that can be found inside the List.php to your custom module.
This should give you an idea what needs to be done.
layout file
<?xml version="1.0"?>
<layout version="0.1.0">
<checkout_cart_index>
<reference name="additional.product.info">
<block type="LokeyCoding_Cart/TierPrice" name="additional.product.info.tierprice" />
</reference>
</checkout_cart_index>
</version>
block file
<?php
class LokeyCoding_Cart_Block_TierPrice extends Mage_Core_Block_Abstract
{
protected function _toHtml()
{
$parent = $this->getParentBlock();
if ($parent) {
$item = $parent->getItem();
if ($item instanceof Mage_Sales_Model_Quote_Item) {
return $item->getProduct()->getTierPriceHtml();
}
}
return '';
}
}

Magento 1.4 - Displaying some products under specific category

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.

Resources