I want to build a REST resource to return Forms as JSON with all labels, help text, default values, etc...
When I use REST's built-in resource /entity/entity_form_display/node.article.default it does not include the translated title, help text, autocomplete paths, or cardinality. Additionally i'm unsure if offering users the required administer node form display
permission is a security issue.
UPDATE: I've finished a GET request built that flattens the Form definition to a simple array, but still hoping there's a more Drupal-standard approach to this that understands the render arrays
i'm parsing, better than I do.
public function get(String $entity_type, String $bundle_or_id) {
$allowedTypes = array('comment'=>1,'node'=>1,'group'=>1,'group_content'=>1,'media'=>1,'user'=>1);
if (!isset($allowedTypes[$entity_type])) {
return $this->returnError('invalid entity_type ' . htmlentities($form_id));
}
if (is_numeric($bundle_or_id)) {
$node = \Drupal::entityTypeManager()->getStorage($entity_type)->load($bundle_or_id);
if (empty($node)) {
return $this->returnError('invalid entity id ' . htmlentities($bundle_or_id));
}
$account = \Drupal\user\Entity\User::load($this->currentUser->id());
$check = $node->access('update', $account);
if (!$check) {
throw new AccessDeniedHttpException();
}
} else {
if (!$this->currentUser->hasPermission('edit own' . $bundle_or_id . ' content')) {
throw new AccessDeniedHttpException();
}
$node = \Drupal::entityTypeManager()->getStorage($entity_type)->create(['type' => $bundle_or_id]);
}
$form = \Drupal::service('entity.form_builder')->getForm($node, 'default');
$fields = \Drupal::service('entity_field.manager')->getFieldDefinitions($entity_type, $node->bundle());
$attrs = array('#ajax', '#autocomplete_route_name', '#value', '#name', '#id', '#cols', '#input', '#options', '#errors', '#attributes', '#placeholder', '#rows', '#default_value', '#type', '#delta', '#required', '#title', 'target_id', 'cardinality', '#type', '#target_type');
$defMethods = array('getLabel'=>'label', 'getDescription'=>'description', 'getType'=>'type', 'getTargetBundle'=>'bundle', 'getCardinality'=>'cardinality', 'getDefaultValueLiteral'=>'default_value', 'getSettings'=>'settings'); // , 'isMultiple'=>'is_multiple' , 'hasCustomStorage'=>'storage', 'getOptionsProivder'=>'options', 'getSchema'=>'schema'
$inputs = array();
foreach ($fields as $field_name => $field_definition) {
if (!isset($form[$field_name])) continue;
//if ($field_definition->isBaseField() === false) continue; // errors out
$field = $form[$field_name];
$index = $field['#weight'];
$inputs[$index] = array('field_name'=>$field_name);
foreach($defMethods as $method=>$label) {
$val = call_user_func(array($field_definition, $method));
$inputs[$index][$label] = ($val instanceof \Drupal\Core\StringTranslation\TranslatableMarkup) ? (string)$val : $val;
}
if (isset($field['#attributes'])) {
$inputs[$index]['#attributes'] = $field['#attributes'];
}
if (!isset($field['widget'])) {
foreach($attrs as $prop) {
if (isset($field[$prop]))
$inputs[$index][$prop] = $field[$prop];
}
continue;
}
$inputs[$index]['widgets'] = array();
$widgets = $field['widget'];
$count = 0;
foreach($widgets as $wi=>$widget) {
if (!is_numeric($wi)) continue;
$value = (isset($widget['value'])) ? $widget['value'] : $widget['target_id'];
$inputs[$index]['widgets'][$wi] = array();
foreach($attrs as $prop) {
if (isset($val[$prop])) {
$inputs[$index]['widgets'][$wi][$prop] = ($value[$prop] instanceof \Drupal\Core\StringTranslation\TranslatableMarkup) ? (string)$value[$prop] : $value[$prop];
}
}
if (empty($inputs[$index]['widgets'][$wi])) unset($inputs[$index]['widgets'][$wi]);
$count++;
}
if (empty($inputs[$index]['widgets'])) unset($inputs[$index]['widgets']);
if (empty($inputs[$index]['cardinality'])) $inputs[$index]['cardinality'] = $count;
}
return new JsonResponse($inputs);
}