/**
  * Adds base field info to an entity type.
  *
  * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
  *   Entity type for adding base fields to.
  *
  * @return \Drupal\Core\Field\BaseFieldDefinition[]
  *   New fields added by moderation state.
  */
 public function entityBaseFieldInfo(EntityTypeInterface $entity_type)
 {
     if ($entity_type->isRevisionable()) {
         $fields = [];
         // @todo write a test for this.
         $fields['moderation_state'] = BaseFieldDefinition::create('entity_reference')->setLabel(t('Moderation state'))->setDescription(t('The moderation state of this piece of content.'))->setSetting('target_type', 'moderation_state')->setTargetEntityTypeId($entity_type->id())->setRevisionable(TRUE)->setDisplayOptions('view', ['label' => 'hidden', 'type' => 'string', 'weight' => -5])->setDisplayOptions('form', ['type' => 'moderation_state_default', 'weight' => 5, 'settings' => []])->addConstraint('ModerationState', [])->setDisplayConfigurable('form', FALSE)->setDisplayConfigurable('view', TRUE);
         return $fields;
     }
     return [];
 }
 /**
  * Detects whether there is a change in the shared table structure.
  *
  * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
  *   The new entity type.
  * @param \Drupal\Core\Entity\EntityTypeInterface $original
  *   The origin entity type.
  *
  * @return bool
  *   Returns TRUE if either the revisionable or translatable flag changes or
  *   a table has been renamed.
  */
 protected function hasSharedTableStructureChange(EntityTypeInterface $entity_type, EntityTypeInterface $original)
 {
     return $entity_type->isRevisionable() != $original->isRevisionable() || $entity_type->isTranslatable() != $original->isTranslatable() || $this->hasSharedTableNameChanges($entity_type, $original);
 }
 /**
  * {@inheritdoc}
  */
 public function onEntityTypeUpdate(EntityTypeInterface $entity_type, EntityTypeInterface $original)
 {
     $changes = [];
     // We implement a specific logic for table updates, which is bound to the
     // default sql content entity storage.
     if (!$this->entityManager->getStorage($entity_type->id()) instanceof SqlContentEntityStorage) {
         return;
     }
     if ($entity_type->getBaseTable() != $original->getBaseTable()) {
         $changes[] = static::BASE_TABLE_RENAME;
     }
     $revision_add = $entity_type->isRevisionable() && !$original->isRevisionable();
     $revision_remove = !$entity_type->isRevisionable() && $original->isRevisionable();
     $translation_add = $entity_type->isTranslatable() && !$original->isTranslatable();
     $translation_remove = !$entity_type->isTranslatable() && $original->isTranslatable();
     if ($revision_add) {
         $changes[] = static::REVISION_TABLE_ADDITION;
     } elseif ($revision_remove) {
         $changes[] = static::REVISION_TABLE_REMOVAL;
     } elseif ($entity_type->isRevisionable() && $entity_type->getRevisionTable() != $original->getRevisionTable()) {
         $changes[] = static::REVISION_TABLE_RENAME;
     }
     if ($translation_add) {
         $changes[] = static::DATA_TABLE_ADDITION;
     } elseif ($translation_remove) {
         $changes[] = static::DATA_TABLE_REMOVAL;
     } elseif ($entity_type->isTranslatable() && $entity_type->getDataTable() != $original->getDataTable()) {
         $changes[] = static::DATA_TABLE_RENAME;
     }
     if ($entity_type->isRevisionable() && $entity_type->isTranslatable()) {
         if ($revision_add || $translation_add) {
             $changes[] = static::REVISION_DATA_TABLE_ADDITION;
         } elseif ($entity_type->getRevisionDataTable() != $original->getRevisionDataTable()) {
             $changes[] = static::REVISION_DATA_TABLE_RENAME;
         }
     } elseif ($original->isRevisionable() && $original->isTranslatable() && ($revision_remove || $translation_remove)) {
         $changes[] = static::REVISION_DATA_TABLE_REMOVAL;
     }
     /** @var \Drupal\views\Entity\View[] $all_views */
     $all_views = $this->entityManager->getStorage('view')->loadMultiple(NULL);
     foreach ($changes as $change) {
         switch ($change) {
             case static::BASE_TABLE_RENAME:
                 $this->baseTableRename($all_views, $entity_type->id(), $original->getBaseTable(), $entity_type->getBaseTable());
                 break;
             case static::DATA_TABLE_RENAME:
                 $this->dataTableRename($all_views, $entity_type->id(), $original->getDataTable(), $entity_type->getDataTable());
                 break;
             case static::DATA_TABLE_ADDITION:
                 $this->dataTableAddition($all_views, $entity_type, $entity_type->getDataTable(), $entity_type->getBaseTable());
                 break;
             case static::DATA_TABLE_REMOVAL:
                 $this->dataTableRemoval($all_views, $entity_type->id(), $original->getDataTable(), $entity_type->getBaseTable());
                 break;
             case static::REVISION_TABLE_RENAME:
                 $this->baseTableRename($all_views, $entity_type->id(), $original->getRevisionTable(), $entity_type->getRevisionTable());
                 break;
             case static::REVISION_TABLE_ADDITION:
                 // If we add revision support we don't have to do anything.
                 break;
             case static::REVISION_TABLE_REMOVAL:
                 $this->revisionRemoval($all_views, $original);
                 break;
             case static::REVISION_DATA_TABLE_RENAME:
                 $this->dataTableRename($all_views, $entity_type->id(), $original->getRevisionDataTable(), $entity_type->getRevisionDataTable());
                 break;
             case static::REVISION_DATA_TABLE_ADDITION:
                 $this->dataTableAddition($all_views, $entity_type, $entity_type->getRevisionDataTable(), $entity_type->getRevisionTable());
                 break;
             case static::REVISION_DATA_TABLE_REMOVAL:
                 $this->dataTableRemoval($all_views, $entity_type->id(), $original->getRevisionDataTable(), $entity_type->getRevisionTable());
                 break;
         }
     }
     foreach ($all_views as $view) {
         // All changes done to the views here can be trusted and this might be
         // called during updates, when it is not safe to rely on configuration
         // containing valid schema. Trust the data and disable schema validation
         // and casting.
         $view->trustData()->save();
     }
 }
Example #4
0
 /**
  * {@inheritdoc}
  */
 public function getViewsData()
 {
     $data = [];
     $base_table = $this->entityType->getBaseTable() ?: $this->entityType->id();
     $views_revision_base_table = NULL;
     $revisionable = $this->entityType->isRevisionable();
     $base_field = $this->entityType->getKey('id');
     $revision_table = '';
     if ($revisionable) {
         $revision_table = $this->entityType->getRevisionTable() ?: $this->entityType->id() . '_revision';
     }
     $translatable = $this->entityType->isTranslatable();
     $data_table = '';
     if ($translatable) {
         $data_table = $this->entityType->getDataTable() ?: $this->entityType->id() . '_field_data';
     }
     // Some entity types do not have a revision data table defined, but still
     // have a revision table name set in
     // \Drupal\Core\Entity\Sql\SqlContentEntityStorage::initTableLayout() so we
     // apply the same kind of logic.
     $revision_data_table = '';
     if ($revisionable && $translatable) {
         $revision_data_table = $this->entityType->getRevisionDataTable() ?: $this->entityType->id() . '_field_revision';
     }
     $revision_field = $this->entityType->getKey('revision');
     // Setup base information of the views data.
     $data[$base_table]['table']['group'] = $this->entityType->getLabel();
     $data[$base_table]['table']['provider'] = $this->entityType->getProvider();
     $views_base_table = $base_table;
     if ($data_table) {
         $views_base_table = $data_table;
     }
     $data[$views_base_table]['table']['base'] = ['field' => $base_field, 'title' => $this->entityType->getLabel(), 'cache_contexts' => $this->entityType->getListCacheContexts()];
     $data[$base_table]['table']['entity revision'] = FALSE;
     if ($label_key = $this->entityType->getKey('label')) {
         if ($data_table) {
             $data[$views_base_table]['table']['base']['defaults'] = array('field' => $label_key, 'table' => $data_table);
         } else {
             $data[$views_base_table]['table']['base']['defaults'] = array('field' => $label_key);
         }
     }
     // Entity types must implement a list_builder in order to use Views'
     // entity operations field.
     if ($this->entityType->hasListBuilderClass()) {
         $data[$base_table]['operations'] = array('field' => array('title' => $this->t('Operations links'), 'help' => $this->t('Provides links to perform entity operations.'), 'id' => 'entity_operations'));
     }
     if ($this->entityType->hasViewBuilderClass()) {
         $data[$base_table]['rendered_entity'] = ['field' => ['title' => $this->t('Rendered entity'), 'help' => $this->t('Renders an entity in a view mode.'), 'id' => 'rendered_entity']];
     }
     // Setup relations to the revisions/property data.
     if ($data_table) {
         $data[$base_table]['table']['join'][$data_table] = ['left_field' => $base_field, 'field' => $base_field, 'type' => 'INNER'];
         $data[$data_table]['table']['group'] = $this->entityType->getLabel();
         $data[$data_table]['table']['provider'] = $this->entityType->getProvider();
         $data[$data_table]['table']['entity revision'] = FALSE;
     }
     if ($revision_table) {
         $data[$revision_table]['table']['group'] = $this->t('@entity_type revision', ['@entity_type' => $this->entityType->getLabel()]);
         $data[$revision_table]['table']['provider'] = $this->entityType->getProvider();
         $views_revision_base_table = $revision_table;
         if ($revision_data_table) {
             $views_revision_base_table = $revision_data_table;
         }
         $data[$views_revision_base_table]['table']['entity revision'] = TRUE;
         $data[$views_revision_base_table]['table']['base'] = array('field' => $revision_field, 'title' => $this->t('@entity_type revisions', array('@entity_type' => $this->entityType->getLabel())));
         // Join the revision table to the base table.
         $data[$views_revision_base_table]['table']['join'][$views_base_table] = array('left_field' => $revision_field, 'field' => $revision_field, 'type' => 'INNER');
         if ($revision_data_table) {
             $data[$revision_data_table]['table']['group'] = $this->t('@entity_type revision', ['@entity_type' => $this->entityType->getLabel()]);
             $data[$revision_data_table]['table']['entity revision'] = TRUE;
             $data[$revision_table]['table']['join'][$revision_data_table] = array('left_field' => $revision_field, 'field' => $revision_field, 'type' => 'INNER');
         }
     }
     $this->addEntityLinks($data[$base_table]);
     // Load all typed data definitions of all fields. This should cover each of
     // the entity base, revision, data tables.
     $field_definitions = $this->entityManager->getBaseFieldDefinitions($this->entityType->id());
     /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
     if ($table_mapping = $this->storage->getTableMapping($field_definitions)) {
         // Fetch all fields that can appear in both the base table and the data
         // table.
         $entity_keys = $this->entityType->getKeys();
         $duplicate_fields = array_intersect_key($entity_keys, array_flip(['id', 'revision', 'bundle']));
         // Iterate over each table we have so far and collect field data for each.
         // Based on whether the field is in the field_definitions provided by the
         // entity manager.
         // @todo We should better just rely on information coming from the entity
         //   storage.
         // @todo https://www.drupal.org/node/2337511
         foreach ($table_mapping->getTableNames() as $table) {
             foreach ($table_mapping->getFieldNames($table) as $field_name) {
                 // To avoid confusing duplication in the user interface, for fields
                 // that are on both base and data tables, only add them on the data
                 // table (same for revision vs. revision data).
                 if ($data_table && ($table === $base_table || $table === $revision_table) && in_array($field_name, $duplicate_fields)) {
                     continue;
                 }
                 $this->mapFieldDefinition($table, $field_name, $field_definitions[$field_name], $table_mapping, $data[$table]);
             }
         }
         foreach ($field_definitions as $field_definition) {
             if ($table_mapping->requiresDedicatedTableStorage($field_definition->getFieldStorageDefinition())) {
                 $table = $table_mapping->getDedicatedDataTableName($field_definition->getFieldStorageDefinition());
                 $data[$table]['table']['group'] = $this->entityType->getLabel();
                 $data[$table]['table']['provider'] = $this->entityType->getProvider();
                 $data[$table]['table']['join'][$views_base_table] = ['left_field' => $base_field, 'field' => 'entity_id', 'extra' => [['field' => 'deleted', 'value' => 0, 'numeric' => TRUE]]];
                 if ($revisionable) {
                     $revision_table = $table_mapping->getDedicatedRevisionTableName($field_definition->getFieldStorageDefinition());
                     $data[$revision_table]['table']['group'] = $this->t('@entity_type revision', ['@entity_type' => $this->entityType->getLabel()]);
                     $data[$revision_table]['table']['provider'] = $this->entityType->getProvider();
                     $data[$revision_table]['table']['join'][$views_revision_base_table] = ['left_field' => $revision_field, 'field' => 'entity_id', 'extra' => [['field' => 'deleted', 'value' => 0, 'numeric' => TRUE]]];
                 }
             }
         }
     }
     // Add the entity type key to each table generated.
     $entity_type_id = $this->entityType->id();
     array_walk($data, function (&$table_data) use($entity_type_id) {
         $table_data['table']['entity type'] = $entity_type_id;
     });
     return $data;
 }
Example #5
0
 /**
  * {@inheritdoc}
  */
 public static function baseFieldDefinitions(EntityTypeInterface $entity_type)
 {
     $fields = [];
     if ($entity_type->hasKey('id')) {
         $fields[$entity_type->getKey('id')] = BaseFieldDefinition::create('integer')->setLabel(new TranslatableMarkup('ID'))->setReadOnly(TRUE)->setSetting('unsigned', TRUE);
     }
     if ($entity_type->hasKey('uuid')) {
         $fields[$entity_type->getKey('uuid')] = BaseFieldDefinition::create('uuid')->setLabel(new TranslatableMarkup('UUID'))->setReadOnly(TRUE);
     }
     if ($entity_type->hasKey('revision')) {
         $fields[$entity_type->getKey('revision')] = BaseFieldDefinition::create('integer')->setLabel(new TranslatableMarkup('Revision ID'))->setReadOnly(TRUE)->setSetting('unsigned', TRUE);
     }
     if ($entity_type->hasKey('langcode')) {
         $fields[$entity_type->getKey('langcode')] = BaseFieldDefinition::create('language')->setLabel(new TranslatableMarkup('Language'))->setDisplayOptions('view', ['type' => 'hidden'])->setDisplayOptions('form', ['type' => 'language_select', 'weight' => 2]);
         if ($entity_type->isRevisionable()) {
             $fields[$entity_type->getKey('langcode')]->setRevisionable(TRUE);
         }
         if ($entity_type->isTranslatable()) {
             $fields[$entity_type->getKey('langcode')]->setTranslatable(TRUE);
         }
     }
     if ($entity_type->hasKey('bundle')) {
         if ($bundle_entity_type_id = $entity_type->getBundleEntityType()) {
             $fields[$entity_type->getKey('bundle')] = BaseFieldDefinition::create('entity_reference')->setLabel($entity_type->getBundleLabel())->setSetting('target_type', $bundle_entity_type_id)->setRequired(TRUE)->setReadOnly(TRUE);
         } else {
             $fields[$entity_type->getKey('bundle')] = BaseFieldDefinition::create('string')->setLabel($entity_type->getBundleLabel())->setRequired(TRUE)->setReadOnly(TRUE);
         }
     }
     return $fields;
 }
 /**
  * {@inheritdoc}
  */
 public function requiresEntityStorageSchemaChanges(EntityTypeInterface $entity_type, EntityTypeInterface $original)
 {
     return $entity_type->getStorageClass() != $original->getStorageClass() || $entity_type->isRevisionable() != $original->isRevisionable() || $entity_type->isTranslatable() != $original->isTranslatable() || $this->getEntitySchemaData($entity_type, $this->getEntitySchema($entity_type, TRUE)) != $this->loadEntitySchemaData($original);
 }