// Create another entity to test that values are marked as deleted when a
// bundle is deleted.
$entity = $storage->create(['type' => 'custom', 'custom_bundle_field' => 'new']); $entity->save();
publicfunctiontestCustomFieldCreateDelete(){ // Install the module which adds the field.
$this->installModule('entity_schema_test'); $storage_definitions = \Drupal::service('entity_field.manager')->getFieldStorageDefinitions('entity_test_update'); $this->assertNotNull($storage_definitions['custom_base_field'], 'Base field definition found.'); $this->assertNotNull($storage_definitions['custom_bundle_field'], 'Bundle field definition found.');
// Make sure the field schema can be created.
\Drupal::service('field_storage_definition.listener')->onFieldStorageDefinitionCreate($storage_definitions['custom_base_field']); \Drupal::service('field_storage_definition.listener')->onFieldStorageDefinitionCreate($storage_definitions['custom_bundle_field']); /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */ $table_mapping = $this->entityTypeManager->getStorage('entity_test_update')->getTableMapping(); $base_table = current($table_mapping->getTableNames()); $base_column = current($table_mapping->getColumnNames('custom_base_field')); $this->assertTrue($this->database->schema()->fieldExists($base_table, $base_column), 'Table column created'); $table = $table_mapping->getDedicatedDataTableName($storage_definitions['custom_bundle_field']); $this->assertTrue($this->database->schema()->tableExists($table), 'Table created');
/**
* Tests getTableMapping() with a simple entity type.
*
* @param string[] $entity_keys
* A map of entity keys to use for the mocked entity type.
*
* @covers ::__construct
* @covers ::getTableMapping
*
* @dataProvider providerTestGetTableMappingSimple
*/
use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
// The field still exists, deleted.
$fields = \Drupal::entityTypeManager()->getStorage('field_config')->loadByProperties(['field_storage_uuid' => $field_storage->uuid(), 'deleted' => TRUE, 'include_deleted' => TRUE]); $this->assertCount(1, $fields, 'There is one deleted field'); $field = $fields[$field->uuid()]; $this->assertEquals($bundle, $field->getTargetBundle(), 'The deleted field is for the correct bundle');
// Check that the actual stored content did not change during delete.
/** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */ $table_mapping = $storage->getTableMapping(); $table = $table_mapping->getDedicatedDataTableName($field_storage); $column = $table_mapping->getFieldColumnName($field_storage, 'value'); $result = Database::getConnection()->select($table, 't') ->fields('t') ->execute(); foreach($resultas$row){ $this->assertEquals($row->{$column}, $this->entities[$row->entity_id]->{$field_name}->value); }
// There are 0 entities of this bundle with non-deleted data.
$found = $storage
// For test runs, the most common storage backend is a SQL database. For
// this case, ensure the tables got created.
$storage = $entity_type_manager->getStorage($entity_type_id); if($storage instanceof SqlEntityStorageInterface){ $tables = $storage->getTableMapping()->getTableNames(); $db_schema = $this->container->get('database')->schema(); foreach($tablesas$table){ $this->assertTrue($db_schema->tableExists($table), "The entity type table '$table' for the entity type '$entity_type_id' should exist."); } } }
/**
* Enables modules for this test.
*
* This method does not install modules fully. Services and hooks for the
* module are available, but the install process is not performed.
*
* To install test modules outside of the testing environment, add
* @code
* $settings['extension_discovery_scan_tests'] = TRUE;
* @endcode
* to your settings.php.
*
* @param string[] $modules
* A list of modules to enable. Dependencies are not resolved; i.e.,
* multiple modules have to be specified individually. The modules are only
* added to the active module list and loaded; i.e., their database schema
* is not installed. hook_install() is not invoked. A custom module weight
* is not applied.
*
* @throws \LogicException
* If any module in $modules is already enabled.
* @throws \RuntimeException
* If a module is not enabled after enabling it.
*/
// This could be derived from the content_moderation_state entity table
// mapping, however this is an internal entity type whose storage should
// remain constant.
$storage = $this->entityTypeManager->getStorage('content_moderation_state'); $storage_definition = $this->entityFieldManager->getActiveFieldStorageDefinitions('content_moderation_state')['moderation_state']; $column_name = $storage->getTableMapping()->getFieldColumnName($storage_definition, 'value'); $this->aliases[$column_name] = $this->tableAlias . '.' . $column_name;
// Check if the passed table is a Shopware attribute table.
if(strpos($table->getName(), '_attributes')){ // if the table is an attribute table we have to use the class name of the parent table.
$parentClass = str_replace('_attributes', '', $table->getName()); $className = $this->getClassNameOfTableName($parentClass);
// If the passed table is not an attribute table, we have to check if the table is already declared
}elseif(\array_key_exists($table->getName(), $this->getTableMapping())){ // If this is the case we will use the already declared class name
$className = $this->tableMapping[$table->getName()]['class']; }
/**
* Helper function to get a class name of the passed table.
* This function uses the internal property "tableMapping".
* The tableMapping array contains the class names and namespace for
* each already declared shopware model/table.
*
* @param string $tableName
*
* @return string
*/
// If the entity type is not using core's default entity storage, we can't
// assume the table mapping layout so we have to return only the latest
// tracked revisions.
if(!$storage instanceof SqlContentEntityStorage){ return$this->getTrackedEntities($workspace_id, $entity_type_id, $entity_ids)[$entity_type_id]; }
// If the entity type is revisionable, we need to take into account views of
// entity revisions. Usually the view will use the entity data table as the
// query base table, however, in case of an entity revision view, we need to
// use the revision table or the revision data table, depending on which one
// is being used as query base table.
if($this->entityType->isRevisionable()){ $query_base_table = $query->relationships[$relationship]['base'] ?? $this->view->storage->get('base_table'); $revision_table = $storage->getRevisionTable(); $revision_data_table = $storage->getRevisionDataTable();
$definitions['multivalued_base_field'] = BaseFieldDefinition::create('string') ->setName('multivalued_base_field') ->setTargetEntityTypeId('entity_test_mulrev') ->setTargetBundle('entity_test_mulrev') ->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) // Base fields are non-translatable and non-revisionable by default, but
// we explicitly set these values here for extra clarity.
->setTranslatable(FALSE) ->setRevisionable(FALSE); $this->state->set('entity_test_mulrev.additional_base_field_definitions', $definitions);
$entity_id_field = $entity_type->getKey('revision'); // This contains the relevant SQL field to be used when joining field
// tables.
$field_id_field = 'revision_id'; } else{ $entity_id_field = $entity_type->getKey('id'); $field_id_field = 'entity_id'; }
// Check whether this field is stored in a dedicated table.
if($field_storage && $table_mapping->requiresDedicatedTableStorage($field_storage)){ $delta = NULL;
if($key < $count){ $next = $specifiers[$key + 1]; // If this is a numeric specifier we're adding a condition on the
// specific delta.
if(is_numeric($next)){ $delta = $next;
// restrictions to SELECT queries. hook_media_access() can be used to apply
// access control to 'update' and 'delete' operations.
if(!($query instanceof SelectInterface)){ return; }
// The tables in the query. This can include media entity tables and other
// tables. Tables might be joined more than once, with aliases.
$query_tables = $query->getTables();
// The tables belonging to media entity storage.
$table_mapping = \Drupal::entityTypeManager()->getStorage('media')->getTableMapping(); $media_tables = $table_mapping->getTableNames();
// For each table in the query, if it's a media entity storage table, add a
// condition to filter out records belonging to a media entity that we wish
// to hide.
foreach($query_tablesas$alias => $info){ // Skip over subqueries.
if($info['table'] instanceof SelectInterface){ continue; } $real_table_name = $info['table'];