silverstripe-framework/Forms/DefaultFormFactory.php
Damian Mooyman 840f275235 API Created a generic FormFactory interface (#6178)
Created a generic DataObject FormFactory interface that can be substituted in place of getCMSFields. Different FormFactories can depend on different kinds of context, such as
'Record' or 'Controller' - it's the responsibility of the code calling the factory to interpret and
supply this context.

The expected use-case is that rather than overriding getCMSFields(), developers can
change CMS UIs by manipulating the FormFactory associated with the given DataObject.

This is an experimental UI and may change before 4.0 stable is released.
2016-10-20 12:42:24 +13:00

109 lines
3.0 KiB
PHP

<?php
namespace SilverStripe\Forms;
use InvalidArgumentException;
use SilverStripe\Control\Controller;
use SilverStripe\Core\Extensible;
/**
* Default form builder class.
*
* @internal WARNING: Experimental and volatile API.
*
* Allows extension by either controller or object via the following methods:
* - updateFormActions
* - updateFormValidator
* - updateFormFields
* - updateForm
*/
class DefaultFormFactory implements FormFactory {
use Extensible;
public function __construct() {
$this->constructExtensions();
}
public function getForm(Controller $controller, $name = FormFactory::DEFAULT_NAME, $context = [])
{
// Validate context
foreach($this->getRequiredContext() as $required) {
if (!isset($context[$required])) {
throw new InvalidArgumentException("Missing required context $required");
}
}
$fields = $this->getFormFields($controller, $name, $context);
$actions = $this->getFormActions($controller, $name, $context);
$validator = $this->getFormValidator($controller, $name, $context);
$form = Form::create($controller, $name, $fields, $actions, $validator);
// Extend form
$this->invokeWithExtensions('updateForm', $form, $controller, $name, $context);
// Populate form from record
$form->loadDataFrom($context['Record']);
return $form;
}
/**
* Build field list for this form
*
* @param Controller $controller
* @param string $name
* @param array $context
* @return FieldList
*/
protected function getFormFields(Controller $controller, $name, $context = []) {
// Fall back to standard "getCMSFields" which itself uses the FormScaffolder as a fallback
// @todo Deprecate or formalise support for getCMSFields()
$fields = $context['Record']->getCMSFields();
$this->invokeWithExtensions('updateFormFields', $fields, $controller, $name, $context);
return $fields;
}
/**
* Build list of actions for this form
*
* @param Controller $controller
* @param string $name
* @param array $context
* @return FieldList
*/
protected function getFormActions(Controller $controller, $name, $context = []) {
// @todo Deprecate or formalise support for getCMSActions()
$actions = $context['Record']->getCMSActions();
$this->invokeWithExtensions('updateFormActions', $actions, $controller, $name, $context);
return $actions;
}
/**
* @param Controller $controller
* @param string $name
* @param array $context
* @return null|Validator
*/
protected function getFormValidator(Controller $controller, $name, $context = []) {
$validator = null;
if ($context['Record']->hasMethod('getCMSValidator')) {
// @todo Deprecate or formalise support for getCMSValidator()
$validator = $context['Record']->getCMSValidator();
}
// Extend validator
$this->invokeWithExtensions('updateFormValidator', $validator, $controller, $name, $context);
return $validator;
}
/**
* Return list of mandatory context keys
*
* @return mixed
*/
public function getRequiredContext()
{
return ['Record'];
}
}