Adding a CMS Action to SilverStripe‘s ModelAdmin

About a year ago I read a tutorial on ssbits.com by Aram Balakjian about adding an action button to the CMS. Aram called it „the slightly hacky way“ because he „left“ the framework by working with the PHP global $_REQUEST.

Sebastian added two action buttons to a model admin of SilverCart. Since he did it with framework measures only, I want to tell you how this works.

The Use Case

As you might know already we have a configuration object in SilverCart. This is accessed via an own model admin called „SilvercartShopConfigurationAdmin“. It has a controller for object manipulation called „SilvercartShopConfigurationAdmin_RecordController“. Sebastian added two action buttons to the congifuraiton objects details view. One button is for the creation of an example configuration(->addExampleConfig()). The other button is for the creation of example data(->addExampleData()).

Fill Me In

First you have to register the record controller in the model admin be defining a static attribute:

public static $record_controller_class = 'SilvercartShopConfigurationAdmin_RecordController';

The record controller class is defined in the same file as the model admin ´SilvercartShopConfigurationAdmin´.

class SilvercartShopConfigurationAdmin_RecordController extends ModelAdmin_RecordController {

    public function handleAction(SS_HTTPRequest $request) {
        $vars = $request->getVars();
        if (array_key_exists('addExampleData', $vars)) {
            return $this->addExampleData();
        } elseif (array_key_exists('addExampleConfig', $vars)) {
            return $this->addExampleConfig();
        } else {
            return parent::handleAction($request);
        }
    }
}

The function „handleAction“ evaluates the request data passed via GET as the button is triggered. Depending on the GET parameters an other function is called, in our case addExampleData() and addExampleConfig(). They are both supposed to return a SS_HTTPResponse.

I guess Sebastian got the idea for this solution from the method edit() of the ModelAdmin_RecordController.

Customizing the CMS Fields

Finally the button must be defined on getCMSFields() of the class managed in the model. As there are no tabs in the model admin per default a new FieldSet with TabSets must be built. I will cut distracting details from the original SilverCart code( SilvercartConfig, line 194ff) out:

public function getCMSFields($params = null) {
        $defaultCMSFields = parent::getCMSFields($params);

        // Building the general tab structure
        $CMSFields = new FieldSet(
                        $rootTab = new TabSet(
                                'Root',
                                $generalTab = new TabSet(
                                        'General',
                                        $tabGeneralMain = new Tab('Main'),
                                        $tabGeneralTestData = new Tab('TestData')
                                )
                        )
        );

        // General Form Fields right here
        $generalTab->setTitle(_t('SilvercartConfig.GENERAL'));
        // General Main
        $tabGeneralMain->setTitle(_t('SilvercartConfig.GENERAL_MAIN'));

        $CMSFields->addFieldsToTab('Root.General.Main', $defaultCMSFields->dataFields());

        // FormFields for Test Data right here
        $tabGeneralTestData->setTitle(_t('SilvercartConfig.GENERAL_TEST_DATA'));

        $addExampleData = new FormAction('addExampleData', _t('SilvercartConfig.ADD_EXAMPLE_DATA', 'Add Example Data'));
        $addExampleData->setRightTitle(_t('SilvercartConfig.ADD_EXAMPLE_DATA_DESCRIPTION'));
        $CMSFields->addFieldToTab('Root.General.TestData', $addExampleData);

        $addExampleConfig = new FormAction('addExampleConfig', _t('SilvercartConfig.ADD_EXAMPLE_CONFIGURATION', 'Add Example Configuration'));
        $addExampleConfig->setRightTitle(_t('SilvercartConfig.ADD_EXAMPLE_CONFIGURATION_DESCRIPTION'));
        $CMSFields->addFieldToTab('Root.General.TestData', $addExampleConfig);
        
        return $CMSFields;
    }

First the parent CMS fields are loaded. Then a field set with a new tab called root is instanciated. That tab set contains another tab set called ,General‘. Within ,General‘ there are two tabs called ,Main‘ and ,TestData‘. Now the parent CMS fields can be added to the tab Root.General.Main. Now the two form action fields for example configuration and example data follow. They trigger the methods addExampleData and addExampleConfig defined on our record controller.