0

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);
  }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.