diff --git a/sites/all/modules/og_menu/LICENSE.txt b/sites/all/modules/og_menu/LICENSE.txt new file mode 100644 index 0000000000000000000000000000000000000000..d159169d1050894d3ea3b98e1c965c4058208fe1 --- /dev/null +++ b/sites/all/modules/og_menu/LICENSE.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/sites/all/modules/og_menu/README.txt b/sites/all/modules/og_menu/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..4b675724d282383ff76878f0c3f9003bfe52d409 --- /dev/null +++ b/sites/all/modules/og_menu/README.txt @@ -0,0 +1,83 @@ + +DESCRIPTION +----------- +Enable users to manage menus inside Organic Groups. + +REQUIREMENTS +------------ +- Organic Groups module (http://drupal.org/project/og). +- Menu module. + +INSTALLATION +------------ +- Enable the module. +- Give "administer og menu" permission to the desired roles. +- Visit the og menu configuration page to configure at will. +- Enable group content types for use with OG Menu. + +USAGE +----- +- Administrators can create OG menus through the regular menu interface at + admin/structure/menu/add. Choose a group to associate with the menu. +- Organic group members with the "administer og menu" permission can also manage + menus at node/[nid]/og_menu. +- "administer og menu" permission can be granted on global or group level. +- Group content types can be enabled for use with OG Menu. Once enabled, users + can add a menu link directly from the node creation form to any of the menu's + they have access to. +- For group types, users can create an associated menu by checking + "Enable menu for this group" on the node edit/creation form. +- You can enable the "OG Menu : single" and the "OG Menu : multiple" blocks at + admin/build/block. + - "OG Menu : single" will display the first available menu for the first + available group in the context. + - "OG Menu : multiple" will display all available menus for all available + groups in the context. +- OG menus won't show on the regular menu interface. They show up on + admin/structure/og_menu. +- Ability to hide OG Menu's from the block admin interface and on other places + for some contrib modules. + +NOTES +----- +Be aware that since menu administration forms are mostly duplicated, if a +contrib module adds functionality to menu administration forms without +additional permissions, these additions may be available for OG menu users with +'administer og menu' permission. This could allow these users to be able to do +things you don't want them to. Please report these modules if you catch one. + +TODO/BUGS/FEATURE REQUESTS +-------------------------- +- See http://drupal.org/project/issues/og_menu. Please search before filing + issues in order to prevent duplicates. +- Please test the D7 release and report any bugs or suggestions you might find. + +UPGRADING FROM 6.x TO 7.x +& +UPGRADING FROM 7.x-2.x TO 7.x-3.x +--------------------------------- +- There currently is no upgrade path! If you need an upgrade path, please file + an issue. + +CREDITS +------- +Originally authored and maintained by Scott Ash (ashsc). + +7.x-3.x port contributors (sorry if anyone was forgotten): + - bulldozer2003 + - zipymonkey + - jgraham + - Jackinloadup + - Wim Vanheste (rv0) (http://www.coworks.net) + +7.x initial port contributors: + - Stefan Vaduva (http://vamist.ro) + - Nick Santamaria (http://www.itomic.com.au) + - Frederik Grunta (Aeternum) + - Wim Vanheste (rv0) (http://www.coworks.net) + +7.x maintainers + - Wim Vanheste (rv0) (http://www.coworks.net) + +6.x-2.x maintainer + - Julien De Luca (jide) \ No newline at end of file diff --git a/sites/all/modules/og_menu/og_menu.css b/sites/all/modules/og_menu/og_menu.css new file mode 100644 index 0000000000000000000000000000000000000000..03247370747fd4e7cd5f0dec2c82f73b0fa17872 --- /dev/null +++ b/sites/all/modules/og_menu/og_menu.css @@ -0,0 +1,7 @@ +.block-og-menu-inset { + margin-bottom: 1.5em; +} + +div.block-og-menu-inset:last-child { + margin-bottom: 0em; +} \ No newline at end of file diff --git a/sites/all/modules/og_menu/og_menu.info b/sites/all/modules/og_menu/og_menu.info new file mode 100644 index 0000000000000000000000000000000000000000..e75b39a43650dad21716c4174ce4e5d341974ac2 --- /dev/null +++ b/sites/all/modules/og_menu/og_menu.info @@ -0,0 +1,17 @@ +name = OG Menu +description = "Allow group creators and site admins to edit their own group menu." +files[] = og_menu.module +dependencies[] = menu +dependencies[] = og (2.x) +dependencies[] = og_ui +dependencies[] = og_context +configure = admin/config/group/og_menu +package = "Organic groups" +core = 7.x + +; Information added by drupal.org packaging script on 2013-01-19 +version = "7.x-3.x-dev" +core = "7.x" +project = "og_menu" +datestamp = "1358558224" + diff --git a/sites/all/modules/og_menu/og_menu.install b/sites/all/modules/og_menu/og_menu.install new file mode 100644 index 0000000000000000000000000000000000000000..3bae9a5f098b5505eb187938d056022e9434929c --- /dev/null +++ b/sites/all/modules/og_menu/og_menu.install @@ -0,0 +1,126 @@ +<?php + +/** + * @file + * Install, update and uninstall functions for the og_menu module. + */ + +/** + * Implements hook_schema(). + */ +function og_menu_schema() { + $schema['og_menu'] = array( + 'description' => 'Stores relationships between organic groups and their custom menus.', + 'fields' => array( + 'menu_name' => array( + 'type' => 'varchar', + 'length' => 32, + 'not null' => TRUE, + 'default' => '', + ), + 'gid' => array( + 'description' => "The group's unique ID.", + 'type' => 'int', + 'size' => 'normal', + 'not null' => TRUE, + ), + 'group_type' => array( + 'description' => "The group's entity type (e.g., node, comment, etc').", + 'type' => 'varchar', + 'length' => '32', + 'not null' => TRUE, + 'default' => '', + ), + ), + 'primary key' => array('menu_name'), + 'foreign keys' => array( + 'menu_custom' => array( + 'table' => 'menu_custom', + 'columns' => array( + 'menu_name' => 'menu_name', + ) + ), + ), + ); + return $schema; +} + +/** + * Implements hook_uninstall(). + */ +function og_menu_uninstall() { + // List custom vars. + $vars = array( + 'og_menu_assignment', + 'og_menu_block_links', + 'og_menu_max_menus_per_group', + 'og_menu_show_blocks', + 'og_menu_show_homebox', + 'og_menu_show_menuposition', + 'og_menu_show_nodetype', + ); + // List all og_menu related node type settings vars. + $node_types = node_type_get_types(); + foreach ($node_types as $type) { + $vars[] = 'og_menu_enable_' . $type->type; + } + // Finally, delete all the vars we listed. + foreach ($vars as $var) { + variable_del($var); + } + // Delete custom menus. + $result = db_select('og_menu', 'm') + ->fields('m', array('menu_name')) + ->execute(); + while ($record = $result->fetchAssoc()) { + if ($menu = menu_load($record['menu_name'])) { + menu_delete($menu); + } + } +} + +/** + * Update og_menu schema to store group type in addition to gid. + */ +function og_menu_update_7300(&$sandbox) { + db_drop_primary_key('og_menu'); + db_query('ALTER TABLE {og_menu} MODIFY COLUMN menu_name varchar(32) NOT NULL DEFAULT \'\' FIRST'); + db_change_field('og_menu', 'gid', 'gid', array( + 'description' => "The group's unique ID.", + 'type' => 'int', + 'size' => 'normal', + 'not null' => TRUE, + )); + db_add_field('og_menu', 'group_type', array( + 'description' => "The group's entity type (e.g., node, comment, etc').", + 'type' => 'varchar', + 'length' => '32', + 'not null' => TRUE, + 'default' => 'node', + )); + db_field_set_default('og_menu', 'group_type', ''); + db_add_primary_key('og_menu', array('menu_name')); +} + +/** + * Enable OG Menu functionality for all group content types (backwards compatibility). + */ +function og_menu_update_7301(&$sandbox) { + $node_types = node_type_get_types(); + $group_content_types = array(); + foreach ($node_types as $type) { + if (og_is_group_content_type('node', $type->type)) { + variable_set('og_menu_enable_' . $type->type, TRUE); + $group_content_types[$type->type] = $type->name; + } + } + if (!empty($group_content_types)) { + drupal_set_message(t("For backwards compatibility reasons, this update has + enabled OG Menu functionality for the following group content types: + %types. You can manually disable this on the !ctypes settings page.", + array( + '%types' => implode(', ', $group_content_types), + '!ctypes' => l(t('content types'), 'admin/structure/types')) + )); + } +} diff --git a/sites/all/modules/og_menu/og_menu.js b/sites/all/modules/og_menu/og_menu.js new file mode 100644 index 0000000000000000000000000000000000000000..7802b3f5775844d4e92a43f8c975e068fc2334fd --- /dev/null +++ b/sites/all/modules/og_menu/og_menu.js @@ -0,0 +1,76 @@ +/** + * @file + * Javascript magic. Shows the eligible menu options when switching groups. + * + */ +(function ($) { + Drupal.behaviors.og_menu = { + + attach: function() { + // Initialize variables + var originalParent = $('.menu-parent-select').val(); + var enabled = $('#edit-menu-enabled').is(':checked'); + + var holder = document.createElement('select'); + var selectors = 'select[name^="og_group_ref"], input[name^="og_group_ref"]'; + + // Toggle menu alteration + function toggle(values) { + // make sure 'values' is always an array, i.e. when using single value select + if (!(values instanceof Array)) { + var v = values; + values = []; + values[0] = v; + } + + $('.menu-parent-select option:not(.value-none)').appendTo(holder); + + $.each(values, function(key, val) { + $('option', holder).each(function() { + parts = $(this).val().split(':'); + if (Drupal.settings.og_menu.admin === true) { + $(this).appendTo('.menu-parent-select'); + } + else { + if (Drupal.settings.og_menu.menus[parts[0]] == val) { + $(this).appendTo('.menu-parent-select'); + } + } + }); + }); + + // If an option exists with the initial value, set it. We do this because + // we want to keep the original parent if user just adds a group to the node. + if (values[0]) { + // Select the menu for the first available group. + for(var i in Drupal.settings.og_menu.menus) { + if ((enabled === true) && $('.menu-parent-select option[value='+originalParent+']')) { + $('.menu-parent-select').val(originalParent); + } + else if (Drupal.settings.og_menu.menus[i] == values[0]) { + $('.menu-parent-select').val(i + ':0'); + } + } + + } + } + + // Toggle function for OG select + var toggleSelect = function() { + if ($(this).val()) { + toggle($(this).val()); + } + }; + + // Alter menu on OG select change and init + if ($(selectors).size()) { + $(selectors).change(toggleSelect).ready(toggleSelect); + } + + // init + toggle($(selectors).val()); + } + + } + +}(jQuery)); \ No newline at end of file diff --git a/sites/all/modules/og_menu/og_menu.module b/sites/all/modules/og_menu/og_menu.module new file mode 100644 index 0000000000000000000000000000000000000000..5a3a22af10a7ce3e1045c2d21c41e5af90cd984c --- /dev/null +++ b/sites/all/modules/og_menu/og_menu.module @@ -0,0 +1,1112 @@ +<?php + +/** + * @file + * Integrates Menu with Organic Groups. + * Lots of menu forms duplication in OG context. + */ + +/** + * Implements hook_permission(). + */ +function og_menu_permission() { + return array( + 'administer og menu configuration' => array( + 'title' => t('Administer OG Menu configuration'), + 'description' => t('Grant access to the global OG Menu configuration.'), + ), + 'administer og menu' => array( + 'title' => t('Administer OG menus'), + 'description' => t('Administer custom menus for all groups.'), + ), + ); +} + +/** + * Implements hook_og_permission(). + */ +function og_menu_og_permission() { + return array( + 'administer og menu' => array( + 'title' => t('Administer OG menus'), + 'description' => t('Administer custom menus in the group context'), + ), + ); +} + +/** + * Implements hook_og_ui_get_group_admin(). + * */ +function og_menu_og_ui_get_group_admin($group_type, $gid) { + $items = array(); + + if (og_user_access($group_type, $gid, 'administer og menu')) { + $items['menus'] = array( + 'title' => t('Menus'), + 'description' => t('Manage group menus.'), + 'href' => 'admin/menus', + ); + } + + return $items; +} + +/** + * Implements hook_help(). + */ +function og_menu_help($path, $arg) { + switch ($path) { + case 'admin/structure/og_menu': + return '<p>' . t('Add new menus on the <a href="@menu">Menu administration page</a>.', array('@menu' => url('admin/structure/menu'))) . '</p>'; + break; + } + if ($path == 'group/%/%/admin/menus' && module_exists('block')) { + if (!variable_get('og_menu_show_blocks', FALSE)) { + return '<p>' . t('With the current setting, OG Menus will not be + exposed as blocks on the blocks administration page. Use the OG Menu + supplied menu blocks on the <a href="@blocks">Blocks administration + page</a>.', array('@blocks' => url('admin/structure/block'))) . '</p>'; + } + else { + return '<p>' . t('Each menu has a corresponding block that is managed on + the <a href="@blocks">Blocks administration page</a>.', + array('@blocks' => url('admin/structure/block'))) . '</p>'; + } + } +} + +/** + * Implements hook_menu(). + * + * @todo Add MENU_LOCAL_ACTION for adding an OG Menu? Meanwhile fix it in hook_help(). + */ +function og_menu_menu() { + $items = array(); + $items['group/%/%/admin/menus'] = array( + 'title' => 'Menus', + 'page callback' => 'og_menu_overview_page', + 'page arguments' => array(1, 2), + 'access callback' => 'og_menu_access', + 'access arguments' => array(1, 2), + 'weight' => 10, + 'file' => 'og_menu.pages.inc', + ); + $items['group/%/%/admin/menus/list'] = array( + 'title' => 'List menus', + 'weight' => -10, + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + $items['group/%/%/admin/menus/add'] = array( + 'title' => 'Add menu', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('og_menu_edit_menu_form', 'add', 1, 2), + 'access callback' => 'og_menu_access', + 'access arguments' => array(1, 2, 'new-menu'), + 'type' => MENU_LOCAL_ACTION, + 'weight' => 1, + 'file' => 'og_menu.pages.inc', + ); + $items['group/%/%/admin/menus/%menu'] = array( + 'title' => 'Customize menu', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('og_menu_overview_form', 1, 2, 5), + 'access callback' => 'og_menu_access', + 'access arguments' => array(1, 2), + 'type' => MENU_CALLBACK, + 'weight' => 1, + 'file' => 'og_menu.pages.inc', + ); + $items['group/%/%/admin/menus/%menu/list'] = array( + 'title' => 'List items', + 'weight' => -10, + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + $items['group/%/%/admin/menus/%menu/add'] = array( + 'title' => 'Add item', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('og_menu_edit_item_form', 'add', 1, 2, 5), + 'access callback' => 'og_menu_access', + 'access arguments' => array(1, 2), + 'type' => MENU_LOCAL_TASK, + 'weight' => 1, + 'file' => 'og_menu.pages.inc', + ); + $items['group/%/%/admin/menus/%menu/edit'] = array( + 'title' => 'Edit menu', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('og_menu_edit_menu_form', 'edit', 1, 2, 5), + 'access callback' => 'og_menu_access', + 'access arguments' => array(1, 2), + 'type' => MENU_LOCAL_TASK, + 'weight' => 1, + 'file' => 'og_menu.pages.inc', + ); + $items['group/%/%/admin/menus/%menu/delete'] = array( + 'title' => 'Delete menu', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('og_menu_delete_menu_confirm', 5, 1, 2), + 'access callback' => 'og_menu_access', + 'access arguments' => array(1, 2), + 'type' => MENU_CALLBACK, + 'weight' => 1, + 'file' => 'og_menu.pages.inc', + ); + $items['group/%/%/admin/menus/%menu/item/%menu_link/edit'] = array( + 'title' => 'Edit menu item', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('og_menu_edit_item_form', 'edit', 1, 2, 5, 7), + 'access callback' => 'og_menu_access', + 'access arguments' => array(1, 2), + 'type' => MENU_LOCAL_TASK, + 'weight' => 1, + 'file' => 'og_menu.pages.inc', + ); + $items['group/%/%/admin/menus/%menu/item/%menu_link/delete'] = array( + 'title' => 'Delete menu item', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('og_menu_delete_item_form', 7, 1, 2, 5), + 'access callback' => 'og_menu_access', + 'access arguments' => array(1, 2), + 'type' => MENU_CALLBACK, + 'weight' => 1, + 'file' => 'og_menu.pages.inc', + ); + $items['admin/config/group/og_menu'] = array( + 'title' => 'OG menu settings', + 'description' => 'Configuration for Organic groups menu', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('og_menu_config_form'), + 'access arguments' => array('administer og menu configuration'), + 'type' => MENU_NORMAL_ITEM, + 'file' => 'og_menu.pages.inc', + ); + $items['admin/structure/og_menu'] = array( + 'title' => 'Organic groups menus', + 'description' => 'Add new organic groups menus to your site, edit existing ones, and rename and reorganize menu links.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('og_admin_menu_overview_form'), + 'access callback' => 'user_access', + 'access arguments' => array('administer menu'), + 'type' => MENU_NORMAL_ITEM, + 'file' => 'og_menu.pages.inc', + ); + $items['og_menu/autocomplete'] = array( + 'page callback' => '_og_menu_autocomplete', + 'access arguments' => array('og_menu_access'), + 'type' => MENU_CALLBACK, + ); + return $items; +} + +/** + * Implements hook_theme_registry_alter(). + */ +function og_menu_theme_registry_alter(&$theme_registry) { + $theme_registry['block']['theme paths'][] = drupal_get_path('module', 'og_menu'); +} + +/** + * Implements hook_block_info(). + */ +function og_menu_block_info() { + $blocks = array( + 'og_single_menu_block' => array('info' => t('OG Menu : single'), 'cache' => DRUPAL_NO_CACHE), + 'og_multi_menu_block' => array('info' => t('OG Menu : multiple'), 'cache' => DRUPAL_NO_CACHE), + ); + return $blocks; +} + +/** + * Implements hook_block_view(). + */ +function og_menu_block_view($delta = '') { + $block = array(); + $context = og_context(); + if ($delta == 'og_single_menu_block' && $context) { + $menus = og_menu_get_group_menus(array( + $context['group_type'] => array($context['gid']) + )); + $menu = array_shift($menus); + + if ($menu) { + if (variable_get('og_menu_block_links', FALSE)) { + $block['subject'] = l($menu['title'], $menu['group_type'] . '/' . $menu['gid']); + } + else { + $block['subject'] = check_plain($menu['title']); + } + $block['content'] = menu_tree($menu['menu_name']); + } + } + if ($delta == 'og_multi_menu_block' && $context) { // @todo Test this!! + drupal_add_css(drupal_get_path('module', 'og_menu') . '/og_menu.css'); + drupal_add_css(drupal_get_path('module', 'og_menu') . '/og_menu.css'); + $menus = og_menu_get_group_menus(array( + $context['group_type'] => array($context['gid']) + )); + $plural = count($menus) > 1 ? TRUE : FALSE; + foreach ($menus as $menu) { + $title = ''; $content = ''; + if (variable_get('og_menu_block_links', FALSE)) { + $title = l($menu['title'], $menu['group_type'] . '/' . $menu['gid']); + } + else { + $title = check_plain($menu['title']); + } + if ($plural) { + $content = "<div class='block-og-menu-inset'><h2>{$title}</h2>" . render(menu_tree($menu['menu_name'])) . "</div>"; + } + else { + $block['subject'] = $title; + $content = render(menu_tree($menu['menu_name'])); + } + $block['content'] = isset($block['content']) ? $block['content'] . $content : $content; + if ($plural) { + $block['subject'] = ''; + } + } + } + return $block; +} + +/** + * Implements hook_field_extra_fields(). + */ +function og_menu_field_extra_fields() { + $extra = array(); + foreach (node_type_get_types() as $type) { + if (og_is_group_type('node', $type->type)) { // We only need to enable OG Menu on group types. + $extra['node'][$type->type] = array( + 'form' => array( + 'og_menu' => array( + 'label' => t('OG Menu'), + 'description' => t('Enable OG Menu'), + 'weight' => 0, + ) + ) + ); + } + } + return $extra; +} + +/** + * Returns the current group context's nid. + */ +function og_menu_get_context() { + $context = og_context(); + return (isset($context['gid']) ? $context['gid'] : 0); +} + +/** + * Implements hook_form_FORMID_alter(). + * + * Alter the node form's menu form. + * We modify the forms for group content and group content types. + */ +function og_menu_form_node_form_alter(&$form, &$form_state) { + $type = $form['#node']->type; + // Group type. + if (og_is_group_type('node', $type)) { + $og_menu_default_value = isset($form['nid']['#value']) ? !empty($form['#node']->og_menu) : variable_get('og_menu_create_by_default', FALSE); + $form['og_menu'] = array( + '#type' => 'checkbox', + '#title' => t('Enable menu for this group'), + '#default_value' => $og_menu_default_value, + '#description' => t('Check to create a menu for this group. Uncheck to delete all menus associated with this group.'), + ); + // @todo If we're going to delete all of the groups menus, + // we should ask the user for confirmation + //$form['#submit'][] = 'og_menu_group_form_validate'; + } + if (og_is_group_content_type('node', $type) + && variable_get('og_menu_enable_' . $type, FALSE)) { + // If there is context and the user doesn't have permission on the group, + // they shouldn't be allowed to change the menu at all. + $context = og_context(); + if ($context && !og_user_access($context['group_type'], $context['gid'], 'administer og menu') && !user_access('administer menu') && !user_access('administer og menu')) { + return; + } + // Available menus were discovered in og_menu_node_prepare(). + $menus = $form['#node']->storage['og_menu']; + $list = array(); + $settings['admin'] = user_access('administer menu'); + if (!empty($menus)) { + foreach ($menus as $menu) { + $list[$menu['menu_name']] = $menu['title']; + $settings['menus'][$menu['menu_name']] = $menu['gid']; + } + // If user has administer menu permission, also show other menu options. + if (user_access('administer menu')) { + // Gets menus available to this content type. + $type_menus = variable_get('menu_options_' . $type, array('main-menu' => 'main-menu')); + $available_menus = array(); + // Get all existing menus with their name. + $result = db_query("SELECT menu_name, title FROM {menu_custom} ORDER BY title"); + while ($menu = $result->fetchObject()) { + if (in_array($menu->menu_name, $type_menus)) { + $available_menus[$menu->menu_name] = $menu->title; + } + } + // We want to merge the menus the user has available anyway and the OG ones + $merged_list = array_merge($available_menus, $list); + } + else { + $merged_list = $list; + } + + $link = $form['#node']->menu; + + // Menu parent options will format the list in a way Drupal expects and give children, etc + $options = menu_parent_options($merged_list, array('mlid' => 0)); + + // If user does not have administer menu, this fieldset wont be created. + if (!isset($form['menu'])) { + if (empty($options)) { + return; + } + _og_menu_add_menufieldset($form, $options); + } + + if ($nid = $form['nid']['#value']) { + $form['menu']['link']['parent']['#default_value'] = $link['menu_name'] . ':' . $link['plid']; + } + $form['menu']['#access'] = !empty($options); + $form['menu']['#attached']['js'][] = drupal_get_path('module', 'og_menu') . '/og_menu.js'; + $form['menu']['#attached']['js'][] = array( + 'data' => array('og_menu' => $settings), + 'type' => 'setting', + ); + $form['menu']['#settings'] = $merged_list; + $form['menu']['link']['parent']['#options'] = $options; + if (!user_access('administer menu')) { + $form['#validate'][] = 'og_menu_node_form_validate'; + } + } + } +} + + +/** + * Implements hook_menu_insert(). + * + * This is used to automatically add links a series of + * predefined links to a new OG Menu. + */ +function og_menu_menu_insert($menu) { + // Check to see if this is the many og_menu + if (preg_match('/^menu-og-(\d+)$/', $menu['menu_name'], $matches)) { + + // Get Default Menu Items from variable + $node = node_load($matches[1]); + $default_links = explode("\n", variable_get('og_menu_default_links_' . strtolower($node->type), '')); + + foreach ($default_links as $default_link) { + $link_parts = explode("|", $default_link); + $link_parts[0] = token_replace($link_parts[0], array('node' => node_load($matches[1]))); + // Create link + $link = array( + 'link_path' => $link_parts[0], + 'link_title' => (isset($link_parts[1])) ? $link_parts[1]: $link_parts[0], + 'menu_name' => $menu['menu_name'], + 'router_path' => 'faculty/%', + ); + $mlid = menu_link_save($link); + } + } +} + +/** + * Implements hook_form_FORMID_alter(). + */ +function og_menu_form_menu_edit_menu_alter(&$form, &$form_state) { + $types = node_type_get_types(); + $gtypes = array(); + foreach ($types as $type) { + if (og_is_group_type('node', $type->type)) + $gtypes[] = $type->type; + } + + $types = $gtypes; + + if (count($types) > 0) { + $options = array('' => '--'); + $values = array(); + // Populate gids + if (user_access('administer group')) { + $result = db_query("SELECT distinct ogm.gid, n.title FROM {og_membership} ogm LEFT JOIN {node} n ON n.nid = ogm.gid WHERE entity_type='node'"); + foreach ($result as $group) { + $options[$group->gid] = $group->title; + } + } + else { + global $user; + + $gids = og_menu_get_node_groups('user', $user); + $groups = node_load_multiple($gids); + if (!empty($groups)) { + foreach ($groups as $gid => $group) { + $options[$gid] = $group->title; + } + } + } + + $ogm = db_select('og_menu', 'gid') + ->fields('gid') + ->condition('menu_name', $form['menu_name']['#default_value'], '=') + ->execute() + ->fetchAssoc(); + $gid = $ogm['gid']; + + $og = $gid ? entity_load_single('node', $gid) : NULL; + // Add menu og assignment to the form + switch (variable_get('og_menu_assignment', 'autocomplete')) { + case 'autocomplete': + $form['og_menu_gid'] = array( + '#title' => t('Enable this menu for the following group'), + '#type' => 'textfield', + '#default_value' => !is_null($gid) ? $og->title . ' [gid:' . $gid . ']' : '', + '#autocomplete_path' => 'og_menu/autocomplete', + ); + break; + + case 'select': + $form['og_menu_gid'] = array( + '#title' => t('Enable this menu for the following group'), + '#type' => 'select', + '#options' => $options, + '#default_value' => !is_null($gid) ? $gid : '', + '#weight' => 1, + ); + break; + default; + } + if (!user_access('administer menu')) { + $form['og_menu_gid']['#required'] = TRUE; + } + if (!isset($form['submit']['#weight'])) { + $form['submit']['#weight'] = 2; + } + $form['#submit'][] = 'og_menu_edit_menu_form_submit'; + } +} + +/** + * Implements hook_form_FORMID_alter(). + * + * Integration with menu module for node type admin page. + * Hides OG Menus from available menu settings. + */ +function og_menu_form_node_type_form_alter(&$form, &$form_state) { + if (!variable_get('og_menu_show_nodetype', FALSE)) { + // Remove OG Menus from the list by default. + $result = db_query("SELECT mc.menu_name FROM {menu_custom} mc, {og_menu} ogm WHERE ogm.menu_name = mc.menu_name")->fetchCol(); + foreach ($result as $ogblock) { + unset($form['menu']['menu_options']['#options'][$ogblock]); + } + } + // Provide a setting to enable OG Menus on this content type. + $form['menu']['og_menu_enable'] = array( + '#type' => 'checkbox', + '#title' => t("Enable for OG Menus"), + '#default_value' => variable_get('og_menu_enable_' . $form['#node_type']->type, FALSE), + '#description' => t("Allow nodes of this content type to be added to OG Menus."), + ); + if (!og_is_group_content_type('node', $form['#node_type']->type)) { + $form['menu']['og_menu_enable']['#description'] .= ' <strong>'; + $form['menu']['og_menu_enable']['#description'] .= t("This setting will not + have any effect until you enable this type as Group Content"); + $form['menu']['og_menu_enable']['#description'] .= '</strong>'; + } +} + +/** + * Implements hook_form_FORMID_alter(). + * + * Integration with Menu Position module for menu_position config page. + * Hides OG Menus from available parent options settings. + */ +function og_menu_form_alter(&$form, &$form_state, $form_id) { + if ($form_id == 'menu_position_add_rule_form' || $form_id == 'menu_position_edit_rule_form') { + if (!variable_get('og_menu_show_menuposition', FALSE)) { + $mlid = !empty($form_state['#menu-position-rule']['mlid']) ? $form_state['#menu-position-rule']['mlid'] : NULL; + $menus = menu_get_menus(); + // @todo convert to new database api functions + $result = db_query("SELECT mc.menu_name FROM {menu_custom} mc, {og_menu} ogm WHERE ogm.menu_name = mc.menu_name")->fetchCol(); + foreach ($result as $ogblock) { + unset($menus[$ogblock]); + } + // Parent menu item. + if ($mlid) { + $options = menu_parent_options($menus, menu_link_load($mlid)); + } + else { + $options = menu_parent_options($menus, array('mlid' => 0)); + } + $form['plid']['#options'] = $options; + } + } +} + +/** + * Implements hook_form_FORMID_alter(). + */ +function og_menu_form_block_admin_display_form_alter(&$form, &$form_state) { +// Only show og menu blocks on the block admin page if the user wants it. + if (!variable_get('og_menu_show_blocks', FALSE)) { + // @todo convert to new database api functions + $result = db_query("SELECT mc.menu_name FROM {menu_custom} mc, {og_menu} ogm WHERE ogm.menu_name = mc.menu_name")->fetchCol(); + foreach ($result as $ogblock) { + unset($form['blocks']['menu_' . $ogblock]); + } + } +} + +/** + * Implements hook_form_FORMID_alter(). + */ +function og_menu_form_menu_delete_menu_confirm_alter(&$form, &$form_state) { + $form['#submit'][] = 'og_menu_delete_menu_confirm_submit'; +} + +/** + * Implements hook_form_FORMID_alter(). + * + * Integration with homebox module. + * Hides OG Menus from Homebox config page. + */ +function og_menu_form_homebox_admin_display_form_alter(&$form, &$form_state) { + if (!variable_get('og_menu_show_homebox', FALSE)) { + // @todo convert to new database api functions + $result = db_query("SELECT mc.menu_name FROM {menu_custom} mc, {og_menu} ogm WHERE ogm.menu_name = mc.menu_name")->fetchCol(); + foreach ($result as $ogblock) { + unset($form['menu_' . $ogblock]); + } + } +} + +/** + * Implements hook_node_prepare(). + */ +function og_menu_node_prepare($node) { + $type = $node->type; + // $node is a group type. + if (og_is_group_type('node', $type)) { + if (!empty($node->nid)) { + $node->og_menu = og_menu_get_group_menus(array( + 'node' => array($node->nid) + )); + } + } + if (og_is_group_content_type('node', $type)) { + // If there is context and the user doesn't have permission on the group, + // they shouldn't be allowed to change the menu at all. + $context = og_context(); + if ($context && !og_user_access($context['group_type'], $context['gid'], 'administer og menu') && !user_access('administer menu') && !user_access('administer og menu')) { + return; + } + $groups = array(); + $og_fields = og_get_group_audience_fields('node', $type); + foreach ($og_fields as $field_name => $label) { + $field = field_info_field($field_name); + $target_type = $field['settings']['target_type']; + // The handler delivers all available targets for each content type, skip + // the ids if we already have that type's results. + if (empty($groups[$target_type])) { + $instance = field_info_instance('node', $field_name, $type); + $instance['field_mode'] = 'default'; + // Using the handler allows us to get user options from OG without + // running through all the user's groups. + $ids = entityreference_get_selection_handler($field, $instance)->getReferencableEntities(); + if (!empty($ids)) { + $field_gids = array(); + foreach ($ids as $key => $values) { + $field_gids += $values; + } + // Create an array similar to what og_get_entity_groups() returns. + $groups[$target_type] = array_keys($field_gids); + } + } + } + $menus = og_menu_get_group_menus($groups); + // Store the menus for later use in form_alter and form_validate + $node->storage['og_menu'] = $menus; + // $node is not a new node and menu link is not set + if (!empty($node->nid) && empty($node->menu['link_title']) && !empty($menus)) { + $menu_names = array(); + foreach ($menus as $menu) { + $menu_names[] = $menu['menu_name']; + } + // This query comes from menu.modules node_prepare, and is how it does it. + $mlid = db_query_range("SELECT mlid FROM {menu_links} WHERE link_path = :path AND module = 'menu' AND menu_name IN (:type_menus) ORDER BY mlid ASC", 0, 1, array( + ':path' => 'node/' . $node->nid, + ':type_menus' => $menu_names, + )) + ->fetchField(); + if ($mlid) { + // We've found something, so load the item and set that in the node form + $item = menu_link_load($mlid); + $options = menu_parent_options(array($item['menu_name']), $item); + if (!empty($options)) { + $node->menu = $item; + // Find the depth limit for the parent select. + if (!isset($node->menu['parent_depth_limit'])) { + $node->menu['parent_depth_limit'] = _menu_parent_depth_limit($node->menu); + } + } + } + } + } +} + +/** + * Implements hook_node_insert(). + */ +function og_menu_node_insert($node) { + if (og_is_group_type('node', $node->type)) { + if ($node->og_menu) { + menu_save(array( + 'menu_name' => 'menu-og-' . $node->nid, + 'title' => $node->title, + 'description' => t('OG Menu for') . ' ' . check_plain($node->title), + )); + og_menu_update_menu('menu-og-' . $node->nid, $node->nid, 'node'); + } + } +} + +/** + * Implements hook_node_update(). + */ +function og_menu_node_update($node) { + if (og_is_group_type('node', $node->type)) { + if (isset($node->og_menu)) { + if ($node->og_menu) { + $menu = og_menu_get_group_menus(array('node' => array($node->nid))); + if (empty($menu)) { + menu_save(array( + 'menu_name' => 'menu-og-' . $node->nid, + 'title' => $node->title, + 'description' => t('OG Menu for') . ' ' . check_plain($node->title), + )); + og_menu_update_menu('menu-og-' . $node->nid, $node->nid, 'node'); + } + } + else { + // Delete the associated menus. + // We can't assume that the menu name is 'menu-og-[gid]' + // we need to look up menus associated with this group + $result = db_select('og_menu', 'm') + ->fields('m', array('menu_name')) + ->condition('gid', $node->nid, '=') + ->condition('group_type', 'node', '=') + ->execute(); + + while ($record = $result->fetchAssoc()) { + $menu = menu_load($record['menu_name']); + menu_delete($menu); + og_menu_delete_menu($record['menu_name']); + } + } + } + // else = programmatic node save, do nothing. + } +} + +/** + * Implements hook_node_delete(). + */ +function og_menu_node_delete($node) { + if (og_is_group_type('node', $node->type)) { + /* We need to be careful here. As users can create menu of whatever name, + * we can't just delete from menu_custom looking for 'menu-og-' . [gid] + * we need the gid of the group being deleted, see if its an og assosiated + * menu from og_menu and then from that menu name, delete it. + */ + $result = db_select('og_menu', 'm') + ->fields('m', array('menu_name')) + ->condition('gid', $node->nid, '=') + ->condition('group_type', 'node', '=') + ->execute(); + + while ($record = $result->fetchAssoc()) { + $menu = menu_load($record['menu_name']); + menu_delete($menu); + og_menu_delete_menu($record['menu_name']); + } + } +} + +/** + * Validation handler for OG group node forms. + * We will only end up here if we have confirmed that the node is a group type content + */ +function og_menu_node_form_validate($form, &$form_state) { + // If the user didn't ask for a menu, we have nothing to do. + if (!isset($form_state['values']['menu']['enabled']) || $form_state['values']['menu']['enabled'] !== 1) { + return; + } + + // Available menus were discovered in og_menu_node_prepare(). + $menus = $form['#node']->storage['og_menu']; + $parents = explode(':', $form_state['values']['menu']['parent']); + $parent = $parents[0]; + $gids = array(); + $has_menu_access = FALSE; + + $group_is_set = FALSE; + + foreach (og_get_group_audience_fields('node', $form_state['values']['type']) as $field_name => $label) { + if (isset($form_state['values'][$field_name][LANGUAGE_NONE])) { + $group_is_set = TRUE; + foreach ($form_state['values'][$field_name][LANGUAGE_NONE] as $item => $gid) { + $gids[] = $gid['target_id']; + } + } + } + + if (!$group_is_set) { + // It's possible that the user doesn't have permission to change + // the group audience once a piece of content has been created. + // In this case, we need to look it up. + $gids = og_get_entity_groups('node', $form_state['node']); + } + foreach ($menus as $menu) { + if ($menu['menu_name'] == $parent) { + // Check if user has access to the chosen menu parent + $has_menu_access = TRUE; + // Check if menu belongs to one of the selected groups + if (!in_array($menu['gid'], $gids)) { + form_set_error('og_groups', t('The menu you chose does not belong to the selected groups.')); + } + } + } + if (!$has_menu_access) { + form_set_error('menu][parent', t('You cannot add menu items to this menu. Choose another parent menu.')); + } +} + +/** + * Updates internal record of group's menu id + */ +function og_menu_update_menu($menu_name, $gid, $group_type) { + db_merge('og_menu') + ->key(array('menu_name' => $menu_name)) + ->fields(array( + 'gid' => $gid, + 'group_type' => $group_type, + )) + ->execute(); +} + +/** + * Deletes menus for og menu table. + */ +function og_menu_delete_menu($menu_name) { + db_delete('og_menu') + ->condition('menu_name', $menu_name) + ->execute(); +} + +/** + * Returns acessible menus for a given user or gids in a structured array. + * + * @param gids + * An optional array of groups as returned by og_get_entity_groups(). + * @param user + * An optional array of the user object. + * @return + * A structured array with menus list. + */ +function og_menu_get_group_menus($groups = NULL, $user = NULL) { + if (!$groups) { + $groups = og_get_entity_groups('user', $user); + } + $menus = array(); + foreach ($groups as $group_type => $gids) { + foreach ($gids as $gid) { + $query = db_select('og_menu', 'om'); + $query + ->join('menu_custom', 'm', 'om.menu_name = m.menu_name'); + $query + ->fields('om', array('gid', 'group_type', 'menu_name')) + ->fields('m', array('title')) + ->condition('om.gid', $gid, '=') + ->condition('om.group_type', $group_type, '='); + $result = $query->execute(); + while ($record = $result->fetchAssoc()) { + $menus[] = $record; + } + } + } + return $menus; +} + +/** + * Access function. + * + * @param node + * The group node for which the menu is edited. + * @param menu + * The edited menu. + */ +function og_menu_access($group_type, $gid, $op = NULL) { + if (!og_is_group($group_type, $gid)) { + return FALSE; + } + elseif (user_access('administer menu')) { + return TRUE; + } + elseif (user_access('administer og menu') || og_user_access_entity('administer og menu', $group_type, $gid)) { + if ($op == 'new-menu') { + $query = db_select('og_menu', 'ogm'); + $query->condition('ogm.gid', $gid, '='); + $count = $query->countQuery()->execute()->fetchField(); + $max = variable_get('og_menu_max_menus_per_group', 1); + if ($max > 0 && $count >= $max) { + return FALSE; + } + else { + return TRUE; + } + } + else { + // return true for all other cases edit menu, add/edit links + return TRUE; + } + } + return FALSE; +} + +/** + * Generic redirect function. + * + * @param form + * The form array. + * @param form_state + * The form_state array. + */ +function og_menu_redirect($form, &$form_state) { + $group_type = $form['og_menu_group_type']['#value']; + $gid = $form['og_menu_gid']['#value']; + $menu_name = $form['og_menu_name']['#value']; + $form_state['redirect'] = 'group/' . $group_type . '/' . $gid . '/admin/menus/' . $menu_name; +} + +/** + * Submit handler used on various forms. + */ +function og_menu_edit_menu_form_submit($form, &$form_state) { + $menu_name = $form_state['values']['menu_name']; + $gid = $form_state['values']['og_menu_gid']; + if (!empty($gid)) { + // If this is a new menu. + if ($form['#insert']) { + $menu_name = 'menu-' . $menu_name; + } + if (is_numeric($gid)) { + og_menu_update_menu($menu_name, $gid, 'node'); + } + else { + preg_match('/^(?:\s*|(.*) )?\[\s*gid\s*:\s*(\d+)\s*\]$/', $gid, $matches); + if (!empty($matches)) { + $gid = $matches[count($matches) - 1]; + if (is_numeric($gid)) { + og_menu_update_menu($menu_name, $gid, 'node'); + } + } + else { + drupal_set_message(t('Cannot assign menu to invalid group, please retry'), 'error'); + } + } + } +} + +/** + * Submit handler used on various forms. + */ +function og_menu_delete_menu_confirm_submit($form, &$form_state) { + $menu = $form['#menu']; + og_menu_delete_menu($menu['menu_name']); +} + +/** + * Submit handler used on various forms. + */ +function og_menu_delete_menu_confirm_submit_redirect($form, &$form_state) { + $group_type = $form['og_menu_group_type']['#value']; + $gid = $form['og_menu_gid']['#value']; + $form_state['redirect'] = 'group/' . $group_type . '/' . $gid . '/admin/menus'; +} + +/** + * Implements hook_menu_delete(). + * + * Looks like og_menu didn't used to catch the case where a menu item was deleted + * in the admin area, and forgot to delete it's own db_record + */ +function og_menu_menu_delete($menu) { + db_delete('og_menu')->condition('menu_name', $menu['menu_name'])->execute(); +} + +/** + * Override menu.module's menu_overview_page(). + * + * We do this so that we can filter out og_menu created menus from the listing + * so that we don't flood the admin pages. + * + * @todo get this into og_menu_pages.inc + * + */ +function og_admin_standard_menu_overview_page() { + $result = db_query("SELECT * + FROM {menu_custom} mc + WHERE NOT EXISTS (SELECT om.menu_name + FROM {og_menu} om + WHERE om.menu_name = mc.menu_name) + ORDER BY title;", array(), array('fetch' => PDO::FETCH_ASSOC)); + $header = array(t('Title'), array( + 'data' => t('Operations'), + 'colspan' => '3', + )); + $rows = array(); + foreach ($result as $menu) { + $row = array(theme('menu_admin_overview', array('title' => $menu['title'], 'name' => $menu['menu_name'], 'description' => $menu['description']))); + $row[] = array('data' => l(t('list links'), 'admin/structure/menu/manage/' . $menu['menu_name'])); + $row[] = array('data' => l(t('edit menu'), 'admin/structure/menu/manage/' . $menu['menu_name'] . '/edit')); + $row[] = array('data' => l(t('add link'), 'admin/structure/menu/manage/' . $menu['menu_name'] . '/add')); + $rows[] = $row; + } + + return theme('table', array('header' => $header, 'rows' => $rows)); +} + +/** + * Implements hook_menu_alter(). + * + * We use this to override the /admin/structure/menu callback and replace it with + * our own og_admin_menu_overview_page(). + */ +function og_menu_menu_alter(&$items) { + $items['admin/structure/menu']['page callback'] = 'og_admin_standard_menu_overview_page'; + $items['admin/structure/menu']['file'] = 'og_menu.module'; + $items['admin/structure/menu']['module'] = 'og_menu'; +} + +/** + * Retrieve autocomplete suggestions for organic groups + */ +function _og_menu_autocomplete($string) { + $matches = array(); + $query = db_select('node', 'n'); + $query->distinct(); + $query->join('og_membership', 'og', 'n.nid = og.gid'); + $query->fields('og', array('gid')); + $query->fields('n', array('title')); + $query->condition('n.title', '%' . db_like($string) . '%', 'LIKE'); + $query->range(0, 10); + $return = $query->execute(); + foreach ($return as $row) { + $matches[$row->title . " [gid:$row->gid]"] = '<div class="og-autocomplete">' . $row->title . '</div>'; + } + // return for JS + drupal_json_output($matches); +} + +/** + * Return a list of node groups corresponding to nodes + * + * @see og_get_entity_groups() + * @param string $group_type the entity type .eg node, user + * @param object the object in question .eg node user + * @return array the gids corresponding to the criteria or empty + */ +function og_menu_get_node_groups($group_type, $object) { + $groups = og_get_entity_groups($group_type, $object); + + if (!empty($groups['node'])) { + $gids = $groups['node']; + } + else { + $gids = array(); + } + + return $gids; +} + +/** + * Adds a standard menu fieldset to a form, mainly copied from menu.module. + * + * @param type $form the form we will add a menu fieldset to + * @param type $optione + */ +function _og_menu_add_menufieldset(&$form, $options) { + $link = $form['#node']->menu; + + $form['menu'] = array( + '#type' => 'fieldset', + '#title' => t('Menu settings'), + '#collapsible' => TRUE, + '#collapsed' => !$link['link_title'], + '#group' => 'additional_settings', + '#attached' => array( + 'js' => array(drupal_get_path('module', 'menu') . '/menu.js'), + ), + '#tree' => TRUE, + '#weight' => -2, + '#attributes' => array('class' => array('menu-link-form')), + ); + $form['menu']['enabled'] = array( + '#type' => 'checkbox', + '#title' => t('Provide a menu link'), + '#default_value' => (int) (bool) $link['mlid'], + ); + $form['menu']['link'] = array( + '#type' => 'container', + '#parents' => array('menu'), + '#states' => array( + 'invisible' => array( + 'input[name="menu[enabled]"]' => array('checked' => FALSE), + ), + ), + ); + + // Populate the element with the link data. + foreach (array('mlid', 'module', 'hidden', 'has_children', 'customized', 'options', 'expanded', 'hidden', 'parent_depth_limit') as $key) { + $form['menu']['link'][$key] = array('#type' => 'value', '#value' => $link[$key]); + } + + $form['menu']['link']['link_title'] = array( + '#type' => 'textfield', + '#title' => t('Menu link title'), + '#default_value' => $link['link_title'], + ); + + $form['menu']['link']['description'] = array( + '#type' => 'textarea', + '#title' => t('Description'), + '#default_value' => isset($link['options']['attributes']['title']) ? $link['options']['attributes']['title'] : '', + '#rows' => 1, + '#description' => t('Shown when hovering over the menu link.'), + ); + + $default = ($link['mlid'] ? $link['menu_name'] . ':' . $link['plid'] : NULL); + if (!isset($options[$default])) { + $array = array_keys($options); + $default = reset($array); + } + $form['menu']['link']['parent'] = array( + '#type' => 'select', + '#title' => t('Parent item'), + '#default_value' => $default, + '#options' => $options, + '#attributes' => array('class' => array('menu-parent-select')), + ); + $form['menu']['link']['weight'] = array( + '#type' => 'weight', + '#title' => t('Weight'), + '#delta' => 50, + '#default_value' => $link['weight'], + '#description' => t('Menu links with smaller weights are displayed before links with larger weights.'), + ); +} \ No newline at end of file diff --git a/sites/all/modules/og_menu/og_menu.pages.inc b/sites/all/modules/og_menu/og_menu.pages.inc new file mode 100644 index 0000000000000000000000000000000000000000..fd2d81a79d2b5e91841b2d196f2d756b58cb133b --- /dev/null +++ b/sites/all/modules/og_menu/og_menu.pages.inc @@ -0,0 +1,505 @@ +<?php + +/** + * @file + * Contains page callbacks for og_menu + */ + +/** + * Menu callback which shows an overview page of all the custom menus in a + * user's group and along with their description. + */ +function og_menu_overview_page($group_type, $gid) { + // Set the title of the page. + $entity_wrapper = entity_metadata_wrapper($group_type, $gid); + $entity_label = $entity_wrapper->label() ? $entity_wrapper->label() : $group_type . ' ' . $gid; + drupal_set_title(t('List menus for %title', array('%title' => $entity_label)), PASS_THROUGH); + // Set the breadcrumb. + og_set_breadcrumb($group_type, $gid, array(l(t('Group'), "$group_type/$gid/group"))); + + // @todo Replace by D7 database independent functions. + $result = db_query(" + SELECT om.gid, om.menu_name as name, m.title as title, m.description as description FROM {og_menu} om + LEFT JOIN {menu_custom} m + ON om.menu_name = m.menu_name + WHERE om.gid = :gid + ORDER BY title", array(':gid' => $gid)); + $header = array(t('Title'), array('data' => t('Operations'), 'colspan' => '3')); + $rows = array(); + foreach ($result as $menu) { + $row = array(theme('menu_admin_overview', array('title' => $menu->title, 'name' => $menu->name, 'description' => $menu->description))); + $row[] = array('data' => l(t('list links'), 'group/' . $group_type . '/' . $gid . '/admin/menus/' . $menu->name)); + $row[] = array('data' => l(t('edit menu'), 'group/' . $group_type . '/' . $gid . '/admin/menus/' . $menu->name . '/edit')); + $row[] = array('data' => l(t('add link'), 'group/' . $group_type . '/' . $gid . '/admin/menus/' . $menu->name . '/add')); + $rows[] = $row; + } + + if ($result->rowCount() == 0) { + return t('There are currently no menus.'); + } + else { + return theme('table', array('header' => $header, 'rows' => $rows)); + } +} + +/** + * Menu callback; Build the form that handles the adding/editing of a custom menu. + */ +function og_menu_edit_menu_form($form, &$form_state, $type, $group_type, $gid, $menu = array()) { + module_load_include('inc', 'menu', 'menu.admin'); + $entity_wrapper = entity_metadata_wrapper($group_type, $gid); + $label = $entity_wrapper->label(); + // Set the breadcrumb. + og_set_breadcrumb($group_type, $gid, array(l(t('Group'), "$group_type/$gid/group"))); + + // Set the title of the page. + switch ($type) { + case 'add': drupal_set_title(t('Add menu for @title', array('@title' => $label)), PASS_THROUGH); + break; + + case 'edit': drupal_set_title(t('Edit menu for @title', array('@title' => $label)), PASS_THROUGH); + break; + } + + // Build the form. + $form = array(); + $form = menu_edit_menu($form, $form_state, $type, $menu); + $form['og_menu_group_type'] = array( + '#type' => 'value', + '#value' => $group_type, + ); + $form['og_menu_gid'] = array( + '#type' => 'value', + '#value' => $gid, + ); + if ($type == 'edit') { + $form['og_menu_name'] = array( + '#type' => 'value', + '#value' => $menu['menu_name'], + ); + } + // Add submit handlers. + $form['#submit'][] = 'menu_edit_menu_submit'; + $form['#submit'][] = 'og_menu_edit_menu_form_submit'; + $form['#submit'][] = 'og_menu_edit_menu_form_submit_redirect'; + $form['actions']['delete']['#submit'][0] = 'og_menu_delete_menu_form_submit'; + return $form; +} + +/** + * Submit handler for og_menu_edit_menu_form + */ +function og_menu_delete_menu_form_submit($form, &$form_state) { + $group_type = $form['og_menu_group_type']['#value']; + $gid = $form['og_menu_gid']['#value']; + $menu_name = $form['og_menu_name']['#value']; + $form_state['redirect'] = 'group/' . $group_type . '/' . $gid . '/admin/menus/' . $menu_name . '/delete'; +} + +/** + * Submit handler which handles redirection for og_menu_edit_menu_form form. + */ +function og_menu_edit_menu_form_submit_redirect($form, &$form_state) { + $group_type = $form['og_menu_group_type']['#value']; + $gid = $form['og_menu_gid']['#value']; + $menu_name = $form['#insert'] ? $menu_name = 'menu-' . $form['menu_name']['#value'] : $form['og_menu_name']['#value']; + $form_state['redirect'] = 'group/' . $group_type . '/' . $gid . '/admin/menus/' . $menu_name; +} + +/** + * Form callback which shows an entire menu tree at once. + */ +function og_menu_overview_form($form, &$form_state, $group_type, $gid, $menu) { + module_load_include('inc', 'menu', 'menu.admin'); + drupal_set_title(t('List items for menu !mtitle', array('!mtitle' => $menu['title'])), PASS_THROUGH); + // Set the breadcrumb. + og_set_breadcrumb($group_type, $gid, array(l(t('Group'), "$group_type/$gid/group"))); + $b = drupal_get_breadcrumb(); + $b[] = l(t('Menus'), 'group/' . $group_type . '/' . $gid . '/admin/menus'); + drupal_set_breadcrumb($b); + $form = menu_overview_form($form, $form_state, $menu); + + $form['#theme'] = 'menu_overview_form'; + $form['#empty_text'] = t('There are no menu links yet.') . ' ' . l(t('Add link'), 'group/' . $group_type . '/' . $gid . '/admin/menus/' . $menu['menu_name'] . '/add'); + + foreach (element_children($form) as $mlid) { + if (strstr($mlid, 'mlid:')) { + $item = $form[$mlid]['#item']; + $operations = array(); + $operations['edit'] = array( + '#type' => 'link', + '#title' => t('edit'), + '#href' => 'group/' . $group_type . '/' . $gid . '/admin/menus/' . $menu['menu_name'] . '/item/' . $item['mlid'] . '/edit', + ); + + if ($item['module'] == 'menu' || $item['updated'] == 1) { + $operations['delete'] = array( + '#type' => 'link', + '#title' => t('delete'), + '#href' => 'group/' . $group_type . '/' . $gid . '/admin/menus/' . $menu['menu_name'] . '/item/' . $item['mlid'] . '/delete', + ); + } + $form[$mlid]['operations'] = $operations; + } + } + return $form; +} + +/** + * Submit function; does the same as the normal menu_overview_form_submit. + */ +function og_menu_overview_form_submit($form, &$form_state) { + menu_overview_form_submit($form, $form_state); +} + +/** + * Form callback for node/%node/admin/menus/%menu/delete. + */ +function og_menu_delete_menu_confirm($form, &$form_state, $menu, $group_type, $gid) { + module_load_include('inc', 'menu', 'menu.admin'); + $form = menu_delete_menu_confirm($form, $form_state, $menu); + $form['og_menu_group_type'] = array( + '#type' => 'value', + '#value' => $group_type, + ); + $form['og_menu_gid'] = array( + '#type' => 'value', + '#value' => $gid, + ); + $form['actions']['cancel']['#href'] = 'group/' . $group_type . '/' . $gid . '/admin/menus/' . $menu['menu_name']; + $form['#submit'][] = 'menu_delete_menu_confirm_submit'; + $form['#submit'][] = 'og_menu_delete_menu_confirm_submit'; + $form['#submit'][] = 'og_menu_delete_menu_confirm_submit_redirect'; + return $form; +} + +/** + * Form callback; Build the menu link editing form. + */ +function og_menu_edit_item_form($form, &$form_state, $type, $group_type, $gid, $menu, $item = array()) { + module_load_include('inc', 'menu', 'menu.admin'); + $form = menu_edit_item($form, $form_state, $type, $item, $menu); + // Set the breadcrumb now to override menu_edit_item() breadcrumb. + og_set_breadcrumb($group_type, $gid, array(l(t('Group'), "$group_type/$gid/group"))); + $b = drupal_get_breadcrumb(); + $b[] = l(t('Menus'), 'group/' . $group_type . '/' . $gid . '/admin/menus'); + $b[] = l($menu['title'], 'group/' . $group_type . '/' . $gid . '/admin/menus/' . $menu['menu_name']); + drupal_set_breadcrumb($b); + $list = array(); + $menus = og_menu_get_group_menus(array($group_type => array(0 => $gid))); + foreach ($menus as $option) { + $list[$option['menu_name']] = $option['title']; + } + + // Set the title of the page. + drupal_set_title(t('Add item into menu !mtitle', array('!mtitle' => $menu['title'])), PASS_THROUGH); + + + // Build the form. + $form['parent']['#options'] = menu_parent_options($list, array('mlid' => 0)); + $form['og_menu_group_type'] = array( + '#type' => 'value', + '#value' => $group_type, + ); + $form['og_menu_gid'] = array( + '#type' => 'value', + '#value' => $gid, + ); + $form['og_menu_name'] = array( + '#type' => 'value', + '#value' => $menu['menu_name'], + ); + $form['#submit'][] = 'menu_edit_item_submit'; + $form['#submit'][] = 'og_menu_redirect'; + $form['#validate'][] = 'menu_edit_item_validate'; + if (!empty($item)) { + $form['actions']['delete'] = array( + '#type' => 'link', + '#title' => 'Delete', + '#href' => 'group/' . $group_type . '/' . $gid . '/admin/menus/' + . $menu['menu_name'] . '/item/' . $item['mlid'] . '/delete', + '#weight' => 10, + ); + } + return $form; +} + +/** + * Form callback for node/%node/og_menu/%menu/item/%menu_link/delete page + */ +function og_menu_delete_item_form($form, &$form_state, $item, $group_type, $gid, $menu) { + module_load_include('inc', 'menu', 'menu.admin'); + $form = menu_item_delete_form($form, $form_state, $item); + $form_state['values']['link_path'] = $form['#item']['link_path']; + $form['og_menu_group_type'] = array( + '#type' => 'value', + '#value' => $group_type, + ); + $form['og_menu_gid'] = array( + '#type' => 'value', + '#value' => $gid, + ); + $form['og_menu_name'] = array( + '#type' => 'value', + '#value' => $menu['menu_name'], + ); + $form['#submit'][] = 'menu_item_delete_form_submit'; + $form['#submit'][] = 'og_menu_redirect'; + $form['actions']['cancel']['#href'] = 'group/' . $group_type . '/' . $gid . '/admin/menus/' . $menu['menu_name']; + return $form; +} + +/** + * Form callback for OG Menu configuration. + */ +function og_menu_config_form($form, &$form_state) { + $bundles = og_get_all_group_bundle(); + + $form['og_menu_block_links'] = array( + '#type' => 'checkbox', + '#title' => t('Convert OG Menu block titles into links'), + '#default_value' => variable_get('og_menu_block_links', FALSE), + '#description' => + t('If enabled, OG Menu block titles will link to the groupnode.'), + ); + $form['og_menu_create_by_default'] = array( + '#type' => 'checkbox', + '#title' => t('Automatically create a OG Menu for new Organic Group'), + '#default_value' => variable_get('og_menu_create_by_default', FALSE), + '#description' => t('If enabled, an OG Menu will be created by default when + a new Organic Group node is created.'), + ); + + $form['og_menu_max_menus_per_group'] = array( + '#type' => 'textfield', + '#title' => t('Maximum number of menus per group'), + '#default_value' => variable_get('og_menu_max_menus_per_group', 1), + '#size' => 20, + '#maxlength' => 5, + '#required' => TRUE, + '#description' => t("Enter 0 for no limit. Users with the 'administer menu' + permission will be able to bypass this."), + ); + + $form['og_menu_assignment'] = array( + '#type' => 'radios', + '#options' => array('select' => t('Select list'), + 'autocomplete' => t('Textbox with autocomplete')), + '#title' => t('Use autocomplete field on menu admin page'), + '#default_value' => variable_get('og_menu_assignment', 'autocomplete'), + '#required' => 'TRUE', + '#description' => + t('Autocomplete is recommended when you have a lot of organic groups.'), + ); + + // OG Menu default links. + $form['og_menu_default_link_bundles'] = array( + '#title' => t('OG Menu default links'), + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#description' => $bundles ? t('Specify default links to be added to get + each new OG Menu for each node bundle. Enter each <b>URL</b> followed by + a <strong>title</strong> delimited by a pipe. Examples: + <ul> + <li>www.example.com|Example Link</li> + <li>faculty/[node:nid]|Link to Faculty Page for Group <em>(If tokens are enabled)</em> + </li> + </ul>') : t('There are no group type bundles yet.'), + ); + + // Add a field for each bundle. + if ($bundles) { + foreach ($bundles['node'] as $bundle => $bundle_label) { + $form['og_menu_default_link_bundles']['og_menu_default_links_' . strtolower($bundle)] = array( + '#type' => 'textarea', + '#title' => t("%bundle Bundle", array('%bundle' => $bundle_label)), + '#default_value' => variable_get('og_menu_default_links_' . strtolower($bundle), FALSE), + '#description' => t("These links will be added to any new OG Menus added + to <b>%bundle</b> groups.", array('%bundle' => $bundle_label)), + ); + } + } + + if (module_exists('token')) { + $form['token_help'] = array( + '#title' => t('Replacement patterns'), + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#description' => t('Prefer raw-text replacements for text to avoid problems with HTML entities!'), + ); + + $form['token_help']['help'] = array( + '#theme' => 'token_tree', + '#token_types' => array('node'), + ); + } + + // Visibility setting to hide OG Menus on selected pages. + $form['og_menu_visibility'] = array( + '#type' => 'fieldset', + '#title' => t('Admin page visibility'), + '#description' => t("On sites with multiple OG Menus it might be prefereable + to hide them in places where you don't need them."), + ); + + $form['og_menu_visibility']['og_menu_show_blocks'] = array( + '#type' => 'checkbox', + '#title' => t("Show blocks for individual OG Menus"), + '#default_value' => variable_get('og_menu_show_blocks', FALSE), + '#description' => t("If disabled, blocks for OG Menus will be hidden from the block administration page."), + ); + $form['og_menu_visibility']['og_menu_show_nodetype'] = array( + '#type' => 'checkbox', + '#title' => t("Include OG Menus in node type menu settings"), + '#default_value' => variable_get('og_menu_show_nodetype', FALSE), + '#description' => t("If disabled, OG Menus will be hidden from the node type config page."), + ); + if (module_exists('menu_position')) { + $form['og_menu_visibility']['og_menu_show_menuposition'] = array( + '#type' => 'checkbox', + '#title' => t("Show as available parent in menu position rules."), + '#default_value' => variable_get('og_menu_show_menuposition', FALSE), + '#description' => t("If disabled, OG Menus will be hidden from the menu position parent selection dropdown."), + ); + } + if (module_exists('homebox')) { + $form['og_menu_visibility']['og_menu_show_homebox'] = array( + '#type' => 'checkbox', + '#title' => t("Show blocks in Homebox admin page"), + '#default_value' => variable_get('og_menu_show_homebox', FALSE), + '#description' => t("If disabled, blocks for OG Menus will be hidden from the homebox administration page."), + ); + } + return system_settings_form($form); +} + +/** + * Validation for OG Menu config form. + */ +function og_menu_config_form_validate($form, &$form_state) { + $max_num = $form_state['values']['og_menu_max_menus_per_group']; + if (!is_numeric($max_num)) { + form_set_error('og_menu_max_menus_per_group', t('You must enter an integer for the maximum number of menus per group.')); + } + elseif ($max_num < 0) { + form_set_error('og_menu_max_menus_per_group', t('Maximum number of menus per group must be positive.')); + } + + foreach ($form_state['values'] as $form_index => $form_val) { + if (preg_match('/^og_menu_default_links_(\w+)$/', $form_index)) { + $links = explode("\n", $form_val ); + foreach ($links as $link) { + $link_parts = explode('|', $link); + if (substr($link_parts[0], 0, 1) == '/') { + form_set_error('$form_index', + t("%link is not a valid link. Make sure link does not start with a '/'.", array('%link' => $link))); + } + } + } + } +} + +/** + * Callback for admin/structure/og_menu + * Just duplicates the standard menu list, but only displays those created through og_menu + */ +function og_admin_menu_overview_form($form, $form_state) { + $session = isset($_SESSION['og_menu_filter']) ? $_SESSION['og_menu_filter'] : array(); + + // Get filter value from $_SESSION variable. + foreach ($session as $filter) { + list($type, $value) = $filter; + } + + $form['filters'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => (isset($type)) ? FALSE : TRUE, + '#title' => 'Filter', + '#description' => 'Filter on the title of the OG menu.', + ); + + $form['filters']['og_menu_filter'] = array( + '#type' => 'textfield', + '#title' => t('Filter this out'), + '#required' => FALSE, + '#size' => 20, + '#default_value' => isset($type) ? $value : '', + ); + + $form['filters']['og_menu_actions'] = array( + '#type' => 'actions', + '#attributes' => array('class' => array('container-inline')), + ); + $form['filters']['og_menu_actions']['submit'] = array( + '#type' => 'submit', + '#value' => t('Filter'), + ); + if (count($session)) { + $form['filters']['og_menu_actions']['reset'] = array('#type' => 'submit', '#value' => t('Reset')); + } + + $header = array(t('Title'), array( + 'data' => t('Operations'), + 'colspan' => '3', + )); + $header = array( + array('data' => 'Title', 'field' => 'title', 'sort' => 'asc'), + array('data' => 'Operations', 'colspan' => '3'), + ); + + // Build Query (extend for paging and sorting). + $query = db_select('menu_custom', 'mc')->extend('PagerDefault')->limit(20); + $query->join('og_menu', 'om', 'mc.menu_name = om.menu_name'); //Pager Extender + $query->fields('mc') + ->fields('om') + ->orderBy('title') + ->extend('TableSort') + ->orderByHeader($header); + + // Add conditional filter if enter by user. + if (isset($type)) { + $query->condition('title', '%' . $value . '%', 'LIKE'); + } + + $result = $query->execute(); + + // Build table. + $rows = array(); + foreach ($result as $menu) { + $row = array(theme('menu_admin_overview', array('title' => $menu->title, 'name' => $menu->menu_name, 'description' => $menu->description))); + $row[] = array('data' => l(t('list links'), 'admin/structure/menu/manage/' . $menu->menu_name)); + $row[] = array('data' => l(t('edit menu'), 'admin/structure/menu/manage/' . $menu->menu_name . '/edit')); + $row[] = array('data' => l(t('add link'), 'admin/structure/menu/manage/' . $menu->menu_name . '/add')); + $rows[] = $row; + } + + $output = theme('table', array('header' => $header, 'rows' => $rows)) . theme('pager'); + + $form['og_menu_menu_list'] = array( + '#type' => 'markup', + '#title' => t('Results'), + '#markup' => $output, + ); + + return $form; +} + +/** + * Process result from OG Menu administration filter form. + */ +function og_admin_menu_overview_form_submit($form, &$form_state) { + switch ($form_state['values']['op']) { + case t('Filter'): + if (isset($form_state['values']['og_menu_filter']) && $form_state['values']['og_menu_filter'] != '') { + $_SESSION['og_menu_filter'][] = array('og_menu_filter', $form_state['values']['og_menu_filter']); + + } + break; + case t('Reset'): + $_SESSION['og_menu_filter'] = array(); + break; + } +}