Skip to content
This repository was archived by the owner on Jan 29, 2020. It is now read-only.

Commit 0a531e2

Browse files
committed
Better ServiceLocatorAware deprecation
We were: - injecting any service that *was not* marked as `ServiceLocatorAware` but implemented `setServiceLocator()`, and - injecting any service that *was* marked `ServiceLocatorAware`, and - emitting a deprecation notice in both cases. The rationale was to allow backwards compatibility with existing implementations, while still messaging to users that they need to update their code not to rely on that. This created a few problems, though: - *Every* controller inheriting from `AbstractController` now emits deprecation notices on instantiation. - Developers who had implemented a `setServiceLocator()` method without implementing `ServiceLocatorAwareInterface` were now getting auto-injected with the service locator instance when they did not expect to. This patch attempts to address those issues as follows: - `ServiceManagerConfig` updates its service locator initializer to: - Inject non-plugin manager `ServiceLocatorAware` instances; in this situation, a deprecation notice *is* emitted. - For `ServiceLocatorAware` plugin managers, it checks to see if a service locator is already composed. If not, it will inject it, but then emit a deprecation notice indicating that the service locator should be injected as a constructor parameter. - `ControllerManager` updates its service locator initializer to: - For non-`ServiceLocatorAware` `AbstractController` implementations, it injects the service locator with no notices. - For all explicitly `ServiceLocatorAware` controllers, it injects the service locator *and* emits a deprecation notice. - It no longer injects non-`ServiceLocatorAware` controllers that implement `setServiceLocator()` unless they extend `AbstractController`. This is fully backwards compatible. - `AbstractController::getServiceLocator()` now emits a deprecation notice prior to returning the service locator instance. This is more appropriate, as we want to encourage users who rely on the service locator composition to upgrade. Interestingly, this allows us to revert a number of changes that were made to the tests to mask deprecation notices, which helps solidify the argument that the original changes were indeed a backwards compatibility break, and that the new changes will address that situation.
1 parent a58183e commit 0a531e2

14 files changed

+44
-124
lines changed

src/Controller/AbstractController.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,15 @@ public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
248248
*/
249249
public function getServiceLocator()
250250
{
251+
trigger_error(sprintf(
252+
'You are retrieving the service locator from within the class %s. Please be aware that '
253+
. 'ServiceLocatorAwareInterface is deprecated and will be removed in version 3.0, along '
254+
. 'with the ServiceLocatorAwareInitializer. You will need to update your class to accept '
255+
. 'all dependencies at creation, either via constructor arguments or setters, and use '
256+
. 'a factory to perform the injections.',
257+
get_class($this)
258+
), E_USER_DEPRECATED);
259+
251260
return $this->serviceLocator;
252261
}
253262

src/Controller/ControllerManager.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -220,18 +220,20 @@ public function injectServiceLocator($first, $second)
220220
$container = $container->getServiceLocator() ?: $container;
221221
}
222222

223+
// Inject AbstractController extensions that are not ServiceLocatorAware
224+
// with the service manager, but do not emit a deprecation notice. We'll
225+
// emit it from AbstractController::getServiceLocator() instead.
223226
if (! $controller instanceof ServiceLocatorAwareInterface
227+
&& $controller instanceof AbstractController
224228
&& method_exists($controller, 'setServiceLocator')
225229
) {
226-
trigger_error(sprintf(
227-
'ServiceLocatorAwareInterface is deprecated and will be removed in version 3.0, along '
228-
. 'with the ServiceLocatorAwareInitializer. Please update your class %s to remove '
229-
. 'the implementation, and start injecting your dependencies via factory instead.',
230-
get_class($controller)
231-
), E_USER_DEPRECATED);
230+
// Do not emit deprecation notice in this case
232231
$controller->setServiceLocator($container);
233232
}
234233

234+
// If a controller implements ServiceLocatorAwareInterface explicitly, we
235+
// inject, but emit a deprecation notice. Since AbstractController no longer
236+
// explicitly does this, this will only affect userland controllers.
235237
if ($controller instanceof ServiceLocatorAwareInterface) {
236238
trigger_error(sprintf(
237239
'ServiceLocatorAwareInterface is deprecated and will be removed in version 3.0, along '

src/Service/ServiceManagerConfig.php

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Zend\EventManager\SharedEventManagerInterface;
1818
use Zend\ModuleManager\Listener\ServiceListener;
1919
use Zend\ModuleManager\ModuleManager;
20+
use Zend\ServiceManager\AbstractPluginManager;
2021
use Zend\ServiceManager\Config;
2122
use Zend\ServiceManager\ServiceLocatorAwareInterface;
2223
use Zend\ServiceManager\ServiceManager;
@@ -132,7 +133,12 @@ public function __construct(array $config = [])
132133
$instance = $first;
133134
}
134135

135-
if ($instance instanceof ServiceLocatorAwareInterface) {
136+
// For service locator aware classes, inject the service
137+
// locator, but emit a deprecation notice. Skip plugin manager
138+
// implementations; they're dealt with later.
139+
if ($instance instanceof ServiceLocatorAwareInterface
140+
&& ! $instance instanceof AbstractPluginManager
141+
) {
136142
trigger_error(sprintf(
137143
'ServiceLocatorAwareInterface is deprecated and will be removed in version 3.0, along '
138144
. 'with the ServiceLocatorAwareInitializer. Please update your class %s to remove '
@@ -142,13 +148,17 @@ public function __construct(array $config = [])
142148
$instance->setServiceLocator($container);
143149
}
144150

145-
if (! $instance instanceof ServiceLocatorAwareInterface
146-
&& method_exists($instance, 'setServiceLocator')
151+
// For service locator aware plugin managers that do not have
152+
// the service locator already injected, inject it, but emit a
153+
// deprecation notice.
154+
if ($instance instanceof ServiceLocatorAwareInterface
155+
&& $instance instanceof AbstractPluginManager
156+
&& ! $instance->getServiceLocator()
147157
) {
148158
trigger_error(sprintf(
149159
'ServiceLocatorAwareInterface is deprecated and will be removed in version 3.0, along '
150-
. 'with the ServiceLocatorAwareInitializer. Please update your class %s to remove '
151-
. 'the implementation, and start injecting your dependencies via factory instead.',
160+
. 'with the ServiceLocatorAwareInitializer. Please update your %s plugin manager factory '
161+
. 'to inject the parent service locator via the constructor.',
152162
get_class($instance)
153163
), E_USER_DEPRECATED);
154164
$instance->setServiceLocator($container);

test/Application/AllowsReturningEarlyFromRoutingTest.php

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
namespace ZendTest\Mvc\Application;
1111

12-
use PHPUnit_Framework_Error_Deprecated;
1312
use PHPUnit_Framework_TestCase as TestCase;
1413
use Zend\Http\PhpEnvironment\Response;
1514
use Zend\Mvc\MvcEvent;
@@ -18,12 +17,6 @@ class AllowsReturningEarlyFromRoutingTest extends TestCase
1817
{
1918
use PathControllerTrait;
2019

21-
public function setUp()
22-
{
23-
// Ignore deprecation errors
24-
PHPUnit_Framework_Error_Deprecated::$enabled = false;
25-
}
26-
2720
public function testAllowsReturningEarlyFromRouting()
2821
{
2922
$application = $this->prepareApplication();

test/Application/ControllerIsDispatchedTest.php

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,13 @@
99

1010
namespace ZendTest\Mvc\Application;
1111

12-
use PHPUnit_Framework_Error_Deprecated;
1312
use PHPUnit_Framework_TestCase as TestCase;
1413
use Zend\Mvc\MvcEvent;
1514

1615
class ControllerIsDispatchedTest extends TestCase
1716
{
1817
use PathControllerTrait;
1918

20-
public function setUp()
21-
{
22-
// Ignore deprecation errors
23-
PHPUnit_Framework_Error_Deprecated::$enabled = false;
24-
}
25-
2619
public function testControllerIsDispatchedDuringRun()
2720
{
2821
$application = $this->prepareApplication();

test/Application/ExceptionsRaisedInDispatchableShouldRaiseDispatchErrorEventTest.php

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,13 @@
99

1010
namespace ZendTest\Mvc\Application;
1111

12-
use PHPUnit_Framework_Error_Deprecated;
1312
use PHPUnit_Framework_TestCase as TestCase;
1413
use Zend\Mvc\MvcEvent;
1514

1615
class ExceptionsRaisedInDispatchableShouldRaiseDispatchErrorEventTest extends TestCase
1716
{
1817
use BadControllerTrait;
1918

20-
public function setUp()
21-
{
22-
// Ignore deprecation errors
23-
PHPUnit_Framework_Error_Deprecated::$enabled = false;
24-
}
25-
2619
/**
2720
* @group error-handling
2821
*/

test/Controller/AbstractControllerTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
use PHPUnit_Framework_TestCase as TestCase;
1313
use ReflectionProperty;
14+
use Zend\ServiceManager\ServiceLocatorInterface;
1415

1516
/**
1617
* @covers \Zend\Mvc\Controller\AbstractController
@@ -104,4 +105,15 @@ public function testSetEventManagerWithDefaultIdentifiersIncludesImplementedInte
104105

105106
$this->controller->setEventManager($eventManager);
106107
}
108+
109+
public function testRetrievingServiceLocatorRaisesDeprecationNotice()
110+
{
111+
$services = $this->prophesize(ServiceLocatorInterface::class)->reveal();
112+
113+
$controller = new TestAsset\SampleController();
114+
$controller->setServiceLocator($services);
115+
116+
$this->setExpectedException('PHPUnit_Framework_Error_Deprecated', 'retrieving the service locator');
117+
$controller->getServiceLocator();
118+
}
107119
}

test/Controller/ControllerManagerTest.php

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,20 @@
99

1010
namespace ZendTest\Mvc\Controller;
1111

12-
use PHPUnit_Framework_Error_Deprecated;
1312
use PHPUnit_Framework_TestCase as TestCase;
1413
use ReflectionClass;
1514
use Zend\EventManager\EventManager;
1615
use Zend\EventManager\SharedEventManager;
1716
use Zend\Mvc\Controller\ControllerManager;
1817
use Zend\Mvc\Controller\PluginManager as ControllerPluginManager;
1918
use Zend\ServiceManager\Config;
20-
use Zend\ServiceManager\Factory\InvokableFactory;
2119
use Zend\ServiceManager\ServiceManager;
2220
use Zend\Console\Adapter\Virtual as ConsoleAdapter;
23-
use ZendTest\Mvc\Service\TestAsset\DuckTypedServiceLocatorAwareController;
2421

2522
class ControllerManagerTest extends TestCase
2623
{
2724
public function setUp()
2825
{
29-
// Disable deprecation notices
30-
PHPUnit_Framework_Error_Deprecated::$enabled = false;
31-
3226
$this->sharedEvents = new SharedEventManager;
3327
$this->events = $this->createEventManager($this->sharedEvents);
3428
$this->consoleAdapter = new ConsoleAdapter();
@@ -151,13 +145,4 @@ public function testDoNotUsePeeringServiceManagers()
151145
$this->setExpectedException('Zend\ServiceManager\Exception\ServiceNotFoundException');
152146
$this->controllers->get('EventManager');
153147
}
154-
155-
public function testServiceLocatorAwareInitializerInjectsDuckTypedImplementations()
156-
{
157-
$this->controllers->setFactory(DuckTypedServiceLocatorAwareController::class, InvokableFactory::class);
158-
159-
$controller = $this->controllers->get(DuckTypedServiceLocatorAwareController::class);
160-
$this->assertInstanceOf(DuckTypedServiceLocatorAwareController::class, $controller);
161-
$this->assertSame($this->services, $controller->getServiceLocator());
162-
}
163148
}

test/Controller/IntegrationTest.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
namespace ZendTest\Mvc\Controller;
1111

12-
use PHPUnit_Framework_Error_Deprecated;
1312
use PHPUnit_Framework_TestCase as TestCase;
1413
use Zend\EventManager\EventManager;
1514
use Zend\EventManager\SharedEventManager;
@@ -22,9 +21,6 @@ class IntegrationTest extends TestCase
2221
{
2322
public function setUp()
2423
{
25-
// Ignore deprecation errors
26-
PHPUnit_Framework_Error_Deprecated::$enabled = false;
27-
2824
$this->sharedEvents = new SharedEventManager();
2925

3026
$this->services = new ServiceManager();

test/Controller/Plugin/ForwardTest.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
namespace ZendTest\Mvc\Controller\Plugin;
1111

12-
use PHPUnit_Framework_Error_Deprecated;
1312
use PHPUnit_Framework_TestCase as TestCase;
1413
use ReflectionClass;
1514
use stdClass;
@@ -52,9 +51,6 @@ class ForwardTest extends TestCase
5251

5352
public function setUp()
5453
{
55-
// Ignore deprecation errors
56-
PHPUnit_Framework_Error_Deprecated::$enabled = false;
57-
5854
$eventManager = $this->createEventManager(new SharedEventManager());
5955
$mockApplication = $this->getMock('Zend\Mvc\ApplicationInterface');
6056
$mockApplication->expects($this->any())->method('getEventManager')->will($this->returnValue($eventManager));

0 commit comments

Comments
 (0)