You are here

class ContentEntityNormalizer in Replication 8

Same name and namespace in other branches
  1. 8.2 src/Normalizer/ContentEntityNormalizer.php \Drupal\replication\Normalizer\ContentEntityNormalizer

Hierarchy

Expanded class hierarchy of ContentEntityNormalizer

1 string reference to 'ContentEntityNormalizer'
replication.services.yml in ./replication.services.yml
replication.services.yml
1 service uses ContentEntityNormalizer
replication.normalizer.content_entity in ./replication.services.yml
Drupal\replication\Normalizer\ContentEntityNormalizer

File

src/Normalizer/ContentEntityNormalizer.php, line 29

Namespace

Drupal\replication\Normalizer
View source
class ContentEntityNormalizer extends NormalizerBase implements DenormalizerInterface {
  use FieldableEntityNormalizerTrait;

  /**
   * @var string[]
   */
  protected $supportedInterfaceOrClass = [
    'Drupal\\Core\\Entity\\ContentEntityInterface',
  ];

  /**
   * @var \Drupal\multiversion\Entity\Index\MultiversionIndexFactory
   */
  protected $indexFactory;

  /**
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $languageManager;

  /**
   * @var \Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface
   */
  protected $selectionManager;

  /**
   * @var \Drupal\replication\UsersMapping
   */
  protected $usersMapping;

  /**
   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
   */
  protected $dispatcher;

  /**
   * @var string[]
   */
  protected $format = [
    'json',
  ];

  /**
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  private $moduleHandler;

  /**
   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
   * @param \Drupal\multiversion\Entity\Index\MultiversionIndexFactory $index_factory
   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
   * @param \Drupal\replication\UsersMapping $users_mapping
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   * @param \Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface $selection_manager
   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
   */
  public function __construct(EntityManagerInterface $entity_manager, MultiversionIndexFactory $index_factory, LanguageManagerInterface $language_manager, UsersMapping $users_mapping, ModuleHandlerInterface $module_handler, SelectionPluginManagerInterface $selection_manager = NULL, EventDispatcherInterface $event_dispatcher = NULL) {
    $this->entityManager = $entity_manager;
    $this->indexFactory = $index_factory;
    $this->languageManager = $language_manager;
    $this->usersMapping = $users_mapping;
    $this->moduleHandler = $module_handler;
    $this->selectionManager = $selection_manager;
    $this->dispatcher = $event_dispatcher;
  }

  /**
   * {@inheritdoc}
   */
  public function normalize($entity, $format = NULL, array $context = []) {
    $workspace = isset($entity->workspace->entity) ? $entity->workspace->entity : null;
    $rev_tree_index = $this->indexFactory
      ->get('multiversion.entity_index.rev.tree', $workspace);
    $entity_type_id = $context['entity_type'] = $entity
      ->getEntityTypeId();
    $entity_type = $this->entityManager
      ->getDefinition($entity_type_id);
    $id_key = $entity_type
      ->getKey('id');
    $revision_key = $entity_type
      ->getKey('revision');
    $uuid_key = $entity_type
      ->getKey('uuid');
    $entity_uuid = $entity
      ->uuid();
    $entity_default_language = $entity
      ->language();
    $entity_languages = $entity
      ->getTranslationLanguages();

    // Create the basic data array with JSON-LD data.
    $data = [
      '@context' => [
        '_id' => '@id',
        '@language' => $entity_default_language
          ->getId(),
      ],
      '@type' => $entity_type_id,
      '_id' => $entity_uuid,
    ];

    // New or mocked entities might not have a rev yet.
    if (!empty($entity->_rev->value)) {
      $data['_rev'] = $entity->_rev->value;
    }

    // Loop through each language of the entity
    $field_definitions = $entity
      ->getFieldDefinitions();
    foreach ($entity_languages as $entity_language) {
      $translation = $entity
        ->getTranslation($entity_language
        ->getId());

      // Add the default language
      $data[$entity_language
        ->getId()] = [
        '@context' => [
          '@language' => $entity_language
            ->getId(),
        ],
      ];
      foreach ($translation as $name => $field) {

        // Add data for each field (through the field's normalizer.
        $field_type = $field_definitions[$name]
          ->getType();
        $items = $this->serializer
          ->normalize($field, $format, $context);
        if ($field_type == 'password') {
          continue;
        }
        $data[$entity_language
          ->getId()][$name] = $items;
      }

      // Override the normalization for the _deleted special field, just so that we
      // follow the API spec.
      if (isset($translation->_deleted->value) && $translation->_deleted->value == TRUE) {
        $data[$entity_language
          ->getId()]['_deleted'] = TRUE;
        $data['_deleted'] = TRUE;
      }
      elseif (isset($data[$entity_language
        ->getId()]['_deleted'])) {
        unset($data[$entity_language
          ->getId()]['_deleted']);
      }
    }

    // @todo: Needs test.}
    // Normalize the $entity->_rev->revisions value.
    if (!empty($entity->_rev->revisions)) {
      $data['_revisions']['ids'] = $entity->_rev->revisions;
      $data['_revisions']['start'] = count($data['_revisions']['ids']);
    }
    if (!empty($context['query']['conflicts'])) {
      $conflicts = $rev_tree_index
        ->getConflicts($entity_uuid);
      foreach ($conflicts as $rev => $status) {
        $data['_conflicts'][] = $rev;
      }
    }

    // Finally we remove certain fields that are "local" to this host.
    unset($data['workspace'], $data[$id_key], $data[$revision_key], $data[$uuid_key]);
    foreach ($entity_languages as $entity_language) {
      $langcode = $entity_language
        ->getId();
      unset($data[$langcode]['workspace'], $data[$langcode][$id_key], $data[$langcode][$revision_key], $data[$langcode][$uuid_key]);
    }
    $event = new ReplicationContentDataAlterEvent($entity, $data, $format, $context);
    $this->dispatcher
      ->dispatch(ReplicationDataEvents::ALTER_CONTENT_DATA, $event);
    return $event
      ->getData();
  }

  /**
   * {@inheritdoc}
   */
  public function denormalize($data, $class, $format = NULL, array $context = []) {

    // Make sure these values start as NULL
    $entity_type_id = NULL;
    $entity_uuid = NULL;
    $entity_id = NULL;

    // Get the default language of the entity
    $default_langcode = $data['@context']['@language'];

    // Get all of the configured languages of the site
    $site_languages = $this->languageManager
      ->getLanguages();

    // Resolve the UUID.
    if (empty($entity_uuid) && !empty($data['_id'])) {
      $entity_uuid = $data['_id'];
    }
    else {
      throw new UnexpectedValueException('The uuid value is missing.');
    }

    // Resolve the entity type ID.
    if (isset($data['@type'])) {
      $entity_type_id = $data['@type'];
    }
    elseif (!empty($context['entity_type'])) {
      $entity_type_id = $context['entity_type'];
    }

    // Map data from the UUID index.
    // @todo: {@link https://www.drupal.org/node/2599938 Needs test.}
    if (!empty($entity_uuid)) {
      $uuid_index = isset($context['workspace']) && $context['workspace'] instanceof WorkspaceInterface ? $this->indexFactory
        ->get('multiversion.entity_index.uuid', $context['workspace']) : $this->indexFactory
        ->get('multiversion.entity_index.uuid');
      if ($record = $uuid_index
        ->get($entity_uuid)) {
        $entity_id = $record['entity_id'];
        if (empty($entity_type_id)) {
          $entity_type_id = $record['entity_type_id'];
        }
        elseif ($entity_type_id != $record['entity_type_id']) {
          throw new UnexpectedValueException('The entity_type value does not match the existing UUID record.');
        }
      }
    }
    if (empty($entity_type_id)) {
      throw new UnexpectedValueException('The entity_type value is missing.');
    }

    // Add the _rev field to the $data array.
    $rev = null;
    if (isset($data['_rev'])) {
      $rev = $data['_rev'];
    }
    $revisions = [];
    if (isset($data['_revisions']['start']) && isset($data['_revisions']['ids'])) {
      $revisions = $data['_revisions'];
    }
    $entity_type = $this->entityManager
      ->getDefinition($entity_type_id);
    $id_key = $entity_type
      ->getKey('id');
    $revision_key = $entity_type
      ->getKey('revision');
    $bundle_key = $entity_type
      ->getKey('bundle');
    $translations = [];
    foreach ($data as $key => $translation) {

      // Skip any keys that start with '_' or '@'.
      if (in_array($key[0], [
        '_',
        '@',
      ])) {
        continue;
      }
      elseif (isset($site_languages[$key]) || $key === LanguageInterface::LANGCODE_NOT_SPECIFIED || $key === LanguageInterface::LANGCODE_NOT_APPLICABLE) {
        $context['language'] = $key;
        $translations[$key] = $this
          ->denormalizeTranslation($translation, $entity_id, $entity_uuid, $entity_type_id, $bundle_key, $entity_type, $id_key, $context, $rev, $revisions);
      }
      elseif (is_array($translation) && $this->moduleHandler
        ->moduleExists('language')) {
        $language = ConfigurableLanguage::createFromLangcode($key);
        $language
          ->save();
        $context['language'] = $key;
        $translations[$key] = $this
          ->denormalizeTranslation($translation, $entity_id, $entity_uuid, $entity_type_id, $bundle_key, $entity_type, $id_key, $context, $rev, $revisions);
      }
    }

    // @todo {@link https://www.drupal.org/node/2599926 Use the passed $class to instantiate the entity.}
    $entity = NULL;
    if ($entity_id && $entity_type_id != 'file' && !empty($translations[$default_langcode])) {
      $entity = $this
        ->createEntityInstance($translations[$default_langcode], $entity_type, $format, $context);
    }
    elseif ($entity_type_id == 'file' && !empty($translations[$default_langcode])) {
      unset($translations[$default_langcode][$id_key], $translations[$default_langcode][$revision_key]);
      $translations[$default_langcode]['status'][0]['value'] = FILE_STATUS_PERMANENT;
      $translations[$default_langcode]['uid'][0]['target_id'] = $this->usersMapping
        ->getUidFromConfig();
      $entity = $this
        ->createEntityInstance($translations[$default_langcode], $entity_type, $format, $context);
    }
    elseif (!empty($translations[$default_langcode])) {
      unset($translations[$default_langcode][$id_key], $translations[$default_langcode][$revision_key]);
      $entity = $this
        ->createEntityInstance($translations[$default_langcode], $entity_type, $format, $context);
    }
    if ($entity instanceof ContentEntityInterface) {
      foreach ($site_languages as $site_language) {
        $langcode = $site_language
          ->getId();
        if ($entity
          ->language()
          ->getId() != $langcode && isset($translations[$langcode]) && !$entity
          ->hasTranslation($langcode)) {
          $entity
            ->addTranslation($langcode, $translations[$langcode]);
        }
      }
    }
    if ($entity_id && $entity) {
      $entity
        ->enforceIsNew(FALSE);
      $entity
        ->setNewRevision(FALSE);
      $entity->_rev->is_stub = FALSE;
    }
    Cache::invalidateTags([
      $entity_type_id . '_list',
    ]);
    return $entity;
  }

  /**
   * @param $translation
   * @param int $entity_id
   * @param \string $entity_uuid
   * @param string $entity_type_id
   * @param $bundle_key
   * @param $entity_type
   * @param $id_key
   * @param $context
   * @param $rev
   * @param array $revisions
   * @return mixed
   */
  private function denormalizeTranslation($translation, $entity_id, $entity_uuid, $entity_type_id, $bundle_key, $entity_type, $id_key, $context, $rev = null, array $revisions = []) {

    // Add the _rev field to the $translation array.
    if (isset($rev)) {
      $translation['_rev'] = [
        [
          'value' => $rev,
        ],
      ];
    }
    if (isset($revisions['start']) && isset($revisions['ids'])) {
      $translation['_rev'][0]['revisions'] = $revisions['ids'];
    }
    if (isset($entity_uuid)) {
      $translation['uuid'][0]['value'] = $entity_uuid;
    }

    // We need to nest the data for the _deleted field in its Drupal-specific
    // structure since it's un-nested to follow the API spec when normalized.
    // @todo {@link https://www.drupal.org/node/2599938 Needs test for situation when a replication overwrites delete.}
    $deleted = isset($translation['_deleted']) ? $translation['_deleted'] : FALSE;
    $translation['_deleted'] = [
      [
        'value' => $deleted,
      ],
    ];
    if ($entity_id) {

      // @todo {@link https://www.drupal.org/node/2599938 Needs test.}
      $translation[$id_key] = [
        'value' => $entity_id,
      ];
    }
    $bundle_id = $entity_type_id;
    if ($entity_type
      ->hasKey('bundle')) {
      if (!empty($translation[$bundle_key][0]['value'])) {

        // Add bundle info when entity is not new.
        $bundle_id = $translation[$bundle_key][0]['value'];
        $translation[$bundle_key] = $bundle_id;
      }
      elseif (!empty($translation[$bundle_key][0]['target_id'])) {

        // Add bundle info when entity is new.
        $bundle_id = $translation[$bundle_key][0]['target_id'];
        $translation[$bundle_key] = $bundle_id;
      }
    }

    // Denormalize entity reference fields.
    foreach ($translation as $field_name => $field_info) {
      if (!is_array($field_info)) {
        continue;
      }
      foreach ($field_info as $delta => $item) {
        if (!is_array($item)) {
          continue;
        }
        if (isset($item['target_uuid'])) {
          $translation[$field_name][$delta] = $item;
          $fields = $this->entityManager
            ->getFieldDefinitions($entity_type_id, $bundle_id);

          // Figure out what bundle we should use when creating the stub.
          $settings = $fields[$field_name]
            ->getSettings();

          // Find the target entity type and target bundle IDs and figure out if
          // the referenced entity exists or not.
          $target_entity_uuid = $item['target_uuid'];

          // Denormalize link field type as an entity reference field if it
          // has info about 'target_uuid' and 'entity_type_id'. These are used
          // to denormalize 'uri' in formats like 'entity:ENTITY_TYPE/ID'.
          $type = $fields[$field_name]
            ->getType();
          if ($type == 'link' && isset($item['entity_type_id'])) {
            $target_entity_type_id = $item['entity_type_id'];
          }
          else {
            $target_entity_type_id = $settings['target_type'];
          }
          if ($target_entity_type_id === 'user') {
            $translation[$field_name] = $this->usersMapping
              ->mapReferenceField($translation, $field_name);
            continue;
          }
          if (isset($settings['handler_settings']['target_bundles'])) {
            $target_bundle_id = reset($settings['handler_settings']['target_bundles']);
          }
          else {

            // @todo: Update when {@link https://www.drupal.org/node/2412569
            // this setting is configurable}.
            $bundles = $this->entityManager
              ->getBundleInfo($target_entity_type_id);
            $target_bundle_id = key($bundles);
          }
          $target_entity = null;
          $uuid_index = isset($context['workspace']) && $context['workspace'] instanceof WorkspaceInterface ? $this->indexFactory
            ->get('multiversion.entity_index.uuid', $context['workspace']) : $this->indexFactory
            ->get('multiversion.entity_index.uuid');
          if ($target_entity_info = $uuid_index
            ->get($target_entity_uuid)) {
            $target_entity = $this->entityManager
              ->getStorage($target_entity_info['entity_type_id'])
              ->load($target_entity_info['entity_id']);
          }

          // Try to get real bundle.
          if (!empty($item['entity_type_id'])) {
            $bundle_key = $this->entityManager
              ->getStorage($item['entity_type_id'])
              ->getEntityType()
              ->getKey('bundle');
            if (!empty($item[$bundle_key])) {
              $target_bundle_id = $item[$bundle_key];
            }
          }

          // This set the correct uri for link field if the target entity
          // already exists.
          if ($type == 'link' && $target_entity) {
            $id = $target_entity
              ->id();
            $translation[$field_name][$delta]['uri'] = "entity:{$target_entity_type_id}/{$id}";
          }
          elseif ($target_entity) {
            $translation[$field_name][$delta]['target_id'] = $target_entity
              ->id();

            // Special handling for Entity Reference Revisions, it needs the
            // revision ID in addition to the primary entity ID.
            if ($type === 'entity_reference_revisions') {
              $revision_key = $target_entity
                ->getEntityType()
                ->getKey('revision');
              $translation[$field_name][$delta]['target_revision_id'] = $target_entity->{$revision_key}->value;
            }
          }
          else {
            $options['target_type'] = $target_entity_type_id;
            if (isset($settings['handler_settings'])) {
              $options['handler_settings'] = $settings['handler_settings'];
            }

            /** @var \Drupal\Core\Entity\EntityReferenceSelection\SelectionWithAutocreateInterface $selection_instance */
            $selection_instance = $this->selectionManager
              ->getInstance($options);

            // We use a temporary label and entity owner ID as this will be
            // backfilled later anyhow, when the real entity comes around.
            $target_entity = $selection_instance
              ->createNewEntity($target_entity_type_id, $target_bundle_id, rand(), 1);
            if (is_subclass_of($target_entity
              ->getEntityType()
              ->getStorageClass(), ContentEntityStorageInterface::class)) {

              // Set the target workspace if we have it in context.
              if (isset($context['workspace']) && $context['workspace'] instanceof WorkspaceInterface && $target_entity
                ->getEntityType()
                ->get('workspace') !== FALSE) {
                $target_entity->workspace->target_id = $context['workspace']
                  ->id();
              }

              // Set the UUID to what we received to ensure it gets updated when
              // the full entity comes around later.
              $target_entity->uuid->value = $target_entity_uuid;

              // Indicate that this revision is a stub.
              $target_entity->_rev->is_stub = TRUE;
              $target_entity->langcode->value = $context['language'];

              // Populate uri and filename fields if we have the info for them
              // in the field item.
              if ($target_entity instanceof FileInterface) {
                if (isset($item['uri'])) {
                  $target_entity
                    ->setFileUri($item['uri']);
                }
                if (isset($item['filename'])) {
                  $target_entity
                    ->setFilename($item['filename']);
                }
                if (isset($item['filesize'])) {
                  $target_entity
                    ->setSize($item['filesize']);
                }
                if (isset($item['filemime'])) {
                  $target_entity
                    ->setMimeType($item['filemime']);
                }
              }

              // This will ensure that stub poll_choice entities will not be saved
              // in Drupal\poll\Entity\Poll:preSave()
              if ($target_entity_type_id === 'poll_choice') {
                $target_entity
                  ->needsSaving(FALSE);
              }

              // Populate the data field.
              $translation[$field_name][$delta]['target_id'] = NULL;
              $translation[$field_name][$delta]['entity'] = $target_entity;
            }
          }
          if (isset($translation[$field_name][$delta]['entity_type_id'])) {
            unset($translation[$field_name][$delta]['entity_type_id']);
          }
          if (isset($translation[$field_name][$delta]['target_uuid'])) {
            unset($translation[$field_name][$delta]['target_uuid']);
          }
        }
      }
    }

    // Denormalize parent field for menu_link_content entity type.
    if ($entity_type_id == 'menu_link_content' && !empty($translation['parent'][0]['value'])) {
      $translation['parent'][0]['value'] = $this
        ->denormalizeMenuLinkParent($translation['parent'][0]['value'], $context, $translation['@context']['@language']);
    }

    // Unset the comment field item if CID is NULL.
    if (!empty($translation['comment']) && is_array($translation['comment'])) {
      foreach ($translation['comment'] as $delta => $item) {
        if (empty($item['cid'])) {
          unset($translation['comment'][$delta]);
        }
      }
    }

    // Exclude "name" field (the user name) for comment entity type because
    // we'll change it during replication if it's a duplicate.
    if ($entity_type_id == 'comment' && isset($translation['name'])) {
      unset($translation['name']);
    }

    // Clean-up attributes we don't needs anymore.
    // Remove changed info, otherwise we can get validation errors when the
    // 'changed' value for existing entity is higher than for the new entity (revision).
    // @see \Drupal\Core\Entity\Plugin\Validation\Constraint\EntityChangedConstraintValidator::validate().
    foreach ([
      '@context',
      '@type',
      '_id',
      '_revisions',
      'changed',
    ] as $key) {
      if (isset($translation[$key])) {
        unset($translation[$key]);
      }
    }
    return $translation;
  }

  /**
   * Handles entity creation for fieldable and non-fieldable entities.
   *
   * This makes sure denormalization runs on field items.
   *
   * @param array $data
   * @param EntityTypeInterface $entity_type
   * @param $format
   * @param array $context
   *
   * @return \Drupal\Core\Entity\EntityInterface
   *
   * @see \Drupal\serialization\Normalizer\FieldableEntityNormalizerTrait
   */
  private function createEntityInstance(array $data, EntityTypeInterface $entity_type, $format, array $context = []) {

    // The bundle property will be required to denormalize a bundleable
    // fieldable entity.
    if ($entity_type
      ->entityClassImplements(FieldableEntityInterface::class)) {

      // Extract bundle data to pass into entity creation if the entity type uses
      // bundles.
      if ($entity_type
        ->hasKey('bundle')) {

        // Get an array containing the bundle only. This also remove the bundle
        // key from the $data array.
        $create_params = $this
          ->extractBundleData($data, $entity_type);
      }
      else {
        $create_params = [];
      }

      // Create the entity from bundle data only, then apply field values after.
      $entity = $this->entityManager
        ->getStorage($entity_type
        ->id())
        ->create($create_params);
      $this
        ->denormalizeFieldData($data, $entity, $format, $context);
    }
    else {

      // Create the entity from all data.
      $entity = $this->entityManager
        ->getStorage($entity_type
        ->id())
        ->create($data);
    }
    return $entity;
  }

  /**
   * @param $data
   * @param $context
   * @param $langcode
   * @return string
   */
  protected function denormalizeMenuLinkParent($data, $context, $langcode) {
    if (strpos($data, 'menu_link_content') === 0) {
      list($type, $uuid, $id) = explode(':', $data);
      if ($type === 'menu_link_content' && $uuid && is_numeric($id)) {
        $storage = $this->entityManager
          ->getStorage('menu_link_content');
        $parent = $storage
          ->loadByProperties([
          'uuid' => $uuid,
        ]);
        $parent = reset($parent);
        if ($parent instanceof MenuLinkContentInterface && $parent
          ->id() && $parent
          ->id() != $id) {
          return $type . ':' . $uuid . ':' . $parent
            ->id();
        }
        elseif (!$parent) {

          // Create a new menu link as stub.
          $parent = $storage
            ->create([
            'uuid' => $uuid,
            'link' => 'internal:/',
            'langcode' => $langcode,
          ]);

          // Set the target workspace if we have it in context.
          if (isset($context['workspace']) && $context['workspace'] instanceof WorkspaceInterface) {
            $parent->workspace->target_id = $context['workspace']
              ->id();
          }

          // Indicate that this revision is a stub.
          $parent->_rev->is_stub = TRUE;
          $parent
            ->save();
          return $type . ':' . $uuid . ':' . $parent
            ->id();
        }
      }
    }
    return $data;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
CacheableNormalizerInterface::SERIALIZATION_CONTEXT_CACHEABILITY constant Name of key for bubbling cacheability metadata via serialization context.
ContentEntityNormalizer::$dispatcher protected property
ContentEntityNormalizer::$format protected property Overrides NormalizerBase::$format 3
ContentEntityNormalizer::$indexFactory protected property
ContentEntityNormalizer::$languageManager protected property
ContentEntityNormalizer::$moduleHandler private property
ContentEntityNormalizer::$selectionManager protected property
ContentEntityNormalizer::$supportedInterfaceOrClass protected property Overrides NormalizerBase::$supportedInterfaceOrClass 6
ContentEntityNormalizer::$usersMapping protected property
ContentEntityNormalizer::createEntityInstance private function Handles entity creation for fieldable and non-fieldable entities.
ContentEntityNormalizer::denormalize public function Denormalizes data back into an object of the given class. 5
ContentEntityNormalizer::denormalizeMenuLinkParent protected function
ContentEntityNormalizer::denormalizeTranslation private function
ContentEntityNormalizer::normalize public function Normalizes an object into a set of arrays/scalars. 6
ContentEntityNormalizer::__construct public function 1
FieldableEntityNormalizerTrait::$entityFieldManager protected property The entity field manager.
FieldableEntityNormalizerTrait::$entityTypeManager protected property The entity type manager. 1
FieldableEntityNormalizerTrait::$entityTypeRepository protected property The entity type repository.
FieldableEntityNormalizerTrait::constructValue protected function Build the field item value using the incoming data. 7
FieldableEntityNormalizerTrait::denormalizeFieldData protected function Denormalizes entity data by denormalizing each field individually.
FieldableEntityNormalizerTrait::determineEntityTypeId protected function Determines the entity type ID to denormalize as.
FieldableEntityNormalizerTrait::extractBundleData protected function Denormalizes the bundle property so entity creation can use it.
FieldableEntityNormalizerTrait::getEntityFieldManager protected function Returns the entity field manager.
FieldableEntityNormalizerTrait::getEntityTypeDefinition protected function Gets the entity type definition.
FieldableEntityNormalizerTrait::getEntityTypeManager protected function Returns the entity type manager.
FieldableEntityNormalizerTrait::getEntityTypeRepository protected function Returns the entity type repository.
NormalizerBase::addCacheableDependency protected function Adds cacheability if applicable.
NormalizerBase::checkFormat protected function Checks if the provided format is supported by this normalizer. 2
NormalizerBase::supportsDenormalization public function Implements \Symfony\Component\Serializer\Normalizer\DenormalizerInterface::supportsDenormalization() 1
NormalizerBase::supportsNormalization public function Checks whether the given class is supported for normalization by this normalizer. 1