public function testGetFormFields()
 {
     $fields = singleton('FormScaffolderTest_Article')->getFrontEndFields();
     $form = new Form(new Controller(), 'TestForm', $fields, new FieldList());
     $form->loadDataFrom(singleton('FormScaffolderTest_Article'));
     $this->assertFalse($fields->hasTabSet(), 'getFrontEndFields() doesnt produce a TabSet by default');
 }
 public function testFormValidation()
 {
     /** @skipUpgrade */
     $form = new Form(new Controller(), 'Form', new FieldList($field = new ConfirmedPasswordField('Password')), new FieldList());
     $form->loadDataFrom(array('Password' => array('_Password' => '123', '_ConfirmPassword' => '999')));
     $this->assertEquals('123', $field->children->first()->Value());
     $this->assertEquals('999', $field->children->last()->Value());
     $this->assertNotEquals($field->children->first()->Value(), $field->children->last()->Value());
 }
 public function testGetStateWithFieldValidationErrors()
 {
     $fields = new FieldList(new TextField('Title'));
     $actions = new FieldList();
     $validator = new RequiredFields('Title');
     $form = new Form(new Controller(), 'TestForm', $fields, $actions, $validator);
     $form->loadDataFrom(['Title' => null]);
     $this->assertFalse($form->validate());
     $formSchema = new FormSchema();
     $expected = ['id' => 'Form_TestForm', 'fields' => [['id' => 'Form_TestForm_Title', 'value' => null, 'message' => ['value' => ['html' => '"Title" is required'], 'type' => 'required'], 'data' => [], 'name' => 'Title'], ['id' => 'Form_TestForm_SecurityID', 'value' => $form->getSecurityToken()->getValue(), 'message' => null, 'data' => [], 'name' => 'SecurityID']], 'valid' => false, 'messages' => []];
     $state = $formSchema->getState($form);
     $this->assertInternalType('array', $state);
     $this->assertJsonStringEqualsJsonString(json_encode($expected), json_encode($state));
 }
 /**
  * Test that data loaded in via Form::loadDataFrom(DataObject) will populate the field correctly,
  * and can format the database value appropriately for the frontend
  *
  * @param string $locale
  * @param array $tests
  */
 public function checkDataFormatting($locale, $tests)
 {
     i18n::set_locale($locale);
     $field = new NumericField('Number');
     /** @skipUpgrade */
     $form = new Form(new Controller(), 'Form', new FieldList($field), new FieldList());
     $dataObject = new NumericFieldTest_Object();
     foreach ($tests as $input => $output) {
         // Given a dataobject as a context, the field should assume the field value is not localised
         $dataObject->Number = (string) $input;
         $form->loadDataFrom($dataObject, Form::MERGE_CLEAR_MISSING);
         // Test value
         $this->assertEquals($input, $field->dataValue(), "Expected {$input} loaded via dataobject to be left intact in locale {$locale}");
         // Test expected formatted value (Substitute nbsp for spaces)
         $this->assertEquals($this->clean($output), $field->Value(), "Expected {$input} to be formatted as {$output} in locale {$locale}");
     }
 }
 /**
  * Save  handler
  *
  * @param array $data
  * @param Form $form
  * @return HTTPResponse
  */
 public function save($data, $form)
 {
     $request = $this->getRequest();
     $className = $this->stat('tree_class');
     // Existing or new record?
     $id = $data['ID'];
     if (is_numeric($id) && $id > 0) {
         $record = DataObject::get_by_id($className, $id);
         if ($record && !$record->canEdit()) {
             return Security::permissionFailure($this);
         }
         if (!$record || !$record->ID) {
             $this->httpError(404, "Bad record ID #" . (int) $id);
         }
     } else {
         if (!singleton($this->stat('tree_class'))->canCreate()) {
             return Security::permissionFailure($this);
         }
         $record = $this->getNewItem($id, false);
     }
     // save form data into record
     $form->saveInto($record, true);
     $record->write();
     $this->extend('onAfterSave', $record);
     $this->setCurrentPageID($record->ID);
     $message = _t('LeftAndMain.SAVEDUP', 'Saved.');
     if ($request->getHeader('X-Formschema-Request')) {
         $schemaId = Controller::join_links($this->Link('schema/DetailEditForm'), $id);
         // Ensure that newly created records have all their data loaded back into the form.
         $form->loadDataFrom($record);
         $form->setMessage($message, 'good');
         $data = $this->getSchemaForForm($form, $schemaId);
         $response = new HTTPResponse(Convert::raw2json($data));
         $response->addHeader('Content-Type', 'application/json');
     } else {
         $response = $this->getResponseNegotiator()->respond($request);
     }
     $response->addHeader('X-Status', rawurlencode($message));
     return $response;
 }
 /**
  * @return Form
  */
 public function SearchForm()
 {
     $context = $this->getSearchContext();
     /** @skipUpgrade */
     $form = new Form($this, "SearchForm", $context->getSearchFields(), new FieldList(FormAction::create('search', _t('MemberTableField.APPLY_FILTER', 'Apply Filter'))->setUseButtonTag(true)->addExtraClass('ss-ui-action-constructive'), ResetFormAction::create('clearsearch', _t('ModelAdmin.RESET', 'Reset'))->setUseButtonTag(true)), new RequiredFields());
     $form->setFormMethod('get');
     $form->setFormAction($this->Link($this->sanitiseClassName($this->modelClass)));
     $form->addExtraClass('cms-search-form');
     $form->disableSecurityToken();
     $form->loadDataFrom($this->getRequest()->getVars());
     $this->extend('updateSearchForm', $form);
     return $form;
 }
 /**
  * Return a {@link Form} instance allowing a user to
  * add images and flash objects to the TinyMCE content editor.
  *
  * @return Form
  */
 public function MediaForm()
 {
     // TODO Handle through GridState within field - currently this state set too late to be useful here (during
     // request handling)
     $parentID = $this->getAttachParentID();
     $fileFieldConfig = GridFieldConfig::create()->addComponents(new GridFieldSortableHeader(), new GridFieldFilterHeader(), new GridFieldDataColumns(), new GridFieldPaginator(7), new GridFieldDeleteAction(), new GridFieldDetailForm());
     $fileField = GridField::create('Files', false, null, $fileFieldConfig);
     $fileField->setList($this->getFiles($parentID));
     $fileField->setAttribute('data-selectable', true);
     $fileField->setAttribute('data-multiselect', true);
     /** @var GridFieldDataColumns $columns */
     $columns = $fileField->getConfig()->getComponentByType('SilverStripe\\Forms\\GridField\\GridFieldDataColumns');
     $columns->setDisplayFields(array('StripThumbnail' => false, 'Title' => _t('File.Title'), 'Created' => File::singleton()->fieldLabel('Created')));
     $columns->setFieldCasting(array('Created' => 'DBDatetime->Nice'));
     $fromCMS = new CompositeField($select = TreeDropdownField::create('ParentID', "", 'SilverStripe\\Assets\\Folder')->addExtraClass('noborder')->setValue($parentID), $fileField);
     $fromCMS->addExtraClass('content ss-uploadfield htmleditorfield-from-cms');
     $select->addExtraClass('content-select');
     $URLDescription = _t('HTMLEditorField.URLDESCRIPTION', 'Insert videos and images from the web into your page simply by entering the URL of the file. Make sure you have the rights or permissions before sharing media directly from the web.<br /><br />Please note that files are not added to the file store of the CMS but embeds the file from its original location, if for some reason the file is no longer available in its original location it will no longer be viewable on this page.');
     $fromWeb = new CompositeField($description = new LiteralField('URLDescription', '<div class="url-description">' . $URLDescription . '</div>'), $remoteURL = new TextField('RemoteURL', 'http://'), new LiteralField('addURLImage', '<button type="button" class="action ui-action-constructive ui-button field font-icon-plus add-url">' . _t('HTMLEditorField.BUTTONADDURL', 'Add url') . '</button>'));
     $remoteURL->addExtraClass('remoteurl');
     $fromWeb->addExtraClass('content ss-uploadfield htmleditorfield-from-web');
     Requirements::css(ltrim(FRAMEWORK_ADMIN_DIR . '/client/dist/styles/AssetUploadField.css', '/'));
     $computerUploadField = UploadField::create('AssetUploadField', '');
     $computerUploadField->setConfig('previewMaxWidth', 40);
     $computerUploadField->setConfig('previewMaxHeight', 30);
     $computerUploadField->addExtraClass('toolbar toolbar--content ss-assetuploadfield htmleditorfield-from-computer');
     $computerUploadField->removeExtraClass('ss-uploadfield');
     $computerUploadField->setTemplate('SilverStripe\\Forms\\HTMLEditorField_UploadField');
     $computerUploadField->setFolderName(Upload::config()->get('uploads_folder'));
     $defaultPanel = new CompositeField($computerUploadField, $fromCMS);
     $fromWebPanel = new CompositeField($fromWeb);
     $defaultPanel->addExtraClass('htmleditorfield-default-panel');
     $fromWebPanel->addExtraClass('htmleditorfield-web-panel');
     $allFields = new CompositeField($defaultPanel, $fromWebPanel, $editComposite = new CompositeField(new LiteralField('contentEdit', '<div class="content-edit ss-uploadfield-files files"></div>')));
     $allFields->addExtraClass('ss-insert-media');
     $headings = new CompositeField(new LiteralField('Heading', sprintf('<h3 class="htmleditorfield-mediaform-heading insert">%s</h3>', _t('HTMLEditorField.INSERTMEDIA', 'Insert media from')) . sprintf('<h3 class="htmleditorfield-mediaform-heading update">%s</h3>', _t('HTMLEditorField.UpdateMEDIA', 'Update media'))));
     $headings->addExtraClass('cms-content-header');
     $editComposite->addExtraClass('ss-assetuploadfield');
     $fields = new FieldList($headings, $allFields);
     $form = new Form($this->controller, "{$this->name}/MediaForm", $fields, new FieldList());
     $form->unsetValidator();
     $form->disableSecurityToken();
     $form->loadDataFrom($this);
     $form->addExtraClass('htmleditorfield-form htmleditorfield-mediaform cms-dialog-content');
     // Allow other people to extend the fields being added to the imageform
     $this->extend('updateMediaForm', $form);
     return $form;
 }
 public function testLoadDataFromObject()
 {
     $article = $this->objFromFixture('CheckboxSetFieldTest_Article', 'articlewithouttags');
     $articleWithTags = $this->objFromFixture('CheckboxSetFieldTest_Article', 'articlewithtags');
     $tag1 = $this->objFromFixture('CheckboxSetFieldTest_Tag', 'tag1');
     $tag2 = $this->objFromFixture('CheckboxSetFieldTest_Tag', 'tag2');
     $field = new CheckboxSetField("Tags", "Test field", DataObject::get("CheckboxSetFieldTest_Tag")->map());
     /** @skipUpgrade */
     $form = new Form(new Controller(), 'Form', new FieldList($field), new FieldList());
     $form->loadDataFrom($articleWithTags);
     $value = $field->Value();
     sort($value);
     $this->assertEquals(array($tag1->ID, $tag2->ID), $value, 'CheckboxSetField loads data from a manymany relationship in an object through Form->loadDataFrom()');
 }
 /**
  * @return Form
  */
 public function EditForm()
 {
     $file = $this->getItem();
     if (!$file) {
         return $this->httpError(404);
     }
     if ($file instanceof Folder) {
         return $this->httpError(403);
     }
     if (!$file->canEdit()) {
         return $this->httpError(403);
     }
     // Get form components
     $fields = $this->parent->getFileEditFields($file);
     $actions = $this->parent->getFileEditActions($file);
     $validator = $this->parent->getFileEditValidator($file);
     $form = new Form($this, __FUNCTION__, $fields, $actions, $validator);
     $form->loadDataFrom($file);
     $form->addExtraClass('small');
     return $form;
 }
Exemplo n.º 10
0
 public function testLoadDataFromIgnoreFalseish()
 {
     $form = new Form(new Controller(), 'Form', new FieldList(new TextField('Biography', 'Biography', 'Custom Default')), new FieldList());
     $captainNoDetails = $this->objFromFixture('FormTest_Player', 'captainNoDetails');
     $captainWithDetails = $this->objFromFixture('FormTest_Player', 'captainWithDetails');
     $form->loadDataFrom($captainNoDetails, Form::MERGE_IGNORE_FALSEISH);
     $this->assertEquals($form->getData(), array('Biography' => 'Custom Default'), 'LoadDataFrom() doesn\'t overwrite fields when MERGE_IGNORE_FALSEISH set and values are false-ish');
     $form->loadDataFrom($captainWithDetails, Form::MERGE_IGNORE_FALSEISH);
     $this->assertEquals($form->getData(), array('Biography' => 'Bio 1'), 'LoadDataFrom() does overwrite fields when MERGE_IGNORE_FALSEISH set and values arent false-ish');
 }
 /**
  * Builds a Form that mirrors the parent editForm, but with an extra field to collect the ChangeSet ID
  *
  * @param DataObject $object The object we're going to be adding to whichever ChangeSet is chosen
  * @return Form
  */
 public function Form($object)
 {
     $inChangeSets = array_unique(ChangeSetItem::get_for_object($object)->column('ChangeSetID'));
     $changeSets = $this->getAvailableChangeSets()->map();
     $campaignDropdown = DropdownField::create('Campaign', '', $changeSets);
     $campaignDropdown->setEmptyString(_t('Campaigns.AddToCampaignFormFieldLabel', 'Select a Campaign'));
     $campaignDropdown->addExtraClass('noborder');
     $campaignDropdown->addExtraClass('no-chosen');
     $campaignDropdown->setDisabledItems($inChangeSets);
     $fields = new FieldList([$campaignDropdown, HiddenField::create('ID', null, $this->data['ID']), HiddenField::create('ClassName', null, $this->data['ClassName'])]);
     $form = new Form($this->controller, $this->name, $fields, new FieldList($action = AddToCampaignHandler_FormAction::create()));
     $action->addExtraClass('add-to-campaign__action');
     $form->setHTMLID('Form_EditForm_AddToCampaign');
     $form->loadDataFrom($this->data);
     $form->getValidator()->addRequiredField('Campaign');
     $form->addExtraClass('form--no-dividers add-to-campaign__form');
     return $form;
 }
 /**
  * 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;
 }