From 713431e500dbee860887237cf6ddb0d65edda1e0 Mon Sep 17 00:00:00 2001
From: James Sansbury <james.sansbury@lullabot.com>
Date: Thu, 27 Jun 2013 17:13:34 -0400
Subject: [PATCH] Issue #1499532: Allow programmatic altering of the node path
 alias language.

---
 .../lib/Drupal/path/Tests/PathLanguageTest.php     |   30 +++++++++++++++++
 core/modules/path/path.module                      |   34 ++++++++++++--------
 2 files changed, 50 insertions(+), 14 deletions(-)

diff --git a/core/modules/path/lib/Drupal/path/Tests/PathLanguageTest.php b/core/modules/path/lib/Drupal/path/Tests/PathLanguageTest.php
index 291b633..8b49ec0 100644
--- a/core/modules/path/lib/Drupal/path/Tests/PathLanguageTest.php
+++ b/core/modules/path/lib/Drupal/path/Tests/PathLanguageTest.php
@@ -162,5 +162,35 @@ function testAliasTranslation() {
     // Second call should return the same alias.
     $french_node_alias = $this->container->get('path.alias_manager')->getPathAlias('node/' . $french_node->nid, $french_node->langcode);
     $this->assertEqual($french_node_alias, $french_alias, 'Alias is the same.');
+
+    // Test that the alias language is the same as the node language by default.
+    // We do this by creating an english node with a path alias, then loading
+    // the alias directly to be sure it matches.
+    $test_node = $this->drupalCreateNode(array('type' => 'page'));
+    $test_alias = $this->randomName();
+
+    $edit = array();
+    $edit['langcode'] = 'en';
+    $edit['path[alias]'] = $test_alias;
+    $this->drupalPost('node/' . $test_node->nid . '/edit', $edit, t('Save'));
+
+    // Now load the path and ensure the langcodes match.
+    $conditions = array(
+      'source' => 'node/' . $test_node->nid,
+      'langcode' => $edit['langcode'],
+    );
+    $path = \Drupal::service('path.crud')->load($conditions);
+    $this->assertEqual($path['langcode'], $edit['langcode'],
+      t('Alias language is equivalent to node language by default.'));
+
+    // Test that a node path alias langcode can be changed programmatically.
+    $test_node = $this->drupalGetNodeByTitle($test_node->title);
+    $test_node->path = $path;
+    $test_node->path['langcode'] = Language::LANGCODE_NOT_SPECIFIED;
+    $test_node->save();
+    $conditions['langcode'] = Language::LANGCODE_NOT_SPECIFIED;
+    $path = \Drupal::service('path.crud')->load($conditions);
+    $this->assertEqual($path['langcode'], Language::LANGCODE_NOT_SPECIFIED,
+      t('Alias language can be altered independently of node language.'));
   }
 }
diff --git a/core/modules/path/path.module b/core/modules/path/path.module
index efc59a8..21f289f 100644
--- a/core/modules/path/path.module
+++ b/core/modules/path/path.module
@@ -113,9 +113,12 @@ function path_form_node_form_alter(&$form, $form_state) {
     'pid' => NULL,
     'source' => isset($node->nid) ? 'node/' . $node->nid : NULL,
     'alias' => '',
-    'langcode' => isset($node->langcode) ? $node->langcode : Language::LANGCODE_NOT_SPECIFIED,
   );
 
+  // Force the path langcode to NULL here. It will be set in the validate
+  // handler if not set programmatically by a form alter or other means.
+  $path['langcode'] = NULL;
+
   $form['path'] = array(
     '#type' => 'details',
     '#title' => t('URL path settings'),
@@ -160,8 +163,13 @@ function path_form_element_validate($element, &$form_state, $complete_form) {
     // originally assigned URL alias language.
     // @todo Remove this after converting Path module to a field, and, after
     //   stopping Locale module from abusing the content language system.
-    if (isset($form_state['values']['langcode'])) {
-      form_set_value($element['langcode'], $form_state['values']['langcode'], $form_state);
+    // We only set the language if it isn't explicitly set on the path. Since
+    // the path's langcode is set to NULL in the form, the value would only be
+    // set by a form alter or other means.
+    if (!isset($form_state['values']['path']['langcode'])) {
+      // If the node's langcode isn't set, use LANGCODE_NOT_SPECIFIED.
+      $langcode = isset($form_state['values']['langcode']) ? $form_state['values']['langcode'] : Language::LANGCODE_NOT_SPECIFIED;
+      form_set_value($element['langcode'], $langcode, $form_state);
     }
 
     $path = $form_state['values']['path'];
@@ -185,16 +193,7 @@ function path_form_element_validate($element, &$form_state, $complete_form) {
  * Implements hook_node_insert().
  */
 function path_node_insert(EntityInterface $node) {
-  if (isset($node->path)) {
-    $alias = trim($node->path['alias']);
-    // Only save a non-empty alias.
-    if (!empty($alias)) {
-      // Ensure fields for programmatic executions.
-      $source = 'node/' . $node->nid;
-      $langcode = isset($node->langcode) ? $node->langcode : Language::LANGCODE_NOT_SPECIFIED;
-      Drupal::service('path.crud')->save($source, $alias, $langcode);
-    }
-  }
+  path_node_update($node);
 }
 
 /**
@@ -203,6 +202,9 @@ function path_node_insert(EntityInterface $node) {
 function path_node_update(EntityInterface $node) {
   if (isset($node->path)) {
     $path = $node->path;
+    // Since path_node_insert() also calls this function, make sure pid and
+    // alias are set to NULL if they aren't set.
+    $path += array('pid' => NULL, 'alias' => NULL);
     $alias = trim($path['alias']);
     // Delete old alias if user erased it.
     if (!empty($path['pid']) && empty($path['alias'])) {
@@ -212,7 +214,11 @@ function path_node_update(EntityInterface $node) {
     if (!empty($path['alias'])) {
       // Ensure fields for programmatic executions.
       $source = 'node/' . $node->nid;
-      $langcode = isset($node->langcode) ? $node->langcode : Language::LANGCODE_NOT_SPECIFIED;
+      // The node's langcode will be used for the path's langcode if it wasn't
+      // set. If the node's langcode isn't set, use LANGCODE_NOT_SPECIFIED.
+      $node_langcode = isset($node->langcode) ? $node->langcode : Language::LANGCODE_NOT_SPECIFIED;
+      // If the path langcode is not specified, use the node's langcode.
+      $langcode = isset($node->path['langcode']) ? $node->path['langcode'] : $node_langcode;
       Drupal::service('path.crud')->save($source, $alias, $langcode, $path['pid']);
     }
   }
-- 
1.7.10.4

