From f3119f6a1d692c5a183593fe36b3e8a913480a59 Mon Sep 17 00:00:00 2001
From: Nathaniel Catchpole <catch@35733.no-reply.drupal.org>
Date: Wed, 14 Sep 2016 10:19:34 +0100
Subject: [PATCH] Issue #2539634 by Berdir, dawehner, cilefen, mpp,
 claudiu.cristea, amateescu, kristiaanvandeneynde: PathItem::delete() never
 runs because the path field type is a computed field in disguise

---
 .../content_translation.admin.inc             |  2 +-
 core/modules/path/path.install                | 32 +++++++++++++++++++
 core/modules/path/path.module                 | 14 +-------
 .../Field/FieldType/PathFieldItemList.php     | 13 ++++++++
 .../src/Plugin/Field/FieldType/PathItem.php   |  9 ------
 core/modules/path/src/Tests/PathAliasTest.php | 12 +++++++
 .../path/src/Tests/PathLanguageTest.php       |  5 +++
 7 files changed, 64 insertions(+), 23 deletions(-)
 create mode 100644 core/modules/path/path.install

diff --git a/core/modules/content_translation/content_translation.admin.inc b/core/modules/content_translation/content_translation.admin.inc
index 057d93adbe5e..39e3247ca17b 100644
--- a/core/modules/content_translation/content_translation.admin.inc
+++ b/core/modules/content_translation/content_translation.admin.inc
@@ -113,7 +113,7 @@ function _content_translation_form_language_content_settings_form_alter(array &$
       $fields = $entity_manager->getFieldDefinitions($entity_type_id, $bundle);
       if ($fields) {
         foreach ($fields as $field_name => $definition) {
-          if (!empty($storage_definitions[$field_name]) && _content_translation_is_field_translatability_configurable($entity_type, $storage_definitions[$field_name])) {
+          if ($definition->isComputed() || (!empty($storage_definitions[$field_name]) && _content_translation_is_field_translatability_configurable($entity_type, $storage_definitions[$field_name]))) {
             $form['settings'][$entity_type_id][$bundle]['fields'][$field_name] = array(
               '#label' => $definition->getLabel(),
               '#type' => 'checkbox',
diff --git a/core/modules/path/path.install b/core/modules/path/path.install
new file mode 100644
index 000000000000..7d454a00b089
--- /dev/null
+++ b/core/modules/path/path.install
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * @file
+ * Update functions for the path module.
+ */
+
+/**
+ * @addtogroup updates-8.2.0
+ * @{
+ */
+
+/**
+ * Change the path field to computed for node and taxonomy_term.
+ */
+function path_update_8200() {
+  $entity_definition_update_manager = \Drupal::entityDefinitionUpdateManager();
+  foreach (['node', 'taxonomy_term'] as $entity_type_id) {
+    if ($entity_definition_update_manager->getEntityType($entity_type_id)) {
+      // Computed field definitions are not tracked by the entity definition
+      // update manager, so remove them.
+      $storage_definition = $entity_definition_update_manager->getFieldStorageDefinition('path', $entity_type_id);
+      if ($storage_definition) {
+        $entity_definition_update_manager->uninstallFieldStorageDefinition($storage_definition);
+      }
+    }
+  }
+}
+
+/**
+ * @} End of "addtogroup updates-8.2.0".
+ */
diff --git a/core/modules/path/path.module b/core/modules/path/path.module
index 3d7f1d0533de..182c6a9dd09b 100644
--- a/core/modules/path/path.module
+++ b/core/modules/path/path.module
@@ -5,7 +5,6 @@
  * Enables users to rename URLs.
  */
 
-use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Field\BaseFieldDefinition;
 use Drupal\Core\Form\FormStateInterface;
@@ -72,19 +71,8 @@ function path_entity_base_field_info(EntityTypeInterface $entity_type) {
         'weight' => 30,
       ))
       ->setDisplayConfigurable('form', TRUE)
-      ->setCustomStorage(TRUE);
+      ->setComputed(TRUE);
 
     return $fields;
   }
 }
-
-/**
- * Implements hook_entity_translation_delete().
- */
-function path_entity_translation_delete(EntityInterface $translation) {
-  if ($translation->hasLinkTemplate('canonical')) {
-    $path = $translation->urlInfo()->getInternalPath();
-    $conditions = array('source' => '/' . $path, 'langcode' => $translation->language()->getId());
-    \Drupal::service('path.alias_storage')->delete($conditions);
-  }
-}
diff --git a/core/modules/path/src/Plugin/Field/FieldType/PathFieldItemList.php b/core/modules/path/src/Plugin/Field/FieldType/PathFieldItemList.php
index ceb091559a54..ee03361d961d 100644
--- a/core/modules/path/src/Plugin/Field/FieldType/PathFieldItemList.php
+++ b/core/modules/path/src/Plugin/Field/FieldType/PathFieldItemList.php
@@ -21,4 +21,17 @@ public function defaultAccess($operation = 'view', AccountInterface $account = N
     return AccessResult::allowedIfHasPermissions($account, ['create url aliases', 'administer url aliases'], 'OR')->cachePerPermissions();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function delete() {
+    // Delete all aliases associated with this entity in the current language.
+    $entity = $this->getEntity();
+    $conditions = [
+      'source' => '/' . $entity->toUrl()->getInternalPath(),
+      'langcode' => $entity->language()->getId(),
+    ];
+    \Drupal::service('path.alias_storage')->delete($conditions);
+  }
+
 }
diff --git a/core/modules/path/src/Plugin/Field/FieldType/PathItem.php b/core/modules/path/src/Plugin/Field/FieldType/PathItem.php
index 2d8fb1e056e4..239588fd5150 100644
--- a/core/modules/path/src/Plugin/Field/FieldType/PathItem.php
+++ b/core/modules/path/src/Plugin/Field/FieldType/PathItem.php
@@ -72,15 +72,6 @@ public function postSave($update) {
     }
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function delete() {
-    // Delete all aliases associated with this entity.
-    $entity = $this->getEntity();
-    \Drupal::service('path.alias_storage')->delete(array('source' => '/' . $entity->urlInfo()->getInternalPath()));
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/path/src/Tests/PathAliasTest.php b/core/modules/path/src/Tests/PathAliasTest.php
index c7e70d2e67e1..28c582dd4f13 100644
--- a/core/modules/path/src/Tests/PathAliasTest.php
+++ b/core/modules/path/src/Tests/PathAliasTest.php
@@ -314,6 +314,18 @@ function testNodeAlias() {
     $this->drupalGet(trim($edit['path[0][alias]'], '/'));
     $this->assertText($node4->label(), 'Alias trimmed trailing slash.');
     $this->assertResponse(200);
+
+    // Create fifth test node.
+    $node5 = $this->drupalCreateNode();
+
+    // Set a path alias.
+    $edit = array('path[0][alias]' => '/' . $this->randomMachineName(8));
+    $this->drupalPostForm('node/' . $node5->id() . '/edit', $edit, t('Save'));
+
+    // Delete the node and check that the path alias is also deleted.
+    $node5->delete();
+    $path_alias = \Drupal::service('path.alias_storage')->lookupPathAlias('/node/' . $node5->id(), $node5->language()->getId());
+    $this->assertFalse($path_alias, 'Alias was successfully deleted when the referenced node was deleted.');
   }
 
   /**
diff --git a/core/modules/path/src/Tests/PathLanguageTest.php b/core/modules/path/src/Tests/PathLanguageTest.php
index 695f6be61ce8..4cb2c994bf42 100644
--- a/core/modules/path/src/Tests/PathLanguageTest.php
+++ b/core/modules/path/src/Tests/PathLanguageTest.php
@@ -186,6 +186,11 @@ function testAliasTranslation() {
     $english_node->removeTranslation('fr');
     $english_node->save();
     $this->assertFalse($this->container->get('path.alias_storage')->aliasExists('/' . $french_alias, 'fr'), 'Alias for French translation is removed when translation is deleted.');
+
+    // Check that the English alias still works.
+    $this->drupalGet($english_alias);
+    $this->assertTrue($this->container->get('path.alias_storage')->aliasExists('/' . $english_alias, 'en'), 'English alias is not deleted when French translation is removed.');
+    $this->assertText($english_node->body->value, 'English alias still works');
   }
 
 }
-- 
GitLab