From af54540567b84bd830f542cda4845ee3a1baacdc Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Tue, 19 Jan 2016 14:57:43 +0000
Subject: [PATCH] Issue #2510150 by tduong, Berdir: AccountProxy is not calling
 date_set_default_timezone() for anonymous users

---
 .../AuthenticationSubscriber.php              |  3 ++
 core/lib/Drupal/Core/Logger/LoggerChannel.php | 14 +++++--
 core/lib/Drupal/Core/Session/AccountProxy.php |  2 +-
 .../rdf/src/Tests/NodeAttributesTest.php      |  8 ++--
 .../simpletest/src/Tests/TimeZoneTest.php     | 42 +++++++++++++++++++
 core/modules/simpletest/src/WebTestBase.php   |  9 ++++
 .../src/Controller/SystemTestController.php   | 12 ++++++
 .../system_test/system_test.routing.yml       |  9 ++++
 .../user/src/Tests/UserTimeZoneTest.php       | 16 ++++++-
 9 files changed, 106 insertions(+), 9 deletions(-)
 create mode 100644 core/modules/simpletest/src/Tests/TimeZoneTest.php

diff --git a/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php
index 6fd0b9997c4e..da0ff6646a58 100644
--- a/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php
@@ -83,8 +83,11 @@ public function onKernelRequestAuthenticate(GetResponseEvent $event) {
         $account = $this->authenticationProvider->authenticate($request);
         if ($account) {
           $this->accountProxy->setAccount($account);
+          return;
         }
       }
+      // No account has been set explicitly, initialize the timezone here.
+      date_default_timezone_set(drupal_get_user_timezone());
     }
   }
 
diff --git a/core/lib/Drupal/Core/Logger/LoggerChannel.php b/core/lib/Drupal/Core/Logger/LoggerChannel.php
index 77b84a85ed70..8e0890c99937 100644
--- a/core/lib/Drupal/Core/Logger/LoggerChannel.php
+++ b/core/lib/Drupal/Core/Logger/LoggerChannel.php
@@ -93,9 +93,17 @@ public function log($level, $message, array $context = array()) {
       $context['request_uri'] = $request->getUri();
       $context['referer'] = $request->headers->get('Referer', '');
       $context['ip'] = $request->getClientIP();
-      if ($this->currentUser) {
-        $context['user'] = $this->currentUser;
-        $context['uid'] = $this->currentUser->id();
+      try {
+        if ($this->currentUser) {
+          $context['user'] = $this->currentUser;
+          $context['uid'] = $this->currentUser->id();
+        }
+      }
+      catch (\Exception $e) {
+        // An exception might be thrown if the database connection is not
+        // available or due to another unexpected reason. It is more important
+        // to log the error that we already have so any additional exceptions
+        // are ignored.
       }
     }
 
diff --git a/core/lib/Drupal/Core/Session/AccountProxy.php b/core/lib/Drupal/Core/Session/AccountProxy.php
index 4d6db573a70d..9bc8c1bcdca2 100644
--- a/core/lib/Drupal/Core/Session/AccountProxy.php
+++ b/core/lib/Drupal/Core/Session/AccountProxy.php
@@ -56,7 +56,7 @@ public function getAccount() {
         // After the container is rebuilt, DrupalKernel sets the initial
         // account to the id of the logged in user. This is necessary in order
         // to refresh the user account reference here.
-        $this->account = $this->loadUserEntity($this->initialAccountId);
+        $this->setAccount($this->loadUserEntity($this->initialAccountId));
       }
       else {
         $this->account = new AnonymousUserSession();
diff --git a/core/modules/rdf/src/Tests/NodeAttributesTest.php b/core/modules/rdf/src/Tests/NodeAttributesTest.php
index 43f736a52dee..29c9882c7fb7 100644
--- a/core/modules/rdf/src/Tests/NodeAttributesTest.php
+++ b/core/modules/rdf/src/Tests/NodeAttributesTest.php
@@ -80,17 +80,17 @@ function testNodeAttributes() {
       'lang' => 'en',
     );
     $this->assertTrue($graph->hasProperty($node_uri, 'http://purl.org/dc/terms/title', $expected_value), 'Node title found in RDF output (dc:title).');
-    // Node date.
+    // Node date (date format must be UTC).
     $expected_value = array(
       'type' => 'literal',
-      'value' => date('c', $node->getCreatedTime()),
+      'value' => \Drupal::service('date.formatter')->format($node->getCreatedTime(), 'custom', 'c', 'UTC'),
       'datatype' => 'http://www.w3.org/2001/XMLSchema#dateTime',
     );
     $this->assertTrue($graph->hasProperty($node_uri, 'http://purl.org/dc/terms/date', $expected_value), 'Node date found in RDF output (dc:date).');
-    // Node date.
+    // Node date (date format must be UTC).
     $expected_value = array(
       'type' => 'literal',
-      'value' => date('c', $node->getCreatedTime()),
+      'value' => \Drupal::service('date.formatter')->format($node->getCreatedTime(), 'custom', 'c', 'UTC'),
       'datatype' => 'http://www.w3.org/2001/XMLSchema#dateTime',
     );
     $this->assertTrue($graph->hasProperty($node_uri, 'http://purl.org/dc/terms/created', $expected_value), 'Node date found in RDF output (dc:created).');
diff --git a/core/modules/simpletest/src/Tests/TimeZoneTest.php b/core/modules/simpletest/src/Tests/TimeZoneTest.php
new file mode 100644
index 000000000000..00c93f6f6d76
--- /dev/null
+++ b/core/modules/simpletest/src/Tests/TimeZoneTest.php
@@ -0,0 +1,42 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\simpletest\Tests\TimeZoneTest.
+ */
+
+namespace Drupal\simpletest\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * This test will check SimpleTest's default time zone handling.
+ *
+ * @group simpletest
+ */
+class TimeZoneTest extends WebTestBase {
+
+  /**
+   * A user with administrative privileges.
+   */
+  protected $adminUser;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->adminUser = $this->drupalCreateUser(['administer site configuration']);
+  }
+
+  /**
+   * Tests that user accounts have the default time zone set.
+   */
+  function testAccountTimeZones() {
+    $expected = 'Australia/Sydney';
+    $this->assertEqual($this->rootUser->getTimeZone(), $expected, 'Root user has correct time zone.');
+    $this->assertEqual($this->adminUser->getTimeZone(), $expected, 'Admin user has correct time zone.');
+  }
+
+}
diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php
index c5fba7f2d4fe..820e562d6467 100644
--- a/core/modules/simpletest/src/WebTestBase.php
+++ b/core/modules/simpletest/src/WebTestBase.php
@@ -528,6 +528,14 @@ protected function drupalLogout() {
    * being executed.
    */
   protected function setUp() {
+    // Set an explicit time zone to not rely on the system one, which may vary
+    // from setup to setup. The Australia/Sydney time zone is chosen so all
+    // tests are run using an edge case scenario (UTC+10 and DST). This choice
+    // is made to prevent time zone related regressions and reduce the
+    // fragility of the testing system in general. This is also set in config in
+    // \Drupal\simpletest\WebTestBase::initConfig().
+    date_default_timezone_set('Australia/Sydney');
+
     // Preserve original batch for later restoration.
     $this->setBatch();
 
@@ -837,6 +845,7 @@ protected function initUserSession() {
       'name' => 'admin',
       'mail' => 'admin@example.com',
       'pass_raw' => $this->randomMachineName(),
+      'timezone' => date_default_timezone_get(),
     ));
 
     // The child site derives its session name from the database prefix when
diff --git a/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php b/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php
index 9d35102722bb..1d8c7b61295e 100644
--- a/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php
+++ b/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php
@@ -341,4 +341,16 @@ public function permissionDependentContent() {
     return $build;
   }
 
+  /**
+   * Returns the current date.
+   *
+   * @return \Symfony\Component\HttpFoundation\Response $response
+   *   A Response object containing the current date.
+   */
+  public function getCurrentDate() {
+    // Uses specific time to test that the right timezone is used.
+    $response = new Response(\Drupal::service('date.formatter')->format(1452702549));
+    return $response;
+  }
+
 }
diff --git a/core/modules/system/tests/modules/system_test/system_test.routing.yml b/core/modules/system/tests/modules/system_test/system_test.routing.yml
index 1fb4069c1d48..a933048daaf7 100644
--- a/core/modules/system/tests/modules/system_test/system_test.routing.yml
+++ b/core/modules/system/tests/modules/system_test/system_test.routing.yml
@@ -150,3 +150,12 @@ system_test.respond_cacheable_response:
     _controller: '\Drupal\system_test\Controller\SystemTestController::respondWithCacheableReponse'
   requirements:
     _access: 'TRUE'
+
+system_test.date:
+  path: '/system-test/date'
+  defaults:
+    _controller: '\Drupal\system_test\Controller\SystemTestController::getCurrentDate'
+  options:
+    no_cache: 'TRUE'
+  requirements:
+    _access: 'TRUE'
diff --git a/core/modules/user/src/Tests/UserTimeZoneTest.php b/core/modules/user/src/Tests/UserTimeZoneTest.php
index 300f57bd1e04..a061795945ac 100644
--- a/core/modules/user/src/Tests/UserTimeZoneTest.php
+++ b/core/modules/user/src/Tests/UserTimeZoneTest.php
@@ -21,7 +21,7 @@ class UserTimeZoneTest extends WebTestBase {
    *
    * @var array
    */
-  public static $modules = array('node');
+  public static $modules = array('node', 'system_test');
 
   /**
    * Tests the display of dates and time when user-configurable time zones are set.
@@ -73,5 +73,19 @@ function testUserTimeZone() {
     $this->assertText('2007-03-11 05:00 CLT', 'Date should be Chile time; four hours ahead of PST');
     $this->drupalGet('node/' . $node3->id());
     $this->assertText('2007-03-21 00:00 CLT', 'Date should be Chile time; three hours ahead of PDT.');
+
+    // Ensure that anonymous users also use the default timezone.
+    $this->drupalLogout();
+    $this->drupalGet('node/' . $node1->id());
+    $this->assertText('2007-03-09 21:00 PST', 'Date should be PST.');
+    $this->drupalGet('node/' . $node2->id());
+    $this->assertText('2007-03-11 01:00 PST', 'Date should be PST.');
+    $this->drupalGet('node/' . $node3->id());
+    $this->assertText('2007-03-20 21:00 PDT', 'Date should be PDT.');
+
+    // Format a date without accessing the current user at all and
+    // ensure that it uses the default timezone.
+    $this->drupalGet('/system-test/date');
+    $this->assertText('2016-01-13 08:29 PST', 'Date should be PST.');
   }
 }
-- 
GitLab