diff --git includes/menu.inc includes/menu.inc index 0d7a821..15d17ad 100644 --- includes/menu.inc +++ includes/menu.inc @@ -2228,6 +2228,24 @@ function _menu_navigation_links_rebuild($menu) { } /** + * 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 = db_query("SELECT * FROM {menu_links} WHERE menu_name = :menu_name", array(':menu_name' => $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.inc modules/shortcut/shortcut.admin.inc new file mode 100644 index 0000000..c82a7c4 --- /dev/null +++ modules/shortcut/shortcut.admin.inc @@ -0,0 +1,76 @@ +roles)) { + return variable_get('mymodule_admin_shortcut_default_set_name'); + } +} + +/** + * @} End of "addtogroup hooks". + */ 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..8b59425 --- /dev/null +++ modules/shortcut/shortcut.install @@ -0,0 +1,104 @@ +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', + '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..ba9fc8d --- /dev/null +++ modules/shortcut/shortcut.module @@ -0,0 +1,312 @@ + array( + 'title' => t('Administer shortcuts'), + 'description' => t('Manage shortcuts and shortcut sets regardless of which user they are assigned to.'), + ), + 'customize shortcut links' => array( + 'title' => t('Customize shortcut links'), + 'description' => t("Edit, add and delete the links in the user's currently displayed shortcut set."), + ), + '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_switch_set'), + 'access arguments' => array('administer shortcuts'), + ); + $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_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_edit', 4), + 'access callback' => 'shortcut_set_access', + 'access arguments' => array(4), + 'type' => MENU_LOCAL_ACTION, + 'file' => 'shortcut.admin.inc', + ); + $items['admin/config/system/shortcut/%shortcut_set/link/%menu_link'] = array( + 'title' => 'Edit shortcut', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('shortcut_link_edit', 4, 6), + 'access callback' => 'shortcut_set_access', + 'access arguments' => array(4), + 'type' => MENU_CALLBACK, + 'file' => 'toolbar.admin.inc', + ); + $items['admin/config/system/shortcut/%shorcut_set/link/%menu_link/delete'] = array( + 'title' => 'Delete shortcut', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('shortcut_link_delete', 6), + 'access callback' => 'shortcut_set_access', + 'access arguments' => array(4), + 'type' => MENU_CALLBACK, + 'file' => 'toolbar.admin.inc', + ); + $items['user/%user/shortcuts'] = array( + 'title' => 'Shortcuts', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('shortcut_switch_set', 1), + 'access callback' => 'shortcut_switch_access', + 'access arguments' => array(1), + 'type' => MENU_LOCAL_TASK, + ); + return $items; +} + +/** + * Access callback for editing a shortcut set. + */ +function shortcut_set_access($shortcut_set) { + // Sufficiently-privileged users can edit their currently displayed shortcut + // set, but not other sets. Shortcut administrators can edit any set. + return user_access('administer shortcuts') || (user_access('customize shortcut links') && ($current_set = shortcut_current_displayed_set()) && $current_set->set_name == $shortcut_set->set_name); +} + +/** + * Access callback for switching the shortcut set assigned to a user account. + */ +function shortcut_switch_access($account) { + 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') && $user->uid == $account->uid); +} + +/** + * Loads the data for a shortcut set. + * + * @param $set_name + * The name of the shortcut set to load. + * @return + * An object containing the basic data about the set (name and title), or + * FALSE if the set does not exist. + */ +function shortcut_set_load($set_name) { + return db_query("SELECT * FROM {shortcut_set} WHERE set_name = :set_name", array(':set_name' => $set_name))->fetchObject(); +} + +/** + * Saves a shortcut set. + * + * @param $shortcut_set + * A shortcut set 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 object. + * - '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. + * @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. + */ +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_get_unique_set_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; +} + +/** + * Returns an array of all shortcut set objects, keyed by the set name. + */ +function shortcut_sets() { + return db_query("SELECT * FROM {shortcut_set}")->fetchAllAssoc('set_name'); +} + +/** + * 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. + $shortcut_set = db_select('shortcut_set', 's') + ->fields('s') + ->join('shortcut_set_users', 'u', 's.set_name = u.set_name') + ->condition('u.uid', $account->uid) + ->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), variable_get('shortcut_default_set_name', shortcut_set_name())); + foreach ($shortcut_set_names as $name) { + if ($shortcut_set = shortcut_set_load($name)) { + break; + } + } + return $shortcut_set; +} + +/** + * 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 + * (optional) A number representing the shortcut set whose name should be + * retrieved. Defaults to one (i.e.,the first shortcut set). + * @return + * A string representing the expected shortcut name. + */ +function shortcut_set_name($number = 1) { + return "shortcut-set-$number"; +} + +/** + * Returns a unique, machine-readable shortcut set name. + */ +function shortcut_get_unique_set_name() { + // Shortcut sets are numbered sequentially, so we keep trying until we find + // one that is available. + $number = 1; + do { + $name = shortcut_set_name($number); + $number++; + } while ($shortcut_set = shortcut_set_load($name)); + return $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_links($shortcut_set = NULL) { + if (!isset($shortcut_set)) { + $shortcut_set = shortcut_current_displayed_set(); + } + return menu_tree($shortcut_set->set_name); +} + +/** + * Menu callback; Build the form for switching shortcut sets. + * + * @param $account + * (optional) The user account whose shortcuts will be switched. Defaults to + * the current logged-in user. + * @return + * An array representing the form definition. + * + * @ingroup forms + * @see shortcut_switch_set_submit() + */ +function shortcut_switch_set($form, &$form_state, $account = NULL) { + global $user; + if (!isset($account)) { + $account = $user; + } + $sets = shortcut_sets(); + // TODO: Copy code here. +} + +/** + * Submit handler for the shorcut set switcher form. + */ +function shortcut_switch_set_submit($form, &$form_state) { + // TODO: Copy code here. +} diff --git modules/toolbar/toolbar.info modules/toolbar/toolbar.info index 60037d8..ecdb2e9 100644 --- modules/toolbar/toolbar.info +++ modules/toolbar/toolbar.info @@ -1,9 +1,9 @@ ; $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.install files[] = toolbar.module -dependencies[] = menu +dependencies[] = shortcut diff --git modules/toolbar/toolbar.install modules/toolbar/toolbar.install deleted file mode 100644 index a4bffd3..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', - ); - $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.module modules/toolbar/toolbar.module index 28371ed..aead7b8 100644 --- modules/toolbar/toolbar.module +++ modules/toolbar/toolbar.module @@ -102,11 +102,10 @@ function toolbar_build() { ); // Add convenience shortcut links. - $shortcuts = menu_tree_all_data('admin_shortcuts'); - $shortcuts = toolbar_menu_navigation_links($shortcuts); + $shortcuts = shortcut_links(); $build['toolbar_shortcuts'] = array( '#theme' => 'links', - '#links' => $shortcuts, + '#links' => toolbar_menu_navigation_links($shortcuts), '#attributes' => array('id' => 'toolbar-shortcuts'), ); diff --git profiles/default/default.info profiles/default/default.info index 9b0ed6c..f9cdb26 100644 --- profiles/default/default.info +++ profiles/default/default.info @@ -13,6 +13,7 @@ dependencies[] = path dependencies[] = taxonomy dependencies[] = dblog dependencies[] = search +dependencies[] = shortcut dependencies[] = toolbar dependencies[] = field_ui dependencies[] = file diff --git sites/default/default.settings.php sites/default/default.settings.php old mode 100644 new mode 100755