public function testLoadDataFromRequest()
 {
     $form = new Form(new Controller(), 'Form', new FieldList(new TextField('key1'), new TextField('namespace[key2]'), new TextField('namespace[key3][key4]'), new TextField('othernamespace[key5][key6][key7]')), new FieldList());
     // url would be ?key1=val1&namespace[key2]=val2&namespace[key3][key4]=val4&othernamespace[key5][key6][key7]=val7
     $requestData = array('key1' => 'val1', 'namespace' => array('key2' => 'val2', 'key3' => array('key4' => 'val4')), 'othernamespace' => array('key5' => array('key6' => array('key7' => 'val7'))));
     $form->loadDataFrom($requestData);
     $fields = $form->Fields();
     $this->assertEquals($fields->fieldByName('key1')->Value(), 'val1');
     $this->assertEquals($fields->fieldByName('namespace[key2]')->Value(), 'val2');
     $this->assertEquals($fields->fieldByName('namespace[key3][key4]')->Value(), 'val4');
     $this->assertEquals($fields->fieldByName('othernamespace[key5][key6][key7]')->Value(), 'val7');
 }
 /**
  * Gets the current state of this form as a nested array.
  *
  * @param Form $form
  * @return array
  */
 public function getState(Form $form)
 {
     // Ensure that session errors are populated within form field messages
     $form->setupFormErrors();
     // @todo - Replace with ValidationResult handling
     // Currently tri-state; null (unsubmitted), true (submitted-valid), false (submitted-invalid)
     $errors = Session::get("FormInfo.{$form->FormName()}.errors");
     $valid = isset($errors) ? empty($errors) : null;
     $state = ['id' => $form->FormName(), 'fields' => [], 'valid' => $valid, 'messages' => []];
     // flattened nested fields are returned, rather than only top level fields.
     $state['fields'] = array_merge($this->getFieldStates($form->Fields()), $this->getFieldStates($form->Actions()));
     if ($message = $form->Message()) {
         $state['messages'][] = ['value' => ['html' => $message], 'type' => $form->MessageType()];
     }
     return $state;
 }
 /**
  * @param Form $form
  */
 public function updateImageForm($form)
 {
     self::$update_called = true;
     self::$fields = $form->Fields();
 }
 public function __call($method, $args = null)
 {
     return $this->form->Fields()->fieldByName($method);
 }
 /**
  * Builds an item edit form.  The arguments to getCMSFields() are the popupController and
  * popupFormName, however this is an experimental API and may change.
  *
  * @todo In the future, we will probably need to come up with a tigher object representing a partially
  * complete controller with gaps for extra functionality.  This, for example, would be a better way
  * of letting Security/login put its log-in form inside a UI specified elsewhere.
  *
  * @return Form
  */
 public function ItemEditForm()
 {
     $list = $this->gridField->getList();
     if (empty($this->record)) {
         $controller = $this->getToplevelController();
         $url = $controller->getRequest()->getURL();
         $noActionURL = $controller->removeAction($url);
         $controller->getResponse()->removeHeader('Location');
         //clear the existing redirect
         return $controller->redirect($noActionURL, 302);
     }
     $canView = $this->record->canView();
     $canEdit = $this->record->canEdit();
     $canDelete = $this->record->canDelete();
     $canCreate = $this->record->canCreate();
     if (!$canView) {
         $controller = $this->getToplevelController();
         // TODO More friendly error
         return $controller->httpError(403);
     }
     // Build actions
     $actions = $this->getFormActions();
     // If we are creating a new record in a has-many list, then
     // pre-populate the record's foreign key.
     if ($list instanceof HasManyList && !$this->record->isInDB()) {
         $key = $list->getForeignKey();
         $id = $list->getForeignID();
         $this->record->{$key} = $id;
     }
     $fields = $this->component->getFields();
     if (!$fields) {
         $fields = $this->record->getCMSFields();
     }
     // If we are creating a new record in a has-many list, then
     // Disable the form field as it has no effect.
     if ($list instanceof HasManyList) {
         $key = $list->getForeignKey();
         if ($field = $fields->dataFieldByName($key)) {
             $fields->makeFieldReadonly($field);
         }
     }
     // Caution: API violation. Form expects a Controller, but we are giving it a RequestHandler instead.
     // Thanks to this however, we are able to nest GridFields, and also access the initial Controller by
     // dereferencing GridFieldDetailForm_ItemRequest->getController() multiple times. See getToplevelController
     // below.
     $form = new Form($this, 'ItemEditForm', $fields, $actions, $this->component->getValidator());
     $form->loadDataFrom($this->record, $this->record->ID == 0 ? Form::MERGE_IGNORE_FALSEISH : Form::MERGE_DEFAULT);
     if ($this->record->ID && !$canEdit) {
         // Restrict editing of existing records
         $form->makeReadonly();
         // Hack to re-enable delete button if user can delete
         if ($canDelete) {
             $form->Actions()->fieldByName('action_doDelete')->setReadonly(false);
         }
     } elseif (!$this->record->ID && !$canCreate) {
         // Restrict creation of new records
         $form->makeReadonly();
     }
     // Load many_many extraData for record.
     // Fields with the correct 'ManyMany' namespace need to be added manually through getCMSFields().
     if ($list instanceof ManyManyList) {
         $extraData = $list->getExtraData('', $this->record->ID);
         $form->loadDataFrom(array('ManyMany' => $extraData));
     }
     // TODO Coupling with CMS
     $toplevelController = $this->getToplevelController();
     if ($toplevelController && $toplevelController instanceof LeftAndMain) {
         // Always show with base template (full width, no other panels),
         // regardless of overloaded CMS controller templates.
         // TODO Allow customization, e.g. to display an edit form alongside a search form from the CMS controller
         $form->setTemplate(['type' => 'Includes', 'SilverStripe\\Admin\\LeftAndMain_EditForm']);
         $form->addExtraClass('cms-content cms-edit-form center fill-height flexbox-area-grow');
         $form->setAttribute('data-pjax-fragment', 'CurrentForm Content');
         if ($form->Fields()->hasTabSet()) {
             $form->Fields()->findOrMakeTab('Root')->setTemplate('SilverStripe\\Forms\\CMSTabSet');
             $form->addExtraClass('cms-tabset');
         }
         $form->Backlink = $this->getBackLink();
     }
     $cb = $this->component->getItemEditFormCallback();
     if ($cb) {
         $cb($form, $this);
     }
     $this->extend("updateItemEditForm", $form);
     return $form;
 }