groupmenu.module in Group Menu 8
Same filename and directory in other branches
Gives the ability to create and manage menus for groups.
File
groupmenu.moduleView source
<?php
/**
* @file
* Gives the ability to create and manage menus for groups.
*/
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\gnode\Plugin\GroupContentEnabler\GroupNode;
use Drupal\group\Entity\Group;
use Drupal\group\Entity\GroupContent;
use Drupal\group\Entity\GroupContentInterface;
use Drupal\group\Entity\GroupContentType;
use Drupal\group\Entity\Form\GroupContentTypeForm;
use Drupal\menu_link_content\Form\MenuLinkContentForm;
use Drupal\menu_ui\Form\MenuLinkEditForm;
use Drupal\system\MenuInterface;
/**
* Implements hook_entity_create_access().
*
* When trying to create a menu it suffices to have the right to
* do so in only one group the menu belongs to.
*/
function groupmenu_entity_create_access(AccountInterface $account, array $context, $entity_bundle) {
$plugin_id = 'group_menu:menu';
$group_content_types = GroupContentType::loadByContentPluginId($plugin_id);
if (isset($group_content_types[$entity_bundle])) {
if ($context['group']
->hasPermission("create {$plugin_id} entity", $account)) {
return AccessResult::allowed();
}
}
return AccessResult::neutral();
}
/**
* Implements hook_entity_access().
*
* When trying to view, update or delete a menu it suffices to have the right to
* do so in only one group the menu belongs to.
*/
function groupmenu_entity_access(EntityInterface $entity, $op, AccountInterface $account) {
if (!$entity instanceof MenuInterface) {
return AccessResult::neutral();
}
return \Drupal::service('groupmenu.menu')
->menuAccess($op, $entity, $account);
}
/**
* Implements hook_module_implements_alter().
*/
function groupmenu_module_implements_alter(&$implementations, $hook) {
if ($hook == 'form_alter') {
// Make sure our hook_node_form_alter runs after the form alter of the
// menu_ui module.
$group = $implementations['groupmenu'];
unset($implementations['groupmenu']);
$implementations['groupmenu'] = $group;
}
}
/**
* Implements hook_form_alter().
*/
function groupmenu_form_alter(&$form, FormStateInterface $form_state, $form_id) {
$form_object = $form_state
->getFormObject();
// Filter menu options to group menus.
if ($form_object instanceof MenuLinkEditForm || $form_object instanceof MenuLinkContentForm) {
$account = \Drupal::currentUser();
if (!$account
->hasPermission('administer menu')) {
groupmenu_filter_parent_options($form['menu_parent']['#options']);
}
}
// Add setting to group node plugins to allow group menus.
if ($form_object instanceof GroupContentTypeForm) {
/** @var \Drupal\group\Entity\GroupContentType $group_content_type */
$group_content_type = $form_object
->getEntity();
if ($group_content_type
->getContentPlugin() instanceof GroupNode) {
$configuration = $group_content_type
->get('plugin_config');
$form['node_form_group_menu'] = [
'#type' => 'checkbox',
'#title' => t("Add group menus to node form"),
'#default_value' => isset($configuration['node_form_group_menu']) ? $configuration['node_form_group_menu'] : FALSE,
];
}
}
}
/**
* Implements hook_form_BASE_FORM_ID_alter().
*/
function groupmenu_form_node_form_alter(&$form, FormStateInterface $form_state) {
$account = \Drupal::currentUser();
$node = $form_state
->getFormObject()
->getEntity();
$groups = [];
// If a node is being edited at /node/%/edit, look for groups that it is a
// part of. If not, try to use the group ID from the URL.
if ($node
->id()) {
$group_content_array = GroupContent::loadByEntity($node);
foreach ($group_content_array as $group_content) {
$group_ids[] = $group_content->gid->target_id;
}
if (!empty($group_ids)) {
$groups = Group::loadMultiple($group_ids);
}
}
elseif (isset($form_state
->getStorage()['group'])) {
$groups[] = $form_state
->getStorage()['group'];
}
if (!empty($groups) || !$account
->hasPermission('administer menu')) {
$menu_options =& $form['menu']['link']['menu_parent']['#options'];
if ($menu_options) {
$filtered_menu_options = groupmenu_filter_parent_options($menu_options, $groups);
if ($filtered_menu_options) {
// If we have access to menu options, this means we have permission to
// edit the group menu. When the menu options were added by Group menu,
// access needs to be restored again as the Menu module removed it.
$form['menu']['#access'] = TRUE;
}
else {
// If there are no menu options available, remove the menu settings tab.
$form['menu']['#access'] = FALSE;
}
}
}
}
/**
* Deletes not allowed menu items from select element for current user.
*
* @param array &$options
* Form options to filter.
* @param \Drupal\group\Entity\GroupInterface[] $groups
* Optionally filter menus by group.
*
* @return bool
* FALSE if there is no allowed menu items,
* TRUE if we have some allowed menu items.
*/
function groupmenu_filter_parent_options(array &$options, array $groups = []) {
$allowed_menus = [];
$groupmenu_service = \Drupal::service('groupmenu.menu');
if (!empty($groups)) {
foreach ($groups as $group) {
$allowed_menus = array_merge($allowed_menus, $groupmenu_service
->loadUserGroupMenusByGroup('edit', $group
->id()));
}
}
else {
$allowed_menus = $groupmenu_service
->loadUserGroupMenus('edit');
}
if (count($allowed_menus) && is_array($options)) {
$option_keys = array_keys($options);
foreach ($option_keys as $option_key) {
list($menu, $item) = explode(':', $option_key);
if (!isset($allowed_menus[$menu])) {
unset($options[$option_key]);
}
}
return count($options);
}
return FALSE;
}
/**
* Implements hook_entity_type_alter().
*/
function groupmenu_entity_type_alter(array &$entity_types) {
// Use a different list builder to exclude group menus.
$config = \Drupal::config('groupmenu.settings');
if ($config
->get('groupmenu_hide_list')) {
$entity_types['menu']
->setHandlerClass('list_builder', 'Drupal\\groupmenu\\GroupMenuListBuilder');
}
}
/**
* Implements hook_preprocess_menu().
*
* Hides group menu's from admin menu.
*/
function groupmenu_preprocess_menu(&$variables) {
if (empty($variables['items'])) {
return;
}
// Ensure that menu_name exists.
if (!isset($variables['menu_name'])) {
// In rare cases (for unknown reasons) menu_name may not be set.
// As fallback, we can fetch it from the first menu item.
$variables['menu_name'] = NULL;
$first_link = reset($variables['items']);
if (isset($first_link['original_link'])) {
$variables['menu_name'] = $first_link['original_link']
->getMenuName();
}
}
if ($variables['menu_name'] == 'admin') {
// Get group types that enabled group menu's.
$plugin_id = 'group_menu:menu';
$group_content_types = \Drupal::entityTypeManager()
->getStorage('group_content_type')
->loadByProperties([
'content_plugin' => $plugin_id,
]);
if (empty($group_content_types)) {
return;
}
_groupmenu_filter_admin_links($variables['items'], $group_content_types);
}
}
/**
* Helper function to hide group menu's from admin menu.
*
* @param array $items
* The menu items to check for group menu's.
* @param array $group_content_types
* The group content types that have group menu content enabled.
*/
function _groupmenu_filter_admin_links(array &$items, array $group_content_types) {
foreach ($items as $route => &$item) {
if (!empty($item['url'])) {
/** @var \Drupal\Core\Url $url */
$url = $item['url'];
if (!$url
->isRouted()) {
continue;
}
$route_name = $url
->getRouteName();
$route_params = $url
->getRouteParameters();
if ($route_name === 'entity.menu.edit_form') {
$menu_name = $route_params['menu'];
// Check if this is a group menu.
$group_contents = \Drupal::entityTypeManager()
->getStorage('group_content')
->loadByProperties([
'type' => array_keys($group_content_types),
'entity_id' => $menu_name,
]);
if (!empty($group_contents)) {
unset($items[$route]);
}
else {
if (!empty($items[$route]['below'])) {
// Recursively call this function for the child items.
_groupmenu_filter_admin_links($items[$route]['below'], $group_content_types);
}
}
}
}
}
}
/**
* Implements hook_ENTITY_TYPE_insert().
*/
function groupmenu_group_content_insert(EntityInterface $entity) {
groupmenu_group_content_update($entity);
}
/**
* Implements hook_ENTITY_TYPE_update().
*/
function groupmenu_group_content_update(EntityInterface $entity) {
if ($entity
->getContentPlugin()
->getPluginId() === 'group_menu:menu') {
\Drupal::service('cache.groupmenu')
->invalidateAll();
}
}
/**
* Implements hook_ENTITY_TYPE_insert().
*/
function groupmenu_group_insert(EntityInterface $entity) {
if (!$entity
->getGroupType()
->hasContentPlugin('group_menu:menu')) {
return;
}
$group_type_configuration = $entity
->getGroupType()
->getContentPlugin('group_menu:menu')
->getConfiguration();
$auto_create_group_menu = $group_type_configuration['auto_create_group_menu'] ?? FALSE;
if (!$auto_create_group_menu) {
return;
}
$group_menu = \Drupal::entityTypeManager()
->getStorage('menu')
->create([
'id' => 'group-' . $entity
->id() . '-menu',
'label' => $entity
->label() . ' menu',
'description' => 'Menu for ' . $entity
->label(),
]);
$group_menu
->save();
// Add menu link for group if enabled.
$auto_create_home_link = $group_type_configuration['auto_create_home_link'] ?? FALSE;
if ($auto_create_home_link) {
\Drupal::entityTypeManager()
->getStorage('menu_link_content')
->create([
'title' => $group_type_configuration['auto_create_home_link_title'] ?? t('Home'),
'link' => [
'uri' => 'internal:/group/' . $entity
->id(),
],
'menu_name' => $group_menu
->id(),
'expanded' => TRUE,
])
->save();
}
$entity
->addContent($group_menu, 'group_menu:menu');
}
/**
* Implements hook_ENTITY_TYPE_delete().
*/
function groupmenu_group_content_delete(EntityInterface $entity) {
if ($entity
->getContentPlugin()
->getPluginId() === 'group_menu:menu') {
\Drupal::service('cache.groupmenu')
->invalidateAll();
}
}
/**
* Implements hook_ENTITY_TYPE_delete().
*/
function groupmenu_group_delete(EntityInterface $entity) {
$autocreated_menu = \Drupal::entityTypeManager()
->getStorage('menu')
->load('group-' . $entity
->id() . '-menu');
if ($autocreated_menu) {
$autocreated_menu
->delete();
}
}
Functions
Name | Description |
---|---|
groupmenu_entity_access | Implements hook_entity_access(). |
groupmenu_entity_create_access | Implements hook_entity_create_access(). |
groupmenu_entity_type_alter | Implements hook_entity_type_alter(). |
groupmenu_filter_parent_options | Deletes not allowed menu items from select element for current user. |
groupmenu_form_alter | Implements hook_form_alter(). |
groupmenu_form_node_form_alter | Implements hook_form_BASE_FORM_ID_alter(). |
groupmenu_group_content_delete | Implements hook_ENTITY_TYPE_delete(). |
groupmenu_group_content_insert | Implements hook_ENTITY_TYPE_insert(). |
groupmenu_group_content_update | Implements hook_ENTITY_TYPE_update(). |
groupmenu_group_delete | Implements hook_ENTITY_TYPE_delete(). |
groupmenu_group_insert | Implements hook_ENTITY_TYPE_insert(). |
groupmenu_module_implements_alter | Implements hook_module_implements_alter(). |
groupmenu_preprocess_menu | Implements hook_preprocess_menu(). |
_groupmenu_filter_admin_links | Helper function to hide group menu's from admin menu. |