Commit 03d6daf7 authored by JohnAlbin's avatar JohnAlbin

Issue #2141119: Remove code for unimplemented features. @TODO Revert this commit and implement.

parent a437c756
ADDING MENU BLOCKS
------------------
To add new menu blocks, use the "Add menu block" link on the administer blocks
page, admin/structure/block. You will then be able to configure your menu block
before adding it.
CONFIGURING MENU BLOCKS
-----------------------
When adding or configuring a menu block, several configuration options are
available:
Basic Options:
Block title
For menu trees that start with the 1st level, the default block title will be
the menu name. For menu trees that start with the 2nd level or deeper, the
default block title will be the title for the parent menu item of the
specified level.
For example, if the active menu trail for the Management menu is: Administer >
Structure > Menus > Main menu, then a menu block configured to start with the
1st level of the Management menu will display a block title of "Management".
And a menu block configured to start with the 3rd level of the Management menu
will display a block title of "Structure".
Block title as link
For menu trees that start with the 2nd level or deeper, the default block
title will be the title for the parent menu item of the specified level. If
this option is checked, the block title will be a link to that menu item.
Administrative title
To help identify the block on the administer blocks page, you can specify a
unique title to be used on that page. If blank, the regular title will be
used.
Menu name
Select the menu to use for the tree of links.
Starting level
Blocks that start with the 1st level will always be visible. Blocks that start
with the 2nd level or deeper will only be visible when the trail to the active
menu item is in the block's tree.
Maximum depth
From the starting level, specify the maximum depth of the tree. Blocks with a
maximum depth of 1 will just be a single un-nested list of links with none of
those links' children displayed.
Advanced options:
Make the starting level follow the active menu item
If the active menu item is deeper than the level specified above, the starting
level will follow the active menu item. Otherwise, the starting level of the
tree will remain fixed.
Expand
All children of this menu will be expanded.
Sort
Sort each item in the active trail to the top of its level. When used on a
deep or wide menu tree, the active menu item's children will be easier to see
when the page is reloaded.
Fixed parent item
If you select a specific menu item, you alter the "starting level" and
"maximum depth" options to be relative to the fixed parent item. The tree of
links will only contain children of the selected parent item.
STYLING MENU BLOCKS
-------------------
Classes:
Themers should look at the myriad of classes added to the <div>, <li> and <a>
elements.
<div>
The <div> wrapped around the menu tree has a class for several of the
configurable options of the block: menu-block-[block id number]
menu-name-[menu name] parent-mlid-[menu link ID] menu-level-[level number]
<li>
The <li> elements of the menu tree can have an extended list of classes
(compared to standard menu trees): first last menu-mlid-[menu link ID]
has-children active active-trail
<a>
The <a> elements of the menu tree can have: active active-trail
Templates:
In addition, the wrapper <div> for the block is generated using the
menu-block-wrapper.tpl.php template. And Menu block provides several theme hook
suggestions for that template:
- menu-block-wrapper--[block id number].tpl.php
- menu-block-wrapper--[menu name].tpl.php
For example, a file in your theme called
menu-block-wrapper--main-menu.tpl.php can be used to override the <div> for
just the "Primary links" menu blocks.
Theme functions:
Menu block uses Drupal core's menu theme functions. However, it also provides
theme hook suggestions that can be used to override any of the theme functions
called by it.
- theme_menu_tree() can be overridden by creating one of:
- [theme]_menu_tree__[menu name]()
- [theme]_menu_tree__menu_block()
- [theme]_menu_tree__menu_block__[menu name]()
- [theme]_menu_tree__menu_block__[block id number]()
- theme_menu_link() can be overridden by creating one of:
- [theme]_menu_link__[menu name]()
- [theme]_menu_link__menu_block()
- [theme]_menu_link__menu_block__[menu name]()
- [theme]_menu_link__menu_block__[block id number]()
For example, if you created a bartik_menu_tree__menu_block() function, it would
override theme_menu_tree() any time it was used by this module, but not when
used by any other module. Similarly, a bartik_menu_link__menu_block__1()
function would override theme_menu_link(), but only for the first menu block in
your system (the menu block with an ID of 1).
MENU BLOCK API
--------------
Developers can use the API of this module to create their own menu trees outside
the confines of blocks. All of the publicly available API functions are
documented in the menu_block.module file.
In addition, Menu block implements HOOK_menu_block_get_menus(),
HOOK_menu_block_get_sort_menus() and HOOK_menu_block_tree_alter(). See
menu_block.api.php for documentation.
menu_block_suppress_core: 0
menu_block_menu_order:
account: ''
main: ''
<?php
/**
* @file
* Hooks provided by the Menu Block module.
*/
/**
* @addtogroup hooks
* @{
*/
/**
* Alter the menu tree and its configuration before the tree is rendered.
*
* @param $tree
* An array containing the unrendered menu tree.
* @param $config
* An array containing the configuration of the tree.
*/
function hook_menu_block_tree_alter(&$tree, &$config) {
}
/**
* Return a list of menus to use with the menu_block module.
*
* @return
* An array containing the menus' machine names as keys with their menu titles
* as values.
*/
function hook_menu_block_get_menus() {
$menus = array();
// For each menu, add the following information:
$menus['menu_name'] = 'menu title';
return $menus;
}
/**
* Return a list of menus to use on menu block's settings form.
*
* Menu block's settings page sorts menus for use with its "the menu selected by
* the page" option.
*
* @return
* An array containing the menus' machine names as keys with their menu titles
* as values. The key may optionally be a regular expression to match several
* menus at a time; see book_menu_block_get_sort_menus() for an example.
*/
function hook_menu_block_get_sort_menus() {
$menus = array();
// For each menu, add the following information:
$menus['menu_name'] = 'menu title';
// Optionally, add a regular expression to match several menus at once.
$menus['/^my\-menus\-.+/'] = t('My menus');
return $menus;
}
/**
* @} End of "addtogroup hooks".
*/
......@@ -4,4 +4,3 @@ core: 8.x
type: module
dependencies:
- menu_ui
# configure: menu_block.configure
menu_block.configure:
title: 'Menu block'
description: 'Configuration options for the menu block module.'
route_name: menu_block.configure
parent: system.admin_config_ui
<?php
/**
* @file
* Provides configurable blocks of menu links.
*/
///**
// * Implements hook_menu_link_defaults().
// */
//function menu_block_menu_link_defaults() {
// $links = array();
// $links['menu_block.configure'] = array(
// 'link_title' => 'Menu Block',
// 'description' => 'Configure menu block.',
// 'route_name' => 'menu_block.configure',
// 'parent' => 'system.admin.config.user-interface',
// );
// return $links;
//}
///**
// * Gets the data structure representing a menu tree for the given configuration.
// *
// * @param $config
// * See the $config param of menu_tree_build().
// *
// * @deprecated as of Drupal 8.x-2.0. Use
// * Drupal::service('menu_block.repository')->blockData() directly instead.
// */
//function menu_tree_block_data(&$config) {
// return \Drupal::service('menu_block.repository')->blockData($config);
//}
//
///**
// * Returns the current page's menu.
// *
// * @deprecated as of Drupal 8.x-2.0. Use
// * Drupal::service('menu_block.repository')->getCurrentPageMenu() directly
// * instead.
// */
//function menu_block_get_current_page_menu() {
// return \Drupal::service('menu_block.repository')->getCurrentPageMenu();
//}
//
///**
// * Build a menu tree based on the provided configuration.
// *
// * @param $config
// * array An array of configuration options that specifies how to build the
// * menu tree and its title.
// * - delta: (string) The menu_block's block delta.
// * - 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.
// * - parent_mlid: (int) The mlid of the item that should root the tree. Use 0
// * to use the menu's root.
// * - title_link: (boolean) Specifies if the title should be rendered as a link
// * or a simple string.
// * - admin_title: (string) An optional title to uniquely identify the block on
// * the administer blocks page.
// * - level: (int) The starting level of the tree.
// * - follow: (string) Specifies if the starting level should follow the
// * active menu item. Should be set to 0, 'active' or 'child'.
// * - depth: (int) The maximum depth the tree should contain, relative to the
// * starting level.
// * - expanded: (boolean) Specifies if the entire tree be expanded or not.
// * - sort: (boolean) Specifies if the tree should be sorted with the active
// * trail at the top of the tree.
// * @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.
// *
// * @deprecated
// */
//function menu_tree_build(&$config) {
// return \Drupal::service('menu_block.render')->build($config);
//}
//
///**
// * Retrieves the menu item to use for the tree's title.
// *
// * @param $render_title_as_link
// * boolean A boolean that says whether to render the title as a link or a
// * simple string.
// * @return
// * array A renderable array containing the tree's title.
// *
// * @deprecated
// */
//function menu_block_get_title($render_title_as_link = TRUE) {
// return \Drupal::service('menu_block.render')->getTitle();
//}
//
///**
// * Returns a renderable menu tree.
// *
// * This is a copy of menu_tree_output() with additional classes added to the
// * output.
// *
// * @param $tree
// * array A data structure representing the tree as returned from menu_tree_data.
// * @return
// * string The rendered HTML of that data structure.
// *
// * @deprecated
// */
//function menu_block_tree_output(&$tree, $config = array()) {
// return \Drupal::service('menu_block.render')->treeOutput();
//}
//
///**
// * Implements hook_menu_block_get_menus() on behalf of book.module.
// * @todo move these to a plugin?
// */
//function book_menu_block_get_menus() {
// $menus = array();
// foreach (\Drupal::service('book.manager')->getAllBooks() AS $book) {
// $menus[$book['menu_name']] = $book['title'];
// }
// return $menus;
//}
//
///**
// * Implements hook_menu_block_get_sort_menus() on behalf of book.module.
// * @todo move these to a plugin?
// */
//function book_menu_block_get_sort_menus() {
// return array(
// '/^book\-toc\-.+/' => t('Book navigation'),
// );
//}
menu_block.configure:
path: '/admin/config/user-interface/menu-block'
defaults:
_form: '\Drupal\menu_block\Form\MenuBlockConfigForm'
_title: 'Menu block'
requirements:
_menu_block_access: 'TRUE'
services:
menu_block.repository:
class: Drupal\menu_block\MenuBlockRepository
arguments: ['@database', '@entity.manager', '@cache.data', '@module_handler']
menu_block.builder:
class: Drupal\menu_block\MenuBlockBuilder
arguments: ['@database', '@entity.manager', '@cache.data', '@module_handler', '@config.factory', '@request', '@menu_block.repository']
menu_block.render:
class: Drupal\menu_block\MenuBlockViewBuilder
arguments: ['@menu_block.builder', '@request', '@menu_block.repository']
access_check.menu_block:
class: Drupal\menu_block\Access\MenuBlockAccessCheck
tags:
- { name: access_check, applies_to: _menu_block_access }
......@@ -8,8 +8,6 @@
namespace Drupal\menu_block\Plugin\Block;
use Drupal\Core\Form\FormStateInterface;
// use Drupal\Core\Session\AccountInterface;
// use Drupal\menu_block\MenuBlockRepositoryInterface;
use Drupal\system\Entity\Menu;
use Drupal\system\Plugin\Block\SystemMenuBlock;
......@@ -89,8 +87,6 @@ class MenuBlock extends SystemMenuBlock {
'#title' => $this->t('Fixed parent item'),
'#description' => $this->t('Alter the options in “Menu levels” to be relative to the fixed parent item. The block will only contain children of the selected menu link.'),
);
// @todo move the constant to the menu block repository.
// $form['advanced']['parent']['#options'][MenuBlockRepositoryInterface::CURRENT_PAGE_MENU . ':0'] = '<' . $this->t('the menu selected by the page') . '>';
// Open the details field sets if their config is not set to defaults.
foreach(array('menu_levels', 'advanced') as $fieldSet) {
......@@ -101,63 +97,6 @@ class MenuBlock extends SystemMenuBlock {
}
}
/*
$form['title_link'] = array(
'#type' => 'checkbox',
'#title' => $this->t('Block title as link'),
'#default_value' => $config['title_link'],
'#description' => $this->t('Make the default block title a link to that menu item. An overridden block title will not be a link.'),
'#states' => array(
'visible' => array(
':input[name=title]' => array('value' => ''),
),
),
);
$form['admin_title'] = array(
'#type' => 'textfield',
'#default_value' => $config['admin_title'],
'#title' => $this->t('Administrative title'),
'#description' => $this->t('This title will be used administratively to identify this block. If blank, the regular title will be used.'),
);
// The value of "follow" in the database/config array is either FALSE or the
// value of the "follow_parent" form element.
if ($follow = $config['follow']) {
$follow_parent = $follow;
$follow = 1;
}
else {
$follow_parent = 'active';
}
$form['follow'] = array(
'#type' => 'checkbox',
'#title' => $this->t('Make the starting level follow the active menu item.'),
'#default_value' => $follow,
'#description' => $this->t('If the active menu item is deeper than the level specified above, the starting level will follow the active menu item. Otherwise, the starting level of the tree will remain fixed.'),
'#element_validate' => array('\Drupal\menu_block\Plugin\Block\MenuBlock::followValidate'),
);
$form['follow_parent'] = array(
'#type' => 'select',
'#title' => $this->t('Starting level will be'),
'#default_value' => $follow_parent,
'#options' => array(
'active' => $this->t('Active menu item'),
'child' => $this->t('Children of active menu item'),
),
'#description' => $this->t('When following the active menu item, specify if the starting level should be the active menu item or its children.'),
'#states' => array(
'visible' => array(
':input[name="follow"]' => array('checked' => TRUE),
),
),
);
$form['sort'] = array(
'#type' => 'checkbox',
'#title' => $this->t('<strong>Sort</strong> menu tree by the active menu item’s trail.'),
'#default_value' => $config['sort'],
'#description' => $this->t('Sort each item in the active trail to the top of its level. When used on a deep or wide menu tree, the active menu item’s children will be easier to see when the page is reloaded.'),
);
*/
return $form;
}
......@@ -181,22 +120,6 @@ class MenuBlock extends SystemMenuBlock {
$this->configuration['parent'] = $form_state->getValue('parent');
}
/**
* Validates the follow element of the block configuration form.
*/
// public static function followValidate($element, &$form_state) {
// // The value of "follow" stored in the database/config array is either FALSE
// // or the value of the "follow_parent" form element.
// if ($form_state['values']['settings']['follow'] && !empty($form_state['values']['settings']['follow_parent'])) {
// $form_state['values']['settings']['follow'] = $form_state['values']['settings']['follow_parent'];
// }
// }
// public function access(AccountInterface $account) {
// return $account->hasPermission('administer blocks') &&
// $account->hasPermission('administer menu');
// }
/**
* {@inheritdoc}
*/
......@@ -245,10 +168,6 @@ class MenuBlock extends SystemMenuBlock {
'depth' => 0,
'expand' => 0,
'parent' => $this->getDerivativeId() . ':',
// 'title_link' => 0,
// 'admin_title' => '',
// 'follow' => 0,
// 'sort' => 0,
];
}
......
<?php
/**
* @file
* Contains Drupal\menu_block\Access\MenuBlockAccessCheck.
*/
namespace Drupal\menu_block\Access;
use Drupal\Core\Routing\Access\AccessInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\HttpFoundation\Request;
/**
* Determine whether the user has permission to use menu_block module.
*/
class MenuBlockAccessCheck implements AccessInterface {
/**
* {@inheritdoc}
*/
public function access(Route $route, Request $request, AccountInterface $account) {
return $account->hasPermission('administer blocks') && $account->hasPermission('administer menu') ? static::ALLOW : static::DENY;
}
}
<?php
/**
* @file
* Contains \Drupal\menu_block\Form\MenuBlockConfigForm.
*/
namespace Drupal\menu_block\Form;
use Drupal\Component\Utility\String;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\ConfigFormBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
class MenuBlockConfigForm extends ConfigFormBase {
/**
* The module handler service.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* Constructs a SiteInformationForm object.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The factory for configuration objects.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
*/
public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler) {
parent::__construct($config_factory);
$this->moduleHandler = $module_handler;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('config.factory'),
$container->get('module_handler')
);
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'menu_block_admin_settings_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, array &$form_state) {
$config = $this->configFactory->get('menu_block.settings');
// Option to suppress core's blocks of menus.
$form['menu_block_suppress_core'] = array(
'#type' => 'checkbox',
'#title' => $this->t('Suppress Drupal’s standard menu blocks'),
'#default_value' => $config->get('menu_block_suppress_core'),
'#description' => $this->t('On the blocks admin page, hide Drupal’s standard blocks of menus.'),
'#access' => $this->moduleHandler->moduleExists('block'),
);
// Retrieve core's menus.
$menus = menu_get_menus();
// Retrieve all the menu names provided by hook_menu_block_get_sort_menus().
$menus = array_merge($menus, $this->moduleHandler->invokeAll('menu_block_get_sort_menus'));
asort($menus);
// Load stored configuration.
$menu_order = $this->config('menu_block.settings')->get('menu_block_menu_order');
// Remove any menus no longer in the list of all menus.
foreach (array_keys($menu_order) as $menu) {
if (!isset($menus[$menu])) {
unset($menu_order[$menu]);
}
}
// Merge the saved configuration with any un-configured menus.
$all_menus = $menu_order + $menus;
$form['heading'] = array(
'#markup' => '<p>' . $this->t('If a block is configured to use <em>"the menu selected by the page"</em>, the block will be generated from the first "available" menu that contains a link to the page.') . '</p>',
);
// Orderable list of menu selections.
$form['menu_order'] = array(
'#type' => 'table',
'#header' => array(
t('Menu'),
t('Available'),
t('Weight'),
),
'#attributes' => array('id' => 'menu-block-menus'),
'#tabledrag' => array(
array(
'action' => 'order',
'relationship' => 'sibling',
'group' => 'menu-weight',
),
),
);
foreach (array_keys($all_menus) as $menu_name) {
$form['menu_order'][$menu_name] = array(
'title' => array(
'#markup' => String::checkPlain($menus[$menu_name]),
),
'available' => array(
'#type' => 'checkbox',
'#attributes' => array('title' => $this->t('Select from the @menu_name menu', array('@menu_name' => $menus[$menu_name]))),
'#default_value' => isset($menu_order[$menu_name]),
),
'weight' => array(
'#type' => 'textfield',
'#title' => t('Weight for @title', array('@title' => $menu_name)),
'#title_display' => 'invisible',
'#default_value' => isset($menu_order[$menu_name]) ? $menu_order[$menu_name] : 0,
'#attributes' => array('class' => array('menu-weight')),
),
'#attributes' => array('class' => array('draggable')),
);
}
$form['footer_note'] = array(
'#markup' => '<p>' . $this->t('The above list will <em>not</em> affect menu blocks that are configured to use a specific menu.') . '</p>',
);
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, array &$form_state) {
$config = $this->configFactory->get('menu_block.settings');
$menu_order = array();
foreach ($form_state['values']['menu_order'] as $menu_name => $row) {
if ($row['available']) {
// Add available menu and its weight to list.
$menu_order[$menu_name] = (int) $row['weight'];
}
}
// Sort the keys by the weight stored in the value.
asort($menu_order);
foreach ($menu_order as $menu_name => $weight) {
// Now that the array is sorted, the weight is redundant data.
$menu_order[$menu_name] = '';
}
$config->set('menu_block_menu_order', $menu_order)
->set('menu_block_suppress_core', $form_state['values']['menu_block_suppress_core'])
->save();
parent::submitForm($form, $form_state);
}
}
This diff is collapsed.
<?php
/**
* @file
* Contains
*/
namespace Drupal\menu_block;
/**
* Defines a service for building menu block output.
*/
interface MenuBlockBuilderInterface {
/**
* Gets the data structure representing a menu tree for the given configuration.
*
* @param array $config
* An array of configuration options that specifies how to build the
* menu tree and its title.
*
* @return array
* An array of menu links.
*
* @see \Drupal\menu_block\MenuBlockBuilder::build().
*/
public function blockData(&$config);
/**
* Returns the current page's menu.
*
* @return string
* Current page's menu name.
*/
public function getCurrentPageMenu();
/**
* Adds the active trail indicators into the tree.
*
* The data returned by menu_tree_page_data() has link['in_active_trail'] set
* to TRUE for each menu item in the active trail. The data returned from
* $this->menuTreeAllData() does not contain the active trail indicators. This is
* a helper function that adds it back in.
*
* @param array $tree
* The menu tree.
*/
public function addActivePath(&$tree);
/**
* Trims everything but the active trail in the tree.
*
* @param array $tree
* The menu tree to trim.
*/
public function trimActivePath(&$tree);
/**
* Sorts the active trail to the top of the tree.