first import
This commit is contained in:
143
sites/all/modules/menu_block/CHANGELOG.txt
Normal file
143
sites/all/modules/menu_block/CHANGELOG.txt
Normal file
@@ -0,0 +1,143 @@
|
||||
Menu Block 7.x-2.x-dev, xxxx-xx-xx (development release)
|
||||
----------------------------------
|
||||
- #1524674 by Crell: Use of $_GET['q'] ignores menu_position module
|
||||
- #1688168 by tim.plunkett: Undefined index errors when using CTools content type and '_active' menu
|
||||
- #1701702: Disabled menu items still trigger "the menu selected by the page"
|
||||
|
||||
Menu Block 7.x-2.3, 2012-02-04
|
||||
------------------------------
|
||||
- #1105372 by mikl, fabsor and JohnAlbin: Add menu tree ctools content type to D7
|
||||
- #1425342 by JohnAlbin and Dave Reid: Menu block fails with Drupal core 7.12; remove work-around for core bug #942782.
|
||||
- #1243978 by Dave Reid: Fixed menu_block_export_menu() items were not translatable since they were not located in menu_block_export.module.
|
||||
- #1243978 by Dave Reid: Fixed menu_block_menu() items were not translatable since they were not located in menu_block.module.
|
||||
- by Dave Reid: Moved menu_block_menu_alter() to menu_block.menu so that it doesn't cause a module hook cache miss.
|
||||
- #1155052 by Dave Reid: Fixed errors if block module is not enabled.
|
||||
- #1162038 by Dave Reid: Fixed 'Add menu block' local action only appears on default theme.
|
||||
- #1114722 by dropcube: Fixed i18n menu support
|
||||
- #1154122 by Dave Reid: Moved block module hook implementations to menu_block.module to prevent problems with hook implementation caching.
|
||||
- #1078806 by Dave Reid: Fixed string untranslated warning from coder.
|
||||
- #1139530 by Dave Reid: Add a base form ID of block_add_block_form to menu_block_add_block_form so other modules can properly and easily alter it.
|
||||
- #1139522 by Dave Reid: Fixed fatal error with current page menu trees.
|
||||
|
||||
Menu Block 7.x-2.2, 2011-03-09
|
||||
------------------------------
|
||||
- #1086376: Custom menu fix doesn't work for new installations
|
||||
|
||||
Menu Block 7.x-2.1, 2011-02-06
|
||||
------------------------------
|
||||
- #1051988: Fix wrong path in menu_block_help()
|
||||
- #1050766: Improve usability of "Parent item" UI
|
||||
- #1050040 by AgentRickard: Remove performance-killing variable_set() calls on non-admin pages
|
||||
|
||||
Menu Block 7.x-2.0, 2011-01-11
|
||||
------------------------------
|
||||
- #1022478: Add "Edit book outline" contextual link for book menu blocks
|
||||
- #1022428: Contextual links for all menu blocks disappear if book menu_block used
|
||||
- #1017142: except for one menu, all other menus (including books) never receive an active trail
|
||||
- #1017122 by becw, mfer and JohnAlbin: Core bug work-around: add active trail to custom menus
|
||||
- Always show core menu blocks if they are in a region
|
||||
- #993998 by tgf: Core menu suppression broken
|
||||
- #993998 by jackinloadup: Delete links misplaced on menu list form
|
||||
- #958166 by Simon Georges and JohnAlbin: secondary-menu removed from core; replace with user-menu
|
||||
- #825132: Performance problem on sites with many books
|
||||
- #945714 by pedrochristopher: theme override misidentified in README
|
||||
- #593126: hook_get_menus() causes conflicts with Menu Access, og_menu, etc
|
||||
- #825132: Add hook_menu_block_get_sort_menus() for improved performance and UX of book integration
|
||||
- #957362 by blixxxa: Add Swedish translation
|
||||
- Fix theme hook suggestions for non-numeric block deltas
|
||||
|
||||
Menu Block 7.x-2.0-beta4, 2010-09-29
|
||||
------------------------------------
|
||||
- #891690: Never accept a fix not in patch form. And if you do, test it!
|
||||
|
||||
Menu Block 7.x-2.0-beta3, 2010-09-29
|
||||
------------------------------------
|
||||
- #891698 by Chris Gillis: Incorrect link to configuration page
|
||||
- #891690 by Chris Gillis: Undefined function db_fetch_array
|
||||
- Updated menu_block_get_title() to return a renderable array
|
||||
- Add #bid context to menu_link theme hook
|
||||
|
||||
Menu Block 7.x-2.0-beta2, 2010-04-16
|
||||
------------------------------------
|
||||
- Add ability to suppress core's standard menu blocks on block admin page
|
||||
- #693302: Add simple bulk export module
|
||||
- Fixed import of exportable menu_blocks
|
||||
- Fixed bug causing missing "delete" link for menu blocks
|
||||
- Fixed configure link on modules page
|
||||
|
||||
Menu Block 7.x-2.0-beta1, 2010-03-26
|
||||
------------------------------------
|
||||
- #693302: Add API for exportable menu_blocks
|
||||
- #749838: Port to Drupal 7
|
||||
|
||||
Menu Block 6.x-2.3, 2010-03-24
|
||||
------------------------------
|
||||
- #739282: Users with "administer menu" privileges can exploit XSS vulnerability
|
||||
- #343061 by sun and JohnAlbin: CSS styling breaks form layout
|
||||
- #345552 by Dmitriy.trt: Inconsistent display of starting level set to children
|
||||
of active item
|
||||
- #474784: Menu title as link is incorrectly always marked as in active trail
|
||||
- #540842 by JohnAlbin and agentrickard: Add option to use current page's
|
||||
selected menu
|
||||
- #580348: Add administrative title to config form to help organize blocks
|
||||
- #350029: Add theme hook suggestions for all theme function calls
|
||||
- #741284 by JohnAlbin, sdboyer, and hefox: Add "menu tree" content types to
|
||||
Chaos Tools/Panels.
|
||||
- #741284 by JohnAlbin and hefox: Add menu_block_get_config() and
|
||||
menu_block_configure_form() to make the configuration form reusable by
|
||||
separating it from the Block API functions.
|
||||
- #553842 by apodran and JohnAlbin: split() is deprecated in PHP 5.3
|
||||
- #398888: "exanded" elements of a menu-item-rooted tree aren't expanded
|
||||
- #703968 by hefox and JohnAlbin: Add menu_tree_build() to allow reuse of tree
|
||||
building code outside of blocks
|
||||
- Refactored API for menu_block_get_title() and menu_block_set_title()
|
||||
- Added HOOK_menu_block_tree_alter() to allow direct tree manipulation
|
||||
- by Denes Szabo and Zoltan Balogh: Added Hungarian translation
|
||||
- Make default menu be "Primary links" instead of "Navigation"
|
||||
- #378206 by sbordage: Added French translation
|
||||
- #345419: Add option for menu title as link
|
||||
- #347805: Add delta to variables and classes in menu-block-wrapper.tpl
|
||||
|
||||
Menu Block 6.x-2.2, 2008-12-16
|
||||
------------------------------
|
||||
- #342498: Give unique class to depth-limited leaves that have children
|
||||
- #341436: Depth-limited leaves that have children get "collapsed" icon
|
||||
- #341345: WSOD on "Add menu block" page with some PHP versions
|
||||
|
||||
Menu Block 6.x-2.1, 2008-12-01
|
||||
------------------------------
|
||||
- #300086: Add option to make starting level follow active menu item
|
||||
- #340868: Clean up display of block configuration options
|
||||
- #300094: Add option to sort active trail to top of menu tree
|
||||
- #328238 by gorbeia: Add support for i18n menu translation
|
||||
- #331934: Add option to select parent item of menu tree
|
||||
- #330978: Add hook_get_menus() and implement Book module integration
|
||||
- #331935: Replace admin/by-module hack with README.txt
|
||||
- #332974: Collapsed menu items get "leaf" class when using "depth" option
|
||||
- #333988: Create template for menu-block-wrapper
|
||||
- #331933 by sun: Help links are displayed if Help module is disabled
|
||||
- #338263: Migration from 5.x-1.x to 6.x-2.x is broken
|
||||
- #305267: Menu blocks incorrectly cached per role
|
||||
|
||||
Menu Block 6.x-2.0, 2008-08-25
|
||||
------------------------------
|
||||
- Added extensive documentation help text
|
||||
- Added extended classes to menu trees
|
||||
- Menu block's administrative interface now matches the block module's standard
|
||||
add, configure, and delete interface
|
||||
- #266230: Port Menu block to D6
|
||||
|
||||
Menu Block 5.x-2.0, 2008-11-24
|
||||
------------------------------
|
||||
- #304675: Port 6.x admin interface to 5.x
|
||||
- Added missing dependency on menu module
|
||||
|
||||
Menu Block 5.x-1.0, 2008-08-05
|
||||
------------------------------
|
||||
- Simplified block configuration
|
||||
|
||||
Menu Block 5.x-0.9, 2008-08-05
|
||||
------------------------------
|
||||
- #266223: Add option to limit the depth of the tree to an arbitrary level
|
||||
- Added block config to specify whether to expand all children
|
||||
- Added settings to enable specific menu blocks
|
339
sites/all/modules/menu_block/LICENSE.txt
Normal file
339
sites/all/modules/menu_block/LICENSE.txt
Normal file
@@ -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.
|
140
sites/all/modules/menu_block/README.txt
Normal file
140
sites/all/modules/menu_block/README.txt
Normal file
@@ -0,0 +1,140 @@
|
||||
ADDING MENU BLOCKS
|
||||
------------------
|
||||
|
||||
To add new menu blocks, use the "Add menu block" link on the administer blocks
|
||||
page, admin/structure/block. You will then be able to configure your menu block
|
||||
before adding it.
|
||||
|
||||
|
||||
CONFIGURING MENU BLOCKS
|
||||
-----------------------
|
||||
|
||||
When adding or configuring a menu block, several configuration options are
|
||||
available:
|
||||
|
||||
Basic Options:
|
||||
|
||||
Block title
|
||||
For menu trees that start with the 1st level, the default block title will be
|
||||
the menu name. For menu trees that start with the 2nd level or deeper, the
|
||||
default block title will be the title for the parent menu item of the
|
||||
specified level.
|
||||
|
||||
For example, if the active menu trail for the Management menu is: Administer >
|
||||
Structure > Menus > Main menu, then a menu block configured to start with the
|
||||
1st level of the Management menu will display a block title of "Management".
|
||||
And a menu block configured to start with the 3rd level of the Management menu
|
||||
will display a block title of "Structure".
|
||||
|
||||
Block title as link
|
||||
For menu trees that start with the 2nd level or deeper, the default block
|
||||
title will be the title for the parent menu item of the specified level. If
|
||||
this option is checked, the block title will be a link to that menu item.
|
||||
|
||||
Administrative title
|
||||
To help identify the block on the administer blocks page, you can specify a
|
||||
unique title to be used on that page. If blank, the regular title will be
|
||||
used.
|
||||
|
||||
Menu name
|
||||
Select the menu to use for the tree of links.
|
||||
|
||||
Starting level
|
||||
Blocks that start with the 1st level will always be visible. Blocks that start
|
||||
with the 2nd level or deeper will only be visible when the trail to the active
|
||||
menu item is in the block's tree.
|
||||
|
||||
Maximum depth
|
||||
From the starting level, specify the maximum depth of the tree. Blocks with a
|
||||
maximum depth of 1 will just be a single un-nested list of links with none of
|
||||
those links' children displayed.
|
||||
|
||||
Advanced options:
|
||||
|
||||
Make the starting level follow the active menu item
|
||||
If the active menu item is deeper than the level specified above, the starting
|
||||
level will follow the active menu item. Otherwise, the starting level of the
|
||||
tree will remain fixed.
|
||||
|
||||
Expand
|
||||
All children of this menu will be expanded.
|
||||
|
||||
Sort
|
||||
Sort each item in the active trail to the top of its level. When used on a
|
||||
deep or wide menu tree, the active menu item's children will be easier to see
|
||||
when the page is reloaded.
|
||||
|
||||
Fixed parent item
|
||||
If you select a specific menu item, you alter the "starting level" and
|
||||
"maximum depth" options to be relative to the fixed parent item. The tree of
|
||||
links will only contain children of the selected parent item.
|
||||
|
||||
|
||||
STYLING MENU BLOCKS
|
||||
-------------------
|
||||
|
||||
Classes:
|
||||
|
||||
Themers should look at the myriad of classes added to the <div>, <li> and <a>
|
||||
elements.
|
||||
|
||||
<div>
|
||||
The <div> wrapped around the menu tree has a class for several of the
|
||||
configurable options of the block: menu-block-[block id number]
|
||||
menu-name-[menu name] parent-mlid-[menu link ID] menu-level-[level number]
|
||||
|
||||
<li>
|
||||
The <li> elements of the menu tree can have an extended list of classes
|
||||
(compared to standard menu trees): first last menu-mlid-[menu link ID]
|
||||
has-children active active-trail
|
||||
|
||||
<a>
|
||||
The <a> elements of the menu tree can have: active active-trail
|
||||
|
||||
Templates:
|
||||
|
||||
In addition, the wrapper <div> for the block is generated using the
|
||||
menu-block-wrapper.tpl.php template. And Menu block provides several theme hook
|
||||
suggestions for that template:
|
||||
- menu-block-wrapper--[block id number].tpl.php
|
||||
- menu-block-wrapper--[menu name].tpl.php
|
||||
|
||||
For example, a file in your theme called
|
||||
menu-block-wrapper--main-menu.tpl.php can be used to override the <div> for
|
||||
just the "Primary links" menu blocks.
|
||||
|
||||
Theme functions:
|
||||
|
||||
Menu block uses Drupal core's menu theme functions. However, it also provides
|
||||
theme hook suggestions that can be used to override any of the theme functions
|
||||
called by it.
|
||||
|
||||
- theme_menu_tree() can be overridden by creating one of:
|
||||
- [theme]_menu_tree__[menu name]()
|
||||
- [theme]_menu_tree__menu_block()
|
||||
- [theme]_menu_tree__menu_block__[menu name]()
|
||||
- [theme]_menu_tree__menu_block__[block id number]()
|
||||
|
||||
- theme_menu_link() can be overridden by creating one of:
|
||||
- [theme]_menu_link__[menu name]()
|
||||
- [theme]_menu_link__menu_block()
|
||||
- [theme]_menu_link__menu_block__[menu name]()
|
||||
- [theme]_menu_link__menu_block__[block id number]()
|
||||
|
||||
For example, if you created a bartik_menu_tree__menu_block() function, it would
|
||||
override theme_menu_tree() any time it was used by this module, but not when
|
||||
used by any other module. Similarly, a bartik_menu_link__menu_block__1()
|
||||
function would override theme_menu_link(), but only for the first menu block in
|
||||
your system (the menu block with an ID of 1).
|
||||
|
||||
|
||||
MENU BLOCK API
|
||||
--------------
|
||||
|
||||
Developers can use the API of this module to create their own menu trees outside
|
||||
the confines of blocks. All of the publicly available API functions are
|
||||
documented in the menu_block.module file.
|
||||
|
||||
In addition, Menu block implements HOOK_menu_block_get_menus(),
|
||||
HOOK_menu_block_get_sort_menus() and HOOK_menu_block_tree_alter(). See
|
||||
menu_block.api.php for documentation.
|
71
sites/all/modules/menu_block/menu-block-admin.css
Normal file
71
sites/all/modules/menu_block/menu-block-admin.css
Normal file
@@ -0,0 +1,71 @@
|
||||
.menu-block-parent-wrapper {
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
label#item-label {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
|
||||
/* Proper buttonset styling is missing from Seven */
|
||||
.menu-block-processed {
|
||||
padding: 0 15px 15px 15px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
.form-type-radios.form-item-display-options {
|
||||
display: none;
|
||||
margin: 0 -15px;
|
||||
padding: 5px 15px;
|
||||
text-align: left;
|
||||
background-color: #eee;
|
||||
}
|
||||
.form-type-radio.form-item-display-options {
|
||||
float: left;
|
||||
}
|
||||
.form-item.form-type-radios.form-item-display-options label,
|
||||
.form-item.form-type-radio.form-item-display-options label {
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.form-item-display-options .ui-buttonset .form-item {
|
||||
padding: 0; /* Seven adds padding */
|
||||
}
|
||||
.form-item-display-options .ui-buttonset label.ui-button {
|
||||
display: inline-block;
|
||||
padding: 2px 10px;
|
||||
border: 1px solid #666;
|
||||
color: #666;
|
||||
font-weight: bold;
|
||||
background-image: url(menu-block-background-display-options.png);
|
||||
background-position: left top;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.form-item-display-options .ui-buttonset label.ui-state-active {
|
||||
color: #fff;
|
||||
background-position: left -50px;
|
||||
}
|
||||
.form-item-display-options .ui-buttonset label.ui-button.ui-corner-right {
|
||||
border-left: none;
|
||||
}
|
||||
.form-item-display-options .ui-button .ui-button-text {
|
||||
display: inline;
|
||||
padding: 0;
|
||||
}
|
||||
.ui-buttonset .ui-corner-left {
|
||||
-moz-border-radius-topleft: 5px
|
||||
-moz-border-radius-bottomleft: 5px;
|
||||
-webkit-border-bottom-left-radius: 5px;
|
||||
-webkit-border-top-left-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
border-top-left-radius: 5px;
|
||||
}
|
||||
.ui-buttonset .ui-corner-right {
|
||||
-moz-border-radius-topright: 5px
|
||||
-moz-border-radius-bottomright: 5px;
|
||||
-webkit-border-bottom-right-radius: 5px;
|
||||
-webkit-border-top-right-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 601 B |
23
sites/all/modules/menu_block/menu-block-wrapper.tpl.php
Normal file
23
sites/all/modules/menu_block/menu-block-wrapper.tpl.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Default theme implementation to wrap menu blocks.
|
||||
*
|
||||
* Available variables:
|
||||
* - $content: The renderable array containing the menu.
|
||||
* - $classes: A string containing the CSS classes for the DIV tag. Includes:
|
||||
* menu-block-DELTA, menu-name-NAME, parent-mlid-MLID, and menu-level-LEVEL.
|
||||
* - $classes_array: An array containing each of the CSS classes.
|
||||
*
|
||||
* The following variables are provided for contextual information.
|
||||
* - $delta: (string) The menu_block's block delta.
|
||||
* - $config: An array of the block's configuration settings. Includes
|
||||
* menu_name, parent_mlid, title_link, admin_title, level, follow, depth,
|
||||
* expanded, and sort.
|
||||
*
|
||||
* @see template_preprocess_menu_block_wrapper()
|
||||
*/
|
||||
?>
|
||||
<div class="<?php print $classes; ?>">
|
||||
<?php print render($content); ?>
|
||||
</div>
|
36
sites/all/modules/menu_block/menu-block.js
Normal file
36
sites/all/modules/menu_block/menu-block.js
Normal file
@@ -0,0 +1,36 @@
|
||||
(function ($) {
|
||||
|
||||
Drupal.behaviors.menu_block = {
|
||||
attach: function (context, settings) {
|
||||
// This behavior attaches by ID, so is only valid once on a page.
|
||||
if ($('#menu-block-settings.menu-block-processed').size()) {
|
||||
return;
|
||||
}
|
||||
$('#menu-block-settings', context).addClass('menu-block-processed');
|
||||
|
||||
// Show the "display options" if javascript is on.
|
||||
$('.form-item-display-options.form-type-radios>label', context).addClass('element-invisible');
|
||||
$('.form-item-display-options.form-type-radios', context).show();
|
||||
// Make the radio set into a jQuery UI buttonset.
|
||||
$('#edit-display-options', context).buttonset();
|
||||
|
||||
// Override the default show/hide animation for Form API states.
|
||||
$('#menu-block-settings', context).bind('state:visible', function(e) {
|
||||
if (e.trigger) {
|
||||
e.stopPropagation() /* Stop the handler further up the tree. */
|
||||
$(e.target).closest('.form-item, .form-wrapper')[e.value ? 'slideDown' : 'slideUp']('fast');
|
||||
}
|
||||
});
|
||||
|
||||
// Syncronize the display of menu and parent item selects.
|
||||
$('.menu-block-parent-mlid', context).change( function() {
|
||||
var menuItem = $(this).val().split(':');
|
||||
$('.menu-block-menu-name').val(menuItem[0]);
|
||||
});
|
||||
$('.menu-block-menu-name', context).change( function() {
|
||||
$('.menu-block-parent-mlid').val($(this).val() + ':0');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery);
|
635
sites/all/modules/menu_block/menu_block.admin.inc
Normal file
635
sites/all/modules/menu_block/menu_block.admin.inc
Normal file
@@ -0,0 +1,635 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Provides infrequently used functions and hooks for menu_block.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_theme().
|
||||
*/
|
||||
function _menu_block_theme(&$existing, $type, $theme, $path) {
|
||||
// Add theme hook suggestion patterns for the core theme functions used in
|
||||
// this module. We can't add them during hook_theme_registry_alter() because
|
||||
// we will already have missed the opportunity for the theme engine's
|
||||
// theme_hook() to process the pattern. And we can't run the pattern ourselves
|
||||
// because we aren't given the type, theme and path in that hook.
|
||||
$existing['menu_tree']['pattern'] = 'menu_tree__';
|
||||
$existing['menu_link']['pattern'] = 'menu_link__';
|
||||
|
||||
return array(
|
||||
'menu_block_wrapper' => array(
|
||||
'template' => 'menu-block-wrapper',
|
||||
'variables' => array('content' => array(), 'config' => array(), 'delta' => NULL),
|
||||
'pattern' => 'menu_block_wrapper__',
|
||||
),
|
||||
'menu_block_menu_order' => array(
|
||||
'render element' => 'element',
|
||||
'file' => 'menu_block.admin.inc',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ctools_plugin_directory().
|
||||
*/
|
||||
function _menu_block_ctools_plugin_directory($module, $plugin) {
|
||||
if ($plugin == 'content_types') {
|
||||
return 'plugins/' . $plugin;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback: display the menu block addition form.
|
||||
*
|
||||
* @see menu_block_add_block_form_submit()
|
||||
*/
|
||||
function menu_block_add_block_form($form, &$form_state) {
|
||||
module_load_include('inc', 'block', 'block.admin');
|
||||
$form = block_admin_configure($form, $form_state, 'menu_block', NULL);
|
||||
|
||||
// Other modules should be able to use hook_form_block_add_block_form_alter()
|
||||
// to modify this form, so add a base form ID.
|
||||
$form_state['build_info']['base_form_id'] = 'block_add_block_form';
|
||||
|
||||
// Prevent block_add_block_form_validate/submit() from being automatically
|
||||
// added because of the base form ID by providing these handlers manually.
|
||||
$form['#validate'] = array();
|
||||
$form['#submit'] = array('menu_block_add_block_form_submit');
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the new menu block.
|
||||
*/
|
||||
function menu_block_add_block_form_submit($form, &$form_state) {
|
||||
// Determine the delta of the new block.
|
||||
$block_ids = variable_get('menu_block_ids', array());
|
||||
$delta = empty($block_ids) ? 1 : max($block_ids) + 1;
|
||||
$form_state['values']['delta'] = $delta;
|
||||
|
||||
// Save the new array of blocks IDs.
|
||||
$block_ids[] = $delta;
|
||||
variable_set('menu_block_ids', $block_ids);
|
||||
|
||||
// Save the block configuration.
|
||||
menu_block_block_save($delta, $form_state['values']);
|
||||
|
||||
// Run the normal new block submission (borrowed from block_add_block_form_submit).
|
||||
$query = db_insert('block')->fields(array('visibility', 'pages', 'custom', 'title', 'module', 'theme', 'region', 'status', 'weight', 'delta', 'cache'));
|
||||
foreach (list_themes() as $key => $theme) {
|
||||
if ($theme->status) {
|
||||
$region = !empty($form_state['values']['regions'][$theme->name]) ? $form_state['values']['regions'][$theme->name] : BLOCK_REGION_NONE;
|
||||
$query->values(array(
|
||||
'visibility' => (int) $form_state['values']['visibility'],
|
||||
'pages' => trim($form_state['values']['pages']),
|
||||
'custom' => (int) $form_state['values']['custom'],
|
||||
'title' => $form_state['values']['title'],
|
||||
'module' => $form_state['values']['module'],
|
||||
'theme' => $theme->name,
|
||||
'region' => ($region == BLOCK_REGION_NONE ? '' : $region),
|
||||
'status' => 0,
|
||||
'status' => (int) ($region != BLOCK_REGION_NONE),
|
||||
'weight' => 0,
|
||||
'delta' => $delta,
|
||||
'cache' => DRUPAL_NO_CACHE,
|
||||
));
|
||||
}
|
||||
}
|
||||
$query->execute();
|
||||
|
||||
$query = db_insert('block_role')->fields(array('rid', 'module', 'delta'));
|
||||
foreach (array_filter($form_state['values']['roles']) as $rid) {
|
||||
$query->values(array(
|
||||
'rid' => $rid,
|
||||
'module' => $form_state['values']['module'],
|
||||
'delta' => $delta,
|
||||
));
|
||||
}
|
||||
$query->execute();
|
||||
|
||||
drupal_set_message(t('The block has been created.'));
|
||||
cache_clear_all();
|
||||
$form_state['redirect'] = 'admin/structure/block';
|
||||
}
|
||||
|
||||
/**
|
||||
* Alters the block admin form to add delete links next to menu blocks.
|
||||
*/
|
||||
function _menu_block_form_block_admin_display_form_alter(&$form, $form_state) {
|
||||
$blocks = module_invoke_all('menu_block_blocks');
|
||||
foreach (variable_get('menu_block_ids', array()) AS $delta) {
|
||||
if (empty($blocks[$delta])) {
|
||||
$form['blocks']['menu_block_' . $delta]['delete'] = array('#type' => 'link', '#title' => t('delete'), '#href' => 'admin/structure/block/delete-menu-block/' . $delta);
|
||||
}
|
||||
}
|
||||
if (variable_get('menu_block_suppress_core')) {
|
||||
foreach (array_keys(menu_get_menus(FALSE)) AS $delta) {
|
||||
if (empty($form['blocks']['menu_' . $delta]['region']['#default_value'])) {
|
||||
unset($form['blocks']['menu_' . $delta]);
|
||||
}
|
||||
}
|
||||
foreach (array_keys(menu_list_system_menus()) AS $delta) {
|
||||
if (empty($form['blocks']['system_' . $delta]['region']['#default_value'])) {
|
||||
unset($form['blocks']['system_' . $delta]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback: confirm deletion of menu blocks.
|
||||
*/
|
||||
function menu_block_delete($form, &$form_state, $delta = 0) {
|
||||
$title = _menu_block_format_title(menu_block_get_config($delta));
|
||||
$form['block_title'] = array('#type' => 'hidden', '#value' => $title);
|
||||
$form['delta'] = array('#type' => 'hidden', '#value' => $delta);
|
||||
|
||||
return confirm_form($form, t('Are you sure you want to delete the "%name" block?', array('%name' => $title)), 'admin/structure/block', NULL, t('Delete'), t('Cancel'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletion of menu blocks.
|
||||
*/
|
||||
function menu_block_delete_submit($form, &$form_state) {
|
||||
// Remove the menu block configuration variables.
|
||||
$delta = $form_state['values']['delta'];
|
||||
$block_ids = variable_get('menu_block_ids', array());
|
||||
unset($block_ids[array_search($delta, $block_ids)]);
|
||||
sort($block_ids);
|
||||
variable_set('menu_block_ids', $block_ids);
|
||||
variable_del("menu_block_{$delta}_title_link");
|
||||
variable_del("menu_block_{$delta}_admin_title");
|
||||
variable_del("menu_block_{$delta}_parent");
|
||||
variable_del("menu_block_{$delta}_level");
|
||||
variable_del("menu_block_{$delta}_follow");
|
||||
variable_del("menu_block_{$delta}_depth");
|
||||
variable_del("menu_block_{$delta}_expanded");
|
||||
variable_del("menu_block_{$delta}_sort");
|
||||
|
||||
db_delete('block')
|
||||
->condition('module', 'menu_block')
|
||||
->condition('delta', $delta)
|
||||
->execute();
|
||||
db_delete('block_role')
|
||||
->condition('module', 'menu_block')
|
||||
->condition('delta', $delta)
|
||||
->execute();
|
||||
drupal_set_message(t('The block "%name" has been removed.', array('%name' => $form_state['values']['block_title'])));
|
||||
cache_clear_all();
|
||||
$form_state['redirect'] = 'admin/structure/block';
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_block_info().
|
||||
*/
|
||||
function _menu_block_block_info() {
|
||||
$blocks = array();
|
||||
$deltas = variable_get('menu_block_ids', array());
|
||||
foreach (array_keys(module_invoke_all('menu_block_blocks')) as $delta) {
|
||||
$deltas[] = $delta;
|
||||
}
|
||||
foreach ($deltas AS $delta) {
|
||||
$blocks[$delta]['info'] = _menu_block_format_title(menu_block_get_config($delta));
|
||||
// Menu blocks can't be cached because each menu item can have
|
||||
// a custom access callback. menu.inc manages its own caching.
|
||||
$blocks[$delta]['cache'] = DRUPAL_NO_CACHE;
|
||||
}
|
||||
return $blocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the title of the block.
|
||||
*
|
||||
* @param $config
|
||||
* array The configuration of the menu block.
|
||||
* @return
|
||||
* string The title of the block.
|
||||
*/
|
||||
function _menu_block_format_title($config) {
|
||||
// If an administrative title is specified, use it.
|
||||
if (!empty($config['admin_title'])) {
|
||||
return check_plain($config['admin_title']);
|
||||
}
|
||||
$menus = menu_block_get_all_menus();
|
||||
$menus[MENU_TREE__CURRENT_PAGE_MENU] = t('Current menu');
|
||||
if (empty($config['menu_name']) || empty($menus[$config['menu_name']])) {
|
||||
$title = t('Unconfigured menu block');
|
||||
}
|
||||
else {
|
||||
// Show the configured levels in the block info
|
||||
$replacements = array(
|
||||
'@menu_name' => $menus[$config['menu_name']],
|
||||
'@level1' => $config['level'],
|
||||
'@level2' => $config['level'] + $config['depth'] - 1,
|
||||
);
|
||||
if ($config['parent_mlid']) {
|
||||
$parent_item = menu_link_load($config['parent_mlid']);
|
||||
$replacements['@menu_name'] = $parent_item['title'];
|
||||
}
|
||||
if ($config['follow']) {
|
||||
$title = t('@menu_name (active menu item)', $replacements);
|
||||
}
|
||||
elseif ($config['depth'] == 1) {
|
||||
$title = t('@menu_name (level @level1)', $replacements);
|
||||
}
|
||||
elseif ($config['depth']) {
|
||||
if ($config['expanded']) {
|
||||
$title = t('@menu_name (expanded levels @level1-@level2)', $replacements);
|
||||
}
|
||||
else {
|
||||
$title = t('@menu_name (levels @level1-@level2)', $replacements);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($config['expanded']) {
|
||||
$title = t('@menu_name (expanded levels @level1+)', $replacements);
|
||||
}
|
||||
else {
|
||||
$title = t('@menu_name (levels @level1+)', $replacements);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_block_configure().
|
||||
*/
|
||||
function _menu_block_block_configure($delta = '') {
|
||||
// Create a pseudo form state.
|
||||
$form_state = array('values' => menu_block_get_config($delta));
|
||||
return menu_block_configure_form(array(), $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configuration form for a menu tree.
|
||||
*
|
||||
* @param $form_state
|
||||
* array An associated array of configuration options should be present in the
|
||||
* 'values' key. If none are given, default configuration is assumed.
|
||||
* @return
|
||||
* array The form in Form API format.
|
||||
*/
|
||||
function menu_block_configure_form($form, &$form_state) {
|
||||
$config = array();
|
||||
// Get the config from the form state.
|
||||
if (!empty($form_state['values'])) {
|
||||
$config = $form_state['values'];
|
||||
if (!empty($config['parent'])) {
|
||||
list($config['menu_name'], $config['parent_mlid']) = explode(':', $config['parent']);
|
||||
}
|
||||
}
|
||||
// Merge in the default configuration.
|
||||
$config += menu_block_get_config();
|
||||
|
||||
// Don't display the config form if this delta is exported to code.
|
||||
if (!empty($config['exported_to_code'])) {
|
||||
$form['exported_message'] = array(
|
||||
'#markup' => '<p><em>' . t('Configuration is being provided by code.') . '</em></p>',
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
// Build the standard form.
|
||||
$form['#attached']['js'][] = drupal_get_path('module', 'menu_block') . '/menu-block.js';
|
||||
$form['#attached']['css'][] = drupal_get_path('module', 'menu_block') . '/menu-block-admin.css';
|
||||
$form['#attached']['library'][] = array('system', 'ui.button');
|
||||
|
||||
$form['menu-block-wrapper-start'] = array(
|
||||
'#markup' => '<div id="menu-block-settings">',
|
||||
'#weight' => -20,
|
||||
);
|
||||
$form['display_options'] = array(
|
||||
'#type' => 'radios',
|
||||
'#title' => t('Display'),
|
||||
'#default_value' => 'basic',
|
||||
'#options' => array(
|
||||
'basic' => t('Basic options'),
|
||||
'advanced' => t('Advanced options'),
|
||||
),
|
||||
'#attributes' => array('class' => array('clearfix')),
|
||||
'#weight' => -19,
|
||||
);
|
||||
$form['title_link'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Block title as link'),
|
||||
'#default_value' => $config['title_link'],
|
||||
'#description' => t('Make the default block title a link to that menu item. An overridden block title will not be a link.'),
|
||||
'#states' => array(
|
||||
'visible' => array(
|
||||
':input[name=title]' => array('value' => ''),
|
||||
),
|
||||
),
|
||||
);
|
||||
// We need a different state if the form is in a Panel overlay.
|
||||
if (isset($form['override_title'])) {
|
||||
$form['title_link']['#states'] = array(
|
||||
'visible' => array(
|
||||
':input[name=override_title]' => array('checked' => FALSE),
|
||||
),
|
||||
);
|
||||
}
|
||||
$form['admin_title'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => $config['admin_title'],
|
||||
'#title' => t('Administrative title'),
|
||||
'#description' => t('This title will be used administratively to identify this block. If blank, the regular title will be used.'),
|
||||
);
|
||||
$menus = menu_block_get_all_menus();
|
||||
$form['menu_name'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Menu'),
|
||||
'#default_value' => $config['menu_name'],
|
||||
'#options' => $menus,
|
||||
'#description' => t('The preferred menus used by <em><the menu selected by the page></em> can be customized on the <a href="!url">Menu block settings page</a>.', array('!url' => url('admin/config/user-interface/menu-block'))),
|
||||
'#attributes' => array('class' => array('menu-block-menu-name')),
|
||||
);
|
||||
$form['level'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Starting level'),
|
||||
'#default_value' => $config['level'],
|
||||
'#options' => array(
|
||||
'1' => t('1st level (primary)'),
|
||||
'2' => t('2nd level (secondary)'),
|
||||
'3' => t('3rd level (tertiary)'),
|
||||
'4' => t('4th level'),
|
||||
'5' => t('5th level'),
|
||||
'6' => t('6th level'),
|
||||
'7' => t('7th level'),
|
||||
'8' => t('8th level'),
|
||||
'9' => t('9th level'),
|
||||
),
|
||||
'#description' => t('Blocks that start with the 1st level will always be visible. Blocks that start with the 2nd level or deeper will only be visible when the trail to the active menu item is in the block’s tree.'),
|
||||
);
|
||||
// The value of "follow" in the database/config array is either FALSE or the
|
||||
// value of the "follow_parent" form element.
|
||||
if ($follow = $config['follow']) {
|
||||
$follow_parent = $follow;
|
||||
$follow = 1;
|
||||
}
|
||||
else {
|
||||
$follow_parent = 'active';
|
||||
}
|
||||
$form['follow'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Make the starting level follow the active menu item.'),
|
||||
'#default_value' => $follow,
|
||||
'#description' => t('If the active menu item is deeper than the level specified above, the starting level will follow the active menu item. Otherwise, the starting level of the tree will remain fixed.'),
|
||||
'#element_validate' => array('menu_block_configure_form_follow_validate'),
|
||||
);
|
||||
$form['follow_parent'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Starting level will be'),
|
||||
'#default_value' => $follow_parent,
|
||||
'#options' => array(
|
||||
'active' => t('Active menu item'),
|
||||
'child' => t('Children of active menu item'),
|
||||
),
|
||||
'#description' => t('When following the active menu item, specify if the starting level should be the active menu item or its children.'),
|
||||
'#states' => array(
|
||||
'visible' => array(
|
||||
':input[name=follow]' => array('checked' => TRUE),
|
||||
),
|
||||
),
|
||||
);
|
||||
$form['depth'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Maximum depth'),
|
||||
'#default_value' => $config['depth'],
|
||||
'#options' => array(
|
||||
'1' => '1',
|
||||
'2' => '2',
|
||||
'3' => '3',
|
||||
'4' => '4',
|
||||
'5' => '5',
|
||||
'6' => '6',
|
||||
'7' => '7',
|
||||
'8' => '8',
|
||||
'9' => '9',
|
||||
'0' => t('Unlimited'),
|
||||
),
|
||||
'#description' => t('From the starting level, specify the maximum depth of the menu tree.'),
|
||||
);
|
||||
$form['expanded'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('<strong>Expand all children</strong> of this tree.'),
|
||||
'#default_value' => $config['expanded'],
|
||||
);
|
||||
$form['sort'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('<strong>Sort</strong> menu tree by the active menu item’s trail.'),
|
||||
'#default_value' => $config['sort'],
|
||||
'#description' => t('Sort each item in the active trail to the top of its level. When used on a deep or wide menu tree, the active menu item’s children will be easier to see when the page is reloaded.'),
|
||||
);
|
||||
$form['parent_mlid'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Fixed parent item'),
|
||||
'#default_value' => $config['menu_name'] . ':' . $config['parent_mlid'],
|
||||
'#options' => menu_parent_options($menus, array('mlid' => 0)),
|
||||
'#description' => t('Alter the “starting level” and “maximum depth” options to be relative to the fixed parent item. The tree of links will only contain children of the selected menu item.'),
|
||||
'#attributes' => array('class' => array('menu-block-parent-mlid')),
|
||||
'#element_validate' => array('menu_block_configure_form_parent_validate'),
|
||||
);
|
||||
$form['parent_mlid']['#options'][MENU_TREE__CURRENT_PAGE_MENU . ':0'] = '<' . t('the menu selected by the page') . '>';
|
||||
$form['menu-block-wrapper-close'] = array('#markup' => '</div>');
|
||||
|
||||
// Set visibility of advanced options.
|
||||
foreach (array('title_link', 'follow', 'follow_parent', 'expanded', 'sort', 'parent_mlid') as $key) {
|
||||
$form[$key]['#states']['visible'][':input[name=display_options]'] = array('value' => 'advanced');
|
||||
}
|
||||
if ($config['title_link'] || $follow || $config['expanded'] || $config['sort'] || $config['parent_mlid']) {
|
||||
$form['display_options']['#default_value'] = 'advanced';
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the parent element of the block configuration form.
|
||||
*/
|
||||
function menu_block_configure_form_parent_validate($element, &$form_state) {
|
||||
// Determine the fixed parent item's menu and mlid.
|
||||
list($menu_name, $parent_mlid) = explode(':', $form_state['values']['parent_mlid']);
|
||||
if ($parent_mlid) {
|
||||
// If mlid is set, its menu overrides the menu_name option.
|
||||
$form_state['values']['menu_name'] = $menu_name;
|
||||
}
|
||||
else {
|
||||
// Otherwise the menu_name overrides the parent item option.
|
||||
$form_state['values']['parent_mlid'] = $menu_name . ':0';
|
||||
}
|
||||
// The value of "parent" stored in the database/config array is the menu name
|
||||
// combined with the optional parent menu item's mlid.
|
||||
$form_state['values']['parent'] = $form_state['values']['parent_mlid'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the follow element of the block configuration form.
|
||||
*/
|
||||
function menu_block_configure_form_follow_validate($element, &$form_state) {
|
||||
// The value of "follow" stored in the database/config array is either FALSE
|
||||
// or the value of the "follow_parent" form element.
|
||||
if ($form_state['values']['follow'] && !empty($form_state['values']['follow_parent'])) {
|
||||
$form_state['values']['follow'] = $form_state['values']['follow_parent'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_block_save().
|
||||
*/
|
||||
function _menu_block_block_save($delta = '', $edit = array()) {
|
||||
if (!empty($delta)) {
|
||||
// Don't save values for an exported block.
|
||||
$config = menu_block_get_config($delta);
|
||||
if (empty($config['exported_to_code'])) {
|
||||
variable_set("menu_block_{$delta}_title_link", $edit['title_link']);
|
||||
variable_set("menu_block_{$delta}_admin_title", $edit['admin_title']);
|
||||
variable_set("menu_block_{$delta}_parent", $edit['parent']);
|
||||
variable_set("menu_block_{$delta}_level", $edit['level']);
|
||||
variable_set("menu_block_{$delta}_follow", $edit['follow']);
|
||||
variable_set("menu_block_{$delta}_depth", $edit['depth']);
|
||||
variable_set("menu_block_{$delta}_expanded", $edit['expanded']);
|
||||
variable_set("menu_block_{$delta}_sort", $edit['sort']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback: admin settings form.
|
||||
*
|
||||
* @return
|
||||
* The settings form used by Menu block.
|
||||
*/
|
||||
function menu_block_admin_settings_form($form, &$form_state) {
|
||||
// Option to suppress core's blocks of menus.
|
||||
$form['menu_block_suppress_core'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Suppress Drupal’s standard menu blocks'),
|
||||
'#default_value' => variable_get('menu_block_suppress_core', 0),
|
||||
'#description' => t('On the blocks admin page, hide Drupal’s standard blocks of menus.'),
|
||||
'#access' => module_exists('block'),
|
||||
);
|
||||
|
||||
// Retrieve core's menus.
|
||||
$menus = menu_get_menus();
|
||||
// Retrieve all the menu names provided by hook_menu_block_get_sort_menus().
|
||||
$menus = array_merge($menus, module_invoke_all('menu_block_get_sort_menus'));
|
||||
asort($menus);
|
||||
|
||||
// Load stored configuration.
|
||||
$menu_order = variable_get('menu_block_menu_order', array('main-menu' => '', 'user-menu' => ''));
|
||||
// Remove any menus no longer in the list of all menus.
|
||||
foreach (array_keys($menu_order) as $menu) {
|
||||
if (!isset($menus[$menu])) {
|
||||
unset($menu_order[$menu]);
|
||||
}
|
||||
}
|
||||
|
||||
// Merge the saved configuration with any un-configured menus.
|
||||
$all_menus = $menu_order + $menus;
|
||||
|
||||
$form['heading'] = array(
|
||||
'#markup' => '<p>' . t('If a block is configured to use <em>"the menu selected by the page"</em>, the block will be generated from the first "available" menu that contains a link to the page.') . '</p>',
|
||||
);
|
||||
|
||||
// Orderable list of menu selections.
|
||||
$form['menu_order'] = array(
|
||||
'#tree' => TRUE,
|
||||
'#theme' => 'menu_block_menu_order',
|
||||
);
|
||||
|
||||
$order = 0;
|
||||
$total_menus = count($all_menus);
|
||||
foreach (array_keys($all_menus) as $menu_name) {
|
||||
$form['menu_order'][$menu_name] = array(
|
||||
'title' => array(
|
||||
'#markup' => check_plain($menus[$menu_name]),
|
||||
),
|
||||
'available' => array(
|
||||
'#type' => 'checkbox',
|
||||
'#attributes' => array('title' => t('Select from the @menu_name menu', array('@menu_name' => $menus[$menu_name]))),
|
||||
'#default_value' => isset($menu_order[$menu_name]),
|
||||
),
|
||||
'weight' => array(
|
||||
'#type' => 'weight',
|
||||
'#default_value' => $order - $total_menus,
|
||||
'#delta' => $total_menus,
|
||||
'#id' => 'edit-menu-block-menus-' . $menu_name,
|
||||
),
|
||||
);
|
||||
$order++;
|
||||
}
|
||||
|
||||
$form['footer_note'] = array(
|
||||
'#markup' => '<p>' . t('The above list will <em>not</em> affect menu blocks that are configured to use a specific menu.') . '</p>',
|
||||
);
|
||||
|
||||
$form['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Save configuration'),
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form submission handler.
|
||||
*/
|
||||
function menu_block_admin_settings_form_submit($form, &$form_state) {
|
||||
$menu_order = array();
|
||||
foreach ($form_state['values']['menu_order'] AS $menu_name => $row) {
|
||||
if ($row['available']) {
|
||||
// Add available menu and its weight to list.
|
||||
$menu_order[$menu_name] = (int) $row['weight'];
|
||||
}
|
||||
}
|
||||
// Sort the keys by the weight stored in the value.
|
||||
asort($menu_order);
|
||||
foreach ($menu_order AS $menu_name => $weight) {
|
||||
// Now that the array is sorted, the weight is redundant data.
|
||||
$menu_order[$menu_name] = '';
|
||||
}
|
||||
variable_set('menu_block_menu_order', $menu_order);
|
||||
if ($form_state['values']['menu_block_suppress_core']) {
|
||||
variable_set('menu_block_suppress_core', 1);
|
||||
}
|
||||
else {
|
||||
variable_del('menu_block_suppress_core');
|
||||
}
|
||||
drupal_set_message(t('The configuration options have been saved.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Theme a drag-to-reorder table of menu selection checkboxes.
|
||||
*/
|
||||
function theme_menu_block_menu_order($variables) {
|
||||
$element = $variables['element'];
|
||||
drupal_add_tabledrag('menu-block-menus', 'order', 'sibling', 'menu-weight');
|
||||
|
||||
$variables = array(
|
||||
'header' => array(
|
||||
t('Menu'),
|
||||
t('Available'),
|
||||
t('Weight'),
|
||||
),
|
||||
'rows' => array(),
|
||||
'attributes' => array('id' => 'menu-block-menus'),
|
||||
);
|
||||
|
||||
// Generate table of draggable menu names.
|
||||
foreach (element_children($element) as $menu_name) {
|
||||
$element[$menu_name]['weight']['#attributes']['class'] = array('menu-weight');
|
||||
$variables['rows'][] = array(
|
||||
'data' => array(
|
||||
drupal_render($element[$menu_name]['title']),
|
||||
drupal_render($element[$menu_name]['available']),
|
||||
drupal_render($element[$menu_name]['weight']),
|
||||
),
|
||||
'class' => array('draggable'),
|
||||
);
|
||||
}
|
||||
|
||||
return theme('table', $variables);
|
||||
}
|
97
sites/all/modules/menu_block/menu_block.api.php
Normal file
97
sites/all/modules/menu_block/menu_block.api.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Hooks provided by the Menu Block module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup hooks
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Alter the menu tree and its configuration before the tree is rendered.
|
||||
*
|
||||
* @param $tree
|
||||
* An array containing the unrendered menu tree.
|
||||
* @param $config
|
||||
* An array containing the configuration of the tree.
|
||||
*/
|
||||
function hook_menu_block_tree_alter(&$tree, &$config) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of configurations for menu blocks.
|
||||
*
|
||||
* Modules that want to have menu block configurations exported to code should
|
||||
* provide them using this hook.
|
||||
*
|
||||
* @see menu_tree_build() for a description of the config array.
|
||||
*/
|
||||
function hook_menu_block_blocks() {
|
||||
return array(
|
||||
// The array key is the block id used by menu block.
|
||||
'custom-nav' => array(
|
||||
// Use the array keys/values described in menu_tree_build().
|
||||
'menu_name' => 'primary-links',
|
||||
'parent_mlid' => 0,
|
||||
'title_link' => FALSE,
|
||||
'admin_title' => 'Drop-down navigation',
|
||||
'level' => 1,
|
||||
'follow' => 0,
|
||||
'depth' => 2,
|
||||
'expanded' => TRUE,
|
||||
'sort' => FALSE,
|
||||
),
|
||||
// To prevent clobbering of the block id, it is recommended to prefix it
|
||||
// with the module name.
|
||||
'custom-active' => array(
|
||||
'menu_name' => MENU_TREE__CURRENT_PAGE_MENU,
|
||||
'title_link' => TRUE,
|
||||
'admin_title' => 'Secondary navigation',
|
||||
'level' => 3,
|
||||
'depth' => 3,
|
||||
// Any config options not specified will get the default value.
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of menus to use with the menu_block module.
|
||||
*
|
||||
* @return
|
||||
* An array containing the menus' machine names as keys with their menu titles
|
||||
* as values.
|
||||
*/
|
||||
function hook_menu_block_get_menus() {
|
||||
$menus = array();
|
||||
// For each menu, add the following information:
|
||||
$menus['menu_name'] = 'menu title';
|
||||
|
||||
return $menus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of menus to use on menu block's settings form.
|
||||
*
|
||||
* Menu block's settings page sorts menus for use with its "the menu selected by
|
||||
* the page" option.
|
||||
*
|
||||
* @return
|
||||
* An array containing the menus' machine names as keys with their menu titles
|
||||
* as values. The key may optionally be a regular expression to match several
|
||||
* menus at a time; see book_menu_block_get_sort_menus() for an example.
|
||||
*/
|
||||
function hook_menu_block_get_sort_menus() {
|
||||
$menus = array();
|
||||
// For each menu, add the following information:
|
||||
$menus['menu_name'] = 'menu title';
|
||||
// Optionally, add a regular expression to match several menus at once.
|
||||
$menus['/^my\-menus\-.+/'] = t('My menus');
|
||||
|
||||
return $menus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "addtogroup hooks".
|
||||
*/
|
59
sites/all/modules/menu_block/menu_block.follow.inc
Normal file
59
sites/all/modules/menu_block/menu_block.follow.inc
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Provides active menu item pruning.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Prune a tree so that it begins at the active menu item.
|
||||
*
|
||||
* @param $tree
|
||||
* array The menu tree to prune.
|
||||
* @param $level
|
||||
* string The level which the tree will be pruned to: 'active' or 'child'.
|
||||
* @return
|
||||
* void
|
||||
*/
|
||||
function _menu_tree_prune_active_tree(&$tree, $level) {
|
||||
do {
|
||||
$found_active_trail = FALSE;
|
||||
// Examine each element at this level for the active trail.
|
||||
foreach ($tree AS $key => &$value) {
|
||||
if ($tree[$key]['link']['in_active_trail']) {
|
||||
$found_active_trail = TRUE;
|
||||
// If the active trail item has children, examine them.
|
||||
if ($tree[$key]['below']) {
|
||||
// If we are pruning to the active menu item's level, check if this
|
||||
// is the active menu item by checking its children.
|
||||
if ($level == 'active') {
|
||||
foreach ($tree[$key]['below'] AS $child_key => &$value) {
|
||||
if ($tree[$key]['below'][$child_key]['link']['in_active_trail']) {
|
||||
// Get the title for the pruned tree.
|
||||
menu_block_set_title($tree[$key]['link']);
|
||||
$tree = $tree[$key]['below'];
|
||||
// Continue in the pruned tree.
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
// If we've found the active item, we're done.
|
||||
break 2;
|
||||
}
|
||||
// Set the title for the pruned tree.
|
||||
menu_block_set_title($tree[$key]['link']);
|
||||
// If we are pruning to the children of the active menu item, just
|
||||
// prune the tree to the children of the item in the active trail.
|
||||
$tree = $tree[$key]['below'];
|
||||
// Continue in the pruned tree.
|
||||
break;
|
||||
}
|
||||
// If the active menu item has no children, we're done.
|
||||
else {
|
||||
if ($level == 'child') {
|
||||
$tree = array();
|
||||
}
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while ($found_active_trail);
|
||||
}
|
22
sites/all/modules/menu_block/menu_block.info
Normal file
22
sites/all/modules/menu_block/menu_block.info
Normal file
@@ -0,0 +1,22 @@
|
||||
name = "Menu Block"
|
||||
description = "Provides configurable blocks of menu items. "
|
||||
|
||||
core = 7.x
|
||||
dependencies[] = menu (>7.11)
|
||||
|
||||
files[] = menu_block.module
|
||||
files[] = menu_block.admin.inc
|
||||
files[] = menu_block.follow.inc
|
||||
files[] = menu_block.pages.inc
|
||||
files[] = menu_block.sort.inc
|
||||
files[] = menu_block.install
|
||||
files[] = plugins/content_types/menu_tree/menu_tree.inc
|
||||
|
||||
configure = admin/config/user-interface/menu-block
|
||||
|
||||
; Information added by drupal.org packaging script on 2012-08-31
|
||||
version = "7.x-2.3+7-dev"
|
||||
core = "7.x"
|
||||
project = "menu_block"
|
||||
datestamp = "1346416665"
|
||||
|
198
sites/all/modules/menu_block/menu_block.install
Normal file
198
sites/all/modules/menu_block/menu_block.install
Normal file
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Provides install, upgrade and un-install functions for menu_block.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_uninstall().
|
||||
*/
|
||||
function menu_block_uninstall() {
|
||||
// Delete menu block variables.
|
||||
foreach (variable_get('menu_block_ids', array()) AS $delta) {
|
||||
variable_del("menu_block_{$delta}_title_link");
|
||||
variable_del("menu_block_{$delta}_admin_title");
|
||||
variable_del("menu_block_{$delta}_parent");
|
||||
variable_del("menu_block_{$delta}_level");
|
||||
variable_del("menu_block_{$delta}_follow");
|
||||
variable_del("menu_block_{$delta}_depth");
|
||||
variable_del("menu_block_{$delta}_expanded");
|
||||
variable_del("menu_block_{$delta}_sort");
|
||||
}
|
||||
variable_del('menu_block_ids');
|
||||
variable_del('menu_block_suppress_core');
|
||||
variable_del('menu_block_menu_order');
|
||||
// Remove block configurations.
|
||||
db_delete('block')
|
||||
->condition('module', 'menu_block')
|
||||
->execute();
|
||||
db_delete('block_role')
|
||||
->condition('module', 'menu_block')
|
||||
->execute();
|
||||
cache_clear_all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_enable().
|
||||
*/
|
||||
function menu_block_enable() {
|
||||
drupal_set_message(t('To use menu blocks, find the "Add menu block" link on the <a href="@url">administer blocks page</a>.', array('@url' => url('admin/structure/block'))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_install().
|
||||
*/
|
||||
function menu_block_install() {
|
||||
// No-op.
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts pre-5.x-1.0 block names to the new format.
|
||||
*/
|
||||
function menu_block_update_5100() {
|
||||
$delta = 0;
|
||||
$enabled_blocks = array();
|
||||
|
||||
// Find the old enabled blocks.
|
||||
foreach (variable_get('menu_block_enabled_blocks', array()) AS $old_delta => $enabled) {
|
||||
list($mid, $level) = explode('-', $old_delta);
|
||||
if ($enabled) {
|
||||
$enabled_blocks[++$delta] = TRUE;
|
||||
variable_set("menu_block_{$delta}_mid", $mid);
|
||||
variable_set("menu_block_{$delta}_level", $level);
|
||||
variable_set("menu_block_{$delta}_depth", variable_get("menu_block_depth_{$mid}_{$level}", 0));
|
||||
variable_set("menu_block_{$delta}_expanded", variable_get("menu_block_expanded_{$mid}_{$level}", 0));
|
||||
}
|
||||
// Remove any of the old-style variables.
|
||||
variable_del("menu_block_depth_{$mid}_{$level}");
|
||||
variable_del("menu_block_expanded_{$mid}_{$level}");
|
||||
}
|
||||
variable_set('menu_block_enabled_blocks', $enabled_blocks);
|
||||
|
||||
return t('A pre-release version of Menu block has been detected. All menu blocks from the pre-release version have been given a new delta and are no longer placed in any block regions; their block placement should be re-configured immediately.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts menu block-tracking data to new format.
|
||||
*/
|
||||
function menu_block_update_5200() {
|
||||
$block_ids = array();
|
||||
foreach (variable_get('menu_block_enabled_blocks', array()) AS $delta => $enabled) {
|
||||
if ($enabled) {
|
||||
$block_ids[] = $delta; // Build new $menu_block_ids.
|
||||
// Convert $menu_block_DELTA_mid to $menu_block_DELTA_menu_name.
|
||||
$mid = variable_get("menu_block_{$delta}_mid", 1);
|
||||
variable_set("menu_block_{$delta}_menu_name", $mid);
|
||||
// If we weren't upgraded to 5.x-2.x before the Drupal 6 upgrade, the
|
||||
// mid-to-menu_name conversion is not possible.
|
||||
variable_set("menu_block_{$delta}_title", $mid == 2 ? 'primary-links' : 'navigation');
|
||||
variable_del("menu_block_{$delta}_mid");
|
||||
}
|
||||
else {
|
||||
// Delete un-enabled menu block.
|
||||
variable_del("menu_block_{$delta}_mid");
|
||||
variable_del("menu_block_{$delta}_level");
|
||||
variable_del("menu_block_{$delta}_depth");
|
||||
variable_del("menu_block_{$delta}_expanded");
|
||||
db_delete('block')
|
||||
->condition('module', 'menu_block')
|
||||
->condition('delta', $delta)
|
||||
->execute();
|
||||
db_delete('block_role')
|
||||
->condition('module', 'menu_block')
|
||||
->condition('delta', $delta)
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
// Finish conversion of $menu_block_enabled_blocks to $menu_block_ids.
|
||||
sort($block_ids);
|
||||
variable_set('menu_block_ids', $block_ids);
|
||||
variable_del('menu_block_enabled_blocks');
|
||||
cache_clear_all();
|
||||
|
||||
return t('A 5.x-1.x version of Menu block has been detected and an attempt was made to upgrade it. Unfortunately, you should have upgraded to Menu block 5.x-2.x before your upgrade to Drupal 7. You may need to re-configure all your menu blocks.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts to Drupal 6 menu names.
|
||||
*/
|
||||
function menu_block_update_6200() {
|
||||
$menus = menu_get_menus();
|
||||
foreach (variable_get('menu_block_ids', array()) AS $delta) {
|
||||
// Drupal 6 uses the menu title to create the new menu_name.
|
||||
$menu_name = preg_replace('/[^a-zA-Z0-9]/', '-', strtolower(variable_get("menu_block_{$delta}_title", '')));
|
||||
// If we can't find the new menu_name, default to the navigation menu.
|
||||
if (empty($menus[$menu_name])) {
|
||||
$menu_name = 'navigation';
|
||||
}
|
||||
variable_set("menu_block_{$delta}_menu_name", $menu_name);
|
||||
variable_del("menu_block_{$delta}_title");
|
||||
}
|
||||
return t('The 5.x-2.x version of Menu block has been upgraded to the 6.x-2.0 data storage format.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the menu names to parent items.
|
||||
*/
|
||||
function menu_block_update_6201() {
|
||||
$menus = menu_get_menus();
|
||||
foreach (variable_get('menu_block_ids', array()) AS $delta) {
|
||||
variable_set("menu_block_{$delta}_parent", variable_get("menu_block_{$delta}_menu_name", 'navigation') . ':0');
|
||||
variable_del("menu_block_{$delta}_menu_name");
|
||||
}
|
||||
return t('The 6.x-2.0 version of Menu block has been upgraded to the 6.x-2.1 data storage format.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts to Drupal 7 menu names.
|
||||
*/
|
||||
function menu_block_update_7200() {
|
||||
foreach (variable_get('menu_block_ids', array()) AS $delta) {
|
||||
$menu_name = '';
|
||||
list($old_menu_name, $parent_mlid) = explode(':', variable_get("menu_block_{$delta}_parent", ' : '));
|
||||
switch ($old_menu_name) {
|
||||
case 'primary-links':
|
||||
$menu_name = 'main-menu';
|
||||
break;
|
||||
case 'secondary-links':
|
||||
$menu_name = 'secondary-menu';
|
||||
break;
|
||||
case 'navigation':
|
||||
$menu_name = 'management';
|
||||
break;
|
||||
}
|
||||
if ($menu_name) {
|
||||
variable_set("menu_block_{$delta}_parent", $menu_name . ':' . $parent_mlid);
|
||||
}
|
||||
}
|
||||
return t('The 6.x-2.x version of Menu block has been upgraded to use the new menu names in Drupal 7. To use menu blocks in Drupal 7, find the "Add menu block" link on the <a href="@url">administer blocks page</a>.', array('@url' => url('admin/structure/block')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to fix custom menus in Drupal 7.0.
|
||||
*/
|
||||
function menu_block_fix_custom_menus() {
|
||||
// Make sure all custom menus are present in the active menus variable so that
|
||||
// their items may appear in the active trail.
|
||||
// @see menu_set_active_menu_names()
|
||||
$active_menus = variable_get('menu_default_active_menus', array_keys(menu_list_system_menus()));
|
||||
$update_variable = FALSE;
|
||||
foreach (menu_get_names() as $menu_name) {
|
||||
if (!in_array($menu_name, $active_menus) && (strpos($menu_name, 'menu-') === 0)) {
|
||||
$active_menus[] = $menu_name;
|
||||
$update_variable = TRUE;
|
||||
}
|
||||
}
|
||||
if ($update_variable) {
|
||||
variable_set('menu_default_active_menus', $active_menus);
|
||||
}
|
||||
// Clear the menu cache.
|
||||
cache_clear_all(NULL, 'cache_menu');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add missing custom menus to active menus list.
|
||||
*/
|
||||
function menu_block_update_7202() {
|
||||
menu_block_fix_custom_menus();
|
||||
}
|
750
sites/all/modules/menu_block/menu_block.module
Normal file
750
sites/all/modules/menu_block/menu_block.module
Normal file
@@ -0,0 +1,750 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Provides configurable blocks of menu items.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Denotes that the tree should use the menu picked by the curent page.
|
||||
*/
|
||||
define('MENU_TREE__CURRENT_PAGE_MENU', '_active');
|
||||
|
||||
// Off-load the following infrequently called hooks to another file.
|
||||
function menu_block_theme(&$existing, $type, $theme, $path) {
|
||||
module_load_include('inc', 'menu_block', 'menu_block.admin');
|
||||
return _menu_block_theme($existing, $type, $theme, $path);
|
||||
}
|
||||
function menu_block_block_info() {
|
||||
module_load_include('inc', 'menu_block', 'menu_block.admin');
|
||||
return _menu_block_block_info();
|
||||
}
|
||||
function menu_block_block_configure($delta = '') {
|
||||
module_load_include('inc', 'menu_block', 'menu_block.admin');
|
||||
return _menu_block_block_configure($delta);
|
||||
}
|
||||
function menu_block_block_save($delta = '', $edit = array()) {
|
||||
module_load_include('inc', 'menu_block', 'menu_block.admin');
|
||||
return _menu_block_block_save($delta, $edit);
|
||||
}
|
||||
function menu_block_form_block_admin_display_form_alter(&$form, $form_state) {
|
||||
module_load_include('inc', 'menu_block', 'menu_block.admin');
|
||||
return _menu_block_form_block_admin_display_form_alter($form, $form_state);
|
||||
}
|
||||
function menu_block_ctools_plugin_directory($module, $plugin) {
|
||||
module_load_include('inc', 'menu_block', 'menu_block.admin');
|
||||
return _menu_block_ctools_plugin_directory($module, $plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_menu().
|
||||
*/
|
||||
function menu_block_menu() {
|
||||
// @todo Remove this check if block module is re-added as a dependency.
|
||||
if (module_exists('block')) {
|
||||
$items['admin/structure/block/add-menu-block'] = array(
|
||||
'title' => 'Add menu block',
|
||||
'description' => 'Add a new menu block.',
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('menu_block_add_block_form'),
|
||||
'access arguments' => array('administer blocks'),
|
||||
'type' => MENU_LOCAL_ACTION,
|
||||
'file' => 'menu_block.admin.inc',
|
||||
);
|
||||
$default_theme = variable_get('theme_default', 'bartik');
|
||||
foreach (list_themes() as $key => $theme) {
|
||||
if ($key != $default_theme) {
|
||||
$items['admin/structure/block/list/' . $key . '/add-menu-block'] = array(
|
||||
'title' => 'Add menu block',
|
||||
'description' => 'Add a new menu block.',
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('menu_block_add_block_form'),
|
||||
'access arguments' => array('administer blocks'),
|
||||
'type' => MENU_LOCAL_ACTION,
|
||||
'file' => 'menu_block.admin.inc',
|
||||
);
|
||||
}
|
||||
}
|
||||
$items['admin/structure/block/delete-menu-block'] = array(
|
||||
'title' => 'Delete menu block',
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('menu_block_delete'),
|
||||
'access arguments' => array('administer blocks'),
|
||||
'type' => MENU_CALLBACK,
|
||||
'file' => 'menu_block.admin.inc',
|
||||
);
|
||||
}
|
||||
|
||||
$items['admin/config/user-interface/menu-block'] = array(
|
||||
'title' => 'Menu block',
|
||||
'description' => 'Configure menu block.',
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('menu_block_admin_settings_form'),
|
||||
'access arguments' => array('administer blocks'),
|
||||
'type' => MENU_NORMAL_ITEM,
|
||||
'file' => 'menu_block.admin.inc',
|
||||
);
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_menu_alter().
|
||||
*/
|
||||
function menu_block_menu_alter(&$items) {
|
||||
// Fake the necessary menu attributes necessary for a contextual link.
|
||||
$items['admin/content/book/%node']['title'] = 'Edit book outline';
|
||||
$items['admin/content/book/%node']['type'] = MENU_LOCAL_TASK;
|
||||
$items['admin/content/book/%node']['context'] = (MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE);
|
||||
$items['admin/content/book/%node']['tab_root'] = 'admin/content/book';
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_help().
|
||||
*/
|
||||
function menu_block_help($path, $arg) {
|
||||
switch ($path) {
|
||||
case 'admin/structure/block/manage/%/%':
|
||||
if ($arg[4] != 'menu_block') {
|
||||
break;
|
||||
}
|
||||
case 'admin/help#menu_block':
|
||||
case 'admin/structure/block/add-menu-block':
|
||||
module_load_include('inc', 'menu_block', 'menu_block.pages');
|
||||
return _menu_block_help($path, $arg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_block_view().
|
||||
*/
|
||||
function menu_block_block_view($delta = '') {
|
||||
$config = menu_block_get_config($delta);
|
||||
$data = menu_tree_build($config);
|
||||
// Add contextual links for this block.
|
||||
if (!empty($data['content'])) {
|
||||
if (in_array($config['menu_name'], array_keys(menu_get_menus()))) {
|
||||
$data['content']['#contextual_links']['menu_block'] = array('admin/structure/menu/manage', array($config['menu_name']));
|
||||
}
|
||||
elseif (strpos($config['menu_name'], 'book-toc-') === 0) {
|
||||
$node = str_replace('book-toc-', '', $config['menu_name']);
|
||||
$data['content']['#contextual_links']['menu_block'] = array('admin/content/book', array($node));
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process variables for menu-block-wrapper.tpl.php.
|
||||
*
|
||||
* @see menu-block-wrapper.tpl.php
|
||||
*/
|
||||
function template_preprocess_menu_block_wrapper(&$variables) {
|
||||
$variables['classes_array'][] = 'menu-block-' . $variables['delta'];
|
||||
$variables['classes_array'][] = 'menu-name-' . $variables['config']['menu_name'];
|
||||
$variables['classes_array'][] = 'parent-mlid-' . $variables['config']['parent_mlid'];
|
||||
$variables['classes_array'][] = 'menu-level-' . $variables['config']['level'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of menu names implemented by all modules.
|
||||
*
|
||||
* @return
|
||||
* array A list of menu names and titles.
|
||||
*/
|
||||
function menu_block_get_all_menus() {
|
||||
$all_menus = &drupal_static(__FUNCTION__);
|
||||
|
||||
if (!$all_menus) {
|
||||
if ($cached = cache_get('menu_block_menus', 'cache_menu')) {
|
||||
$all_menus = $cached->data;
|
||||
}
|
||||
else {
|
||||
// Retrieve core's menus.
|
||||
$all_menus = menu_get_menus();
|
||||
// Retrieve all the menu names provided by hook_menu_block_get_menus().
|
||||
$all_menus = array_merge($all_menus, module_invoke_all('menu_block_get_menus'));
|
||||
// Add an option to use the menu for the active menu item.
|
||||
$all_menus[MENU_TREE__CURRENT_PAGE_MENU] = '<' . t('the menu selected by the page') . '>';
|
||||
asort($all_menus);
|
||||
cache_set('menu_block_menus', $all_menus, 'cache_menu');
|
||||
}
|
||||
}
|
||||
return $all_menus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configuration for the requested block delta.
|
||||
*
|
||||
* @param $delta
|
||||
* string The delta that uniquely identifies the block in the block system. If
|
||||
* not specified, the default configuration will be returned.
|
||||
* @return
|
||||
* array An associated array of configuration options.
|
||||
*/
|
||||
function menu_block_get_config($delta = NULL) {
|
||||
$config = array(
|
||||
'delta' => $delta,
|
||||
'menu_name' => 'main-menu',
|
||||
'parent_mlid' => 0,
|
||||
'title_link' => 0,
|
||||
'admin_title' => '',
|
||||
'level' => 1,
|
||||
'follow' => 0,
|
||||
'depth' => 0,
|
||||
'expanded' => 0,
|
||||
'sort' => 0,
|
||||
);
|
||||
|
||||
// Get the block configuration options.
|
||||
if ($delta) {
|
||||
static $blocks;
|
||||
if (!isset($blocks)) {
|
||||
$blocks = module_invoke_all('menu_block_blocks');
|
||||
}
|
||||
if (!empty($blocks[$delta])) {
|
||||
// Merge the default values.
|
||||
$config = $blocks[$delta] + $config;
|
||||
// Set the delta.
|
||||
$config['delta'] = $delta;
|
||||
// Flag the block as exported.
|
||||
$config['exported_to_code'] = TRUE;
|
||||
}
|
||||
|
||||
$config['title_link'] = variable_get("menu_block_{$delta}_title_link", $config['title_link']);
|
||||
$config['admin_title'] = variable_get("menu_block_{$delta}_admin_title", $config['admin_title']);
|
||||
$config['level'] = variable_get("menu_block_{$delta}_level", $config['level']);
|
||||
$config['follow'] = variable_get("menu_block_{$delta}_follow", $config['follow']);
|
||||
$config['depth'] = variable_get("menu_block_{$delta}_depth", $config['depth']);
|
||||
$config['expanded'] = variable_get("menu_block_{$delta}_expanded", $config['expanded']);
|
||||
$config['sort'] = variable_get("menu_block_{$delta}_sort", $config['sort']);
|
||||
list($config['menu_name'], $config['parent_mlid']) = explode(':', variable_get("menu_block_{$delta}_parent", $config['menu_name'] . ':' . $config['parent_mlid']));
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a menu tree based on the provided configuration.
|
||||
*
|
||||
* @param $config
|
||||
* array An array of configuration options that specifies how to build the
|
||||
* menu tree and its title.
|
||||
* - delta: (string) The menu_block's block delta.
|
||||
* - menu_name: (string) The machine name of the requested menu. Can also be
|
||||
* set to MENU_TREE__CURRENT_PAGE_MENU to use the menu selected by the page.
|
||||
* - parent_mlid: (int) The mlid of the item that should root the tree. Use 0
|
||||
* to use the menu's root.
|
||||
* - title_link: (boolean) Specifies if the title should be rendered as a link
|
||||
* or a simple string.
|
||||
* - admin_title: (string) An optional title to uniquely identify the block on
|
||||
* the administer blocks page.
|
||||
* - level: (int) The starting level of the tree.
|
||||
* - follow: (string) Specifies if the starting level should follow the
|
||||
* active menu item. Should be set to 0, 'active' or 'child'.
|
||||
* - depth: (int) The maximum depth the tree should contain, relative to the
|
||||
* starting level.
|
||||
* - expanded: (boolean) Specifies if the entire tree be expanded or not.
|
||||
* - sort: (boolean) Specifies if the tree should be sorted with the active
|
||||
* trail at the top of the tree.
|
||||
* @return
|
||||
* array An associative array containing several pieces of data.
|
||||
* - content: The tree as a renderable array.
|
||||
* - subject: The title rendered as HTML.
|
||||
* - subject_array: The title as a renderable array.
|
||||
*/
|
||||
function menu_tree_build($config) {
|
||||
// Retrieve the active menu item from the database.
|
||||
if ($config['menu_name'] == MENU_TREE__CURRENT_PAGE_MENU) {
|
||||
// Retrieve the list of available menus.
|
||||
$menu_order = variable_get('menu_block_menu_order', array('main-menu' => '', 'user-menu' => ''));
|
||||
|
||||
// Check for regular expressions as menu keys.
|
||||
$patterns = array();
|
||||
foreach (array_keys($menu_order) as $pattern) {
|
||||
if ($pattern[0] == '/') {
|
||||
$patterns[$pattern] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the "current" path from the request, or from the active menu
|
||||
// trail if applicable.
|
||||
$link_path = $_GET['q'] ? $_GET['q'] : '<front>';
|
||||
$trail = menu_get_active_trail();
|
||||
$last_item = end($trail);
|
||||
if (!empty($last_item['link_path'])) {
|
||||
$link_path = $last_item['link_path'];
|
||||
}
|
||||
|
||||
// Retrieve all the menus containing a link to the current page.
|
||||
$result = db_query("SELECT menu_name FROM {menu_links} WHERE link_path = :link_path", array(':link_path' => $link_path));
|
||||
foreach ($result as $item) {
|
||||
// Check if the menu is in the list of available menus.
|
||||
if (isset($menu_order[$item->menu_name])) {
|
||||
// Mark the menu.
|
||||
$menu_order[$item->menu_name] = MENU_TREE__CURRENT_PAGE_MENU;
|
||||
}
|
||||
else {
|
||||
// Check if the menu matches one of the available patterns.
|
||||
foreach (array_keys($patterns) as $pattern) {
|
||||
if (preg_match($pattern, $item->menu_name)) {
|
||||
// Mark the menu.
|
||||
$menu_order[$pattern] = MENU_TREE__CURRENT_PAGE_MENU;
|
||||
// Store the actual menu name.
|
||||
$patterns[$pattern] = $item->menu_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Find the first marked menu.
|
||||
$config['menu_name'] = array_search(MENU_TREE__CURRENT_PAGE_MENU, $menu_order);
|
||||
// If a pattern was matched, use the actual menu name instead of the pattern.
|
||||
if (!empty($patterns[$config['menu_name']])) {
|
||||
$config['menu_name'] = $patterns[$config['menu_name']];
|
||||
}
|
||||
$config['parent_mlid'] = 0;
|
||||
|
||||
// If no menu link was found, don't display the block.
|
||||
if (empty($config['menu_name'])) {
|
||||
return array(
|
||||
'subject' => t('The menu selected by the page'),
|
||||
'subject_array' => array(),
|
||||
'content' => array(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the default block name.
|
||||
$menu_names = menu_block_get_all_menus();
|
||||
menu_block_set_title(t($menu_names[$config['menu_name']]));
|
||||
|
||||
if ($config['expanded'] || $config['parent_mlid']) {
|
||||
// Get the full, un-pruned tree.
|
||||
$tree = menu_tree_all_data($config['menu_name']);
|
||||
// And add the active trail data back to the full tree.
|
||||
menu_tree_add_active_path($tree);
|
||||
}
|
||||
else {
|
||||
// Get the tree pruned for just the active trail.
|
||||
$tree = menu_tree_page_data($config['menu_name']);
|
||||
}
|
||||
|
||||
// Allow alteration of the tree and config before we begin operations on it.
|
||||
drupal_alter('menu_block_tree', $tree, $config);
|
||||
|
||||
// Localize the tree.
|
||||
if (module_exists('i18n_menu')) {
|
||||
$tree = i18n_menu_localize_tree($tree);
|
||||
}
|
||||
|
||||
// Prune the tree along the active trail to the specified level.
|
||||
if ($config['level'] > 1 || $config['parent_mlid']) {
|
||||
if ($config['parent_mlid']) {
|
||||
$parent_item = menu_link_load($config['parent_mlid']);
|
||||
menu_tree_prune_tree($tree, $config['level'], $parent_item);
|
||||
}
|
||||
else {
|
||||
menu_tree_prune_tree($tree, $config['level']);
|
||||
}
|
||||
}
|
||||
|
||||
// Prune the tree to the active menu item.
|
||||
if ($config['follow']) {
|
||||
menu_tree_prune_active_tree($tree, $config['follow']);
|
||||
}
|
||||
|
||||
// If the menu-item-based tree is not "expanded", trim the tree to the active path.
|
||||
if ($config['parent_mlid'] && !$config['expanded']) {
|
||||
menu_tree_trim_active_path($tree);
|
||||
}
|
||||
|
||||
// Trim the branches that extend beyond the specified depth.
|
||||
if ($config['depth'] > 0) {
|
||||
menu_tree_depth_trim($tree, $config['depth']);
|
||||
}
|
||||
|
||||
// Sort the active path to the top of the tree.
|
||||
if ($config['sort']) {
|
||||
menu_tree_sort_active_path($tree);
|
||||
}
|
||||
|
||||
// Render the tree.
|
||||
$data = array();
|
||||
$title = menu_block_get_title($config['title_link'], $config);
|
||||
$data['subject_array'] = $title;
|
||||
$data['subject'] = drupal_render($title);
|
||||
$data['content']['#content'] = menu_block_tree_output($tree, $config);
|
||||
if (!empty($data['content']['#content'])) {
|
||||
$data['content']['#theme'] = array(
|
||||
'menu_block_wrapper__' . str_replace('-', '_', $config['delta']),
|
||||
'menu_block_wrapper__' . str_replace('-', '_', $config['menu_name']),
|
||||
'menu_block_wrapper'
|
||||
);
|
||||
$data['content']['#config'] = $config;
|
||||
$data['content']['#delta'] = $config['delta'];
|
||||
}
|
||||
else {
|
||||
$data['content'] = '';
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the menu item to use for the tree's title.
|
||||
*
|
||||
* @param $render_title_as_link
|
||||
* boolean A boolean that says whether to render the title as a link or a
|
||||
* simple string.
|
||||
* @return
|
||||
* array A renderable array containing the tree's title.
|
||||
*/
|
||||
function menu_block_get_title($render_title_as_link = TRUE) {
|
||||
$menu_item = menu_block_set_title();
|
||||
|
||||
// The tree's title is a menu title, a normal string.
|
||||
if (is_string($menu_item)) {
|
||||
$title = array('#markup' => check_plain($menu_item));
|
||||
}
|
||||
// The tree's title is a menu item with a link.
|
||||
elseif ($render_title_as_link) {
|
||||
if (!empty($menu_item['in_active_trail'])) {
|
||||
if (!empty($menu_item['localized_options']['attributes']['class'])) {
|
||||
$menu_item['localized_options']['attributes']['class'][] = 'active-trail';
|
||||
}
|
||||
else {
|
||||
$menu_item['localized_options']['attributes']['class'][] = 'active-trail';
|
||||
}
|
||||
}
|
||||
$title = array(
|
||||
'#type' => 'link',
|
||||
'#title' => $menu_item['title'],
|
||||
'#href' => $menu_item['href'],
|
||||
'#options' => $menu_item['localized_options'],
|
||||
);
|
||||
}
|
||||
// The tree's title is a menu item.
|
||||
else {
|
||||
$title = array('#markup' => check_plain($menu_item['title']));
|
||||
}
|
||||
return $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the menu item to use for the tree's title.
|
||||
*
|
||||
* @param $item
|
||||
* array The menu item (an array) or the menu item's title as a string.
|
||||
*/
|
||||
function menu_block_set_title($item = NULL) {
|
||||
$menu_item = &drupal_static(__FUNCTION__);
|
||||
|
||||
// Save the menu item.
|
||||
if (!is_null($item)) {
|
||||
$menu_item = $item;
|
||||
}
|
||||
|
||||
return $menu_item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the active trail indicators into the tree.
|
||||
*
|
||||
* The data returned by menu_tree_page_data() has link['in_active_trail'] set to
|
||||
* TRUE for each menu item in the active trail. The data returned from
|
||||
* menu_tree_all_data() does not contain the active trail indicators. This is a
|
||||
* helper function that adds it back in.
|
||||
*
|
||||
* @param $tree
|
||||
* array The menu tree.
|
||||
* @return
|
||||
* void
|
||||
*/
|
||||
function menu_tree_add_active_path(&$tree) {
|
||||
// Grab any menu item to find the menu_name for this tree.
|
||||
$menu_item = current($tree);
|
||||
$tree_with_trail = menu_tree_page_data($menu_item['link']['menu_name']);
|
||||
|
||||
// To traverse the original tree down the active trail, we use a pointer.
|
||||
$subtree_pointer =& $tree;
|
||||
|
||||
// Find each key in the active trail.
|
||||
while ($tree_with_trail) {
|
||||
foreach ($tree_with_trail AS $key => &$value) {
|
||||
if ($tree_with_trail[$key]['link']['in_active_trail']) {
|
||||
// Set the active trail info in the original tree.
|
||||
$subtree_pointer[$key]['link']['in_active_trail'] = TRUE;
|
||||
// Continue in the subtree, if it exists.
|
||||
$tree_with_trail =& $tree_with_trail[$key]['below'];
|
||||
$subtree_pointer =& $subtree_pointer[$key]['below'];
|
||||
break;
|
||||
}
|
||||
else {
|
||||
unset($tree_with_trail[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim everything but the active trail in the tree.
|
||||
*
|
||||
* @param $tree
|
||||
* array The menu tree to trim.
|
||||
* @return
|
||||
* void
|
||||
*/
|
||||
function menu_tree_trim_active_path(&$tree) {
|
||||
foreach ($tree AS $key => &$value) {
|
||||
if (($tree[$key]['link']['in_active_trail'] || $tree[$key]['link']['expanded']) && $tree[$key]['below']) {
|
||||
// Continue in the subtree, if it exists.
|
||||
menu_tree_trim_active_path($tree[$key]['below']);
|
||||
}
|
||||
else {
|
||||
// Trim anything not expanded or along the active trail.
|
||||
$tree[$key]['below'] = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the active trail to the top of the tree.
|
||||
*
|
||||
* @param $tree
|
||||
* array The menu tree to sort.
|
||||
* @return
|
||||
* void
|
||||
*/
|
||||
function menu_tree_sort_active_path(&$tree) {
|
||||
module_load_include('inc', 'menu_block', 'menu_block.sort');
|
||||
_menu_tree_sort_active_path($tree);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prune a tree so that it begins at the specified level.
|
||||
*
|
||||
* This function will follow the active menu trail to the specified level.
|
||||
*
|
||||
* @param $tree
|
||||
* array The menu tree to prune.
|
||||
* @param $level
|
||||
* int The level of the original tree that will start the pruned tree.
|
||||
* @param $parent_item
|
||||
* array The menu item that should be used as the root of the tree.
|
||||
* @return
|
||||
* void
|
||||
*/
|
||||
function menu_tree_prune_tree(&$tree, $level, $parent_item = FALSE) {
|
||||
if (!empty($parent_item)) {
|
||||
// Prune the tree along the path to the menu item.
|
||||
for ($i = 1; $i <= MENU_MAX_DEPTH && $parent_item["p$i"] != '0'; $i++) {
|
||||
$plid = $parent_item["p$i"];
|
||||
$found_active_trail = FALSE;
|
||||
// Examine each element at this level for the ancestor.
|
||||
foreach ($tree AS $key => &$value) {
|
||||
if ($tree[$key]['link']['mlid'] == $plid) {
|
||||
menu_block_set_title($tree[$key]['link']);
|
||||
// Prune the tree to the children of this ancestor.
|
||||
$tree = $tree[$key]['below'] ? $tree[$key]['below'] : array();
|
||||
$found_active_trail = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If we don't find the ancestor, bail out.
|
||||
if (!$found_active_trail) {
|
||||
$tree = array();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Trim the upper levels down to the one desired.
|
||||
for ($i = 1; $i < $level; $i++) {
|
||||
$found_active_trail = FALSE;
|
||||
// Examine each element at this level for the active trail.
|
||||
foreach ($tree AS $key => &$value) {
|
||||
if ($tree[$key]['link']['in_active_trail']) {
|
||||
// Get the title for the pruned tree.
|
||||
menu_block_set_title($tree[$key]['link']);
|
||||
// Prune the tree to the children of the item in the active trail.
|
||||
$tree = $tree[$key]['below'] ? $tree[$key]['below'] : array();
|
||||
$found_active_trail = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If we don't find the active trail, the active item isn't in the tree we want.
|
||||
if (!$found_active_trail) {
|
||||
$tree = array();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prune a tree so that it begins at the active menu item.
|
||||
*
|
||||
* @param $tree
|
||||
* array The menu tree to prune.
|
||||
* @param $level
|
||||
* string The level which the tree will be pruned to: 'active' or 'child'.
|
||||
* @return
|
||||
* void
|
||||
*/
|
||||
function menu_tree_prune_active_tree(&$tree, $level) {
|
||||
module_load_include('inc', 'menu_block', 'menu_block.follow');
|
||||
_menu_tree_prune_active_tree($tree, $level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prune a tree so it does not extend beyond the specified depth limit.
|
||||
*
|
||||
* @param $tree
|
||||
* array The menu tree to prune.
|
||||
* @param $depth_limit
|
||||
* int The maximum depth of the returned tree; must be a positive integer.
|
||||
* @return
|
||||
* void
|
||||
*/
|
||||
function menu_tree_depth_trim(&$tree, $depth_limit) {
|
||||
// Prevent invalid input from returning a trimmed tree.
|
||||
if ($depth_limit < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Examine each element at this level to find any possible children.
|
||||
foreach ($tree AS $key => &$value) {
|
||||
if ($tree[$key]['below']) {
|
||||
if ($depth_limit > 1) {
|
||||
menu_tree_depth_trim($tree[$key]['below'], $depth_limit-1);
|
||||
}
|
||||
else {
|
||||
// Remove the children items.
|
||||
$tree[$key]['below'] = FALSE;
|
||||
}
|
||||
}
|
||||
if ($depth_limit == 1 && $tree[$key]['link']['has_children']) {
|
||||
// Turn off the menu styling that shows there were children.
|
||||
$tree[$key]['link']['has_children'] = FALSE;
|
||||
$tree[$key]['link']['leaf_has_children'] = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rendered menu tree.
|
||||
*
|
||||
* This is a copy of menu_tree_output() with additional classes added to the
|
||||
* output.
|
||||
*
|
||||
* @param $tree
|
||||
* array A data structure representing the tree as returned from menu_tree_data.
|
||||
* @return
|
||||
* string The rendered HTML of that data structure.
|
||||
*/
|
||||
function menu_block_tree_output(&$tree, $config = array()) {
|
||||
$build = array();
|
||||
$items = array();
|
||||
|
||||
// Create context if no config was provided.
|
||||
if (empty($config)) {
|
||||
$config['delta'] = 0;
|
||||
// Grab any menu item to find the menu_name for this tree.
|
||||
$menu_item = current($tree);
|
||||
$config['menu_name'] = $menu_item['link']['menu_name'];
|
||||
}
|
||||
$hook_delta = str_replace('-', '_', $config['delta']);
|
||||
$hook_menu_name = str_replace('-', '_', $config['menu_name']);
|
||||
|
||||
// Pull out just the menu items we are going to render so that we
|
||||
// get an accurate count for the first/last classes.
|
||||
foreach ($tree as $key => &$value) {
|
||||
if (!$tree[$key]['link']['hidden']) {
|
||||
$items[] = $tree[$key];
|
||||
}
|
||||
}
|
||||
|
||||
$num_items = count($items);
|
||||
foreach ($items as $i => &$data) {
|
||||
$class = array();
|
||||
if ($i == 0) {
|
||||
$class[] = 'first';
|
||||
}
|
||||
if ($i == $num_items - 1) {
|
||||
$class[] = 'last';
|
||||
}
|
||||
// Set a class if the link has children.
|
||||
if ($data['below']) {
|
||||
$class[] = 'expanded';
|
||||
}
|
||||
elseif ($data['link']['has_children']) {
|
||||
$class[] = 'collapsed';
|
||||
}
|
||||
else {
|
||||
$class[] = 'leaf';
|
||||
}
|
||||
if (!empty($data['link']['leaf_has_children'])) {
|
||||
$class[] = 'has-children';
|
||||
}
|
||||
// Set a class if the link is in the active trail.
|
||||
if ($data['link']['in_active_trail']) {
|
||||
$class[] = 'active-trail';
|
||||
$data['link']['localized_options']['attributes']['class'][] = 'active-trail';
|
||||
}
|
||||
if ($data['link']['href'] == $_GET['q'] || ($data['link']['href'] == '<front>' && drupal_is_front_page())) {
|
||||
$class[] = 'active';
|
||||
}
|
||||
// Set a menu link ID class.
|
||||
$class[] = 'menu-mlid-' . $data['link']['mlid'];
|
||||
|
||||
// Allow menu-specific theme overrides.
|
||||
$element['#theme'] = array(
|
||||
'menu_link__menu_block__' . $hook_delta,
|
||||
'menu_link__menu_block__' . $hook_menu_name,
|
||||
'menu_link__menu_block',
|
||||
'menu_link__' . $hook_menu_name,
|
||||
'menu_link',
|
||||
);
|
||||
$element['#attributes']['class'] = $class;
|
||||
$element['#title'] = $data['link']['title'];
|
||||
$element['#href'] = $data['link']['href'];
|
||||
$element['#localized_options'] = !empty($data['link']['localized_options']) ? $data['link']['localized_options'] : array();
|
||||
$element['#below'] = $data['below'] ? menu_block_tree_output($data['below'], $config) : $data['below'];
|
||||
$element['#original_link'] = $data['link'];
|
||||
$element['#bid'] = array('module' => 'menu_block', 'delta' => $config['delta']);
|
||||
// Index using the link's unique mlid.
|
||||
$build[$data['link']['mlid']] = $element;
|
||||
}
|
||||
if ($build) {
|
||||
// Make sure drupal_render() does not re-order the links.
|
||||
$build['#sorted'] = TRUE;
|
||||
// Add the theme wrapper for outer markup.
|
||||
// Allow menu-specific theme overrides.
|
||||
$build['#theme_wrappers'][] = array(
|
||||
'menu_tree__menu_block__' . $hook_delta,
|
||||
'menu_tree__menu_block__' . $hook_menu_name,
|
||||
'menu_tree__menu_block',
|
||||
'menu_tree__' . $hook_menu_name,
|
||||
'menu_tree',
|
||||
);
|
||||
}
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_menu_block_get_menus() on behalf of book.module.
|
||||
*/
|
||||
function book_menu_block_get_menus() {
|
||||
$menus = array();
|
||||
foreach (book_get_books() AS $book) {
|
||||
$menus[$book['menu_name']] = $book['title'];
|
||||
}
|
||||
return $menus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_menu_block_get_sort_menus() on behalf of book.module.
|
||||
*/
|
||||
function book_menu_block_get_sort_menus() {
|
||||
return array(
|
||||
'/^book\-toc\-.+/' => t('Book navigation'),
|
||||
);
|
||||
}
|
61
sites/all/modules/menu_block/menu_block.pages.inc
Normal file
61
sites/all/modules/menu_block/menu_block.pages.inc
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Provides infrequently used pages for menu_block.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_help().
|
||||
*/
|
||||
function _menu_block_help($path, $arg) {
|
||||
$output = '';
|
||||
switch ($path) {
|
||||
case 'admin/structure/block/manage/%/%':
|
||||
case 'admin/structure/block/add-menu-block':
|
||||
if (module_exists('help')) {
|
||||
$output = '<p>' . t('To learn more about configuring menu blocks, see <a href="!url">menu block’s detailed help</a>.', array('!url' => url('admin/help/menu_block'))) . '</p>';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'admin/help#menu_block':
|
||||
$output =
|
||||
'<h3>' . t('Adding menu blocks') . '</h3>'
|
||||
. '<p>' . t('To add new menu blocks, use the "<a href="!add-url">Add menu block</a>" link on the <a href="!block-url">administer blocks page</a>. You will then be able to configure your menu block before adding it.', array('!add-url' => url('admin/structure/block/add-menu-block'), '!block-url' => url('admin/structure/block'))) . '</p>'
|
||||
. '<h3>' . t('Configuring menu blocks') . '</h3>'
|
||||
. '<p>' . t('When adding or configuring a menu block, several configuration options are available:') . '</p>'
|
||||
. '<h4>' . t('Basic options') . '</h4>'
|
||||
. '<dl>'
|
||||
. '<dt><strong>' . t('Block title') . '</strong></dt>'
|
||||
. '<dd>' . t('For menu trees that start with the 1st level, the default block title will be the menu name. For menu trees that start with the 2nd level or deeper, the default block title will be the title for the parent menu item of the specified level.')
|
||||
. '<p>' . t('For example, if the active menu trail for the Mangement menu is: Administer › Structure › Menus › Main menu, then a menu block configured to start with the 1st level of the Management menu will display a block title of “Management”. And a menu block configured to start with the 3rd level of the Management menu will display a block title of “Structure”.') . '</p></dd>'
|
||||
. '<dt><strong>' . t('Block title as link') . '</strong></dt>'
|
||||
. '<dd>' . t('For menu trees that start with the 2nd level or deeper, the default block title will be the title for the parent menu item of the specified level. If this option is checked, the block title will be a link to that menu item.') . '</dd>'
|
||||
. '<dt><strong>' . t('Administrative title') . '</strong></dt>'
|
||||
. '<dd>' . t('To help identify the block on the administer blocks page, you can specify a unique title to be used on that page. If blank, the regular title will be used.') . '</dd>'
|
||||
. '<dt><strong>' . t('Menu name') . '</strong></dt>'
|
||||
. '<dd>' . t('Select the menu to use for the tree of links.') . '</dd>'
|
||||
. '<dt><strong>' . t('Starting level') . '</strong></dt>'
|
||||
. '<dd>' . t('Blocks that start with the 1st level will always be visible. Blocks that start with the 2nd level or deeper will only be visible when the trail to the active menu item is in the block’s tree.') . '</dd>'
|
||||
. '<dt><strong>' . t('Maximum depth') . '</strong></dt>'
|
||||
. '<dd>' . t('From the starting level, specify the maximum depth of the tree. Blocks with a maximum depth of 1 will just be a single un-nested list of links with none of those links’ children displayed.') . '</dd>'
|
||||
. '</dl>'
|
||||
. '<h4>' . t('Advanced options') . '</h4>'
|
||||
. '<dl>'
|
||||
. '<dt><strong>' . t('Make the starting level follow the active menu item') . '</strong></dt>'
|
||||
. '<dd>' . t('If the active menu item is deeper than the level specified above, the starting level will follow the active menu item. Otherwise, the starting level of the tree will remain fixed.') . '</dd>'
|
||||
. '<dt><strong>' . t('Expand all children') . '</strong></dt>'
|
||||
. '<dd>' . t('All children of this menu will be expanded.') . '</dd>'
|
||||
. '<dt><strong>' . t('Sort') . '</strong></dt>'
|
||||
. '<dd>' . t('Sort each item in the active trail to the top of its level. When used on a deep or wide menu tree, the active menu item’s children will be easier to see when the page is reloaded.') . '</dd>'
|
||||
. '<dt><strong>' . t('Fixed parent item') . '</strong></dt>'
|
||||
. '<dd>' . t('If you select a specific menu item, you alter the “starting level” and “maximum depth” options to be relative to the fixed parent item. The tree of links will only contain children of the selected parent item.') . '</dd>'
|
||||
. '</dl>'
|
||||
. '<h3>' . t('Styling menu blocks') . '</h3>'
|
||||
. '<p>' . t('Themers should be aware of the myriad of classes, templates and theme functions available to them. See the <a href="!url">online documentation</a> or the README.txt file for detailed information about each of them.', array('!url' => url('http://drupal.org/node/748022'))) . '</p>'
|
||||
. '<h3>' . t('Menu block API') . '</h3>'
|
||||
. '<p>' . t('Developers can use the API of this module to create their own menu trees outside the confines of blocks. All of the publicly available API functions are documented in the menu_block.module file.') . '</p>'
|
||||
. '<p>' . t('In addition, Menu block implements HOOK_get_menus() and HOOK_menu_block_tree_alter(). See menu_block.api.php for documentation.') . '</p>';
|
||||
break;
|
||||
}
|
||||
return $output;
|
||||
}
|
54
sites/all/modules/menu_block/menu_block.sort.inc
Normal file
54
sites/all/modules/menu_block/menu_block.sort.inc
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Provides optional sorting of the active trail in the menu tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sort the active trail to the top of the tree.
|
||||
*
|
||||
* @param $tree
|
||||
* array The menu tree to sort.
|
||||
* @return
|
||||
* void
|
||||
*/
|
||||
function _menu_tree_sort_active_path(&$tree) {
|
||||
// To traverse the original tree down the active trail, we use a pointer.
|
||||
$current_level =& $tree;
|
||||
|
||||
// Traverse the tree along the active trail.
|
||||
do {
|
||||
$next_level = $sort = $first_key = FALSE;
|
||||
foreach ($current_level AS $key => &$value) {
|
||||
// Save the first key for later use.
|
||||
if (!$first_key) {
|
||||
$first_key = $key;
|
||||
}
|
||||
if ($current_level[$key]['link']['in_active_trail'] && $current_level[$key]['below']) {
|
||||
// Don't re-sort if its already sorted.
|
||||
if ($key != $first_key) {
|
||||
// Create a new key that will come before the first key.
|
||||
list($first_key, ) = explode(' ', $first_key);
|
||||
$first_key--;
|
||||
list(, $new_key) = explode(' ', $key, 2);
|
||||
$new_key = "$first_key $new_key";
|
||||
// Move the item to the new key.
|
||||
$current_level[$new_key] = $current_level[$key];
|
||||
unset($current_level[$key]);
|
||||
$key = $new_key;
|
||||
$sort = TRUE; // Flag sorting.
|
||||
}
|
||||
$next_level = $key; // Flag subtree.
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Sort this level.
|
||||
if ($sort) {
|
||||
ksort($current_level);
|
||||
}
|
||||
// Continue in the subtree, if it exists.
|
||||
if ($next_level) {
|
||||
$current_level =& $current_level[$next_level]['below'];
|
||||
}
|
||||
} while ($next_level);
|
||||
}
|
111
sites/all/modules/menu_block/menu_block_export.admin.inc
Normal file
111
sites/all/modules/menu_block/menu_block_export.admin.inc
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides infrequently used functions and hooks for menu_block_export.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Page callback to export menu blocks in bulk.
|
||||
*/
|
||||
function menu_block_export_export() {
|
||||
$blocks = variable_get('menu_block_ids', array());
|
||||
|
||||
if (!empty($blocks)) {
|
||||
$form_state = array(
|
||||
'no_redirect' => TRUE,
|
||||
);
|
||||
|
||||
$output = drupal_build_form('menu_block_export_form', $form_state);
|
||||
if (!empty($form_state['output'])) {
|
||||
$output = $form_state['output'];
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
else {
|
||||
return t('There are no menu blocks to be exported at this time.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; export form.
|
||||
*
|
||||
* @return
|
||||
* The export form used by Menu block.
|
||||
*/
|
||||
function menu_block_export_form($form, &$form_state) {
|
||||
$form['name'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Module name'),
|
||||
'#default_value' => 'custom',
|
||||
'#description' => t('Enter the module name to export code to.'),
|
||||
);
|
||||
$form['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Export'),
|
||||
);
|
||||
|
||||
$form['#action'] = url('admin/config/user-interface/menu-block/export/results');
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit callback for menu_block_export_form().
|
||||
*/
|
||||
function menu_block_export_form_submit(&$form, &$form_state) {
|
||||
$output = '';
|
||||
$module = check_plain($form_state['values']['name']);
|
||||
|
||||
foreach (variable_get('menu_block_ids', array()) AS $delta) {
|
||||
$config = menu_block_get_config($delta);
|
||||
// Use the constant instead of the constant's value.
|
||||
if ($config['menu_name'] == MENU_TREE__CURRENT_PAGE_MENU) {
|
||||
$config['menu_name'] = 'MENU_TREE__CURRENT_PAGE_MENU';
|
||||
}
|
||||
else {
|
||||
// If it's not the constant, wrap value in quotes.
|
||||
$config['menu_name'] = "'" . $config['menu_name'] . "'";
|
||||
}
|
||||
$output .= <<<END_OF_CONFIG
|
||||
|
||||
'$module-$delta' => array(
|
||||
'menu_name' => {$config['menu_name']},
|
||||
'parent_mlid' => {$config['parent_mlid']},
|
||||
'title_link' => {$config['title_link']},
|
||||
'admin_title' => '{$config['admin_title']}',
|
||||
'level' => {$config['level']},
|
||||
'follow' => {$config['follow']},
|
||||
'depth' => {$config['depth']},
|
||||
'expanded' => {$config['expanded']},
|
||||
'sort' => {$config['sort']},
|
||||
),
|
||||
END_OF_CONFIG;
|
||||
}
|
||||
|
||||
$output = <<<END_OF_CONFIG
|
||||
/**
|
||||
* Implements hook_menu_block_blocks().
|
||||
*/
|
||||
function {$module}_menu_block_blocks() {
|
||||
// The array key is the block delta used by menu block.
|
||||
return array($output
|
||||
);
|
||||
}
|
||||
|
||||
END_OF_CONFIG;
|
||||
|
||||
$element = array(
|
||||
'#type' => 'textarea',
|
||||
'#title' => t('Use this in your !module.module file:', array('!module' => $module)),
|
||||
'#value' => $output,
|
||||
'#rows' => 20,
|
||||
// Since this isn't a real form, manually add additional required properties.
|
||||
'#id' => 'menu-block-export-textarea',
|
||||
'#name' => 'export',
|
||||
'#required' => FALSE,
|
||||
'#attributes' => array('style' => 'font-family: monospace;'),
|
||||
'#title_display' => 'before',
|
||||
'#parents' => array('dummy'),
|
||||
);
|
||||
$form_state['output'] = drupal_render($element);
|
||||
}
|
18
sites/all/modules/menu_block/menu_block_export.info
Normal file
18
sites/all/modules/menu_block/menu_block_export.info
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
name = "Menu Block Export"
|
||||
description = "Provides export interface for Menu block module."
|
||||
|
||||
core = 7.x
|
||||
dependencies[] = menu_block
|
||||
|
||||
files[] = menu_block_export.module
|
||||
files[] = menu_block_export.admin.inc
|
||||
|
||||
configure = admin/config/user-interface/menu-block/export
|
||||
|
||||
; Information added by drupal.org packaging script on 2012-08-31
|
||||
version = "7.x-2.3+7-dev"
|
||||
core = "7.x"
|
||||
project = "menu_block"
|
||||
datestamp = "1346416665"
|
||||
|
33
sites/all/modules/menu_block/menu_block_export.module
Normal file
33
sites/all/modules/menu_block/menu_block_export.module
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides export interface for Menu block.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_menu().
|
||||
*/
|
||||
function menu_block_export_menu() {
|
||||
$items['admin/config/user-interface/menu-block/config'] = array(
|
||||
'title' => 'Configure',
|
||||
'type' => MENU_DEFAULT_LOCAL_TASK,
|
||||
);
|
||||
$items['admin/config/user-interface/menu-block/export'] = array(
|
||||
'title' => 'export',
|
||||
'description' => 'Export menu blocks.',
|
||||
'access arguments' => array('administer blocks'),
|
||||
'page callback' => 'menu_block_export_export',
|
||||
'type' => MENU_LOCAL_TASK,
|
||||
'file' => 'menu_block_export.admin.inc',
|
||||
);
|
||||
$items['admin/config/user-interface/menu-block/export/results'] = array(
|
||||
'title' => 'Menu block bulk export results',
|
||||
'description' => 'Exported menu blocks.',
|
||||
'access arguments' => array('administer blocks'),
|
||||
'page callback' => 'menu_block_export_export',
|
||||
'type' => MENU_CALLBACK,
|
||||
'file' => 'menu_block_export.admin.inc',
|
||||
);
|
||||
return $items;
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 415 B |
Binary file not shown.
After Width: | Height: | Size: 785 B |
Binary file not shown.
After Width: | Height: | Size: 719 B |
Binary file not shown.
After Width: | Height: | Size: 552 B |
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Provides ctools integration for "Menu block" trees.
|
||||
*
|
||||
* "Menu block" trees operate with no context at all. They are basically the
|
||||
* same as a 'custom content' block, but not even that sophisticated.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Plugins are described by creating a $plugin array which will be used
|
||||
* by the system that includes this file.
|
||||
*/
|
||||
$plugin = array(
|
||||
// And this is just the administrative title.
|
||||
// All our callbacks are named according to the standard pattern and can be deduced.
|
||||
'title' => t('Menu tree'),
|
||||
);
|
||||
|
||||
/**
|
||||
* Supplies a list of menu tree content sub-types.
|
||||
*/
|
||||
function menu_block_menu_tree_content_type_content_types() {
|
||||
$common_plugin = array(
|
||||
'description' => t('A configurable tree provided by Menu block.'),
|
||||
'icon' => 'icon_contrib_menu.png',
|
||||
'category' => array(t('Menus'), -9),
|
||||
|
||||
// The default context.
|
||||
'defaults' => menu_block_get_config(),
|
||||
|
||||
// JavaScript and CSS for the config form.
|
||||
'js' => array(drupal_get_path('module', 'menu_block') . '/menu-block.js'),
|
||||
'css' => array(drupal_get_path('module', 'menu_block') . '/menu-block-admin.css'),
|
||||
);
|
||||
unset($common_plugin['defaults']['delta']);
|
||||
|
||||
$menus = menu_block_get_all_menus();
|
||||
$items = array();
|
||||
foreach ($menus as $menu_name => $title) {
|
||||
$items[$menu_name] = $common_plugin;
|
||||
$items[$menu_name]['title'] = t('%menu menu tree', array('%menu' => $title));
|
||||
$items[$menu_name]['defaults']['menu_name'] = $menu_name;
|
||||
$items[$menu_name]['menu_title'] = $title;
|
||||
// Custom icons/titles for some menus.
|
||||
switch ($menu_name) {
|
||||
case MENU_TREE__CURRENT_PAGE_MENU:
|
||||
$items[$menu_name]['title'] = t('menu tree of %menu', array('%menu' => 'the menu selected by the page'));
|
||||
break;
|
||||
case 'main-menu':
|
||||
case 'secondary-menu':
|
||||
$items[$menu_name]['icon'] = 'icon_contrib_main_menu.png';
|
||||
break;
|
||||
case 'management':
|
||||
$items[$menu_name]['icon'] = 'icon_contrib_management.png';
|
||||
break;
|
||||
}
|
||||
if (strpos($menu_name, 'book-toc-') === 0) {
|
||||
$items[$menu_name]['icon'] = 'icon_contrib_booknavigation.png';
|
||||
}
|
||||
}
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a menu_tree content type based on the delta supplied in the configuration.
|
||||
*
|
||||
* @param $subtype
|
||||
* @param $conf
|
||||
* Configuration as done at admin time.
|
||||
* @param $args
|
||||
* @param $context
|
||||
* Context; in this case we don't have any.
|
||||
* @return
|
||||
* object An object with at least title and content members.
|
||||
*/
|
||||
function menu_block_menu_tree_content_type_render($subtype, $conf, $args, $context) {
|
||||
// Ensure the delta is unique.
|
||||
$ids = &drupal_static(__FUNCTION__, array());
|
||||
if (empty($ids[$conf['menu_name']])) {
|
||||
$ids[$conf['menu_name']] = 0;
|
||||
}
|
||||
$delta = ++$ids[$conf['menu_name']];
|
||||
$conf['delta'] = 'ctools-' . $conf['menu_name'] . '-' . $delta;
|
||||
|
||||
$tree = menu_tree_build($conf);
|
||||
|
||||
$block = new stdClass();
|
||||
$block->subtype = $conf['menu_name'];
|
||||
$block->title = $tree['subject'];
|
||||
$block->title_array = $tree['subject_array'];
|
||||
$block->content = $tree['content'];
|
||||
|
||||
return $block;
|
||||
}
|
||||
|
||||
/**
|
||||
* 'Edit form' callback for the content type.
|
||||
*/
|
||||
function menu_block_menu_tree_content_type_edit_form($form, &$form_state) {
|
||||
$conf = $form_state['conf'];
|
||||
|
||||
// Load the standard config form.
|
||||
module_load_include('inc', 'menu_block', 'menu_block.admin');
|
||||
// Create a pseudo form state.
|
||||
$sub_form_state = array('values' => $conf);
|
||||
$form += menu_block_configure_form($form, $sub_form_state);
|
||||
|
||||
// Hide the menu selector.
|
||||
$form['menu_name']['#type'] = 'hidden';
|
||||
|
||||
// Set the options to a simple list of menu links for the configured menu.
|
||||
$menus = menu_block_get_all_menus();
|
||||
$form['parent_mlid']['#options'] = menu_parent_options(array($conf['menu_name'] => $menus[$conf['menu_name']]), array('mlid' => 0));
|
||||
// Hide the Parent item option for the special "active" menu.
|
||||
if ($conf['menu_name'] == MENU_TREE__CURRENT_PAGE_MENU) {
|
||||
$form['parent_mlid']['#type'] = 'hidden';
|
||||
}
|
||||
// Remove CSS class hooks for jQuery script on parent select.
|
||||
unset($form['parent_mlid']['#attributes']);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit callback for content type editing form.
|
||||
*/
|
||||
function menu_block_menu_tree_content_type_edit_form_submit(&$form, &$form_state) {
|
||||
foreach (array_keys($form_state['subtype']['defaults']) as $key) {
|
||||
if (!empty($form_state['values'][$key])) {
|
||||
$form_state['conf'][$key] = $form_state['values'][$key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the tree's title with an admin-sensitive prefix.
|
||||
*/
|
||||
function menu_block_menu_tree_content_type_admin_title($subtype, $conf, $context = NULL) {
|
||||
if (!empty($conf['admin_title'])) {
|
||||
$output = filter_xss_admin($conf['admin_title']);
|
||||
}
|
||||
else {
|
||||
// Build the menu tree.
|
||||
module_load_include('inc', 'menu_block', 'menu_block.admin');
|
||||
$output = _menu_block_format_title($conf);
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to provide administrative info (the preview in panels when building a panel).
|
||||
*/
|
||||
function menu_block_menu_tree_content_type_admin_info($subtype, $conf, $context = NULL) {
|
||||
// Ensure the delta is unique.
|
||||
$ids = &drupal_static(__FUNCTION__, array());
|
||||
if (empty($ids[$conf['menu_name']])) {
|
||||
$ids[$conf['menu_name']] = 0;
|
||||
}
|
||||
$delta = ++$ids[$conf['menu_name']];
|
||||
$conf['delta'] = 'ctools-' . $conf['menu_name'] . '-' . $delta;
|
||||
|
||||
// Force the title to not be a link.
|
||||
$conf['title_link'] = 0;
|
||||
$tree = menu_tree_build($conf);
|
||||
|
||||
$block = new stdClass();
|
||||
$block->subtype = $conf['menu_name'];
|
||||
$block->title = $tree['subject'];
|
||||
$block->content = $tree['content'];
|
||||
|
||||
return $block;
|
||||
}
|
Reference in New Issue
Block a user