From da21d14ac51a97c1d0ffe5c7054858f5f4ef7400 Mon Sep 17 00:00:00 2001
From: catch <catch@35733.no-reply.drupal.org>
Date: Fri, 14 Feb 2020 09:51:24 +0000
Subject: [PATCH] Issue #3113476 by alexpott, mpdonadio: Fallback when request
 is not available on the stack in Time service

---
 core/lib/Drupal/Component/Datetime/Time.php   | 16 ++++++++++++--
 .../Component/Datetime/TimeInterface.php      |  6 +++++
 .../Tests/Component/Datetime/TimeTest.php     | 22 +++++++++++++++++++
 3 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/core/lib/Drupal/Component/Datetime/Time.php b/core/lib/Drupal/Component/Datetime/Time.php
index 77da2e2c1f5e..566debba0494 100644
--- a/core/lib/Drupal/Component/Datetime/Time.php
+++ b/core/lib/Drupal/Component/Datetime/Time.php
@@ -30,14 +30,26 @@ public function __construct(RequestStack $request_stack) {
    * {@inheritdoc}
    */
   public function getRequestTime() {
-    return $this->requestStack->getCurrentRequest()->server->get('REQUEST_TIME');
+    $request = $this->requestStack->getCurrentRequest();
+    if ($request) {
+      return $request->server->get('REQUEST_TIME');
+    }
+    // If this is called prior to the request being pushed to the stack fallback
+    // to built-in globals (if available) or the system time.
+    return $_SERVER['REQUEST_TIME'] ?? $this->getCurrentTime();
   }
 
   /**
    * {@inheritdoc}
    */
   public function getRequestMicroTime() {
-    return $this->requestStack->getCurrentRequest()->server->get('REQUEST_TIME_FLOAT');
+    $request = $this->requestStack->getCurrentRequest();
+    if ($request) {
+      return $request->server->get('REQUEST_TIME_FLOAT');
+    }
+    // If this is called prior to the request being pushed to the stack fallback
+    // to built-in globals (if available) or the system time.
+    return $_SERVER['REQUEST_TIME_FLOAT'] ?? $this->getCurrentMicroTime();
   }
 
   /**
diff --git a/core/lib/Drupal/Component/Datetime/TimeInterface.php b/core/lib/Drupal/Component/Datetime/TimeInterface.php
index 0c81575c73a1..cedea4fe80da 100644
--- a/core/lib/Drupal/Component/Datetime/TimeInterface.php
+++ b/core/lib/Drupal/Component/Datetime/TimeInterface.php
@@ -14,6 +14,9 @@ interface TimeInterface {
    * of the request. It will be the same value for the life of the request
    * (even for long execution times).
    *
+   * If the request is not available it will fallback to the current system
+   * time.
+   *
    * This method can replace instances of
    * @code
    * $request_time = $_SERVER['REQUEST_TIME'];
@@ -50,6 +53,9 @@ public function getRequestTime();
    * microsecond precision, at the start of the request. It will be the same
    * value for the life of the request (even for long execution times).
    *
+   * If the request is not available it will fallback to the current system
+   * time with microsecond precision.
+   *
    * This method can replace instances of
    * @code
    * $request_time_float = $_SERVER['REQUEST_TIME_FLOAT'];
diff --git a/core/tests/Drupal/Tests/Component/Datetime/TimeTest.php b/core/tests/Drupal/Tests/Component/Datetime/TimeTest.php
index e3723135c64d..ddc9d585278b 100644
--- a/core/tests/Drupal/Tests/Component/Datetime/TimeTest.php
+++ b/core/tests/Drupal/Tests/Component/Datetime/TimeTest.php
@@ -79,6 +79,28 @@ public function testGetRequestMicroTime() {
     $this->assertEquals($expected, $this->time->getRequestMicroTime());
   }
 
+  /**
+   * @covers ::getRequestTime
+   */
+  public function testGetRequestTimeNoRequest() {
+    $expected = 12345678;
+    unset($_SERVER['REQUEST_TIME']);
+    $this->assertEquals($expected, $this->time->getRequestTime());
+    $_SERVER['REQUEST_TIME'] = 23456789;
+    $this->assertEquals(23456789, $this->time->getRequestTime());
+  }
+
+  /**
+   * @covers ::getRequestMicroTime
+   */
+  public function testGetRequestMicroTimeNoRequest() {
+    $expected = 1234567.89;
+    unset($_SERVER['REQUEST_TIME_FLOAT']);
+    $this->assertEquals($expected, $this->time->getRequestMicroTime());
+    $_SERVER['REQUEST_TIME_FLOAT'] = 2345678.90;
+    $this->assertEquals(2345678.90, $this->time->getRequestMicroTime());
+  }
+
   /**
    * Tests the getCurrentTime method.
    *
-- 
GitLab