Reputation: 5391
I am using Zend Navigation with ACL. My users can have multiple roles, which have no relation to each other, but Zend Navigation only accepts one role and checks the ACL with that role which is not good for me.
How can I register a new Helper for the Navigation such that I can override the acceptAcl
method. I tried to create and register a simple view helper but that didn't work
class Menu extends \Zend\View\Helper\Navigation\Menu implements \Zend\ServiceManager\ServiceLocatorAwareInterface
{
protected function acceptAcl(AbstractPage $page)
{
if (!$acl = $this->getAcl()) {
// no acl registered means don't use acl
return true;
}
$userIdentity = $this->getServiceLocator()->get('user_identity');
$resource = $page->getResource();
$privilege = $page->getPrivilege();
$allowed = true;
if ($userIdentity->id !== "1") {
if ($acl->hasResource($resource)) {
$allowed = false;
foreach ($userIdentity->rolls as $roll) {
if ($acl->isAllowed($roll['id'], $resource)) {
$allowed = true;
continue;
}
}
}
}
return $allowed;
}
public function renderMenu($container = null, array $options = array())
{
return 'this is my menu';
}
}
'view_helpers' => array(
'invokables' => array(
'myMenu' => 'Application\View\Helper\Menu',
),
),
How can I register this helper so that the Navigation knows about it?
Upvotes: 2
Views: 2543
Reputation: 7787
My users can have multiple roles, which have no relation to each other, but Zend Navigation only accepts one role and checks the ACL with that role which is not good for me.
That problem is easy enough to solve: just create a role for this user, which inherits from the real roles. See the official docs, and search for the paragraphs referring to the role "someUser", which you should understand as referring to the current user. Hence: the role should be added to the ACL dynamically.
$roles = ['staff', 'editor'];
$this->acl->addRole(new Role('currentuser'), $roles);
Then use "currentuser" as the role to check against.
One issue is that you have to list the "parent roles" in a proper order, i.e. the least privileged roles first, as they're checked in reverse order.
You can try to take care of that by using using something like the following snippet, which will ignore any roles it doesn't recognize, and keep them in the order of the hardcoded list.
# $userRoles is an array with the roles of the current user
$this->acl->addRole(new Role('currentuser'),
array_intesect(['member', 'staff', 'editor', 'admin'], $userRoles));
Upvotes: 0
Reputation: 884
Even if the topic is old, that solution didn't work for me in ZF2 v2.3.3.
After some research, I found that Navigation Helper is not shared, or it is the twig module that mess up sharing, and if I try to add custom plugin to Navigation (such as a new menu) in module bootstrap, it is just ineffective. But I found an interesting thing in reading Navigation Helper construction in
Zend\Navigation\View\HelperConfig.php
the Navigation plugin manager can be configured in module, global or local config under the key navigation_helpers
. That is an easy way to extends Navigation with plugins.
Ex :
module.config.php
'navigation_helpers' => array (
'invokables' => array(
'menu' => 'Application\View\Helper\Navigation\Menu',
),
),
Upvotes: 4
Reputation: 7238
The Navigation
view helper is registered on the ViewHelperPluginManager
. All the navigation helpers (Menu
, Breadcrumbs
etc) are managed by a seperate pluginmanager. As far as I know you cannot overwrite the navigation helpers in your configuration yet.
Try to add the following to your Module.php
:
class Module
{
public function onBootstrap($e)
{
$application = $e->getApplication();
/** @var $serviceManager \Zend\ServiceManager\ServiceManager */
$serviceManager = $application->getServiceManager();
$pm = $serviceManager->get('ViewHelperManager')->get('Navigation')->getPluginManager();
$pm->setInvokableClass('myMenu', '\Application\View\Helper\Menu');
}
}
Upvotes: 3