Code Monkey home page Code Monkey logo

cake-menu_builder's Introduction

Build Status Coverage Status Total Downloads Latest Stable Version

MenuBuilder Helper

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.x
  • PHP 5.3

Installation

[Using Composer]

Add the plugin to your project's composer.json - something like this:

  {
    "require": {
      "torifat/cake-menu_builder": "2.0.3"
    }
  }

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.)

[Manual]

[GIT Submodule]

In your app directory type:

  git submodule add -b master git://github.com/torifat/cake-menu_builder.git Plugin/MenuBuilder
  git submodule init
  git submodule update

[GIT Clone]

In your Plugin directory type:

git clone -b master git://github.com/torifat/cake-menu_builder.git MenuBuilder

Enable plugin

In 2.0 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

<?php
...
CakePlugin::load('MenuBuilder');
?>

or

<?php
...
CakePlugin::loadAll();
?>

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 $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', array('class' => array('fun', 'red'));
    // OR
    echo $this->MenuBuilder->build('main-menu', array('class' => 'fun green');
?>

Advance Setup

You can provide advance options in the array like the following:

<?php
...
var $helpers = array(
    ...
    'MenuBuilder.MenuBuilder' => array(/* array of settings */)
);
?>

Default 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',
);

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' => 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="/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:

<?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!

Other Menu Options

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 /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' => 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="/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

The MIT License (MIT)

Copyright (c) 2011 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.

cake-menu_builder's People

Contributors

bmcclure avatar bobbykostadinov avatar chrisspony avatar lilhermit avatar steefaan avatar torifat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cake-menu_builder's Issues

Support CakePHP 2.0

Hi there. Your plugin seems to have saved my life :) I had to restructure it a bit to make it work with 2.0, though it's really just a matter of renaming stuff around. I uploaded it to http://www.morpheu5.net/public/MenuBuilder.tar.bz2 if you want to consider making it a branch.

PS. I had to use the full syntax for the build method because it seems that something has changed in the way you retrieve the menu array:

<?php echo $this->MenuBuilder->build('main-menu', array(), $menu['main-menu']) ?>

Travis ci

Can you add travis ci support to be sur your plugin is fonctionnal

thx

Permission based setup Doesn't works with Auth.

Hi ,
I found issue in your code:
var user : array( 'id' => '6', 'username' => 'ruslan', 'roll_id' => null, 'group' => 'admin', 'created' => '2016-02-08 12:24:15', 'modified' => '0000-00-00 00:00:00' )
in your constructor:
public $settings = array( 'activeClass' => 'active', 'firstClass' => 'first-item', 'childrenClass' => 'has-children', 'menuClass' => null, 'evenOdd' => false, 'itemFormat' => '<li%s>%s%s</li>', 'wrapperFormat' => '<ul%s>%s</ul>', 'wrapperClass' => null, 'noLinkFormat' => '<a href="#">%s</a>', 'menuVar' => 'menu', 'authVar' => 'user', 'authModel' => 'User', 'authField' => 'group', 'indentHtmlOutput' => true, ); if (isset($View->viewVars[$this->settings['authVar']]) && isset($View->viewVars[$this->settings['authVar']][$this->settings['authModel']]) && isset($View->viewVars[$this->settings['authVar']][$this->settings['authModel']][$this->settings['authField']])) { $this->_group = $View->viewVars[$this->settings['authVar']][$this->settings['authModel']][$this->settings['authField']]; }
$this->_group - Always is null;

Readme alteration

Might be worth adding a section about Loading the Plugin to the bootstrap.php

CakePlugin::load('MenuBuilder');

if the

CakePlugin::loadAll();

is not used.

Permissions Issue

Hello!
I'm using the plugin of cakephp menu builder. I've followed the guide but i'm having troubles with the permissions for the users. The menu item with the "permsissions" disappears even though the user has permission to view it. I'm using ACL too, does it have anything to do with that problem?
Can anyone help me.
Thanks.

Trying to Make noLinkFormat work with jQuery UI Accordion

I'm trying to make the noLinkFormat parameter work with jQuery UI Accordion. Theoretically, I need to surround the non-linking menu entry with something distinguishable to jQuery like

tags. Here's what I tried initially:

In the helper array:

'Menu.MenuBuilder' => array(
'noLinkFormat' => '

%s

',
'authField' => 'role',
'authVar' => 'user',
'authModel' => 'Users.User'
),

In the menu array itself:

array(
'title' => 'Learning Resources',
'permissions' => array(''),
'children' => array(
array(
'title' => 'Collections',
'url' => 'admin/collections/index',
and so

Unfortunately, that produced unclickable "Learning Resources" entry in the menu that looked like this in the source code:

  • Home
  • Learning Resources

      So I changed my menu array to look like this:

      array(
      'title' => 'Learning Resources',
      'url' => '#',
      'permissions' => array(''),
      'children' => array(
      array( and so on

      However, cake-menu then totally ignored my noLinkFormat parameter and produced this kind of source code:

    • Home
    • Learning Resources
      • With that, I don't see anything that I can hook jQuery UI accordion onto. Am I missing something? Is there a way to do that? Or to set the parameters to create the kind of hooks that it needs?

  • Permissions

    I wanted to ask a question about the plugin for cakephp menu builder. I configured everything correctly by following his guide and menu function without problems, but once I try to set the permissions for the users menu item with the "permsissions" disappears even though the user has permission to view it. Can you help me?. Thank you.

    Permissions Not Working

    I'm using CakePHP 2.7 with the CakeDC/Users plugin to manage authentication and access control. When I insert the 'permissions' entry into the Cake-Menu array, it has no effect. Specifically, in my controller $helpers, I have:

    public $helpers = array(
                'Html',
                'Form',
                'Session',
                'Js' => array('jquery'),
                'Menu.MenuBuilder' => array(
                    'noLinkFormat' => '<h3>%s</h3>',
                    'authField' => 'group_id',
                    'authVar' => 'user',
                    'authModel' => 'Users.User'),
            );

    In the pertinent portion of the $menu array, I have this:

    array(
                            'title'    => 'Articles',
                            'url'      => '#',
                            'children' => array(
                                array(
                                    'title' => 'Manage Articles',
                                    'url'   => array(
                                        'plugin'     => FALSE,
                                        'admin'      => TRUE,
                                        'controller' => 'posts',
                                        'action'     => 'index',
                                        'permissions' => array('512b9492-097c-462d-9c34-08b058f5bb4b'),
                                    ),
                                ), array(
                                    'title' => 'Add Article',
                                    'url'   => array(
                                        'plugin'     => FALSE,
                                        'admin'      => TRUE,
                                        'controller' => 'posts',
                                        'action'     => 'add'
                                    ),
                                ),
                            ),

    512b9492-097c-462d-9c34-08b058f5bb4b is the GUID for the admin group and is found in the group_id field for my record in the users table.

    In this example, I would expect to see the Add Article menu entry even when no one is logged in, but only see the Manage Articles entry when an admin, such as me, is logged in. However, the Manage Articles entry is _always_ available -- even when no one is logged in. (I have a display in the footer that shows who is logged in so I can confirm this both ways.) Of course, if I am not logged in and click the Manage Articles menu entry, Auth blocks me from getting to admin_index for Posts, but the menu entry shouldn't show up.

    Any ideas on what I may be doing wrong or what I need to do to make this work?

    Permissions with Related Role Model

    When I try to use 'permissions' => array('admin') or 'permissions' => array('') it doesn't seem to work, The first never displays, even if an admin user is logged in, and the second always displays even though an admin is logged in. I'm guessing that it's because there is no role or group field in the User model. Instead, there is a role_id field to a related Role model in keeping with an ACL configuration. Is there a way to restrict the display of menu items by role in this situation?

    I've tried including the following settings for MenuBuilder in AppController:

    'Menu.MenuBuilder' => array(
                    'noLinkFormat' => '<div>%s</div>',
                    'authField' => 'role_id',
                ),
    

    In this case, I also tried using the role_id numbers as in 'permissions' => array('1', '2', '3') , but that prevents the display of the menu item even though debug shows that the logged in user has 'role_id' => '1' in his $user array.

    Recommend Projects

    • React photo React

      A declarative, efficient, and flexible JavaScript library for building user interfaces.

    • Vue.js photo Vue.js

      ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

    • Typescript photo Typescript

      TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

    • TensorFlow photo TensorFlow

      An Open Source Machine Learning Framework for Everyone

    • Django photo Django

      The Web framework for perfectionists with deadlines.

    • D3 photo D3

      Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

    Recommend Topics

    • javascript

      JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

    • web

      Some thing interesting about web. New door for the world.

    • server

      A server is a program made to process requests and deliver data to clients.

    • Machine learning

      Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

    • Game

      Some thing interesting about game, make everyone happy.

    Recommend Org

    • Facebook photo Facebook

      We are working to build community through open source technology. NB: members must have two-factor auth.

    • Microsoft photo Microsoft

      Open source projects and samples from Microsoft.

    • Google photo Google

      Google โค๏ธ Open Source for everyone.

    • D3 photo D3

      Data-Driven Documents codes.