diff --git a/core/modules/views/src/Entity/Render/ConfigurableLanguageRenderer.php b/core/modules/views/src/Entity/Render/ConfigurableLanguageRenderer.php index 697ae8a..ce96c49 100644 --- a/core/modules/views/src/Entity/Render/ConfigurableLanguageRenderer.php +++ b/core/modules/views/src/Entity/Render/ConfigurableLanguageRenderer.php @@ -44,7 +44,7 @@ public function __construct(ViewExecutable $view, LanguageManagerInterface $lang /** * {@inheritdoc} */ - public function getLangcode(ResultRow $row) { + public function getLangcode(ResultRow $row, $relationship = 'none') { return $this->langcode; } diff --git a/core/modules/views/src/Entity/Render/DefaultLanguageRenderer.php b/core/modules/views/src/Entity/Render/DefaultLanguageRenderer.php index dbd3a72..55f5a5b 100644 --- a/core/modules/views/src/Entity/Render/DefaultLanguageRenderer.php +++ b/core/modules/views/src/Entity/Render/DefaultLanguageRenderer.php @@ -17,8 +17,10 @@ class DefaultLanguageRenderer extends EntityTranslationRendererBase { /** * {@inheritdoc} */ - public function getLangcode(ResultRow $row) { - return $row->_entity->getUntranslated()->language()->getId(); + public function getLangcode(ResultRow $row, $relationship = 'none') { + if ($entity = $this->getEntity($row, $relationship)) { + return $entity->getUntranslated()->language()->getId(); + } } } diff --git a/core/modules/views/src/Entity/Render/EntityFieldRenderer.php b/core/modules/views/src/Entity/Render/EntityFieldRenderer.php index b00a572..3c2c84a 100644 --- a/core/modules/views/src/Entity/Render/EntityFieldRenderer.php +++ b/core/modules/views/src/Entity/Render/EntityFieldRenderer.php @@ -200,7 +200,8 @@ protected function buildFields(array $values) { $field = $this->view->field[current($field_ids)]; foreach ($values as $result_row) { $entity = $field->getEntity($result_row); - $entities_by_bundles[$entity->bundle()][$result_row->index] = $this->getEntityTranslation($entity, $result_row); + $relationship = isset($field->options['relationship']) ? $field->options['relationship'] : 'none'; + $entities_by_bundles[$entity->bundle()][$result_row->index] = $this->getEntityTranslation($entity, $result_row, $relationship); } // Determine unique sets of fields that can be processed by the same diff --git a/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php b/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php index 7f9f44c..20f6815 100644 --- a/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php +++ b/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php @@ -67,18 +67,20 @@ protected function getEntityTranslationRenderer() { * The entity object the field value being processed is attached to. * @param \Drupal\views\ResultRow $row * The result row the field value being processed belongs to. + * @param string $relationship + * The relationship to be used, or 'none' by default. * * @return \Drupal\Core\Entity\FieldableEntityInterface * The entity translation object for the specified row. */ - public function getEntityTranslation(EntityInterface $entity, ResultRow $row) { + public function getEntityTranslation(EntityInterface $entity, ResultRow $row, $relationship = 'none') { // We assume the same language should be used for all entity fields // belonging to a single row, even if they are attached to different entity // types. Below we apply language fallback to ensure a valid value is always // picked. $translation = $entity; if ($entity instanceof TranslatableInterface && count($entity->getTranslationLanguages()) > 1) { - $langcode = $this->getEntityTranslationRenderer()->getLangcode($row); + $langcode = $this->getEntityTranslationRenderer()->getLangcode($row, $relationship); $translation = $this->getEntityManager()->getTranslationFromContext($entity, $langcode); } return $translation; diff --git a/core/modules/views/src/Entity/Render/EntityTranslationRendererBase.php b/core/modules/views/src/Entity/Render/EntityTranslationRendererBase.php index 4da6672..9a5cdf3 100644 --- a/core/modules/views/src/Entity/Render/EntityTranslationRendererBase.php +++ b/core/modules/views/src/Entity/Render/EntityTranslationRendererBase.php @@ -20,11 +20,13 @@ * * @param \Drupal\views\ResultRow $row * The result row. + * @param string $relationship + * The relationship to be used, or 'none' by default. * * @return string * A language code. */ - abstract public function getLangcode(ResultRow $row); + abstract public function getLangcode(ResultRow $row, $relationship = 'none'); /** * {@inheritdoc} @@ -33,27 +35,62 @@ public function query(QueryPluginBase $query, $relationship = NULL) { } /** - * {@inheritdoc} + * Runs before each entity is rendered. + * + * @param \Drupal\views\ResultRow[] $result + * The full array of results from the query. + * @param string $relationship + * The relationship to be used, or 'none' by default. */ - public function preRender(array $result) { + public function preRender(array $result, $relationship = 'none') { $view_builder = $this->view->rowPlugin->entityManager->getViewBuilder($this->entityType->id()); - /** @var \Drupal\views\ResultRow $row */ foreach ($result as $row) { - // @todo Take relationships into account. - // See https://www.drupal.org/node/2457999. - $entity = $row->_entity; - $entity->view = $this->view; - $this->build[$entity->id()] = $view_builder->view($entity, $this->view->rowPlugin->options['view_mode'], $this->getLangcode($row)); + if ($entity = $this->getEntity($row, $relationship)) { + $entity->view = $this->view; + $this->build[$entity->id()] = $view_builder->view($entity, $this->view->rowPlugin->options['view_mode'], $this->getLangcode($row, $relationship)); + } } } /** - * {@inheritdoc} + * Renders entity data. + * + * @param \Drupal\views\ResultRow $row + * A single row of the query result. + * @param string $relationship + * The relationship to be used, or 'none' by default. + * + * @return array + * A renderable array for the entity data contained in the result row. */ - public function render(ResultRow $row) { - $entity_id = $row->_entity->id(); - return $this->build[$entity_id]; + public function render(ResultRow $row, $relationship = 'none') { + if ($entity = $this->getEntity($row, $relationship)) { + $entity_id = $entity->id(); + return $this->build[$entity_id]; + } + } + + /** + * Gets the entity assosiated with a row. + * + * @param \Drupal\views\ResultRow $row + * The result row. + * @param string $relationship + * (optional) The relationship. + * + * @return \Drupal\Core\Entity\EntityInterface|null + * The entity might be optional, because the relationship entity might not + * always exist. + */ + protected function getEntity($row, $relationship = 'none') { + if ($relationship === 'none') { + return $row->_entity; + } + elseif (isset($row->_relationship_entities[$relationship])) { + return $row->_relationship_entities[$relationship]; + } + return NULL; } } diff --git a/core/modules/views/src/Entity/Render/RendererBase.php b/core/modules/views/src/Entity/Render/RendererBase.php index a7de2a5..0a65d82 100644 --- a/core/modules/views/src/Entity/Render/RendererBase.php +++ b/core/modules/views/src/Entity/Render/RendererBase.php @@ -92,18 +92,8 @@ public function getCacheContexts() { * * @param \Drupal\views\ResultRow[] $result * The full array of results from the query. - * @param string $relationship - * The relationship to be used, or 'none' by default. */ - public function preRender(array $result, $relationship = 'none') { - $view_builder = $this->view->rowPlugin->entityManager->getViewBuilder($this->entityType->id()); - - foreach ($result as $row) { - if ($entity = $this->getEntity($row, $relationship)) { - $entity->view = $this->view; - $this->build[$entity->id()] = $view_builder->view($entity, $this->view->rowPlugin->options['view_mode'], $this->getLangcode($row)); - } - } + public function preRender(array $result) { } /** @@ -117,26 +107,4 @@ public function preRender(array $result, $relationship = 'none') { */ abstract public function render(ResultRow $row); - /** - * Gets the entity assosiated with a row. - * - * @param \Drupal\views\ResultRow $row - * The result row. - * @param string $relationship - * (optional) The relationship. - * - * @return \Drupal\Core\Entity\EntityInterface|null - * The entity might be optional, because the relationship entity might not - * always exist. - */ - protected function getEntity($row, $relationship = 'none') { - if ($relationship === 'none') { - return $row->_entity; - } - elseif (isset($row->_relationship_entities[$relationship])) { - return $row->_relationship_entities[$relationship]; - } - return NULL; - } - } diff --git a/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php b/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php index 5603de1..34d918d 100644 --- a/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php +++ b/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php @@ -55,8 +55,8 @@ public function preRender(array $result, $relationship = 'none') { foreach ($result as $row) { if ($entity = $this->getEntity($row, $relationship)) { $entity->view = $this->view; - $langcode = $this->getLangcode($row); - $this->build[$entity->id()][$langcode] = $view_builder->view($entity, $this->view->rowPlugin->options['view_mode'], $this->getLangcode($row)); + $langcode = $this->getLangcode($row, $relationship); + $this->build[$entity->id()][$langcode] = $view_builder->view($entity, $this->view->rowPlugin->options['view_mode'], $langcode); } } } @@ -64,16 +64,18 @@ public function preRender(array $result, $relationship = 'none') { /** * {@inheritdoc} */ - public function render(ResultRow $row) { - $entity_id = $row->_entity->id(); - $langcode = $this->getLangcode($row); - return $this->build[$entity_id][$langcode]; + public function render(ResultRow $row, $relationship = 'none') { + if ($entity = $this->getEntity($row, $relationship)) { + $entity_id = $entity->id(); + $langcode = $this->getLangcode($row, $relationship); + return $this->build[$entity_id][$langcode]; + } } /** * {@inheritdoc} */ - public function getLangcode(ResultRow $row) { + public function getLangcode(ResultRow $row, $relationship = 'none') { return isset($row->{$this->langcodeAlias}) ? $row->{$this->langcodeAlias} : $this->languageManager->getDefaultLanguage()->getId(); } diff --git a/core/modules/views/src/Plugin/views/row/EntityRow.php b/core/modules/views/src/Plugin/views/row/EntityRow.php index de24cb2..c0034d4 100644 --- a/core/modules/views/src/Plugin/views/row/EntityRow.php +++ b/core/modules/views/src/Plugin/views/row/EntityRow.php @@ -172,7 +172,13 @@ public function summaryTitle() { */ public function query() { parent::query(); - $this->getEntityTranslationRenderer()->query($this->view->getQuery()); + if (isset($this->options['relationship'], $this->view->relationship[$this->options['relationship']])) { + $relationship = $this->view->relationship[$this->options['relationship']]->alias; + } + else { + $relationship = NULL; + } + $this->getEntityTranslationRenderer()->query($this->view->getQuery(), $relationship); } /** @@ -189,7 +195,7 @@ public function preRender($result) { * Overrides Drupal\views\Plugin\views\row\RowPluginBase::render(). */ public function render($row) { - return $this->getEntityTranslationRenderer()->render($row); + return $this->getEntityTranslationRenderer()->render($row, isset($this->options['relationship']) ? $this->options['relationship'] : 'none'); } /** diff --git a/core/modules/views/src/Tests/Plugin/EntityRowTest.php b/core/modules/views/src/Tests/Plugin/EntityRowTest.php index 15bc52e..46a6366 100644 --- a/core/modules/views/src/Tests/Plugin/EntityRowTest.php +++ b/core/modules/views/src/Tests/Plugin/EntityRowTest.php @@ -26,7 +26,7 @@ class EntityRowTest extends ViewUnitTestBase { * * @var array */ - public static $modules = ['entity_test', 'field', 'entity', 'system', 'user']; + public static $modules = ['entity_test', 'field', 'system', 'user']; /** * Views used by this test. @@ -60,6 +60,16 @@ public function testEntityRow() { ]); $entity_test->save(); + // Ensure entities have different ids. + if ($entity_test->id() == $user->id()) { + $entity_test->delete(); + $entity_test = EntityTest::create([ + 'user_id' => $user->id(), + 'name' => 'test entity test', + ]); + $entity_test->save(); + } + $view = Views::getView('test_entity_row'); $build = $view->preview(); $this->render($build); diff --git a/core/modules/views/src/Tests/Plugin/RowEntityTest.php b/core/modules/views/src/Tests/Plugin/RowEntityTest.php deleted file mode 100644 index 7de0305..0000000 --- a/core/modules/views/src/Tests/Plugin/RowEntityTest.php +++ /dev/null @@ -1,71 +0,0 @@ -installEntitySchema('taxonomy_term'); - $this->installConfig(array('taxonomy')); - \Drupal::service('router.builder')->rebuild(); - } - - /** - * Tests the entity row handler. - */ - public function testEntityRow() { - $vocab = entity_create('taxonomy_vocabulary', array('name' => $this->randomMachineName(), 'vid' => strtolower($this->randomMachineName()))); - $vocab->save(); - $term = entity_create('taxonomy_term', array('name' => $this->randomMachineName(), 'vid' => $vocab->id() )); - $term->save(); - - $view = Views::getView('test_entity_row'); - $build = $view->preview(); - $this->render($build); - - $this->assertText($term->getName(), 'The rendered entity appears as row in the view.'); - - // Tests the available view mode options. - $form = array(); - $form_state = new FormState(); - $form_state->set('view', $view->storage); - $view->rowPlugin->buildOptionsForm($form, $form_state); - - $this->assertTrue(isset($form['view_mode']['#options']['default']), 'Ensure that the default view mode is available'); - } - -}