As of today, this plugin has been completely refactored in a number of ways that will undoubtedly break your existing code.
Unless you are comfortable digging in to the plugin code to figure out how it works now, I'd recommend holding off updating until I release updated documentation.
Some of the major changes include:
A dynamic menu building helper for CakePHP
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
app/plugins
menu_builder
In your app directory type:
git submodule add git://github.com/torifat/cake-menu_builder.git plugins/menu_builder
git submodule init
git submodule update
In your plugin directory type
git clone git://github.com/torifat/cake-menu_builder.git menu_builder
To use this helper add the following to your AppController:
<?php
...
var $helpers = array(..., 'MenuBuilder.MenuBuilder');
function beforeFilter() {
...
// Define your menu
$menu = array(
'main-menu' => array(
array(
'title' => 'Home',
'url' => array('controller' => 'pages', 'action' => 'home'),
),
array(
'title' => 'About Us',
'url' => '/pages/about-us',
),
),
'left-menu' => array(
array(
'title' => 'Item 1',
'url' => array('controller' => 'items', 'action' => 'view', 1),
'children' => array(
array(
'title' => 'Item 3',
'url' => array('controller' => 'items', 'action' => 'view', 3),
),
array(
'title' => 'Item 4',
'url' => array('controller' => 'items', 'action' => 'view', 4),
),
)
),
array(
'title' => 'Item 2',
'url' => array('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:
<?php
echo $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="https://github.com/bmcclure/CakePHP-Menu-Plugin/blob/cake-2.0/pages/home">Home</a></li>
<li><a title="About Us" href="https://github.com/bmcclure/CakePHP-Menu-Plugin/blob/cake-2.0/pages/about-us">About Us</a></li>
</ul>
And to build your left-menu
use the following code in the View:
<?php
echo $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="https://github.com/bmcclure/CakePHP-Menu-Plugin/blob/cake-2.0/items/view/1">Item 1</a>
<ul>
<li class="first-item">
<a title="Item 3" href="https://github.com/bmcclure/CakePHP-Menu-Plugin/blob/cake-2.0/items/view/3">Item 3</a>
</li>
<li class="active">
<a title="Item 4" href="https://github.com/bmcclure/CakePHP-Menu-Plugin/blob/cake-2.0/items/view/4">Item 4</a>
</li>
</ul>
</li>
<li>
<a title="Item 2" href="https://github.com/bmcclure/CakePHP-Menu-Plugin/blob/cake-2.0/items/view/2">Item 2</a>
</li>
</ul>
You can pass optional parameter in build
function like -
<?php
echo $menuBuilder->build('main-menu', array('class' => array('fun', 'red'));
// OR
echo $menuBuilder->build('main-menu', array('class' => 'fun green');
?>
You can provide advance options in the array like the following:
<?php
...
var $helpers = array(
...
'MenuBuilder.MenuBuilder' => array(/* array of settings */)
);
?>
if you do not provide any settings then the following settings will work.
$settings = array(
'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',
);
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="https://github.com/bmcclure/CakePHP-Menu-Plugin/blob/cake-2.0/pages/home">Home</a>
</li>
<li class="even">
<a title="About Us" href="https://github.com/bmcclure/CakePHP-Menu-Plugin/blob/cake-2.0/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' => array(
'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="https://github.com/bmcclure/CakePHP-Menu-Plugin/blob/cake-2.0/pages/home">Home</a>
</div>
<div>
<a title="About Us" href="https://github.com/bmcclure/CakePHP-Menu-Plugin/blob/cake-2.0/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'
)
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:
<?php
...
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:
<?php
...
function beforeFilter() {
...
$user = Authsome::get();
$this->set(compact('user'));
}
?>
Now we have to define permissions in our menu like this:
<?php
...
function beforeFilter() {
...
// Define your menu
$menu = array(
'main-menu' => array(
// Anybody can see this
array(
'title' => 'Home',
'url' => array('controller' => 'pages', 'action' => 'home'),
),
// Users and Admins can see this, Guests and Managers can't
array(
'title' => 'About Us',
'url' => array('controller' => 'pages', 'action' => 'about-us'),
'permissions' => array('user','admin'),
),
// Only Guests can see this
array(
'title' => 'Login',
'url' => array('controller' => 'users', 'action' => 'login'),
'permissions' => array(''),
),
),
...
);
// For default settings name must be menu
$this->set(compact('menu'));
...
}
?>
You're Done!
permissions
Array of type/group/permission/level whose can view that item (default - array()
)
partialMatch
Normally url
matching are strict. Suppose you are in /items/details
and your menu contains an entry for /item
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' => array(
'itemFormat' => '<dd%s>%s%s</dd>',
'wrapperFormat' => '<dl%s>%s</dl>',
'noLinkFormat' => '<dd>%s</dd>',
),
Example Menu
<?php
...
var $helpers = array(..., 'MenuBuilder.MenuBuilder');
function beforeFilter() {
...
// Define your menu
$menu = array(
'main-menu' => array(
array(
'separator' => '<dt>Main Menu</dt>',
),
array(
'title' => 'Home',
'url' => array('controller' => 'pages', 'action' => 'home'),
),
array(
'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="https://github.com/bmcclure/CakePHP-Menu-Plugin/blob/cake-2.0/pages/home">Home</a>
</dd>
<dd>
<a title="About Us" href="https://github.com/bmcclure/CakePHP-Menu-Plugin/blob/cake-2.0/pages/about-us">About Us</a>
</dd>
</dl>
More to come :)
Add More Test Cases
Copyright (c) 2011 M. M. Rifat-Un-Nabi
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.