Browse Source

[add] Admin menu contrib module.

opi 8 years ago
parent
commit
7d60d6a177
31 changed files with 4876 additions and 0 deletions
  1. 366 0
      sites/all/modules/admin_menu/CHANGELOG.txt
  2. 339 0
      sites/all/modules/admin_menu/LICENSE.txt
  3. 188 0
      sites/all/modules/admin_menu/README.txt
  4. 12 0
      sites/all/modules/admin_menu/admin_devel/admin_devel.info
  5. 40 0
      sites/all/modules/admin_menu/admin_devel/admin_devel.js
  6. 33 0
      sites/all/modules/admin_menu/admin_devel/admin_devel.module
  7. 64 0
      sites/all/modules/admin_menu/admin_menu-rtl.css
  8. 62 0
      sites/all/modules/admin_menu/admin_menu.admin.js
  9. 164 0
      sites/all/modules/admin_menu/admin_menu.api.php
  10. 45 0
      sites/all/modules/admin_menu/admin_menu.color.css
  11. 233 0
      sites/all/modules/admin_menu/admin_menu.css
  12. 910 0
      sites/all/modules/admin_menu/admin_menu.inc
  13. 16 0
      sites/all/modules/admin_menu/admin_menu.info
  14. 123 0
      sites/all/modules/admin_menu/admin_menu.install
  15. 385 0
      sites/all/modules/admin_menu/admin_menu.js
  16. 147 0
      sites/all/modules/admin_menu/admin_menu.map.inc
  17. 852 0
      sites/all/modules/admin_menu/admin_menu.module
  18. 9 0
      sites/all/modules/admin_menu/admin_menu.uid1.css
  19. 145 0
      sites/all/modules/admin_menu/admin_menu_toolbar/admin_menu_toolbar.css
  20. 12 0
      sites/all/modules/admin_menu/admin_menu_toolbar/admin_menu_toolbar.info
  21. 37 0
      sites/all/modules/admin_menu/admin_menu_toolbar/admin_menu_toolbar.install
  22. 56 0
      sites/all/modules/admin_menu/admin_menu_toolbar/admin_menu_toolbar.js
  23. 118 0
      sites/all/modules/admin_menu/admin_menu_toolbar/admin_menu_toolbar.module
  24. BIN
      sites/all/modules/admin_menu/admin_menu_toolbar/toolbar.png
  25. BIN
      sites/all/modules/admin_menu/images/arrow-rtl.png
  26. BIN
      sites/all/modules/admin_menu/images/arrow.png
  27. BIN
      sites/all/modules/admin_menu/images/bkg-red.png
  28. BIN
      sites/all/modules/admin_menu/images/bkg.png
  29. BIN
      sites/all/modules/admin_menu/images/bkg_tab.png
  30. BIN
      sites/all/modules/admin_menu/images/icon_users.png
  31. 520 0
      sites/all/modules/admin_menu/tests/admin_menu.test

+ 366 - 0
sites/all/modules/admin_menu/CHANGELOG.txt

@@ -0,0 +1,366 @@
+
+Admin Menu 7.x-3.x, xxxx-xx-xx
+------------------------------
+#1177202 by das-peter, dereine, sun: Fixed copying and re-injection of child
+  router items breaks badly. Change them by reference instead.
+  Requires latest Views 3.x code.
+#1212064 by sun: Updated admin_views default views for VBO 3.x.
+#1196590 by sun: Fixed errors and notices for admin_views with Views 3.
+#1144768 by idlewilder, sun: Fixed devel modules to skip are not displayed.
+#1079374 by WillHall: Fixed JS Error: unrecognized expression: [href=/].
+#1114132 by joelstein, sun: Added Field UI to list of developer modules.
+#1008380 by bdragon, sun: Updated admin_views for D7.
+#1146644 by sun: Fixed PHP 5.3 compability in tests.
+#442560 by sun: Fixed 'defer' script attribute breaks Drupal.behaviors in FF3.6.
+#1022902 by matglas86, sun: Updated for changed core Toolbar styles.
+
+
+Admin Menu 7.x-3.0-RC1, 2010-01-07
+----------------------------------
+#990774 by sun: Updated for $closure renamed to $page_bottom.
+#991906 by johnv, sun: Added configure to .info file.
+#947198 by sun: Added hint about disabling Toolbar.
+by sun: Updated administrative settings form for D7 UX guidelines.
+by sun: Disabled "Rebuild system links" button on settings form.
+#420816 by sun, smk-ka: Improved on-demand loading of dynamic paths.
+#420816 by tim.plunkett: Fixed dynamic Field UI paths for vocabularies.
+#871774 by swentel: Fixed developer modules toggle still uses referer_uri().
+#671760 by sun: Updated for new preprocess defaults.
+#731462 by sun: Updated for system_rebuild_theme_data().
+by sun: Re-added a "Rebuild system links" button to settings form.
+#420816 by tim.plunkett: Updated taxonomy path map for machine names.
+#857688 by sun: Updated for reverted system_settings_form().
+#420816 by smk-ka, sun: Added merging of menu trees containing dynamic paths.
+by sun: Fixed tests and minor admin_menu_toolbar styling issues.
+by sun: Fixed various styling issues for admin_menu and admin_menu_toolbar.
+by sun: Updated for Schema API, DBTNG, coding standards.
+by sun: Updated for new admin/modules path.
+#701424 by hutch: Updated for new admin/people/people path.
+by sun: Removed orphan menu rewrite function.
+#667858 by sun: Don't remove the current user from the switch user list.
+#631550 by sun: Updated for fixed MENU_VISIBLE_IN_BREADCRUMB behavior.
+#658344 by dereine, sun: Updated for removed drupal_session_count().
+by sun: Added separate permission to flush cashes.
+by sun: Updated for changed Devel settings form.
+by sun: Updated for new {system}.info module data.
+#614730 by azriprajwala, sun: Updated for hook_theme() key changes.
+by sun: Updated for all theme functions should take a single argument.
+by sun: Reverted removal of registry cache flushing option.
+#578520 by sun: Fixed destination query parameter is processed wrongly.
+#578520 by sun: Updated for $query in url() should always be an array.
+by Dave Reid: Updated for PHP 5 date constants.
+by sun: Updated for new database API.
+by smk-ka: Removed remnants of the registry. Fixed flush admin menu cache
+  command.
+#567618 by smk-ka: Revised test cases. Abstracted out base web test class.
+by sun: Updated for removed registry, new admin paths.
+#326539 by sun: Updated for class attribute array.
+#519782 by sun: Updated for hook_footer() replaced by hook_page_alter().
+#525638 by Razorraser: Updated for admin/build renamed to admin/structure.
+by Dave Reid: Updated for hook_permission().
+#482314 by Dave Reid: Updated for node_type_get_types().
+#437506 by yched, Dave Reid: Updated for menu_router_build().
+#376816 by sun: Updated for compatibility for other JavaScript libraries.
+#337820 by Dave Reid: Updated for new user/logout path.
+#340546 by Dave Reid: Updated for drupal_add_js().
+#340531 by Dave Reid: Updated for module_list().
+#266358 by sun: Updated for drupal_add_css().
+#320526 by yettyn, sun: Updated to UNSTABLE-2 (DBTNG queries, permissions, etc).
+by sun: Changed admin_menu_wipe() to admin_menu_flush_caches().
+by sun: Updated content-type edit menu item locations.
+by sun: Fixed sess_count() changed to drupal_session_count().
+
+
+Admin Menu 6.x-3.x, xxxx-xx-xx
+------------------------------
+#588936 by fenstrat: Fixed Toolbar shortcuts not visible.
+#860390 by Kevin Rogers: Fixed .info file parsing error on uncertain platform.
+#551484 by sun: Fixed stale hook_admin_menu_output_alter() docs.
+
+
+Admin Menu 6.x-3.0-ALPHA4, 2010-03-11
+-------------------------------------
+#730156 by sun: Fixed Administration views.
+by sun: Fixed missing .element-hidden style in D6 for permissions tweak.
+#645526 by TravisCarden: Fixed stale local tasks markup after moving them.
+#366442 by sun: Added tweak to collapse modules on permissions page.
+#655926 by donquixote, sun: Improved performance of delayed mouseout.
+#557062 by sun: Fixed admin_menu_toolbar JS/CSS loaded before admin_menu's.
+#599462 by sun, koyama: Added background-color to avoid unintentional override.
+#601918 by BWPanda: Fixed admin_menu.css overrides admin_menu_toolbar.css.
+#586228 by Island Usurper: Fixed for PHP 5.3.
+#554124 by Dave Reid: Added missing toolbar.png.
+#557062 by Dave Reid: Fixed undefined Drupal.admin error when including
+  admin_menu_toolbar.js before admin_menu.js.
+#511744 by smk-ka, sun: Fixed /admin page links are broken.
+by smk-ka: Added missing variables to hook_uninstall().
+#571038 by smk-ka: Removed call to admin_menu_wipe() and cleaned install file.
+#552190 by Bartezz: Fixed missing t() for user logout link.
+
+
+Admin Menu 6.x-3.0-ALPHA3, 2009-08-16
+-------------------------------------
+#502500 by sun: Added "Create content" menu.
+#538714 by sun: Fixed wrong re-parenting in Drupal's menu system.
+#550132 by sun: Fixed (temporarily) admin_views menu items.
+by sun: Added Administration views sub-module, converting all administrative
+  listing pages in Drupal core into real, ajaxified, and alterable views.
+#547206 by sun: Fixed menu link descriptions lead to mouseover clashes.
+#540954 by Rob Loach: Added String Overrides to list of developer modules.
+#540762 by Deslack: Added Malay translation.
+
+
+Admin Menu 6.x-3.0-ALPHA2, 2009-08-02
+-------------------------------------
+#527908 by sun: Changed theme_admin_menu_links() to use $element['#children'].
+#527908 by markus_petrux, sun: Changed admin menu into a renderable array.
+#420812 by sun, smk-ka: Added support for hook_js().
+by sun: Fixed destination query string of current page not applied to links.
+by sun: Changed Drupal.admin.attachBehaviors() to accept local JS settings.
+#276751 by sun: Revamped rendering of menu additions/widgets.
+#500866 by sun: Updated for removed t() from getInfo() in tests.
+#402058 by sun: Added Administration menu toolbar module.
+by markus_petrux, sun: Added API documentation.
+#461264 by sun: Added site/domain as CSS class.
+#451270 by smk-ka, sun: Changed visual indication for uid1.
+by sun: Minor code clean-up.
+#490670 by sun: Fixed missing menu after installation/upgrade.
+#515718 by joelstein, sun: Added rules_admin module to developer modules list.
+#352065 by sun: Added setting to select developer modules to keep enabled.
+#511854 by psynaptic: Fixed logout link.
+#424960 by markus_petrux, sun: Fixed gzip compression for cached output.
+by sun: Fixed opacity of links in sub-menus.
+#479922 by sun: Fixed fieldsets not collapsed on admin/build/modules/list*.
+#495148 by sun: Fixed MENU_NORMAL_ITEMs do not appear in administration menu.
+by sun: Fixed tests for new content-type locations.
+#345984 by markus_petrux, sun: Fixed old menu links not removed on upgrade.
+#276751 by sun: Major rewrite. Fixed menu items cannot be moved, altered, or
+  added as well as various performance issues.
+by sun: Added variable to allow to disable caching (rewrite).
+
+
+Admin Menu 6.x-3.0-ALPHA1, 2009-06-10
+-------------------------------------
+#236657 by sun: Updated for corrected arguments of system_clear_cache_submit().
+#483870 by sun: Fixed compatibility with new Admin module.
+#483152 by sun: Fixed admin_menu caches not flushed when clean URLs are toggled.
+#479922 by danep: Fixed fieldsets not collapsed on admin/build/modules/list.
+#469716 by sun: Fixed wrong AJAX callback URL under various conditions.
+#471504 by wulff: Updated Danish translation.
+by sun: Fixed admin_menu_suppress() does not suppress margin-top.
+#451270 by sun: Added visual indication when working as uid 1.
+by Dave Reid: Updated for getInfo() in tests.
+#420828 by sun: Added dynamic replacements for cached administration menu.
+#420840 by sun: Fixed Drupal.behaviors.adminMenu must be only executed once.
+#345984 by markus_petrux, sun: Added client-side caching of administration menu.
+  Attention: A new era of Drupal user experience starts here.  This is the very
+  first issue of a series of improvements targeting plain awesomeness.
+#349169 by sun: Fixed Devel switch user links contain multiple path prefixes.
+#345984 by sun: Code clean-up in preparation for client-side caching.
+#415196 by psynaptic: Updated for CSS coding standards.
+#406672 by mr.j, sun: Fixed "Move local tasks" option leaves stale UL.
+by sun: Major code clean-up and sync across 3.x branches.
+#349505 by smk-ka, sun: Performance: Added caching of entire menu output.
+#315342 by wulff: Added "My account" link (by splitting the "Log out" item).
+#384100 by kepol, sun: Fixed content-type items displayed in wrong place.
+#373339 by sun: Fixed double-escaped 'Edit <content-type>' link titles.
+#373372 by sun: Turned procedural JavaScript into admin menu behaviors.
+by sun: Fixed admin menu tests (and updated to 6.x for SimpleTest 2.x).
+#359158 by nitrospectide, sun: Fixed Devel Themer breaks admin menu.
+#365335 by sun: Fixed not all variables removed after uninstall.
+
+
+Admin Menu 6.x-1.3, 2009-01-24
+------------------------------
+#362454 by sun: Fixed Drupal.settings.admin_menu is undefined JS error in some
+  browsers.
+
+
+Admin Menu 6.x-1.2, 2009-01-20
+------------------------------
+#358697 by sun: Added docs about admin_menu_suppress() to README.txt.
+#342684 by darumaki, sun: Added notice about Opera configuration to README.txt.
+#350932 by sun: Fixed "Run updates" link repeated per language/site.
+#342298 by gustz: Updated Spanish translation.
+#346106 by sun: Fixed XHTML-Strict validation for admin menu icon.
+#287448 by sun: Fixed unnecessary menu rebuild for users without permission to
+  use admin menu.
+#342002 by AltaVida: Fixed improper test for node/add paths.
+#272920 by keith.smith: Changed all text strings throughout the module.
+#322731 by sun: Fixed improper use of t() in module install file.
+#282030 by sun: Fixed "Run updates" item visible for unprivileged users.
+#322877 by sun: Added tweak to move page tabs into administration menu.
+#287468 by sun: Fixed module paths directly below "admin" get the wrong parent.
+#310423 by sun: Added optional position: fixed configuration setting.
+#292657 by smk-ka: Improved rendering performance.
+#234149 by yhager, sun: Fixed RTL support for IE.
+#323726 by danez1972: Added Spanish translation.
+#325057 by sun: Updated README.txt.
+#234149 by yhager, levavie, sun: Added RTL support.
+#325057 by sun: Added links to flush specific caches.
+#324334 by AltaVida: Fixed usernames with spaces not in Devel user switch links.
+#319382 by betz: Added Dutch translation.
+
+
+Admin Menu 6.x-1.1, 2008-09-12
+------------------------------
+#295476 by pwolanin, use <front> for icon path to fix front-page path-change
+  bug and pathauto conflict, add wipe button to admin form.
+#301370 by sun: Disabled module fieldset collapsing behavior by default.
+#288672 by sun: Fixed JS hover behavior not working in IE.
+#290803 by sun: Fixed missing devel_themer in devel modules; added some others.
+#286636 by sun: Fixed menus do not drop down in IE6.
+#249537 by pwolanin, sun: Added admin_menu_suppress() to allow other modules to
+  disable the display of admin_menu on certain pages (f.e. popups).
+#268211 by sun: Fixed invalid issue queue links for custom modules and
+  sub-modules of projects.
+#261461 by sun: Added FAQ entry for displaying other menus like admin_menu.
+#264067 by sun: Added FAQ entry for huge amount of anonymous users displayed.
+#280002 by pwolanin: Clean up .test setUp function.
+#242377 by sun: Fixed sub-level menu items exceed total document height.
+
+
+Admin Menu 6.x-1.0, 2008-06-26
+------------------------------
+#266308 by sun: Fixed jQuery 1.0.x incompatible selector for collapsing modules.
+#268373 by sun: Added hook_update to cleanup for alpha/beta testers.
+#268373 by sun: Added menu callback to disable/enable developer modules.
+#132524 by pwolanin: Fixed admin_menu links are re-inserted each time menu links
+  are rebuilt.
+by smk-ka: Performance: Use 'defer' attribute for JavaScript to delay execution.
+#266099 by sun: Fixed description of "Apply margin-top" configuration setting.
+#266308 by sun: Usability: Added Utility module features to collapse module
+  fieldsets on Modules page.
+#251341 by sun: Added docs about display drupal links permission.
+
+
+Admin Menu 6.x-1.0-BETA, 2008-06-08
+-----------------------------------
+#132524 by sun: Fixed support for sub-content-types below node/add.
+#132524 by pwolanin: Added support for localizable menu links.
+#132524 by pwolanin, sun: Fixed menu links adjustments.
+#132524 by pwolanin: Added simpletest.
+#132524 by pwolanin: Major rewrite to better use Drupal 6 menu system.
+#132524 by sun: Moved gettext translation files into translations.
+#132524 by sun: Committing pre-alpha code for D6 due to public demand.
+
+
+Admin Menu 5.x-2.x, xxxx-xx-xx
+------------------------------
+#246221 by sun: Fixed user counter displays different values than Who's online
+  block.
+#239022 by mikl: Added Danish translation.
+#234444 by smk-ka: Fixed admin_menu icon does not respect theme settings.
+#198240 by sun: Fixed admin_menu displayed in print output.
+
+
+Admin Menu 5.x-2.4, 2008-02-24
+------------------------------
+#214740 by sun: Regression: Fixed directly applied marginTop not supported by IE.
+#214725 by sun: Fixed wrong CSS id in admin_menu.js (missed in 5.x-2.3).
+
+
+Admin Menu 5.x-2.3, 2008-02-24
+------------------------------
+#214725 by sun: Fixed CSS id and classes should not contain underscores.
+#209390 by sun: Added note about interaction with user role permissions.
+#214740 by jjeff, sun: Added module settings to configure margin-top CSS.
+#200737 by sun: Changed admin_menu (fav)icon to use theme setting, if defined.
+#203116 by smk-ka: Improved performance of non-cached admin_menu by storing
+  already processed URLs in the cache.
+#224605 by sun: 'Add <content_type>' items do not appear without 'administer
+  nodes' permission.
+#210615 by robertgarrigos: Fixed Mozilla Mac: Collapsible fieldsets display
+  error.
+
+
+Admin Menu 5.x-2.2, 2007-01-08
+------------------------------
+#204884 by jjeff: Usability: Override theme font family declaration.
+#204935 by jjeff: Added mouseout delay for hovered menus (yay!).
+#193941 by downgang: Fixed margin in IE6 using Garland theme.
+#197306 by sun: Fixed 'Run updates' leads to wrong url with clean URLs disabled.
+Moved images into sub-folder.
+by smk-ka: Fixed icon title for user counter not displayed & coding style.
+Fixed user count not displayed without 'administer users' permission.
+
+
+Admin Menu 5.x-2.1, 2007-12-02
+------------------------------
+Fixed adding menu items with negative weight not always working.
+Fixed admin_menu_copy_items() is overwriting already existing items.
+Fixed display menu item ids in devel settings does not work.
+
+
+Admin Menu 5.x-2.0, 2007-12-02
+------------------------------
+Added devel_admin_menu() for fast access to clear-cache, variable editor and
+  switch_user.
+Added username to logout button.
+Added hook_admin_menu() to allow other modules to alter admin_menu.
+#194189 by sun: Added counter for current anonymous/authenticated users.
+Added Drupal.org project issue queue links for all enabled contrib modules.
+#189701 by sun: Changed admin_menu icon to be a menu.
+#193925 by sun: Removed obsolete menu slicing code.
+#193669 by smk-ka: Moved admin_menu builder functions into include file.
+
+
+Admin Menu 5.x-1.2, 2007-11-18
+------------------------------
+#176969 by smk-ka: Fixed performance issues with path(auto) module by
+  introducing a menu cache for admin_menu.
+#179648 by sun: Inject admin_menu into theme.
+  Fixes several CSS bugs in various themes and also activation of admin_menu
+  immediately after installation.
+#191213 by Standard: Fixed block info shouldn't contain the word "block".
+#187816 by sun: Fixed "Add" not translatable.
+#186218 by sun: Fixed admin menu icon too big in Safari.
+#182563 by sun: Fixed wrong datatype for array_search in _admin_menu_get_children().
+#183496 by sun: Fixed invalid argument supplied for foreach in admin_menu_copy_items().
+
+
+Admin Menu 5.x-1.1, 2007-10-10
+------------------------------
+#178876 by sun: Fixed 3rd-level submenus expand without hover over.
+#153455 by sun: Fixed add product node sub-elements are empty.
+Fixed path_to_theme() call breaking blocks page.
+#177582 by sun: Fixed bluebreeze theme compatibility.
+
+
+Admin Menu 5.x-1.0, 2007-09-06
+------------------------------
+#156952 by sun: Fixed admin menu inaccessible due to margins.
+#149229 by sun: Fixed admin menu not expanding in IE7.
+#172545 by sun: Use opacity instead of -moz-opacity.
+#132867 Fixed z-index too low.
+- Fixed admin menu block selectors to override any other theme styles.
+#155589 by sun: Added permission to access administration menu.
+- Fixed a PHP warning when there are no content types defined in the system, as
+  node/add then has no child menu items.
+#155312 by sun: Fixed menu item tooltip clashes.
+Added support for custom stylesheets per theme.
+Removed 4.7.x compatibility.
+
+
+Admin Menu 4.7-1.3, 2007-03-30
+------------------------------
+#126601 Fixed Users can see inaccessible items.
+#121027 Fixed Page not found entries for menu-collapsed.png.
+
+
+Admin Menu 4.7-1.2, 2007-03-04
+------------------------------
+- Fixed menu item adjustments
+- Fixed IE / Safari support
+- Fixed base_path for IE support
+- Added create content options to content management menu
+
+
+Admin Menu 4.7-1.1, 2007-01-24
+------------------------------
+First stable release, compatible to Drupal 4.7.x and 5.x.
+
+
+Admin Menu 4.7-1.0, 2007-01-16
+------------------------------
+Initial release of admin_menu module. Already supporting Drupal 5.0.

+ 339 - 0
sites/all/modules/admin_menu/LICENSE.txt

@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.

+ 188 - 0
sites/all/modules/admin_menu/README.txt

@@ -0,0 +1,188 @@
+
+-- SUMMARY --
+
+The Administration menu module displays the entire administrative menu tree (and
+most local tasks) in a drop-down menu, providing administrators one- or
+two-click access to most pages.  Other modules may also add menu links to the
+menu using hook_admin_menu_output_alter().
+
+For a full description of the module, visit the project page:
+  http://drupal.org/project/admin_menu
+
+To submit bug reports and feature suggestions, or to track changes:
+  http://drupal.org/project/issues/admin_menu
+
+
+-- REQUIREMENTS --
+
+None.
+
+
+-- INSTALLATION --
+
+* Install as usual, see http://drupal.org/node/895232 for further information.
+
+* You likely want to disable Toolbar module, since its output clashes with
+  Administration menu.
+
+
+-- CONFIGURATION --
+
+* Configure user permissions in Administration » People » Permissions:
+
+  - Use the administration pages and help (System module)
+
+    The top-level administration categories require this permission to be
+    accessible. The administration menu will be empty unless this permission is
+    granted.
+
+  - Access administration menu
+
+    Users in roles with the "Access administration menu" permission will see
+    the administration menu at the top of each page.
+
+  - Display Drupal links
+
+    Users in roles with the "Display drupal links" permission will receive
+    links to drupal.org issue queues for all enabled contributed modules. The
+    issue queue links appear under the administration menu icon.
+
+  Note that the menu items displayed in the administration menu depend on the
+  actual permissions of the viewing user. For example, the "People" menu item
+  is not displayed to a user who is not a member of a role with the "Administer
+  users" permission.
+
+* Customize the menu settings in Administration » Configuration and modules »
+  Administration » Administration menu.
+
+* To prevent administrative menu items from appearing twice, you may hide the
+  "Management" menu block.
+
+
+-- CUSTOMIZATION --
+
+* To override the default administration menu icon, you may:
+
+  1) Disable it via CSS in your theme:
+
+     body #admin-menu-icon { display: none; }
+
+  2) Alter the image by overriding the theme function:
+
+     Copy the entire theme_admin_menu_icon() function into your template.php,
+     rename it to phptemplate_admin_menu_icon() or THEMENAME_admin_menu_icon(),
+     and customize the output according to your needs.
+
+  Remember that the output of the administration menu is cached. To see changes
+  from your theme override function, you must clear your site cache (via
+  the "Flush all caches" link on the menu).
+
+* To override the font size, add the following line to your theme's stylesheet:
+
+  body #admin-menu { font-size: 10px; }
+
+
+-- TROUBLESHOOTING --
+
+* If the menu does not display, check the following:
+
+  - Are the "Access administration menu" and "Use the administration pages and help"
+    permissions enabled for the appropriate roles?
+
+  - Does html.tpl.php of your theme output the $page_bottom variable?
+
+* If the menu is rendered behind a Flash movie object, add this property to your
+  Flash object(s):
+
+  <param name="wmode" value="transparent" />
+
+  See http://drupal.org/node/195386 for further information.
+
+
+-- FAQ --
+
+Q: When the administration menu module is enabled, blank space is added to the
+   bottom of my theme. Why?
+
+A: This is caused by a long list of links to module issue queues at Drupal.org.
+   Use Administer >> User management >> Permissions to disable the "display
+   drupal links" permission for all appropriate roles. Note that since UID 1
+   automatically receives all permissions, the list of issue queue links cannot
+   be disabled for UID 1.
+
+
+Q: After upgrading to 6.x-1.x, the menu disappeared. Why?
+
+A: You may need to regenerate your menu. Visit
+   http://example.com/admin/build/modules to regenerate your menu (substitute
+   your site name for example.com).
+
+
+Q: Can I configure the administration menu module to display another menu (like
+   the Navigation menu, for instance)?
+
+A: No. As the name implies, administration menu module is for administrative
+   menu links only. However, you can copy and paste the contents of
+   admin_menu.css into your theme's stylesheet and replace #admin-menu with any
+   other menu block id (#block-menu-1, for example).
+
+
+Q: Sometimes, the user counter displays a lot of anonymous users, but no spike
+   of users or requests appear in Google Analytics or other tracking tools.
+
+A: If your site was concurrently spidered by search-engine robots, it may have
+   a significant number of anonymous users for a short time. Most web tracking
+   tools like Google Analytics automatically filter out these requests.
+
+
+Q: I enabled "Aggregate and compress CSS files", but admin_menu.css is still
+   there. Is this normal?
+
+A: Yes, this is the intended behavior. the administration menu module only loads
+   its stylesheet as needed (i.e., on page requests by logged-on, administrative
+   users).
+
+
+Q: Why are sub-menus not visible in Opera?
+
+A: In the Opera browser preferences under "web pages" there is an option to fit
+   to width. By disabling this option, sub-menus in the administration menu
+   should appear.
+
+
+Q: How can the administration menu be hidden on certain pages?
+
+A: You can suppress it by simply calling the following function in PHP:
+
+     module_invoke('admin_menu', 'suppress');
+
+   However, this needs to happen as early as possible in the page request, so
+   placing it in the theming layer (resp. a page template file) is too late.
+   Ideally, the function is called in hook_init() in a custom module.  If you do
+   not have a custom module, placing it into some conditional code at the top of
+   template.php may work out, too.
+
+
+-- CONTACT --
+
+Current maintainers:
+* Daniel F. Kudwien (sun) - http://drupal.org/user/54136
+* Peter Wolanin (pwolanin) - http://drupal.org/user/49851
+* Stefan M. Kudwien (smk-ka) - http://drupal.org/user/48898
+* Dave Reid (Dave Reid) - http://drupal.org/user/53892
+
+Major rewrite for Drupal 6 by Peter Wolanin (pwolanin).
+
+This project has been sponsored by:
+* UNLEASHED MIND
+  Specialized in consulting and planning of Drupal powered sites, UNLEASHED
+  MIND offers installation, development, theming, customization, and hosting
+  to get you started. Visit http://www.unleashedmind.com for more information.
+
+* Lullabot
+  Friendly Drupal experts providing professional consulting & education
+  services. Visit http://www.lullabot.com for more information.
+
+* Acquia
+  Commercially Supported Drupal. Visit http://acquia.com for more information.
+

+ 12 - 0
sites/all/modules/admin_menu/admin_devel/admin_devel.info

@@ -0,0 +1,12 @@
+name = Administration Development tools
+description = Administration and debugging functionality for developers and site builders.
+package = Administration
+core = 7.x
+scripts[] = admin_devel.js
+
+; Information added by Drupal.org packaging script on 2014-12-19
+version = "7.x-3.0-rc5"
+core = "7.x"
+project = "admin_menu"
+datestamp = "1419029284"
+

+ 40 - 0
sites/all/modules/admin_menu/admin_devel/admin_devel.js

@@ -0,0 +1,40 @@
+(function($) {
+
+/**
+ * jQuery debugging helper.
+ *
+ * Invented for Dreditor.
+ *
+ * @usage
+ *   $.debug(var [, name]);
+ *   $variable.debug( [name] );
+ */
+jQuery.extend({
+  debug: function () {
+    // Setup debug storage in global window. We want to look into it.
+    window.debug = window.debug || [];
+
+    args = jQuery.makeArray(arguments);
+    // Determine data source; this is an object for $variable.debug().
+    // Also determine the identifier to store data with.
+    if (typeof this == 'object') {
+      var name = (args.length ? args[0] : window.debug.length);
+      var data = this;
+    }
+    else {
+      var name = (args.length > 1 ? args.pop() : window.debug.length);
+      var data = args[0];
+    }
+    // Store data.
+    window.debug[name] = data;
+    // Dump data into Firebug console.
+    if (typeof console != 'undefined') {
+      console.log(name, data);
+    }
+    return this;
+  }
+});
+// @todo Is this the right way?
+jQuery.fn.debug = jQuery.debug;
+
+})(jQuery);

+ 33 - 0
sites/all/modules/admin_menu/admin_devel/admin_devel.module

@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * @file
+ * Administration and debugging functionality for developers and site builders.
+ */
+
+/**
+ * Implements hook_form_FORMID_alter().
+ */
+function admin_devel_form_admin_menu_theme_settings_alter(&$form, &$form_state) {
+  $form['actions']['wipe_rebuild'] = array(
+    '#type' => 'submit',
+    '#value' => t('Rebuild system links'),
+    '#submit' => array('admin_devel_form_admin_menu_theme_settings_alter_rebuild_submit'),
+    // @todo Not necessarily ready for mass-consumption yet.
+    '#access' => FALSE,
+  );
+}
+
+/**
+ * Form submit handler to wipe and rebuild all 'module' = 'system' menu links.
+ */
+function admin_devel_form_admin_menu_theme_settings_alter_rebuild_submit($form, &$form_state) {
+  // Delete all auto-generated menu links derived from menu router items.
+  db_delete('menu_links')
+    ->condition('module', 'system')
+    ->execute();
+  // Rebuild menu links from current menu router items.
+  menu_rebuild();
+
+  drupal_set_message(t('System links derived from menu router paths have been rebuilt.'));
+}

+ 64 - 0
sites/all/modules/admin_menu/admin_menu-rtl.css

@@ -0,0 +1,64 @@
+
+#admin-menu {
+  text-align: right;
+}
+#admin-menu .dropdown .admin-menu-users a {
+  background-position: 10% center;
+  padding-left: 22px;
+  padding-right: 0;
+}
+#admin-menu .dropdown .admin-menu-action,
+#admin-menu .dropdown .admin-menu-search {
+  float: left;
+}
+#admin-menu .dropdown .admin-menu-action a {
+  border-left: none;
+  border-right: 1px solid #323232;
+}
+
+/* All lists */
+#admin-menu a {
+  text-align: right;
+}
+#admin-menu .dropdown a {
+  border-left: 1px solid #323232;
+  border-right: 0;
+}
+#admin-menu .dropdown .admin-menu-tab a {
+  border-left: 1px solid #52565E;
+  border-right: 0;
+}
+#admin-menu .dropdown li li a {
+  border-left: 0;
+}
+
+/* All list items */
+#admin-menu .dropdown li {
+  float: right;
+}
+#admin-menu .dropdown li li {
+}
+
+/* Second-level lists */
+#admin-menu .dropdown li ul {
+  left: auto;
+  right: -999em;
+}
+
+/* Third-and-above-level lists */
+#admin-menu .dropdown li li.expandable ul {
+  margin-left: 0;
+  margin-right: 160px;
+}
+
+/* Lists nested under hovered list items */
+#admin-menu .dropdown li.admin-menu-action:hover ul {
+  left: 0 !important;
+  right: auto;
+}
+
+/* Second-and-more-level hovering */
+#admin-menu .dropdown li li.expandable {
+  background-image: url(images/arrow-rtl.png);
+  background-position: 5px 6px;
+}

+ 62 - 0
sites/all/modules/admin_menu/admin_menu.admin.js

@@ -0,0 +1,62 @@
+(function($) {
+
+/**
+ * Live preview of Administration menu components.
+ */
+Drupal.behaviors.adminMenuLivePreview = {
+  attach: function (context, settings) {
+    $('input[name^="admin_menu_components"]', context).once('admin-menu-live-preview')
+      .change(function () {
+        var target = $(this).attr('rel');
+        $(target).toggle(this.checked);
+      })
+      .trigger('change');
+  }
+};
+
+/**
+ * Automatically enables required permissions on demand.
+ *
+ * Many users do not understand that two permissions are required for the
+ * administration menu to appear. Since Drupal core provides no facility for
+ * this, we implement a simple manual confirmation for automatically enabling
+ * the "other" permission.
+ */
+Drupal.behaviors.adminMenuPermissionsSetupHelp = {
+  attach: function (context, settings) {
+    $('#permissions', context).once('admin-menu-permissions-setup', function () {
+      // Retrieve matrix/mapping - these need to use the same indexes for the
+      // same permissions and roles.
+      var $roles = $(this).find('th:not(:first)');
+      var $admin = $(this).find('input[name$="[access administration pages]"]');
+      var $menu = $(this).find('input[name$="[access administration menu]"]');
+
+      // Retrieve the permission label - without description.
+      var adminPermission = $.trim($admin.eq(0).parents('td').prev().children().get(0).firstChild.textContent);
+      var menuPermission = $.trim($menu.eq(0).parents('td').prev().children().get(0).firstChild.textContent);
+
+      $admin.each(function (index) {
+        // Only proceed if both are not enabled already.
+        if (!(this.checked && $menu[index].checked)) {
+          // Stack both checkboxes and attach a click event handler to both.
+          $(this).add($menu[index]).click(function () {
+            // Do nothing when disabling a permission.
+            if (this.checked) {
+              // Figure out which is the other, check whether it still disabled,
+              // and if so, ask whether to auto-enable it.
+              var other = (this == $admin[index] ? $menu[index] : $admin[index]);
+              if (!other.checked && confirm(Drupal.t('Also allow !name role to !permission?', {
+                '!name': $roles[index].textContent,
+                '!permission': (this == $admin[index] ? menuPermission : adminPermission)
+              }))) {
+                other.checked = 'checked';
+              }
+            }
+          });
+        }
+      });
+    });
+  }
+};
+
+})(jQuery);

+ 164 - 0
sites/all/modules/admin_menu/admin_menu.api.php

@@ -0,0 +1,164 @@
+<?php
+
+/**
+ * @file
+ * API documentation for Administration menu.
+ */
+
+/**
+ * Provide expansion arguments for dynamic menu items.
+ *
+ * The map items must be keyed by the dynamic path to expand, i.e. a menu path
+ * containing one or more '%' placeholders. Each map item may have the following
+ * properties:
+ * - parent: The parent menu path to link the expanded items to.
+ * - arguments: An array of argument sets that will be used in the expansion.
+ *   Each set consists of an array of one or more placeholders, which again is
+ *   an array of possible expansion values. Upon expansion, each argument is
+ *   combined with every other argument from the set (technically, the cartesian
+ *   product of all arguments). The expansion values may be empty; that is, you
+ *   do not need to insert logic to skip map items for which no values exist,
+ *   since Administration menu will take care of that.
+ *
+ * @see admin_menu.map.inc
+ */
+function hook_admin_menu_map() {
+  // Expand content types below Structure > Content types.
+  // The key denotes the dynamic path to expand to multiple menu items.
+  $map['admin/structure/types/manage/%node_type'] = array(
+    // Link generated items directly to the "Content types" item.
+    'parent' => 'admin/structure/types',
+    // Create expansion arguments for the '%node_type' placeholder.
+    'arguments' => array(
+      array(
+        '%node_type' => array_keys(node_type_get_types()),
+      ),
+    ),
+  );
+  return $map;
+}
+
+/**
+ * Add to the administration menu content before it is rendered.
+ *
+ * Only use this hook to add new data to the menu structure. Use
+ * hook_admin_menu_output_alter() to *alter* existing data.
+ *
+ * @param array $content
+ *   A structured array suitable for drupal_render(), potentially containing:
+ *   - menu: The administrative menu of links below the path 'admin/*'.
+ *   - icon: The icon menu.
+ *   - account: The user account name and log out link.
+ *   - users: The user counter.
+ *   Additionally, these special properties:
+ *   - #components: The actual components contained in $content are configurable
+ *     and depend on the 'admin_menu_components' configuration value. #components
+ *     holds a copy of that for convenience.
+ *   - #complete: A Boolean indicating whether the complete menu should be built,
+ *     ignoring the current configuration in #components.
+ *   Passed by reference.
+ *
+ * @see hook_admin_menu_output_alter()
+ * @see admin_menu_links_menu()
+ * @see admin_menu_links_icon()
+ * @see admin_menu_links_user()
+ * @see theme_admin_menu_links()
+ */
+function hook_admin_menu_output_build(&$content) {
+  // In case your implementation provides a configurable component, check
+  // whether the component should be displayed:
+  if (empty($content['#components']['shortcut.links']) && !$content['#complete']) {
+    return;
+  }
+
+  // Add new top-level item to the menu.
+  if (isset($content['menu'])) {
+    $content['menu']['myitem'] = array(
+      '#title' => t('My item'),
+      // #attributes are used for list items (LI).
+      '#attributes' => array('class' => array('mymodule-myitem')),
+      '#href' => 'mymodule/path',
+      // #options are passed to l().
+      '#options' => array(
+        'query' => drupal_get_destination(),
+        // Apply a class on the link (anchor).
+        'attributes' => array('class' => array('myitem-link-anchor')),
+      ),
+      // #weight controls the order of links in the resulting item list.
+      '#weight' => 50,
+    );
+  }
+  // Add link to the icon menu to manually run cron.
+  if (isset($content['icon'])) {
+    $content['icon']['myitem']['cron'] = array(
+      '#title' => t('Run cron'),
+      '#access' => user_access('administer site configuration'),
+      '#href' => 'admin/reports/status/run-cron',
+    );
+  }
+}
+
+/**
+ * Change the administration menu content before it is rendered.
+ *
+ * Only use this hook to alter existing data in the menu structure. Use
+ * hook_admin_menu_output_build() to *add* new data.
+ *
+ * @param array $content
+ *   A structured array suitable for drupal_render(). Passed by reference.
+ *
+ * @see hook_admin_menu_output_build()
+ */
+function hook_admin_menu_output_alter(&$content) {
+}
+
+/**
+ * Return content to be replace via JS in the cached menu output.
+ *
+ * @param bool $complete
+ *   A Boolean indicating whether all available components of the menu will be
+ *   output and the cache will be skipped.
+ *
+ * @return array
+ *   An associative array whose keys are jQuery selectors and whose values are
+ *   strings containing the replacement content.
+ */
+function hook_admin_menu_replacements($complete) {
+  $items = array();
+  // If the complete menu is output, then it is uncached and will contain the
+  // current counts already.
+  if (!$complete) {
+    // Check whether the users count component is enabled.
+    $components = variable_get('admin_menu_components', array());
+    if (!empty($components['admin_menu.users']) && ($user_count = admin_menu_get_user_count())) {
+      // Replace the counters in the cached menu output with current counts.
+      $items['.admin-menu-users a'] = $user_count;
+    }
+  }
+  return $items;
+}
+
+/**
+ * Inform about additional module-specific caches that can be cleared.
+ *
+ * Administration menu uses this hook to gather information about available
+ * caches that can be flushed individually. Each returned item forms a separate
+ * menu link below the "Flush all caches" link in the icon menu.
+ *
+ * @return array
+ *   An associative array whose keys denote internal identifiers for a
+ *   particular caches (which can be freely defined, but should be in a module's
+ *   namespace) and whose values are associative arrays containing:
+ *   - title: The name of the cache, without "cache" suffix. This label is
+ *     output as link text, but also for the "!title cache cleared."
+ *     confirmation message after flushing the cache; make sure it works and
+ *     makes sense to users in both locations.
+ *   - callback: The name of a function to invoke to flush the individual cache.
+ */
+function hook_admin_menu_cache_info() {
+  $caches['update'] = array(
+    'title' => t('Update data'),
+    'callback' => '_update_cache_clear',
+  );
+  return $caches;
+}

+ 45 - 0
sites/all/modules/admin_menu/admin_menu.color.css

@@ -0,0 +1,45 @@
+
+/**
+ * @file
+ * Administration menu color override.
+ */
+
+#admin-menu {
+  background-color: #911;
+  background-image: url(images/bkg-red.png);
+}
+#admin-menu li.admin-menu-action a {
+  border-left-color: #a91f1f;
+}
+
+/* All lists */
+#admin-menu ul a {
+  border-right-color: #a91f1f;
+}
+#admin-menu ul li.admin-menu-tab a {
+  border-right-color: #52565E;
+}
+#admin-menu li li a {
+  border-top-color: #801f1f;
+}
+
+/* All list items */
+#admin-menu li li {
+  background-color: #991f1f;
+}
+
+/* Second-and-more-level hovering */
+#admin-menu li li.expandable {
+  background-color: #b93f3f;
+}
+#admin-menu li li:hover {
+  background-color: #690f0f;
+}
+#admin-menu li li.expandable:hover a,
+#admin-menu li li.expandable:hover li.expandable:hover a {
+  border-color: #801f1f;
+}
+#admin-menu li li.expandable:hover li a,
+#admin-menu li li.expandable:hover li.expandable:hover li a {
+  border-color: #801f1f;
+}

+ 233 - 0
sites/all/modules/admin_menu/admin_menu.css

@@ -0,0 +1,233 @@
+
+/**
+ * @file
+ * Administration menu.
+ *
+ * Implementation of Sons of Suckerfish Dropdowns.
+ *
+ * @see www.htmldog.com/articles/suckerfish
+ */
+
+#admin-menu {
+  background: #101010 url(images/bkg.png) bottom left repeat-x;
+  font-size: 9px;
+  font-family: "lucida grande", tahoma, verdana, arial, sans-serif;
+  left: 0;
+  position: absolute;
+  text-align: left;
+  top: 0;
+  width: 100%;
+}
+#admin-menu-wrapper {
+  overflow: hidden;
+}
+#admin-menu .dropdown .admin-menu-icon a {
+  padding: 1px 8px 4px;
+}
+#admin-menu .dropdown .admin-menu-icon ul a {
+  padding: 4px 8px;
+}
+#admin-menu .dropdown .admin-menu-icon img {
+  vertical-align: bottom;
+}
+#admin-menu .dropdown .admin-menu-users a {
+  background: transparent url(images/icon_users.png) 90% center no-repeat;
+  padding-right: 22px;
+}
+#admin-menu .dropdown .admin-menu-action,
+#admin-menu .dropdown .admin-menu-search {
+  float: right;
+}
+#admin-menu .dropdown .admin-menu-action a {
+  border-left: 1px solid #323232;
+  border-right: none;
+}
+body.admin-menu {
+  margin-top: 20px !important;
+}
+
+/* All lists */
+#admin-menu,
+#admin-menu .dropdown {
+  line-height: 1.4em;
+  list-style: none;
+  margin: 0;
+  padding: 0;
+  z-index: 999;
+}
+#admin-menu .dropdown {
+  position: static;
+}
+#admin-menu a,
+#admin-menu li > span {
+  background: transparent none;
+  border: none;
+  color: #EEE;
+  font-weight: normal;
+  text-align: left; /* LTR */
+  text-decoration: none;
+}
+#admin-menu .dropdown a,
+#admin-menu .dropdown li > span {
+  border-right: 1px solid #323232; /* LTR */
+  display: block;
+  padding: 4px 8px;
+}
+#admin-menu .dropdown .admin-menu-tab a {
+  border-right: 1px solid #52565E; /* LTR */
+}
+#admin-menu .dropdown li li a {
+  border-right: none; /* LTR */
+  border-top: 1px solid #323232;
+}
+
+/* All list items */
+#admin-menu .dropdown li {
+  background-image: none;
+  float: left; /* LTR */
+  height: 100%;
+  list-style-image: none;
+  list-style-type: none;
+  margin: 0 !important;
+  padding: 0;
+}
+#admin-menu .dropdown .admin-menu-tab {
+  background: url(images/bkg_tab.png) repeat-x left bottom;
+  padding-bottom: 1px;
+}
+#admin-menu .dropdown li li {
+  background: #202020;
+  filter: Alpha(opacity=88);
+  float: none;
+  opacity: 0.88;
+  width: 160px; /* Required for Opera */
+}
+#admin-menu .dropdown li li li {
+  filter: Alpha(opacity=100);
+  opacity: 1;
+}
+
+/* Second-level lists */
+/* Note: We must hide sub-lists or scrollbars might appear (display: none is not read by screen readers). */
+#admin-menu .dropdown li ul {
+  background: none;
+  display: none;
+  left: -999em; /* LTR */
+  line-height: 1.2em;
+  margin: 0;
+  position: absolute;
+  width: 160px;
+}
+
+/* Third-and-above-level lists */
+#admin-menu .dropdown li li.expandable ul {
+  margin: -20px 0 0 160px; /* LTR */
+}
+
+#admin-menu .dropdown li:hover ul ul,
+#admin-menu .dropdown li:hover ul ul ul,
+#admin-menu .dropdown li:hover ul ul ul ul,
+#admin-menu .dropdown li:hover ul ul ul ul ul {
+  display: none;
+  left: -999em; /* LTR */
+}
+
+/* Lists nested under hovered list items */
+#admin-menu .dropdown li:hover ul,
+#admin-menu .dropdown li li:hover ul,
+#admin-menu .dropdown li li li:hover ul,
+#admin-menu .dropdown li li li li:hover ul,
+#admin-menu .dropdown li li li li li:hover ul {
+  display: block;
+  left: auto; /* LTR */
+}
+#admin-menu .dropdown li.admin-menu-action:hover ul {
+  right: 0; /* LTR */
+}
+
+/* Second-and-more-level hovering */
+#admin-menu .dropdown li li.expandable {
+  background: #45454A url(images/arrow.png) no-repeat 145px 6px;
+}
+#admin-menu .dropdown li li:hover {
+  background-color: #111;
+}
+#admin-menu .dropdown li li:hover a,
+#admin-menu .dropdown li li:hover li:hover a,
+#admin-menu .dropdown li li:hover li:hover li:hover a {
+  color: #FFF;
+}
+#admin-menu .dropdown li li.expandable:hover a,
+#admin-menu .dropdown li li.expandable:hover li.expandable:hover a {
+  border-color: #444;
+  color: #EEE;
+}
+#admin-menu .dropdown li li.expandable:hover li a,
+#admin-menu .dropdown li li.expandable:hover li.expandable:hover li a {
+  border-color: #323232;
+}
+#admin-menu .dropdown li li:hover li a {
+  color: #EEE;
+}
+
+/* Search form */
+#admin-menu .admin-menu-search .form-item {
+  margin: 0;
+  padding: 0;
+}
+#admin-menu .admin-menu-search input {
+  background: #fff none center right no-repeat;
+  border: none;
+  -webkit-border-radius: 5px;
+  -moz-border-radius: 5px;
+  border-radius: 5px;
+  font-size: 10px;
+  margin: 1px 0;
+  outline: none;
+  padding: 2px 22px 2px 4px;
+  width: 158px;
+}
+
+#admin-menu .dropdown .admin-menu-search-results {
+  display: block !important;
+  left: auto !important;
+  top: 100%;
+}
+#admin-menu .admin-menu-search-results,
+#admin-menu .admin-menu-search-results li {
+  width: 186px;
+}
+
+#admin-menu li.highlight {
+  background-color: #eee !important;
+}
+#admin-menu li.highlight > a {
+  border-color: #ccc !important;
+  color: #111 !important;
+}
+
+/* #210615: Mozilla on Mac fix */
+html.js fieldset.collapsible div.fieldset-wrapper {
+  overflow: visible;
+}
+
+/* Hide the menu on print output. */
+@media print {
+  #admin-menu {
+    display: none !important;
+  }
+  body.admin-menu {
+    margin-top: 0 !important;
+  }
+}
+
+/**
+ * Tweaks permissions, if enabled.
+ */
+tr.admin-menu-tweak-permissions-processed {
+  cursor: pointer;
+  cursor: hand;
+}
+tr.admin-menu-tweak-permissions-processed td.module {
+  border-top: 0;
+}

+ 910 - 0
sites/all/modules/admin_menu/admin_menu.inc

@@ -0,0 +1,910 @@
+<?php
+
+/**
+ * @file
+ * Menu builder functions for Administration menu.
+ */
+
+/**
+ * Build the full administration menu tree from static and expanded dynamic items.
+ *
+ * @param $menu_name
+ *   The menu name to use as base for the tree.
+ */
+function admin_menu_tree($menu_name) {
+  // Get placeholder expansion arguments from hook_admin_menu_map()
+  // implementations.
+  module_load_include('inc', 'admin_menu', 'admin_menu.map');
+  $expand_map = module_invoke_all('admin_menu_map');
+  // Allow modules to alter the expansion map.
+  drupal_alter('admin_menu_map', $expand_map);
+
+  $new_map = array();
+  foreach ($expand_map as $path => $data) {
+    // Convert named placeholders to anonymous placeholders, since the menu
+    // system stores paths using anonymous placeholders.
+    $replacements = array_fill_keys(array_keys($data['arguments'][0]), '%');
+    $data['parent'] = strtr($data['parent'], $replacements);
+    $new_map[strtr($path, $replacements)] = $data;
+  }
+  $expand_map = $new_map;
+  unset($new_map);
+
+  // Retrieve dynamic menu link tree for the expansion mappings.
+  // @todo Skip entire processing if initial $expand_map is empty and directly
+  //   return $tree?
+  if (!empty($expand_map)) {
+    $tree_dynamic = admin_menu_tree_dynamic($expand_map);
+  }
+  else {
+    $tree_dynamic = array();
+  }
+
+  // Merge local tasks with static menu tree.
+  $tree = menu_tree_all_data($menu_name);
+  admin_menu_merge_tree($tree, $tree_dynamic, array());
+
+  return $tree;
+}
+
+/**
+ * Load menu link trees for router paths containing dynamic arguments.
+ *
+ * @param $expand_map
+ *   An array containing menu router path placeholder expansion argument
+ *   mappings.
+ *
+ * @return
+ *   An associative array whose keys are the parent paths of the menu router
+ *   paths given in $expand_map as well as the parent paths of any child link
+ *   deeper down the tree. The parent paths are used in admin_menu_merge_tree()
+ *   to check whether anything needs to be merged.
+ *
+ * @see hook_admin_menu_map()
+ */
+function admin_menu_tree_dynamic(array $expand_map) {
+  $p_columns = array();
+  for ($i = 1; $i <= MENU_MAX_DEPTH; $i++) {
+    $p_columns[] = 'p' . $i;
+  }
+
+  // Fetch p* columns for all router paths to expand.
+  $router_paths = array_keys($expand_map);
+  $plids = db_select('menu_links', 'ml')
+    ->fields('ml', $p_columns)
+    ->condition('router_path', $router_paths)
+    ->execute()
+    ->fetchAll(PDO::FETCH_ASSOC);
+
+  // Unlikely, but possible.
+  if (empty($plids)) {
+    return array();
+  }
+
+  // Use queried plid columns to query sub-trees for the router paths.
+  $query = db_select('menu_links', 'ml');
+  $query->join('menu_router', 'm', 'ml.router_path = m.path');
+  $query
+    ->fields('ml')
+    ->fields('m', array_diff(drupal_schema_fields_sql('menu_router'), drupal_schema_fields_sql('menu_links')));
+
+  // The retrieved menu link trees have to be ordered by depth, so parents
+  // always come before their children for the storage logic below.
+  foreach ($p_columns as $column) {
+    $query->orderBy($column, 'ASC');
+  }
+
+  $db_or = db_or();
+  foreach ($plids as $path_plids) {
+    $db_and = db_and();
+    // plids with value 0 may be ignored.
+    foreach (array_filter($path_plids) as $column => $plid) {
+      $db_and->condition($column, $plid);
+    }
+    $db_or->condition($db_and);
+  }
+  $query->condition($db_or);
+  $result = $query
+    ->execute()
+    ->fetchAllAssoc('mlid', PDO::FETCH_ASSOC);
+
+  // Store dynamic links grouped by parent path for later merging and assign
+  // placeholder expansion arguments.
+  $tree_dynamic = array();
+  foreach ($result as $mlid => $link) {
+    // If contained in $expand_map, then this is a (first) parent, and we need
+    // to store by the defined 'parent' path for later merging, as well as
+    // provide the expansion map arguments to apply to the dynamic tree.
+    if (isset($expand_map[$link['path']])) {
+      $parent_path = $expand_map[$link['path']]['parent'];
+      $link['expand_map'] = $expand_map[$link['path']]['arguments'];
+    }
+    // Otherwise, just store this link keyed by its parent path; the expand_map
+    // is automatically derived from parent paths.
+    else {
+      $parent_path = $result[$link['plid']]['path'];
+    }
+
+    $tree_dynamic[$parent_path][] = $link;
+  }
+
+  return $tree_dynamic;
+}
+
+/**
+ * Walk through the entire menu tree and merge in expanded dynamic menu links.
+ *
+ * @param &$tree
+ *   A menu tree structure as returned by menu_tree_all_data().
+ * @param $tree_dynamic
+ *   A dynamic menu tree structure as returned by admin_menu_tree_dynamic().
+ * @param $expand_map
+ *   An array containing menu router path placeholder expansion argument
+ *   mappings.
+ *
+ * @see hook_admin_menu_map()
+ * @see admin_menu_tree_dynamic()
+ * @see menu_tree_all_data()
+ */
+function admin_menu_merge_tree(array &$tree, array $tree_dynamic, array $expand_map) {
+  foreach ($tree as $key => $data) {
+    $path = $data['link']['router_path'];
+
+    // Recurse into regular menu tree.
+    if ($tree[$key]['below']) {
+      admin_menu_merge_tree($tree[$key]['below'], $tree_dynamic, $expand_map);
+    }
+    // Nothing to merge, if this parent path is not in our dynamic tree.
+    if (!isset($tree_dynamic[$path])) {
+      continue;
+    }
+
+    // Add expanded dynamic items.
+    foreach ($tree_dynamic[$path] as $link) {
+      // If the dynamic item has custom placeholder expansion parameters set,
+      // use them, otherwise keep current.
+      if (isset($link['expand_map'])) {
+        // If there are currently no expansion parameters, we may use the new
+        // set immediately.
+        if (empty($expand_map)) {
+          $current_expand_map = $link['expand_map'];
+        }
+        else {
+          // Otherwise we need to filter out elements that differ from the
+          // current set, i.e. that are not in the same path.
+          $current_expand_map = array();
+          foreach ($expand_map as $arguments) {
+            foreach ($arguments as $placeholder => $value) {
+              foreach ($link['expand_map'] as $new_arguments) {
+                // Skip the new argument if it doesn't contain the current
+                // replacement placeholders or if their values differ.
+                if (!isset($new_arguments[$placeholder]) || $new_arguments[$placeholder] != $value) {
+                  continue;
+                }
+                $current_expand_map[] = $new_arguments;
+              }
+            }
+          }
+        }
+      }
+      else {
+        $current_expand_map = $expand_map;
+      }
+
+      // Skip dynamic items without expansion parameters.
+      if (empty($current_expand_map)) {
+        continue;
+      }
+
+      // Expand anonymous to named placeholders.
+      // @see _menu_load_objects()
+      $path_args = explode('/', $link['path']);
+      $load_functions = unserialize($link['load_functions']);
+      if (is_array($load_functions)) {
+        foreach ($load_functions as $index => $function) {
+          if ($function) {
+            if (is_array($function)) {
+              list($function,) = each($function);
+            }
+            // Add the loader function name minus "_load".
+            $placeholder = '%' . substr($function, 0, -5);
+            $path_args[$index] = $placeholder;
+          }
+        }
+      }
+      $path_dynamic = implode('/', $path_args);
+
+      // Create new menu items using expansion arguments.
+      foreach ($current_expand_map as $arguments) {
+        // Create the cartesian product for all arguments and create new
+        // menu items for each generated combination thereof.
+        foreach (admin_menu_expand_args($arguments) as $replacements) {
+          $newpath = strtr($path_dynamic, $replacements);
+          // Skip this item, if any placeholder could not be replaced.
+          // Faster than trying to invoke _menu_translate().
+          if (strpos($newpath, '%') !== FALSE) {
+            continue;
+          }
+          $map = explode('/', $newpath);
+          $item = admin_menu_translate($link, $map);
+          // Skip this item, if the current user does not have access.
+          if (empty($item)) {
+            continue;
+          }
+          // Build subtree using current replacement arguments.
+          $new_expand_map = array();
+          foreach ($replacements as $placeholder => $value) {
+            $new_expand_map[$placeholder] = array($value);
+          }
+          admin_menu_merge_tree($item, $tree_dynamic, array($new_expand_map));
+          $tree[$key]['below'] += $item;
+        }
+      }
+    }
+    // Sort new subtree items.
+    ksort($tree[$key]['below']);
+  }
+}
+
+/**
+ * Translate an expanded router item into a menu link suitable for rendering.
+ *
+ * @param $router_item
+ *   A menu router item.
+ * @param $map
+ *   A path map with placeholders replaced.
+ */
+function admin_menu_translate($router_item, $map) {
+  _menu_translate($router_item, $map, TRUE);
+
+  // Run through hook_translated_menu_link_alter() to add devel information,
+  // if configured.
+  $router_item['menu_name'] = 'management';
+  // @todo Invoke as usual like _menu_link_translate().
+  admin_menu_translated_menu_link_alter($router_item, NULL);
+
+  if ($router_item['access']) {
+    // Override mlid to make this item unique; since these items are expanded
+    // from dynamic items, the mlid is always the same, so each item would
+    // replace any other.
+    // @todo Doing this instead leads to plenty of duplicate links below
+    //   admin/structure/menu; likely a hidden recursion problem.
+    // $router_item['mlid'] = $router_item['href'] . $router_item['mlid'];
+    $router_item['mlid'] = $router_item['href'];
+    // Turn menu callbacks into regular menu items to make them visible.
+    if ($router_item['type'] == MENU_CALLBACK) {
+      $router_item['type'] = MENU_NORMAL_ITEM;
+    }
+
+    // @see _menu_tree_check_access()
+    $key = (50000 + $router_item['weight']) . ' ' . $router_item['title'] . ' ' . $router_item['mlid'];
+    return array($key => array(
+      'link' => $router_item,
+      'below' => array(),
+    ));
+  }
+
+  return array();
+}
+
+/**
+ * Create the cartesian product of multiple varying sized argument arrays.
+ *
+ * @param $arguments
+ *   A two dimensional array of arguments.
+ *
+ * @see hook_admin_menu_map()
+ */
+function admin_menu_expand_args($arguments) {
+  $replacements = array();
+
+  // Initialize line cursors, move out array keys (placeholders) and assign
+  // numeric keys instead.
+  $i = 0;
+  $placeholders = array();
+  $new_arguments = array();
+  foreach ($arguments as $placeholder => $values) {
+    // Skip empty arguments.
+    if (empty($values)) {
+      continue;
+    }
+    $cursor[$i] = 0;
+    $placeholders[$i] = $placeholder;
+    $new_arguments[$i] = $values;
+    $i++;
+  }
+  $arguments = $new_arguments;
+  unset($new_arguments);
+
+  if ($rows = count($arguments)) {
+    do {
+      // Collect current argument from each row.
+      $row = array();
+      for ($i = 0; $i < $rows; ++$i) {
+        $row[$placeholders[$i]] = $arguments[$i][$cursor[$i]];
+      }
+      $replacements[] = $row;
+
+      // Increment cursor position.
+      $j = $rows - 1;
+      $cursor[$j]++;
+      while (!array_key_exists($cursor[$j], $arguments[$j])) {
+        // No more arguments left: reset cursor, go to next line and increment
+        // that cursor instead. Repeat until argument found or out of rows.
+        $cursor[$j] = 0;
+        if (--$j < 0) {
+          // We're done.
+          break 2;
+        }
+        $cursor[$j]++;
+      }
+    } while (1);
+  }
+
+  return $replacements;
+}
+
+/**
+ * Build the administration menu as renderable menu links.
+ *
+ * @param $tree
+ *   A data structure representing the administration menu tree as returned from
+ *   menu_tree_all_data().
+ *
+ * @return
+ *   The complete administration menu, suitable for theme_admin_menu_links().
+ *
+ * @see theme_admin_menu_links()
+ * @see admin_menu_menu_alter()
+ */
+function admin_menu_links_menu($tree) {
+  $links = array();
+  foreach ($tree as $data) {
+    // Skip items that are inaccessible, invisible, or link to their parent.
+    // (MENU_DEFAULT_LOCAL_TASK), and MENU_CALLBACK-alike items that should only
+    // appear in the breadcrumb.
+    if (!$data['link']['access'] || $data['link']['type'] & MENU_LINKS_TO_PARENT || $data['link']['type'] == MENU_VISIBLE_IN_BREADCRUMB || $data['link']['hidden'] == 1) {
+      continue;
+    }
+    // Hide 'Administer' and make child links appear on this level.
+    // @todo Make this configurable.
+    if ($data['link']['router_path'] == 'admin') {
+      if ($data['below']) {
+        $links = array_merge($links, admin_menu_links_menu($data['below']));
+      }
+      continue;
+    }
+    // Omit alias lookups.
+    $data['link']['localized_options']['alias'] = TRUE;
+    // Remove description to prevent mouseover tooltip clashes.
+    unset($data['link']['localized_options']['attributes']['title']);
+
+    // Make action links (typically "Add ...") appear first in dropdowns.
+    // They might appear first already, but only as long as there is no link
+    // that comes alphabetically first (e.g., a node type with label "Ad").
+    if ($data['link']['type'] & MENU_IS_LOCAL_ACTION) {
+      $data['link']['weight'] -= 1000;
+    }
+
+    $links[$data['link']['href']] = array(
+      '#title' => $data['link']['title'],
+      '#href' => $data['link']['href'],
+      '#options' => $data['link']['localized_options'],
+      '#weight' => $data['link']['weight'],
+    );
+
+    // Recurse to add any child links.
+    $children = array();
+    if ($data['below']) {
+      $children = admin_menu_links_menu($data['below']);
+      $links[$data['link']['href']] += $children;
+    }
+
+    // Handle links pointing to category/overview pages.
+    if ($data['link']['page_callback'] == 'system_admin_menu_block_page' || $data['link']['page_callback'] == 'system_admin_config_page') {
+      // Apply a marker for others to consume.
+      $links[$data['link']['href']]['#is_category'] = TRUE;
+      // Automatically hide empty categories.
+      // Check for empty children first for performance. Only when non-empty
+      // (typically 'admin/config'), check whether children are accessible.
+      if (empty($children) || !element_get_visible_children($children)) {
+        $links[$data['link']['href']]['#access'] = FALSE;
+      }
+    }
+  }
+  return $links;
+}
+
+/**
+ * Build icon menu links; mostly containing maintenance helpers.
+ *
+ * @see theme_admin_menu_links()
+ */
+function admin_menu_links_icon() {
+  $destination = drupal_get_destination();
+
+  $links = array(
+    '#theme' => 'admin_menu_links',
+    '#wrapper_attributes' => array('id' => 'admin-menu-icon'),
+    '#weight' => -100,
+  );
+  $links['icon'] = array(
+    '#title' => theme('admin_menu_icon'),
+    '#attributes' => array('class' => array('admin-menu-icon')),
+    '#href' => '<front>',
+    '#options' => array(
+      'html' => TRUE,
+    ),
+  );
+  // Add link to manually run cron.
+  $links['icon']['cron'] = array(
+    '#title' => t('Run cron'),
+    '#weight' => 50,
+    '#access' => user_access('administer site configuration'),
+    '#href' => 'admin/reports/status/run-cron',
+  );
+  // Add link to run update.php.
+  $links['icon']['update'] = array(
+    '#title' => t('Run updates'),
+    '#weight' => 50,
+    // @see update_access_allowed()
+    '#access' => $GLOBALS['user']->uid == 1 || !empty($GLOBALS['update_free_access']) || user_access('administer software updates'),
+    '#href' => base_path() . 'update.php',
+    '#options' => array(
+      'external' => TRUE,
+    ),
+  );
+  // Add link to drupal.org.
+  $links['icon']['drupal.org'] = array(
+    '#title' => 'Drupal.org',
+    '#weight' => 100,
+    '#access' => user_access('display drupal links'),
+    '#href' => 'http://drupal.org',
+  );
+  // Add links to project issue queues.
+  foreach (module_list(FALSE, TRUE) as $module) {
+    $info = drupal_parse_info_file(drupal_get_path('module', $module) . '/' . $module . '.info');
+    if (!isset($info['project']) || isset($links['icon']['drupal.org'][$info['project']])) {
+      continue;
+    }
+    $links['icon']['drupal.org'][$info['project']] = array(
+      '#title' => t('@project issue queue', array('@project' => $info['name'])),
+      '#weight' => ($info['project'] == 'drupal' ? -10 : 0),
+      '#href' => 'http://drupal.org/project/issues/' . $info['project'],
+      '#options' => array(
+        'query' => array('version' => (isset($info['core']) ? $info['core'] : 'All')),
+      ),
+    );
+  }
+  // Add items to flush caches.
+  $links['icon']['flush-cache'] = array(
+    '#title' => t('Flush all caches'),
+    '#weight' => 20,
+    '#access' => user_access('flush caches'),
+    '#href' => 'admin_menu/flush-cache',
+    '#options' => array(
+      'query' => $destination + array('token' => drupal_get_token('admin_menu/flush-cache')),
+    ),
+  );
+  $caches = module_invoke_all('admin_menu_cache_info');
+  foreach ($caches as $name => $cache) {
+    $links['icon']['flush-cache'][$name] = array(
+      '#title' => $cache['title'],
+      '#href' => 'admin_menu/flush-cache/' . $name,
+      '#options' => array(
+        'query' => $destination + array('token' => drupal_get_token('admin_menu/flush-cache/' . $name)),
+      ),
+    );
+  }
+
+  // Add Devel module menu links.
+  if (module_exists('devel')) {
+    $devel_tree = menu_build_tree('devel');
+    $devel_links = admin_menu_links_menu($devel_tree);
+    if (element_get_visible_children($devel_links)) {
+      $links['icon']['devel'] = array(
+        '#title' => t('Development'),
+        '#weight' => 30,
+      ) + $devel_links;
+    }
+  }
+
+  return $links;
+}
+
+/**
+ * Builds the account links.
+ *
+ * @see theme_admin_menu_links()
+ */
+function admin_menu_links_account() {
+  $links = array(
+    '#theme' => 'admin_menu_links',
+    '#wrapper_attributes' => array('id' => 'admin-menu-account'),
+    '#weight' => 100,
+  );
+  $links['account'] = array(
+    '#title' => format_username($GLOBALS['user']),
+    '#weight' => -99,
+    '#attributes' => array('class' => array('admin-menu-action', 'admin-menu-account')),
+    '#href' => 'user/' . $GLOBALS['user']->uid,
+  );
+  $links['logout'] = array(
+    '#title' => t('Log out'),
+    '#weight' => -100,
+    '#attributes' => array('class' => array('admin-menu-action')),
+    '#href' => 'user/logout',
+  );
+  // Add Devel module switch user links.
+  $switch_links = module_invoke('devel', 'switch_user_list');
+  if (!empty($switch_links) && count($switch_links) > 1) {
+    foreach ($switch_links as $uid => $link) {
+      $links['account'][$link['title']] = array(
+        '#title' => $link['title'],
+        '#description' => $link['attributes']['title'],
+        '#href' => $link['href'],
+        '#options' => array(
+          'query' => $link['query'],
+          'html' => !empty($link['html']),
+        ),
+      );
+    }
+  }
+  return $links;
+}
+
+/**
+ * Builds user counter.
+ *
+ * @see theme_admin_menu_links()
+ */
+function admin_menu_links_users() {
+  $links = array(
+    '#theme' => 'admin_menu_links',
+    '#wrapper_attributes' => array('id' => 'admin-menu-users'),
+    '#weight' => 150,
+  );
+  // Add link to show current authenticated/anonymous users.
+  $links['user-counter'] = array(
+    '#title' => admin_menu_get_user_count(),
+    '#description' => t('Current anonymous / authenticated users'),
+    '#weight' => -90,
+    '#attributes' => array('class' => array('admin-menu-action', 'admin-menu-users')),
+    '#href' => (user_access('administer users') ? 'admin/people/people' : 'user'),
+  );
+  return $links;
+}
+
+/**
+ * Build search widget.
+ *
+ * @see theme_admin_menu_links()
+ */
+function admin_menu_links_search() {
+  $links = array(
+    '#theme' => 'admin_menu_links',
+    '#wrapper_attributes' => array('id' => 'admin-menu-search'),
+    '#weight' => 180,
+  );
+  $links['search'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Search'),
+    '#title_display' => 'attribute',
+    '#attributes' => array(
+      'placeholder' => t('Search'),
+      'class' => array('admin-menu-search'),
+    ),
+  );
+  return $links;
+}
+
+/**
+ * Form builder function for module settings.
+ */
+function admin_menu_theme_settings() {
+  $form['admin_menu_margin_top'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Adjust top margin'),
+    '#default_value' => variable_get('admin_menu_margin_top', 1),
+    '#description' => t('Shifts the site output down by approximately 20 pixels from the top of the viewport. If disabled, absolute- or fixed-positioned page elements may be covered by the administration menu.'),
+  );
+  $form['admin_menu_position_fixed'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Keep menu at top of page'),
+    '#default_value' => variable_get('admin_menu_position_fixed', 1),
+    '#description' => t('Displays the administration menu always at the top of the browser viewport (even when scrolling the page).'),
+  );
+  // @todo Re-confirm this with latest browser versions.
+  $form['admin_menu_position_fixed']['#description'] .= '<br /><strong>' . t('In some browsers, this setting may result in a malformed page, an invisible cursor, non-selectable elements in forms, or other issues.') . '</strong>';
+
+  $form['advanced'] = array(
+    '#type' => 'vertical_tabs',
+    '#title' => t('Advanced settings'),
+  );
+
+  $form['plugins'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Plugins'),
+    '#group' => 'advanced',
+  );
+  $form['plugins']['admin_menu_components'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Enabled components'),
+    '#options' => array(
+      'admin_menu.icon' => t('Icon menu'),
+      'admin_menu.menu' => t('Administration menu'),
+      'admin_menu.search' => t('Search bar'),
+      'admin_menu.users' => t('User counts'),
+      'admin_menu.account' => t('Account links'),
+    ),
+  );
+  $form['plugins']['admin_menu_components']['#default_value'] = array_keys(array_filter(variable_get('admin_menu_components', $form['plugins']['admin_menu_components']['#options'])));
+
+  $process = element_info_property('checkboxes', '#process', array());
+  $form['plugins']['admin_menu_components']['#process'] = array_merge(array('admin_menu_settings_process_components'), $process);
+  $form['#attached']['js'][] = drupal_get_path('module', 'admin_menu') . '/admin_menu.admin.js';
+
+  $form['tweaks'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('System tweaks'),
+    '#group' => 'advanced',
+  );
+  $form['tweaks']['admin_menu_tweak_modules'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Collapse module groups on the <a href="!modules-url">%modules</a> page', array(
+      '%modules' => t('Modules'),
+      '!modules-url' => url('admin/modules'),
+    )),
+    '#default_value' => variable_get('admin_menu_tweak_modules', 0),
+  );
+  if (module_exists('util')) {
+    $form['tweaks']['admin_menu_tweak_modules']['#description'] .= '<br /><strong>' . t('If the Utility module was installed for this purpose, it can be safely disabled and uninstalled.') . '</strong>';
+  }
+  $form['tweaks']['admin_menu_tweak_permissions'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Collapse module groups on the <a href="@permissions-url">%permissions</a> page', array(
+      '%permissions' => t('Permissions'),
+      '@permissions-url' => url('admin/people/permissions'),
+    )),
+    '#default_value' => variable_get('admin_menu_tweak_permissions', 0),
+  );
+  $form['tweaks']['admin_menu_tweak_tabs'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Move local tasks into menu'),
+    '#default_value' => variable_get('admin_menu_tweak_tabs', 0),
+    '#description' => t('Moves the tabs on all pages into the administration menu. Only possible for themes using the CSS classes <code>tabs primary</code> and <code>tabs secondary</code>.'),
+  );
+
+  $form['performance'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Performance'),
+    '#group' => 'advanced',
+  );
+  $form['performance']['admin_menu_cache_client'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Cache menu in client-side browser'),
+    '#default_value' => variable_get('admin_menu_cache_client', 1),
+  );
+
+  return system_settings_form($form);
+}
+
+/**
+ * #process callback for component plugin form element in admin_menu_theme_settings().
+ */
+function admin_menu_settings_process_components($element) {
+  // Assign 'rel' attributes to all options to achieve a live preview.
+  // Unfortunately, #states relies on wrapping .form-wrapper classes, so it
+  // cannot be used here.
+  foreach ($element['#options'] as $key => $label) {
+    if (!isset($element[$key]['#attributes']['rel'])) {
+      $id = preg_replace('/[^a-z]/', '-', $key);
+      $element[$key]['#attributes']['rel'] = '#' . $id;
+    }
+  }
+  return $element;
+}
+
+/**
+ * Form validation handler for admin_menu_theme_settings().
+ */
+function admin_menu_theme_settings_validate(&$form, &$form_state) {
+  // Change the configured components to Boolean values.
+  foreach ($form_state['values']['admin_menu_components'] as $component => &$enabled) {
+    $enabled = (bool) $enabled;
+  }
+}
+
+/**
+ * Implementation of hook_form_FORM_ID_alter().
+ *
+ * Extends Devel module with Administration menu developer settings.
+ */
+function _admin_menu_form_devel_admin_settings_alter(&$form, $form_state) {
+  // Shift system_settings_form buttons.
+  $weight = isset($form['buttons']['#weight']) ? $form['buttons']['#weight'] : 0;
+  $form['buttons']['#weight'] = $weight + 1;
+
+  $form['admin_menu'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Administration menu settings'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+  );
+  $display_options = array('mid', 'weight', 'pid');
+  $display_options = array(0 => t('None'), 'mlid' => t('Menu link ID'), 'weight' => t('Weight'), 'plid' => t('Parent link ID'));
+  $form['admin_menu']['admin_menu_display'] = array(
+    '#type' => 'radios',
+    '#title' => t('Display additional data for each menu item'),
+    '#default_value' => variable_get('admin_menu_display', 0),
+    '#options' => $display_options,
+    '#description' => t('Display the selected items next to each menu item link.'),
+  );
+  $form['admin_menu']['admin_menu_show_all'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Display all menu items'),
+    '#default_value' => variable_get('admin_menu_show_all', 0),
+    '#description' => t('If enabled, all menu items are displayed regardless of your site permissions. <em>Note: Do not enable on a production site.</em>'),
+  );
+}
+
+/**
+ * Flush all caches or a specific one.
+ *
+ * @param $name
+ *   (optional) Name of cache to flush.
+ */
+function admin_menu_flush_cache($name = NULL) {
+  if (!isset($_GET['token']) || !drupal_valid_token($_GET['token'], current_path())) {
+    return MENU_ACCESS_DENIED;
+  }
+  if (isset($name)) {
+    $caches = module_invoke_all('admin_menu_cache_info');
+    if (!isset($caches[$name])) {
+      return MENU_NOT_FOUND;
+    }
+  }
+  else {
+    $caches[$name] = array(
+      'title' => t('Every'),
+      'callback' => 'drupal_flush_all_caches',
+    );
+  }
+  // Pass the cache to flush forward to the callback.
+  $function = $caches[$name]['callback'];
+  $function($name);
+
+  drupal_set_message(t('!title cache cleared.', array('!title' => $caches[$name]['title'])));
+
+  // The JavaScript injects a destination request parameter pointing to the
+  // originating page, so the user is redirected back to that page. Without
+  // destination parameter, the redirect ends on the front page.
+  drupal_goto();
+}
+
+/**
+ * Implements hook_admin_menu_cache_info().
+ */
+function admin_menu_admin_menu_cache_info() {
+  $caches['admin_menu'] = array(
+    'title' => t('Administration menu'),
+    'callback' => '_admin_menu_flush_cache',
+  );
+  return $caches;
+}
+
+/**
+ * Implements hook_admin_menu_cache_info() on behalf of System module.
+ */
+function system_admin_menu_cache_info() {
+  $caches = array(
+    'assets' => t('CSS and JavaScript'),
+    'cache' => t('Page and else'),
+    'menu' => t('Menu'),
+    'registry' => t('Class registry'),
+    'theme' => t('Theme registry'),
+  );
+  foreach ($caches as $name => $cache) {
+    $caches[$name] = array(
+      'title' => $cache,
+      'callback' => '_admin_menu_flush_cache',
+    );
+  }
+  return $caches;
+}
+
+/**
+ * Implements hook_admin_menu_cache_info() on behalf of Update module.
+ */
+function update_admin_menu_cache_info() {
+  $caches['update'] = array(
+    'title' => t('Update data'),
+    'callback' => '_update_cache_clear',
+  );
+  return $caches;
+}
+
+/**
+ * Flush all caches or a specific one.
+ *
+ * @param $name
+ *   (optional) Name of cache to flush.
+ *
+ * @see system_admin_menu_cache_info()
+ */
+function _admin_menu_flush_cache($name = NULL) {
+  switch ($name) {
+    case 'admin_menu':
+      admin_menu_flush_caches();
+      break;
+
+    case 'menu':
+      menu_rebuild();
+      break;
+
+    case 'registry':
+      registry_rebuild();
+      // Fall-through to clear cache tables, since registry information is
+      // usually the base for other data that is cached (e.g. SimpleTests).
+    case 'cache':
+      // Don't clear cache_form - in-progress form submissions may break.
+      // Ordered so clearing the page cache will always be the last action.
+      // @see drupal_flush_all_caches()
+      $core = array('cache', 'cache_bootstrap', 'cache_filter', 'cache_page');
+      $cache_tables = array_merge(module_invoke_all('flush_caches'), $core);
+      foreach ($cache_tables as $table) {
+        cache_clear_all('*', $table, TRUE);
+      }
+      break;
+
+    case 'assets':
+      // Change query-strings on css/js files to enforce reload for all users.
+      _drupal_flush_css_js();
+
+      drupal_clear_css_cache();
+      drupal_clear_js_cache();
+
+      // Clear the page cache, since cached HTML pages might link to old CSS and
+      // JS aggregates.
+      cache_clear_all('*', 'cache_page', TRUE);
+      break;
+
+    case 'theme':
+      system_rebuild_theme_data();
+      drupal_theme_rebuild();
+      break;
+  }
+}
+
+/**
+ * Preprocesses variables for theme_admin_menu_icon().
+ */
+function template_preprocess_admin_menu_icon(&$variables) {
+  // Image source might have been passed in as theme variable.
+  if (!isset($variables['src'])) {
+    if (theme_get_setting('toggle_favicon')) {
+      $variables['src'] = theme_get_setting('favicon');
+    }
+    else {
+      $variables['src'] = base_path() . 'misc/favicon.ico';
+    }
+  }
+  // Strip the protocol without delimiters for transient HTTP/HTTPS support.
+  // Since the menu is cached on the server-side and client-side, the cached
+  // version might contain a HTTP link, whereas the actual page is on HTTPS.
+  // Relative paths will work fine, but theme_get_setting() returns an
+  // absolute URI.
+  $variables['src'] = preg_replace('@^https?:@', '', $variables['src']);
+  $variables['src'] = check_plain($variables['src']);
+  $variables['alt'] = t('Home');
+}
+
+/**
+ * Renders an icon to display in the administration menu.
+ *
+ * @ingroup themeable
+ */
+function theme_admin_menu_icon($variables) {
+  return '<img class="admin-menu-icon" src="' . $variables['src'] . '" width="16" height="16" alt="' . $variables['alt'] . '" />';
+}
+

+ 16 - 0
sites/all/modules/admin_menu/admin_menu.info

@@ -0,0 +1,16 @@
+name = Administration menu
+description = "Provides a dropdown menu to most administrative tasks and other common destinations (to users with the proper permissions)."
+package = Administration
+core = 7.x
+configure = admin/config/administration/admin_menu
+; Requires menu_build_tree() conditions; available after 7.10.
+; @see http://drupal.org/node/1025582
+dependencies[] = system (>7.10)
+files[] = tests/admin_menu.test
+
+; Information added by Drupal.org packaging script on 2014-12-19
+version = "7.x-3.0-rc5"
+core = "7.x"
+project = "admin_menu"
+datestamp = "1419029284"
+

+ 123 - 0
sites/all/modules/admin_menu/admin_menu.install

@@ -0,0 +1,123 @@
+<?php
+
+/**
+ * @file
+ * Install, update, and uninstall functions for the admin menu module.
+ */
+
+/**
+ * Implements hook_schema().
+ */
+function admin_menu_schema() {
+  $schema['cache_admin_menu'] = drupal_get_schema_unprocessed('system', 'cache');
+  $schema['cache_admin_menu']['description'] = 'Cache table for Administration menu to store client-side caching hashes.';
+  return $schema;
+}
+
+/**
+ * Implements hook_install().
+ */
+function admin_menu_install() {
+  // Increase the module weight, so admin_menu catches any alterations made by
+  // other modules in hook_menu_alter().
+  db_update('system')
+    ->fields(array('weight' => 100))
+    ->condition('type', 'module')
+    ->condition('name', 'admin_menu')
+    ->execute();
+}
+
+/**
+ * Implements hook_uninstall().
+ */
+function admin_menu_uninstall() {
+  // Delete variables.
+  variable_del('admin_menu_components');
+  variable_del('admin_menu_margin_top');
+  variable_del('admin_menu_position_fixed');
+  variable_del('admin_menu_tweak_modules');
+  variable_del('admin_menu_tweak_tabs');
+  variable_del('admin_menu_show_all');
+  variable_del('admin_menu_display');
+  variable_del('admin_menu_cache_server');
+  variable_del('admin_menu_cache_client');
+  // Unused variables still should be deleted.
+  variable_del('admin_menu_devel_modules');
+  variable_del('admin_menu_devel_modules_enabled');
+  variable_del('admin_menu_devel_modules_skip');
+}
+
+/**
+ * Ensure that admin_menu is rebuilt after upgrading to D6.
+ */
+function admin_menu_update_6000() {
+  // Drop the {admin_menu} table in admin_menu_update_6000() on sites that used
+  // one of the later patches in #132524.
+  if (db_table_exists('admin_menu')) {
+    db_drop_table('admin_menu');
+  }
+}
+
+/**
+ * Wipe and rebuild so we can switch the icon path to <front>.
+ */
+function admin_menu_update_6001() {
+  db_delete('menu_links')->condition('module', 'admin_menu')->execute();
+  menu_cache_clear('admin_menu');
+}
+
+/**
+ * Add {cache_admin_menu} table.
+ */
+function admin_menu_update_7300() {
+  if (!db_table_exists('cache_admin_menu')) {
+    $schema = drupal_get_schema_unprocessed('system', 'cache');
+    db_create_table('cache_admin_menu', $schema);
+  }
+}
+
+/**
+ * Increase the module weight.
+ *
+ * @see admin_menu_install()
+ */
+function admin_menu_update_7302() {
+  db_update('system')
+    ->fields(array('weight' => 100))
+    ->condition('type', 'module')
+    ->condition('name', 'admin_menu')
+    ->execute();
+}
+
+/**
+ * Remove local tasks from {menu_links} table.
+ */
+function admin_menu_update_7303() {
+  db_delete('menu_router')
+    ->condition('path', 'admin/%', 'LIKE')
+    ->condition('type', MENU_IS_LOCAL_TASK, '&')
+    ->execute();
+}
+
+/**
+ * Remove obsolete 'admin_menu' menu and all orphan links in it.
+ */
+function admin_menu_update_7304() {
+  // Remove the custom menu used by 6.x-1.x.
+  if (db_table_exists('menu_custom')) {
+    db_delete('menu_custom')->condition('menu_name', 'admin_menu')->execute();
+  }
+
+  // 6.x-1.x cloned the entire link structure below the path 'admin' into a
+  // separate 'menu_name' "admin_menu" with 'module' "admin_menu". 6.x-3.x and
+  // early alpha versions of 7.x-3.x still did something similar. All of these
+  // records are obsolete. Removal of the 'module' records (without different
+  // menu_name) is particularly important, since they would otherwise appear
+  // as duplicate links.
+  db_delete('menu_links')
+    ->condition(db_or()
+      ->condition('module', 'admin_menu')
+      ->condition('menu_name', 'admin_menu')
+    )
+    ->execute();
+}

+ 385 - 0
sites/all/modules/admin_menu/admin_menu.js

@@ -0,0 +1,385 @@
+(function($) {
+
+Drupal.admin = Drupal.admin || {};
+Drupal.admin.behaviors = Drupal.admin.behaviors || {};
+Drupal.admin.hashes = Drupal.admin.hashes || {};
+
+/**
+ * Core behavior for Administration menu.
+ *
+ * Test whether there is an administration menu is in the output and execute all
+ * registered behaviors.
+ */
+Drupal.behaviors.adminMenu = {
+  attach: function (context, settings) {
+    // Initialize settings.
+    settings.admin_menu = $.extend({
+      suppress: false,
+      margin_top: false,
+      position_fixed: false,
+      tweak_modules: false,
+      tweak_permissions: false,
+      tweak_tabs: false,
+      destination: '',
+      basePath: settings.basePath,
+      hash: 0,
+      replacements: {}
+    }, settings.admin_menu || {});
+    // Check whether administration menu should be suppressed.
+    if (settings.admin_menu.suppress) {
+      return;
+    }
+    var $adminMenu = $('#admin-menu:not(.admin-menu-processed)', context);
+    // Client-side caching; if administration menu is not in the output, it is
+    // fetched from the server and cached in the browser.
+    if (!$adminMenu.length && settings.admin_menu.hash) {
+      Drupal.admin.getCache(settings.admin_menu.hash, function (response) {
+          if (typeof response == 'string' && response.length > 0) {
+            $('body', context).append(response);
+          }
+          var $adminMenu = $('#admin-menu:not(.admin-menu-processed)', context);
+          // Apply our behaviors.
+          Drupal.admin.attachBehaviors(context, settings, $adminMenu);
+          // Allow resize event handlers to recalculate sizes/positions.
+          $(window).triggerHandler('resize');
+      });
+    }
+    // If the menu is in the output already, this means there is a new version.
+    else {
+      // Apply our behaviors.
+      Drupal.admin.attachBehaviors(context, settings, $adminMenu);
+    }
+  }
+};
+
+/**
+ * Collapse fieldsets on Modules page.
+ */
+Drupal.behaviors.adminMenuCollapseModules = {
+  attach: function (context, settings) {
+    if (settings.admin_menu.tweak_modules) {
+      $('#system-modules fieldset:not(.collapsed)', context).addClass('collapsed');
+    }
+  }
+};
+
+/**
+ * Collapse modules on Permissions page.
+ */
+Drupal.behaviors.adminMenuCollapsePermissions = {
+  attach: function (context, settings) {
+    if (settings.admin_menu.tweak_permissions) {
+      // Freeze width of first column to prevent jumping.
+      $('#permissions th:first', context).css({ width: $('#permissions th:first', context).width() });
+      // Attach click handler.
+      $modules = $('#permissions tr:has(td.module)', context).once('admin-menu-tweak-permissions', function () {
+        var $module = $(this);
+        $module.bind('click.admin-menu', function () {
+          // @todo Replace with .nextUntil() in jQuery 1.4.
+          $module.nextAll().each(function () {
+            var $row = $(this);
+            if ($row.is(':has(td.module)')) {
+              return false;
+            }
+            $row.toggleClass('element-hidden');
+          });
+        });
+      });
+      // Collapse all but the targeted permission rows set.
+      if (window.location.hash.length) {
+        $modules = $modules.not(':has(' + window.location.hash + ')');
+      }
+      $modules.trigger('click.admin-menu');
+    }
+  }
+};
+
+/**
+ * Apply margin to page.
+ *
+ * Note that directly applying marginTop does not work in IE. To prevent
+ * flickering/jumping page content with client-side caching, this is a regular
+ * Drupal behavior.
+ */
+Drupal.behaviors.adminMenuMarginTop = {
+  attach: function (context, settings) {
+    if (!settings.admin_menu.suppress && settings.admin_menu.margin_top) {
+      $('body:not(.admin-menu)', context).addClass('admin-menu');
+    }
+  }
+};
+
+/**
+ * Retrieve content from client-side cache.
+ *
+ * @param hash
+ *   The md5 hash of the content to retrieve.
+ * @param onSuccess
+ *   A callback function invoked when the cache request was successful.
+ */
+Drupal.admin.getCache = function (hash, onSuccess) {
+  if (Drupal.admin.hashes.hash !== undefined) {
+    return Drupal.admin.hashes.hash;
+  }
+  $.ajax({
+    cache: true,
+    type: 'GET',
+    dataType: 'text', // Prevent auto-evaluation of response.
+    global: false, // Do not trigger global AJAX events.
+    url: Drupal.settings.admin_menu.basePath.replace(/admin_menu/, 'js/admin_menu/cache/' + hash),
+    success: onSuccess,
+    complete: function (XMLHttpRequest, status) {
+      Drupal.admin.hashes.hash = status;
+    }
+  });
+};
+
+/**
+ * TableHeader callback to determine top viewport offset.
+ *
+ * @see toolbar.js
+ */
+Drupal.admin.height = function() {
+  var $adminMenu = $('#admin-menu');
+  var height = $adminMenu.outerHeight();
+  // In IE, Shadow filter adds some extra height, so we need to remove it from
+  // the returned height.
+  if ($adminMenu.css('filter') && $adminMenu.css('filter').match(/DXImageTransform\.Microsoft\.Shadow/)) {
+    height -= $adminMenu.get(0).filters.item("DXImageTransform.Microsoft.Shadow").strength;
+  }
+  return height;
+};
+
+/**
+ * @defgroup admin_behaviors Administration behaviors.
+ * @{
+ */
+
+/**
+ * Attach administrative behaviors.
+ */
+Drupal.admin.attachBehaviors = function (context, settings, $adminMenu) {
+  if ($adminMenu.length) {
+    $adminMenu.addClass('admin-menu-processed');
+    $.each(Drupal.admin.behaviors, function() {
+      this(context, settings, $adminMenu);
+    });
+  }
+};
+
+/**
+ * Apply 'position: fixed'.
+ */
+Drupal.admin.behaviors.positionFixed = function (context, settings, $adminMenu) {
+  if (settings.admin_menu.position_fixed) {
+    $adminMenu.addClass('admin-menu-position-fixed');
+    $adminMenu.css('position', 'fixed');
+  }
+};
+
+/**
+ * Move page tabs into administration menu.
+ */
+Drupal.admin.behaviors.pageTabs = function (context, settings, $adminMenu) {
+  if (settings.admin_menu.tweak_tabs) {
+    var $tabs = $(context).find('ul.tabs.primary');
+    $adminMenu.find('#admin-menu-wrapper > ul').eq(1)
+      .append($tabs.find('li').addClass('admin-menu-tab'));
+    $(context).find('ul.tabs.secondary')
+      .appendTo('#admin-menu-wrapper > ul > li.admin-menu-tab.active')
+      .removeClass('secondary');
+    $tabs.remove();
+  }
+};
+
+/**
+ * Perform dynamic replacements in cached menu.
+ */
+Drupal.admin.behaviors.replacements = function (context, settings, $adminMenu) {
+  for (var item in settings.admin_menu.replacements) {
+    $(item, $adminMenu).html(settings.admin_menu.replacements[item]);
+  }
+};
+
+/**
+ * Inject destination query strings for current page.
+ */
+Drupal.admin.behaviors.destination = function (context, settings, $adminMenu) {
+  if (settings.admin_menu.destination) {
+    $('a.admin-menu-destination', $adminMenu).each(function() {
+      this.search += (!this.search.length ? '?' : '&') + Drupal.settings.admin_menu.destination;
+    });
+  }
+};
+
+/**
+ * Apply JavaScript-based hovering behaviors.
+ *
+ * @todo This has to run last.  If another script registers additional behaviors
+ *   it will not run last.
+ */
+Drupal.admin.behaviors.hover = function (context, settings, $adminMenu) {
+  // Delayed mouseout.
+  $('li.expandable', $adminMenu).hover(
+    function () {
+      // Stop the timer.
+      clearTimeout(this.sfTimer);
+      // Display child lists.
+      $('> ul', this)
+        .css({left: 'auto', display: 'block'})
+        // Immediately hide nephew lists.
+        .parent().siblings('li').children('ul').css({left: '-999em', display: 'none'});
+    },
+    function () {
+      // Start the timer.
+      var uls = $('> ul', this);
+      this.sfTimer = setTimeout(function () {
+        uls.css({left: '-999em', display: 'none'});
+      }, 400);
+    }
+  );
+};
+
+/**
+ * Apply the search bar functionality.
+ */
+Drupal.admin.behaviors.search = function (context, settings, $adminMenu) {
+  // @todo Add a HTML ID.
+  var $input = $('input.admin-menu-search', $adminMenu);
+  // Initialize the current search needle.
+  var needle = $input.val();
+  // Cache of all links that can be matched in the menu.
+  var links;
+  // Minimum search needle length.
+  var needleMinLength = 2;
+  // Append the results container.
+  var $results = $('<div />').insertAfter($input);
+
+  /**
+   * Executes the search upon user input.
+   */
+  function keyupHandler() {
+    var matches, $html, value = $(this).val();
+    // Only proceed if the search needle has changed.
+    if (value !== needle) {
+      needle = value;
+      // Initialize the cache of menu links upon first search.
+      if (!links && needle.length >= needleMinLength) {
+        // @todo Limit to links in dropdown menus; i.e., skip menu additions.
+        links = buildSearchIndex($adminMenu.find('li:not(.admin-menu-action, .admin-menu-action li) > a'));
+      }
+      // Empty results container when deleting search text.
+      if (needle.length < needleMinLength) {
+        $results.empty();
+      }
+      // Only search if the needle is long enough.
+      if (needle.length >= needleMinLength && links) {
+        matches = findMatches(needle, links);
+        // Build the list in a detached DOM node.
+        $html = buildResultsList(matches);
+        // Display results.
+        $results.empty().append($html);
+      }
+    }
+  }
+
+  /**
+   * Builds the search index.
+   */
+  function buildSearchIndex($links) {
+    return $links
+      .map(function () {
+        var text = (this.textContent || this.innerText);
+        // Skip menu entries that do not contain any text (e.g., the icon).
+        if (typeof text === 'undefined') {
+          return;
+        }
+        return {
+          text: text,
+          textMatch: text.toLowerCase(),
+          element: this
+        };
+      });
+  }
+
+  /**
+   * Searches the index for a given needle and returns matching entries.
+   */
+  function findMatches(needle, links) {
+    var needleMatch = needle.toLowerCase();
+    // Select matching links from the cache.
+    return $.grep(links, function (link) {
+      return link.textMatch.indexOf(needleMatch) !== -1;
+    });
+  }
+
+  /**
+   * Builds the search result list in a detached DOM node.
+   */
+  function buildResultsList(matches) {
+    var $html = $('<ul class="dropdown admin-menu-search-results" />');
+    $.each(matches, function () {
+      var result = this.text;
+      var $element = $(this.element);
+
+      // Check whether there is a top-level category that can be prepended.
+      var $category = $element.closest('#admin-menu-wrapper > ul > li');
+      var categoryText = $category.find('> a').text()
+      if ($category.length && categoryText) {
+        result = categoryText + ': ' + result;
+      }
+
+      var $result = $('<li><a href="' + $element.attr('href') + '">' + result + '</a></li>');
+      $result.data('original-link', $(this.element).parent());
+      $html.append($result);
+    });
+    return $html;
+  }
+
+  /**
+   * Highlights selected result.
+   */
+  function resultsHandler(e) {
+    var $this = $(this);
+    var show = e.type === 'mouseenter' || e.type === 'focusin';
+    $this.trigger(show ? 'showPath' : 'hidePath', [this]);
+  }
+
+  /**
+   * Closes the search results and clears the search input.
+   */
+  function resultsClickHandler(e, link) {
+    var $original = $(this).data('original-link');
+    $original.trigger('mouseleave');
+    $input.val('').trigger('keyup');
+  }
+
+  /**
+   * Shows the link in the menu that corresponds to a search result.
+   */
+  function highlightPathHandler(e, link) {
+    if (link) {
+      var $original = $(link).data('original-link');
+      var show = e.type === 'showPath';
+      // Toggle an additional CSS class to visually highlight the matching link.
+      // @todo Consider using same visual appearance as regular hover.
+      $original.toggleClass('highlight', show);
+      $original.trigger(show ? 'mouseenter' : 'mouseleave');
+    }
+  }
+
+  // Attach showPath/hidePath handler to search result entries.
+  $results.delegate('li', 'mouseenter mouseleave focus blur', resultsHandler);
+  // Hide the result list after a link has been clicked, useful for overlay.
+  $results.delegate('li', 'click', resultsClickHandler);
+  // Attach hover/active highlight behavior to search result entries.
+  $adminMenu.delegate('.admin-menu-search-results li', 'showPath hidePath', highlightPathHandler);
+  // Attach the search input event handler.
+  $input.bind('keyup search', keyupHandler);
+};
+
+/**
+ * @} End of "defgroup admin_behaviors".
+ */
+
+})(jQuery);

+ 147 - 0
sites/all/modules/admin_menu/admin_menu.map.inc

@@ -0,0 +1,147 @@
+<?php
+
+/**
+ * @file
+ * Implements hook_admin_menu_map() on behalf of core modules.
+ *
+ * @todo Replace all/most of those API functions with direct DB queries;
+ *   we only need the menu arguments (keys), not fully loaded objects.
+ */
+
+/**
+ * Implements hook_admin_menu_map() on behalf of Filter module.
+ */
+function filter_admin_menu_map() {
+  if (!user_access('administer filters')) {
+    return;
+  }
+  $map['admin/config/content/formats/%filter_format'] = array(
+    'parent' => 'admin/config/content/formats',
+    'arguments' => array(
+      array('%filter_format' => array_keys(filter_formats())),
+    ),
+  );
+  return $map;
+}
+
+/**
+ * Implements hook_admin_menu_map() on behalf of Menu module.
+ */
+function menu_admin_menu_map() {
+  if (!user_access('administer menu')) {
+    return;
+  }
+  $map['admin/structure/menu/manage/%menu'] = array(
+    'parent' => 'admin/structure/menu',
+    'arguments' => array(
+      array('%menu' => array_keys(menu_get_menus())),
+    ),
+  );
+  return $map;
+}
+
+/**
+ * Implements hook_admin_menu_map() on behalf of Node module.
+ */
+function node_admin_menu_map() {
+  if (!user_access('administer content types')) {
+    return;
+  }
+  $map['admin/structure/types/manage/%node_type'] = array(
+    'parent' => 'admin/structure/types',
+    'arguments' => array(
+      array('%node_type' => array_keys(node_type_get_types())),
+    ),
+  );
+  return $map;
+}
+
+/**
+ * Implements hook_admin_menu_map() on behalf of Field UI module.
+ *
+ * @todo Figure out how to fix the comment entity bundle mappings.
+ */
+function field_ui_admin_menu_map() {
+  $map = array();
+
+  foreach (entity_get_info() as $entity_type => $entity_info) {
+    if (!$entity_info['fieldable']) {
+      continue;
+    }
+
+    foreach ($entity_info['bundles'] as $bundle => $bundle_info) {
+      // @see field_ui_menu()
+      if (!isset($bundle_info['admin'])) {
+        continue;
+      }
+
+      // Check access to this bundle.
+      $bundle_info['admin'] += array(
+        'access callback' => 'user_access',
+        'access arguments' => array('administer site configuration'),
+      );
+      if (!call_user_func_array($bundle_info['admin']['access callback'], $bundle_info['admin']['access arguments'])) {
+        continue;
+      }
+
+      if ($fields = field_info_instances($entity_type, $bundle)) {
+        $path = $bundle_info['admin']['path'];
+        $argument = array();
+        if (isset($bundle_info['admin']['bundle argument'])) {
+          $bundle_arg = arg($bundle_info['admin']['bundle argument'], $path);
+          $argument[$bundle_arg] = array($bundle);
+        }
+        $argument['%field_ui_menu'] = array_keys($fields);
+
+        if (!isset($map["$path/fields/%field_ui_menu"])) {
+          $map["$path/fields/%field_ui_menu"] = array(
+            'parent' => "$path/fields",
+            'arguments' => array(),
+          );
+        }
+        $map["$path/fields/%field_ui_menu"]['arguments'][] = $argument;
+      }
+    }
+  }
+
+  return $map;
+}
+
+/**
+ * Implements hook_admin_menu_map() on behalf of Taxonomy module.
+ */
+function taxonomy_admin_menu_map() {
+  if (!user_access('administer taxonomy')) {
+    return;
+  }
+  $map['admin/structure/taxonomy/%taxonomy_vocabulary_machine_name'] = array(
+    'parent' => 'admin/structure/taxonomy',
+    'arguments' => array(
+      array('%taxonomy_vocabulary_machine_name' => array_keys(taxonomy_vocabulary_get_names())),
+    ),
+  );
+  return $map;
+}
+
+/**
+ * Implements hook_admin_menu_map() on behalf of Views UI module.
+ */
+function views_ui_admin_menu_map() {
+  if (!user_access('administer views')) {
+    return;
+  }
+  $views = array();
+  foreach (views_get_enabled_views() as $name => $view) {
+    $views[] = $name;
+  }
+  if (empty($views)) {
+    return;
+  }
+  $map['admin/structure/views/view/%views_ui_cache'] = array(
+    'parent' => 'admin/structure/views',
+    'arguments' => array(
+      array('%views_ui_cache' => $views),
+    ),
+  );
+  return $map;
+}

File diff suppressed because it is too large
+ 852 - 0
sites/all/modules/admin_menu/admin_menu.module


+ 9 - 0
sites/all/modules/admin_menu/admin_menu.uid1.css

@@ -0,0 +1,9 @@
+
+/**
+ * @file
+ * Administration menu color override for uid1.
+ */
+
+#admin-menu li.admin-menu-account > a {
+  background: #911 url(images/bkg-red.png) bottom left repeat-x;
+}

+ 145 - 0
sites/all/modules/admin_menu/admin_menu_toolbar/admin_menu_toolbar.css

@@ -0,0 +1,145 @@
+
+/**
+ * @file
+ * Toolbar style for Administration menu.
+ *
+ * Important: We cannot re-use toolbar.png from Toolbar module, since we cannot
+ * reliably determine the path to it.
+ *
+ * @todo Separate shortcut functionality into own module/widget.
+ */
+
+/* Adjust margin/height */
+html body.admin-menu {
+  margin-top: 29px !important;
+}
+html body.admin-menu-with-shortcuts {
+  margin-top: 65px !important;
+}
+/* Displace the core Toolbar, if concurrently output. */
+body div#toolbar.toolbar {
+  top: 30px;
+}
+
+/**
+ * Base styles.
+ *
+ * We use a keyword for the toolbar font size to make it display consistently
+ * across different themes, while still allowing browsers to resize the text.
+ */
+#admin-menu {
+  font: normal small "Lucida Grande", Verdana, sans-serif;
+  -moz-box-shadow: 0 -10px 20px 13px #000;
+  -webkit-box-shadow: 0 -10px 20px 13px #000;
+  box-shadow: 0 -10px 20px 13px #000;
+  right: 0;
+  width: auto;
+}
+#admin-menu-wrapper {
+  font-size: .846em;
+  padding: 5px 10px 0;
+}
+
+#admin-menu .dropdown a {
+  color: #fafafa;
+}
+
+/* Remove border from all lists and actions */
+#admin-menu .dropdown .admin-menu-action a {
+  border-left: 0;
+}
+#admin-menu .dropdown .admin-menu-icon > a {
+  padding: 2px 10px 3px;
+}
+
+/**
+ * Administration menu.
+ */
+#admin-menu .dropdown .admin-menu-icon > a span {
+  vertical-align: text-bottom;
+  width: 11px;
+  height: 14px;
+  display: block;
+  background: url(toolbar.png) no-repeat 0 -45px;
+  text-indent: -9999px;
+}
+#admin-menu > div > .dropdown > li > a {
+  border-right: 0;
+  margin-bottom: 4px;
+  padding: 2px 10px 3px;
+}
+#admin-menu .dropdown .admin-menu-toolbar-category > a,
+#admin-menu .dropdown .admin-menu-action > a {
+  border-radius: 10px;
+  -moz-border-radius: 10px;
+  -webkit-border-radius: 10px;
+}
+#admin-menu .dropdown .admin-menu-toolbar-category > a.active-trail {
+  text-shadow: #333 0 1px 0;
+  background: url(toolbar.png) 0 0 repeat-x;
+}
+#admin-menu .dropdown .admin-menu-toolbar-category > a:hover {
+  background-color: #444;
+}
+#admin-menu .dropdown .admin-menu-tab a {
+  border-right: 0;
+}
+#admin-menu .dropdown li li.expandable ul {
+  margin: -22px 0 0 160px;
+}
+
+/**
+ * Shortcuts toggle.
+ */
+#admin-menu .shortcut-toggle {
+  cursor: pointer;
+  background: url(toolbar.png) 0 -20px no-repeat;
+  display: block;
+  float: right;
+  margin: 0 0 0 1.3em;
+  text-indent: -9999px;
+  overflow: hidden;
+  width: 25px;
+  height: 25px;
+}
+#admin-menu .shortcut-toggle:focus,
+#admin-menu .shortcut-toggle:hover {
+  background-position: -50px -20px;
+}
+#admin-menu .shortcut-toggle.active {
+  background-position: -25px -20px;
+}
+#admin-menu .shortcut-toggle.active:focus,
+#admin-menu .shortcut-toggle.active:hover {
+  background-position: -75px -20px;
+}
+
+/**
+ * Shortcuts widget.
+ */
+#admin-menu .shortcut-toolbar {
+  background-color: #666;
+  clear: both;
+  display: none;
+  margin: 0 -10px;
+  overflow: hidden;
+  /* Align with icon; @see shortcut.css */
+  padding-left: 5px;
+}
+#admin-menu .shortcut-toolbar.active {
+  display: block;
+}
+/* Override theme list style; @see shortcut.css */
+#admin-menu .shortcut-toolbar ul {
+  margin: 0;
+}
+/* @see toolbar.css */
+#admin-menu .shortcut-toolbar li {
+  float: left;
+  list-style-image: none;
+  list-style-type: none;
+}
+#admin-menu .shortcut-toolbar a {
+  display: block;
+}
+

+ 12 - 0
sites/all/modules/admin_menu/admin_menu_toolbar/admin_menu_toolbar.info

@@ -0,0 +1,12 @@
+name = Administration menu Toolbar style
+description = A better Toolbar.
+package = Administration
+core = 7.x
+dependencies[] = admin_menu
+
+; Information added by Drupal.org packaging script on 2014-12-19
+version = "7.x-3.0-rc5"
+core = "7.x"
+project = "admin_menu"
+datestamp = "1419029284"
+

+ 37 - 0
sites/all/modules/admin_menu/admin_menu_toolbar/admin_menu_toolbar.install

@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * @file
+ * Installation functionality for Administration menu toolbar module.
+ */
+
+/**
+ * Implements hook_install().
+ */
+function admin_menu_toolbar_install() {
+  // Required to load JS/CSS in hook_init() after admin_menu.
+  db_update('system')
+    ->fields(array('weight' => 101))
+    ->condition('type', 'module')
+    ->condition('name', 'admin_menu_toolbar')
+    ->execute();
+}
+
+/**
+ * Set module weight to a value higher than admin_menu.
+ *
+ * At this point, admin_menu should have a weight of 100. To account for
+ * customized weights, we increase the weight relatively.
+ *
+ * @see admin_menu_toolbar_install()
+ */
+function admin_menu_toolbar_update_6300() {
+  $weight = db_query("SELECT weight FROM {system} WHERE type = 'module' AND name = 'admin_menu'")->fetchField();
+  $weight++;
+  db_update('system')
+    ->fields(array('weight' => $weight))
+    ->condition('type', 'module')
+    ->condition('name', 'admin_menu_toolbar')
+    ->execute();
+}
+

+ 56 - 0
sites/all/modules/admin_menu/admin_menu_toolbar/admin_menu_toolbar.js

@@ -0,0 +1,56 @@
+(function($) {
+
+Drupal.admin = Drupal.admin || {};
+Drupal.admin.behaviors = Drupal.admin.behaviors || {};
+
+/**
+ * @ingroup admin_behaviors
+ * @{
+ */
+
+/**
+ * Apply active trail highlighting based on current path.
+ *
+ * @todo Not limited to toolbar; move into core?
+ */
+Drupal.admin.behaviors.toolbarActiveTrail = function (context, settings, $adminMenu) {
+  if (settings.admin_menu.toolbar && settings.admin_menu.toolbar.activeTrail) {
+    $adminMenu.find('> div > ul > li > a[href="' + settings.admin_menu.toolbar.activeTrail + '"]').addClass('active-trail');
+  }
+};
+
+/**
+ * Toggles the shortcuts bar.
+ */
+Drupal.admin.behaviors.shortcutToggle = function (context, settings, $adminMenu) {
+  var $shortcuts = $adminMenu.find('.shortcut-toolbar');
+  if (!$shortcuts.length) {
+    return;
+  }
+  var storage = window.localStorage || false;
+  var storageKey = 'Drupal.admin_menu.shortcut';
+  var $body = $(context).find('body');
+  var $toggle = $adminMenu.find('.shortcut-toggle');
+  $toggle.click(function () {
+    var enable = !$shortcuts.hasClass('active');
+    $shortcuts.toggleClass('active', enable);
+    $toggle.toggleClass('active', enable);
+    if (settings.admin_menu.margin_top) {
+      $body.toggleClass('admin-menu-with-shortcuts', enable);
+    }
+    // Persist toggle state across requests.
+    storage && enable ? storage.setItem(storageKey, 1) : storage.removeItem(storageKey);
+    this.blur();
+    return false;
+  });
+
+  if (!storage || storage.getItem(storageKey)) {
+    $toggle.trigger('click');
+  }
+};
+
+/**
+ * @} End of "ingroup admin_behaviors".
+ */
+
+})(jQuery);

+ 118 - 0
sites/all/modules/admin_menu/admin_menu_toolbar/admin_menu_toolbar.module

@@ -0,0 +1,118 @@
+<?php
+
+/**
+ * @file
+ * Renders Administration menu like Toolbar (core) module.
+ *
+ * @todo Separate shortcut functionality into own module/widget.
+ */
+
+/**
+ * Implements hook_form_FORMID_alter().
+ */
+function admin_menu_toolbar_form_admin_menu_theme_settings_alter(&$form) {
+  // Add the shortcut links as component on behalf of Shortcut module.
+  $form['plugins']['admin_menu_components']['#options']['shortcut.links'] = t('Shortcuts');
+  // The shortcut bar consists of two elements, so we target their class names
+  // instead of cluttering the markup with additional IDs.
+  $form['plugins']['admin_menu_components']['shortcut.links']['#attributes']['rel'] = '.shortcut-toggle, .shortcut-toolbar';
+}
+
+/**
+ * Implementation of hook_page_build().
+ */
+function admin_menu_toolbar_page_build(&$page) {
+  if (!isset($page['page_bottom']['admin_menu'])) {
+    return;
+  }
+  $path = drupal_get_path('module', 'admin_menu_toolbar');
+  $attached = &$page['page_bottom']['admin_menu']['#attached'];
+  $options = array('every_page' => TRUE);
+
+  $attached['css'][$path . '/admin_menu_toolbar.css'] = $options;
+  $attached['js'][$path . '/admin_menu_toolbar.js'] = $options;
+
+  // @todo Stop-gap fix until cached rendering is resolved.
+  // @see http://drupal.org/node/1567622
+  if (module_exists('shortcut')) {
+    $attached['css'][drupal_get_path('module', 'shortcut') . '/shortcut.css'] = $options;
+  }
+
+  $settings = array();
+  // Add current path to support menu item highlighting.
+  // @todo Compile real active trail here?
+  $args = explode('/', $_GET['q']);
+  if ($args[0] == 'admin' && !empty($args[1])) {
+    $settings['activeTrail'] = url($args[0] . '/' . $args[1]);
+  }
+  elseif (drupal_is_front_page()) {
+    $settings['activeTrail'] = url('<front>');
+  }
+
+  $attached['js'][] = array(
+    'data' => array('admin_menu' => array('toolbar' => $settings)),
+    'type' => 'setting',
+  );
+}
+
+/**
+ * Implements hook_admin_menu_output_build().
+ */
+function admin_menu_toolbar_admin_menu_output_build(&$content) {
+  if (empty($content['#components']['shortcut.links']) && !$content['#complete']) {
+    return;
+  }
+  // Add shortcuts toggle.
+  $content['shortcut-toggle'] = array(
+    '#access' => module_exists('shortcut'),
+    '#weight' => -200,
+    '#type' => 'link',
+    '#title' => t('Show shortcuts'),
+    '#href' => '',
+    '#options' => array(
+      'attributes' => array('class' => array('shortcut-toggle')),
+    ),
+  );
+
+  // Add shortcuts bar.
+  $content['shortcut'] = array(
+    '#access' => module_exists('shortcut'),
+    '#weight' => 200,
+    '#prefix' => '<div class="shortcut-toolbar">',
+    '#suffix' => '</div>',
+  );
+  $content['shortcut']['shortcuts'] = array(
+    // Shortcut module's CSS relies on Toolbar module's markup.
+    // @see http://drupal.org/node/1217038
+    '#prefix' => '<div id="toolbar">',
+    '#suffix' => '</div>',
+    // @todo Links may contain .active-trail classes.
+    '#pre_render' => array('shortcut_toolbar_pre_render'),
+  );
+}
+
+/**
+ * Implements hook_admin_menu_output_alter().
+ */
+function admin_menu_toolbar_admin_menu_output_alter(&$content) {
+  // Add a class to top-level items for styling.
+  if (isset($content['menu'])) {
+    foreach (element_children($content['menu']) as $link) {
+      $content['menu'][$link]['#attributes']['class'][] = 'admin-menu-toolbar-category';
+    }
+  }
+
+  // Alter icon.
+  if (isset($content['icon'])) {
+    unset($content['icon']['icon']['#theme']);
+    $content['icon']['icon']['#title'] = '<span>' . t('Home') . '</span>';
+    $content['icon']['icon']['#attributes']['class'][] = 'admin-menu-toolbar-category';
+  }
+
+  // Alter user account link.
+  if (isset($content['account'])) {
+    $content['account']['account']['#title'] = t('Hello <strong>@username</strong>', array('@username' => $content['account']['account']['#title']));
+    $content['account']['account']['#options']['html'] = TRUE;
+  }
+}
+

BIN
sites/all/modules/admin_menu/admin_menu_toolbar/toolbar.png


BIN
sites/all/modules/admin_menu/images/arrow-rtl.png


BIN
sites/all/modules/admin_menu/images/arrow.png


BIN
sites/all/modules/admin_menu/images/bkg-red.png


BIN
sites/all/modules/admin_menu/images/bkg.png


BIN
sites/all/modules/admin_menu/images/bkg_tab.png


BIN
sites/all/modules/admin_menu/images/icon_users.png


+ 520 - 0
sites/all/modules/admin_menu/tests/admin_menu.test

@@ -0,0 +1,520 @@
+<?php
+
+/**
+ * @file
+ * Tests for the Administration menu module.
+ */
+
+/**
+ * Base class for all administration menu web test cases.
+ */
+class AdminMenuWebTestCase extends DrupalWebTestCase {
+  protected $profile = 'testing';
+
+  protected $basePermissions = array(
+    'system' => 'access administration pages',
+    'admin_menu' => 'access administration menu',
+  );
+
+  function setUp() {
+    // Enable admin menu module and any other modules.
+    $modules = func_get_args();
+    $modules = isset($modules[0]) ? $modules[0] : $modules;
+    $modules[] = 'admin_menu';
+    parent::setUp($modules);
+
+    // Disable client-side caching.
+    variable_set('admin_menu_cache_client', FALSE);
+    // Disable Clean URLs to ensure drupal.org testbot compatibility.
+    variable_set('clean_url', 0);
+  }
+
+  /**
+   * Check that an element exists in HTML markup.
+   *
+   * @param $xpath
+   *   An XPath expression.
+   * @param array $arguments
+   *   (optional) An associative array of XPath replacement tokens to pass to
+   *   DrupalWebTestCase::buildXPathQuery().
+   * @param $message
+   *   The message to display along with the assertion.
+   * @param $group
+   *   The type of assertion - examples are "Browser", "PHP".
+   *
+   * @return
+   *   TRUE if the assertion succeeded, FALSE otherwise.
+   */
+  protected function assertElementByXPath($xpath, array $arguments = array(), $message, $group = 'Other') {
+    $elements = $this->xpath($xpath, $arguments);
+    return $this->assertTrue(!empty($elements[0]), $message, $group);
+  }
+
+  /**
+   * Check that an element does not exist in HTML markup.
+   *
+   * @param $xpath
+   *   An XPath expression.
+   * @param array $arguments
+   *   (optional) An associative array of XPath replacement tokens to pass to
+   *   DrupalWebTestCase::buildXPathQuery().
+   * @param $message
+   *   The message to display along with the assertion.
+   * @param $group
+   *   The type of assertion - examples are "Browser", "PHP".
+   *
+   * @return
+   *   TRUE if the assertion succeeded, FALSE otherwise.
+   */
+  protected function assertNoElementByXPath($xpath, array $arguments = array(), $message, $group = 'Other') {
+    $elements = $this->xpath($xpath, $arguments);
+    return $this->assertTrue(empty($elements), $message, $group);
+  }
+
+  /**
+   * Asserts that links appear in the menu in a specified trail.
+   *
+   * @param array $trail
+   *   A list of menu link titles to assert in the menu.
+   */
+  protected function assertLinkTrailByTitle(array $trail) {
+    $xpath = array();
+    $args = array();
+    $message = '';
+    foreach ($trail as $i => $title) {
+      $xpath[] = '/li/a[text()=:title' . $i . ']';
+      $args[':title' . $i] = $title;
+      $message .= ($i ? ' » ' : '') . check_plain($title);
+    }
+    $xpath = '//div[@id="admin-menu"]/div/ul' . implode('/parent::li/ul', $xpath);
+    $this->assertElementByXPath($xpath, $args, $message . ' link found.');
+  }
+
+  /**
+   * Asserts that no link appears in the menu for a specified trail.
+   *
+   * @param array $trail
+   *   A list of menu link titles to assert in the menu.
+   */
+  protected function assertNoLinkTrailByTitle(array $trail) {
+    $xpath = array();
+    $args = array();
+    $message = '';
+    foreach ($trail as $i => $title) {
+      $xpath[] = '/li/a[text()=:title' . $i . ']';
+      $args[':title' . $i] = $title;
+      $message .= ($i ? ' » ' : '') . check_plain($title);
+    }
+    $xpath = '//div[@id="admin-menu"]/div/ul' . implode('/parent::li/ul', $xpath);
+    $this->assertNoElementByXPath($xpath, $args, $message . ' link not found.');
+  }
+}
+
+/**
+ * Tests menu links depending on user permissions.
+ */
+class AdminMenuPermissionsTestCase extends AdminMenuWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Menu link access permissions',
+      'description' => 'Tests appearance of menu links depending on user permissions.',
+      'group' => 'Administration menu',
+    );
+  }
+
+  function setUp() {
+    parent::setUp(array('node'));
+  }
+
+  /**
+   * Test that the links are added to the page (no JS testing).
+   */
+  function testPermissions() {
+    module_enable(array('contact'));
+    $this->resetAll();
+
+    // Anonymous users should not see the menu.
+    $this->drupalGet('');
+    $this->assertNoElementByXPath('//div[@id="admin-menu"]', array(), t('Administration menu not found.'));
+
+    // Create a user who
+    // - can access content overview
+    // - cannot access drupal.org links
+    // - cannot administer Contact module
+    $permissions = $this->basePermissions + array(
+      'access content overview',
+    );
+    $admin_user = $this->drupalCreateUser($permissions);
+    $this->drupalLogin($admin_user);
+
+    // Check that the user can see the admin links, but not the drupal links.
+    $this->assertElementByXPath('//div[@id="admin-menu"]', array(), 'Administration menu found.');
+    $this->assertElementByXPath('//div[@id="admin-menu"]//a[contains(@href, :path)]', array(':path' => 'admin/content'), 'Content link found.');
+    $this->assertNoElementByXPath('//div[@id="admin-menu"]//a[@href=:path]', array(':path' => 'http://drupal.org'), 'Icon » Drupal.org link not found.');
+    $this->assertNoElementByXPath('//div[@id="admin-menu"]//a[contains(@href, :path)]', array(':path' => 'admin/structure/contact'), 'Structure » Contact link not found.');
+
+    // Create a user "reversed" to the above; i.e., who
+    // - cannot access content overview
+    // - can access drupal.org links
+    // - can administer Contact module
+    $permissions = $this->basePermissions + array(
+      'display drupal links',
+      'administer contact forms',
+    );
+    $admin_user2 = $this->drupalCreateUser($permissions);
+    $this->drupalLogin($admin_user2);
+    $this->assertElementByXPath('//div[@id="admin-menu"]', array(), 'Administration menu found.');
+    $this->assertNoElementByXPath('//div[@id="admin-menu"]//a[contains(@href, :path)]', array(':path' => 'admin/content'), 'Content link not found.');
+    $this->assertElementByXPath('//div[@id="admin-menu"]//a[@href=:path]', array(':path' => 'http://drupal.org'), 'Icon » Drupal.org link found.');
+    $this->assertElementByXPath('//div[@id="admin-menu"]//a[contains(@href, :path)]', array(':path' => 'admin/structure/contact'), 'Structure » Contact link found.');
+  }
+
+  /**
+   * Tests handling of links pointing to category/overview pages.
+   */
+  function testCategories() {
+    // Create a user with minimum permissions.
+    $admin_user = $this->drupalCreateUser($this->basePermissions);
+    $this->drupalLogin($admin_user);
+
+    // Verify that no category links appear.
+    $this->assertNoLinkTrailByTitle(array(t('Structure')));
+    $this->assertNoLinkTrailByTitle(array(t('Configuration')));
+
+    // Create a user with access to one configuration category.
+    $permissions = $this->basePermissions + array(
+      'administer users',
+    );
+    $admin_user = $this->drupalCreateUser($permissions);
+    $this->drupalLogin($admin_user);
+
+    // Verify that only expected category links appear.
+    $this->assertNoLinkTrailByTitle(array(t('Structure')));
+    $this->assertLinkTrailByTitle(array(t('People')));
+    $this->assertLinkTrailByTitle(array(t('Configuration')));
+    $this->assertLinkTrailByTitle(array(t('Configuration'), t('People')));
+    // Random picks are sufficient.
+    $this->assertNoLinkTrailByTitle(array(t('Configuration'), t('Media')));
+    $this->assertNoLinkTrailByTitle(array(t('Configuration'), t('System')));
+  }
+
+  /**
+   * Tests that user role and permission changes are properly taken up.
+   */
+  function testPermissionChanges() {
+    // Create a user who is able to change permissions.
+    $permissions = $this->basePermissions + array(
+      'administer permissions',
+    );
+    $admin_user = $this->drupalCreateUser($permissions);
+    $this->drupalLogin($admin_user);
+
+    // Extract the user role ID that was created for above permissions.
+    $rid = key(array_diff_key($admin_user->roles, array(DRUPAL_AUTHENTICATED_RID => 0)));
+
+    // Verify that Configuration does not appear.
+    $this->assertNoLinkTrailByTitle(array(t('Configuration')));
+    // Grant the 'administer site configuration' permission to ourselves.
+    $edit = array(
+      $rid . '[administer site configuration]' => TRUE,
+    );
+    $this->drupalPost('admin/people/permissions', $edit, t('Save permissions'));
+    // Verify that Configuration appears.
+    $this->assertLinkTrailByTitle(array(t('Configuration')));
+
+    // Verify that Structure » Content types does not appear.
+    $this->assertNoLinkTrailByTitle(array(t('Structure'), t('Content types')));
+    // Create a new role.
+    $edit = array(
+      'name' => 'test',
+    );
+    $this->drupalPost('admin/people/permissions/roles', $edit, t('Add role'));
+    // It should be safe to assume that the new role gets the next ID.
+    $test_rid = $rid + 1;
+    // Grant the 'administer content types' permission for the role.
+    $edit = array(
+      $test_rid . '[administer content types]' => TRUE,
+    );
+    $this->drupalPost('admin/people/permissions/' . $test_rid, $edit, t('Save permissions'));
+    // Verify that Structure » Content types does not appear.
+    $this->assertNoLinkTrailByTitle(array(t('Structure'), t('Content types')));
+
+    // Assign the role to ourselves.
+    $edit = array(
+      'roles[' . $test_rid . ']' => TRUE,
+    );
+    $this->drupalPost('user/' . $admin_user->uid . '/edit', $edit, t('Save'));
+    // Verify that Structure » Content types appears.
+    $this->assertLinkTrailByTitle(array(t('Structure'), t('Content types')));
+
+    // Delete the role.
+    $this->drupalPost('admin/people/permissions/roles/edit/' . $test_rid, array(), t('Delete role'));
+    $this->drupalPost(NULL, array(), t('Delete'));
+    // Verify that Structure » Content types does not appear.
+    $this->assertNoLinkTrailByTitle(array(t('Structure'), t('Content types')));
+  }
+}
+
+/**
+ * Tests appearance, localization, and escaping of dynamic links.
+ */
+class AdminMenuDynamicLinksTestCase extends AdminMenuWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Dynamic links',
+      'description' => 'Tests appearance, localization, and escaping of dynamic links.',
+      'group' => 'Administration menu',
+    );
+  }
+
+  function setUp() {
+    parent::setUp(array('node'));
+  }
+
+  /**
+   * Tests node type links.
+   */
+  function testNode() {
+    $type = $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
+    // Create a content-type with special characters.
+    $type = $this->drupalCreateContentType(array('type' => 'special', 'name' => 'Cool & Special'));
+
+    $permissions = $this->basePermissions + array(
+      'administer content types',
+      'create article content',
+      'create special content',
+    );
+    $this->admin_user = $this->drupalCreateUser($permissions);
+    $this->drupalLogin($this->admin_user);
+
+    // Verify that dynamic links are displayed.
+    $this->drupalGet('');
+    $this->assertElementByXPath('//div[@id="admin-menu"]', array(), t('Administration menu found.'));
+    $this->assertElementByXPath('//div[@id="admin-menu"]//a[contains(@href, :path)]', array(':path' => 'admin/structure/types'), "Structure » Content types link found.");
+
+    // Verify link title output escaping.
+    $this->assertNoRaw('Cool & Special');
+    $this->assertRaw(check_plain('Cool & Special'));
+
+    // Verify Manage content type links.
+    $links = array(
+      'admin/structure/types/manage/article' => 'Article',
+      'admin/structure/types/manage/special' => 'Cool & Special',
+    );
+    foreach ($links as $path => $title) {
+      $this->assertElementByXPath('//div[@id="admin-menu"]//a[contains(@href, :path) and text()=:title]', array(
+        ':path' => $path,
+        ':title' => $title,
+      ), "Structure » Content types » $title link found.");
+    }
+
+    // Verify Add content links.
+    $links = array(
+      'node/add/article' => 'Article',
+      'node/add/special' => 'Cool & Special',
+    );
+    foreach ($links as $path => $title) {
+      $this->assertElementByXPath('//div[@id="admin-menu"]//a[contains(@href, :path) and text()=:title]', array(
+        ':path' => $path,
+        ':title' => $title,
+      ), "Add content » $title link found.");
+    }
+  }
+
+  /**
+   * Tests Add content links.
+   */
+  function testNodeAdd() {
+    $type = $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
+
+    // Verify that "Add content" does not appear for unprivileged users.
+    $permissions = $this->basePermissions + array(
+      'access content',
+    );
+    $this->web_user = $this->drupalCreateUser($permissions);
+    $this->drupalLogin($this->web_user);
+    $this->assertNoText(t('Add content'));
+
+    // Verify "Add content" appears below "Content" for administrative users.
+    $permissions = $this->basePermissions + array(
+      'access content overview',
+      'access content',
+      'create article content',
+    );
+    $this->admin_user = $this->drupalCreateUser($permissions);
+    $this->drupalLogin($this->admin_user);
+    $this->assertLinkTrailByTitle(array(
+      t('Content'),
+      t('Add content'),
+    ));
+
+    // Verify "Add content" appears on the top-level for regular users.
+    $permissions = $this->basePermissions + array(
+      'access content',
+      'create article content',
+    );
+    $this->web_user = $this->drupalCreateUser($permissions);
+    $this->drupalLogin($this->web_user);
+    $this->assertLinkTrailByTitle(array(
+      t('Add content'),
+    ));
+  }
+}
+
+/**
+ * Tests appearance of different types of links.
+ */
+class AdminMenuLinkTypesTestCase extends AdminMenuWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Link types',
+      'description' => 'Tests appearance of different types of links.',
+      'group' => 'Administration menu',
+    );
+  }
+
+  function setUp() {
+    parent::setUp(array('help'));
+
+    $permissions = module_invoke_all('permission');
+    $permissions = array_keys($permissions);
+    $this->admin_user = $this->drupalCreateUser($permissions);
+    $this->drupalLogin($this->admin_user);
+  }
+
+  /**
+   * Tests appearance of different router item link types.
+   */
+  function testLinkTypes() {
+    // Verify that MENU_NORMAL_ITEMs appear.
+    $this->assertLinkTrailByTitle(array(
+      t('Configuration'),
+      t('System'),
+      t('Site information'),
+    ));
+
+    // Verify that MENU_LOCAL_TASKs appear.
+    $this->assertLinkTrailByTitle(array(t('People'), t('Permissions')));
+    $this->assertLinkTrailByTitle(array(t('Appearance'), t('Settings')));
+    $this->assertLinkTrailByTitle(array(t('Modules'), t('Uninstall')));
+
+    // Verify that MENU_LOCAL_ACTIONs appear.
+    $this->assertLinkTrailByTitle(array(
+      t('People'),
+      t('Add user'),
+    ));
+
+    // Verify that MENU_DEFAULT_LOCAL_TASKs do NOT appear.
+    $this->assertNoLinkTrailByTitle(array(t('Modules'), t('List')));
+    $this->assertNoLinkTrailByTitle(array(t('People'), t('List')));
+    $this->assertNoLinkTrailByTitle(array(t('People'), t('Permissions'), t('Permissions')));
+    $this->assertNoLinkTrailByTitle(array(t('Appearance'), t('List')));
+
+    // Verify that MENU_VISIBLE_IN_BREADCRUMB items (exact type) do NOT appear.
+    $this->assertNoLinkTrailByTitle(array(t('Modules'), t('Uninstall'), t('Uninstall')));
+    $this->assertNoLinkTrailByTitle(array(t('Help'), 'admin_menu'));
+
+    // Verify that special "Index" link appears below icon.
+    $this->assertElementByXPath('//div[@id="admin-menu"]//a[contains(@href, :path) and text()=:title]', array(
+      ':path' => 'admin/index',
+      ':title' => t('Index'),
+    ), "Icon » Index link found.");
+  }
+}
+
+/**
+ * Tests customized menu links.
+ */
+class AdminMenuCustomizedTestCase extends AdminMenuWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Customized links',
+      'description' => 'Tests customized menu links.',
+      'group' => 'Administration menu',
+    );
+  }
+
+  function setUp() {
+    parent::setUp(array('menu'));
+
+    $this->admin_user = $this->drupalCreateUser($this->basePermissions + array(
+      'administer menu',
+    ));
+    $this->drupalLogin($this->admin_user);
+  }
+
+  /**
+   * Test disabled custom links.
+   */
+  function testCustomDisabled() {
+    $type = $this->drupalCreateContentType();
+    $node = $this->drupalCreateNode(array('type' => $type->type));
+    $text = $this->randomName();
+    $xpath = $this->buildXPathQuery('//div[@id=:id]//a[contains(text(), :text)]', array(
+      ':id' => 'admin-menu',
+      ':text' => $text,
+    ));
+
+    // Verify that the link does not appear in the menu.
+    $this->drupalGet('node');
+    $elements = $this->xpath($xpath);
+    $this->assertFalse($elements, 'Custom link not found.');
+
+    // Add a custom link to the node to the menu.
+    $edit = array(
+      'link_path' => 'node/' . $node->nid,
+      'link_title' => $text,
+      'parent' => 'management:' . $this->queryMlidByPath('admin'),
+    );
+    $this->drupalPost('admin/structure/menu/manage/management/add', $edit, t('Save'));
+
+    // Verify that the link appears in the menu.
+    $this->drupalGet('node');
+    $elements = $this->xpath($xpath);
+    $this->assertTrue($elements, 'Custom link found.');
+
+    // Disable the link.
+    $edit = array(
+      'enabled' => FALSE,
+    );
+    $this->drupalPost('admin/structure/menu/item/' . $this->queryMlidByPath('node/' . $node->nid) . '/edit', $edit, t('Save'));
+
+    // Verify that the disabled link does not appear in the menu.
+    $this->drupalGet('node');
+    $elements = $this->xpath($xpath);
+    $this->assertFalse($elements, 'Disabled custom link not found.');
+  }
+
+  /**
+   * Tests external links.
+   */
+  function testCustomExternal() {
+    // Add a custom link to the node to the menu.
+    $edit = array(
+      'link_path' => 'http://example.com',
+      'link_title' => 'Example',
+      'parent' => 'management:' . $this->queryMlidByPath('admin'),
+    );
+    $this->drupalPost('admin/structure/menu/manage/management/add', $edit, t('Save'));
+
+    // Verify that the link appears in the menu.
+    $this->drupalGet('');
+    $elements = $this->xpath('//div[@id=:id]//a[@href=:href and contains(text(), :text)]', array(
+      ':id' => 'admin-menu',
+      ':href' => $edit['link_path'],
+      ':text' => $edit['link_title'],
+    ));
+    $this->assertTrue($elements, 'External link found.');
+  }
+
+  /**
+   * Returns the menu link ID for a given link path in the management menu.
+   */
+  protected function queryMlidByPath($path) {
+    return db_query('SELECT mlid FROM {menu_links} WHERE menu_name = :menu AND link_path = :path', array(
+      ':menu' => 'management',
+      ':path' => $path,
+    ))->fetchField();
+  }
+}
+