diff --git a/core/modules/file/src/FileViewsData.php b/core/modules/file/src/FileViewsData.php index f7b1702..5a977a2 100644 --- a/core/modules/file/src/FileViewsData.php +++ b/core/modules/file/src/FileViewsData.php @@ -6,7 +6,7 @@ */ namespace Drupal\file; -use Drupal\Component\Utility\NestedArray; + use Drupal\views\EntityViewsData; /** @@ -18,63 +18,36 @@ class FileViewsData extends EntityViewsData { * {@inheritdoc} */ public function getViewsData() { - $parent_views_data = parent::getViewsData(); + $data = parent::getViewsData(); - $data['file_managed']['table']['base'] = array( - // @TODO There is no corresponding information in entity metadata. - 'help' => t("Files maintained by Drupal and various modules."), - 'defaults' => array( - 'field' => 'filename' - ), - ); + // @TODO There is no corresponding information in entity metadata. + $data['file_managed']['table']['base']['help'] = t('Files maintained by Drupal and various modules.'); + $data['file_managed']['table']['base']['defaults']['field'] = 'filename'; $data['file_managed']['table']['wizard_id'] = 'file_managed'; - // Describes fid field in file_managed table. - $data['file_managed']['fid'] = array( - 'title' => t('File ID'), - 'help' => t('The ID of the file.'), - 'field' => array( - 'id' => 'file', - ), - 'argument' => array( - 'id' => 'file_fid', - // The field to display in the summary. - 'name field' => 'filename', - 'numeric' => TRUE, - ), - 'relationship' => array( - 'title' => t('File usage'), - 'help' => t('Relate file entities to their usage.'), - 'id' => 'standard', - 'base' => 'file_usage', - 'base field' => 'fid', - 'field' => 'fid', - 'label' => t('File usage'), - ), + $data['file_managed']['fid']['field']['id'] ='file'; + $data['file_managed']['fid']['argument'] = array( + 'id' => 'file_fid', + // The field to display in the summary. + 'name field' => 'filename', + 'numeric' => TRUE, ); - - // Describes filename field in file_managed table. - $data['file_managed']['filename'] = array( - 'field' => array( - 'id' => 'file', - ), + $data['file_managed']['fid']['relationship'] = array( + 'title' => t('File usage'), + 'help' => t('Relate file entities to their usage.'), + 'id' => 'standard', + 'base' => 'file_usage', + 'base field' => 'fid', + 'field' => 'fid', + 'label' => t('File usage'), ); - // Describes uri field in file_managed table. - $data['file_managed']['uri'] = array( - 'field' => array( - 'id' => 'file_uri', - ), - ); + $data['file_managed']['filename']['field']['id'] = 'file'; - // Describes filemime field in file_managed table. - $data['file_managed']['filemime'] = array( - 'field' => array( - 'id' => 'file_filemime', - ), - ); + $data['file_managed']['uri']['field']['id'] = 'file_uri'; + + $data['file_managed']['filemime']['field']['id'] = 'file_filemime'; - // Describes extension field in file_managed table. $data['file_managed']['extension'] = array( 'title' => t('Extension'), 'help' => t('The extension of the file.'), @@ -85,32 +58,14 @@ public function getViewsData() { ), ); - // Describes filesize field in file_managed table. - $data['file_managed']['filesize'] = array( - 'field' => array( - 'id' => 'file_size', - ), - ); + $data['file_managed']['filesize']['field']['id'] = 'file_size'; - // Describes status field in file_managed table. - $data['file_managed']['status'] = array( - 'field' => array( - 'id' => 'file_status', - ), - 'filter' => array( - 'id' => 'file_status', - ), - ); + $data['file_managed']['status']['field']['id'] = 'file_status'; + $data['file_managed']['status']['filter']['id'] = 'file_status'; - // Describes uid field in file_managed table. - $data['file_managed']['uid'] = array( - 'relationship' => array( - 'title' => t('User who uploaded'), - 'label' => t('User who uploaded'), - ), - ); + $data['file_managed']['uid']['relationship']['title'] = t('User who uploaded'); + $data['file_managed']['uid']['relationship']['label'] = t('User who uploaded'); - // Sets 'group' index for file_usage table. $data['file_usage']['table']['group'] = t('File Usage'); // Provide field-type-things to several base tables; on the core files table @@ -404,7 +359,7 @@ public function getViewsData() { ), ); - return NestedArray::mergeDeep($parent_views_data, $data); + return $data; } } diff --git a/core/modules/node/src/NodeViewsData.php b/core/modules/node/src/NodeViewsData.php index 3a19428..008d175 100644 --- a/core/modules/node/src/NodeViewsData.php +++ b/core/modules/node/src/NodeViewsData.php @@ -7,7 +7,6 @@ namespace Drupal\node; -use Drupal\Component\Utility\NestedArray; use Drupal\views\EntityViewsData; use Drupal\views\EntityViewsDataInterface; @@ -20,76 +19,36 @@ class NodeViewsData extends EntityViewsData implements EntityViewsDataInterface * {@inheritdoc} */ public function getViewsData() { - $parent_views_data = parent::getViewsData(); + $data = parent::getViewsData(); - $data['node']['table']['base'] = array( - 'weight' => -10, - 'access query tag' => 'node_access', - 'defaults' => array( - 'field' => 'title', - ), - ); + $data['node']['table']['base']['weight'] = -10; + $data['node']['table']['base']['access query tag'] = 'node_access'; $data['node']['table']['wizard_id'] = 'node'; - $data['node_field_data']['table']['join']['node'] = array( - 'type' => 'INNER', - ); - - $data['node']['nid'] = array( - 'field' => array( - 'id' => 'node', - ), - 'argument' => array( - 'id' => 'node_nid', - 'name field' => 'title', - 'numeric' => TRUE, - 'validate type' => 'nid', - ), - ); + $data['node']['nid']['field']['id'] = 'node'; + $data['node']['nid']['field']['argument'] = [ + 'id' => 'node_nid', + 'name field' => 'title', + 'numeric' => TRUE, + 'validate type' => 'nid', + ]; - // This definition has more items in it than it needs to as an example. - $data['node_field_data']['title'] = array( - 'field' => array( - // This is the real field which could be left out since it is the same. - 'field' => 'title', - // This is the UI group which could be left out since it is the same. - 'group' => t('Content'), - 'id' => 'node', - 'link_to_node default' => TRUE, - ), - ); + $data['node_field_data']['title']['field']['id'] = 'node'; + $data['node_field_data']['title']['field']['link_to_node default'] = TRUE; - $data['node_field_data']['type'] = array( - 'field' => array( - 'id' => 'node_type', - ), - 'argument' => array( - 'id' => 'node_type', - ), - ); + $data['node_field_data']['type']['field']['id'] = 'node_type'; + $data['node_field_data']['type']['argument']['id'] = 'node_type'; - if (\Drupal::moduleHandler()->moduleExists('language')) { - $data['node_field_data']['langcode'] = array( - 'help' => t('The language of the content or translation.'), - 'field' => array( - 'id' => 'node_language', - ), - ); - } + $data['node_field_data']['langcode']['help'] = t('The language of the content or translation.'); + $data['node_field_data']['langcode']['field']['id'] = 'node_language'; - $data['node_field_data']['status'] = array( - 'field' => array( - 'output formats' => array( - 'published-notpublished' => array(t('Published'), t('Not published')), - ), - ), - 'filter' => array( - 'label' => t('Published status'), - 'type' => 'yes-no', - // Use status = 1 instead of status <> 0 in WHERE statement. - 'use_equal' => TRUE, - ), - ); + $data['node_field_data']['status']['field']['output formats'] = [ + 'published-notpublished' => array(t('Published'), t('Not published')), + ]; + $data['node_field_data']['status']['filter']['label'] = t('Published status'); + $data['node_field_data']['status']['filter']['type'] = 'yes-no'; + // Use status = 1 instead of status <> 0 in WHERE statement. + $data['node_field_data']['status']['filter']['use_equal'] = TRUE; $data['node_field_data']['status_extra'] = array( 'title' => t('Published status or admin user'), @@ -101,43 +60,27 @@ public function getViewsData() { ), ); - $data['node_field_data']['promote'] = array( - 'field' => array( - 'output formats' => array( - 'promoted-notpromoted' => array(t('Promoted'), t('Not promoted')), - ), - ), - 'filter' => array( - 'label' => t('Promoted to front page status'), - 'type' => 'yes-no', - ), - ); + $data['node_field_data']['promote']['field']['output formats'] = [ + 'promoted-notpromoted' => array(t('Promoted'), t('Not promoted')), + ]; + $data['node_field_data']['promote']['filter']['label'] = t('Promoted to front page status'); + $data['node_field_data']['promote']['filter']['type'] = 'yes-no'; + + $data['node_field_data']['sticky']['field']['output formats'] = [ + 'sticky' => array(t('Sticky'), t('Not sticky')), + ]; + $data['node_field_data']['sticky']['filter']['label'] = t('Sticky status'); + $data['node_field_data']['sticky']['filter']['type'] = 'yes-no'; + $data['node_field_data']['sticky']['sort']['help'] = t('Whether or not the content is sticky. To list sticky content first, set this to descending.'); - $data['node_field_data']['sticky'] = array( + $data['node']['translation_link'] = array( + 'title' => t('Translation link'), + 'help' => t('Provide a link to the translations overview for nodes.'), 'field' => array( - 'output formats' => array( - 'sticky' => array(t('Sticky'), t('Not sticky')), - ), - ), - 'filter' => array( - 'label' => t('Sticky status'), - 'type' => 'yes-no', - ), - 'sort' => array( - 'help' => t('Whether or not the content is sticky. To list sticky content first, set this to descending.'), + 'id' => 'content_translation_link', ), ); - if (\Drupal::moduleHandler()->moduleExists('content_translation')) { - $data['node']['translation_link'] = array( - 'title' => t('Translation link'), - 'help' => t('Provide a link to the translations overview for nodes.'), - 'field' => array( - 'id' => 'content_translation_link', - ), - ); - } - $data['node']['view_node'] = array( 'field' => array( 'title' => t('Link to content'), @@ -281,20 +224,12 @@ public function getViewsData() { ), ); - $data['node_field_data']['uid'] = array( - 'help' => t('The user authoring the content. If you need more fields than the uid add the content: author relationship'), - 'relationship' => array( - 'title' => t('Content author'), - 'help' => t('Relate content to the user who created it.'), - 'label' => t('author'), - ), - 'filter' => array( - 'id' => 'user_name', - ), - 'field' => array( - 'id' => 'user', - ), - ); + $data['node_field_data']['uid']['help'] = t('The user authoring the content. If you need more fields than the uid add the content: author relationship'); + $data['node_field_data']['uid']['filter']['id'] = 'user_name'; + $data['node_field_data']['uid']['field']['id'] = 'user'; + $data['node_field_data']['uid']['relationship']['title'] = t('Content author'); + $data['node_field_data']['uid']['relationship']['help'] = t('Relate content to the user who created it.'); + $data['node_field_data']['uid']['relationship']['label'] = t('author'); $data['node']['node_listing_empty'] = array( 'title' => t('Empty Node Frontpage behavior'), @@ -304,44 +239,30 @@ public function getViewsData() { ), ); - $data['node_field_data']['uid_revision'] = array( - 'title' => t('User has a revision'), - 'help' => t('All nodes where a certain user has a revision'), - 'real field' => 'nid', - 'filter' => array( - 'id' => 'node_uid_revision', - ), - 'argument' => array( - 'id' => 'node_uid_revision', - ), - ); + $data['node_field_data']['uid_revision']['title'] = t('User has a revision'); + $data['node_field_data']['uid_revision']['help'] = t('All nodes where a certain user has a revision'); + $data['node_field_data']['uid_revision']['real field'] = 'nid'; + $data['node_field_data']['uid_revision']['filter']['id'] = 'node_uid_revision'; + $data['node_field_data']['uid_revision']['argument']['id'] = 'node_uid_revision'; $data['node_revision']['table']['wizard_id'] = 'node_revision'; // Advertise this table as a possible base table. - $data['node_revision']['table']['base'] = array( - 'help' => t('Content revision is a history of changes to content.'), - 'defaults' => array( - 'field' => 'title', - ), - ); - - $data['node_revision']['nid'] = array( - 'argument' => array( - 'id' => 'node_nid', - 'numeric' => TRUE, - ), - // @todo the NID field needs different behaviour on revision/non-revision - // tables. It would be neat if this could be encoded in the base field - // definition. - 'relationship' => array( - 'id' => 'standard', - 'base' => 'node', - 'base field' => 'nid', - 'title' => t('Content'), - 'label' => t('Get the actual content from a content revision.'), - ), - ); + $data['node_revision']['table']['base']['help'] = t('Content revision is a history of changes to content.'); + $data['node_revision']['table']['base']['defaults']['title'] = 'title'; + + $data['node_revision']['nid']['argument'] = [ + 'id' => 'node_nid', + 'numeric' => TRUE, + ]; + // @todo the NID field needs different behaviour on revision/non-revision + // tables. It would be neat if this could be encoded in the base field + // definition. + $data['node_revision']['nid']['relationship']['id'] = 'standard'; + $data['node_revision']['nid']['relationship']['base'] = 'node'; + $data['node_revision']['nid']['relationship']['base field'] = 'nid'; + $data['node_revision']['nid']['relationship']['title'] = t('Content'); + $data['node_revision']['nid']['relationship']['label'] = t('Get the actual content from a content revision.'); $data['node_revision']['vid'] = array( 'argument' => array( @@ -355,60 +276,29 @@ public function getViewsData() { 'title' => t('Content'), 'label' => t('Get the actual content from a content revision.'), ), - ); + ) + $data['node_revision']['vid']; - if (\Drupal::moduleHandler()->moduleExists('language')) { - $data['node_revision']['langcode'] = array( - 'help' => t('The language the original content is in.'), - 'field' => array( - 'id' => 'node_language', - ), - ); - } + $data['node_revision']['langcode']['help'] = t('The language the original content is in.'); + $data['node_revision']['langcode']['field']['id'] = 'node_language'; - $data['node_revision']['revision_log'] = array( - 'field' => array( - 'id' => 'xss', - ), - ); + $data['node_revision']['revision_log']['field']['id'] = 'xss'; - $data['node_revision']['revision_uid'] = array( - 'help' => t('Relate a content revision to the user who created the revision.'), - 'relationship' => array( - 'label' => t('revision user'), - ), - ); + $data['node_revision']['revision_uid']['help'] = t('Relate a content revision to the user who created the revision.'); + $data['node_revision']['revision_uid']['relationship']['label'] = t('revision user'); $data['node_field_revision']['table']['wizard_id'] = 'node_field_revision'; - // For other base tables, explain how we join. - $data['node_field_revision']['table']['join'] = array( - 'node' => array( - 'left_field' => 'vid', - 'field' => 'vid', - ), - ); + $data['node_field_revision']['table']['join']['node']['left_field'] = 'vid'; + $data['node_field_revision']['table']['join']['node']['field'] = 'vid'; - $data['node_field_revision']['status'] = array( - 'field' => array( - 'output formats' => array( - 'published-notpublished' => array(t('Published'), t('Not published')), - ), - ), - 'filter' => array( - 'label' => t('Published'), - 'type' => 'yes-no', - // Use status = 1 instead of status <> 0 in WHERE statement. - 'use_equal' => TRUE, - ), - ); + $data['node_field_revision']['status']['field']['output formats'] = [ + 'published-notpublished' => [t('Published'), t('Not published')], + ]; + $data['node_field_revision']['status']['filter']['label'] = t('Published'); + $data['node_field_revision']['status']['filter']['type'] = 'yes-no'; + $data['node_field_revision']['status']['filter']['use_equal'] = TRUE; - $data['node_field_revision']['title'] = array( - 'field' => array( - 'field' => 'title', - 'id' => 'node_revision', - ), - ); + $data['node_field_revision']['title']['field']['id'] = 'node_revision'; $data['node_revision']['link_to_revision'] = array( 'field' => array( @@ -534,7 +424,7 @@ public function getViewsData() { } } - return NestedArray::mergeDeep($parent_views_data, $data); + return $data; } } diff --git a/core/modules/system/entity.api.php b/core/modules/system/entity.api.php index dfe0ef3..f7411c6 100644 --- a/core/modules/system/entity.api.php +++ b/core/modules/system/entity.api.php @@ -310,8 +310,8 @@ * config entities will use \Drupal\Core\Config\Entity\ConfigEntityStorage. * You can extend one of these classes to provide custom behavior. * - views_data: A class implementing \Drupal\views\EntityViewsDataInterface - * to provide views data for the entity type. The class can use - * \Drupal\views\EntityViewsData to autogenerate most of the views data. + * to provide views data for the entity type. You can autogenerate most of + * the views data by extending \Drupal\views\EntityViewsData. * - For content entities, the annotation will refer to a number of database * tables and their fields. These annotation properties, such as 'base_table', * 'data_table', 'entity_keys', etc., are documented on diff --git a/core/modules/views/src/EntityViewsData.php b/core/modules/views/src/EntityViewsData.php index 9c7574b..48d8a87 100644 --- a/core/modules/views/src/EntityViewsData.php +++ b/core/modules/views/src/EntityViewsData.php @@ -140,11 +140,26 @@ public function getViewsData() { 'title' => $this->entityType->getLabel(), ]; + if ($label_key = $this->entityType->getKey('label')) { + if ($data_table) { + $data[$base_table]['table']['base']['defaults'] = array( + 'field' => $label_key, + 'table' => $data_table, + ); + } + else { + $data[$base_table]['table']['base']['defaults'] = array( + 'field' => $label_key, + ); + } + } + // Setup relations to the revisions/property data. if ($data_table) { $data[$data_table]['table']['join'][$base_table] = [ 'left_field' => $base_field, 'field' => $base_field, + 'type' => 'INNER' ]; $data[$data_table]['table']['entity type'] = $this->entityType->id(); $data[$data_table]['table']['group'] = $this->entityType->getLabel(); @@ -160,6 +175,7 @@ public function getViewsData() { $data[$revision_table]['table']['join'][$base_table] = array( 'left_field' => $revision_field, 'field' => $revision_field, + 'type' => 'INNER', ); if ($revision_data_table) { @@ -169,6 +185,7 @@ public function getViewsData() { $data[$revision_data_table]['table']['join'][$revision_table] = array( 'left_field' => $revision_field, 'field' => $revision_field, + 'type' => 'INNER', ); } } @@ -352,6 +369,16 @@ protected function mapSingleFieldViewsData($table, $field_name, $data_type, $sch return $views_field; } + /** + * Processes the views data for a language field. + * + * @param string $table + * The table the language field is added to. + * @param string $field_name + * The field name of the language field. + * @param array $views_field + * The views field data. + */ protected function processViewsDataForLanguage($table, $field_name, array &$views_field) { // Apply special titles for the langcode field. if ($field_name == 'langcode') { @@ -364,6 +391,16 @@ protected function processViewsDataForLanguage($table, $field_name, array &$view } } + /** + * Processes the views data for a language field. + * + * @param string $table + * The table the language field is added to. + * @param string $field_name + * The field name of the language field. + * @param array $views_field + * The views field data. + */ protected function processViewsDataForString($table, $field_name, array &$views_field) { if ($field_name == $this->entityType->getKey('bundle')) { // @todo Use the other bundle handlers, once @@ -380,10 +417,10 @@ protected function processViewsDataForString($table, $field_name, array &$views_ * the data table right from the beginning. * * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type - * The entity type + * The entity type. * * @return string - * THe name of the base table in views. + * The name of the base table in views. */ protected function getViewsTableForEntityType(EntityTypeInterface $entity_type) { return $entity_type->getBaseTable(); diff --git a/core/modules/views/tests/Drupal/views/Tests/EntityViewsDataTest.php b/core/modules/views/tests/Drupal/views/Tests/EntityViewsDataTest.php index 7e01256..0d1fd0e 100644 --- a/core/modules/views/tests/Drupal/views/Tests/EntityViewsDataTest.php +++ b/core/modules/views/tests/Drupal/views/Tests/EntityViewsDataTest.php @@ -123,6 +123,8 @@ public function testBaseTables() { $this->assertEquals('id', $data['entity_test']['table']['base']['field']); $this->assertEquals('Entity test', $data['entity_test']['table']['base']['title']); + $this->assertFalse(isset($data['entity_test']['table']['defaults'])); + $this->assertFalse(isset($data['entity_test_mul_property_data'])); $this->assertFalse(isset($data['revision_table'])); $this->assertFalse(isset($data['revision_data_table'])); @@ -134,7 +136,8 @@ public function testBaseTables() { */ public function testDataTable() { $entity_type = $this->baseEntityType->set('data_table', 'entity_test_mul_property_data') - ->set('id', 'entity_test_mul'); + ->set('id', 'entity_test_mul') + ->setKey('label', 'label'); $this->viewsData->setEntityType($entity_type); @@ -144,10 +147,11 @@ public function testDataTable() { $this->assertEquals('entity_test_mul', $data['entity_test_mul_property_data']['table']['entity type']); $this->assertEquals('Entity test', $data['entity_test_mul_property_data']['table']['group']); + $this->assertEquals(['field' => 'label', 'table' => 'entity_test_mul_property_data'], $data['entity_test']['table']['base']['defaults']); // Ensure the join information is set up properly. $this->assertCount(1, $field_views_data['table']['join']); - $this->assertEquals(['entity_test' => ['left_field' => 'id', 'field' => 'id']], $field_views_data['table']['join']); + $this->assertEquals(['entity_test' => ['left_field' => 'id', 'field' => 'id', 'type' => 'INNER']], $field_views_data['table']['join']); $this->assertFalse(isset($data['revision_table'])); $this->assertFalse(isset($data['revision_data_table'])); } @@ -174,10 +178,10 @@ public function testRevisionTable() { // Tests the join definition between the base and the revision table. $revision_data = $data['entity_test_mulrev_revision']; $this->assertCount(1, $revision_data['table']['join']); - $this->assertEquals(['entity_test' => ['left_field' => 'revision_id', 'field' => 'revision_id']], $revision_data['table']['join']); + $this->assertEquals(['entity_test' => ['left_field' => 'revision_id', 'field' => 'revision_id', 'type' => 'INNER']], $revision_data['table']['join']); $revision_data = $data['entity_test_mulrev_property_revision']; $this->assertCount(1, $revision_data['table']['join']); - $this->assertEquals(['entity_test_mulrev_revision' => ['left_field' => 'revision_id', 'field' => 'revision_id']], $revision_data['table']['join']); + $this->assertEquals(['entity_test_mulrev_revision' => ['left_field' => 'revision_id', 'field' => 'revision_id', 'type' => 'INNER']], $revision_data['table']['join']); $this->assertFalse(isset($data['data_table'])); }