pieceofcake2 / menu_builder
A dynamic menu building helper for CakePHP 2.x
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 34
Type:cakephp-plugin
pkg:composer/pieceofcake2/menu_builder
Requires
- php: ^8.0
- composer/installers: *
- pieceofcake2/cakephp: ^2.10
Requires (Dev)
- cakephp/cakephp-codesniffer: ^5.0
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^9.6
- pieceofcake2/app: ^2.1
- pieceofcake2/phpstan-cakephp2: ^0.2.1
Replaces
README
This is forked for CakePHP2.
A dynamic menu building helper for CakePHP
Background
This is a menu building helper with lot of customization options. Check out the Usage section.
Now it supports menus built with ACL Menu Component by Mark Story
Features
- Generate menu based on current user type/group/permission/level (Can be used with Auth, Authsome, etc Components)
- Provide various useful CSS class
- Multi-level menu support
- Supports ACL Menu Component by Mark Story
- CakePHP Unit Test (
100% Code coverage)
Requirements
- CakePHP 2.10+
- PHP 8.0+
Installation
Add the plugin to your project's:
composer require pieceofcake2/menu_builder
Because this plugin has the type cakephp-plugin
set in its own composer.json
, Composer will install it inside your /Plugins
directory, rather than in the usual vendors file. It is recommended that you add /Plugins/MenuBuilder
to your .gitignore file. (Why? read this.)
Enable plugin
In 2.x you need to enable the plugin in your app/Config/bootstrap.php
file:
CakePlugin::load('MenuBuilder');
If you are already using CakePlugin::loadAll();
, then this is not necessary.
Usage
Minimal Setup
Load the Plugin by modifying your app/Config/bootstrap.php
... CakePlugin::load('MenuBuilder');
or
... CakePlugin::loadAll();
To use this helper add the following to your AppController:
... var $helpers = [..., 'MenuBuilder.MenuBuilder']; function beforeFilter() { ... // Define your menu $menu = [ 'main-menu' => [ [ 'title' => 'Home', 'url' => ['controller' => 'pages', 'action' => 'home'], ], [ 'title' => 'About Us', 'url' => '/pages/about-us', ], ], 'left-menu' => [ [ 'title' => 'Item 1', 'url' => ['controller' => 'items', 'action' => 'view', 1], 'children' => [ [ 'title' => 'Item 3', 'url' => ['controller' => 'items', 'action' => 'view', 3], ], [ 'title' => 'Item 4', 'url' => ['controller' => 'items', 'action' => 'view', 4], ], ] ], [ 'title' => 'Item 2', 'url' => ['controller' => 'items', 'action' => 'view', 2], ], ], ]; // For default settings name must be menu $this->set(compact('menu')); ... }
Now to build your main-menu
use the following code in the View:
echo $this->MenuBuilder->build('main-menu');
You'll get the following output in the Home (/pages/home) page:
<ul id="main-menu"> <li class="first-item active"><a title="Home" href="/pages/home">Home</a></li> <li><a title="About Us" href="/pages/about-us">About Us</a></li> </ul>
And to build your left-menu
use the following code in the View:
<?php echo $this->MenuBuilder->build('left-menu'); ?>
You'll get the following output in your 'Item 4' (/items/view/4) page:
<ul id="left-menu"> <li class="first-item active has-children"> <a title="Item 1" href="/items/view/1">Item 1</a> <ul> <li class="first-item"> <a title="Item 3" href="/items/view/3">Item 3</a> </li> <li class="active"> <a title="Item 4" href="/items/view/4">Item 4</a> </li> </ul> </li> <li> <a title="Item 2" href="/items/view/2">Item 2</a> </li> </ul>
You can pass optional parameter in build
function like -
<?php echo $this->MenuBuilder->build('main-menu', ['class' => ['fun', 'red']]); // OR echo $this->MenuBuilder->build('main-menu', ['class' => 'fun green']); ?>
Advance Setup
You can provide advance options in the array like the following:
... var $helpers = [ ... 'MenuBuilder.MenuBuilder' => [/* array of settings */] ];
Default Settings
if you do not provide any settings then the following settings will work.
$settings = [ 'activeClass' => 'active', 'firstClass' => 'first-item', 'childrenClass' => 'has-children', 'evenOdd' => false, 'itemFormat' => '<li%s>%s%s</li>', 'wrapperFormat' => '<ul%s>%s</ul>', 'noLinkFormat' => '<a href="#">%s</a>', 'menuVar' => 'menu', 'authVar' => 'user', 'authModel' => 'User', 'authField' => 'group', ];
Settings Details
activeClass
CSS classname for the selected/current item and it's successors. (default - 'active'
)
firstClass
CSS classname for the first item of each level. (default - 'first-item'
)
childrenClass
CSS classname for an item containing sub menu. (default - 'has-children'
)
evenOdd
If it is set to true
then even/odd classname will be provided with each item. (default - false
)
<ul id="main-menu"> <li class="first-item odd"> <a title="Home" href="/pages/home">Home</a> </li> <li class="even"> <a title="About Us" href="/pages/about-us">About Us</a> </li> </ul>
itemFormat
if you want to use other tag than li
for menu items (default - '<li%s>%s%s</li>'
)
wrapperFormat
if you want to use other tag than ul
for menu items container (default - '<ul%s>%s</ul>'
)
noLinkFormat
Format for empty link item (default - '<a href="#">%s</a>'
)
Example Setting
'MenuBuilder.MenuBuilder' => [ 'itemFormat' => '<div%s>%s%s</div>', 'wrapperFormat' => '<div%s>%s</div>', 'noLinkFormat' => '<div>%s</div>', ],
Example Output (an extra item added to explain noLinkFormat
)
<div id="main-menu"> <div class="first-item"> <a title="Home" href="/pages/home">Home</a> </div> <div> <a title="About Us" href="/pages/about-us">About Us</a> </div> <div> Empty </div> </div>
menuVar
Name of the variable that contains all menus (default - 'menu'
)
Following settings will be used for permission based menu (see below)
authVar
Name of the variable that contains the User
data (default - 'user'
)
authModel
Name of the authentication model (default - 'User'
)
authField
Name of the field that contains the user's type/group/permission/level (default - 'group'
)
Permission Based Menu
Suppose you have a users
table like the following one:
CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `email` varchar(255) NOT NULL, `password` char(40) NOT NULL, `group` enum('user','manager','admin') NOT NULL DEFAULT 'user', `name` varchar(255) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY (`email`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Now suppose you are using the CakePHP auth component for authentication so add the following to your AppController:
... function beforeFilter() { ... $user = $this->Auth->user(); $this->set(compact('user')); }
But, If you are using Authsome component for authentication then add the following to your AppController:
... function beforeFilter() { ... $user = Authsome::get(); $this->set(compact('user')); }
Now we have to define permissions in our menu like this:
... function beforeFilter() { ... // Define your menu $menu = [ 'main-menu' => [ // Anybody can see this [ 'title' => 'Home', 'url' => ['controller' => 'pages', 'action' => 'home'], ], // Users and Admins can see this, Guests and Managers can't [ 'title' => 'About Us', 'url' => ['controller' => 'pages', 'action' => 'about-us'], 'permissions' => ['user','admin'], ], // Only Guests can see this [ 'title' => 'Login', 'url' => ['controller' => 'users', 'action' => 'login'], 'permissions' => [''], ], ], ... ]; // For default settings name must be menu $this->set(compact('menu')); ... }
You're Done!
Other Menu Options
permissions
Array of type/group/permission/level whose can view that item (default - []
)
partialMatch
Normally url
matching are strict. Suppose you are in /items/details
and your menu contains an entry for /items
then by default it'll not set active. But if you set partialMatch
to true
then it'll set active . (default - false
)
id
Provide CSS id to the item (default - null
)
class
Provide CSS class to the item (default - null
)
separator
If you want to define some separator in your menu, below is a nice example of what you can do with it. (default - false
)
Example Setting
'MenuBuilder.MenuBuilder' => [ 'itemFormat' => '<dd%s>%s%s</dd>', 'wrapperFormat' => '<dl%s>%s</dl>', 'noLinkFormat' => '<dd>%s</dd>', ],
Example Menu
... var $helpers = [..., 'MenuBuilder.MenuBuilder']; function beforeFilter() { ... // Define your menu $menu = [ 'main-menu' => [ [ 'separator' => '<dt>Main Menu</dt>', ], [ 'title' => 'Home', 'url' => ['controller' => 'pages', 'action' => 'home'], ], [ 'title' => 'About Us', 'url' => '/pages/about-us', ], ] ]; // For default settings name must be menu $this->set(compact('menu')); ... }
Example Output
<dl id="main-menu"> <dt>Main Menu</dt> <dd class="first-item"> <a title="Home" href="/pages/home">Home</a> </dd> <dd> <a title="About Us" href="/pages/about-us">About Us</a> </dd> </dl>
More to come :)
ToDo
Add More Test Cases
License
MIT License