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

Ensure navigation helpers are injected with application service container #50

Merged
merged 6 commits into from
Feb 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ before_install:
- if [[ $ZEND_EVENTMANAGER_VERSION == '' ]]; then composer require --no-update "zendframework/zend-eventmanager:^3.0" ; fi
- if [[ $ZEND_SERVICEMANAGER_VERSION != '' ]]; then composer require --dev --no-update "zendframework/zend-servicemanager:$ZEND_SERVICEMANAGER_VERSION" ; fi
- if [[ $ZEND_SERVICEMANAGER_VERSION == '' ]]; then composer require --dev --no-update "zendframework/zend-servicemanager:^3.0.3" ; fi
- if [[ $ZEND_SERVICEMANAGER_VERSION == '' ]]; then composer remove --dev --no-update zendframework/zend-mvc zendframework/zend-session ; fi
- if [[ $ZEND_SERVICEMANAGER_VERSION == '' ]]; then composer remove --dev --no-update zendframework/zend-modulemanager zendframework/zend-mvc zendframework/zend-session ; fi

install:
- travis_retry composer install --no-interaction --ignore-platform-reqs
Expand Down
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

All notable changes to this project will be documented in this file, in reverse chronological order by release.

## 2.6.3 - TBD
## 2.6.3 - 2016-02-19

### Added

Expand All @@ -18,7 +18,11 @@ All notable changes to this project will be documented in this file, in reverse

### Fixed

- Nothing.
- [#50](https://github.com/zendframework/zend-view/pull/50) fixes
the initializer defined and registered in
`Navigation\PluginManager::__construct()` to ensure it properly pulls and
injects the application container into navigation helpers, under both
zend-servicemanager v2 and v3.

## 2.6.2 - 2016-02-18

Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"zendframework/zend-i18n": "^2.6",
"zendframework/zend-json": "^2.6.1",
"zendframework/zend-log": "^2.7",
"zendframework/zend-modulemanager": "^2.5",
"zendframework/zend-mvc": "^2.6.1",
"zendframework/zend-navigation": "^2.5",
"zendframework/zend-paginator": "^2.5",
Expand Down
2 changes: 1 addition & 1 deletion src/Helper/Navigation.php
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ public function setPluginManager(Navigation\PluginManager $plugins)
public function getPluginManager()
{
if (null === $this->plugins) {
$this->setPluginManager(new Navigation\PluginManager());
$this->setPluginManager(new Navigation\PluginManager($this->getServiceLocator()));
}

return $this->plugins;
Expand Down
22 changes: 22 additions & 0 deletions src/Helper/Navigation/AbstractHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

use Interop\Container\ContainerInterface;
use RecursiveIteratorIterator;
use ReflectionProperty;
use Zend\EventManager\EventManager;
use Zend\EventManager\EventManagerAwareInterface;
use Zend\EventManager\EventManagerInterface;
Expand All @@ -19,6 +20,7 @@
use Zend\Navigation;
use Zend\Navigation\Page\AbstractPage;
use Zend\Permissions\Acl;
use Zend\ServiceManager\AbstractPluginManager;
use Zend\View;
use Zend\View\Exception;

Expand Down Expand Up @@ -753,6 +755,26 @@ public function hasRole()
*/
public function setServiceLocator(ContainerInterface $serviceLocator)
{
// If we are provided a plugin manager, we should pull the parent
// context from it.
// @todo We should update tests and code to ensure that this situation
// doesn't happen in the future.
if ($serviceLocator instanceof AbstractPluginManager
&& ! method_exists($serviceLocator, 'configure')
&& $serviceLocator->getServiceLocator()
) {
$serviceLocator = $serviceLocator->getServiceLocator();
}

// v3 variant; likely won't be needed.
if ($serviceLocator instanceof AbstractPluginManager
&& method_exists($serviceLocator, 'configure')
) {
$r = new ReflectionProperty($serviceLocator, 'creationContext');
$r->setAccessible(true);
$serviceLocator = $r->getValue($serviceLocator);
}

$this->serviceLocator = $serviceLocator;
return $this;
}
Expand Down
22 changes: 21 additions & 1 deletion src/Helper/Navigation/PluginManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,31 @@ class PluginManager extends HelperPluginManager
*/
public function __construct($configOrContainerInstance = null, array $v3config = [])
{
$this->initializers[] = function ($container, $instance) {
$this->initializers[] = function ($first, $second) {
// v2 vs v3 argument order
if ($first instanceof ContainerInterface) {
// v3
$container = $first;
$instance = $second;
} else {
// v2
$container = $second;
$instance = $first;
}

if (! $instance instanceof AbstractHelper) {
return;
}

// This initializer was written with v2 functionality in mind; as such,
// we need to test and see if we're called in a v2 context, and, if so,
// set the service locator to the parent locator.
//
// Under v3, the parent locator is what is passed to the method already.
if (! method_exists($container, 'configure') && $container->getServiceLocator()) {
$container = $container->getServiceLocator();
}

$instance->setServiceLocator($container);
};

Expand Down
11 changes: 8 additions & 3 deletions test/Helper/Navigation/AbstractTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ abstract class AbstractTest extends \PHPUnit_Framework_TestCase
*/
protected function setUp()
{
if (! class_exists(PluginFlashMessenger::class)) {
if (! class_exists(ServiceManagerConfig::class)) {
$this->markTestSkipped(
'Skipping zend-mvc-related tests until that component is updated '
. 'to be forwards-compatible with zend-eventmanager, zend-stdlib, '
Expand Down Expand Up @@ -126,7 +126,7 @@ protected function setUp()
'extra_config' => [
'service_manager' => [
'factories' => [
'Config' => function () use ($config) {
'config' => function () use ($config) {
return [
'navigation' => [
'default' => $config->get('nav_test1'),
Expand All @@ -139,7 +139,10 @@ protected function setUp()
],
];

$sm = $this->serviceManager = new ServiceManager(new ServiceManagerConfig);
$sm = $this->serviceManager = new ServiceManager();
$sm->setAllowOverride(true);

(new ServiceManagerConfig())->configureServiceManager($sm);
$sm->setService('ApplicationConfig', $smConfig);
$sm->get('ModuleManager')->loadModules();
$sm->get('Application')->bootstrap();
Expand All @@ -148,6 +151,8 @@ protected function setUp()
$sm->setService('nav1', $this->_nav1);
$sm->setService('nav2', $this->_nav2);

$sm->setAllowOverride(false);

$app = $this->serviceManager->get('Application');
$app->getMvcEvent()->setRouteMatch(new RouteMatch([
'controller' => 'post',
Expand Down
35 changes: 28 additions & 7 deletions test/Helper/Navigation/NavigationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

namespace ZendTest\View\Helper\Navigation;

use Interop\Container\ContainerInterface;
use Zend\Navigation\Navigation as Container;
use Zend\Navigation\Page;
use Zend\Permissions\Acl;
use Zend\Permissions\Acl\Role;
use Zend\ServiceManager\ServiceManager;
Expand Down Expand Up @@ -61,11 +63,10 @@ public function testAcceptAclShouldReturnGracefullyWithUnknownResource()
$this->_helper->setRole($acl['role']);

$accepted = $this->_helper->accept(
new \Zend\Navigation\Page\Uri([
new Page\Uri([
'resource' => 'unknownresource',
'privilege' => 'someprivilege'
],
false)
], false)
);

$this->assertEquals($accepted, false);
Expand Down Expand Up @@ -144,10 +145,9 @@ public function testServiceManagerIsUsedToRetrieveContainer()
$serviceManager = new ServiceManager;
$serviceManager->setService('navigation', $container);

$pluginManager = new View\HelperPluginManager;
$pluginManager->setServiceLocator($serviceManager);
$pluginManager = new View\HelperPluginManager($serviceManager);

$this->_helper->setServiceLocator($pluginManager);
$this->_helper->setServiceLocator($serviceManager);
$this->_helper->setContainer('navigation');

$expected = $this->_helper->getContainer();
Expand Down Expand Up @@ -558,7 +558,7 @@ public function testMultipleNavigationsWithSameHelperAndSameContainer()

public function testSetPluginManagerAndView()
{
$pluginManager = new \Zend\View\Helper\Navigation\PluginManager();
$pluginManager = new Navigation\PluginManager();
$view = new PhpRenderer();

$helper = new $this->_helperName;
Expand All @@ -568,6 +568,27 @@ public function testSetPluginManagerAndView()
$this->assertEquals($view, $pluginManager->getRenderer());
}

/**
* @group 49
*/
public function testInjectsLazyInstantiatedPluginManagerWithCurrentServiceLocator()
{
$services = $this->prophesize(ContainerInterface::class)->reveal();
$helper = new $this->_helperName;
$helper->setServiceLocator($services);

$plugins = $helper->getPluginManager();
$this->assertInstanceOf(Navigation\PluginManager::class, $plugins);

if (method_exists($plugins, 'configure')) {
// v3
$this->assertAttributeSame($services, 'creationContext', $plugins);
} else {
// v2
$this->assertSame($services, $plugins->getServiceLocator());
}
}

/**
* Returns the contens of the expected $file, normalizes newlines
* @param string $file
Expand Down
18 changes: 18 additions & 0 deletions test/Helper/Navigation/PluginManagerCompatibilityTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Zend\ServiceManager\Test\CommonPluginManagerTrait;
use Zend\View\Exception\InvalidHelperException;
use Zend\View\Helper\Navigation\AbstractHelper;
use Zend\View\Helper\Navigation\Breadcrumbs;
use Zend\View\Helper\Navigation\PluginManager;

/**
Expand Down Expand Up @@ -65,4 +66,21 @@ public function testConstructorAllowsConfigInstanceAsFirstArgumentUnderV2()
$helpers = new PluginManager(new Config([]));
$this->assertInstanceOf(PluginManager::class, $helpers);
}

public function testInjectsParentContainerIntoHelpers()
{
$config = new Config([
'navigation' => [
'default' => [],
],
]);

$services = new ServiceManager();
$config->configureServiceManager($services);
$helpers = new PluginManager($services);

$helper = $helpers->get('breadcrumbs');
$this->assertInstanceOf(Breadcrumbs::class, $helper);
$this->assertSame($services, $helper->getServiceLocator());
}
}