diff --git includes/menu.inc includes/menu.inc
index 86746f2..8253270 100644
--- includes/menu.inc
+++ includes/menu.inc
@@ -2257,6 +2257,75 @@ function _menu_navigation_links_rebuild($menu) {
}
/**
+ * Clone an array of menu links.
+ *
+ * @param $links
+ * An array of menu links to clone.
+ * @param $menu_name
+ * (optional) The name of a menu that the links will be cloned for. If not
+ * set, the cloned links will be in the same menu as the original set of
+ * links that were passed in.
+ * @return
+ * An array of menu links with the same properties as the passed-in array,
+ * but with the link identifiers removed so that a new link will be created
+ * when any of them is passed in to menu_link_save().
+ *
+ * @see menu_link_save()
+ */
+function menu_links_clone($links, $menu_name = NULL) {
+ foreach ($links as &$link) {
+ unset($link['mlid']);
+ unset($link['plid']);
+ if (isset($menu_name)) {
+ $link['menu_name'] = $menu_name;
+ }
+ }
+ return $links;
+}
+
+/**
+ * Returns an array containing all links for a menu.
+ *
+ * @param $menu_name
+ * The name of the menu whose links should be returned.
+ * @return
+ * An array of menu links.
+ */
+function menu_load_links($menu_name) {
+ $links = db_select('menu_links', 'ml', array('fetch' => PDO::FETCH_ASSOC))
+ ->fields('ml')
+ ->condition('ml.menu_name', $menu_name)
+ // Order by weight so as to be helpful for menus that are only one level
+ // deep.
+ ->orderBy('weight')
+ ->execute()
+ ->fetchAll();
+
+ foreach ($links as &$link) {
+ $link['options'] = unserialize($link['options']);
+ }
+ return $links;
+}
+
+/**
+ * Deletes all links for a menu.
+ *
+ * @param $menu_name
+ * The name of the menu whose links will be deleted.
+ */
+function menu_delete_links($menu_name) {
+ $links = menu_load_links($menu_name);
+ foreach ($links as $link) {
+ // To speed up the deletion process, we reset some link properties that
+ // would trigger re-parenting logic in _menu_delete_item() and
+ // _menu_update_parental_status().
+ $link['has_children'] = FALSE;
+ $link['plid'] = 0;
+ _menu_delete_item($link);
+ }
+}
+
+/**
* Delete one or several menu links.
*
* @param $mlid
diff --git modules/menu/menu.module modules/menu/menu.module
index 5d0fd21..f91a4b7 100644
--- modules/menu/menu.module
+++ modules/menu/menu.module
@@ -271,21 +271,13 @@ function menu_save($menu) {
*
* @see menu_load()
*
- * _menu_delete_item() will take care of clearing the page cache. Other modules
+ * menu_delete_links() will take care of clearing the page cache. Other modules
* should take care of their menu-related data by implementing
* hook_menu_delete().
*/
function menu_delete($menu) {
// Delete all links from the menu.
- $links = db_query("SELECT * FROM {menu_links} WHERE menu_name = :menu_name", array(':menu_name' => $menu['menu_name']));
- foreach ($links as $link) {
- // To speed up the deletion process, we reset some link properties that
- // would trigger re-parenting logic in _menu_delete_item() and
- // _menu_update_parental_status().
- $link['has_children'] = FALSE;
- $link['plid'] = 0;
- _menu_delete_item($link);
- }
+ menu_delete_links($menu['menu_name']);
// Delete the custom menu.
db_delete('menu_custom')
diff --git modules/shortcut/shortcut.admin.css modules/shortcut/shortcut.admin.css
new file mode 100644
index 0000000..f2ff5be
--- /dev/null
+++ modules/shortcut/shortcut.admin.css
@@ -0,0 +1,14 @@
+/* $Id$ */
+
+h4.shortcuts-set,
+div.shortcuts-change-set {
+ display: inline;
+}
+
+.shortcut-slot-hidden {
+ display: none;
+}
+
+div.form-item-set div.form-item-new {
+ display: inline;
+}
diff --git modules/shortcut/shortcut.admin.inc modules/shortcut/shortcut.admin.inc
new file mode 100644
index 0000000..d6e0ebf
--- /dev/null
+++ modules/shortcut/shortcut.admin.inc
@@ -0,0 +1,542 @@
+ $set) {
+ $options[$name] = check_plain($set->title);
+ }
+
+ // Only administrators can add shortcut sets.
+ $add_access = user_access('administer shortcuts');
+ if ($add_access) {
+ $options['new'] = t('New set');
+ }
+
+ $form['account'] = array(
+ '#type' => 'value',
+ '#value' => $account,
+ );
+
+ $form['set'] = array(
+ '#type' => 'radios',
+ '#title' => t('Choose a set of shortcuts to show in your toolbar'),
+ '#options' => $options,
+ '#default_value' => $current_set->set_name,
+ );
+
+ $form['new'] = array(
+ '#type' => 'textfield',
+ '#description' => t('The new set is created by copying items from the @default set.', array('@default' => $default_set->title)),
+ '#access' => $add_access,
+ );
+
+ $form['#attached'] = array(
+ 'css' => array(drupal_get_path('module', 'shortcut') . '/shortcut.admin.css'),
+ 'js' => array(drupal_get_path('module', 'shortcut') . '/shortcut.admin.js'),
+ );
+
+ $form['submit'] = array(
+ '#type' => 'submit',
+ '#value' => t('Save configuration'),
+ );
+
+ return $form;
+}
+
+function shortcut_set_switch_confirm($form, &$form_state, $shortcut_set) {
+ global $user;
+ $form = array();
+ $form['set'] = array (
+ '#type' => 'value',
+ '#value' => $shortcut_set->set_name,
+ );
+ $form['account'] = array (
+ '#type' => 'value',
+ '#value' => $user,
+ );
+
+ $form['#submit'] = array('shortcut_set_switch_submit');
+ $title = $shortcut_set->title;
+
+ return confirm_form(
+ $form,
+ t("Would you like to switch to %title", array('%title' => $title)),
+ 'admin/config/system/shortcut',
+ "",
+ t("Switch to @title", array('@title' => $title)),
+ t("Keep using current shortcuts")
+ );
+}
+/**
+ * Submit handler for the form that switches shortcut sets.
+ */
+function shortcut_set_switch_submit($form, &$form_state) {
+ global $user;
+ $account = $form_state['values']['account'];
+
+ if ($form_state['values']['set'] == 'new') {
+ // Save a new shortcut set with links copied from the default set.
+ $default_set = shortcut_default_set();
+ $set = (object) array(
+ 'title' => $form_state['values']['new'],
+ 'links' => menu_links_clone($default_set->links),
+ );
+ shortcut_set_save($set);
+ $replacements = array(
+ '%user' => $account->name,
+ '%set_name' => $set->title,
+ );
+ drupal_set_message($account->uid == $user->uid ? t('A new shortcut set called %set_name was created with the default shortcut items.', $replacements) : t('%user is now using a new shortcut set called %set_name with the default shortcut items.', $replacements));
+ $form_state['redirect'] = 'admin/config/system/shortcut/switch/confirm/' . $set->set_name;
+ return;
+ }
+ else {
+ // Switch to a different shortcut set.
+ $set = shortcut_set_load($form_state['values']['set']);
+ $replacements = array(
+ '%user' => $account->name,
+ '%set_name' => $set->title,
+ );
+ drupal_set_message($account->uid == $user->uid ? t('You are now using the %set_name shortcut set.', $replacements) : t('%user is now using the %set_name shortcut set.', $replacements));
+ }
+
+ // Assign the shortcut set to the provided user account.
+ shortcut_set_assign_user($set, $account);
+ if (user_access('administer shortcuts')) {
+ $form_state['redirect'] = 'admin/config/system/shortcut';
+ }
+}
+
+/**
+ * Theme function for the form that switches shortcut sets.
+ *
+ * @param $variables
+ * An associative array containing:
+ * - form: An array representing the form.
+ * @return
+ * A themed HTML string representing the content of the form.
+ *
+ * @ingroup themeable
+ * @see shortcut_set_switch()
+ */
+function theme_shortcut_set_switch($variables) {
+ $form = $variables['form'];
+ // Render the textfield for adding a new set inline with the radio button.
+ $form['set']['new']['#title'] = t('New set: !textfield', array('!textfield' => drupal_render($form['new'])));
+ return drupal_render_children($form);
+}
+
+/**
+ * Menu callback; Build the form for customizing shortcut sets.
+ *
+ * @param $form
+ * An associative array containing the structure of the form.
+ * @param $form_state
+ * An associative array containing the current state of the form.
+ * @param $shortcut_set
+ * An object representing the shortcut set which is being edited.
+ * @return
+ * An array representing the form definition.
+ *
+ * @ingroup forms
+ * @see shortcut_set_customize_submit()
+ */
+function shortcut_set_customize($form, &$form_state, $shortcut_set) {
+ $form['set'] = array(
+ '#markup' => t('Using set "@set"', array('@set' => $shortcut_set->title)),
+ '#prefix' => '
',
+ '#suffix' => '
',
+ '#weight' => -100,
+ );
+
+ $form['change_set'] = array(
+ '#markup' => l(t('Change set'), 'admin/config/system/shortcut'),
+ '#prefix' => ' (',
+ '#suffix' => ')
',
+ '#weight' => -99,
+ '#access' => shortcut_set_switch_access(),
+ );
+
+ $form['shortcuts']['#tree'] = TRUE;
+ $form['shortcuts']['enabled'] = $form['shortcuts']['disabled'] = array();
+ foreach ($shortcut_set->links as $link) {
+ $mlid = $link['mlid'];
+ $status = $link['hidden'] ? 'disabled' : 'enabled';
+ $form['shortcuts'][$status][$mlid]['name']['#markup'] = l($link['link_title'], $link['link_path']);
+ $form['shortcuts'][$status][$mlid]['weight'] = array(
+ '#type' => 'weight',
+ '#title' => t('Weight'),
+ '#delta' => 50,
+ '#default_value' => $link['weight'],
+ '#attributes' => array('class' => array('shortcut-weight')),
+ );
+ $form['shortcuts'][$status][$mlid]['status'] = array(
+ '#type' => 'select',
+ '#title' => t('Status'),
+ '#options' => array('disabled' => t('Disabled'), 'enabled' => t('Enabled')),
+ '#default_value' => $status,
+ '#attributes' => array('class' => array('shortcut-status-select')),
+ );
+
+ $form['shortcuts'][$status][$mlid]['edit']['#markup'] = l(t('edit'), 'admin/config/system/shortcut/link/' . $mlid);
+ $form['shortcuts'][$status][$mlid]['delete']['#markup'] = l(t('delete'), 'admin/config/system/shortcut/link/' . $mlid . '/delete');
+ }
+
+ $form['#attached'] = array(
+ 'css' => array(drupal_get_path('module', 'shortcut') . '/shortcut.admin.css'),
+ 'js' => array(drupal_get_path('module', 'shortcut') . '/shortcut.admin.js'),
+ );
+
+ $form['submit'] = array(
+ '#type' => 'submit',
+ '#value' => t('Save Changes'),
+ );
+
+ return $form;
+}
+
+/**
+ * Submit handler for the shortcut set customization form.
+ */
+function shortcut_set_customize_submit($form, &$form_state) {
+ foreach ($form_state['values']['shortcuts'] as $group => $links) {
+ foreach ($links as $mlid => $data) {
+ $link = menu_link_load($mlid);
+ $link['hidden'] = $data['status'] == 'enabled' ? 0 : 1;
+ $link['weight'] = $data['weight'];
+ menu_link_save($link);
+ }
+ }
+ drupal_set_message(t('The shortcut set has been updated.'));
+}
+
+/**
+ * Theme function for the shortcut set customization form.
+ *
+ * @param $variables
+ * An associative array containing:
+ * - form: An array representing the form.
+ * @return
+ * A themed HTML string representing the content of the form.
+ *
+ * @ingroup themeable
+ * @see shortcut_set_customize()
+ */
+function theme_shortcut_set_customize($variables) {
+ $form = $variables['form'];
+ $map = array('disabled' => t('Disabled'), 'enabled' => t('Enabled'));
+
+ $rows = array();
+ foreach (array('enabled', 'disabled') as $status) {
+ drupal_add_tabledrag('shortcuts', 'match', 'sibling', 'shortcut-status-select');
+ drupal_add_tabledrag('shortcuts', 'order', 'sibling', 'shortcut-weight');
+ $rows[] = array(
+ 'data' => array(array(
+ 'colspan' => 5,
+ 'data' => '' . $map[$status] . '',
+ )),
+ 'class' => array('shortcut-status', 'shortcut-status-' . $status),
+ );
+ foreach (element_children($form['shortcuts'][$status]) as $key) {
+ $shortcut = &$form['shortcuts'][$status][$key];
+ $row = array();
+ $row[] = drupal_render($shortcut['name']);
+ $row[] = drupal_render($shortcut['weight']);
+ $row[] = drupal_render($shortcut['status']);
+ $row[] = drupal_render($shortcut['edit']);
+ $row[] = drupal_render($shortcut['delete']);
+ $rows[] = array(
+ 'data' => $row,
+ 'class' => array('draggable'),
+ );
+ }
+ if ($status == 'enabled') {
+ for ($i = 0; $i < shortcut_max_slots(); $i++) {
+ $rows['empty-' . $i] = array(
+ 'data' => array(array(
+ 'colspan' => 5,
+ 'data' => '' . t('Empty') . '',
+ )),
+ 'class' => array('shortcut-slot-empty'),
+ );
+ }
+ $count_shortcuts = count(element_children($form['shortcuts'][$status]));
+ if (!empty($count_shortcuts)) {
+ for ($i = 0; $i < min($count_shortcuts, shortcut_max_slots()); $i++) {
+ $rows['empty-' . $i]['class'][] = 'shortcut-slot-hidden';
+ }
+ }
+ }
+ }
+ $header = array(t('Name'), t('Weight'), t('Status'), array('data' => t('Operations'), 'colspan' => 2));
+ $output = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'shortcuts')));
+ $output .= drupal_render($form['submit']);
+ $output = drupal_render_children($form) . $output;
+ return $output;
+}
+
+/**
+ * Menu callback; Build the form for adding a new shortcut link.
+ *
+ * @param $form
+ * An associative array containing the structure of the form.
+ * @param $form_state
+ * An associative array containing the current state of the form.
+ * @param $shortcut_set
+ * An object representing the shortcut set to which the link will be added.
+ * @return
+ * An array representing the form definition.
+ *
+ * @ingroup forms
+ * @see shortcut_link_add_submit()
+ */
+function shortcut_link_add($form, &$form_state, $shortcut_set) {
+ drupal_set_title(t('Add new shortcut'));
+ $form['shortcut_set'] = array(
+ '#type' => 'value',
+ '#value' => $shortcut_set,
+ );
+ $form += _shortcut_link_form_elements();
+ return $form;
+}
+
+/**
+ * Menu callback; Build the form for editing a shortcut link.
+ *
+ * @param $form
+ * An associative array containing the structure of the form.
+ * @param $form_state
+ * An associative array containing the current state of the form.
+ * @param $shortcut_link
+ * An array representing the link that is being edited.
+ * @return
+ * An array representing the form definition.
+ *
+ * @ingroup forms
+ * @see shortcut_link_edit_submit()
+ */
+function shortcut_link_edit($form, &$form_state, $shortcut_link) {
+ drupal_set_title(t('Editing @shortcut', array('@shortcut' => $shortcut_link['link_title'])));
+ $form['original_shortcut_link'] = array(
+ '#type' => 'value',
+ '#value' => $shortcut_link,
+ );
+ $form += _shortcut_link_form_elements($shortcut_link);
+ return $form;
+}
+
+/**
+ * Helper function for building a form for adding or editing shortcut links.
+ *
+ * @param $shortcut_link
+ * (optional) An array representing the shortcut link that will be edited. If
+ * not provided, a new link will be created.
+ * @return
+ * An array of form elements.
+ */
+function _shortcut_link_form_elements($shortcut_link = NULL) {
+ if (!isset($shortcut_link)) {
+ $shortcut_link = array(
+ 'link_title' => '',
+ 'link_path' => ''
+ );
+ }
+
+ $form['shortcut_link']['#tree'] = TRUE;
+ $form['shortcut_link']['link_title'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Name'),
+ '#description' => t('The name of the shortcut.'),
+ '#size' => 40,
+ '#maxlength' => 255,
+ '#default_value' => $shortcut_link['link_title'],
+ );
+
+ $form['shortcut_link']['link_path'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Path'),
+ '#description' => t('The path to the shortcut.'),
+ '#size' => 40,
+ '#maxlength' => 255,
+ '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q='),
+ '#default_value' => $shortcut_link['link_path'],
+ );
+
+ $form['submit'] = array(
+ '#type' => 'submit',
+ '#value' => t('Save'),
+ );
+
+ return $form;
+}
+
+/**
+ * Submit handler for the shortcut link editing form.
+ */
+function shortcut_link_edit_submit($form, &$form_state) {
+ $shortcut_link = array_merge($form_state['values']['original_shortcut_link'], $form_state['values']['shortcut_link']);
+ menu_link_save($shortcut_link);
+ $form_state['redirect'] = 'admin/config/system/shortcut/' . $shortcut_link['menu_name'];
+ drupal_set_message(t('The shortcut %link has been updated.', array('%link' => $shortcut_link['link_title'])));
+}
+
+/**
+ * Submit handler for the form that adds shortcut links.
+ */
+function shortcut_link_add_submit($form, &$form_state) {
+ // Add the shortcut link to the set.
+ $shortcut_set = $form_state['values']['shortcut_set'];
+ $shortcut_link = $form_state['values']['shortcut_link'];
+ $shortcut_link['menu_name'] = $shortcut_set->set_name;
+ shortcut_admin_add_link($shortcut_link, $shortcut_set, shortcut_max_slots());
+ shortcut_set_save($shortcut_set);
+ $form_state['redirect'] = 'admin/config/system/shortcut/' . $shortcut_link['menu_name'];
+ drupal_set_message(t('Added a shortcut for %title.', array('%title' => $shortcut_link['link_title'])));
+}
+
+/**
+ * Add a link to the end of a shortcut set, keeping within a prescribed limit.
+ *
+ * @param $link
+ * An array representing a shortcut link.
+ * @param $shortcut_set
+ * An object representing the shortcut set which the link will be added to.
+ * The links in the shortcut set will be re-weighted so that the new link is
+ * at the end, and some existing links may be disabled (if the $limit
+ * parameter is provided).
+ * @param $limit
+ * (optional) The maximum number of links that are allowed to be enabled for
+ * this shortcut set. If provided, existing links at the end of the list that
+ * exceed the limit will be automatically disabled. If not provided, no limit
+ * will be enforced.
+ */
+function shortcut_admin_add_link($shortcut_link, &$shortcut_set, $limit = NULL) {
+ if (isset($limit)) {
+ // Disable any existing links at the end of the list that would cause the
+ // limit to be exceeded. Take into account whether or not the new link will
+ // be enabled and count towards the total.
+ $number_enabled = !empty($shortcut_link['hidden']) ? 0 : 1;
+ foreach ($shortcut_set->links as &$link) {
+ if (!$link['hidden']) {
+ $number_enabled++;
+ if ($number_enabled > $limit) {
+ $link['hidden'] = 1;
+ }
+ }
+ }
+ }
+
+ // Add the link to the end of the list.
+ $shortcut_set->links[] = $shortcut_link;
+ shortcut_set_reset_link_weights($shortcut_set);
+}
+
+/**
+ * Menu callback; Build the form for deleting a shortcut link.
+ *
+ * @param $form
+ * An associative array containing the structure of the form.
+ * @param $form_state
+ * An associative array containing the current state of the form.
+ * @param $shortcut_link
+ * An array representing the link that will be deleted.
+ * @return
+ * An array representing the form definition.
+ *
+ * @ingroup forms
+ * @see shortcut_link_delete_submit()
+ */
+function shortcut_link_delete($form, &$form_state, $shortcut_link) {
+ $form['shortcut_link'] = array(
+ '#type' => 'value',
+ '#value' => $shortcut_link,
+ );
+
+ return confirm_form(
+ $form,
+ t('Are you sure you want to delete the shortcut %title?', array('%title' => $shortcut_link['link_title'])),
+ 'admin/config/system/shortcut/' . $shortcut_link['menu_name'],
+ t('This action cannot be undone.'),
+ t('Delete'),
+ t('Cancel')
+ );
+}
+
+/**
+ * Submit handler for the shortcut link deletion form.
+ */
+function shortcut_link_delete_submit($form, &$form_state) {
+ $shortcut_link = $form_state['values']['shortcut_link'];
+ menu_link_delete($shortcut_link['mlid']);
+ $form_state['redirect'] = 'admin/config/system/shortcut/' . $shortcut_link['menu_name'];
+ drupal_set_message(t('The shortcut %title has been deleted.', array('%title' => $shortcut_link['link_title'])));
+}
+
+/**
+ * Menu callback; Creates a new link in the provided shortcut set
+ *
+ * After completion, redirects the user back to where they came from.
+ *
+ * @param $shortcut_set
+ * Returned from shortcut_set_load().
+ */
+function shortcut_link_add_inline($shortcut_set) {
+ if (isset($_REQUEST['token']) && drupal_valid_token($_REQUEST['token'], 'shortcut-add-link')) {
+ $link = array(
+ 'link_title' => $_GET['name'],
+ 'link_path' => $_GET['link'],
+ );
+ shortcut_admin_add_link($link, $shortcut_set, shortcut_max_slots());
+ if (shortcut_set_save($shortcut_set)) {
+ drupal_set_message(t('Added a shortcut for %title.', array('%title' => $link['link_title'])));
+ drupal_goto();
+ }
+ else {
+ drupal_set_message(t('Unable to add a shortcut for %title.', array('%title' => $link['link_title'])));
+ }
+ }
+ return drupal_access_denied();
+}
diff --git modules/shortcut/shortcut.admin.js modules/shortcut/shortcut.admin.js
new file mode 100644
index 0000000..e1c1675
--- /dev/null
+++ modules/shortcut/shortcut.admin.js
@@ -0,0 +1,100 @@
+// $Id$
+(function ($) {
+
+/**
+ * Handle the concept of a fixed number of slots.
+ *
+ * This behavior is dependent on the tableDrag behavior, since it uses the
+ * objects initialized in that behavior to update the row.
+ */
+Drupal.behaviors.shortcutDrag = {
+ attach: function (context, settings) {
+ if (Drupal.tableDrag) {
+ var table = $('table#shortcuts'),
+ visibleLength = 0,
+ slots = 0,
+ tableDrag = Drupal.tableDrag.shortcuts;
+ $('> tbody > tr, > tr', table)
+ .filter(':visible')
+ .filter(':odd').filter('.odd')
+ .removeClass('odd').addClass('even')
+ .end().end()
+ .filter(':even').filter('.even')
+ .removeClass('even').addClass('odd')
+ .end().end()
+ .end()
+ .filter('.shortcut-slot-empty').each(function(index) {
+ if ($(this).is(':visible')) {
+ visibleLength++;
+ }
+ slots++;
+ });
+
+ // Add a handler for when a row is swapped.
+ tableDrag.row.prototype.onSwap = function (swappedRow) {
+ var disabledIndex = $(table).find('tr').index($(table).find('tr.shortcut-status-disabled')) - slots - 2,
+ count = 0;
+ $(table).find('tr.shortcut-status-enabled').nextAll().filter(':not(.shortcut-slot-empty)').each(function(index) {
+ if (index < disabledIndex) {
+ count++;
+ }
+ });
+ var total = slots - count;
+ if (total == -1) {
+ var disabled = $(table).find('tr.shortcut-status-disabled');
+ disabled.after(disabled.prevAll().filter(':not(.shortcut-slot-empty)').get(0));
+ }
+ else if (total != visibleLength) {
+ if (total > visibleLength) {
+ // Less slots on screen than needed.
+ $('.shortcut-slot-empty:hidden:last').show();
+ visibleLength++;
+ }
+ else {
+ // More slots on screen than needed.
+ $('.shortcut-slot-empty:visible:last').hide();
+ visibleLength--;
+ }
+ }
+ };
+
+ // Add a handler so when a row is dropped, update fields dropped into new regions.
+ tableDrag.onDrop = function () {
+ // Use "status-message" row instead of "status" row because
+ // "status-{status_name}-message" is less prone to regexp match errors.
+ var statusRow = $(this.rowObject.element).prevAll('tr.shortcut-status').get(0);
+ var statusName = statusRow.className.replace(/([^ ]+[ ]+)*shortcut-status-([^ ]+)([ ]+[^ ]+)*/, '$2');
+ var statusField = $('select.shortcut-status-select', this.rowObject.element);
+ statusField.val(statusName);
+ return true;
+ };
+
+ tableDrag.restripeTable = function () {
+ // :even and :odd are reversed because jQuery counts from 0 and
+ // we count from 1, so we're out of sync.
+ // Match immediate children of the parent element to allow nesting.
+ $('> tbody > tr:visible, > tr:visible', this.table)
+ .filter(':odd').filter('.odd')
+ .removeClass('odd').addClass('even')
+ .end().end()
+ .filter(':even').filter('.even')
+ .removeClass('even').addClass('odd');
+ };
+ }
+ }
+};
+
+/**
+ * Make it so when you enter text into the "New set" textfield, the
+ * corresponding radio button gets selected.
+ */
+Drupal.behaviors.newSet = {
+ attach: function (context, settings) {
+ var selectDefault = function() {
+ $($(this).parents('div.form-item').get(1)).find('> label > input').attr('checked', 'checked');
+ };
+ $('div.form-item-new input').focus(selectDefault).keyup(selectDefault);
+ }
+};
+
+})(jQuery);
diff --git modules/shortcut/shortcut.api.php modules/shortcut/shortcut.api.php
new file mode 100644
index 0000000..355ccb7
--- /dev/null
+++ modules/shortcut/shortcut.api.php
@@ -0,0 +1,40 @@
+roles)) {
+ return variable_get('mymodule_admin_shortcut_default_set_name');
+ }
+}
+
+/**
+ * @} End of "addtogroup hooks".
+ */
diff --git modules/shortcut/shortcut.css modules/shortcut/shortcut.css
new file mode 100644
index 0000000..6a2797e
--- /dev/null
+++ modules/shortcut/shortcut.css
@@ -0,0 +1,75 @@
+/* $Id$ */
+div#toolbar a#toolbar-customize {
+ float: right;
+}
+
+div#toolbar div.toolbar-shortcuts ul {
+ padding: 5px 0;
+ height: 40px;
+ line-height: 30px;
+ overflow: hidden;
+ float: left;
+ margin-left:5px;
+}
+
+div#toolbar div.toolbar-shortcuts ul li a {
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ padding: 5px 10px 5px 5px;
+ margin-right: 5px;
+}
+
+div#toolbar div.toolbar-shortcuts ul li a:focus,
+div#toolbar div.toolbar-shortcuts ul li a:hover,
+div#toolbar div.toolbar-shortcuts ul li a.active:focus {
+ background: #555;
+}
+
+div#toolbar div.toolbar-shortcuts ul li a.active:hover,
+div#toolbar div.toolbar-shortcuts ul li a.active {
+ background: url(../toolbar/toolbar.png) 0 -20px repeat-x;
+}
+
+div#toolbar div.toolbar-shortcuts span.icon {
+ float: left;
+ background: #444;
+ width: 30px;
+ height: 30px;
+ margin-right: 5px;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+}
+
+div.add-to-shortcuts a span.icon {
+ display: block;
+ width: 12px;
+ background: url(../toolbar/toolbar.png) no-repeat -50px -60px;
+ height: 12px;
+ float: left;
+ margin-left:8px;
+}
+
+div.add-to-shortcuts a:hover span.icon {
+ background-position: -50px -72px;
+}
+
+div.add-to-shortcuts a span.text {
+ float: left;
+ padding-left:10px;
+ display: none;
+}
+
+div.add-to-shortcuts a:hover span.text {
+ font-size: 10px;
+ line-height: 12px;
+ color: #fff;
+ background-color: #5f605b;
+ display: block;
+ padding-right: 6px;
+ cursor: pointer;
+ -moz-border-radius-topright: 5px;
+ -moz-border-radius-bottomright: 5px;
+ -webkit-border-top-right-radius: 5px;
+ -webkit-border-bottom-right-radius: 5px;
+}
+
diff --git modules/shortcut/shortcut.info modules/shortcut/shortcut.info
new file mode 100644
index 0000000..65f37c0
--- /dev/null
+++ modules/shortcut/shortcut.info
@@ -0,0 +1,9 @@
+; $Id$
+name = Shortcut
+description = Allows users to manage customizable lists of shortcut links.
+package = Core
+version = VERSION
+core = 7.x
+files[] = shortcut.module
+files[] = shortcut.admin.inc
+files[] = shortcut.install
diff --git modules/shortcut/shortcut.install modules/shortcut/shortcut.install
new file mode 100644
index 0000000..8fd57f0
--- /dev/null
+++ modules/shortcut/shortcut.install
@@ -0,0 +1,109 @@
+title = $t('Default');
+ $shortcut_set->links = array(
+ array(
+ 'link_path' => 'node/add',
+ 'link_title' => $t('Add content'),
+ 'weight' => -20,
+ ),
+ array(
+ 'link_path' => 'admin/content',
+ 'link_title' => $t('Find content'),
+ 'weight' => -19,
+ ),
+ array(
+ 'link_path' => 'admin/dashboard',
+ 'link_title' => $t('Dashboard'),
+ 'weight' => -18,
+ ),
+ );
+ shortcut_set_save($shortcut_set);
+}
+
+/**
+ * Implement hook_uninstall().
+ */
+function shortcut_uninstall() {
+ // Delete the menu links associated with each shortcut set.
+ foreach (shortcut_sets() as $shortcut_set) {
+ menu_delete_links($shortcut_set->set_name);
+ }
+}
+
+/**
+ * Implement hook_schema().
+ */
+function shortcut_schema() {
+ $schema['shortcut_set'] = array(
+ 'description' => 'Stores information about sets of shortcuts links.',
+ 'fields' => array(
+ 'set_name' => array(
+ 'type' => 'varchar',
+ 'length' => 32,
+ 'not null' => TRUE,
+ 'default' => '',
+ 'description' => "Primary Key: The {menu_links}.menu_name under which the set's links are stored.",
+ ),
+ 'title' => array(
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => TRUE,
+ 'default' => '',
+ 'description' => 'The title of the set.',
+ ),
+ ),
+ 'primary key' => array('set_name'),
+ 'foreign keys' => array(
+ 'set_name' => array('menu_links' => 'menu_name'),
+ ),
+ );
+
+ $schema['shortcut_set_users'] = array(
+ 'description' => 'Maps users to shortcut sets.',
+ 'fields' => array(
+ 'uid' => array(
+ 'type' => 'int',
+ 'unsigned' => TRUE,
+ 'not null' => TRUE,
+ 'default' => 0,
+ 'description' => 'The {users}.uid for this set.',
+ ),
+ 'set_name' => array(
+ 'type' => 'varchar',
+ 'length' => 32,
+ 'not null' => TRUE,
+ 'default' => '',
+ 'description' => "The {shortcut_set}.set_name that will be displayed for this user.",
+ ),
+ ),
+ 'primary key' => array('uid'),
+ 'indexes' => array(
+ 'set_name' => array('set_name'),
+ ),
+ 'foreign keys' => array(
+ 'uid' => array('users' => 'uid'),
+ 'set_name' => array('shortcut_set' => 'set_name'),
+ ),
+ );
+
+ return $schema;
+}
diff --git modules/shortcut/shortcut.module modules/shortcut/shortcut.module
new file mode 100644
index 0000000..328700a
--- /dev/null
+++ modules/shortcut/shortcut.module
@@ -0,0 +1,544 @@
+ array(
+ 'title' => t('Administer shortcuts'),
+ 'description' => t('Manage all shortcut and shortcut sets.'),
+ ),
+ 'customize shortcut links' => array(
+ 'title' => t('Customize shortcut links'),
+ 'description' => t("Edit, add and delete the links in shortcut set the user is using."),
+ ),
+ 'switch shortcut sets' => array(
+ 'title' => t('Choose a different shortcut set'),
+ 'description' => t('Choose which set of shortcuts are displayed for the user.')
+ ),
+ );
+}
+
+/**
+ * Implement hook_menu().
+ */
+function shortcut_menu() {
+ $items['admin/config/system/shortcut'] = array(
+ 'title' => 'Shortcuts',
+ 'description' => 'List the available shortcut sets and switch between them.',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('shortcut_set_switch'),
+ 'access arguments' => array('administer shortcuts'),
+ 'file' => 'shortcut.admin.inc',
+ );
+ $items['admin/config/system/shortcut/switch/confirm/%shortcut_set'] = array(
+ 'title' => 'Switch to new shortcut set',
+ 'description' => 'Confirmation form for switching to a new set.',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('shortcut_set_switch_confirm', 6),
+ 'access arguments' => array('administer shortcuts'),
+ 'type' => MENU_CALLBACK,
+ 'file' => 'shortcut.admin.inc',
+ );
+ $items['admin/config/system/shortcut/%shortcut_set'] = array(
+ 'title' => 'Customize shortcuts',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('shortcut_set_customize', 4),
+ 'access callback' => 'shortcut_set_edit_access',
+ 'access arguments' => array(4),
+ 'type' => MENU_CALLBACK,
+ 'file' => 'shortcut.admin.inc',
+ );
+ $items['admin/config/system/shortcut/%shortcut_set/add-link'] = array(
+ 'title' => 'Add shortcut',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('shortcut_link_add', 4),
+ 'access callback' => 'shortcut_set_edit_access',
+ 'access arguments' => array(4),
+ 'type' => MENU_LOCAL_ACTION,
+ 'file' => 'shortcut.admin.inc',
+ );
+ $items['admin/config/system/shortcut/%shortcut_set/add-link-inline'] = array(
+ 'title' => 'Add shortcut',
+ 'page callback' => 'shortcut_link_add_inline',
+ 'page arguments' => array(4),
+ 'access callback' => 'shortcut_set_edit_access',
+ 'access arguments' => array(4),
+ 'type' => MENU_CALLBACK,
+ 'file' => 'shortcut.admin.inc',
+ );
+ $items['admin/config/system/shortcut/link/%menu_link'] = array(
+ 'title' => 'Edit shortcut',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('shortcut_link_edit', 5),
+ 'access callback' => 'shortcut_link_access',
+ 'access arguments' => array(5),
+ 'type' => MENU_CALLBACK,
+ 'file' => 'shortcut.admin.inc',
+ );
+ $items['admin/config/system/shortcut/link/%menu_link/delete'] = array(
+ 'title' => 'Delete shortcut',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('shortcut_link_delete', 5),
+ 'access callback' => 'shortcut_link_access',
+ 'access arguments' => array(5),
+ 'type' => MENU_CALLBACK,
+ 'file' => 'shortcut.admin.inc',
+ );
+ $items['user/%user/shortcuts'] = array(
+ 'title' => 'Shortcuts',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('shortcut_set_switch', 1),
+ 'access callback' => 'shortcut_set_switch_access',
+ 'access arguments' => array(1),
+ 'type' => MENU_LOCAL_TASK,
+ 'file' => 'shortcut.admin.inc',
+ );
+ return $items;
+}
+
+/**
+ * Implement hook_theme().
+ */
+function shortcut_theme() {
+ return array(
+ 'shortcut_set_switch' => array(
+ 'arguments' => array('form' => NULL),
+ 'file' => 'shortcut.admin.inc',
+ ),
+ 'shortcut_set_customize' => array(
+ 'arguments' => array('form' => NULL),
+ 'file' => 'shortcut.admin.inc',
+ ),
+ );
+}
+
+/**
+ * Implement hook_block_info().
+ */
+function shortcut_block_info() {
+ $blocks['shortcuts']['info'] = t('Shortcuts');
+ // Shortcut blocks can't be cached because each menu item can have a custom
+ // access callback. menu.inc manages its own caching.
+ $blocks['shortcuts']['cache'] = DRUPAL_NO_CACHE;
+ return $blocks;
+}
+
+/**
+ * Implement hook_block_view().
+ */
+function shortcut_block_view($delta = '') {
+ if ($delta == 'shortcuts') {
+ $shortcut_set = shortcut_current_displayed_set();
+ $data['subject'] = t('@shortcut_set shortcuts', array('@shortcut_set' => $shortcut_set->title));
+ $data['content'] = shortcut_renderable_links($shortcut_set);
+ return $data;
+ }
+}
+
+/**
+ * Access callback for editing a shortcut set.
+ *
+ * @param $shortcut_set
+ * (optional) The shortcut set to be edited. If not set, the current
+ * displayed shortcut set will be assumed.
+ * @return
+ * TRUE if the current user has access to edit the shortcut set, FALSE
+ * otherwise.
+ */
+function shortcut_set_edit_access($shortcut_set = NULL) {
+ // Sufficiently-privileged users can edit their currently displayed shortcut
+ // set, but not other sets. Shortcut administrators can edit any set.
+ if (user_access('administer shortcuts')) {
+ return TRUE;
+ }
+ if (user_access('customize shortcut links')) {
+ return !isset($shortcut_set) || $shortcut_set == shortcut_current_displayed_set();
+ }
+ return FALSE;
+}
+
+/**
+ * Access callback for switching the shortcut set assigned to a user account.
+ *
+ * @param $account
+ * (optional) The user account whose shortcuts will be switched. If not set,
+ * the account of the current logged-in user will be assumed.
+ * @return
+ * TRUE if the current user has access to switch the shortcut set of the
+ * provided account, FALSE otherwise.
+ */
+function shortcut_set_switch_access($account = NULL) {
+ global $user;
+ // Sufficiently-privileged users can switch their own shortcut sets, but not
+ // those of other users. Shortcut administrators can switch any user's set.
+ return user_access('administer shortcuts') || (user_access('switch shortcut sets') && (!isset($account) || $user->uid == $account->uid));
+}
+
+/**
+ * Access callback for editing a link in a shortcut set.
+ */
+function shortcut_link_access($menu_link) {
+ // The link must belong to a shortcut set that the current user has access
+ // to edit.
+ if ($shortcut_set = shortcut_set_load($menu_link['menu_name'])) {
+ return shortcut_set_edit_access($shortcut_set);
+ }
+ return FALSE;
+}
+
+/**
+ * Loads the data for a shortcut set.
+ *
+ * @param $set_name
+ * The name of the shortcut set to load.
+ * @return
+ * If the shortcut set exists, an object of type stdClass containing the
+ * following properties:
+ * - 'set_name': The internal name of the shortcut set.
+ * - 'title': The title of the shortcut set.
+ * - 'links': An array of links associated with this shortcut set.
+ * If the shortcut set does not exist, the function returns FALSE.
+ */
+function shortcut_set_load($set_name) {
+ $set = db_select('shortcut_set', 'ss')
+ ->fields('ss')
+ ->condition('set_name', $set_name)
+ ->execute()
+ ->fetchObject();
+ if (!$set) {
+ return FALSE;
+ }
+ $set->links = menu_load_links($set_name);
+ return $set;
+}
+
+/**
+ * Saves a shortcut set.
+ *
+ * @param $shortcut_set
+ * An object containing the following properties:
+ * - 'title': The title of the shortcut set.
+ * - 'set_name': (optional) The internal name of the shortcut set. If
+ * omitted, a new shortcut set will be created, and the 'set_name' property
+ * will be added to the passed-in array.
+ * - 'links': (optional) An array of menu links to save for the shortcut set.
+ * Each link is an array containing at least the following keys (which will
+ * be expanded to fill in other default values after the shortcut set is
+ * saved):
+ * - 'link_path': The Drupal path or external path that the link points to.
+ * - 'link_title': The title of the link.
+ * Any other keys accepted by menu_link_save() may also be provided.
+ * @return
+ * A constant which is either SAVED_NEW or SAVED_UPDATED depending on whether
+ * a new set was created or an existing one was updated.
+ *
+ * @see menu_link_save()
+ */
+function shortcut_set_save(&$shortcut_set) {
+ // First save the shortcut set itself.
+ if (isset($shortcut_set->set_name)) {
+ $return = drupal_write_record('shortcut_set', $shortcut_set, 'set_name');
+ }
+ else {
+ $shortcut_set->set_name = shortcut_set_get_unique_name();
+ $return = drupal_write_record('shortcut_set', $shortcut_set);
+ }
+ // If links were provided for the set, save them, replacing any that were
+ // there before.
+ if (isset($shortcut_set->links)) {
+ menu_delete_links($shortcut_set->set_name);
+ foreach ($shortcut_set->links as &$link) {
+ // Do not specifically associate these links with the shortcut module,
+ // since other modules may make them editable via the menu system.
+ // However, we do need to specify the correct menu name.
+ $link['menu_name'] = $shortcut_set->set_name;
+ menu_link_save($link);
+ }
+ // Make sure that we have a return value, since if the links were updated
+ // but the shortcut set was not, the call to drupal_write_record() above
+ // would not return an indication that anything had changed.
+ if (empty($return)) {
+ $return = SAVED_UPDATED;
+ }
+ }
+ return $return;
+}
+
+/**
+ * Deletes a shortcut set.
+ *
+ * Note that the default set cannot be deleted.
+ *
+ * @param $shortcut_set
+ * An object representing the shortcut set to delete.
+ * @return
+ * TRUE if the set was deleted, FALSE otherwise.
+ */
+function shortcut_set_delete($shortcut_set) {
+ // Make sure not to delete the default set.
+ $default_set = shortcut_default_set();
+ if ($shortcut_set->set_name == $default_set->set_name) {
+ return FALSE;
+ }
+ // First, delete any user assignments for this set, so that each of these
+ // users will go back to using whatever default set applies.
+ db_delete('shortcut_set_users')
+ ->condition('set_name', $shortcut_set->set_name)
+ ->execute();
+ // Next, delete the menu links for this set.
+ menu_delete_links($shortcut_set->set_name);
+ // Finally, delete the set itself.
+ $deleted = db_delete('shortcut_set')
+ ->condition('set_name', $shortcut_set->set_name)
+ ->execute();
+ return (bool) $deleted;
+}
+
+/**
+ * Reset the link weights in a shortcut set to match their current order.
+ *
+ * This function can be used, for example, when a new shortcut link is added to
+ * the set. If the link is added to the end of the array and this function is
+ * called, it will force that link to display at the end of the list.
+ *
+ * @param $shortcut_set
+ * An object representing a shortcut set. The link weights of the passed-in
+ * object will be reset as described above.
+ */
+function shortcut_set_reset_link_weights(&$shortcut_set) {
+ $weight = -50;
+ foreach ($shortcut_set->links as &$link) {
+ $link['weight'] = $weight;
+ $weight++;
+ }
+}
+
+/**
+ * Assign a user to a particular shortcut set.
+ *
+ * @param $shortcut_set
+ * An object representing the shortcut set.
+ * @param $account
+ * A user account that will be assigned to use the set.
+ */
+function shortcut_set_assign_user($shortcut_set, $account) {
+ db_merge('shortcut_set_users')
+ ->key(array('uid' => $account->uid))
+ ->fields(array('set_name' => $shortcut_set->set_name))
+ ->execute();
+}
+
+/**
+ * Unassign a user from any shortcut set they may have been assigned to.
+ *
+ * The user will go back to using whatever default set applies.
+ *
+ * @param $account
+ * A user account that will be removed from the shortcut set assignment.
+ * @return
+ * TRUE if the user was previously assigned to a shortcut set and has been
+ * successfully removed from it. FALSE if the user was already not assigned
+ * to any set.
+ */
+function shortcut_set_unassign_user($account) {
+ $deleted = db_delete('shortcut_set')
+ ->condition('uid', $account->uid)
+ ->execute();
+ return (bool) $deleted;
+}
+
+/**
+ * Returns the current displayed shortcut set for the provided user account.
+ *
+ * @param $account
+ * (optional) The user account whose shortcuts will be returned. Defaults to
+ * the current logged-in user.
+ * @return
+ * An object representing the shortcut set that should be displayed to the
+ * current user. If the user does not have an explicit shortcut set defined,
+ * the default set is returned.
+ */
+function shortcut_current_displayed_set($account = NULL) {
+ $shortcut_sets = &drupal_static(__FUNCTION__, array());
+ global $user;
+ if (!isset($account)) {
+ $account = $user;
+ }
+ // Try to return a shortcut set from the static cache.
+ if (isset($shortcut_sets[$account->uid])) {
+ return $shortcut_sets[$account->uid];
+ }
+ // If none was found, try to find a shortcut set that is explicitly assigned
+ // to this user.
+ $query = db_select('shortcut_set', 's');
+ $query->fields('s');
+ $query->join('shortcut_set_users', 'u', 's.set_name = u.set_name');
+ $query->condition('u.uid', $account->uid);
+ $shortcut_set = $query->execute()->fetchObject();
+ // Otherwise, use the default set.
+ if (!$shortcut_set) {
+ $shortcut_set = shortcut_default_set($account);
+ }
+ $shortcut_sets[$account->uid] = $shortcut_set;
+ return $shortcut_set;
+}
+
+/**
+ * Returns the default shortcut set for a given user account.
+ *
+ * @param $account
+ * (optional) The user account whose shortcuts will be returned. Defaults to
+ * the current logged-in user.
+ * @return
+ * An object representing the default shortcut set.
+ */
+function shortcut_default_set($account = NULL) {
+ global $user;
+ if (!isset($account)) {
+ $account = $user;
+ }
+ // Allow modules to return a default shortcut set name. Since we can only
+ // have one, we take the first valid result we get. If we don't find one,
+ // fall back on the site-wide default.
+ $shortcut_set_names = array_merge(module_invoke_all('shortcut_default_set_name', $account), array(SHORTCUT_DEFAULT_SET_NAME));
+ foreach ($shortcut_set_names as $name) {
+ if ($shortcut_set = shortcut_set_load($name)) {
+ break;
+ }
+ }
+ return $shortcut_set;
+}
+
+/**
+ * Returns a unique, machine-readable shortcut set name.
+ */
+function shortcut_set_get_unique_name() {
+ // Shortcut sets are numbered sequentially, so we keep trying until we find
+ // one that is available. For better performance, we start with a number
+ // equal to one more than the current number of shortcut sets, so that if
+ // no shortcut sets have been deleted from the database, this will
+ // automatically give us the correct one.
+ $number = db_query("SELECT COUNT(*) FROM {shortcut_set}")->fetchField() + 1;
+ do {
+ $name = shortcut_set_name($number);
+ $number++;
+ } while ($shortcut_set = shortcut_set_load($name));
+ return $name;
+}
+
+/**
+ * Returns the name of a shortcut set, based on a provided number.
+ *
+ * All shortcut sets have names like "shortcut-set-N" so that they can be
+ * matched with a properly-namespaced entry in the {menu_links} table.
+ *
+ * @param $number
+ * A number representing the shortcut set whose name should be retrieved.
+ * @return
+ * A string representing the expected shortcut name.
+ */
+function shortcut_set_name($number) {
+ return "shortcut-set-$number";
+}
+
+/**
+ * Returns an array of all shortcut sets, keyed by the set name.
+ *
+ * @return
+ * An array of shortcut sets. Note that only the basic shortcut set
+ * properties (name and title) are returned by this function, not the list
+ * of menu links that belong to the set.
+ */
+function shortcut_sets() {
+ return db_select('shortcut_set', 'ss')
+ ->fields('ss')
+ ->execute()
+ ->fetchAllAssoc('set_name');
+}
+
+/**
+ * Returns an array of shortcut links, suitable for rendering.
+ *
+ * @param $shortcut_set
+ * (optional) An object representing the set whose links will be displayed.
+ * If not provided, the user's current set will be displayed.
+ * @return
+ * An array of shortcut links, in the format returned by the menu system.
+ *
+ * @see menu_tree()
+ */
+function shortcut_renderable_links($shortcut_set = NULL) {
+ if (!isset($shortcut_set)) {
+ $shortcut_set = shortcut_current_displayed_set();
+ }
+ return menu_tree($shortcut_set->set_name);
+}
+
+/**
+ * Implement hook_page_build().
+ */
+function shortcut_page_build(&$page) {
+ if (shortcut_set_edit_access()) {
+ $link = $_GET['q'];
+ $query_parameters = drupal_get_query_parameters();
+ if (!empty($query_parameters)) {
+ $link .= '?' . drupal_http_build_query($query_parameters);
+ }
+ $query = array(
+ 'link' => $link,
+ 'name' => drupal_get_title(),
+ 'token' => drupal_get_token('shortcut-add-link'),
+ );
+ $query += drupal_get_destination();
+
+ $shortcut_set = shortcut_current_displayed_set();
+ $link_text = shortcut_set_switch_access() ? t('Add to %shortcut_set shortcuts', array('%shortcut_set' => $shortcut_set->title)) : t('Add to shortcuts');
+ $page['add_to_shortcuts'] = array(
+ '#prefix' => '',
+ '#markup' => l('' . $link_text . '', 'admin/config/system/shortcut/' . $shortcut_set->set_name . '/add-link-inline', array('query' => $query, 'html' => TRUE)),
+ '#suffix' => '
',
+ );
+ }
+
+ $links = shortcut_renderable_links();
+ $links['#attached'] = array('css' => array(drupal_get_path('module', 'shortcut') . '/shortcut.css'));
+ $links['#prefix'] = '';
+ $links['#suffix'] = '
';
+ $shortcut_set = shortcut_current_displayed_set();
+ $configure_link = NULL;
+ if (shortcut_set_edit_access($shortcut_set)) {
+ $configure_link = array('#markup' => l(t('edit shortcuts'), 'admin/config/system/shortcut/' . $shortcut_set->set_name, array('attributes' => array('id' => 'toolbar-customize'))));
+ }
+
+ $drawer = array(
+ 'shortcuts' => $links,
+ 'configure' => $configure_link,
+ );
+
+ $page['toolbar_drawer'] = $drawer;
+}
+
+/**
+ * Implement hook_preprocess_page().
+ */
+function shortcut_preprocess_page(&$variables) {
+ if (isset($variables['page']['add_to_shortcuts'])) {
+ $variables['add_to_shortcuts'] = drupal_render($variables['page']['add_to_shortcuts']);
+ }
+}
diff --git modules/simpletest/tests/menu.test modules/simpletest/tests/menu.test
index cf4d390..6f9947c 100644
--- modules/simpletest/tests/menu.test
+++ modules/simpletest/tests/menu.test
@@ -159,7 +159,7 @@ class MenuIncTestCase extends DrupalWebTestCase {
function testMenuGetNames() {
// The main-menu is there but has no items by default, so not returned by
// menu_get_names(). Therefore we cannot check for that.
- $this->assertEqual(menu_get_names(), array('admin_shortcuts', 'management', 'navigation', 'original', 'user-menu'), t('Expected menu names were returned.'));
+ $this->assertEqual(menu_get_names(), array('management', 'navigation', 'original', 'shortcut-set-1', 'user-menu'), t('Expected menu names were returned.'));
}
/**
diff --git modules/toolbar/toolbar.css modules/toolbar/toolbar.css
index d530e8b..12cffff 100644
--- modules/toolbar/toolbar.css
+++ modules/toolbar/toolbar.css
@@ -4,7 +4,7 @@ body.toolbar {
padding-top: 30px;
}
-body.toolbar-shortcuts {
+body.toolbar-drawer {
padding-top: 80px;
}
@@ -118,49 +118,13 @@ div#toolbar div.toolbar-menu ul li a.active {
}
/**
- * Administration shortcuts.
+ * Collapsed drawer of additional toolbar content.
*/
-div#toolbar div.toolbar-shortcuts {
+div#toolbar div.toolbar-drawer {
position: relative;
padding: 0 10px;
}
-div#toolbar div.toolbar-shortcuts ul {
- padding: 5px 0;
- height: 40px;
- line-height: 30px;
- overflow: hidden;
- float: left;
-}
-
-div#toolbar div.toolbar-shortcuts ul li a {
- -moz-border-radius: 5px;
- -webkit-border-radius: 5px;
- padding: 5px 10px 5px 5px;
- margin-right: 5px;
-}
-
-div#toolbar div.toolbar-shortcuts ul li a:focus,
-div#toolbar div.toolbar-shortcuts ul li a:hover,
-div#toolbar div.toolbar-shortcuts ul li a.active:focus {
- background: #555;
-}
-
-div#toolbar div.toolbar-shortcuts ul li a.active:hover,
-div#toolbar div.toolbar-shortcuts ul li a.active {
- background: url(toolbar.png) 0 -20px repeat-x;
-}
-
-div#toolbar div.toolbar-shortcuts span.icon {
- float: left;
- background: #444;
- width: 30px;
- height: 30px;
- margin-right: 5px;
- -moz-border-radius: 5px;
- -webkit-border-radius: 5px;
-}
-
/**
* IE 6 Fixes.
*
@@ -168,7 +132,7 @@ div#toolbar div.toolbar-shortcuts span.icon {
* the behavior of the admin toolbar entirely to static positioning.
*/
* html body.toolbar,
-* html body.toolbar-shortcuts {
+* html body.toolbar-drawer {
padding-top: 0;
}
diff --git modules/toolbar/toolbar.info modules/toolbar/toolbar.info
index 60037d8..db85c72 100644
--- modules/toolbar/toolbar.info
+++ modules/toolbar/toolbar.info
@@ -1,9 +1,7 @@
; $Id: toolbar.info,v 1.2 2009-07-06 13:54:21 dries Exp $
name = Toolbar
-description = Toolbar exposing the top level administration menu items
+description = Toolbar exposing the top level administration menu items.
core = 7.x
package = Core
version = VERSION
-files[] = toolbar.install
files[] = toolbar.module
-dependencies[] = menu
diff --git modules/toolbar/toolbar.install modules/toolbar/toolbar.install
deleted file mode 100644
index fcbc2a1..0000000
--- modules/toolbar/toolbar.install
+++ /dev/null
@@ -1,56 +0,0 @@
- 'admin_shortcuts',
- 'title' => $t('Administration shortcuts'),
- 'description' => $t('The Administration shortcuts menu contains commonly used links for administrative tasks.'),
- );
- menu_save($menu);
-
- // Add starter convenience shortcuts.
- menu_rebuild();
- $items = array(
- 'node/add' => 'Add content',
- 'admin/content' => 'Find content',
- 'admin/dashboard' => 'Dashboard',
- );
- $weight = -20;
- foreach ($items as $path => $title) {
- $link = array(
- 'mlid' => 0,
- 'link_title' => $title,
- 'link_path' => $path,
- 'router_path' => $path,
- 'menu_name' => 'admin_shortcuts',
- 'module' => 'menu',
- 'weight' => $weight,
- );
-
- // Check for an existing menu item before attempting to create a new one.
- $menu_link = db_query("SELECT mlid FROM {menu_links} WHERE link_path = :path AND menu_name = :menu_name", array(
- ':path' => $link['link_path'],
- ':menu_name' => $link['menu_name']
- ))
- ->fetchField();
- if (!$menu_link) {
- menu_link_save($link);
- }
-
- // Increment weight so items can be displayed in desired order.
- $weight++;
- }
-}
diff --git modules/toolbar/toolbar.js modules/toolbar/toolbar.js
index 7763203..222a4c7 100644
--- modules/toolbar/toolbar.js
+++ modules/toolbar/toolbar.js
@@ -10,7 +10,7 @@ Drupal.behaviors.admin = {
// Set the intial state of the toolbar.
$('#toolbar', context).once('toolbar', Drupal.admin.toolbar.init);
- // Toggling of admin shortcuts visibility.
+ // Toggling toolbar drawer.
$('#toolbar span.toggle', context).once('toolbar-toggle').click(function() {
Drupal.admin.toolbar.toggle();
return false;
@@ -44,9 +44,9 @@ Drupal.admin.toolbar.init = function() {
* Collapse the admin toolbar.
*/
Drupal.admin.toolbar.collapse = function() {
- $('#toolbar div.toolbar-shortcuts').addClass('collapsed');
+ $('#toolbar div.toolbar-drawer').addClass('collapsed');
$('#toolbar span.toggle').removeClass('toggle-active');
- $('body').removeClass('toolbar-shortcuts');
+ $('body').removeClass('toolbar-drawer');
$.cookie(
'Drupal.admin.toolbar.collapsed',
1,
@@ -58,9 +58,9 @@ Drupal.admin.toolbar.collapse = function() {
* Expand the admin toolbar.
*/
Drupal.admin.toolbar.expand = function() {
- $('#toolbar div.toolbar-shortcuts').removeClass('collapsed');
+ $('#toolbar div.toolbar-drawer').removeClass('collapsed');
$('#toolbar span.toggle').addClass('toggle-active');
- $('body').addClass('toolbar-shortcuts');
+ $('body').addClass('toolbar-drawer');
$.cookie(
'Drupal.admin.toolbar.collapsed',
0,
@@ -72,7 +72,7 @@ Drupal.admin.toolbar.expand = function() {
* Toggle the admin toolbar.
*/
Drupal.admin.toolbar.toggle = function() {
- if ($('#toolbar div.toolbar-shortcuts').is('.collapsed')) {
+ if ($('#toolbar .toolbar-drawer').is('.collapsed')) {
Drupal.admin.toolbar.expand();
}
else {
diff --git modules/toolbar/toolbar.module modules/toolbar/toolbar.module
index 28371ed..36145ef 100644
--- modules/toolbar/toolbar.module
+++ modules/toolbar/toolbar.module
@@ -38,17 +38,18 @@ function toolbar_theme($existing, $type, $theme, $path) {
function toolbar_page_build(&$page) {
if (user_access('access toolbar')) {
$page['page_top']['toolbar'] = toolbar_build();
+ $page['page_top']['toolbar']['toolbar_drawer'] = isset($page['toolbar_drawer']) ? $page['toolbar_drawer'] : array();
}
}
/**
- * Implement hook_preprocess_page().
+ * Implement hook_preprocess_html().
*
* Add some page classes, so global page theming can adjust to the toolbar.
*/
function toolbar_preprocess_html(&$vars) {
if (user_access('access toolbar')) {
- $vars['classes_array'][] = 'toolbar toolbar-shortcuts';
+ $vars['classes_array'][] = 'toolbar toolbar-drawer';
}
}
@@ -100,16 +101,6 @@ function toolbar_build() {
),
'#attributes' => array('id' => 'toolbar-user'),
);
-
- // Add convenience shortcut links.
- $shortcuts = menu_tree_all_data('admin_shortcuts');
- $shortcuts = toolbar_menu_navigation_links($shortcuts);
- $build['toolbar_shortcuts'] = array(
- '#theme' => 'links',
- '#links' => $shortcuts,
- '#attributes' => array('id' => 'toolbar-shortcuts'),
- );
-
return $build;
}
diff --git modules/toolbar/toolbar.png modules/toolbar/toolbar.png
index ffe41ff0f80bed5a7a4be26209bf02466f7c21aa..391d2e7507792751292db5852058dc431bf0a473 100644
GIT binary patch
delta 1052
zcmcc1x|u_O@8LdgiO1E{-7;x8BT&
z_qZG=a{T-q3A@bdfOh7^N{)^qJr@&_x;hUBG#_Aht&)15bq{fzBKsx&Hd1}hVri&Rlhu`SkI?7^my*+Jn)Y@Ej?WJ!XAK1T4tA3^S7VC^%
z9(UQdT+ayG;vgZzUd;H}bBhzF+Bfc7y&jR5>wGkpSrgFj2YzwZ=1F?lH~_gA6HDN=9wZ5umzb@Oocfs=I>HCdd{WH3G
zuPZMXNg%v5y>=&JUFTx_0eaLuog)WpNXAc9$p!TsU{`+@XcN?>au^
zZJ*s071+Po;ZlS4)KfG6{P|Oxy7=|44_m`lFFiBcr)&SK7cV+)p2#t4zpW-*kzZQ6
zb$Va@rpHs3eV(JXY|oxM-no<6WEeG-j1}fwe^|ia$F$;V)`bicksSxFToHM&L|{wf
zwI3_Xzh1o>dg9C(pBD?v&CL@lDkT2Y{hwI9a^=c^@No9b%uIDV+*v^k=m*H)r=-F6`yyrJ%2`pZI_!)u3J?Ati;S>EMI9y-o``t{-o*
zQ+s>C{Y&I$`+cu%FX#Pz^1Czr;;tRBwS|R(F?!eUeMx-x`KQpTDmOQ_kdP1uuT%FX
zXe`fO)qnY_=HiII!pC0SojP^u(#Xij33KQ2evdk1QK?n&<%8jhkX1hpUcYuNp{7P=
zQT$bds<{vV=7(J6Y`RkHZ}=q>E_%
z+a~twcl@E+&&?auFW!#yc=feh?6*gJe7rHxI+h>nBjyU_*1UebKWTkoQ&v`%)n(aV
z_U7kzB!6AEe6B*un!2BtL=FFc5xK+JG-2bfPnU!^Bv!b6YyQ2x9sZ$W*}-3re%47y8#h?$b23ZZTxr8{R`1b7w{`n;
zw0`&p9=z_#dS6WR&UutPQ@8Hkeb>LN`}Z^PF#Pzq;<))0MLl4KXYh3Ob6Mw<&;$U<
C>G`t&
literal 733
zcmeAS@N?(olHy`uVBq!ia0vp^AAmT8gAGXTShV*zkdiEMjVKAuPb(=;EJ|f?Ovz75
zRq)JBOiv9;O-!jQJeg|4z`#`R>EaktaqG<;!+fDYh65kf6JI2Bao;_1w&c>q)`iT?
zIWI1LS9}bHWnTZ2@n=AP)Gn_hXWuCG={Mmh?zkOuqkS2aKxr)m0Urhfke#n)#X1w
zEo!+Q`{eZR*|TTAzF$7?kwn1ChR-YJJ$>E(^V2Vm_5U^F*U8Drf0d{_aevR;5MSN+
zHg_&Yxz9=US;{kg-!PtKU}+Hl`+_X5W5>6ulWC-UuXL1
zg2KYUSDtIGzb+^*7dM-IR{s3lxpQ0N){CDze|~Rt!3iFl`RBVYq-~B|sV?~VP1){+
zarJ+`tK=R3`>2(fdEfs1{Fh&DsgSweeRRIlJ`eK}=?~h68D6se
zxn$t5i_zX3B)qReQi$)z%ESg2=Dzq#d`n)oGcYr3v^%ruJ`-~&FugK(y85}Sb4q9e
E0LX1a8~^|S
diff --git modules/toolbar/toolbar.tpl.php modules/toolbar/toolbar.tpl.php
index 2bbd893..cfd4cd1 100644
--- modules/toolbar/toolbar.tpl.php
+++ modules/toolbar/toolbar.tpl.php
@@ -8,7 +8,7 @@
* Available variables:
* - $toolbar['toolbar_user']: User account / logout links.
* - $toolbar['toolbar_menu']: Top level management menu links.
- * - $toolbar['toolbar_shortcuts']: Convenience shortcuts.
+ * - $toolbar['toolbar_drawer']: A place for extended toolbar content.
*
* @see template_preprocess()
* @see template_preprocess_admin_toolbar()
@@ -16,13 +16,15 @@
?>