Saving mouse klicks

SilverStripe2 has some inconveniences when it comes to backend usibility. If an object has a relation to a file or an image you have to save the object first before you can append a file. This took the user some extra klicks.

SilverCart 1.3 has this problem solved with a simple trick. If a user presses the „add“ button to append a new file or image to a product the object gets saved in the background. If the user leaves the popup field without saving the object gets deleted to prevent empty entires in the table. Sounds easy but it took Sebastian and me some time to figure out where to do this. Have a look at the code:

public function getCMSFieldsForContext($params = null) {
        /* @var $request SS_HTTPRequest */
        $request = Controller::curr()->getRequest();
        if ($this->ID == 0 &&
            $request->param('Action') == 'add') {
            $this->write();
            $editURL = str_replace('/add', '/item/' . $this->ID . '/edit', $request->getURL());
            Director::redirect($editURL);
        }
        $fields = parent::getCMSFields($params);
        return $fields;
    }

The method belongs to the class SilvercartImage. If the CMS fields for an image are instanciated two conditions get checked before the image gets written. First the ID must be „0“ which is the case if the object has not been written yet. Second the request action must be „add“. We want to save only if the user pressed the „add“ button.

Now the second part which is implemented in SilvercartProductAdmin:

public function init() {
        $request = $this->getRequest();
        $postVars = $request->postVars();
        if (array_key_exists('update', $postVars)) {
            $productID = $postVars['update'];
            $currentProduct = DataObject::get_by_id('SilvercartProduct', $productID);
            if ($currentProduct->SilvercartFiles()) {
                foreach ($currentProduct->SilvercartFiles() as $file) {
                    if ($file->isEmptyObject()) {
                        $file->delete();
                    }
                }
            }
            if ($currentProduct->SilvercartImages()) {
                foreach ($currentProduct->SilvercartImages() as $image) {
                    if ($image->isEmptyObject()) {
                        $image->delete();
                    }
                }
            }
        }
        
        parent::init();
        $this->extend('updateInit');
    }

Leaving the window without saving leads to a controller action and the right column in the product admin controller will be reloaded. The request has an action „update“ in this usecase. The classes SilvercartImage and SilvercartFile have a method isEmptyObject() that returns true if there is no file appended and no attributes are set. In this case the current object will be deleted.