diff -u b/diff.views.inc b/diff.views.inc --- b/diff.views.inc +++ b/diff.views.inc @@ -1,4 +1,5 @@ getDefinitions(); - $revisionable_entity_types = array_filter($entity_types, function (EntityTypeInterface $entity_type) { - return $entity_type->isRevisionable(); - }); /** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type */ - foreach ($revisionable_entity_types as $entity_type) { - $revision_base_table = $entity_type->getRevisionDataTable() ?: $entity_type->getRevisionTable(); - - $data[$revision_base_table]['diff_from'] = [ - 'title' => t('Diff from'), - 'help' => '', - 'field' => [ - 'id' => 'diff__from', - ], - ]; + foreach (\Drupal::entityTypeManager()->getDefinitions() as $entity_type) { + // Add the diff_from and diff_to fields to every revisionable entity type. + if ($entity_type->isRevisionable()) { + $revision_base_table = $entity_type->getRevisionDataTable() ?: $entity_type->getRevisionTable(); - $data[$revision_base_table]['diff_to'] = [ - 'title' => t('Diff to'), - 'help' => '', - 'field' => [ - 'id' => 'diff__to', - ], - ]; + $data[$revision_base_table]['diff_from'] = [ + 'title' => t('Diff from'), + 'help' => '', + 'field' => [ + 'id' => 'diff__from', + ], + ]; + $data[$revision_base_table]['diff_to'] = [ + 'title' => t('Diff to'), + 'help' => '', + 'field' => [ + 'id' => 'diff__to', + ], + ]; + } } return $data; diff -u b/src/Plugin/views/field/DiffFrom.php b/src/Plugin/views/field/DiffFrom.php --- b/src/Plugin/views/field/DiffFrom.php +++ b/src/Plugin/views/field/DiffFrom.php @@ -35,28 +35,22 @@ public function viewsForm(&$form, FormStateInterface $form_state) { // Replace the form submit button label. $form['actions']['submit']['#value'] = $this->t('Compare'); - - $use_revision = array_key_exists('revision', $this->view->getQuery()->getEntityTableInfo()); - if (!empty($this->view->result)) { - $form[$this->options['id']]['#tree'] = TRUE; - foreach ($this->view->result as $row_index => $row) { - $entity = $row->_entity; - $form[$this->options['id']][$row_index] = [ - '#type' => 'radio', - '#parents' => [$this->options['id']], - '#title' => $this->t('Compare this item'), - '#title_display' => 'invisible', - '#return_value' => $this->calculateEntityDiffFormKey($entity, $use_revision), - ]; - } - } + parent::viewsForm($form, $form_state); } + /** + * Returns the diff_to field ID. + * + * @return string + * The diff_to field ID, or null if the field was not found on the view. + */ protected function getToFieldId() { - $to_fields = array_filter($this->view->field, function (FieldPluginBase $field) { - return $field instanceof DiffTo; - }); - return array_keys($to_fields)[0]; + /** @var FieldPluginBase $field */ + foreach ($this->view->field as $id => $field) { + if ($field instanceof DiffTo) { + return $id; + } + } } /** @@ -78,12 +72,18 @@ $diff_to = $form_state->getValue($this->getToFieldId()); $diff_to_entity = $this->loadEntityFromDiffFormKey($diff_to); + // We need both entities, so quietly abort if neither can be loaded for + // any reason. + // TODO: Should we throw an exception instead? + if (empty($diff_from_entity) || empty($diff_to_entity)) { + return; + } + $options = array( 'query' => $this->getDestinationArray(), ); $entity_type_id = $diff_from_entity->getEntityTypeId(); - if ($diff_from_entity instanceof NodeInterface) { $form_state->setRedirect('diff.revisions_diff', [$entity_type_id => $diff_from_entity->id(),'left_vid' => $diff_from_entity->getRevisionId(), 'right_vid' => $diff_to_entity->getRevisionId()], $options); } diff -u b/src/Plugin/views/field/DiffPluginBase.php b/src/Plugin/views/field/DiffPluginBase.php --- b/src/Plugin/views/field/DiffPluginBase.php +++ b/src/Plugin/views/field/DiffPluginBase.php @@ -7,9 +7,11 @@ namespace Drupal\diff\Plugin\views\field; +use Drupal\Component\Serialization\Json; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Entity\RevisionableInterface; +use Drupal\Core\Form\FormStateInterface; use Drupal\Core\TypedData\TranslatableInterface; use Drupal\views\Plugin\views\field\FieldPluginBase; use Drupal\views\Plugin\views\field\UncacheableFieldHandlerTrait; @@ -64,6 +66,12 @@ $this->ensureMyTable(); } + /** + * Returns the maximum possible age of cache items for this plugin. + * + * @return int + * The maximum cache age in seconds. + */ public function getCacheMaxAge() { return 0; } @@ -76,6 +84,25 @@ } /** + * {@inheritdoc} + */ + public function viewsForm(&$form, FormStateInterface $form_state) { + if (!empty($this->view->result)) { + $form[$this->options['id']]['#tree'] = TRUE; + foreach ($this->view->result as $row_index => $row) { + $entity = $row->_entity; + $form[$this->options['id']][$row_index] = [ + '#type' => 'radio', + '#parents' => [$this->options['id']], + '#title' => $this->t('Compare this item'), + '#title_display' => 'invisible', + '#return_value' => $this->calculateEntityDiffFormKey($entity), + ]; + } + } + } + + /** * Calculates a diff form key. * * This generates a key that is used as the checkbox return value when @@ -101,11 +128,10 @@ // An entity ID could be an arbitrary string (although they are typically // numeric). JSON then Base64 encoding ensures the diff_form_key is // safe to use in HTML, and that the key parts can be retrieved. - $key = json_encode($key_parts); + $key = Json::encode($key_parts); return base64_encode($key); } - /** * Loads an entity based on a diff form key. * @@ -119,7 +145,7 @@ */ protected function loadEntityFromDiffFormKey($diff_form_key) { $key = base64_decode($diff_form_key); - $key_parts = json_decode($key); + $key_parts = Json::decode($key); $revision_id = NULL; // If there are 3 items, vid will be last. diff -u b/src/Plugin/views/field/DiffTo.php b/src/Plugin/views/field/DiffTo.php --- b/src/Plugin/views/field/DiffTo.php +++ b/src/Plugin/views/field/DiffTo.php @@ -26,23 +26,2 @@ - /** - * {@inheritdoc} - */ - public function viewsForm(&$form, FormStateInterface $form_state) { - $use_revision = array_key_exists('revision', $this->view->getQuery()->getEntityTableInfo()); - - if (!empty($this->view->result)) { - $form[$this->options['id']]['#tree'] = TRUE; - foreach ($this->view->result as $row_index => $row) { - $entity = $row->_entity; - $form[$this->options['id']][$row_index] = [ - '#type' => 'radio', - '#parents' => [$this->options['id']], - '#title' => $this->t('Compare this item'), - '#title_display' => 'invisible', - '#return_value' => $this->calculateEntityDiffFormKey($entity, $use_revision), - ]; - } - } - } - } diff -u b/src/Tests/DiffViewsTest.php b/src/Tests/DiffViewsTest.php --- b/src/Tests/DiffViewsTest.php +++ b/src/Tests/DiffViewsTest.php @@ -24,6 +24,9 @@ */ public static $modules = ['node', 'diff', 'user', 'diff_test']; + /** + * Tests the behavior of a view that uses the diff_from and diff_to fields. + */ public function testDiffView() { $node_type = NodeType::create([ 'type' => 'article', @@ -57,7 +60,7 @@ 'diff_to' => $to_second, ]; $this->drupalPostForm(NULL, $edit, t('Compare')); - $this->assertUrl(Url::fromRoute('diff.revisions_diff', ['left_vid' => 1, 'right_vid' => 2]), ['query' => ['destination' => '/node/1/diff-views']]); + $this->assertUrl(Url::fromRoute('diff.revisions_diff', ['node' => $node->id(), 'left_vid' => 1, 'right_vid' => 2]), ['query' => ['destination' => '/node/1/diff-views']]); $this->assertRaw('Test article: giraffe'); $this->assertRaw('Test article: llama'); }