- <?php
-
- * Implements hook_block_configure().
- */
- function _system_block_configure($delta = '', $settings = array()) {
-
- $settings += system_menu_block_defaults($delta);
- return system_menu_block_form($settings);
- }
-
- * The default menu block configuration.
- *
- * @return array
- */
- function system_menu_block_defaults($menu_name) {
- $defaults = array(
- 'level' => 1,
- 'menu_name' => $menu_name,
- 'style' => NULL,
- 'expand_all' => FALSE,
- 'clickdown' => FALSE,
- );
- if ($menu_name == 'main-menu') {
- $defaults['depth'] = 1;
- $defaults['toggle'] = TRUE;
- }
- else {
- $defaults['depth'] = 0;
- $defaults['toggle'] = FALSE;
- }
- return $defaults;
- }
-
- * Returns the configuration form for a menu tree.
- *
- * @param $config
- * An associated array of settings passed in by hook_block_configure().
- * If none are given, default configuration is assumed.
- * @return
- * The form array. This is a form fragment and not in full Form API format.
- */
- function system_menu_block_form($config) {
- $form['menu_name'] = array(
- '#type' => 'value',
- '#value' => $config['menu_name'],
- );
-
- $form['style'] = array(
- '#type' => 'select',
- '#title' => t('Menu style'),
- '#options' => array(
- 'top_only' => t('Top level only'),
- 'dropdown' => t('Dropdown menu'),
- 'tree' => t('Hierarchical tree'),
- ),
- '#default_value' => empty($config['style']) ? 'tree' : $config['style'],
- );
-
- $form['level'] = array(
- '#type' => 'select',
- '#title' => t('Starting level'),
- '#default_value' => $config['level'],
- '#options' => array(
- '1' => t('1st level (primary)'),
- '2' => t('2nd level (secondary)'),
- '3' => t('3rd level (tertiary)'),
- '4' => t('4th level'),
- '5' => t('5th level'),
- '6' => t('6th level'),
- '7' => t('7th level'),
- '8' => t('8th level'),
- '9' => t('9th level'),
- ),
- '#description' => t('The block will be visible only if the current page has its menu item at or below the level set here.'),
- '#states' => array(
- 'visible' => array(
- 'select[name="block_settings[style]"]' => array('value' => 'tree'),
- ),
- ),
- );
- $form['depth'] = array(
- '#type' => 'select',
- '#title' => t('Maximum depth'),
- '#default_value' => $config['depth'],
- '#options' => array(
- '1' => '1',
- '2' => '2',
- '3' => '3',
- '4' => '4',
- '5' => '5',
- '6' => '6',
- '7' => '7',
- '8' => '8',
- '9' => '9',
- '0' => t('Unlimited'),
- ),
- '#description' => t('The maximum depth of the menu tree from the starting level (if available).'),
- '#states' => array(
- 'invisible' => array(
- 'select[name="block_settings[style]"]' => array('value' => 'top_only'),
- ),
- ),
- );
- $form['expand_all'] = array(
- '#type' => 'checkbox',
- '#title' => t('Show all menu links'),
- '#default_value' => $config['expand_all'],
- '#description' => t('When unchecked, only expanded or active trail menu links will be displayed.'),
- '#states' => array(
- 'visible' => array(
- 'select[name="block_settings[style]"]' => array('value' => 'tree'),
- ),
- ),
- );
- $form['clickdown'] = array(
- '#type' => 'checkbox',
- '#title' => t('Use a click to open, instead of a hover'),
- '#default_value' => $config['clickdown'],
- '#description' => t('Menus that don\'t appear or disappear on hover can be better for usability in some cases.'),
- '#states' => array(
- 'visible' => array(
- 'select[name="block_settings[style]"]' => array('value' => 'dropdown'),
- ),
- ),
- );
- $link = t('menu settings');
- if (user_access('administer menu')) {
- $link = l($link, 'admin/structure/menu/settings', array(
- 'attributes' => array('target' => '_blank'),
- ));
- }
- $form['toggle'] = array(
- '#type' => 'checkbox',
- '#title' => t('Display menu toggle button on small screens'),
- '#default_value' => $config['toggle'],
- '#description' => t('On devices with small screens, this option reduces the menu to a toggle button, commonly known as <a href="https://en.wikipedia.org/wiki/Hamburger_button" target="_blank"><em>hamburger button</em></a>. Clicking the icon reveals or hides the menu, saving screen space. The breakpoint for small screens can be configured in the global !menu_settings.', array(
- '!menu_settings' => $link,
- )),
- );
-
- return $form;
- }
-
- * Build a menu tree based on the provided configuration.
- *
- * @param array $config
- * An array of configuration options that specifies how to build the
- * menu tree and its title.
- * - menu_name: (string) The machine name of the requested menu. Can also be
- * set to MENU_TREE__CURRENT_PAGE_MENU to use the menu selected by the page.
- * - style: (string) The menu style used to render this menu.
- * - level: (int) The starting level of the tree. Some styles may ignore this
- * setting.
- * - depth: (int) The maximum depth the tree should contain, relative to the
- * starting level. Some styles may ignore this setting.
- *
- * @return array
- * An associative array containing several pieces of data.
- * - content: The tree as a renderable array.
- * - subject: The title rendered as HTML.
- * - subject_array: The title as a renderable array.
- */
- function system_menu_block_build(array $config) {
- if (module_exists('menu')) {
- $menu_names = menu_get_menus();
- }
- else {
- $menu_names = menu_list_system_menus();
- }
-
-
- $menu_name = str_replace('_', '-', $config['menu_name']);
- $config += system_menu_block_defaults($menu_name);
- if (empty($config['style'])) {
- $config['style'] = 'tree';
- }
-
-
- if ($config['style'] === 'dropdown') {
- $config['expand_all'] = TRUE;
- }
-
-
- backdrop_static_reset('menu_block_set_title');
- system_menu_block_set_title($menu_names[$menu_name]);
-
-
- $tree = system_menu_tree_block_data($config);
- $title = system_menu_block_get_title();
-
- $data = array();
- $data['subject'] = $title;
- $data['content'] = array();
-
- if (!empty($tree) && $output = menu_tree_output($tree)) {
- $data['content'] = $output;
-
- if (!empty($config['style'])) {
- $data['content']['#wrapper_attributes']['class'][] = 'menu-' . str_replace('_', '-', $config['style']);
- $data['content']['#wrapper_attributes']['data-menu-style'] = $config['style'];
- $data['content']['#wrapper_attributes']['data-clickdown'] = $config['clickdown'];
- $data['content']['#attached']['library'][] = array('system', 'backdrop.menus');
- if ($config['style'] === 'dropdown') {
- $data['content']['#attached']['library'][] = array('system', 'smartmenus');
- }
- }
- if (!empty($config['toggle']) && $config['toggle'] == TRUE) {
- $id = backdrop_html_id('menu-toggle-state');
- $data['content']['#wrapper_attributes']['data-menu-toggle-id'] = $id;
- $data['content']['#prefix'] = theme('menu_toggle', array('enabled' => $config['toggle'], 'id' => $id, 'text' => t('Menu')));
- $data['content']['#attached']['library'][] = array('system', 'backdrop.menu-toggle');
- }
- if (!empty($config['style_settings'])) {
- $data['content']['#wrapper_attributes']['data-menu-style'] = backdrop_json_encode($config['style_settings']);
- }
- }
-
- return $data;
- }
-
- * Gets the data structure representing a menu tree for the given configuration.
- *
- * @param array $config
- * See the $config param of menu_tree_build().
- *
- * @return array
- */
- function system_menu_tree_block_data(array &$config) {
-
-
-
- if ($config['style'] === 'top_only') {
- $config['level'] = 1;
- $config['depth'] = 1;
- }
- elseif ($config['style'] === 'dropdown') {
- $config['level'] = 1;
- }
-
-
- $max_depth = ($config['depth'] == 0) ? NULL : min($config['level'] + $config['depth'] - 1, MENU_MAX_DEPTH);
-
-
- $expand_all = FALSE;
- if ($config['depth'] != 1) {
- if (isset($config['expand_all'])) {
- $expand_all = (bool) $config['expand_all'];
- }
-
- elseif ($config['style'] !== 'tree') {
- $expand_all = TRUE;
- }
- }
-
-
-
- $tree = menu_tree_page_data($config['menu_name'], $max_depth, FALSE, $expand_all);
-
-
- backdrop_alter('menu_block_tree', $tree, $config);
-
-
- if ($config['level'] > 1) {
- system_menu_tree_prune_tree($tree, $config['level']);
- }
-
-
- if (!$expand_all) {
- system_menu_tree_trim_active_path($tree);
- }
-
-
- if ($config['depth'] > 0) {
- system_menu_tree_depth_trim($tree, $config['depth']);
- }
-
- return $tree;
- }
-
- * Prune a tree so that it begins at the specified level.
- *
- * This function will follow the active menu trail to the specified level.
- *
- * @param array $tree
- * The menu tree to prune.
- * @param int $level
- * The level of the original tree that will start the pruned tree.
- * @param array $parent_item
- * The menu item that should be used as the root of the tree.
- */
- function system_menu_tree_prune_tree(array &$tree, $level, array $parent_item = NULL) {
- if (!empty($parent_item)) {
-
- for ($i = 1; $i <= MENU_MAX_DEPTH && $parent_item["p$i"] != '0'; $i++) {
- $plid = $parent_item["p$i"];
- $found_active_trail = FALSE;
-
- foreach ($tree as $key => &$value) {
- if ($tree[$key]['link']['mlid'] == $plid) {
- system_menu_block_set_title($tree[$key]['link']);
-
- $tree = $tree[$key]['below'] ? $tree[$key]['below'] : array();
- $found_active_trail = TRUE;
- break;
- }
- }
-
- if (!$found_active_trail) {
- $tree = array();
- break;
- }
- }
- }
-
- $is_front_page = backdrop_is_front_page();
-
- for ($i = 1; $i < $level; $i++) {
- $found_active_trail = FALSE;
-
- foreach ($tree as $key => &$value) {
-
- if ($tree[$key]['link']['in_active_trail'] || ($tree[$key]['link']['link_path'] == '<front>' && $is_front_page)) {
-
- system_menu_block_set_title($tree[$key]['link']);
-
- $tree = $tree[$key]['below'] ? $tree[$key]['below'] : array();
- $found_active_trail = TRUE;
- break;
- }
- }
-
- if (!$found_active_trail) {
- $tree = array();
- break;
- }
- }
- }
-
- * Trim everything but the active trail in the tree.
- *
- * @param array $tree
- * The menu tree to trim.
- */
- function system_menu_tree_trim_active_path(array &$tree) {
- foreach ($tree as $key => &$value) {
- if (($tree[$key]['link']['in_active_trail'] || $tree[$key]['link']['expanded']) && $tree[$key]['below']) {
-
- system_menu_tree_trim_active_path($tree[$key]['below']);
- }
- else {
-
- $tree[$key]['below'] = FALSE;
- }
- }
- }
-
- * Prune a tree so it does not extend beyond the specified depth limit.
- *
- * @param array $tree
- * The menu tree to prune.
- * @param int $depth_limit
- * The maximum depth of the returned tree; must be a positive integer.
- */
- function system_menu_tree_depth_trim(array &$tree, $depth_limit) {
-
- if ($depth_limit < 1) {
- return;
- }
-
-
- foreach ($tree as $key => &$value) {
- if ($tree[$key]['below']) {
- if ($depth_limit > 1) {
- system_menu_tree_depth_trim($tree[$key]['below'], $depth_limit-1);
- }
- else {
-
- $tree[$key]['below'] = FALSE;
- }
- }
- }
- }
-
-
- * Sets the menu item to use for the tree's title.
- *
- * @param array|string $item
- * The menu item (an array) or the menu item's title as a string.
- *
- * @return array|string
- * The saved title value.
- */
- function system_menu_block_set_title($item = NULL) {
- $menu_item = &backdrop_static(__FUNCTION__, '');
-
- if (!is_null($item)) {
- $menu_item = $item;
- }
-
- return $menu_item;
- }
-
- * Retrieves the menu item to use for the tree's title.
- *
- * @return array|string
- * A render array or string containing the tree's title.
- */
- function system_menu_block_get_title() {
- $menu_item = system_menu_block_set_title();
-
- if (is_string($menu_item)) {
-
- $title = check_plain($menu_item);
- }
-
- else {
- $title = check_plain($menu_item['title']);
- }
- return $title;
- }