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];
      $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]);
      if (empty($inputs[$index]['widgets'])) unset($inputs[$index]['widgets']);
      if (empty($inputs[$index]['cardinality'])) $inputs[$index]['cardinality'] = $count;

    return new JsonResponse($inputs);


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Browse other questions tagged or ask your own question.