diff --git a/_config.php b/_config.php index 9e519d4a..71c7914c 100644 --- a/_config.php +++ b/_config.php @@ -5,5 +5,4 @@ // Avoid creating global variables call_user_func(function () { - }); diff --git a/src/Controllers/LinkFieldController.php b/src/Controllers/LinkFieldController.php new file mode 100644 index 00000000..f3158ace --- /dev/null +++ b/src/Controllers/LinkFieldController.php @@ -0,0 +1,137 @@ + 'apiSaveForm', + # '$FormName/field/$FieldName' => 'formAction', // do we need this? + ]; + + /** + * Routed to be LeftAndMain::schema() + * /admin/linkfield/schema/linkForm/ + * + * Adapted from ElementalAreaController::getElementForm() + * + * @param int $elementID -- TODO not sure if this is required or not + * @return Form + */ + public function getLinkForm(int $linkID): Form + { + $formFactory = FormFactory::create(); + + // this is a hackish way to get the correct DataObject type, I'm not sure what the clean method is + $obj = Link::get()->byID($linkID); + if ($obj && $obj->exists()) { + $className = $obj->ClassName; + $obj = $className::get()->byID($linkID); + } else { + $obj = Link::create(); + } + + /** @var Form $form */ + $form = $formFactory->getForm($this, "LinkForm_$linkID", ['Record' => $obj]); + $form->addExtraClass('link-editor-editform__form'); + + if (!$obj->canEdit()) { + $form->makeReadonly(); + } + + + return $form; + } + + /** + * Code adapted from https://github.com/silverstripe/silverstripe-elemental/pull/1113/files#diff-942115e4b8f6030e4d72ebc2b3a0772ec65e5dfcd08fbd0e677c70d1231daf28R189 + * + * Save an inline edit form for a Link + */ + public function apiSaveForm(HTTPRequest $request): HTTPResponse + { + $id = $this->param('ID'); // $this->urlParams['ID'] + // Validate required input data + if (!$id) { + $this->jsonError(400); + } + + $data = $request->postVars(); + // $data = json_decode($request->getBody(), true); + if (empty($data)) { + $this->jsonError(400); + } + + // Check security token - TODO have temporarily disabled for easier dev + if (false) { + if (!SecurityToken::inst()->checkRequest($request)) { + $this->jsonError(400); + } + } + + /** @var BaseElement $element */ + $link = Link::get()->byID($id); + // Ensure the element can be edited by the current user + if (!$link || !$link->canEdit()) { + $this->jsonError(403); + } + + // get form and populate it with POSTed data + $form = $this->getLinkForm($id); + $form->loadDataFrom($data); + + // validate the Form + $validationResult = $form->validationResult(); + + // validate the DataObject + $element->updateFromFormData($data); + $validationResult->combineAnd($element->validate()); + + // handle validation failure and sent json formschema as response + if (!$validationResult->isValid()) { + // add headers to the request here so you don't need to do it in the client + // in the future I'd like these be the default response from formschema if + // the header wasn't defined + $request->addHeader('X-Formschema-Request', 'auto,schema,state,errors'); + // generate schema response + $url = $this->getRequest()->getURL(); // admin/elemntal-area/api/saveForm/3 + $response = $this->getSchemaResponse($url, $form, $validationResult); + // returning a 400 means that FormBuilder.js::handleSubmit() submitFn() + // that will end up in the catch() .. throw error block and the error + // will just end up in the javascript console + // $response->setStatusCode(400); + // + // return a 200 for now just to get things to work even though it's + // clearly the wrong code. Will require a PR to admin to fix this + $response->setStatusCode(200); + return $response; + } + + $updated = false; + if ($element->isChanged()) { + $element->write(); + // Track changes so we can return to the client + $updated = true; + } + + // create and send success json response + return HTTPResponse::create(json_encode([ + 'status' => 'success', + 'updated' => $updated, + ]))->addHeader('Content-Type', 'application/json'); + } +}