From 364373250cb85d771dded718c25f32c4f6bfd675 Mon Sep 17 00:00:00 2001 From: MGatner Date: Fri, 15 Jan 2021 15:43:41 +0000 Subject: [PATCH] Enable namespace service precedence --- app/Config/Services.php | 4 ++-- phpstan.neon.dist | 1 + system/Common.php | 2 +- system/Config/BaseService.php | 2 +- system/Config/Services.php | 4 ++-- tests/_support/Config/Services.php | 9 +++++---- tests/system/Config/ServicesTest.php | 18 ++++++++---------- user_guide_src/source/changelogs/v4.0.5.rst | 1 + .../source/installation/upgrade_405.rst | 5 +++++ 9 files changed, 26 insertions(+), 20 deletions(-) diff --git a/app/Config/Services.php b/app/Config/Services.php index 684d9aed35..898bcd030f 100644 --- a/app/Config/Services.php +++ b/app/Config/Services.php @@ -2,7 +2,7 @@ namespace Config; -use CodeIgniter\Config\Services as CoreServices; +use CodeIgniter\Config\BaseService; /** * Services Configuration file. @@ -17,7 +17,7 @@ use CodeIgniter\Config\Services as CoreServices; * method format you should use for your service methods. For more examples, * see the core Services file at system/Config/Services.php. */ -class Services extends CoreServices +class Services extends BaseService { // public static function example($getShared = true) // { diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 64d7f74c47..b77464cdfb 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -37,6 +37,7 @@ parameters: - '#Call to an undefined method CodeIgniter\\Database\\BaseConnection::supportsForeignKeys\(\)#' - '#Call to an undefined method CodeIgniter\\Database\\ConnectionInterface::(tableExists|protectIdentifiers|setAliasedTables|escapeIdentifiers|affectedRows|addTableAlias|getIndexData)\(\)#' - '#Call to an undefined method CodeIgniter\\Router\\RouteCollectionInterface::(getDefaultNamespace|isFiltered|getFilterForRoute|getRoutesOptions)\(\)#' + - '#Call to an undefined static method Config\\Services::[a-z]+\(\)#' - '#Cannot access property [\$a-z_]+ on ((bool\|)?object\|resource)#' - '#Cannot call method [a-zA-Z_]+\(\) on ((bool\|)?object\|resource)#' - '#Method CodeIgniter\\Database\\ConnectionInterface::query\(\) invoked with 3 parameters, 1-2 required#' diff --git a/system/Common.php b/system/Common.php index 56264267ac..ac0a0a7ff4 100644 --- a/system/Common.php +++ b/system/Common.php @@ -907,7 +907,7 @@ if (! function_exists('redirect')) */ function redirect(string $uri = null): RedirectResponse { - $response = Services::redirectResponse(null, true); + $response = Services::redirectresponse(null, true); if (! empty($uri)) { diff --git a/system/Config/BaseService.php b/system/Config/BaseService.php index 5435439093..bdcb269114 100644 --- a/system/Config/BaseService.php +++ b/system/Config/BaseService.php @@ -182,7 +182,7 @@ class BaseService public static function serviceExists(string $name): ?string { static::buildServicesCache(); - $services = array_merge([Services::class], self::$serviceNames); + $services = array_merge(self::$serviceNames, [Services::class]); $name = strtolower($name); foreach ($services as $service) diff --git a/system/Config/Services.php b/system/Config/Services.php index 0b41dc0d35..6f8b4ba136 100644 --- a/system/Config/Services.php +++ b/system/Config/Services.php @@ -600,11 +600,11 @@ class Services extends BaseService * * @return RedirectResponse */ - public static function redirectResponse(App $config = null, bool $getShared = true) + public static function redirectresponse(App $config = null, bool $getShared = true) { if ($getShared) { - return static::getSharedInstance('redirectResponse', $config); + return static::getSharedInstance('redirectresponse', $config); } $config = $config ?? config('App'); diff --git a/tests/_support/Config/Services.php b/tests/_support/Config/Services.php index 15c2426a32..c13ed388a0 100644 --- a/tests/_support/Config/Services.php +++ b/tests/_support/Config/Services.php @@ -3,13 +3,13 @@ namespace Tests\Support\Config; use Config\Services as BaseServices; -use Tatter\Https\ServerRequest; +use RuntimeException; /** * Services Class * - * Defines our version of the HTTP services to override - * the framework defaults. + * Provides a replacement uri Service + * to demonstrate overriding core services. */ class Services extends BaseServices { @@ -23,9 +23,10 @@ class Services extends BaseServices */ public static function uri(string $uri = null, bool $getShared = true) { + // Intercept our test case if ($uri === 'testCanReplaceFrameworkServices') { - $_SESSION['testCanReplaceFrameworkServices'] = true; + throw new RuntimeException('Service originated from ' . static::class); } if ($getShared) diff --git a/tests/system/Config/ServicesTest.php b/tests/system/Config/ServicesTest.php index f520157ef0..6ee0821339 100644 --- a/tests/system/Config/ServicesTest.php +++ b/tests/system/Config/ServicesTest.php @@ -25,6 +25,14 @@ class ServicesTest extends CIUnitTestCase Services::reset(); } + public function testCanReplaceFrameworkServices() + { + $this->expectException('RuntimeException'); + $this->expectExceptionMessage('Service originated from Tests\Support\Config\Services'); + + Services::uri('testCanReplaceFrameworkServices'); + } + public function testNewAutoloader() { $actual = Services::autoloader(); @@ -351,14 +359,4 @@ class ServicesTest extends CIUnitTestCase $this->assertInstanceOf(\Config\Services::class, new \Config\Services()); rename(COMPOSER_PATH . '.backup', COMPOSER_PATH); } - - public function testCanReplaceFrameworkServices() - { - $this->assertArrayNotHasKey('testCanReplaceFrameworkServices', $_SESSION); - - Services::uri('testCanReplaceFrameworkServices'); - - $this->assertArrayHasKey('testCanReplaceFrameworkServices', $_SESSION); - unset($_SESSION['testCanReplaceFrameworkServices']); - } } diff --git a/user_guide_src/source/changelogs/v4.0.5.rst b/user_guide_src/source/changelogs/v4.0.5.rst index 9a55cf6d6e..1f05bb66ed 100644 --- a/user_guide_src/source/changelogs/v4.0.5.rst +++ b/user_guide_src/source/changelogs/v4.0.5.rst @@ -23,6 +23,7 @@ Bugs Fixed: - Fixed a bug in ``Entity`` class where declaring class parameters was preventing data propagation to the ``attributes`` array. - Handling for the environment variable ``encryption.key`` has changed. Previously, explicit function calls, like ``getenv('encryption.key')`` or ``env('encryption.key')`` where the value has the special prefix ``hex2bin:`` returns an automatically converted binary string. This is now changed to just return the character string with the prefix. This change was due to incompatibility with handling binary strings in environment variables on Windows platforms. However, accessing ``$key`` using ``Encryption`` class config remains unchanged and still returns a binary string. +- ``Config\Services`` (in **app/Config/Services.php**) now extends ``CodeIgniter\Config\BaseService`` to allow proper discovery of third-party services. Deprecations: diff --git a/user_guide_src/source/installation/upgrade_405.rst b/user_guide_src/source/installation/upgrade_405.rst index e8a5167321..4f66fef4b9 100644 --- a/user_guide_src/source/installation/upgrade_405.rst +++ b/user_guide_src/source/installation/upgrade_405.rst @@ -57,3 +57,8 @@ updated requirements. These methods are as follows: To facilitate use of this interface these methods have been moved from the framework's ``Response`` into a ``ResponseTrait`` which you may use, and ``DownloadResponse`` now extends ``Response`` directly to ensure maximum compatibility. + +**Config\Services** + +Service discovery has been updated to allow third-party services (when enabled via Modules) to take precedence over core services. Update +**app/Config/Services.php** so the class extends ``CodeIgniter\Config\BaseService`` to allow proper discovery of third-party services.