From 46cf76b7e8aa0490eebc9e7968835152aa119739 Mon Sep 17 00:00:00 2001
From: Andy Hebrank <ahebrank@gmail.com>
Date: Thu, 25 May 2017 20:32:07 -0400
Subject: [PATCH] move display::preexecute to hook_entity_view; add cache key
 for contextual arguments

---
 eva.module                       | 37 ++++++++++++++++++++++++++++++++++++-
 src/Plugin/views/display/Eva.php | 30 ++----------------------------
 2 files changed, 38 insertions(+), 29 deletions(-)

diff --git a/eva.module b/eva.module
index 74ac602..cb40106 100644
--- a/eva.module
+++ b/eva.module
@@ -105,7 +105,8 @@ function eva_entity_view(array &$build, EntityInterface $entity, EntityViewDispl
       if ($view = Views::getView($info['name'])) {
         $view->setDisplay($info['display']);
         if ((empty($info['bundles']) || in_array($display->getTargetBundle(), $info['bundles'])) && $view->access($info['display'])) {
-          // no parent for current_entity; it's used by the display's preExecute
+
+          // save the entity for path calculation
           $view->current_entity = $entity;
 
           // exposed form
@@ -115,6 +116,40 @@ function eva_entity_view(array &$build, EntityInterface $entity, EntityViewDispl
             $build[$longname . '_form'] = $exposed_form->renderExposedForm(TRUE);
           }
 
+          // gather info about the attched-to entity
+          $entity_type = $view->display_handler->getOption('entity_type');
+          $entity_info = \Drupal::entityManager()->getDefinition($entity_type);
+      
+          $arg_mode = $view->display_handler->getOption('argument_mode');
+          if ($arg_mode == 'token') {
+            if ($token_string = $view->display_handler->getOption('default_argument')) {
+              // Now do the token replacement.
+              $token_values = eva_get_arguments_from_token_string($token_string, $entity_type, $entity);
+              $new_args = array();
+              // We have to be careful to only replace arguments that have tokens.
+              foreach ($token_values as $key => $value) {
+                $new_args[Html::escape($key)] = Html::escape($value);
+              }
+      
+              $view->args = $new_args;
+            }
+          }
+          elseif ($arg_mode == 'id') {
+            $view->args = array($entity->id());
+          }
+
+          // add an argument cache key 
+          // If there are more than one of the same Eva on the same page,
+          // the first one gets cached.
+          // Presumably they should vary by contextual argument, so this 
+          // adds a cache key for the argument(s).
+          // see https://www.drupal.org/node/2873385
+          if ($view->args) {
+            $view->element['#cache'] += ['keys' => []];
+            $view->element['#cache']['keys'] = array_merge([implode(':', $view->args)], $view->element['#cache']['keys']);
+          }
+
+          // build the render
           $element = $view->buildRenderable($info['display']);
 
           if (!empty($element)) {
diff --git a/src/Plugin/views/display/Eva.php b/src/Plugin/views/display/Eva.php
index 2283a82..6adb305 100644
--- a/src/Plugin/views/display/Eva.php
+++ b/src/Plugin/views/display/Eva.php
@@ -252,34 +252,6 @@ public function submitOptionsForm(&$form, FormStateInterface $form_state) {
     }
   }
 
-  public function preExecute() {
-    parent::preExecute();
-    
-    if (isset($this->view->current_entity)) {
-      $entity = $this->view->current_entity;
-      $entity_type = $this->view->display_handler->getOption('entity_type');
-      $entity_info = \Drupal::entityManager()->getDefinition($entity_type);
-  
-      $arg_mode = $this->view->display_handler->getOption('argument_mode');
-      if ($arg_mode == 'token') {
-        if ($token_string = $this->view->display_handler->getOption('default_argument')) {
-          // Now do the token replacement.
-          $token_values = eva_get_arguments_from_token_string($token_string, $entity_type, $entity);
-          $new_args = array();
-          // We have to be careful to only replace arguments that have tokens.
-          foreach ($token_values as $key => $value) {
-            $new_args[Html::escape($key)] = Html::escape($value);
-          }
-  
-          $this->view->args = $new_args;
-        }
-      }
-      elseif ($arg_mode == 'id') {
-        $this->view->args = array($entity->id());
-      }
-    }
-  }
-  
   public function getPath() {
     if (isset($this->view->current_entity)) {
       /** @var \Drupal\Core\Entity\EntityInterface $current_entity */
@@ -307,5 +279,7 @@ function execute() {
     if (!empty($this->view->result) || $this->getOption('empty') || !empty($this->view->style_plugin->definition['even empty'])) {
       return $element;
     }
+
+    return [];
   }
 }
