From 0fb29a472611c584a13632c7167666666446ab7c Mon Sep 17 00:00:00 2001 From: Guy Sartorelli Date: Tue, 12 Nov 2024 16:30:42 +1300 Subject: [PATCH] NEW Move form schema logic into FormSchemaController --- code/FormSchemaController.php | 162 +++++++++++++++++++++++++++++++++ code/LeftAndMain.php | 163 +--------------------------------- code/ModalController.php | 77 +++------------- 3 files changed, 178 insertions(+), 224 deletions(-) create mode 100644 code/FormSchemaController.php diff --git a/code/FormSchemaController.php b/code/FormSchemaController.php new file mode 100644 index 000000000..b1a6e50ca --- /dev/null +++ b/code/FormSchemaController.php @@ -0,0 +1,162 @@ + 'schema', + 'GET methodSchema/$Method/$FormName/$ItemID' => 'methodSchema', + ]; + + private static array $dependencies = [ + 'FormSchema' => '%$' . FormSchema::class, + ]; + + /** + * Current form schema helper + */ + private ?FormSchema $schema = null; + + /** + * Get form schema helper + */ + public function getFormSchema(): FormSchema + { + if (!$this->schema) { + $this->schema = FormSchema::singleton(); + } + return $this->schema; + } + + /** + * Set form schema helper for this controller + */ + public function setFormSchema(FormSchema $schema): static + { + $this->schema = $schema; + return $this; + } + + /** + * Gets a JSON schema representing the current edit form. + */ + public function schema(HTTPRequest $request): HTTPResponse + { + $formName = $request->param('FormName'); + $itemID = $request->param('ItemID'); + + if (!$formName) { + $this->jsonError(400, 'Missing request params'); + } + + // The getter can accept an ID where the main form action wouldn't + $formMethod = "get{$formName}"; + if (!$this->hasMethod($formMethod)) { + $formMethod = $formName; + if (!$this->hasMethod($formMethod)) { + $this->jsonError(404, 'Form not found'); + } + } + + if (!$this->hasAction($formName)) { + $this->jsonError(401, 'Form not accessible'); + } + + if ($itemID) { + $form = $this->{$formMethod}($itemID); + } else { + $form = $this->{$formMethod}(); + } + $schemaID = $request->getURL(); + return $this->getSchemaResponse($schemaID, $form); + } + + /** + * Get the form schema from a given method. + * The method must return a Form. + */ + public function methodSchema(HTTPRequest $request): HTTPResponse + { + $method = $request->param('Method'); + $formName = $request->param('FormName'); + $itemID = $request->param('ItemID'); + + if (!$formName || !$method) { + $this->jsonError(400, 'Missing request params'); + } + + if (!$this->hasMethod($method)) { + $this->jsonError(404, 'Method not found'); + } + if (!$this->hasAction($method)) { + $this->jsonError(401, 'Method not accessible'); + } + + $methodItem = $this->{$method}(); + if (!$methodItem->hasMethod($formName)) { + $this->jsonError(404, 'Form not found'); + } + if (!$methodItem->hasAction($formName)) { + $this->jsonError(401, 'Form not accessible'); + } + + $form = $methodItem->{$formName}($itemID); + $schemaID = $request->getURL(); + + return $this->getSchemaResponse($schemaID, $form); + } + + /** + * Check if the current request has a X-Formschema-Request header set. + * Used by conditional logic that responds to validation results + */ + protected function getSchemaRequested(): bool + { + $parts = $this->getRequest()->getHeader(static::SCHEMA_HEADER); + return !empty($parts); + } + + /** + * Generate schema for the given form based on the X-Formschema-Request header value + * + * @param string $schemaID ID for this schema. Required. + * @param Form|null $form Required for 'state' or 'schema' response + * @param ValidationResult $errors Required for 'error' response + * @param array $extraData Any extra data to be merged with the schema response + */ + protected function getSchemaResponse(string $schemaID, ?Form $form = null, ValidationResult $errors = null, array $extraData = []): HTTPResponse + { + $parts = $this->getRequest()->getHeader(static::SCHEMA_HEADER); + $data = $this + ->getFormSchema() + ->getMultipartSchema($parts, $schemaID, $form, $errors); + + if ($extraData) { + $data = array_merge($data, $extraData); + } + + $response = new HTTPResponse(json_encode($data)); + $response->addHeader('Content-Type', 'application/json'); + return $response; + } +} diff --git a/code/LeftAndMain.php b/code/LeftAndMain.php index bba5a92a5..4f08a570b 100644 --- a/code/LeftAndMain.php +++ b/code/LeftAndMain.php @@ -56,14 +56,8 @@ * This is essentially an abstract class which should be subclassed. * See {@link CMSMain} for a good example. */ -class LeftAndMain extends AdminController implements PermissionProvider +class LeftAndMain extends FormSchemaController implements PermissionProvider { - - /** - * Form schema header identifier - */ - const SCHEMA_HEADER = 'X-Formschema-Request'; - /** * Enable front-end debugging (increases verbosity) in dev mode. * Will be ignored in live environments. @@ -98,7 +92,6 @@ class LeftAndMain extends AdminController implements PermissionProvider * * @config * @var string - * @deprecated 5.4.0 Will be renamed to model_class */ private static $model_class = null; @@ -110,32 +103,16 @@ class LeftAndMain extends AdminController implements PermissionProvider 'save', 'printable', 'show', - 'Modals', 'EditForm', 'AddForm', 'batchactions', 'BatchActionsForm', - 'schema', - 'methodSchema', - ]; - - private static $url_handlers = [ - 'GET schema/$FormName/$ItemID/$OtherItemID' => 'schema', - 'GET methodSchema/$Method/$FormName/$ItemID' => 'methodSchema', ]; private static $dependencies = [ - 'FormSchema' => '%$' . FormSchema::class, 'VersionProvider' => '%$' . VersionProvider::class, ]; - /** - * Current form schema helper - * - * @var FormSchema - */ - protected $schema = null; - /** * Current pageID for this request * @@ -330,141 +307,19 @@ public function getClientConfig(): array { // Add WYSIWYG link form schema before extensions are applied $this->beforeExtending('updateClientConfig', function (array &$clientConfig): void { + $modalController = ModalController::singleton(); $clientConfig['form'] = [ 'EditorExternalLink' => [ - 'schemaUrl' => $this->Link('methodSchema/Modals/EditorExternalLink'), + 'schemaUrl' => $modalController->Link('schema/EditorExternalLink'), ], 'EditorEmailLink' => [ - 'schemaUrl' => $this->Link('methodSchema/Modals/EditorEmailLink'), + 'schemaUrl' => $modalController->Link('schema/EditorEmailLink'), ], ]; }); return parent::getClientConfig(); } - /** - * Get form schema helper - * - * @return FormSchema - */ - public function getFormSchema() - { - return $this->schema; - } - - /** - * Set form schema helper for this controller - * - * @param FormSchema $schema - * @return $this - */ - public function setFormSchema(FormSchema $schema) - { - $this->schema = $schema; - return $this; - } - - /** - * Gets a JSON schema representing the current edit form. - */ - public function schema(HTTPRequest $request): HTTPResponse - { - $formName = $request->param('FormName'); - $itemID = $request->param('ItemID'); - - if (!$formName) { - $this->jsonError(400, 'Missing request params'); - } - - $formMethod = "get{$formName}"; - if (!$this->hasMethod($formMethod)) { - $this->jsonError(404, 'Form not found'); - } - - if (!$this->hasAction($formName)) { - $this->jsonError(401, 'Form not accessible'); - } - - if ($itemID) { - $form = $this->{$formMethod}($itemID); - } else { - $form = $this->{$formMethod}(); - } - $schemaID = $request->getURL(); - return $this->getSchemaResponse($schemaID, $form); - } - - /** - * Get the form schema from a given method. - * The method must return a Form. - */ - public function methodSchema(HTTPRequest $request): HTTPResponse - { - $method = $request->param('Method'); - $formName = $request->param('FormName'); - $itemID = $request->param('ItemID'); - - if (!$formName || !$method) { - $this->jsonError(400, 'Missing request params'); - } - - if (!$this->hasMethod($method)) { - $this->jsonError(404, 'Method not found'); - } - if (!$this->hasAction($method)) { - $this->jsonError(401, 'Method not accessible'); - } - - $methodItem = $this->{$method}(); - if (!$methodItem->hasMethod($formName)) { - $this->jsonError(404, 'Form not found'); - } - if (!$methodItem->hasAction($formName)) { - $this->jsonError(401, 'Form not accessible'); - } - - $form = $methodItem->{$formName}($itemID); - $schemaID = $request->getURL(); - - return $this->getSchemaResponse($schemaID, $form); - } - - /** - * Check if the current request has a X-Formschema-Request header set. - * Used by conditional logic that responds to validation results - * - * @return bool - */ - protected function getSchemaRequested() - { - $parts = $this->getRequest()->getHeader(static::SCHEMA_HEADER); - return !empty($parts); - } - - /** - * Generate schema for the given form based on the X-Formschema-Request header value - * - * @param string $schemaID ID for this schema. Required. - * @param Form $form Required for 'state' or 'schema' response - * @param ValidationResult $errors Required for 'error' response - * @param array $extraData Any extra data to be merged with the schema response - */ - protected function getSchemaResponse($schemaID, $form = null, ValidationResult $errors = null, $extraData = []): HTTPResponse - { - $parts = $this->getRequest()->getHeader(static::SCHEMA_HEADER); - $data = $this - ->getFormSchema() - ->getMultipartSchema($parts, $schemaID, $form, $errors); - - if ($extraData) { - $data = array_merge($data, $extraData); - } - - $response = new HTTPResponse(json_encode($data)); - $response->addHeader('Content-Type', 'application/json'); - return $response; - } - /** * Try to redirect to an appropriate admin section if we can't access this one */ @@ -1254,16 +1109,6 @@ public function EmptyForm() return $form; } - /** - * Handler for all global modals - * - * @return ModalController - */ - public function Modals() - { - return ModalController::create($this, "Modals"); - } - /** * Renders a panel containing tools which apply to all displayed * "content" (mostly through {@link EditForm()}), for example a tree navigation or a filter panel. diff --git a/code/ModalController.php b/code/ModalController.php index ac6ff3277..34e85e3a3 100644 --- a/code/ModalController.php +++ b/code/ModalController.php @@ -4,101 +4,48 @@ use SilverStripe\Admin\Forms\EditorEmailLinkFormFactory; use SilverStripe\Admin\Forms\EditorExternalLinkFormFactory; -use SilverStripe\Control\Controller; -use SilverStripe\Control\RequestHandler; use SilverStripe\Forms\Form; /** * Parent controller for all CMS-global modals */ -class ModalController extends RequestHandler +class ModalController extends FormSchemaController { + private static ?string $url_segment = 'modals'; + private static $allowed_actions = [ 'EditorExternalLink', 'EditorEmailLink', ]; - public function Link($action = null) - { - return Controller::join_links( - $this->getController()->Link(), - $this->getName(), - $action, - '/' - ); - } - - /** - * @var Controller - */ - protected $controller; - - /** - * @var string - */ - protected $name; - - public function __construct($controller, $name) - { - parent::__construct(); - - $this->controller = $controller; - $this->name = $name; - } - - public function getRequest() - { - return $this->controller->getRequest(); - } - - /** - * @return Controller - */ - public function getController() - { - return $this->controller; - } - - /** - * Get urlsegment - * - * @return string - */ - public function getName() - { - return $this->name; - } + private static string $required_permission_codes = 'CMS_ACCESS'; /** * Builds and returns the external link form - * - * @return Form */ - public function EditorExternalLink() + public function EditorExternalLink(): Form { // Show link text field if requested - $showLinkText = $this->controller->getRequest()->getVar('requireLinkText'); + $showLinkText = $this->getRequest()->getVar('requireLinkText'); $factory = EditorExternalLinkFormFactory::singleton(); return $factory->getForm( - $this->controller, - "{$this->name}/EditorExternalLink", + $this, + __FUNCTION__, [ 'RequireLinkText' => isset($showLinkText) ] ); } /** * Builds and returns the external link form - * - * @return Form */ - public function EditorEmailLink() + public function EditorEmailLink(): Form { // Show link text field if requested - $showLinkText = $this->controller->getRequest()->getVar('requireLinkText'); + $showLinkText = $this->getRequest()->getVar('requireLinkText'); $factory = EditorEmailLinkFormFactory::singleton(); return $factory->getForm( - $this->controller, - "{$this->name}/EditorEmailLink", + $this, + __FUNCTION__, [ 'RequireLinkText' => isset($showLinkText) ] ); }