public function doSave($data, $form)
    {
        $className = $this->gridField->list->dataClass;
        $singleton = singleton($className);

        $formsData = array();
        $ids = array();
        $done = 0;

        //unescape and sort form data per record ID
        foreach ($data as $fieldName => $value) {
            if ($fieldInfo = $this->unEscapeFieldName($fieldName)) {
                if (!isset($formsData[$fieldInfo['id']])) {
                    $formsData[$fieldInfo['id']] = array();
                }

                $formsData[$fieldInfo['id']][$fieldInfo['name']] = $value;
            }
        }

        //process each record's form data and save
        foreach ($formsData as $recordID => $recordData) {
            $record = DataObject::get_by_id($className, $recordID);
            $recordForm = Form::create(
                $this,
                'RecordForm',
                $record->getCMSFields(),
                FieldList::create()
            );

            $recordForm->loadDataFrom($recordData);
            $recordForm->saveInto($record);
            $id = $record->write();

            array_push($ids, $record->ID);

            if ($id) {
                ++$done;
            }
        }

        //compose form message
        $messageModelClass = (($done > 1) ? $singleton->i18n_plural_name() : $singleton->i18n_singular_name());
        $message = _t(
            'GRIDFIELD_BULKMANAGER_EDIT_HANDLER.SAVE_RESULT_TEXT',
            '{count} {class} saved successfully.',
            array(
                'count' => $done,
                'class' => $messageModelClass,
            )
        );
        $form->sessionMessage($message, 'good');

        //return back to form
        return Controller::curr()->redirect($this->Link('?records[]=' . implode('&records[]=', $ids)));
        //return Controller::curr()->redirect($form->Backlink); //returns to gridField
    }