-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
NEW LinkFieldController to handle FormSchema
- Loading branch information
1 parent
f0a3b25
commit 6011f97
Showing
2 changed files
with
137 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,5 +5,4 @@ | |
|
||
// Avoid creating global variables | ||
call_user_func(function () { | ||
|
||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
<?php | ||
|
||
namespace SilverStripe\LinkField\Controllers; | ||
|
||
use SilverStripe\Admin\LeftAndMain; | ||
use SilverStripe\Control\HTTPRequest; | ||
use SilverStripe\Control\HTTPResponse; | ||
use SilverStripe\Core\Injector\Injector; | ||
use SilverStripe\LinkField\Form\FormFactory; | ||
use SilverStripe\Forms\Form; | ||
use SilverStripe\LinkField\Models\Link; | ||
use SilverStripe\Security\SecurityToken; | ||
use SilverStripe\ORM\ValidationResult; | ||
|
||
class LinkFieldController extends LeftAndMain | ||
{ | ||
private static $url_segment = 'linkfield'; | ||
|
||
// copying ElementalAreaController | ||
private static $url_handlers = [ | ||
// API access points with structured data | ||
'POST api/saveForm/$ID' => 'apiSaveForm', | ||
# '$FormName/field/$FieldName' => 'formAction', // do we need this? | ||
]; | ||
|
||
/** | ||
* Routed to be LeftAndMain::schema() | ||
* /admin/linkfield/schema/linkForm/<linkID> | ||
* | ||
* 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'); | ||
} | ||
} |