I want to add new button to category page on admin side with delete category and save category.I try the way to override the block Catalog_Category_Edit_Form but didn't work.My xml code is :
<adminhtml>
<rewrite>
<Catalog_Category_Edit_Form>Mymodule_Block_Rewrite_Editcate</Catalog_Category_Edit_Form>
</rewrite>
</adminhtml>
While my block code is
<?php
class Mymodule_Block_Rewrite_Editcate extends Mage_Adminhtml_Block_Catalog_Category_Edit_Form
{
private $parent;
protected function _prepareLayout()
{
// Delete button
$this->parent = parent::_prepareLayout();
$this->removeButton('delete_button');
return $this->parent;
}
}.
Can anyone help me the right way ? In above code i try to remove button to check my code works .
Sorry guys i find a solution .My new xml is look like
<adminhtml>
<rewrite>
<catalog_category_edit_form>Mymodule_Block_Adminhtml_Catalog_Category_Edit_Form</catalog_category_edit_form>
</rewrite>
</adminhtml>
And my block code is :
<?php
class Mymodule_Block_Adminhtml_Catalog_Category_Edit_Form extends Mage_Adminhtml_Block_Catalog_Category_Edit_Form
{
protected function _prepareLayout()
{
parent::_prepareLayout();
$this->addAdditionalButton('update_button', array('name' => 'update_button','title'=>'Copy Category','type'=>"button",'label'=> Mage::helper('catalog')->__('Copy Category') ));
return parent::_prepareLayout();
}
}.
This is it.Mian function is addAdditionButton.Only pass parameter to it.I have override it.
Related
I create tab Opinion in adminhtml catalog product page.
I want that my tab 'Opinion' was first in list of tabs.
app/code/local/Fishpig/Customtabs/Block/Adminhtml/Catalog/Product/Tab.php
class Fishpig_Customtabs_Block_Adminhtml_Catalog_Product_Tab
extends Mage_Adminhtml_Block_Template
implements Mage_Adminhtml_Block_Widget_Tab_Interface {
public function _construct()
{
parent::_construct();
$this->setTemplate('customtabs/catalog/product/tab.phtml');
}
public function getTabLabel()
{
return $this->__('Opinion');
}
public function getTabTitle()
{
return $this->__('Click here to view your custom tab content');
}
public function canShowTab()
{
return true;
}
public function isHidden()
{
return false;
}
app/design/adminhtml/default/default/layout/customtabs.xml
*
<layout>
<adminhtml_catalog_product_edit>
<reference name="product_tabs">
<action method="addTab">
<name>opinion</name>
<block>customtabs/adminhtml_catalog_product_tab</block>
</action>enter code here
</reference>
</adminhtml_catalog_product_edit>
</layout>
*
If you want your tab at the first in Admin Catalog Product Add Or Edit page
then you need to do these Steps
1: Override this File
<global>
<blocks>
<adminhtml>
<rewrite>
<catalog_product_edit_tabs>Namespace_Modulename_Block_Adminhtml_Catalog_Product_Edit_Tabs</catalog_product_edit_tabs>
</rewrite>
</adminhtml>
</blocks>
</global>
Step 2 : in the file
there is one function named : _prepareLayout
override that in your module file
and add the tab after this code
$product = $this->getProduct();
if (!($setId = $product->getAttributeSetId())) {
$setId = $this->getRequest()->getParam('set', null);
}
add this code
$this->addTab('opinion', array(
'label' => Mage::helper('core')->__('Opinion'),
'url' => $this->getUrl('module/controller/opinion', array('_current' => true)),
'class' => 'ajax',
));
Step 3 : in controller create one function opinion and set your template file there with $this->setTemplate('customtabs/catalog/product/tab.phtml');
let me know if you need more help
Try using the addTabAfter method instead
<action method="addTabAfter">
<name>opinion</name>
<block>customtabs/adminhtml_catalog_product_tab</block>
<after></after>
</action>
To determine after which tab you want add you cutom tab you need in your file
app/code/local/Fishpig/Customtabs/Block/Adminhtml/Catalog/Product/Tab.php
add such method:
public function getAfter()
{
return 'group_32'; // Name of tab after which you want add your tab
}
group_32 it's name of General tab in my case.
I am Using Observer Event in my custom module's Config.xml
<controller_action_layout_render_before>
<observers>
<Test_Check_Model_Observer>
<class>Test_Check_Helper_Data</class>
<method>checkValidi</method>
</Test_Check_Model_Observer>
</observers> </controller_action_layout_render_before>
Now in Test/Check/Helper/Data checkValidi Method I am inserting a block in Content.
>
class Test_Check_Helper_Data extends Mage_Core_Helper_Abstract {
> public function checkValidi($observer) {
> $layout = Mage::app()->getLayout();
> $content = $layout->getBlock('content');
> $block = 'hello! I am Working';
> $content->insert($block);
> }
But In Frontend When I am Filling Checkout billing and other information it gives me an Error Call to a member function insert() on a non-object in right side bar of Your Checkout Progress ,Please Give me any Solution for that Thanks
If you look at layout of checkout module checkout.xml you can see that some handles do not have content block. Eg, checkout_onepage_progress_billing or checkout_onepage_progress_shipping
So, you will get non-object error with your code. I think you should check $block variable before calling method.
$layout = Mage::app()->getLayout();
$content = $layout->getBlock('content');
if ($content) {
$block = 'hello! I am Working';
$content->insert($block);
}
It is not good idea to call helper from observer.
Observer always call a model file ,it did not class
i have modify and code config.xml code is
<global>
<models>
<testcheck>
<class>Test_Check_Model</class>
</testcheck>
</models>
</global>
<events>
<controller_action_layout_render_before>
<observers>
<test_check_codel_observer>
<type>singleton</type>
<class>testcheck/observer</class>
<method>your_function_name</method>
</test_check_codel_observer>
</observers>
</controller_action_layout_render_before>
</events>
And then Create Observer Observer.php file Under app/code/YourcodePoll/Test/Check/Model/
and below
code in Observer.php
is
<?php class Test_Check_Model_Observer
{
public function your_function_name($observer){
$block = $this->getLayout()
->createBlock('core/text', 'example-block')
->setText('<h1>This is a text block</h1>');
$observer->getEvent()->getLayout()->getBlock('content')->append($block);
//$observer->getEvent()->getLayout()->getUpdate();
}
}
It seems like everything is being properly configured and I can get the output that I want but I would prefer not echoing the layout object directly from my controller:
Here is what Im working with
config.xml
<config>
<modules>
<ALS_Bestselling>
<version>0.1.0</version>
</ALS_Bestselling>
</modules>
<global>
<models>
<bestselling>
<class>ALS_Bestselling_Model</class>
</bestselling>
</models>
<blocks>
<bestselling>
<class>ALS_Bestselling_Block</class>
</bestselling>
</blocks>
<helpers>
<bestselling>
<class>ALS_Bestselling_Helper</class>
</bestselling>
</helpers>
</global>
<frontend>
<layout>
<updates>
<als_bestselling>
<file>bestselling.xml</file>
</als_bestselling>
</updates>
</layout>
</frontend>
<default>
<web>
<routers>
<bestselling_router>
<area>frontend</area>
<class>ALS_Bestselling_Controller_Router</class>
</bestselling_router>
</routers>
</web>
<shorturls>
</shorturls>
</default>
</config>
and
#File: Controller/Router.php
<?php
class ALS_Bestselling_Controller_Router extends Mage_Core_Controller_Varien_Router_Abstract
{
private static $_module = 'bestsellers';
private static $_realModule = 'ALS_Bestselling';
private static $_controller = 'index';
private static $_controllerClass = 'ALS_Bestselling_Controller_Index';
private static $_action = 'view';
public function initControllerRouters($observer)
{
$front = $observer->getEvent()->getFront();
$front->addRouter('bestselling', $this);
}
public function collectRoutes()
{
// nothing to do here
}
public function match(Zend_Controller_Request_Http $request)
{
$this->_request = $request;
$front = $this->getFront();
$identifier = trim($request->getPathInfo(), '/');
if(!substr($identifier,0,strlen('bestsellers')) == 'bestsellers'){
return false;
}else{
//$rewrite = Mage::getModel('core/url_rewrite');
$route_params = str_replace ( "bestsellers/" , "" , $identifier );
$rewrite = Mage::getModel('core/url_rewrite');
$rewrite->setStoreId(1);
$rewrite->loadByRequestPath($route_params);
$category_route = $rewrite->getIdPath();
//If no route exists for category send to a different router
if(!$category_route != ""){
return false;
}//Otherwise send the parameters to the request
else{
$id = str_replace ( "category/" , "" , $category_route );
$this->_request->setParam('id',$id);
}
$this->_setRequestRoute();
$this->_dispatch();
return true;
}
}
protected function _setRequestRoute()
{
$this->_request->setModuleName(self::$_module);
$this->_request->setControllerName(self::$_controller);
$this->_request->setActionName(self::$_action);
$this->_request->setControllerModule(self::$_realModule);
}
protected function _dispatch()
{
$this->_request->setDispatched(true);
$controller = Mage::getControllerInstance(self::$_controllerClass, $this->_request, $this->_response);
$controller->dispatch(self::$_action);
}
}
and
File: Controller/Index.php
class ALS_Bestselling_Controller_Index extends Mage_Core_Controller_Front_Action{
public function viewAction(){
$layout = Mage::app()->getLayout();
$layout->generateXml()->generateBlocks();
$render = $layout->getBlock('root')->toHtml();
echo $render;
}
}
The previous works but the following:
$update = $this->getLayout()->getUpdate();
$update->addHandle('default');
$this->renderLayout();
throws an error Call to a member function appendBody() on a non-object.
Is this how I am suppose to do this or is there something missing from the recipe?
Custom routing classes are on the fringe of what most developers do with Magento — the standard approach would be to setup a standard module controller with a frontname of bestselling, or create your feature in a non-seo friendly way and then create a rewrite entity/object to SEO-ify it.
I, however, have a soft spot for custom routing objects, even if there's little in the way of best community practices behind them. Without a line number, it sounds like your exception
Call to a member function appendBody() on a non-object
comes from the following code
#File: app/code/core/Mage/Core/Controller/Varien/Action.php
$this->getResponse()->appendBody($output);
Given the definition for getResponse
public function getResponse()
{
return $this->_response;
}
It sounds like your controller object doesn't have a proper response object set.
Looking at your controller instantiation code
$controller = Mage::getControllerInstance(self::$_controllerClass, $this->_request, $this->_response);
You're referencing a $this->_response property — but your router class and the abstract router class don't have this property. It's impossible to say based on what you've posted, but this is probably your problem. Take a look at how the standard router's match method does it.
#File: app/code/core/Mage/Core/Controller/Varien/Router/Standard.php
//...
$controllerInstance = Mage::getControllerInstance($controllerClassName, $request, $front->getResponse());
So, use the front-controller object to grab the response object, pass that into the getCongrollerInstance factory method, and you should be good to go (or at least onto the next problem)
On the WYSIWYG editor for CMS pages in Magento there's a tool to add Magento widgets to the editor. I'd like this also to be available for the WYSIWYG on the product and category descriptions.
I'm struggling to find where the editor is even loaded at the moment. Could anyone let me know what I might have to do or at least point me in the right direction?
Thanks in advance.
After enabling add_widgets and add_variables in class Mage_Adminhtml_Block_Catalog_Helper_Form_Wysiwyg_Content as per #David Manner's answer, you will likely find that whilst this will certainly enable these in the WYSIWYG editor and function properly, it will only render the raw widget/variable code in the front end (rather than the appropriate markup).
You can fix with the following:-
Navigate to /app/design/frontend/package/theme/template/catalog/category/view.phtml
Find <?php if($_description=$this->getCurrentCategory()->getDescription()): ?>
Add the following below this line:-
<?php
$helper = Mage::helper('cms');
$processor = $helper->getPageTemplateProcessor();
$_description = $processor->filter($_description);
?>
This will render in the frontend correctly then.
Under the class Mage_Adminhtml_Block_Catalog_Helper_Form_Wysiwyg_Content there are two flags in the config array 'add_widgets' and 'add_variables'. Both of these are set to false by default.
Setting these to true will then be caught in the Mage_Widget_Model_Observer class function prepareWidgetsPluginConfig on the event cms_wysiwyg_config_prepare.
I would suggest rewriting the Mage_Adminhtml_Block_Catalog_Helper_Form_Wysiwyg_Content to fit your needs, but setting add_widgets and add_variables to true should work for both categories and products.
After read all answers I found elegant solution. This solution rewrite only one Block class and doesn't change any template file.
Rewrite Mage_Adminhtml_Block_Catalog_Helper_Form_Wysiwyg_Content
<config>
...
<global>
<blocks>
...
<adminhtml>
<rewrite>
<catalog_helper_form_wysiwyg_content>Agere_Wysiwyg_Block_Widget_Anywhere</catalog_helper_form_wysiwyg_content>
</rewrite>
</adminhtml>
</blocks>
...
</global>
</config>
Change only two flags in the config array 'add_widgets' and 'add_variables' to true
class Agere_Wysiwyg_Block_Widget_Anywhere extends Mage_Adminhtml_Block_Catalog_Helper_Form_Wysiwyg_Content {
protected function _prepareForm() {
//return parent::_prepareForm();
$form = new Varien_Data_Form(array('id' => 'wysiwyg_edit_form', 'action' => $this->getData('action'), 'method' => 'post'));
$config['document_base_url'] = $this->getData('store_media_url');
$config['store_id'] = $this->getData('store_id');
$config['add_variables'] = true;
$config['add_widgets'] = true;
$config['add_directives'] = true;
$config['use_container'] = true;
$config['container_class'] = 'hor-scroll';
$form->addField($this->getData('editor_element_id'), 'editor', array(
'name' => 'content',
'style' => 'width:725px;height:460px',
'required' => true,
'force_load' => true,
'config' => Mage::getSingleton('cms/wysiwyg_config')->getConfig($config)
));
$this->setForm($form);
return $this;
}
}
Create handler that will process content from category or product
class Agere_Wysiwyg_Helper_Filter extends Mage_Core_Helper_Abstract {
public function categoryAttribute($mainHelper, $result, $params) {
return $this->process($result);
}
public function productAttribute($mainHelper, $result, $params) {
return $this->process($result);
}
public function process($result) {
/** #var Mage_Cms_Helper_Data $helperCms */
$helperCms = Mage::helper('cms');
$processor = $helperCms->getPageTemplateProcessor();
return $processor->filter($result);
}
}
Finally create Observer wich add handlers for out wysiwyg
class Agere_Wysiwyg_Model_Observer extends Varien_Event_Observer {
public function addWysiwygHandler(Varien_Event_Observer $observer) {
/** #var Mage_Catalog_Helper_Output $_helperOutput */
/** #var Agere_Wysiwyg_Helper_Filter $_helperFilter */
$_helperOutput = Mage::helper('catalog/output');
$_helperFilter = Mage::helper('agere_wysiwyg/filter');
$_helperOutput->addHandler('categoryAttribute', $_helperFilter);
$_helperOutput->addHandler('productAttribute', $_helperFilter);
}
}
Full snap of code see by link https://github.com/popovsergiy/magento-wysiwyg
Think a better way is to create a new observer that listening on the same event, and make the module depending on Mage_Widget. Then our observer will be running after Mage_Widget
So I'm trying to get a grid to display in my custom module (displaying anything for the time being, I'll worry about the collection once it's working!).
The problem is that the _prepareCollection() and/or _prepareColumns() methods of my grid widget class never seem to get called and the grid never shows (nor do the buttons and header text). (The Magento admin header and footer and navigation display correctly. It's just blank in the middle!)
This is what I have so far:
app/code/local/MyNamespace/Mymodule/etc/config.xml
<?xml version="1.0" ?>
<config>
<modules>
<MyNamespace_Mymodule>
<version>0.0.1</version>
</MyNamespace_Mymodule>
</modules>
<!-- Define frontend and backend routers -->
<admin>
<routers>
<mymodule>
<use>admin</use>
<args>
<module>MyNamespace_Mymodule</module>
<frontName>mymodule</frontName>
</args>
</mymodule>
</routers>
</admin>
<!-- /Define frontend and backend routers -->
<global>
<helpers>
<mymodule>
<class>MyNamespace_Mymodule_Helper</class>
</mymodule>
</helpers>
<blocks>
<mymodule>
<class>MyNamespace_Mymodule_Block</class>
</mymodule>
</blocks>
</global>
<adminhtml>
<menu>
<mymodule module="mymodule">
<title>My Module</title>
<sort_order>80</sort_order>
<children>
<items module="mymodule">
<title>Manage My Module</title>
<sort_order>0</sort_order>
<action>mymodule/adminhtml_mymodule</action>
</items>
</children>
</mymodule>
</menu>
<!-- define layout updates -->
<layout>
<updates>
<mymodule>
<file>mymodule.xml</file>
</mymodule>
</updates>
</layout>
<!-- /define layout updates -->
</adminhtml>
</config>
Then my controller:
app/code/local/MyNamespace/Mymodule/controllers/Adminhtml/MymoduleController.php
<?php
class MyNamespace_Mymodule_Adminhtml_MymoduleController extends Mage_Adminhtml_Controller_action
{
public function indexAction() {
$this->getLayout()->createBlock('mymodule/adminhtml_mymodule');
$this->loadLayout();
$this->renderLayout();
}
}
Then in my grid container:
app/code/local/MyNamespace/Mymodule/Block/Adminhtml/Mymodule.php
<?php
class MyNamespace_Mymodule_Block_Adminhtml_Mymodule extends Mage_Adminhtml_Block_Widget_Grid_Container
{
public function __construct()
{
echo __METHOD__ . " (Line #" . __LINE__ . ")<br/>";
parent::__construct();
$this->_controller = 'adminhtml_mymodule';
$this->_blockGroup = 'mymodule';
$this->_headerText = Mage::helper('mymodule')->__('my header text'); // this is not rendered
$this->_addButtonLabel = Mage::helper('mymodule')->__('my button text'); // this is not rendered
}
protected function _prepareLayout()
{
$this->setChild( 'grid',
$this->getLayout()->createBlock( $this->_blockGroup.'/' . $this->_controller . '_grid',
$this->_controller . '.grid')->setSaveParametersInSession(true) );
return parent::_prepareLayout();
}
}
Then in my grid widget:
app/code/local/MyNamespace/Mymodule/Block/Adminhtml/Mymodule/Grid.php
<?php
class MyNamespace_Mymodule_Block_Adminhtml_Mymodule_Grid extends Mage_Adminhtml_Block_Widget_Grid
{
public function __construct()
{
parent::__construct();
$this->setId('mymoduleGrid');
$this->setDefaultSort('id');
$this->setDefaultDir('ASC');
$this->setSaveParametersInSession(true);
}
protected function _prepareCollection()
{
echo __METHOD__ . " (Line #" . __LINE__ . ")<br/>"; // This is never called
$collection = Mage::getModel('catalog/product')->getCollection(); // just a temp collection for the time being
$this->setCollection($collection);
return parent::_prepareCollection();
}
protected function _prepareColumns()
{
echo __METHOD__ . " (Line #" . __LINE__ . ")<br/>"; // This is never called
$this->addColumn('id', array(
'header' => Mage::helper('mymodule')->__('ID'),
'align' =>'right',
'width' => '10px',
'index' => 'id',
));
return parent::_prepareColumns();
}
}
And finally my layout xml:
app/design/adminhtml/default/default/layout/mymodule.xml
<?xml version="1.0"?>
<layout version="0.1.0">
<adminhtml_mymodule_index>
<reference name="content">
<block type="mymodule/adminhtml_mymodule" name="mymodule" />
</reference>
</adminhtml_mymodule_index>
</layout>
There are no errors being shown in the logs and I'm now a bit stumpped and other SO answers don't seem to fit.
Anyone shed any light on why my grid (even an empty one) isn't showing?
Thank you.
EDIT Noticed that some classes had the wrong case (Mynamespace should be MyNamespace). Changed them but no difference
It is the problem of your layout's handle tag.
It should be:
<?xml version="1.0"?>
<layout version="0.1.0">
<mymodule_adminhtml_mymodule_index>
<reference name="content">
<block type="mymodule/adminhtml_mymodule" name="mymodule" />
</reference>
</mymodule_adminhtml_mymodule_index>
</layout>
For the explanation and few tips, you can read this:
My layout isn't loading in my Magento admin view
= UPDATE =
You also need not to call $this->getLayout()->createBlock('mymodule/adminhtml_mymodule'); in your controller as is has been called in your mymodule.xml
OR
you can omit your mymodule.xml (no need to call it) by changing your controller's action into:
public function indexAction() {
$this->loadLayout();
$myblock = $this->getLayout()->createBlock('mymodule/adminhtml_mymodule');
$this->_addContent($myblock);
$this->renderLayout();
}
see the definition:
Mage_Adminhtml_Controller_Action
protected function _addContent(Mage_Core_Block_Abstract $block)
{
$this->getLayout()->getBlock('content')->append($block);
return $this;
}
those codes above do the same thing like the mymodule.xml, appending block 'mymodule/adminhtml_mymodule' to the content
It's all your choice!
Can you please make sure your index action is being called properly?
when you do this :
<?php
class Mynamespace_Mymodule_Adminhtml_MymoduleController extends Mage_Adminhtml_Controller_action
{
public function indexAction() {
echo "im here";exit; //<----does this display?
$this->getLayout()->createBlock('mymodule/adminhtml_mymodule');
$this->loadLayout();
$this->renderLayout();
}
}
and then finally its important to load your layout first. so in my opnion change your index action to this :
<?php
class Mynamespace_Mymodule_Adminhtml_MymoduleController extends Mage_Adminhtml_Controller_action
{
public function indexAction() {
$this->loadLayout(); // <---- This first
$this->getLayout()->createBlock('mymodule/adminhtml_mymodule');// <---- then this
$this->renderLayout();
}
}
I know this isn't strictly related to the answer, but hopefully this might help someone.
Just in case anyone is reading this, completely bereft of hope - make sure there's a layout file in app/design/adminhtml/default/default/layout.
I had no problems with my custom grid locally, but when I migrated it, it was displaying the symptoms above (blank screen etc)
It was due to me not copying that file over.