1 | <?php |
||||
2 | |||||
3 | namespace DNADesign\Elemental\Controllers; |
||||
4 | |||||
5 | use DNADesign\Elemental\Forms\EditFormFactory; |
||||
6 | use DNADesign\Elemental\Models\BaseElement; |
||||
7 | use DNADesign\Elemental\Services\ElementTypeRegistry; |
||||
8 | use Exception; |
||||
9 | use Psr\Log\LoggerInterface; |
||||
10 | use SilverStripe\CMS\Controllers\CMSMain; |
||||
11 | use SilverStripe\Control\HTTPRequest; |
||||
12 | use SilverStripe\Control\HTTPResponse; |
||||
13 | use SilverStripe\Control\HTTPResponse_Exception; |
||||
14 | use SilverStripe\Core\Convert; |
||||
15 | use SilverStripe\Core\Injector\Injector; |
||||
16 | use SilverStripe\Forms\Form; |
||||
17 | use SilverStripe\Security\SecurityToken; |
||||
18 | |||||
19 | /** |
||||
20 | * Controller for "ElementalArea" - handles loading and saving of in-line edit forms in an elemental area in admin |
||||
21 | */ |
||||
22 | class ElementalAreaController extends CMSMain |
||||
23 | { |
||||
24 | const FORM_NAME_TEMPLATE = 'ElementForm_%s'; |
||||
25 | |||||
26 | private static $url_segment = 'elemental-area'; |
||||
27 | |||||
28 | private static $ignore_menuitem = true; |
||||
29 | |||||
30 | private static $url_handlers = [ |
||||
31 | // API access points with structured data |
||||
32 | 'POST api/saveForm/$ID' => 'apiSaveForm', |
||||
33 | '$FormName/field/$FieldName' => 'formAction', |
||||
34 | ]; |
||||
35 | |||||
36 | private static $allowed_actions = [ |
||||
37 | 'elementForm', |
||||
38 | 'schema', |
||||
39 | 'apiSaveForm', |
||||
40 | 'formAction', |
||||
41 | ]; |
||||
42 | |||||
43 | public function getClientConfig() |
||||
44 | { |
||||
45 | $clientConfig = parent::getClientConfig(); |
||||
46 | $clientConfig['form']['elementForm'] = [ |
||||
47 | 'schemaUrl' => $this->Link('schema/elementForm'), |
||||
48 | 'saveUrl' => $this->Link('api/saveForm'), |
||||
49 | 'saveMethod' => 'post', |
||||
50 | 'payloadFormat' => 'json', |
||||
51 | 'formNameTemplate' => sprintf(static::FORM_NAME_TEMPLATE, '{id}'), |
||||
52 | ]; |
||||
53 | |||||
54 | // Configuration that is available per element type |
||||
55 | $clientConfig['elementTypes'] = ElementTypeRegistry::generate()->getDefinitions(); |
||||
56 | |||||
57 | return $clientConfig; |
||||
58 | } |
||||
59 | |||||
60 | /** |
||||
61 | * @param HTTPRequest|null $request |
||||
62 | * @return Form |
||||
63 | * @throws HTTPResponse_Exception |
||||
64 | */ |
||||
65 | public function elementForm(HTTPRequest $request = null) |
||||
66 | { |
||||
67 | // Get ID either from posted back value, or url parameter |
||||
68 | if (!$request) { |
||||
69 | $this->jsonError(400); |
||||
70 | return null; |
||||
71 | } |
||||
72 | $id = $request->param('ID'); |
||||
73 | if (!$id) { |
||||
74 | $this->jsonError(400); |
||||
75 | return null; |
||||
76 | } |
||||
77 | return $this->getElementForm($id) ?: $this->jsonError(404); |
||||
78 | } |
||||
79 | |||||
80 | /** |
||||
81 | * @param int $elementID |
||||
82 | * @return Form|null Returns null if no element exists for the given ID |
||||
83 | */ |
||||
84 | public function getElementForm($elementID) |
||||
85 | { |
||||
86 | $scaffolder = Injector::inst()->get(EditFormFactory::class); |
||||
87 | $element = BaseElement::get()->byID($elementID); |
||||
88 | |||||
89 | if (!$element) { |
||||
90 | return null; |
||||
91 | } |
||||
92 | |||||
93 | /** @var Form $form */ |
||||
94 | $form = $scaffolder->getForm( |
||||
95 | $this, |
||||
96 | sprintf(static::FORM_NAME_TEMPLATE, $elementID), |
||||
97 | ['Record' => $element] |
||||
98 | ); |
||||
99 | |||||
100 | if (!$element->canEdit()) { |
||||
101 | $form->makeReadonly(); |
||||
102 | } |
||||
103 | |||||
104 | $form->addExtraClass('element-editor-editform__form'); |
||||
105 | |||||
106 | return $form; |
||||
107 | } |
||||
108 | |||||
109 | /** |
||||
110 | * Save an inline edit form for a block |
||||
111 | * |
||||
112 | * @param HTTPRequest $request |
||||
113 | * @return HTTPResponse|null JSON encoded string or null if an exception is thrown |
||||
114 | * @throws HTTPResponse_Exception |
||||
115 | */ |
||||
116 | public function apiSaveForm(HTTPRequest $request) |
||||
117 | { |
||||
118 | // Validate required input data |
||||
119 | if (!isset($this->urlParams['ID'])) { |
||||
120 | $this->jsonError(400); |
||||
121 | return null; |
||||
122 | } |
||||
123 | |||||
124 | $data = Convert::json2array($request->getBody()); |
||||
0 ignored issues
–
show
|
|||||
125 | if (empty($data)) { |
||||
126 | $this->jsonError(400); |
||||
127 | return null; |
||||
128 | } |
||||
129 | |||||
130 | // Inject request body as request vars |
||||
131 | foreach ($data as $key => $value) { |
||||
132 | $request->offsetSet($key, $value); |
||||
133 | } |
||||
134 | |||||
135 | // Check security token |
||||
136 | if (!SecurityToken::inst()->checkRequest($request)) { |
||||
137 | $this->jsonError(400); |
||||
138 | return null; |
||||
139 | } |
||||
140 | |||||
141 | /** @var BaseElement $element */ |
||||
142 | $element = BaseElement::get()->byID($this->urlParams['ID']); |
||||
143 | // Ensure the element can be edited by the current user |
||||
144 | if (!$element || !$element->canEdit()) { |
||||
145 | $this->jsonError(403); |
||||
146 | return null; |
||||
147 | } |
||||
148 | |||||
149 | // Remove the pseudo namespaces that were added by the form factory |
||||
150 | $data = $this->removeNamespacesFromFields($data, $element->ID); |
||||
151 | |||||
152 | try { |
||||
153 | $updated = false; |
||||
154 | |||||
155 | $element->updateFromFormData($data); |
||||
156 | // Check if anything will actually be changed before writing |
||||
157 | if ($element->isChanged()) { |
||||
158 | $element->write(); |
||||
159 | // Track changes so we can return to the client |
||||
160 | $updated = true; |
||||
161 | } |
||||
162 | } catch (Exception $ex) { |
||||
163 | Injector::inst()->get(LoggerInterface::class)->debug($ex->getMessage()); |
||||
164 | |||||
165 | $this->jsonError(500); |
||||
166 | return null; |
||||
167 | } |
||||
168 | |||||
169 | $body = Convert::raw2json([ |
||||
0 ignored issues
–
show
The function
SilverStripe\Core\Convert::raw2json() has been deprecated: 4.4.0:5.0.0 Use json_encode() instead
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.
Loading history...
|
|||||
170 | 'status' => 'success', |
||||
171 | 'updated' => $updated, |
||||
172 | ]); |
||||
173 | return HTTPResponse::create($body)->addHeader('Content-Type', 'application/json'); |
||||
174 | } |
||||
175 | |||||
176 | /** |
||||
177 | * Provides action control for form fields that are request handlers when they're used in an in-line edit form. |
||||
178 | * |
||||
179 | * Eg. UploadField |
||||
180 | * |
||||
181 | * @param HTTPRequest $request |
||||
182 | * @return array|HTTPResponse|\SilverStripe\Control\RequestHandler|string |
||||
183 | */ |
||||
184 | public function formAction(HTTPRequest $request) |
||||
185 | { |
||||
186 | $formName = $request->param('FormName'); |
||||
187 | |||||
188 | // Get the element ID from the form name |
||||
189 | $id = substr($formName, strlen(sprintf(self::FORM_NAME_TEMPLATE, ''))); |
||||
190 | $form = $this->getElementForm($id); |
||||
191 | |||||
192 | $field = $form->getRequestHandler()->handleField($request); |
||||
193 | |||||
194 | return $field->handleRequest($request); |
||||
195 | } |
||||
196 | |||||
197 | /** |
||||
198 | * Remove the pseudo namespaces that were added to form fields by the form factory |
||||
199 | * |
||||
200 | * @param array $data |
||||
201 | * @param int $elementID |
||||
202 | * @return array |
||||
203 | */ |
||||
204 | public static function removeNamespacesFromFields(array $data, $elementID) |
||||
205 | { |
||||
206 | $output = []; |
||||
207 | $template = sprintf(EditFormFactory::FIELD_NAMESPACE_TEMPLATE, $elementID, ''); |
||||
208 | foreach ($data as $key => $value) { |
||||
209 | // Only look at fields that match the namespace template |
||||
210 | if (substr($key, 0, strlen($template)) !== $template) { |
||||
211 | continue; |
||||
212 | } |
||||
213 | |||||
214 | $fieldName = substr($key, strlen($template)); |
||||
215 | $output[$fieldName] = $value; |
||||
216 | } |
||||
217 | return $output; |
||||
218 | } |
||||
219 | } |
||||
220 |
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.