      1: <?php
      2:
      3: /**
      4:  * Pancake
      5:  *
      6:  * A simple, fast, self-hosted invoicing application
      7:  *
      8:  * @package             Pancake
      9:  * @author              Pancake Dev Team
     10:  * @copyright           Copyright (c) 2014, Pancake Payments
     11:  * @license             http://pancakeapp.com/license
     12:  * @link        http://pancakeapp.com
     13:  * @since       Version 4.1.20
     14:  */
     15:
     16: namespace Pancake;
     17:
     18: /**
     19:  * The Navigation API<br />Allows you to add navbar links/dividers/labels.
     20:  *
     21:  * @category Navigation
     22:  */
     23: class Navigation {
     24:
     25:     /**
     26:      * A navbar item of type link.
     27:      * Will be rendered as &lt;a>.
     28:      *
     29:      * @ignore
     30:      */
     31:     const TYPE_LINK = 1;
     32:
     33:     /**
     34:      * A navbar item of type label.
     35:      * Will be rendered as &lt;label>.
     36:      *
     37:      * @ignore
     38:      */
     39:     const TYPE_LABEL = 2;
     40:
     41:     /**
     42:      * A navbar item of type divider.
     43:      * Will be rendered as &lt;li class='divider'>&lt;/li>.
     44:      *
     45:      * @ignore
     46:      */
     47:     const TYPE_DIVIDER = 4;
     48:
     49:     /**
     50:      * Contains all of the links/labels/dividers currently registered in the navbar.
     51:      * @var array
     52:      */
     53:     protected static $navbar;
     54:
     55:     /**
     56:      * Contains all of the quick links currently registered.
     57:      * @var array
     58:      */
     59:     protected static $quicklinks;
     60:
     61:     /**
     62:      * Add a new new navbar link.
     63:      *
     64:      * If $parent_url is specified, this link will be added in a submenu of the link with $url == $parent_url.
     65:      *
     66:      * @param string $url
     67:      * @param string $title
     68:      * @param string $parent_url
     69:      * @throws NavigationException
     70:      */
     71:     public static function registerNavbarLink($url, $title, $parent_url = null) {
     72:         self::registerNavbarItem($url, $title, $parent_url, self::TYPE_LINK);
     73:     }
     74:
     75:     /**
     76:      * Add a new new navbar label.
     77:      *
     78:      * If $parent_url is specified, this label will be added in a submenu of the link with $url == $parent_url.
     79:      *
     80:      * @link http://i.28hours.org/20140402-130106-1b36.png What a navbar label looks like
     81:      * @param string $title
     82:      * @param string $parent_url
     83:      * @throws NavigationException
     84:      */
     85:     public static function registerNavbarLabel($title, $parent_url) {
     86:         self::registerNavbarItem($title, $title, $parent_url, self::TYPE_LABEL);
     87:     }
     88:
     89:     /**
     90:      * Add a new new navbar divider.
     91:      *
     92:      * If $parent_url is specified, this label will be added in a submenu of the link with $url == $parent_url.
     93:      *
     94:      * @link http://i.28hours.org/20140402-130239-9c04.png What a navbar divider looks like
     95:      * @param string $title
     96:      * @param string $parent_url
     97:      * @throws NavigationException
     98:      */
     99:     public static function registerDivider($parent_url) {
    100:         $title = "divider-" . uniqid();
    101:         self::registerNavbarItem($title, $title, $parent_url, self::TYPE_DIVIDER);
    102:     }
    103:
    104:     /**
    105:      * Display a number or string in a badge to the right of your link.
    106:      *
    107:      * @link http://i.28hours.org/20140402-130421-0fc0.png What a badge looks like in the main menu
    108:      * @link http://i.28hours.org/20140402-130409-d58b.png What a badge looks like in submenus
    109:      * @param string $url
    110:      * @param string $badge
    111:      * @throws NavigationException
    112:      */
    113:     public static function setBadge($url, $badge) {
    114:         if (!isset(self::$navbar[$url])) {
    115:             throw new NavigationException("You cannot set a badge for the link '$url', because it is not a navbar link.");
    116:         }
    117:
    118:         self::$navbar[$url]['badge'] = $badge;
    119:     }
    120:
    121:     /**
    122:      * Add a class to a link's &lt;a>.
    123:      *
    124:      * @param string $url
    125:      * @param string $class
    126:      * @throws NavigationException
    127:      */
    128:     public static function setClass($url, $class) {
    129:         if (!isset(self::$navbar[$url])) {
    130:             throw new NavigationException("You cannot set a class for the link '$url', because it is not a navbar link.");
    131:         }
    132:
    133:         self::$navbar[$url]['class'] = $class;
    134:     }
    135:
    136:     /**
    137:      * Add a class to a link's container &lt;li>.
    138:      *
    139:      * @param string $url
    140:      * @param string $container_class
    141:      * @throws NavigationException
    142:      */
    143:     public static function setContainerClass($url, $container_class) {
    144:         if (!isset(self::$navbar[$url])) {
    145:             throw new NavigationException("You cannot set a class for the container of the link '$url', because it is not a navbar link.");
    146:         }
    147:
    148:         self::$navbar[$url]['container_class'] = $container_class;
    149:     }
    150:
    151:     /**
    152:      * Add data-* attributes to a link's container &lt;li>.
    153:      *
    154:      * `$data_attributes` is an array of attribute name => attribute value pairs. For example:
    155:      *
    156:      * `$data_attributes = array("attribute1" => "yes");`
    157:      *
    158:      * This will add `data-attribute1="yes"` to the specified link's container &lt;li>.
    159:      *
    160:      * @param string $url
    161:      * @param array $data_attributes
    162:      * @throws NavigationException
    163:      */
    164:     public static function setContainerDataAttributes($url, $data_attributes) {
    165:         if (!isset(self::$navbar[$url])) {
    166:             throw new NavigationException("You cannot set data attributes for the container of the link '$url', because it is not a navbar link.");
    167:         }
    168:
    169:         if (is_array($data_attributes) or $data_attributes instanceof ArrayAccess) {
    170:             self::$navbar[$url]['container_data_attributes'] = $data_attributes;
    171:         } else {
    172:             throw new NavigationException("Unexpected \$data_attributes type: " . gettype($data_attributes) . " (Expected: array or instanceof ArrayAccess)");
    173:         }
    174:     }
    175:
    176:     /**
    177:      * @todo WIP
    178:      *
    179:      * @param string $url
    180:      * @ignore
    181:      */
    182:     public static function registerQuickLinkOwner($url) {
    183:         self::$quicklinks[$url] = array();
    184:     }
    185:
    186:     /**
    187:      * @todo WIP
    188:      *
    189:      * @param string $owner
    190:      * @param string $url
    191:      * @param string $title
    192:      * @ignore
    193:      */
    194:     public static function registerQuickLink($owner, $url, $title) {
    195:         if (!isset(self::$quicklinks[$url])) {
    196:             throw new NavigationException("The page '$owner' does not use Quick Links, and thus no Quick Links can be registered for it.");
    197:         }
    198:
    199:         self::$quicklinks[$url] = $title;
    200:     }
    201:
    202:     /**
    203:      * Get a tree of navbar links, ready to be displayed.
    204:      *
    205:      * @return array
    206:      * @ignore
    207:      */
    208:     public static function getNavbarLinks() {
    209:         $navbar = array();
    210:         $self_navbar = self::$navbar;
    211:
    212:         $process_children = function($details) use (&$process_children, $self_navbar) {
    213:             if (count($details['children']) > 0) {
    214:                 $children = array();
    215:                 foreach ($details['children'] as $child) {
    216:                     $child_details = $self_navbar[$child];
    217:                     $child_details['children'] = $process_children($child_details);
    218:                     $children[$child] = $child_details;
    219:                 }
    220:                 return $children;
    221:             }
    222:         };
    223:
    224:         foreach (self::$navbar as $url => $details) {
    225:             if ($details['parent_url'] === null) {
    226:                 $details['children'] = $process_children($details);
    227:                 $navbar[$url] = $details;
    228:             }
    229:         }
    230:
    231:         return $navbar;
    232:     }
    233:
    234:     /**
    235:      * Get all registered quick links for a given page.
    236:      *
    237:      * @param string $owner
    238:      * @return array
    239:      * @throws NavigationException
    240:      * @ignore
    241:      */
    242:     public static function getQuickLinks($owner) {
    243:         if (!isset(self::$quicklinks[$owner])) {
    244:             throw new NavigationException("The page '$owner' does not use Quick Links, and thus it is impossible to get Quick Links for it.");
    245:         }
    246:
    247:         return self::$quicklinks[$owner];
    248:     }
    249:
    250:     /**
    251:      * Register a navbar item (of any kind).
    252:      *
    253:      * @param string $url
    254:      * @param string $title
    255:      * @param string $parent_url
    256:      * @param (one of the TYPE_* constants) $type
    257:      * @throws NavigationException
    258:      * @ignore
    259:      */
    260:     protected static function registerNavbarItem($url, $title, $parent_url, $type) {
    261:         if ($parent_url !== null and ! isset(self::$navbar[$parent_url])) {
    262:             throw new NavigationException("The link '$parent_url' cannot be set as the parent of '$url' because it is not a navbar link.");
    263:         }
    264:
    265:         self::$navbar[$url] = array(
    266:             'title' => $title,
    267:             'children' => array(),
    268:             'parent_url' => $parent_url,
    269:             'badge' => null,
    270:             'class' => null,
    271:             'container_class' => null,
    272:             'type' => $type,
    273:             'container_data_attributes' => array(),
    274:         );
    275:
    276:         if ($parent_url !== null) {
    277:             self::$navbar[$parent_url]['children'][] = $url;
    278:         }
    279:     }
    280:
    281: }
    282: