Magento Rule Conditions in Custom Form

Table of Content

При написані модулів часто виникає потреба у використанні універсальних компонентів для обробки різних умов.
Можна, звичайно, вдатись до написання власного “велосипеду”, а можна просто розібратись в роботі Rule Conditions в Magento і пропонувати користувача зручний уніфікований функціонал, який часто використовується в core модулях.

В деталі створення модуля в даній статті не йтиметься, лише код який відноситься до Rule Conditions

Крок 1. Додаємо поля для зберігання фільтрів у нашій таблиці

// app/code/community/Popov/Seo/sql/popov_seo_setup/upgrade-0.1.8-0.1.9.php
$installer = $this;
$tableRule = $installer->getTable('popov_seo/rule');

$installer->startSetup();

$conn = $installer->getConnection();
$conn->addColumn($tableRule, 'conditions_serialized',
    array(
        'type'      => Varien_Db_Ddl_Table::TYPE_TEXT,
        'nullable'  => false,
        'comment'   => 'Serialized condition rules'
    )
);

$installer->endSetup();

Крок 2. Створюємо модель котра буде розширювати Mage_CatalogRule_Model_Rule.

// app/code/community/Popov/Seo/Model/Rule.php
class Popov_Seo_Model_Rule extends Mage_CatalogRule_Model_Rule
{
    protected function _construct()
    {
        $this->_init('popov_seo/rule');
    }

    public function getConditionsInstance()
    {
        return Mage::getModel('catalogrule/rule_condition_combine');
    }
}

Можна розширити декілька системних класів і цим самим отримати різні фільтри на виході, як от наприклад, Mage_CatalogRule_Model_Rule дасть змогу працювати з атрибутами товару у фільтрації, Mage_SalesRule_Model_Rule (Mage_SalesRule_Model_Rule_Condition_Combine) дозволить працювати з атрибутами кошику або Mage_Rule_Model_Rule.

Крок 3. Відкриваємо блок і додаємо наступний код

// app/code/community/Popov/Seo/Block/Adminhtml/Meta/Edit/Tab/Conditions.php
class Popov_Seo_Block_Adminhtml_Meta_Edit_Tab_Conditions extends Mage_Adminhtml_Block_Widget_Form
{
    protected function _prepareForm()
    {
        $model = Mage::registry('current_popov_meta');

        $form = new Varien_Data_Form();
        $form->setHtmlIdPrefix('rule_'); // is important, must be as begin of 'rule_conditions_fieldset'
        $this->setForm($form);
        $model->getConditions()->setJsFormObject('rule_conditions_fieldset');

        $renderer = Mage::getBlockSingleton('adminhtml/widget_form_renderer_fieldset')
            ->setTemplate('promo/fieldset.phtml')
            ->setNewChildUrl($this->getUrl('adminhtml/promo_quote/newConditionHtml/form/rule_conditions_fieldset'));

        $fieldset = $form->addFieldset('conditions_fieldset', array(
            'legend' => $this->__('Apply the rule only if the following conditions are met (leave blank for all order)'),
        ))->setRenderer($renderer);

        $fieldset->addField('conditions', 'text', array(
            'name' => 'conditions',
            'label' => $this->__('Conditions'),
            'title' => $this->__('Conditions'),
            'required' => true,
        ))->setRule($model)->setRenderer(Mage::getBlockSingleton('rule/conditions'));

        // this must be after fieldset declaration
        if ($data = Mage::getSingleton('adminhtml/session')->getFormData()) {
            $form->setValues($data);
        } else {
            $form->setValues($model->getData());
        }

        return parent::_prepareForm();
    }
}

Крок 4. Додаємо завантаження скриптів для побудови фільтрів

// app/design/adminhtml/default/default/layout/popov/seo.xml
<?xml version="1.0"?>
<layout>
    <!-- ... -->
    <adminhtml_meta_edit>
        <reference name="head">
            <action method="setCanLoadExtJs"><flag>1</flag></action>
            <action method="setCanLoadRulesJs"><flag>1</flag></action>
        </reference>
        <reference name="left">
            <block type="popov_seo/adminhtml_meta_edit_tabs" name="seo.meta.tags.edit.tabs"/>
        </reference>
    </adminhtml_meta_edit>
</layout>

Крок 5. Додаємо показ табів на формі

// app/code/community/Popov/Seo/Block/Adminhtml/Meta/Edit/Tabs.php
class Popov_Seo_Block_Adminhtml_Meta_Edit_Tabs extends Mage_Adminhtml_Block_Widget_Tabs
{
    public function __construct()
    {
        parent::__construct();
        $this->setId('popov_meta_tabs');
        $this->setDestElementId('edit_form'); //this should be same as the form id define above
        $this->setTitle($this->__('Meta Information'));
    }

    protected function _beforeToHtml()
    {
        // here you can add any number of tabs
        #$this->addTab('popov_meta_form', array(
        #    'label'     => $this->__('General'),
        #    'title'     => $this->__('General'),
        #    'content'   => $this->getLayout()->createBlock('popov_seo/adminhtml_meta_edit_tab_form')->toHtml(),
        #));

        $this->addTab('popov_meta_conditions', array(
            'label'     => $this->__('Conditions'),
            'title'     => $this->__('Conditions'),
            'content'   => $this->getLayout()->createBlock('popov_seo/adminhtml_meta_edit_tab_conditions')->toHtml(),
        ));

        return parent::_beforeToHtml();
    }
}

Крок 6. Додаємо в контролер код правильно обробляти і зберігати фільтри

// app/code/community/Popov/Seo/controllers/Adminhtml/MetaController.php
public function saveAction() 
{
    // ...

    if (isset($data['rule']['conditions'])) {
        $data['conditions'] = $data['rule']['conditions'];
    }
    //if (isset($data['rule']['actions'])) {
    //    $data['actions'] = $data['rule']['actions'];
    //}

    unset($data['rule']);

    $model = Mage::getModel('popov_seo/rule');
    $model->setData($data)
        ->loadPost($data) // this method load only conditions
        ->setId($this->getRequest()->getParam('id'));

    $model->save();

    $this->_redirect('*/*/');

    // ...
}

Основні налаштування на цьому завершено і цього достатньо у більшості випадків.
Якщо є необхідність створити користувацькі фільтри, тоді варто розібратись у роботі Mage_Adminhtml_Promo_CatalogController::newConditionHtmlAction, це є стартовою точкою генерації фільтрів.

Leave a Reply

Your email address will not be published. Required fields are marked *