public function __construct($name, $title = null, $value = '', $extension = null, $areaCode = null, $countryCode = null) { $this->areaCode = $areaCode; $this->ext = $extension; $this->countryCode = $countryCode; // Build fields $fields = new FieldList(); if ($this->countryCode !== null) { $countryField = NumericField::create($name . '[Country]', false, $countryCode, 4)->addExtraClass('phonenumber-field__country'); $fields->push($countryField); } if ($this->areaCode !== null) { $areaField = NumericField::create($name . '[Area]', false, $areaCode, 4)->addExtraClass('phonenumber-field__area'); $fields->push($areaField); } $numberField = NumericField::create($name . '[Number]', false, null, 10)->addExtraClass('phonenumber-field__number'); $fields->push($numberField); if ($this->ext !== null) { $extensionField = NumericField::create($name . '[Extension]', false, $extension, 6)->addExtraClass('phonenumber-field__extension'); $fields->push($extensionField); } parent::__construct($title, $fields); $this->setName($name); if (isset($value)) { $this->setValue($value); } }
/** * Constructor * * @param Controller $controller The parent controller, necessary to create the appropriate form action tag. * @param string $name The method on the controller that will return this form object. * @param FieldList|FormField $fields All of the fields in the form - a {@link FieldList} of * {@link FormField} objects. * @param FieldList|FormAction $actions All of the action buttons in the form - a {@link FieldList} of */ public function __construct($controller, $name, $fields = null, $actions = null) { if (isset($_REQUEST['BackURL'])) { $backURL = $_REQUEST['BackURL']; } else { $backURL = Session::get('BackURL'); } if (!$fields) { $fields = new FieldList(); // Security/changepassword?h=XXX redirects to Security/changepassword // without GET parameter to avoid potential HTTP referer leakage. // In this case, a user is not logged in, and no 'old password' should be necessary. if (Member::currentUser()) { $fields->push(new PasswordField("OldPassword", _t('Member.YOUROLDPASSWORD', "Your old password"))); } $fields->push(new PasswordField("NewPassword1", _t('Member.NEWPASSWORD', "New Password"))); $fields->push(new PasswordField("NewPassword2", _t('Member.CONFIRMNEWPASSWORD', "Confirm New Password"))); } if (!$actions) { $actions = new FieldList(new FormAction("doChangePassword", _t('Member.BUTTONCHANGEPASSWORD', "Change Password"))); } if (isset($backURL)) { $fields->push(new HiddenField('BackURL', 'BackURL', $backURL)); } parent::__construct($controller, $name, $fields, $actions); }
/** * Return the form's fields - used by the templates * * @return FieldList The form fields */ public function Fields() { foreach ($this->getExtraFields() as $field) { if (!$this->fields->fieldByName($field->getName())) { $this->fields->push($field); } } return $this->fields; }
public function __construct(Controller $controller, $name) { // Set default fields $fields = new FieldList(HiddenField::create("AuthenticationMethod", null, $this->authenticator_class, $this), HiddenField::create('tempid', null, $controller->getRequest()->requestVar('tempid')), PasswordField::create("Password", _t('Member.PASSWORD', 'Password')), LiteralField::create('forgotPassword', sprintf('<p id="ForgotPassword"><a href="%s" target="_top">%s</a></p>', $this->getExternalLink('lostpassword'), _t('CMSMemberLoginForm.BUTTONFORGOTPASSWORD', "Forgot password?")))); if (Security::config()->autologin_enabled) { $fields->push(CheckboxField::create("Remember", _t('Member.REMEMBERME', "Remember me next time?"))); } // Determine returnurl to redirect to parent page $logoutLink = $this->getExternalLink('logout'); if ($returnURL = $controller->getRequest()->requestVar('BackURL')) { $logoutLink = Controller::join_links($logoutLink, '?BackURL=' . urlencode($returnURL)); } // Make actions $actions = new FieldList(FormAction::create('dologin', _t('CMSMemberLoginForm.BUTTONLOGIN', "Log back in")), LiteralField::create('doLogout', sprintf('<p id="doLogout"><a href="%s" target="_top">%s</a></p>', $logoutLink, _t('CMSMemberLoginForm.BUTTONLOGOUT', "Log out")))); parent::__construct($controller, $name, $fields, $actions); }
/** * @param string $name * @param string $title * @param mixed $value * @param Form $form * @param boolean $showOnClick * @param string $titleConfirmField Alternate title (not localizeable) */ public function __construct($name, $title = null, $value = "", $form = null, $showOnClick = false, $titleConfirmField = null) { // Set field title $title = isset($title) ? $title : _t('Member.PASSWORD', 'Password'); // naming with underscores to prevent values from actually being saved somewhere $this->children = new FieldList($this->passwordField = new PasswordField("{$name}[_Password]", $title), $this->confirmPasswordfield = new PasswordField("{$name}[_ConfirmPassword]", isset($titleConfirmField) ? $titleConfirmField : _t('Member.CONFIRMPASSWORD', 'Confirm Password'))); // has to be called in constructor because Field() isn't triggered upon saving the instance if ($showOnClick) { $this->children->push($this->hiddenField = new HiddenField("{$name}[_PasswordFieldVisible]")); } // disable auto complete foreach ($this->children as $child) { /** @var FormField $child */ $child->setAttribute('autocomplete', 'off'); } $this->showOnClick = $showOnClick; parent::__construct($name, $title); $this->setValue($value); }
/** * Generate a CSV import form for a single {@link DataObject} subclass. * * @return Form|false */ public function ImportForm() { $modelSNG = singleton($this->modelClass); $modelName = $modelSNG->i18n_singular_name(); // check if a import form should be generated if (!$this->showImportForm || is_array($this->showImportForm) && !in_array($this->modelClass, $this->showImportForm)) { return false; } $importers = $this->getModelImporters(); if (!$importers || !isset($importers[$this->modelClass])) { return false; } if (!$modelSNG->canCreate(Member::currentUser())) { return false; } $fields = new FieldList(new HiddenField('ClassName', _t('ModelAdmin.CLASSTYPE'), $this->modelClass), new FileField('_CsvFile', false)); // get HTML specification for each import (column names etc.) $importerClass = $importers[$this->modelClass]; /** @var BulkLoader $importer */ $importer = new $importerClass($this->modelClass); $spec = $importer->getImportSpec(); $specFields = new ArrayList(); foreach ($spec['fields'] as $name => $desc) { $specFields->push(new ArrayData(array('Name' => $name, 'Description' => $desc))); } $specRelations = new ArrayList(); foreach ($spec['relations'] as $name => $desc) { $specRelations->push(new ArrayData(array('Name' => $name, 'Description' => $desc))); } $specHTML = $this->customise(array('ClassName' => $this->sanitiseClassName($this->modelClass), 'ModelName' => Convert::raw2att($modelName), 'Fields' => $specFields, 'Relations' => $specRelations))->renderWith($this->getTemplatesWithSuffix('_ImportSpec')); $fields->push(new LiteralField("SpecFor{$modelName}", $specHTML)); $fields->push(new CheckboxField('EmptyBeforeImport', _t('ModelAdmin.EMPTYBEFOREIMPORT', 'Replace data'), false)); $actions = new FieldList(new FormAction('import', _t('ModelAdmin.IMPORT', 'Import from CSV'))); $form = new Form($this, "ImportForm", $fields, $actions); $form->setFormAction(Controller::join_links($this->Link($this->sanitiseClassName($this->modelClass)), 'ImportForm')); $this->extend('updateImportForm', $form); return $form; }
/** * Return a disabled version of this field. Keeps the composition but returns disabled * versions of all the child {@link FormField} objects. * * @return CompositeField */ public function performDisabledTransformation() { $newChildren = new FieldList(); $clone = clone $this; if ($clone->getChildren()) { foreach ($clone->getChildren() as $child) { /** @var FormField $child */ $child = $child->transform(new DisabledTransformation()); $newChildren->push($child); } } $clone->setChildren($newChildren); $clone->setDisabled(true); $clone->addExtraClass($this->extraClass()); $clone->setDescription($this->getDescription()); foreach ($this->attributes as $k => $v) { $clone->setAttribute($k, $v); } return $clone; }
/** * Build the set of form field actions for this DataObject * * @return FieldList */ protected function getFormActions() { $canEdit = $this->record->canEdit(); $canDelete = $this->record->canDelete(); $actions = new FieldList(); if ($this->record->ID !== 0) { if ($canEdit) { $actions->push(FormAction::create('doSave', _t('GridFieldDetailForm.Save', 'Save'))->setUseButtonTag(true)->addExtraClass('ss-ui-action-constructive')->setAttribute('data-icon', 'accept')); } if ($canDelete) { $actions->push(FormAction::create('doDelete', _t('GridFieldDetailForm.Delete', 'Delete'))->setUseButtonTag(true)->addExtraClass('ss-ui-action-destructive action-delete')); } } else { // adding new record //Change the Save label to 'Create' $actions->push(FormAction::create('doSave', _t('GridFieldDetailForm.Create', 'Create'))->setUseButtonTag(true)->addExtraClass('ss-ui-action-constructive')->setAttribute('data-icon', 'add')); // Add a Cancel link which is a button-like link and link back to one level up. $crumbs = $this->Breadcrumbs(); if ($crumbs && $crumbs->count() >= 2) { $oneLevelUp = $crumbs->offsetGet($crumbs->count() - 2); $text = sprintf("<a class=\"%s\" href=\"%s\">%s</a>", "crumb ss-ui-button ss-ui-action-destructive cms-panel-link ui-corner-all", $oneLevelUp->Link, _t('GridFieldDetailForm.CancelBtn', 'Cancel')); $actions->push(new LiteralField('cancelbutton', $text)); } } $this->extend('updateFormActions', $actions); return $actions; }
protected function getFormFields(Controller $controller, $name, $context = []) { $record = $context['Record']; // Build standard fields for all folders / files /** @var File $record */ $fields = new FieldList(HeaderField::create('TitleHeader', $record ? $record->Title : null, 1)->addExtraClass('editor__heading'), LiteralField::create("IconFull", $this->getIconMarkup($record))->addExtraClass('editor__file-preview'), $this->getFormFieldTabs($record, $context)); if ($record) { $fields->push(HiddenField::create('ID', $record->ID)); } $this->invokeWithExtensions('updateFormFields', $fields, $controller, $name, $context); return $fields; }
/** * Transform this FieldList with a given tranform method, * e.g. $this->transform(new ReadonlyTransformation()) * * @param FormTransformation $trans * @return FieldList */ public function transform($trans) { $this->flushFieldsCache(); $newFields = new FieldList(); foreach ($this as $field) { $newFields->push($field->transform($trans)); } return $newFields; }
/** * Note: Doesn't call {@link FormField->setForm()} * on the returned {@link HiddenField}, you'll need to take * care of this yourself. * * @param FieldList $fieldset * @return HiddenField|false */ public function updateFieldSet(&$fieldset) { if (!$fieldset->fieldByName($this->getName())) { $field = new HiddenField($this->getName(), null, $this->getValue()); $fieldset->push($field); return $field; } else { return false; } }
/** * Adds additional form actions * * @param FieldList $actions * @param Controller $controller * @param string $name * @param array $context */ public function updateFormActions(FieldList &$actions, Controller $controller, $name, $context = []) { // Add publish button if record is versioned if (empty($context['Record'])) { return; } $record = $context['Record']; if ($record->hasExtension(Versioned::class)) { $actions->push(new FormAction('publish', 'Publish')); } }
/** * Get list of fields for previewing this records details * * @return FieldList */ protected function getDetailFields() { $fields = new FieldList(ReadonlyField::create("FileType", _t('AssetTableField.TYPE', 'File type'), $this->getFileType()), HTMLReadonlyField::create('ClickableURL', _t('AssetTableField.URL', 'URL'), $this->getExternalLink())); // Get file size if ($this->getSize()) { $fields->insertAfter('FileType', ReadonlyField::create("Size", _t('AssetTableField.SIZE', 'File size'), $this->getSize())); } // Get modified details of local record if ($this->getFile()) { $fields->push(new DateField_Disabled("Created", _t('AssetTableField.CREATED', 'First uploaded'), $this->getFile()->Created)); $fields->push(new DateField_Disabled("LastEdited", _t('AssetTableField.LASTEDIT', 'Last changed'), $this->getFile()->LastEdited)); } return $fields; }
/** * Caution: Only call on instances, not through a singleton. * The "root group" fields will be created through {@link SecurityAdmin->EditForm()}. * * @return FieldList */ public function getCMSFields() { $fields = new FieldList(new TabSet("Root", new Tab('Members', _t('SecurityAdmin.MEMBERS', 'Members'), new TextField("Title", $this->fieldLabel('Title')), $parentidfield = DropdownField::create('ParentID', $this->fieldLabel('Parent'), Group::get()->exclude('ID', $this->ID)->map('ID', 'Breadcrumbs'))->setEmptyString(' '), new TextareaField('Description', $this->fieldLabel('Description'))), $permissionsTab = new Tab('Permissions', _t('SecurityAdmin.PERMISSIONS', 'Permissions'), $permissionsField = new PermissionCheckboxSetField('Permissions', false, 'SilverStripe\\Security\\Permission', 'GroupID', $this)))); $parentidfield->setDescription(_t('Group.GroupReminder', 'If you choose a parent group, this group will take all it\'s roles')); // Filter permissions // TODO SecurityAdmin coupling, not easy to get to the form fields through GridFieldDetailForm $permissionsField->setHiddenPermissions((array) Config::inst()->get('SilverStripe\\Admin\\SecurityAdmin', 'hidden_permissions')); if ($this->ID) { $group = $this; $config = GridFieldConfig_RelationEditor::create(); $config->addComponent(new GridFieldButtonRow('after')); $config->addComponents(new GridFieldExportButton('buttons-after-left')); $config->addComponents(new GridFieldPrintButton('buttons-after-left')); /** @var GridFieldAddExistingAutocompleter $autocompleter */ $autocompleter = $config->getComponentByType('SilverStripe\\Forms\\GridField\\GridFieldAddExistingAutocompleter'); /** @skipUpgrade */ $autocompleter->setResultsFormat('$Title ($Email)')->setSearchFields(array('FirstName', 'Surname', 'Email')); /** @var GridFieldDetailForm $detailForm */ $detailForm = $config->getComponentByType('SilverStripe\\Forms\\GridField\\GridFieldDetailForm'); $detailForm->setValidator(Member_Validator::create())->setItemEditFormCallback(function ($form, $component) use($group) { /** @var Form $form */ $record = $form->getRecord(); $groupsField = $form->Fields()->dataFieldByName('DirectGroups'); if ($groupsField) { // If new records are created in a group context, // set this group by default. if ($record && !$record->ID) { $groupsField->setValue($group->ID); } elseif ($record && $record->ID) { // TODO Mark disabled once chosen.js supports it // $groupsField->setDisabledItems(array($group->ID)); $form->Fields()->replaceField('DirectGroups', $groupsField->performReadonlyTransformation()); } } }); $memberList = GridField::create('Members', false, $this->DirectMembers(), $config)->addExtraClass('members_grid'); // @todo Implement permission checking on GridField //$memberList->setPermissions(array('edit', 'delete', 'export', 'add', 'inlineadd')); $fields->addFieldToTab('Root.Members', $memberList); } // Only add a dropdown for HTML editor configurations if more than one is available. // Otherwise Member->getHtmlEditorConfigForCMS() will default to the 'cms' configuration. $editorConfigMap = HTMLEditorConfig::get_available_configs_map(); if (count($editorConfigMap) > 1) { $fields->addFieldToTab('Root.Permissions', new DropdownField('HtmlEditorConfig', 'HTML Editor Configuration', $editorConfigMap), 'Permissions'); } if (!Permission::check('EDIT_PERMISSIONS')) { $fields->removeFieldFromTab('Root', 'Permissions'); } // Only show the "Roles" tab if permissions are granted to edit them, // and at least one role exists if (Permission::check('APPLY_ROLES') && DataObject::get('SilverStripe\\Security\\PermissionRole')) { $fields->findOrMakeTab('Root.Roles', _t('SecurityAdmin.ROLES', 'Roles')); $fields->addFieldToTab('Root.Roles', new LiteralField("", "<p>" . _t('SecurityAdmin.ROLESDESCRIPTION', "Roles are predefined sets of permissions, and can be assigned to groups.<br />" . "They are inherited from parent groups if required.") . '<br />' . sprintf('<a href="%s" class="add-role">%s</a>', SecurityAdmin::singleton()->Link('show/root#Root_Roles'), _t('Group.RolesAddEditLink', 'Manage roles')) . "</p>")); // Add roles (and disable all checkboxes for inherited roles) $allRoles = PermissionRole::get(); if (!Permission::check('ADMIN')) { $allRoles = $allRoles->filter("OnlyAdminCanApply", 0); } if ($this->ID) { $groupRoles = $this->Roles(); $inheritedRoles = new ArrayList(); $ancestors = $this->getAncestors(); foreach ($ancestors as $ancestor) { $ancestorRoles = $ancestor->Roles(); if ($ancestorRoles) { $inheritedRoles->merge($ancestorRoles); } } $groupRoleIDs = $groupRoles->column('ID') + $inheritedRoles->column('ID'); $inheritedRoleIDs = $inheritedRoles->column('ID'); } else { $groupRoleIDs = array(); $inheritedRoleIDs = array(); } $rolesField = ListboxField::create('Roles', false, $allRoles->map()->toArray())->setDefaultItems($groupRoleIDs)->setAttribute('data-placeholder', _t('Group.AddRole', 'Add a role for this group'))->setDisabledItems($inheritedRoleIDs); if (!$allRoles->count()) { $rolesField->setAttribute('data-placeholder', _t('Group.NoRoles', 'No roles found')); } $fields->addFieldToTab('Root.Roles', $rolesField); } $fields->push($idField = new HiddenField("ID")); $this->extend('updateCMSFields', $fields); return $fields; }
/** * Determine which properties on the DataObject are * searchable, and map them to their default {@link FormField} * representations. Used for scaffolding a searchform for {@link ModelAdmin}. * * Some additional logic is included for switching field labels, based on * how generic or specific the field type is. * * Used by {@link SearchContext}. * * @param array $_params * 'fieldClasses': Associative array of field names as keys and FormField classes as values * 'restrictFields': Numeric array of a field name whitelist * @return FieldList */ public function scaffoldSearchFields($_params = null) { $params = array_merge(array('fieldClasses' => false, 'restrictFields' => false), (array) $_params); $fields = new FieldList(); foreach ($this->searchableFields() as $fieldName => $spec) { if ($params['restrictFields'] && !in_array($fieldName, $params['restrictFields'])) { continue; } // If a custom fieldclass is provided as a string, use it $field = null; if ($params['fieldClasses'] && isset($params['fieldClasses'][$fieldName])) { $fieldClass = $params['fieldClasses'][$fieldName]; $field = new $fieldClass($fieldName); // If we explicitly set a field, then construct that } else { if (isset($spec['field'])) { // If it's a string, use it as a class name and construct if (is_string($spec['field'])) { $fieldClass = $spec['field']; $field = new $fieldClass($fieldName); // If it's a FormField object, then just use that object directly. } else { if ($spec['field'] instanceof FormField) { $field = $spec['field']; // Otherwise we have a bug } else { user_error("Bad value for searchable_fields, 'field' value: " . var_export($spec['field'], true), E_USER_WARNING); } } // Otherwise, use the database field's scaffolder } else { $field = $this->relObject($fieldName)->scaffoldSearchField(); } } // Allow fields to opt out of search if (!$field) { continue; } if (strstr($fieldName, '.')) { $field->setName(str_replace('.', '__', $fieldName)); } $field->setTitle($spec['title']); $fields->push($field); } return $fields; }
/** * Adds a new {@link FormField} instance. * * @param FormField $field */ public function addField($field) { $this->fields->push($field); }
/** * FieldList::changeFieldOrder() should place specified fields in given * order then add any unspecified remainders at the end. Can be given an * array or list of arguments. */ public function testChangeFieldOrder() { $fieldNames = array('A', 'B', 'C', 'D', 'E'); $setArray = new FieldList(); $setArgs = new FieldList(); foreach ($fieldNames as $fN) { $setArray->push(new TextField($fN)); $setArgs->push(new TextField($fN)); } $setArray->changeFieldOrder(array('D', 'B', 'E')); $this->assertEquals(0, $setArray->fieldPosition('D')); $this->assertEquals(1, $setArray->fieldPosition('B')); $this->assertEquals(2, $setArray->fieldPosition('E')); $this->assertEquals(3, $setArray->fieldPosition('A')); $this->assertEquals(4, $setArray->fieldPosition('C')); $setArgs->changeFieldOrder('D', 'B', 'E'); $this->assertEquals(0, $setArgs->fieldPosition('D')); $this->assertEquals(1, $setArgs->fieldPosition('B')); $this->assertEquals(2, $setArgs->fieldPosition('E')); $this->assertEquals(3, $setArgs->fieldPosition('A')); $this->assertEquals(4, $setArgs->fieldPosition('C')); unset($setArray, $setArgs); }
/** * Gets the form fields as defined through the metadata * on {@link $obj} and the custom parameters passed to FormScaffolder. * Depending on those parameters, the fields can be used in ajax-context, * contain {@link TabSet}s etc. * * @return FieldList */ public function getFieldList() { $fields = new FieldList(); // tabbed or untabbed if ($this->tabbed) { $fields->push(new TabSet("Root", $mainTab = new Tab("Main"))); $mainTab->setTitle(_t('SiteTree.TABMAIN', "Main")); } // Add logical fields directly specified in db config foreach ($this->obj->config()->db as $fieldName => $fieldType) { // Skip restricted fields if ($this->restrictFields && !in_array($fieldName, $this->restrictFields)) { continue; } // @todo Pass localized title if ($this->fieldClasses && isset($this->fieldClasses[$fieldName])) { $fieldClass = $this->fieldClasses[$fieldName]; $fieldObject = new $fieldClass($fieldName); } else { $fieldObject = $this->obj->dbObject($fieldName)->scaffoldFormField(null, $this->getParamsArray()); } // Allow fields to opt-out of scaffolding if (!$fieldObject) { continue; } $fieldObject->setTitle($this->obj->fieldLabel($fieldName)); if ($this->tabbed) { $fields->addFieldToTab("Root.Main", $fieldObject); } else { $fields->push($fieldObject); } } // add has_one relation fields if ($this->obj->hasOne()) { foreach ($this->obj->hasOne() as $relationship => $component) { if ($this->restrictFields && !in_array($relationship, $this->restrictFields)) { continue; } $fieldName = $component === 'SilverStripe\\ORM\\DataObject' ? $relationship : "{$relationship}ID"; if ($this->fieldClasses && isset($this->fieldClasses[$fieldName])) { $fieldClass = $this->fieldClasses[$fieldName]; $hasOneField = new $fieldClass($fieldName); } else { $hasOneField = $this->obj->dbObject($fieldName)->scaffoldFormField(null, $this->getParamsArray()); } if (empty($hasOneField)) { continue; } // Allow fields to opt out of scaffolding $hasOneField->setTitle($this->obj->fieldLabel($relationship)); if ($this->tabbed) { $fields->addFieldToTab("Root.Main", $hasOneField); } else { $fields->push($hasOneField); } } } // only add relational fields if an ID is present if ($this->obj->ID) { // add has_many relation fields if ($this->obj->hasMany() && ($this->includeRelations === true || isset($this->includeRelations['has_many']))) { foreach ($this->obj->hasMany() as $relationship => $component) { if ($this->tabbed) { $fields->findOrMakeTab("Root.{$relationship}", $this->obj->fieldLabel($relationship)); } $fieldClass = isset($this->fieldClasses[$relationship]) ? $this->fieldClasses[$relationship] : 'SilverStripe\\Forms\\GridField\\GridField'; /** @var GridField $grid */ $grid = Object::create($fieldClass, $relationship, $this->obj->fieldLabel($relationship), $this->obj->{$relationship}(), GridFieldConfig_RelationEditor::create()); if ($this->tabbed) { $fields->addFieldToTab("Root.{$relationship}", $grid); } else { $fields->push($grid); } } } if ($this->obj->manyMany() && ($this->includeRelations === true || isset($this->includeRelations['many_many']))) { foreach ($this->obj->manyMany() as $relationship => $component) { if ($this->tabbed) { $fields->findOrMakeTab("Root.{$relationship}", $this->obj->fieldLabel($relationship)); } $fieldClass = isset($this->fieldClasses[$relationship]) ? $this->fieldClasses[$relationship] : 'SilverStripe\\Forms\\GridField\\GridField'; /** @var GridField $grid */ $grid = Object::create($fieldClass, $relationship, $this->obj->fieldLabel($relationship), $this->obj->{$relationship}(), GridFieldConfig_RelationEditor::create()); if ($this->tabbed) { $fields->addFieldToTab("Root.{$relationship}", $grid); } else { $fields->push($grid); } } } } return $fields; }