123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627 |
- <?php
- /**
- * Elgg navigation library
- * Functions for managing menus and other navigational elements
- *
- * Breadcrumbs
- * Elgg uses a breadcrumb stack. The page handlers (controllers in MVC terms)
- * push the breadcrumb links onto the stack. @see elgg_push_breadcrumb()
- *
- *
- * Pagination
- * Automatically handled by Elgg when using elgg_list_entities* functions.
- * @see elgg_list_entities()
- *
- *
- * Tabs
- * @see navigation/tabs view
- *
- *
- * Menus
- * Elgg uses a single interface to manage its menus. Menu items are added with
- * {@link elgg_register_menu_item()}. This is generally used for menus that
- * appear only once per page. For dynamic menus (such as the hover
- * menu for user's avatar), a plugin hook is emitted when the menu is being
- * created. The hook is 'register', 'menu:<menu_name>'. For more details on this,
- * @see elgg_view_menu().
- *
- * Menus supported by the Elgg core
- * Standard menus:
- * site Site navigation shown on every page.
- * page Page menu usually shown in a sidebar. Uses Elgg's context.
- * topbar Topbar menu shown on every page. The default has two sections.
- * footer Like the topbar but in the footer.
- * extras Links about content on the page. The RSS link is added to this.
- *
- * Dynamic menus (also called just-in-time menus):
- * user_hover Avatar hover menu. The user entity is passed as a parameter.
- * entity The set of links shown in the summary of an entity.
- * river Links shown on river items.
- * owner_block Links shown for a user or group in their owner block.
- * filter The tab filter for content (all, mine, friends)
- * title The buttons shown next to a content title.
- * longtext The links shown above the input/longtext view.
- * login Menu of links at bottom of login box
- *
- * @package Elgg.Core
- * @subpackage Navigation
- */
- /**
- * Register an item for an Elgg menu
- *
- * @warning Generally you should not use this in response to the plugin hook:
- * 'register', 'menu:<menu_name>'. If you do, you may end up with many incorrect
- * links on a dynamic menu.
- *
- * @warning A menu item's name must be unique per menu. If more than one menu
- * item with the same name are registered, the last menu item takes priority.
- *
- * @see elgg_view_menu() for the plugin hooks available for modifying a menu as
- * it is being rendered.
- *
- * @see ElggMenuItem::factory() is used to turn an array value of $menu_item into an
- * ElggMenuItem object.
- *
- * @param string $menu_name The name of the menu: site, page, userhover,
- * userprofile, groupprofile, or any custom menu
- * @param mixed $menu_item A \ElggMenuItem object or an array of options in format:
- * name => STR Menu item identifier (required)
- * text => STR Menu item display text as HTML (required)
- * href => STR Menu item URL (required) (false for non-links.
- * @warning If you disable the href the <a> tag will
- * not appear, so the link_class will not apply. If you
- * put <a> tags in manually through the 'text' option
- * the default CSS selector .elgg-menu-$menu > li > a
- * may affect formatting. Wrap in a <span> if it does.)
- * contexts => ARR Page context strings
- * section => STR Menu section identifier
- * title => STR Menu item tooltip
- * selected => BOOL Is this menu item currently selected
- * parent_name => STR Identifier of the parent menu item
- * link_class => STR A class or classes for the <a> tag
- * item_class => STR A class or classes for the <li> tag
- *
- * Additional options that the view output/url takes can be
- * passed in the array. Custom options can be added by using
- * the 'data' key with the value being an associative array.
- *
- * @return bool False if the item could not be added
- * @since 1.8.0
- */
- function elgg_register_menu_item($menu_name, $menu_item) {
- global $CONFIG;
- if (is_array($menu_item)) {
- $options = $menu_item;
- $menu_item = \ElggMenuItem::factory($options);
- if (!$menu_item) {
- $menu_item_name = elgg_extract('name', $options, 'MISSING NAME');
- elgg_log("Unable to add menu item '{$menu_item_name}' to '$menu_name' menu", 'WARNING');
- return false;
- }
- }
- if (!$menu_item instanceof ElggMenuItem) {
- elgg_log('Second argument of elgg_register_menu_item() must be an instance of ElggMenuItem or an array of menu item factory options', 'ERROR');
- return false;
- }
- if (!isset($CONFIG->menus[$menu_name])) {
- $CONFIG->menus[$menu_name] = array();
- }
- $CONFIG->menus[$menu_name][] = $menu_item;
- return true;
- }
- /**
- * Remove an item from a menu
- *
- * @param string $menu_name The name of the menu
- * @param string $item_name The unique identifier for this menu item
- *
- * @return \ElggMenuItem|null
- * @since 1.8.0
- */
- function elgg_unregister_menu_item($menu_name, $item_name) {
- global $CONFIG;
- if (empty($CONFIG->menus[$menu_name])) {
- return null;
- }
- foreach ($CONFIG->menus[$menu_name] as $index => $menu_object) {
- /* @var \ElggMenuItem $menu_object */
- if ($menu_object instanceof ElggMenuItem && $menu_object->getName() == $item_name) {
- $item = $CONFIG->menus[$menu_name][$index];
- unset($CONFIG->menus[$menu_name][$index]);
- return $item;
- }
- }
- return null;
- }
- /**
- * Check if a menu item has been registered
- *
- * @param string $menu_name The name of the menu
- * @param string $item_name The unique identifier for this menu item
- *
- * @return bool
- * @since 1.8.0
- */
- function elgg_is_menu_item_registered($menu_name, $item_name) {
- global $CONFIG;
- if (!isset($CONFIG->menus[$menu_name])) {
- return false;
- }
- foreach ($CONFIG->menus[$menu_name] as $menu_object) {
- /* @var \ElggMenuItem $menu_object */
- if ($menu_object->getName() == $item_name) {
- return true;
- }
- }
- return false;
- }
- /**
- * Get a menu item registered for a menu
- *
- * @param string $menu_name The name of the menu
- * @param string $item_name The unique identifier for this menu item
- *
- * @return ElggMenuItem|null
- * @since 1.9.0
- */
- function elgg_get_menu_item($menu_name, $item_name) {
- global $CONFIG;
- if (!isset($CONFIG->menus[$menu_name])) {
- return null;
- }
- foreach ($CONFIG->menus[$menu_name] as $index => $menu_object) {
- /* @var \ElggMenuItem $menu_object */
- if ($menu_object->getName() == $item_name) {
- return $CONFIG->menus[$menu_name][$index];
- }
- }
- return null;
- }
- /**
- * Convenience function for registering a button to the title menu
- *
- * The URL must be $handler/$name/$guid where $guid is the guid of the page owner.
- * The label of the button is "$handler:$name" so that must be defined in a
- * language file.
- *
- * This is used primarily to support adding an add content button
- *
- * @param string $handler The handler to use or null to autodetect from context
- * @param string $name Name of the button
- * @return void
- * @since 1.8.0
- */
- function elgg_register_title_button($handler = null, $name = 'add') {
- if (elgg_is_logged_in()) {
- if (!$handler) {
- $handler = elgg_get_context();
- }
- $owner = elgg_get_page_owner_entity();
- if (!$owner) {
- // no owns the page so this is probably an all site list page
- $owner = elgg_get_logged_in_user_entity();
- }
- if ($owner && $owner->canWriteToContainer()) {
- $guid = $owner->getGUID();
- elgg_register_menu_item('title', array(
- 'name' => $name,
- 'href' => "$handler/$name/$guid",
- 'text' => elgg_echo("$handler:$name"),
- 'link_class' => 'elgg-button elgg-button-action',
- ));
- }
- }
- }
- /**
- * Adds a breadcrumb to the breadcrumbs stack.
- *
- * See elgg_get_breadcrumbs() and the navigation/breadcrumbs view.
- *
- * @param string $title The title to display. During rendering this is HTML encoded.
- * @param string $link Optional. The link for the title. During rendering links are
- * normalized via elgg_normalize_url().
- *
- * @return void
- * @since 1.8.0
- * @see elgg_get_breadcrumbs
- */
- function elgg_push_breadcrumb($title, $link = null) {
- global $CONFIG;
- if (!isset($CONFIG->breadcrumbs)) {
- $CONFIG->breadcrumbs = array();
- }
- $CONFIG->breadcrumbs[] = array('title' => $title, 'link' => $link);
- }
- /**
- * Removes last breadcrumb entry.
- *
- * @return array popped breadcrumb array or empty array
- * @since 1.8.0
- */
- function elgg_pop_breadcrumb() {
- global $CONFIG;
- if (empty($CONFIG->breadcrumbs) || !is_array($CONFIG->breadcrumbs)) {
- return array();
- }
- return array_pop($CONFIG->breadcrumbs);
- }
- /**
- * Returns all breadcrumbs as an array of array('title' => 'Title', 'link' => 'URL')
- *
- * Since 1.11, breadcrumbs are filtered through the plugin hook [prepare, breadcrumbs] before
- * being returned.
- *
- * @return array Breadcrumbs
- * @since 1.8.0
- * @see elgg_prepare_breadcrumbs
- */
- function elgg_get_breadcrumbs() {
- global $CONFIG;
- // if no crumbs set, still allow hook to populate it
- if (isset($CONFIG->breadcrumbs) && is_array($CONFIG->breadcrumbs)) {
- $breadcrumbs = $CONFIG->breadcrumbs;
- } else {
- $breadcrumbs = array();
- }
- $params = array(
- 'breadcrumbs' => $breadcrumbs,
- );
- $breadcrumbs = elgg_trigger_plugin_hook('prepare', 'breadcrumbs', $params, $breadcrumbs);
- if (!is_array($breadcrumbs)) {
- return array();
- }
- return $breadcrumbs;
- }
- /**
- * Hook handler to turn titles into 100-character excerpts. To remove this behavior, unregister this
- * function from the [prepare, breadcrumbs] hook.
- *
- * @param string $hook "prepare"
- * @param string $type "breadcrumbs"
- * @param array $breadcrumbs Breadcrumbs to be altered
- * @param array $params Hook parameters
- *
- * @return array
- * @since 1.11
- */
- function elgg_prepare_breadcrumbs($hook, $type, $breadcrumbs, $params) {
- foreach (array_keys($breadcrumbs) as $i) {
- $breadcrumbs[$i]['title'] = elgg_get_excerpt($breadcrumbs[$i]['title'], 100);
- }
- return $breadcrumbs;
- }
- /**
- * Set up the site menu
- *
- * Handles default, featured, and custom menu items
- *
- * @access private
- */
- function _elgg_site_menu_setup($hook, $type, $return, $params) {
- $featured_menu_names = elgg_get_config('site_featured_menu_names');
- $custom_menu_items = elgg_get_config('site_custom_menu_items');
- if ($featured_menu_names || $custom_menu_items) {
- // we have featured or custom menu items
- $registered = $return['default'];
- /* @var \ElggMenuItem[] $registered */
- // set up featured menu items
- $featured = array();
- foreach ($featured_menu_names as $name) {
- foreach ($registered as $index => $item) {
- if ($item->getName() == $name) {
- $featured[] = $item;
- unset($registered[$index]);
- }
- }
- }
- // add custom menu items
- $n = 1;
- foreach ($custom_menu_items as $title => $url) {
- $item = new \ElggMenuItem("custom$n", $title, $url);
- $featured[] = $item;
- $n++;
- }
- $return['default'] = $featured;
- if (count($registered) > 0) {
- $return['more'] = $registered;
- }
- } else {
- // no featured menu items set
- $max_display_items = 5;
- // the first n are shown, rest added to more list
- // if only one item on more menu, stick it with the rest
- $num_menu_items = count($return['default']);
- if ($num_menu_items > ($max_display_items + 1)) {
- $return['more'] = array_splice($return['default'], $max_display_items);
- }
- }
-
- // check if we have anything selected
- $selected = false;
- foreach ($return as $section) {
- /* @var \ElggMenuItem[] $section */
- foreach ($section as $item) {
- if ($item->getSelected()) {
- $selected = true;
- break 2;
- }
- }
- }
-
- if (!$selected) {
- // nothing selected, match name to context or match url
- $current_url = current_page_url();
- foreach ($return as $section_name => $section) {
- foreach ($section as $key => $item) {
- // only highlight internal links
- if (strpos($item->getHref(), elgg_get_site_url()) === 0) {
- if ($item->getName() == elgg_get_context()) {
- $return[$section_name][$key]->setSelected(true);
- break 2;
- }
- if ($item->getHref() == $current_url) {
- $return[$section_name][$key]->setSelected(true);
- break 2;
- }
- }
- }
- }
- }
- return $return;
- }
- /**
- * Add the comment and like links to river actions menu
- * @access private
- */
- function _elgg_river_menu_setup($hook, $type, $return, $params) {
- if (elgg_is_logged_in()) {
- $item = $params['item'];
- /* @var \ElggRiverItem $item */
- $object = $item->getObjectEntity();
- // add comment link but annotations cannot be commented on
- if ($item->annotation_id == 0) {
- if ($object->canComment()) {
- $options = array(
- 'name' => 'comment',
- 'href' => "#comments-add-$object->guid",
- 'text' => elgg_view_icon('speech-bubble'),
- 'title' => elgg_echo('comment:this'),
- 'rel' => 'toggle',
- 'priority' => 50,
- );
- $return[] = \ElggMenuItem::factory($options);
- }
- }
-
- if (elgg_is_admin_logged_in()) {
- $options = array(
- 'name' => 'delete',
- 'href' => elgg_add_action_tokens_to_url("action/river/delete?id=$item->id"),
- 'text' => elgg_view_icon('delete'),
- 'title' => elgg_echo('river:delete'),
- 'confirm' => elgg_echo('deleteconfirm'),
- 'priority' => 200,
- );
- $return[] = \ElggMenuItem::factory($options);
- }
- }
- return $return;
- }
- /**
- * Entity menu is list of links and info on any entity
- * @access private
- */
- function _elgg_entity_menu_setup($hook, $type, $return, $params) {
- if (elgg_in_context('widgets')) {
- return $return;
- }
-
- $entity = $params['entity'];
- /* @var \ElggEntity $entity */
- $handler = elgg_extract('handler', $params, false);
- // access
- if (elgg_is_logged_in()) {
- $access = elgg_view('output/access', array('entity' => $entity));
- $options = array(
- 'name' => 'access',
- 'text' => $access,
- 'href' => false,
- 'priority' => 100,
- );
- $return[] = \ElggMenuItem::factory($options);
- }
-
- if ($entity->canEdit() && $handler) {
- // edit link
- $options = array(
- 'name' => 'edit',
- 'text' => elgg_echo('edit'),
- 'title' => elgg_echo('edit:this'),
- 'href' => "$handler/edit/{$entity->getGUID()}",
- 'priority' => 200,
- );
- $return[] = \ElggMenuItem::factory($options);
- // delete link
- $options = array(
- 'name' => 'delete',
- 'text' => elgg_view_icon('delete'),
- 'title' => elgg_echo('delete:this'),
- 'href' => "action/$handler/delete?guid={$entity->getGUID()}",
- 'confirm' => elgg_echo('deleteconfirm'),
- 'priority' => 300,
- );
- $return[] = \ElggMenuItem::factory($options);
- }
- return $return;
- }
- /**
- * Widget menu is a set of widget controls
- * @access private
- */
- function _elgg_widget_menu_setup($hook, $type, $return, $params) {
- $widget = $params['entity'];
- /* @var \ElggWidget $widget */
- $show_edit = elgg_extract('show_edit', $params, true);
- $collapse = array(
- 'name' => 'collapse',
- 'text' => ' ',
- 'href' => "#elgg-widget-content-$widget->guid",
- 'link_class' => 'elgg-widget-collapse-button',
- 'rel' => 'toggle',
- 'priority' => 1,
- );
- $return[] = \ElggMenuItem::factory($collapse);
- if ($widget->canEdit()) {
- $delete = array(
- 'name' => 'delete',
- 'text' => elgg_view_icon('delete-alt'),
- 'title' => elgg_echo('widget:delete', array($widget->getTitle())),
- 'href' => "action/widgets/delete?widget_guid=$widget->guid",
- 'is_action' => true,
- 'link_class' => 'elgg-widget-delete-button',
- 'id' => "elgg-widget-delete-button-$widget->guid",
- 'data-elgg-widget-type' => $widget->handler,
- 'priority' => 900,
- );
- $return[] = \ElggMenuItem::factory($delete);
- if ($show_edit) {
- $edit = array(
- 'name' => 'settings',
- 'text' => elgg_view_icon('settings-alt'),
- 'title' => elgg_echo('widget:edit'),
- 'href' => "#widget-edit-$widget->guid",
- 'link_class' => "elgg-widget-edit-button",
- 'rel' => 'toggle',
- 'priority' => 800,
- );
- $return[] = \ElggMenuItem::factory($edit);
- }
- }
- return $return;
- }
- /**
- * Add the register and forgot password links to login menu
- * @access private
- */
- function _elgg_login_menu_setup($hook, $type, $return, $params) {
- if (elgg_get_config('allow_registration')) {
- $return[] = \ElggMenuItem::factory(array(
- 'name' => 'register',
- 'href' => 'register',
- 'text' => elgg_echo('register'),
- 'link_class' => 'registration_link',
- ));
- }
- $return[] = \ElggMenuItem::factory(array(
- 'name' => 'forgotpassword',
- 'href' => 'forgotpassword',
- 'text' => elgg_echo('user:password:lost'),
- 'link_class' => 'forgot_link',
- ));
- return $return;
- }
- /**
- * Navigation initialization
- * @access private
- */
- function _elgg_nav_init() {
- elgg_register_plugin_hook_handler('prepare', 'breadcrumbs', 'elgg_prepare_breadcrumbs');
- elgg_register_plugin_hook_handler('prepare', 'menu:site', '_elgg_site_menu_setup');
- elgg_register_plugin_hook_handler('register', 'menu:river', '_elgg_river_menu_setup');
- elgg_register_plugin_hook_handler('register', 'menu:entity', '_elgg_entity_menu_setup');
- elgg_register_plugin_hook_handler('register', 'menu:widget', '_elgg_widget_menu_setup');
- elgg_register_plugin_hook_handler('register', 'menu:login', '_elgg_login_menu_setup');
- elgg_register_plugin_hook_handler('public_pages', 'walled_garden', '_elgg_nav_public_pages');
- elgg_register_menu_item('footer', \ElggMenuItem::factory(array(
- 'name' => 'powered',
- 'text' => elgg_echo("elgg:powered"),
- 'href' => 'http://elgg.org',
- 'title' => 'Elgg ' . elgg_get_version(true),
- 'section' => 'meta',
- )));
- elgg_register_ajax_view('navigation/menu/user_hover/contents');
- }
- /**
- * Extend public pages
- *
- * @param string $hook_name "public_pages"
- * @param string $entity_type "walled_garden"
- * @param string[] $return_value Paths accessible outside the "walled garden"
- * @param mixed $params unused
- *
- * @return string[]
- * @access private
- * @since 1.11.0
- */
- function _elgg_nav_public_pages($hook_name, $entity_type, $return_value, $params) {
- if (is_array($return_value)) {
- $return_value[] = 'navigation/menu/user_hover/contents';
- }
- return $return_value;
- }
- return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) {
- $events->registerHandler('init', 'system', '_elgg_nav_init');
- };
|