diff --git a/CHANGELOG.md b/CHANGELOG.md index 4568b81..8f95b13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ### Unreleased +### v1.5.0-beta3 (2020-10-09) + +* Init the DeviceIdentifier to a fixed value in the CLI environment without setting any cookies, to prevent + errors if the process has already sent output. * Add MutexWrapper with Mock and Db (mysql) backed implementations for preventing concurrent executions of code. diff --git a/src/Logging/DeviceIdentifier.php b/src/Logging/DeviceIdentifier.php index e3c5838..7c8667d 100644 --- a/src/Logging/DeviceIdentifier.php +++ b/src/Logging/DeviceIdentifier.php @@ -45,10 +45,19 @@ public static function forceGlobalTestValue(string $id): void * before sending any output. * * @param bool $ssl_available + * @param bool $is_cli */ - public static function initAndEnsureCookieSet(bool $ssl_available): void + public static function initAndEnsureCookieSet(bool $ssl_available, bool $is_cli = (PHP_SAPI === 'cli')): void { - static::$instance = new DeviceIdentifier(new CookieWrapper($ssl_available)); + if ($is_cli) { + // Stub the class without setting cookies for use in a CLI environment. + // Note that as it's not really appropriate to inject the `is_cli` arg to `::get()`, and we can't stub + // PHP_SAPI for testing, that method will still return `-unset-` if it is called before + // ::initAndEnsureCookieSet() + static::forceGlobalTestValue(static::CLI_ID); + } else { + static::$instance = new DeviceIdentifier(new CookieWrapper($ssl_available)); + } static::$instance->init(); } @@ -68,8 +77,9 @@ public static function get(): string return $i->getValue(); } + const CLI_ID = 'cli-------------------'; const COOKIE_LIFETIME = 'P5Y'; - const VALID_REGEX = '/^[a-zA-Z0-9\-_=]{22}$/'; + const VALID_REGEX = '/^[a-zA-Z0-9\-_=]{22}$/'; /** * @var string|null diff --git a/test/unit/Logging/DeviceIdentifierTest.php b/test/unit/Logging/DeviceIdentifierTest.php index 517a1e3..6fa56c3 100644 --- a/test/unit/Logging/DeviceIdentifierTest.php +++ b/test/unit/Logging/DeviceIdentifierTest.php @@ -154,7 +154,7 @@ function () { DeviceIdentifier::$instance = NULL; } $old_cookie = $_COOKIE; try { $_COOKIE['did'] = '1234567890123456789012'; - DeviceIdentifier::initAndEnsureCookieSet(TRUE); + DeviceIdentifier::initAndEnsureCookieSet(TRUE, FALSE); $this->assertSame('1234567890123456789012', DeviceIdentifier::get()); // Note that here the init method has assigned a global instance so changes to $_COOKIE @@ -168,6 +168,18 @@ function () { DeviceIdentifier::$instance = NULL; } $this->assertSame('1234567890123456789012', DeviceIdentifier::get()); } + public function test_its_static_init_creates_instance_and_initialises_with_fixed_id_in_cli() + { + ScopeChangingCaller::call( + DeviceIdentifier::class, + function () { DeviceIdentifier::$instance = NULL; } + ); + + DeviceIdentifier::initAndEnsureCookieSet(TRUE); // Fall back to default arg + $this->assertSame(DeviceIdentifier::CLI_ID, DeviceIdentifier::get()); + $this->assertRegExp(DeviceIdentifier::VALID_REGEX, DeviceIdentifier::get()); + } + public function test_its_static_get_can_read_from_cookies_even_if_not_initialised() { ScopeChangingCaller::call(