From 22afce419519e7903ecb456d9caf5b89a8ac7d61 Mon Sep 17 00:00:00 2001 From: Chris Gross <gross.364@osu.edu> Date: Thu, 5 Nov 2015 10:42:01 -0500 Subject: [PATCH] daily build --- profiles/wcm_base/CHANGELOG.txt | 5 + .../contrib/file_entity_swf/LICENSE.txt | 339 ++++ .../file_entity_swf/file_entity_swf.file.inc | 22 + .../file_entity_swf.file_default_displays.inc | 41 + .../file_entity_swf/file_entity_swf.info | 12 + .../file_entity_swf/file_entity_swf.module | 125 ++ .../file_entity_swf/file_entity_swf.theme.inc | 32 + .../private_files_download_permission.info | 6 +- .../private_files_download_permission.module | 8 +- .../modules/contrib/redirect/LICENSE.txt | 339 ++++ .../modules/contrib/redirect/README.txt | 3 + .../contrib/redirect/redirect.admin.inc | 922 +++++++++ .../contrib/redirect/redirect.admin.js | 28 + .../modules/contrib/redirect/redirect.api.php | 295 +++ .../contrib/redirect/redirect.controller.inc | 20 + .../contrib/redirect/redirect.drush.inc | 72 + .../contrib/redirect/redirect.generate.inc | 182 ++ .../modules/contrib/redirect/redirect.info | 21 + .../modules/contrib/redirect/redirect.install | 422 +++++ .../modules/contrib/redirect/redirect.js | 29 + .../modules/contrib/redirect/redirect.module | 1674 +++++++++++++++++ .../modules/contrib/redirect/redirect.test | 287 +++ .../contrib/redirect/views/redirect.views.inc | 219 +++ .../redirect/views/redirect.views_default.inc | 16 + ...ect_handler_field_redirect_link_delete.inc | 41 + ...irect_handler_field_redirect_link_edit.inc | 41 + ...rect_handler_field_redirect_operations.inc | 68 + ...direct_handler_field_redirect_redirect.inc | 66 + ...redirect_handler_field_redirect_source.inc | 66 + .../redirect_handler_filter_redirect_type.inc | 20 + .../contrib/redirect/views/redirects.view | 177 ++ .../ocio_buckeye_alert/css/buckeye-alert.css | 2 +- .../ocio_buckeye_alert.module | 13 +- ...o_permissions.features.user_permission.inc | 37 + .../ocio_permissions/ocio_permissions.info | 7 + ...o_url_aliases.features.user_permission.inc | 23 + .../ocio_url_aliases/ocio_url_aliases.info | 13 + .../ocio_url_aliases/ocio_url_aliases.make | 11 + .../ocio_url_aliases.strongarm.inc | 81 +- .../ocio-full/ocio-full-layout.tpl.php | 2 +- .../layouts/ocio-2/ocio-2.layout.no-query.css | 89 +- .../ocio_omega_2/css/ocio-2.no-query.css | 4 +- .../themes/ocio_omega_2/css/ocio-2.styles.css | 4 +- .../layouts/ocio-2/ocio-2-layout.tpl.php | 2 +- .../sass/components/_main-content.scss | 4 +- .../ocio-2/ocio-2.layout.no-query.scss | 2 +- .../layouts/ocio-3/ocio-3-layout.tpl.php | 2 +- .../css/ocio-omega-base.no-query.css | 79 +- .../css/ocio-omega-base.styles.css | 102 +- .../sass/components/_featured-slideshow.scss | 83 +- .../sass/components/nodes/_landing-page.scss | 8 - .../themes/ocio_omega_base/template.php | 5 - profiles/wcm_base/wcm_base.info | 1 + profiles/wcm_base/wcm_base.make | 3 + 54 files changed, 6036 insertions(+), 139 deletions(-) create mode 100644 profiles/wcm_base/modules/contrib/file_entity_swf/LICENSE.txt create mode 100644 profiles/wcm_base/modules/contrib/file_entity_swf/file_entity_swf.file.inc create mode 100644 profiles/wcm_base/modules/contrib/file_entity_swf/file_entity_swf.file_default_displays.inc create mode 100644 profiles/wcm_base/modules/contrib/file_entity_swf/file_entity_swf.info create mode 100644 profiles/wcm_base/modules/contrib/file_entity_swf/file_entity_swf.module create mode 100644 profiles/wcm_base/modules/contrib/file_entity_swf/file_entity_swf.theme.inc create mode 100644 profiles/wcm_base/modules/contrib/redirect/LICENSE.txt create mode 100644 profiles/wcm_base/modules/contrib/redirect/README.txt create mode 100644 profiles/wcm_base/modules/contrib/redirect/redirect.admin.inc create mode 100644 profiles/wcm_base/modules/contrib/redirect/redirect.admin.js create mode 100644 profiles/wcm_base/modules/contrib/redirect/redirect.api.php create mode 100755 profiles/wcm_base/modules/contrib/redirect/redirect.controller.inc create mode 100644 profiles/wcm_base/modules/contrib/redirect/redirect.drush.inc create mode 100644 profiles/wcm_base/modules/contrib/redirect/redirect.generate.inc create mode 100644 profiles/wcm_base/modules/contrib/redirect/redirect.info create mode 100644 profiles/wcm_base/modules/contrib/redirect/redirect.install create mode 100644 profiles/wcm_base/modules/contrib/redirect/redirect.js create mode 100644 profiles/wcm_base/modules/contrib/redirect/redirect.module create mode 100644 profiles/wcm_base/modules/contrib/redirect/redirect.test create mode 100644 profiles/wcm_base/modules/contrib/redirect/views/redirect.views.inc create mode 100644 profiles/wcm_base/modules/contrib/redirect/views/redirect.views_default.inc create mode 100644 profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_field_redirect_link_delete.inc create mode 100644 profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_field_redirect_link_edit.inc create mode 100644 profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_field_redirect_operations.inc create mode 100644 profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_field_redirect_redirect.inc create mode 100644 profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_field_redirect_source.inc create mode 100644 profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_filter_redirect_type.inc create mode 100644 profiles/wcm_base/modules/contrib/redirect/views/redirects.view create mode 100644 profiles/wcm_base/modules/custom/ocio_url_aliases/ocio_url_aliases.features.user_permission.inc create mode 100644 profiles/wcm_base/modules/custom/ocio_url_aliases/ocio_url_aliases.make diff --git a/profiles/wcm_base/CHANGELOG.txt b/profiles/wcm_base/CHANGELOG.txt index a92657af..02721ba5 100644 --- a/profiles/wcm_base/CHANGELOG.txt +++ b/profiles/wcm_base/CHANGELOG.txt @@ -1,3 +1,8 @@ +WCM Base 7.x-1.x, 2015-11-04 +---------------------------- +- OCIO URL Aliases: Added redirect module, create redirects on alias change. +- WCM Base Profile: Added File Entity SWF module. + WCM Base 7.x-1.x, 2015-10-26 ---------------------------- - jQuery Update: Patched to size all accordion items independently. diff --git a/profiles/wcm_base/modules/contrib/file_entity_swf/LICENSE.txt b/profiles/wcm_base/modules/contrib/file_entity_swf/LICENSE.txt new file mode 100644 index 00000000..d159169d --- /dev/null +++ b/profiles/wcm_base/modules/contrib/file_entity_swf/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/profiles/wcm_base/modules/contrib/file_entity_swf/file_entity_swf.file.inc b/profiles/wcm_base/modules/contrib/file_entity_swf/file_entity_swf.file.inc new file mode 100644 index 00000000..8f74c511 --- /dev/null +++ b/profiles/wcm_base/modules/contrib/file_entity_swf/file_entity_swf.file.inc @@ -0,0 +1,22 @@ +<?php + +/** + * @file + * File hook implementations for File Entity SWF + */ + +/** + * Implements hook_file_presave(). + */ +function file_entity_swf_file_presave($file) { + if (!in_array($file->type, array('flash'))) { + return null; + } + + // Get metadata on the .swf file. + $data = @getimagesize(drupal_realpath($file->uri)); + if (isset($data) && is_array($data)) { + $file->metadata['width'] = $data[0]; + $file->metadata['height'] = $data[1]; + } +} diff --git a/profiles/wcm_base/modules/contrib/file_entity_swf/file_entity_swf.file_default_displays.inc b/profiles/wcm_base/modules/contrib/file_entity_swf/file_entity_swf.file_default_displays.inc new file mode 100644 index 00000000..76a25c6f --- /dev/null +++ b/profiles/wcm_base/modules/contrib/file_entity_swf/file_entity_swf.file_default_displays.inc @@ -0,0 +1,41 @@ +<?php + +/** + * @file + * Default display configuration for Flash file type. + */ + +/** + * Implements hook_file_default_displays(). + */ +function file_entity_swf_file_default_displays() { + $file_displays = array(); + + $file_display = new stdClass(); + $file_display->api_version = 1; + $file_display->name = 'flash__default__file_swf'; + $file_display->weight = 0; + $file_display->status = TRUE; + $file_display->settings = array(); + $file_displays['flash__default__file_swf'] = $file_display; + + // Flash previews should be displayed using a large filetype icon. + $file_display = new stdClass(); + $file_display->api_version = 1; + $file_display->name = 'flash__preview__file_field_media_large_icon'; + $file_display->weight = 0; + $file_display->status = TRUE; + $file_display->settings = ''; + $file_displays['flash__preview__file_field_media_large_icon'] = $file_display; + + // Flash media_wysiwyg should be displayed using a large filetype icon. + $file_display = new stdClass(); + $file_display->api_version = 1; + $file_display->name = 'flash__wysiwyg__file_field_media_large_icon'; + $file_display->weight = 0; + $file_display->status = TRUE; + $file_display->settings = ''; + $file_displays['flash__wysiwyg__file_field_media_large_icon'] = $file_display; + + return $file_displays; +} diff --git a/profiles/wcm_base/modules/contrib/file_entity_swf/file_entity_swf.info b/profiles/wcm_base/modules/contrib/file_entity_swf/file_entity_swf.info new file mode 100644 index 00000000..90fca90f --- /dev/null +++ b/profiles/wcm_base/modules/contrib/file_entity_swf/file_entity_swf.info @@ -0,0 +1,12 @@ +name = File Entity SWF +description = Adds SWF support for File Entity +core = 7.x + +dependencies[] = file_entity + +; Information added by Drupal.org packaging script on 2015-04-24 +version = "7.x-1.0-rc2" +core = "7.x" +project = "file_entity_swf" +datestamp = "1429903982" + diff --git a/profiles/wcm_base/modules/contrib/file_entity_swf/file_entity_swf.module b/profiles/wcm_base/modules/contrib/file_entity_swf/file_entity_swf.module new file mode 100644 index 00000000..59cc4b7d --- /dev/null +++ b/profiles/wcm_base/modules/contrib/file_entity_swf/file_entity_swf.module @@ -0,0 +1,125 @@ +<?php + +/** + * @file + * Module file for File Entity SWF + */ + +/** + * Implements hook_ctools_plugin_api(). + */ +function file_entity_swf_ctools_plugin_api($owner, $api) { + if ($owner == 'file_entity' && $api == 'file_type') { + return array('version' => 1); + } + if ($owner == 'file_entity' && $api == 'file_default_displays') { + return array('version' => 1); + } +} + +/** + * Implements hook_file_default_types(). + */ +function file_entity_swf_file_default_types() { + return array( + 'flash' => (object) array( + 'api_version' => 1, + 'type' => 'flash', + 'label' => t('Flash'), + 'description' => t("<em>Flash</em> provides animated and rich media experiences."), + 'mimetypes' => array( + 'application/x-shockwave-flash', + ), + ), + ); +} + +/** + * Implements hook_theme(). + */ +function file_entity_swf_theme($existing, $type, $theme, $path) { + return array( + 'file_entity_file_swf' => array( + 'variables' => array( + 'params' => array( + 'movie' => NULL, + 'wmode' => 'transparent', + 'FlashVars' => '', + 'quality' => 'high', + 'menu' => FALSE, + ), + 'attributes' => array( + 'class' => array(), + 'type' => 'application/x-shockwave-flash', + 'data' => NULL, + ), + ), + 'file' => 'file_entity_swf.theme.inc', + ), + ); +} + +/** + * Implements hook_file_formatter_info(). + */ +function file_entity_swf_file_formatter_info() { + $formatters['file_swf'] = array( + 'label' => t('Flash object'), + // @todo: Expose width/height + 'default settings' => array(), + 'view callback' => 'file_entity_swf_file_formatter_file_swf_view', + 'settings callback' => 'file_entity_swf_file_formatter_file_swf_settings', + 'hidden' => FALSE, + 'mime types' => array('application/x-shockwave-flash'), + ); + return $formatters; +} + +/** + * Implements hook_file_formatter_FORMATTER_view(). + */ +function file_entity_swf_file_formatter_file_swf_view($file, $display, $langcode) { + // Prevent PHP notices when trying to read empty files. + // @see http://drupal.org/node/681042 + if (!$file->filesize) { + return NULL; + } + + // This shouldn't happen, but make sure we have right filemime. + if ($file->filemime != 'application/x-shockwave-flash') { + return NULL; + } + + if (!isset($file->metadata)) { + $file->metadata = array(); + } + $file->metadata += array('width' => NULL, 'height' => NULL); + + + $path = file_create_url($file->uri); + $element = array( + '#theme' => 'file_entity_file_swf', + '#params' => array( + 'movie' => $path, + 'wmode' => 'transparent', + 'FlashVars' => '', + 'quality' => 'high', + 'menu' => FALSE, + ), + '#attributes' => array( + 'data' => $path, + 'width' => $file->metadata['width'], + 'height' => $file->metadata['height'], + ), + ); + + return $element; +} + +/** + * Implements hook_file_formatter_FORMATTER_settings(). + */ +function file_entity_swf_file_formatter_file_swf_settings($form, &$form_state, $settings) { + // @todo: Add some settings. + return null; +} diff --git a/profiles/wcm_base/modules/contrib/file_entity_swf/file_entity_swf.theme.inc b/profiles/wcm_base/modules/contrib/file_entity_swf/file_entity_swf.theme.inc new file mode 100644 index 00000000..52572509 --- /dev/null +++ b/profiles/wcm_base/modules/contrib/file_entity_swf/file_entity_swf.theme.inc @@ -0,0 +1,32 @@ +<?php + +/** + * @file + * Theme functions for File Entity SWF + */ + +/** + * Returns an <object> element with child <param> values. + * + * Add additional params via hook_preprocess_file_entity_file_swf. An example + * would be to add "allowfullscreen", simple add the "allowfullscreen" key as + * $variables['params']['allowfullscreen'] with the value of ture or false. + * + * @param array $variables An associative array of themable variables. + * + * @ingroup themeable + * + * @return string + */ +function theme_file_entity_file_swf($variables) { + $output = '<object' . drupal_attributes($variables['attributes']) . '>'; + foreach ($variables['params'] as $param => $param_value) { + $param_attributes = array( + 'name' => $param, + 'value' => $param_value, + ); + $output .= '<param' . drupal_attributes($param_attributes) . '>'; + } + $output .= '</object>'; + return $output; +} diff --git a/profiles/wcm_base/modules/contrib/private_files_download_permission/private_files_download_permission.info b/profiles/wcm_base/modules/contrib/private_files_download_permission/private_files_download_permission.info index 601fa3db..466b49ea 100644 --- a/profiles/wcm_base/modules/contrib/private_files_download_permission/private_files_download_permission.info +++ b/profiles/wcm_base/modules/contrib/private_files_download_permission/private_files_download_permission.info @@ -4,9 +4,9 @@ core = 7.x package = Access control configure = admin/config/media/private-files-download-permission -; Information added by Drupal.org packaging script on 2015-01-01 -version = "7.x-2.3+7-dev" +; Information added by Drupal.org packaging script on 2015-11-02 +version = "7.x-2.3+8-dev" core = "7.x" project = "private_files_download_permission" -datestamp = "1420135983" +datestamp = "1446474242" diff --git a/profiles/wcm_base/modules/contrib/private_files_download_permission/private_files_download_permission.module b/profiles/wcm_base/modules/contrib/private_files_download_permission/private_files_download_permission.module index 6a91988b..0fed3e3b 100644 --- a/profiles/wcm_base/modules/contrib/private_files_download_permission/private_files_download_permission.module +++ b/profiles/wcm_base/modules/contrib/private_files_download_permission/private_files_download_permission.module @@ -579,12 +579,16 @@ function private_files_download_permission_file_download($uri) { // Evaluate user and role permissions and optionally allow access to $uri. if (variable_get('private_files_download_permission_by_user_checks')) { if (in_array($user->uid, array_keys($best_matching_directory->uid))) { - return array('Content-Type' => file_get_mimetype($uri)); + $files = file_load_multiple(array(), array('uri' => $uri)); + $file = reset($files); + return file_transfer($uri, file_get_content_headers($file)); } } foreach ($user->roles as $rid => $role) { if (in_array($rid, array_keys($best_matching_directory->rid))) { - return array('Content-Type' => file_get_mimetype($uri)); + $files = file_load_multiple(array(), array('uri' => $uri)); + $file = reset($files); + return file_transfer($uri, file_get_content_headers($file)); } } } diff --git a/profiles/wcm_base/modules/contrib/redirect/LICENSE.txt b/profiles/wcm_base/modules/contrib/redirect/LICENSE.txt new file mode 100644 index 00000000..d159169d --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/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/profiles/wcm_base/modules/contrib/redirect/README.txt b/profiles/wcm_base/modules/contrib/redirect/README.txt new file mode 100644 index 00000000..3ea2f179 --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/README.txt @@ -0,0 +1,3 @@ + +This is the new module home for a unified redirection API (also replaces +path_redirect and globalredirect). diff --git a/profiles/wcm_base/modules/contrib/redirect/redirect.admin.inc b/profiles/wcm_base/modules/contrib/redirect/redirect.admin.inc new file mode 100644 index 00000000..1e804383 --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/redirect.admin.inc @@ -0,0 +1,922 @@ +<?php + +/** + * @file + * Administrative page callbacks for the redirect module. + */ + +function redirect_list_form($form, &$form_state) { + $form['#operations'] = redirect_get_redirect_operations(); + if (isset($form_state['values']['operation']) && empty($form_state['values']['confirm'])) { + return redirect_list_form_operations_confirm_form($form, $form_state, $form_state['values']['operation'], array_filter($form_state['values']['rids'])); + } + + $destination = drupal_get_destination(); + $default_status_code = variable_get('redirect_default_status_code', 301); + + // Set up the header. + $header = array( + 'source' => array('data' => t('From'), 'field' => 'source', 'sort' => 'asc'), + 'redirect' => array('data' => t('To'), 'field' => 'redirect'), + 'status' => array('data' => t('Status'), 'field' => 'status'), + 'status_code' => array('data' => t('Type'), 'field' => 'status_code'), + 'language' => array('data' => t('Language'), 'field' => 'language'), + 'count' => array('data' => t('Count'), 'field' => 'count'), + 'access' => array('data' => t('Last accessed'), 'field' => 'access'), + 'operations' => array('data' => t('Operations')), + ); + + // Do not include the language column if locale is disabled. + if (!module_exists('locale')) { + unset($header['language']); + } + + // Get filter keys and add the filter form. + $keys = func_get_args(); + $keys = array_splice($keys, 2); // Offset the $form and $form_state parameters. + $keys = implode('/', $keys); + $form['redirect_list_filter_form'] = redirect_list_filter_form($keys); + + // Build the 'Update options' form. + $form['operations'] = array( + '#type' => 'fieldset', + '#title' => t('Update options'), + '#prefix' => '<div class="container-inline">', + '#suffix' => '</div>', + '#attributes' => array( + 'class' => array('redirect-list-operations'), + ), + ); + $operations = array(); + foreach ($form['#operations'] as $key => $operation) { + $operations[$key] = $operation['action']; + } + $form['operations']['operation'] = array( + '#type' => 'select', + '#options' => $operations, + '#default_value' => 'delete', + ); + $form['operations']['submit'] = array( + '#type' => 'submit', + '#value' => t('Update'), + '#validate' => array('redirect_list_form_operations_validate'), + '#submit' => array('redirect_list_form_operations_submit'), + ); + + // Building the SQL query and load the redirects. + $query = db_select('redirect', 'r')->extend('TableSort')->extend('PagerDefault'); + $query->addField('r', 'rid'); + $query->condition('r.type', 'redirect'); + $query->orderByHeader($header); + $query->limit(50); + $query->addTag('redirect_list'); + $query->addTag('redirect_access'); + redirect_build_filter_query($query, array('source', 'redirect'), $keys); + $rids = $query->execute()->fetchCol(); + $redirects = redirect_load_multiple($rids); + + $rows = array(); + foreach ($redirects as $rid => $redirect) { + $row = array(); + $redirect->source_options = array_merge($redirect->source_options, array('alias' => TRUE, 'language' => redirect_language_load($redirect->language))); + $source_url = redirect_url($redirect->source, $redirect->source_options); + $redirect_url = redirect_url($redirect->redirect, array_merge($redirect->redirect_options, array('alias' => TRUE))); + drupal_alter('redirect_url', $redirect->source, $redirect->source_options); + drupal_alter('redirect_url', $redirect->redirect, $redirect->redirect_options); + $row['source'] = l($source_url, $redirect->source, $redirect->source_options); + $row['redirect'] = l($redirect_url, $redirect->redirect, $redirect->redirect_options); + $row['status'] = $redirect->status ? t('Enabled') : t('Disabled'); + $row['status_code'] = $redirect->status_code ? $redirect->status_code : t('Default (@default)', array('@default' => $default_status_code)); + $row['language'] = module_invoke('locale', 'language_name', $redirect->language); + $row['count'] = $redirect->count; + if ($redirect->access) { + $row['access'] = array( + 'data' => t('!interval ago', array('!interval' => format_interval(REQUEST_TIME - $redirect->access))), + 'title' => t('Last accessed on @date', array('@date' => format_date($redirect->access))), + ); + } + else { + $row['access'] = t('Never'); + } + + // Mark redirects that override existing paths with a warning in the table. + if (drupal_valid_path($redirect->source)) { + $row['#attributes']['class'][] = 'warning'; + $row['#attributes']['title'] = t('This redirect overrides an existing internal path.'); + } + + $operations = array(); + if (redirect_access('update', $redirect)) { + $operations['edit'] = array( + 'title' => t('Edit'), + 'href' => 'admin/config/search/redirect/edit/' . $rid, + 'query' => $destination, + ); + } + if (redirect_access('delete', $redirect)) { + $operations['delete'] = array( + 'title' => t('Delete'), + 'href' => 'admin/config/search/redirect/delete/' . $rid, + 'query' => $destination, + ); + } + $row['operations'] = array( + 'data' => array( + '#theme' => 'links', + '#links' => $operations, + '#attributes' => array('class' => array('links', 'inline', 'nowrap')), + ), + ); + + $rows[$rid] = $row; + } + + $form['rids'] = array( + '#type' => 'tableselect', + '#header' => $header, + '#options' => $rows, + '#empty' => t('No URL redirects available.'), + '#attributes' => array( + 'class' => array('redirect-list-tableselect'), + ), + '#attached' => array( + 'js' => array( + drupal_get_path('module', 'redirect') . '/redirect.admin.js', + ), + ), + ); + if (redirect_access('create', 'redirect')) { + $form['rids']['#empty'] .= ' ' . l(t('Add URL redirect.'), 'admin/config/search/redirect/add', array('query' => $destination)); + } + $form['pager'] = array('#theme' => 'pager'); + return $form; +} + +/** + * Return a form to filter URL redirects. + * + * @see redirect_list_filter_form_submit() + * + * @ingroup forms + */ +function redirect_list_filter_form($keys = '') { + $form['#attributes'] = array('class' => array('search-form')); + $form['basic'] = array( + '#type' => 'fieldset', + '#title' => t('Filter redirects'), + '#attributes' => array('class' => array('container-inline')), + ); + $form['basic']['filter'] = array( + '#type' => 'textfield', + '#title' => '', + '#default_value' => $keys, + '#maxlength' => 128, + '#size' => 25, + ); + $form['basic']['submit'] = array( + '#type' => 'submit', + '#value' => t('Filter'), + '#submit' => array('redirect_list_filter_form_submit'), + ); + if ($keys) { + $form['basic']['reset'] = array( + '#type' => 'submit', + '#value' => t('Reset'), + '#submit' => array('redirect_list_filter_form_reset'), + ); + } + return $form; +} + +/** + * Process filter form submission when the Filter button is pressed. + */ +function redirect_list_filter_form_submit($form, &$form_state) { + $form_state['redirect'] = 'admin/config/search/redirect/list/' . trim($form_state['values']['filter']); +} + +/** + * Process filter form submission when the Reset button is pressed. + */ +function redirect_list_filter_form_reset($form, &$form_state) { + $form_state['redirect'] = 'admin/config/search/redirect'; +} + +/** + * Extends a query object for URL redirect filters. + * + * @param $query + * Query object that should be filtered. + * @param $keys + * The filter string to use. + */ +function redirect_build_filter_query(QueryAlterableInterface $query, array $fields, $keys = '') { + if ($keys && $fields) { + // Replace wildcards with PDO wildcards. + $conditions = db_or(); + $wildcard = '%' . trim(preg_replace('!\*+!', '%', db_like($keys)), '%') . '%'; + foreach ($fields as $field) { + $conditions->condition($field, $wildcard, 'LIKE'); + } + $query->condition($conditions); + } +} + +/** + * Validate redirect_list_form form submissions. + * + * Check if any redirects have been selected to perform the chosen + * 'Update option' on. + */ +function redirect_list_form_operations_validate($form, &$form_state) { + // Error if there are no redirects selected. + if (!is_array($form_state['values']['rids']) || !count(array_filter($form_state['values']['rids']))) { + form_set_error('', t('No redirects selected.')); + } +} + +/** + * Process redirect_list_form form submissions. + * + * Execute the chosen 'Update option' on the selected redirects. + */ +function redirect_list_form_operations_submit($form, &$form_state) { + $operations = $form['#operations']; + $operation = $operations[$form_state['values']['operation']]; + + // Filter out unchecked redirects + $rids = array_filter($form_state['values']['rids']); + + if (!empty($operation['confirm']) && empty($form_state['values']['confirm'])) { + // We need to rebuild the form to go to a second step. For example, to + // show the confirmation form for the deletion of redirects. + $form_state['rebuild'] = TRUE; + } + else { + $function = $operation['callback']; + + // Add in callback arguments if present. + if (isset($operation['callback arguments'])) { + $args = array_merge(array($rids), $operation['callback arguments']); + } + else { + $args = array($rids); + } + call_user_func_array($function, $args); + + // We display the number of redirects the user selected, regardless of + // how many redirects actually changed status. Eg. if 1 enabled and 1 + // disabled redirects are checked for being enabled, we'll still display + // "Enabled 1 redirect." + $count = count($form_state['values']['rids']); + watchdog('redirect', '@action @count redirects.', array('@action' => $operation['action_past'], '@count' => $count)); + drupal_set_message(format_plural(count($rids), '@action @count redirect.', '@action @count redirects.', array('@action' => $operation['action_past'], '@count' => $count))); + } +} + +function redirect_list_form_operations_confirm_form($form, &$form_state, $operation, $rids) { + $operations = $form['#operations']; + $operation = $operations[$form_state['values']['operation']]; + + $form['rids_list'] = array( + '#theme' => 'item_list', + '#items' => array(), + ); + $form['rids'] = array( + '#type' => 'value', + '#value' => $rids, + ); + + $redirects = redirect_load_multiple($rids); + foreach ($redirects as $rid => $redirect) { + $form['rids_list']['#items'][$rid] = check_plain(redirect_url($redirect->source, $redirect->source_options)); + } + + $form['operation'] = array('#type' => 'hidden', '#value' => $form_state['values']['operation']); + $form['#submit'][] = 'redirect_list_form_operations_submit'; + $confirm_question = format_plural(count($rids), 'Are you sure you want to @action this redirect?', 'Are you sure you want to @action these redirects?', array('@action' => drupal_strtolower($operation['action']))); + + return confirm_form( + $form, + $confirm_question, + 'admin/config/search/redirect', // @todo This does not redirect back to filtered page. + t('This action cannot be undone.'), + $operation['action'], + t('Cancel') + ); +} + +/** + * Form builder to add or edit an URL redirect. + * + * @see redirect_element_validate_source() + * @see redirect_element_validate_redirect() + * @see redirect_edit_form_validate() + * @see redirect_edit_form_submit() + * + * @ingroup forms + */ +function redirect_edit_form($form, &$form_state, $redirect = NULL) { + if (!isset($redirect)) { + $redirect = new stdClass(); + } + + // Merge default values. + redirect_object_prepare($redirect, array( + 'source' => isset($_GET['source']) ? urldecode($_GET['source']) : '', + 'source_options' => isset($_GET['source_options']) ? drupal_get_query_array($_GET['source_options']) : array(), + 'redirect' => isset($_GET['redirect']) ? urldecode($_GET['redirect']) : '', + 'redirect_options' => isset($_GET['redirect_options']) ? drupal_get_query_array($_GET['redirect_options']) : array(), + 'language' => isset($_GET['language']) ? urldecode($_GET['language']) : LANGUAGE_NONE, + )); + + $form['rid'] = array( + '#type' => 'value', + '#value' => $redirect->rid, + ); + $form['type'] = array( + '#type' => 'value', + '#value' => $redirect->type, + ); + $form['hash'] = array( + '#type' => 'value', + '#value' => $redirect->hash, + ); + $form['uid'] = array( + '#type' => 'value', + '#value' => $redirect->uid, + ); + + $form['source'] = array( + '#type' => 'textfield', + '#title' => t('From'), + '#description' => t("Enter an internal Drupal path or path alias to redirect (e.g. %example1 or %example2). Fragment anchors (e.g. %anchor) are <strong>not</strong> allowed.", array('%example1' => 'node/123', '%example2' => 'taxonomy/term/123', '%anchor' => '#anchor')), + '#maxlength' => 560, + '#default_value' => $redirect->rid || $redirect->source ? redirect_url($redirect->source, $redirect->source_options + array('alter' => FALSE)) : '', + '#required' => TRUE, + '#field_prefix' => $GLOBALS['base_url'] . '/' . (variable_get('clean_url', 0) ? '' : '?q='), + '#element_validate' => array('redirect_element_validate_source'), + ); + $form['source_options'] = array( + '#type' => 'value', + '#value' => $redirect->source_options, + '#tree' => TRUE, + ); + $form['redirect'] = array( + '#type' => 'textfield', + '#title' => t('To'), + '#maxlength' => 560, + '#default_value' => $redirect->rid || $redirect->redirect ? redirect_url($redirect->redirect, $redirect->redirect_options, TRUE) : '', + '#required' => TRUE, + '#description' => t('Enter an internal Drupal path, path alias, or complete external URL (like http://example.com/) to redirect to. Use %front to redirect to the front page.', array('%front' => '<front>')), + '#element_validate' => array('redirect_element_validate_redirect'), + ); + + $form['redirect_options'] = array( + '#type' => 'value', + '#value' => $redirect->redirect_options, + '#tree' => TRUE, + ); + + // This will be a hidden value unless locale module is enabled. + $form['language'] = array( + '#type' => 'value', + '#value' => $redirect->language, + ); + + $form['status'] = array( + '#type' => 'checkbox', + '#title' => t('Enabled'), + '#description' => t('If this box is checked, this redirect will be enabled.'), + '#default_value' => $redirect->status, + '#required' => FALSE, + ); + + $form['advanced'] = array( + '#type' => 'fieldset', + '#title' => t('Advanced options'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + $form['advanced']['status_code'] = array( + '#type' => 'select', + '#title' => t('Redirect status'), + '#description' => t('You can find more information about HTTP redirect status codes at <a href="@status-codes">@status-codes</a>.', array('@status-codes' => 'http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_Redirection')), + '#default_value' => $redirect->status_code, + '#options' => array(0 => t('Default (@default)', array('@default' => variable_get('redirect_default_status_code', 301)))) + redirect_status_code_options(), + ); + + $form['override'] = array( + '#type' => 'checkbox', + '#title' => t('I understand the following warnings and would like to proceed with saving this URL redirect'), + '#default_value' => FALSE, + '#access' => FALSE, + '#required' => FALSE, + '#weight' => -100, + '#prefix' => '<div class="messages warning">', + '#suffix' => '</div>', + ); + if (!empty($form_state['storage']['override_messages'])) { + $form['override']['#access'] = TRUE; + //$form['override']['#required'] = TRUE; + $form['override']['#description'] = theme('item_list', array('items' => $form_state['storage']['override_messages'])); + // Reset the messages. + $form_state['storage']['override_messages'] = array(); + } + + $form['actions'] = array('#type' => 'actions'); + $form['actions']['submit'] = array( + '#type' => 'submit', + '#value' => t('Save'), + ); + $form['actions']['cancel'] = array( + '#type' => 'link', + '#title' => t('Cancel'), + '#href' => isset($_GET['destination']) ? $_GET['destination'] : 'admin/config/search/redirect', + ); + + return $form; +} + +/** + * Element validate handler; validate the source of an URL redirect. + * + * @see redirect_edit_form() + */ +function redirect_element_validate_source($element, &$form_state) { + $value = &$element['#value']; + + // Check that the source contains no URL fragment. + if (strpos($value, '#') !== FALSE) { + form_error($element, t('The source path cannot contain an URL fragment anchor.')); + } + + _redirect_extract_url_options($element, $form_state); + + // Disallow redirections from the frontpage. + if ($value === '<front>') { + form_error($element, t('The source path cannot be the front page.')); + } + + // Cannot create redirects for valid paths. + if (empty($form_state['values']['override'])) { + $menu_item = menu_get_item($value); + if ($menu_item && $menu_item['page_callback'] != 'redirect_redirect' && $value == $menu_item['path']) { + $form_state['storage']['override_messages']['valid-path'] = t('The source path %path is likely a valid path. It is preferred to <a href="@url-alias">create URL aliases</a> for existing paths rather than redirects.', array('%path' => $value, '@url-alias' => url('admin/config/search/path/add'))); + $form_state['rebuild'] = TRUE; + } + } + + return $element; +} + +/** + * Element validate handler; validate the redirect of an URL redirect. + * + * @see redirect_edit_form() + */ +function redirect_element_validate_redirect($element, &$form_state) { + $value = &$element['#value']; + _redirect_extract_url_options($element, $form_state); + $value = &$form_state['values']['redirect']; + + + // Normalize the path. + $value = drupal_get_normal_path($value, $form_state['values']['language']); + + if (!valid_url($value) && !valid_url($value, TRUE) && $value != '<front>' && $value != '' && !file_exists($value)) { + form_error($element, t('The redirect path %value is not valid.', array('%value' => $value))); + } + + return $element; +} + +/** + * Extract the query and fragment parts out of an URL field. + */ +function _redirect_extract_url_options(&$element, &$form_state) { + $value = &$element['#value']; + $type = $element['#name']; + $options = &$form_state['values']["{$type}_options"]; + + $parsed = redirect_parse_url($value); + + if (isset($parsed['fragment'])) { + $options['fragment'] = $parsed['fragment']; + } + else { + unset($options['fragment']); + } + + if (isset($parsed['query'])) { + $options['query'] = $parsed['query']; + } + else { + unset($options['query']); + } + + if (isset($parsed['scheme']) && $parsed['scheme'] == 'https') { + $options['https'] = TRUE; + } + else { + unset($options['https']); + } + + if (!url_is_external($parsed['url'])) { + $parsed['url'] = drupal_get_normal_path($parsed['url'], $form_state['values']['language']); + } + + form_set_value($element, $parsed['url'], $form_state); + return $parsed; +} + +/** + * Form validate handler; validate an URL redirect + * + * @see redirect_edit_form() + */ +function redirect_edit_form_validate($form, &$form_state) { + $redirect = (object) $form_state['values']; + + if (empty($form_state['values']['override'])) { + // Find out if any (disabled or enabled) redirect with this source already + // exists. + if ($existing = redirect_load_by_source($redirect->source, $redirect->language, array(), FALSE)) { + if ($redirect->rid != $existing->rid && $redirect->language == $existing->language) { + // The "from" path should not conflict with another (disabled or + // enabled) redirect. + $form_state['storage']['override_messages']['redirect-conflict'] = t('A redirect already exists for the source path %source. Do you want to <a href="@edit-page">edit the existing redirect</a>?', array('%source' => $redirect->source, '@edit-page' => url('admin/config/search/redirect/edit/'. $existing->rid))); + $form_state['rebuild'] = TRUE; + } + } + + if ($form['override']['#access']) { + drupal_set_message('Did you read the warnings and click the checkbox?', 'error'); + $form_state['rebuild'] = TRUE; + //form_set_error('override', 'CLICK DA BUTTON!'); + } + } + + redirect_validate($redirect, $form, $form_state); +} + +/** + * Form submit handler; insert or update an URL redirect. + * + * @see redirect_edit_form() + */ +function redirect_edit_form_submit($form, &$form_state) { + form_state_values_clean($form_state); + $redirect = (object) $form_state['values']; + redirect_save($redirect); + drupal_set_message(t('The redirect has been saved.')); + $form_state['redirect'] = 'admin/config/search/redirect'; +} + +/** + * Form builder to delete an URL redirect. + * + * @see redirect_delete_form() + * @see confirm_form() + * + * @ingroup forms + */ +function redirect_delete_form($form, &$form_state, $redirect) { + $form['rid'] = array( + '#type' => 'value', + '#value' => $redirect->rid, + ); + + return confirm_form( + $form, + t('Are you sure you want to delete the URL redirect from %source to %redirect?', array('%source' => $redirect->source, '%redirect' => $redirect->redirect)), + 'admin/config/search/redirect' + ); +} + +/** + * Form submit handler; delete an URL redirect after confirmation. + * + * @see redirect_delete_form() + */ +function redirect_delete_form_submit($form, &$form_state) { + redirect_delete($form_state['values']['rid']); + drupal_set_message(t('The redirect has been deleted.')); + $form_state['redirect'] = 'admin/config/search/redirect'; +} + +/** + * Form builder for redirection settings. + * + * @see system_settings_form() + * @see redirect_settings_form_submit() + * + * @ingroup forms + */ +function redirect_settings_form($form, &$form_state) { + $form['redirect_auto_redirect'] = array( + '#type' => 'checkbox', + '#title' => t('Automatically create redirects when URL aliases are changed.'), + '#default_value' => variable_get('redirect_auto_redirect', TRUE), + '#disabled' => !module_exists('path'), + ); + $form['redirect_passthrough_querystring'] = array( + '#type' => 'checkbox', + '#title' => t('Retain query string through redirect.'), + '#default_value' => variable_get('redirect_passthrough_querystring', 1), + '#description' => t('For example, given a redirect from %source to %redirect, if a user visits %sourcequery they would be redirected to %redirectquery. The query strings in the redirection will always take precedence over the current query string.', array('%source' => 'source-path', '%redirect' => 'node?a=apples', '%sourcequery' => 'source-path?a=alligators&b=bananas', '%redirectquery' => 'node?a=apples&b=bananas')), + ); + $form['redirect_warning'] = array( + '#type' => 'checkbox', + '#title' => t('Display a warning message to users when they are redirected.'), + '#default_value' => variable_get('redirect_warning', FALSE), + '#access' => FALSE, + ); + $form['redirect_default_status_code'] = array( + '#type' => 'select', + '#title' => t('Default redirect status'), + '#description' => t('You can find more information about HTTP redirect status codes at <a href="@status-codes">@status-codes</a>.', array('@status-codes' => 'http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_Redirection')), + '#options' => redirect_status_code_options(), + '#default_value' => variable_get('redirect_default_status_code', 301), + ); + $form['redirect_page_cache'] = array( + '#type' => 'checkbox', + '#title' => t('Allow redirects to be saved into the page cache.'), + '#default_value' => variable_get('redirect_page_cache', 0), + '#description' => t('This feature requires <a href="@performance">Cache pages for anonymous users</a> to be enabled and the %variable variable to be true (currently set to @value).', array('@performance' => url('admin/config/development/performance'), '%variable' => "\$conf['page_cache_invoke_hooks']", '@value' => var_export(variable_get('page_cache_invoke_hooks', TRUE), TRUE))), + '#disabled' => !variable_get('cache', 0) || !variable_get('page_cache_invoke_hooks', TRUE), + ); + $form['redirect_purge_inactive'] = array( + '#type' => 'select', + '#title' => t('Delete redirects that have not been accessed for'), + '#default_value' => variable_get('redirect_purge_inactive', 0), + '#options' => array(0 => t('Never (do not discard)')) + drupal_map_assoc(array(604800, 1209600, 1814400, 2592000, 5184000, 7776000, 10368000, 15552000, 31536000), 'format_interval'), + '#description' => t('Only redirects managed by the redirect module itself will be deleted. Redirects managed by other modules will be left alone.'), + '#disabled' => variable_get('redirect_page_cache', 0) && !variable_get('page_cache_invoke_hooks', TRUE), + ); + + $form['globals'] = array( + '#type' => 'fieldset', + '#title' => t('Always enabled redirections'), + '#description' => t('(formerly Global Redirect features)'), + '#access' => FALSE, + ); + $form['globals']['redirect_global_home'] = array( + '#type' => 'checkbox', + '#title' => t('Redirect from paths like index.php and /node to the root directory.'), + '#default_value' => variable_get('redirect_global_home', 1), + '#access' => FALSE, + ); + $form['globals']['redirect_global_clean'] = array( + '#type' => 'checkbox', + '#title' => t('Redirect from non-clean URLs to clean URLs.'), + '#default_value' => variable_get('redirect_global_clean', 1), + '#disabled' => !variable_get('clean_url', 0), + '#access' => FALSE, + ); + $form['globals']['redirect_global_canonical'] = array( + '#type' => 'checkbox', + '#title' => t('Redirect from non-canonical URLs to the canonical URLs.'), + '#default_value' => variable_get('redirect_global_canonical', 1), + ); + $form['globals']['redirect_global_deslash'] = array( + '#type' => 'checkbox', + '#title' => t('Remove trailing slashes from paths.'), + '#default_value' => variable_get('redirect_global_deslash', 0), + '#access' => FALSE, + ); + $form['globals']['redirect_global_admin_paths'] = array( + '#type' => 'checkbox', + '#title' => t('Allow redirections on admin paths.'), + '#default_value' => variable_get('redirect_global_admin_paths', 0), + ); + + $form['#submit'][] = 'redirect_settings_form_submit'; + return system_settings_form($form); +} + +/** + * Form submit handler; clears the page cache. + * + * @see redirect_settings_form() + */ +function redirect_settings_form_submit($form, &$form_state) { + redirect_page_cache_clear(); +} + +function redirect_404_list($form = NULL) { + $destination = drupal_get_destination(); + + // Get filter keys and add the filter form. + $keys = func_get_args(); + //$keys = array_splice($keys, 2); // Offset the $form and $form_state parameters. + $keys = implode('/', $keys); + $build['redirect_list_404_filter_form'] = drupal_get_form('redirect_list_404_filter_form', $keys); + + $header = array( + array('data' => t('Page'), 'field' => 'message'), + array('data' => t('Count'), 'field' => 'count', 'sort' => 'desc'), + array('data' => t('Last accessed'), 'field' => 'timestamp'), + array('data' => t('Operations')), + ); + + $count_query = db_select('watchdog', 'w'); + $count_query->addExpression('COUNT(DISTINCT(w.message))'); + $count_query->leftJoin('redirect', 'r', 'w.message = r.source'); + $count_query->condition('w.type', 'page not found'); + $count_query->isNull('r.rid'); + redirect_build_filter_query($count_query, array('w.message'), $keys); + + $query = db_select('watchdog', 'w')->extend('PagerDefault')->extend('TableSort'); + $query->fields('w', array('message')); + $query->addExpression('COUNT(wid)', 'count'); + $query->addExpression('MAX(timestamp)', 'timestamp'); + $query->leftJoin('redirect', 'r', 'w.message = r.source'); + $query->isNull('r.rid'); + $query->condition('w.type', 'page not found'); + $query->groupBy('w.message'); + $query->orderByHeader($header); + $query->limit(25); + redirect_build_filter_query($query, array('w.message'), $keys); + $query->setCountQuery($count_query); + $results = $query->execute(); + + $rows = array(); + foreach ($results as $result) { + $row = array(); + $row['source'] = l($result->message, $result->message, array('query' => $destination)); + $row['count'] = $result->count; + $row['timestamp'] = format_date($result->timestamp, 'short'); + + $operations = array(); + if (redirect_access('create', 'redirect')) { + $operations['add'] = array( + 'title' => t('Add redirect'), + 'href' => 'admin/config/search/redirect/add/', + 'query' => array('source' => $result->message) + $destination, + ); + } + $row['operations'] = array( + 'data' => array( + '#theme' => 'links', + '#links' => $operations, + '#attributes' => array('class' => array('links', 'inline', 'nowrap')), + ), + ); + + $rows[] = $row; + } + + $build['redirect_404_table'] = array( + '#theme' => 'table', + '#header' => $header, + '#rows' => $rows, + '#empty' => t('No 404 pages without redirects found.'), + ); + $build['redirect_404_pager'] = array('#theme' => 'pager'); + return $build; +} + +/** + * Return a form to filter URL redirects. + * + * @see redirect_list_filter_form_submit() + * + * @ingroup forms + */ +function redirect_list_404_filter_form($form, &$form_state, $keys = '') { + $form['#attributes'] = array('class' => array('search-form')); + $form['basic'] = array( + '#type' => 'fieldset', + '#title' => t('Filter 404s'), + '#attributes' => array('class' => array('container-inline')), + ); + $form['basic']['filter'] = array( + '#type' => 'textfield', + '#title' => '', + '#default_value' => $keys, + '#maxlength' => 128, + '#size' => 25, + ); + $form['basic']['submit'] = array( + '#type' => 'submit', + '#value' => t('Filter'), + '#submit' => array('redirect_list_404_filter_form_submit'), + ); + if ($keys) { + $form['basic']['reset'] = array( + '#type' => 'submit', + '#value' => t('Reset'), + '#submit' => array('redirect_list_404_filter_form_reset'), + ); + } + return $form; +} + +/** + * Process filter form submission when the Filter button is pressed. + */ +function redirect_list_404_filter_form_submit($form, &$form_state) { + $form_state['redirect'] = 'admin/config/search/redirect/404/' . trim($form_state['values']['filter']); +} + +/** + * Process filter form submission when the Reset button is pressed. + */ +function redirect_list_404_filter_form_reset($form, &$form_state) { + $form_state['redirect'] = 'admin/config/search/redirect/404'; +} + +function redirect_list_table($redirects, $header) { + $destination = drupal_get_destination(); + $default_status_code = variable_get('redirect_default_status_code', 301); + + // Set up the header. + $header = array_combine($header, $header); + $header = array_intersect_key(array( + 'source' => array('data' => t('From'), 'field' => 'source', 'sort' => 'asc'), + 'redirect' => array('data' => t('To'), 'field' => 'redirect'), + 'status' => array('data' => t('Status'), 'field' => 'status'), + 'status_code' => array('data' => t('Type'), 'field' => 'status_code'), + 'language' => array('data' => t('Language'), 'field' => 'language'), + 'count' => array('data' => t('Count'), 'field' => 'count'), + 'access' => array('data' => t('Last accessed'), 'field' => 'access'), + 'operations' => array('data' => t('Operations')), + ), $header); + + // Do not include the language column if locale is disabled. + if (!module_exists('locale')) { + unset($header['language']); + } + + $rows = array(); + foreach ($redirects as $rid => $redirect) { + $row = array(); + $redirect->source_options = array_merge($redirect->source_options, array('alias' => TRUE, 'language' => redirect_language_load($redirect->language))); + $source_url = redirect_url($redirect->source, $redirect->source_options); + $redirect_url = redirect_url($redirect->redirect, array_merge($redirect->redirect_options, array('alias' => TRUE))); + $row['data']['source'] = l($source_url, $redirect->source, $redirect->source_options); + $row['data']['redirect'] = l($redirect_url, $redirect->redirect, $redirect->redirect_options); + $row['data']['status'] = $redirect->status ? t('Enabled') : t('Disabled'); + $row['data']['status_code'] = $redirect->status_code ? $redirect->status_code : t('Default (@default)', array('@default' => $default_status_code)); + $row['data']['language'] = module_invoke('locale', 'language_name', $redirect->language); + $row['data']['count'] = $redirect->count; + if ($redirect->access) { + $row['data']['access'] = array( + 'data' => t('!interval ago', array('!interval' => format_interval(REQUEST_TIME - $redirect->access))), + 'title' => t('Last accessed on @date', array('@date' => format_date($redirect->access))), + ); + } + else { + $row['data']['access'] = t('Never'); + } + + // Mark redirects that override existing paths with a warning in the table. + if (drupal_valid_path($redirect->source)) { + $row['class'][] = 'warning'; + $row['title'] = t('This redirect overrides an existing internal path.'); + } + if ($redirect->status) { + $row['class'][] = 'redirect-enabled'; + } + else { + $row['class'][] = 'redirect-disabled'; + } + + $operations = array(); + if (redirect_access('update', $redirect)) { + $operations['edit'] = array( + 'title' => t('Edit'), + 'href' => 'admin/config/search/redirect/edit/' . $rid, + 'query' => $destination, + ); + } + if (redirect_access('delete', $redirect)) { + $operations['delete'] = array( + 'title' => t('Delete'), + 'href' => 'admin/config/search/redirect/delete/' . $rid, + 'query' => $destination, + ); + } + $row['data']['operations'] = array( + 'data' => array( + '#theme' => 'links', + '#links' => $operations, + '#attributes' => array('class' => array('links', 'inline', 'nowrap')), + ), + ); + + $row['data'] = array_intersect_key($row['data'], $header); + $rows[$rid] = $row; + } + + $build['list'] = array( + '#theme' => 'table', + '#header' => $header, + '#rows' => $rows, + '#empty' => t('No URL redirects available.'), + '#attributes' => array('class' => array('redirect-list')), + ); + + return $build; +} diff --git a/profiles/wcm_base/modules/contrib/redirect/redirect.admin.js b/profiles/wcm_base/modules/contrib/redirect/redirect.admin.js new file mode 100644 index 00000000..d169d4be --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/redirect.admin.js @@ -0,0 +1,28 @@ + +(function ($) { + +Drupal.behaviors.redirectAdmin = { + attach: function (context) { + $('table.redirect-list-tableselect tbody input:checkbox').bind('change', function(context) { + var checked = $('table.redirect-list-tableselect input:checkbox:checked').length; + if (checked) { + $('fieldset.redirect-list-operations').slideDown(); + } + else { + $('fieldset.redirect-list-operations').slideUp(); + } + }); + $('table.redirect-list-tableselect th.select-all input:checkbox').bind('change', function(context) { + var checked = $(this, context).attr('checked'); + if (checked) { + $('fieldset.redirect-list-operations').slideDown(); + } + else { + $('fieldset.redirect-list-operations').slideUp(); + } + }); + $('fieldset.redirect-list-operations').hide(); + } +}; + +})(jQuery); diff --git a/profiles/wcm_base/modules/contrib/redirect/redirect.api.php b/profiles/wcm_base/modules/contrib/redirect/redirect.api.php new file mode 100644 index 00000000..f38d7153 --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/redirect.api.php @@ -0,0 +1,295 @@ +<?php + +/** + * @file + * Hooks provided by the Redirect module. + */ + +/** + * @defgroup redirect_api_hooks Redirect API Hooks + * @{ + * During redirect operations (create, update, view, delete, etc.), there are + * several sets of hooks that get invoked to allow modules to modify the + * redirect operation: + * - All-module hooks: Generic hooks for "redirect" operations. These are + * always invoked on all modules. + * - Entity hooks: Generic hooks for "entity" operations. These are always + * invoked on all modules. + * + * Here is a list of the redirect and entity hooks that are invoked, and other + * steps that take place during redirect operations: + * - Creating a new redirect (calling redirect_save() on a new redirect): + * - hook_redirect_presave() (all) + * - Redirect written to the database + * - hook_redirect_insert() (all) + * - hook_entity_insert() (all) + * - Updating an existing redirect (calling redirect_save() on an existing redirect): + * - hook_redirect_presave() (all) + * - Redirect written to the database + * - hook_redirect_update() (all) + * - hook_entity_update() (all) + * - Loading a redirect (calling redirect_load(), redirect_load_multiple(), or + * entity_load() with $entity_type of 'redirect'): + * - Redirect information is read from database. + * - hook_entity_load() (all) + * - hook_redirect_load() (all) + * - Deleting a redirect (calling redirect_delete() or redirect_delete_multiple()): + * - Redirect is loaded (see Loading section above) + * - Redirect information is deleted from database + * - hook_redirect_delete() (all) + * - hook_entity_delete() (all) + * - Preparing a redirect for editing (note that if it's + * an existing redirect, it will already be loaded; see the Loading section + * above): + * - hook_redirect_prepare() (all) + * - Validating a redirect during editing form submit (calling + * redirect_form_validate()): + * - hook_redirect_validate() (all) + * @} + */ + +/** + * @addtogroup hooks + * @{ + */ + +/** + * Act on redirects being loaded from the database. + * + * This hook is invoked during redirect loading, which is handled by + * entity_load(), via classes RedirectController and + * DrupalDefaultEntityController. After the redirect information is read from + * the database or the entity cache, hook_entity_load() is invoked on all + * implementing modules, and then hook_redirect_load() is invoked on all + * implementing modules. + * + * This hook should only be used to add information that is not in the redirect + * table, not to replace information that is in that table (which could + * interfere with the entity cache). For performance reasons, information for + * all available redirects should be loaded in a single query where possible. + * + * The $types parameter allows for your module to have an early return (for + * efficiency) if your module only supports certain redirect types. + * + * @param $redirects + * An array of the redirects being loaded, keyed by rid. + * @param $types + * An array containing the types of the redirects. + * + * @ingroup redirect_api_hooks + */ +function hook_redirect_load(array &$redirects, $types) { + +} + +/** + * Alter the list of redirects matching a certain source. + * + * @param $redirects + * An array of redirect objects. + * @param $source + * The source request path. + * @param $context + * An array with the following key/value pairs: + * - language: The language code of the source request. + * - query: An array of the source request query string. + * + * @see redirect_load_by_source() + * @ingroup redirect_api_hooks + */ +function hook_redirect_load_by_source_alter(array &$redirects, $source, array $context) { + foreach ($redirects as $rid => $redirect) { + if ($redirect->source !== $source) { + // If the redirects to do not exactly match $source (e.g. case + // insensitive matches), then remove them from the results. + unset($redirects[$rid]); + } + } +} + +/** + * Control access to a redirect. + * + * Modules may implement this hook if they want to have a say in whether or not + * a given user has access to perform a given operation on a redirect. + * + * The administrative account (user ID #1) always passes any access check, + * so this hook is not called in that case. Users with the "administer redirects" + * permission may always update and delete redirects through the administrative + * interface. + * + * Note that not all modules will want to influence access on all + * redirect types. If your module does not want to actively grant or + * block access, return REDIRECT_ACCESS_IGNORE or simply return nothing. + * Blindly returning FALSE will break other redirect access modules. + * + * @param $redirect + * The redirect object on which the operation is to be performed, or, if it + * does not yet exist, the type of redirect to be created. + * @param $op + * The operation to be performed. Possible values: + * - "create" + * - "delete" + * - "update" + * @param $account + * A user object representing the user for whom the operation is to be + * performed. + * + * @return + * REDIRECT_ACCESS_ALLOW if the operation is to be allowed; + * REDIRECT_ACCESS_DENY if the operation is to be denied; + * REDIRECT_ACCESSS_IGNORE to not affect this operation at all. + * + * @see redirect_access() + * @ingroup redirect_api_hooks + */ +function hook_redirect_access($op, $redirect, $account) { + $type = is_string($redirect) ? $redirect : $redirect->type; + + if (in_array($type, array('normal', 'special'))) { + if ($op == 'create' && user_access('create ' . $type . ' redirects', $account)) { + return REDIRECT_ACCESS_ALLOW; + } + + if ($op == 'update') { + if (user_access('edit any ' . $type . ' content', $account) || (user_access('edit own ' . $type . ' content', $account) && ($account->uid == $redirect->uid))) { + return REDIRECT_ACCESS_ALLOW; + } + } + + if ($op == 'delete') { + if (user_access('delete any ' . $type . ' content', $account) || (user_access('delete own ' . $type . ' content', $account) && ($account->uid == $redirect->uid))) { + return REDIRECT_ACCESS_ALLOW; + } + } + } + + // Returning nothing from this function would have the same effect. + return REDIRECT_ACCESS_IGNORE; +} + +/** + * Act on a redirect object about to be shown on the add/edit form. + * + * This hook is invoked from redirect_object_prepare(). + * + * @param $redirect + * The redirect that is about to be shown on the add/edit form. + * + * @ingroup redirect_api_hooks + */ +function hook_redirect_prepare($redirect) { + +} + +/** + * Perform redirect validation before a redirect is created or updated. + * + * This hook is invoked from redirect_validate(), after a user has has finished + * editing the redirect and is submitting it. It is invoked at the end of all + * the standard validation steps. + * + * To indicate a validation error, use form_set_error(). + * + * Note: Changes made to the $redirect object within your hook implementation + * will have no effect. The preferred method to change a redirect's content is + * to use hook_redirect_presave() instead. If it is really necessary to change + * the redirect at the validate stage, you can use form_set_value(). + * + * @param $redirect + * The redirect being validated. + * @param $form + * The form being used to edit the redirect. + * @param $form_state + * The form state array. + * + * @see redirect_validate() + * @ingroup redirect_api_hooks + */ +function hook_redirect_validate($redirect, $form, $form_state) { + +} + +/** + * Act on a redirect being inserted or updated. + * + * This hook is invoked from redirect_save() before the redirect is saved to + * the database. + * + * @param $redirect + * The redirect that is being inserted or updated. + * + * @see redirect_save() + * @ingroup redirect_api_hooks + */ +function hook_redirect_presave($redirect) { + +} + +/** + * Respond to creation of a new redirect. + * + * This hook is invoked from redirect_save() after the redirect is inserted + * into the redirect table in the database. + * + * @param $redirect + * The redirect that is being created. + * + * @see redirect_save() + * @ingroup redirect_api_hooks + */ +function hook_redirect_insert($redirect) { + +} + +/** + * Respond to updates to a redirect. + * + * This hook is invoked from redirect_save() after the redirect is updated in + * the redirect table in the database. + * + * @param $redirect + * The redirect that is being updated. + * + * @see redirect_save() + * @ingroup redirect_api_hooks + */ +function hook_redirect_update($redirect) { + +} + +/** + * Respond to redirect deletion. + * + * This hook is invoked from redirect_delete_multiple() after the redirect has + * been removed from the redirect table in the database. + * + * @param $redirect + * The redirect that is being deleted. + * + * @see redirect_delete_multiple() + * @ingroup redirect_api_hooks + */ +function hook_redirect_delete($redirect) { + +} + +/** + * Act on a redirect being redirected. + * + * This hook is invoked from redirect_redirect() before the redirect callback + * is invoked. + * + * @param $redirect + * The redirect that is being used for the redirect. + * + * @see redirect_redirect() + * @see drupal_page_is_cacheable() + * @ingroup redirect_api_hooks + */ +function hook_redirect_alter($redirect) { +} + +/** + * @} End of "addtogroup hooks". + */ diff --git a/profiles/wcm_base/modules/contrib/redirect/redirect.controller.inc b/profiles/wcm_base/modules/contrib/redirect/redirect.controller.inc new file mode 100755 index 00000000..2d289b1e --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/redirect.controller.inc @@ -0,0 +1,20 @@ +<?php + + +/** + * Controller class for redirects. + * + * This extends the DrupalDefaultEntityController class, adding required + * special handling for redirect objects. + */ +class RedirectController extends DrupalDefaultEntityController { + + protected function attachLoad(&$redirects, $revision_id = FALSE) { + // Unserialize the URL option fields. + foreach ($redirects as $key => $redirect) { + $redirects[$key]->source_options = unserialize($redirect->source_options); + $redirects[$key]->redirect_options = unserialize($redirect->redirect_options); + } + parent::attachLoad($redirects, $revision_id); + } +} diff --git a/profiles/wcm_base/modules/contrib/redirect/redirect.drush.inc b/profiles/wcm_base/modules/contrib/redirect/redirect.drush.inc new file mode 100644 index 00000000..304f89a2 --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/redirect.drush.inc @@ -0,0 +1,72 @@ +<?php + +/** + * @file + * Drush integration for the redirect module. + */ + +/** + * Implementation of hook_drush_command(). + */ +function redirect_drush_command() { + $items['generate-redirects'] = array( + 'description' => 'Create redirects.', + 'drupal dependencies' => array('devel_generate'), + 'arguments' => array( + 'count' => 'Number of redirects to generate.', + ), + 'options' => array( + 'delete' => 'Delete all redirects before generating new ones.', + ), + ); + + return $items; +} + +/** + * Command callback. Generate a number of redirects. + */ +function drush_redirect_generate_redirects($count = NULL) { + if (drush_generate_is_number($count) == FALSE) { + return drush_set_error('DEVEL_GENERATE_INVALID_INPUT', t('Invalid number of redirects.')); + } + module_load_include('inc', 'redirect', 'redirect.generate'); + drush_generate_include_devel(); + redirect_run_unprogressive_batch('redirect_generate_redirects_batch_info', $count, drush_get_option('delete')); +} + +/** + * Perform an unprogressive batch process for CLI. + */ +function redirect_run_unprogressive_batch() { + $batch = batch_get(); + if (!empty($batch)) { + // If there is already something in the batch, don't run. + return FALSE; + } + + $args = func_get_args(); + $batch_callback = array_shift($args); + + if (!lock_acquire($batch_callback)) { + return FALSE; + } + + // Attempt to increase the execution time. + drupal_set_time_limit(240); + + // Build the batch array. + $batch = call_user_func_array($batch_callback, $args); + batch_set($batch); + + // We need to manually set the progressive variable again. + // @todo Remove when http://drupal.org/node/638712 is fixed. + $batch =& batch_get(); + $batch['progressive'] = FALSE; + + // Run the batch process. + batch_process(); + + lock_release($batch_callback); + return TRUE; +} diff --git a/profiles/wcm_base/modules/contrib/redirect/redirect.generate.inc b/profiles/wcm_base/modules/contrib/redirect/redirect.generate.inc new file mode 100644 index 00000000..c18357ab --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/redirect.generate.inc @@ -0,0 +1,182 @@ +<?php + +/** + * @file + * Devel generate integration for the redirect module. + */ + +function redirect_generate_form() { + $form['count'] = array( + '#type' => 'textfield', + '#title' => t('How many URL redirects would you like to generate?'), + '#default_value' => 50, + '#size' => 4, + ); + $form['delete'] = array( + '#type' => 'checkbox', + '#title' => t('Delete all URL redirects before generating new URL redirects.'), + '#default_value' => FALSE, + ); + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Generate'), + ); + + return $form; +} + +function redirect_generate_form_submit(&$form, &$form_state) { + // Run the batch. + $batch = redirect_generate_redirects_batch_info($form_state['values']['count'], $form_state['values']['delete']); + batch_set($batch); +} + +function redirect_generate_redirects_batch_info($count, $delete = FALSE) { + if ($delete) { + $operations[] = array('redirect_generate_batch_delete', array()); + } + + $operations[] = array('redirect_generate_batch_generate', array($count)); + + return array( + 'operations' => $operations, + 'finished' => 'redirect_generate_batch_finished', + 'file' => drupal_get_path('module', 'redirect') . '/redirect.generate.inc', + ); +} + +function redirect_generate_batch_delete(array &$context) { + if (empty($context['sandbox'])) { + $context['sandbox'] = array(); + $context['sandbox']['progress'] = 0; + $context['sandbox']['current_rid'] = 0; + $context['sandbox']['max'] = db_query('SELECT COUNT(DISTINCT rid) FROM {redirect}')->fetchField(); + } + + $limit = 20; + $rids = db_query_range("SELECT rid FROM {redirect} WHERE rid > :rid ORDER BY rid", 0, $limit, array(':rid' => $context['sandbox']['current_rid']))->fetchCol(); + redirect_delete_multiple($rids); + + // Update our progress information. + $context['sandbox']['progress'] += count($rids); + $context['sandbox']['current_rid'] = end($rids); + $context['message'] = t('Deleted URL redirect @rid.', array('@rid' => end($rids))); + + // Inform the batch engine that we are not finished, + // and provide an estimation of the completion level we reached. + if ($context['sandbox']['progress'] != $context['sandbox']['max']) { + $context['finished'] = ($context['sandbox']['progress'] >= $context['sandbox']['max']); + } +} + +function redirect_generate_batch_generate($num, array &$context) { + if (empty($context['sandbox'])) { + $context['sandbox'] = array(); + $context['sandbox']['progress'] = 0; + $context['sandbox']['max'] = $num; + + $query = db_select('node', 'n'); + $query->addField('n', 'nid'); + $query->condition('n.status', NODE_PUBLISHED); + $query->addTag('node_access'); + $context['sandbox']['nids'] = $query->execute()->fetchAllKeyed(0, 0); + } + + module_load_include('inc', 'devel_generate'); + + $limit = 20; + $types = array_keys(redirect_status_code_options()); + $languages = module_exists('locale') ? array_keys(locale_language_list('name')) : array(); + + for ($i = 0; $i < min($limit, $context['sandbox']['max'] - $context['sandbox']['progress']); $i++) { + $rand = mt_rand(0, 100); + + $redirect = new stdClass(); + redirect_object_prepare($redirect); + $redirect->source = _redirect_generate_url(); + $redirect->devel_generate = TRUE; + + if ($context['sandbox']['nids'] && $rand >= 40) { + $redirect->redirect = 'node/'. array_rand($context['sandbox']['nids']); + } + else { + $redirect->redirect = _redirect_generate_url(TRUE); + if ($rand <= 20) { + $redirect->redirect_options['query'] = _redirect_generate_querystring(); + } + if ($rand <= 5) { + $redirect->redirect_options['fragment'] = devel_generate_word(mt_rand(4, 8)); + } + } + + if ($rand <= 20) { + $redirect->status_code = $types[array_rand($types)]; + } + + if ($languages && $rand <= 20) { + $redirect->language = $languages[array_rand($languages)]; + } + + if ($rand <= 30) { + $redirect->source_options['query'] = _redirect_generate_querystring(); + } + + redirect_save($redirect); + + if (mt_rand(0, 1)) { + db_update('redirect') + ->fields(array( + 'count' => mt_rand(1, 500), + 'access' => mt_rand(REQUEST_TIME - 31536000, REQUEST_TIME), + )) + ->condition('rid', $redirect->rid) + ->execute(); + } + + $context['results'][] = $redirect->rid; + } + + // Update our progress information. + $context['sandbox']['progress'] += $limit; + //$context['message'] = t('Deleted URL redirect @rid.', array('@rid' => end($rids))); + + // Inform the batch engine that we are not finished, + // and provide an estimation of the completion level we reached. + if ($context['sandbox']['progress'] != $context['sandbox']['max']) { + $context['finished'] = ($context['sandbox']['progress'] >= $context['sandbox']['max']); + } +} + +function redirect_generate_batch_finished($success, $results, $operations) { + if ($success) { + drupal_set_message(format_plural(count($results), 'One URL redirect created.', '@count URL redirects created.')); + } + else { + // An error occurred. + // $operations contains the operations that remained unprocessed. + $error_operation = reset($operations); + drupal_set_message(t('An error occurred while processing @operation with arguments : @args', array('@operation' => $error_operation[0], '@args' => print_r($error_operation[0], TRUE)))); + } +} + +function _redirect_generate_url($external = FALSE, $max_levels = 2) { + module_load_include('inc', 'devel_generate'); + + $url = array(); + if ($external) { + $tlds = array('com', 'net', 'org'); + $url[] = 'http://www.example.'. $tlds[array_rand($tlds)]; + } + $max_levels = mt_rand($external ? 0 : 1, $max_levels); + for ($i = 1; $i <= $max_levels; $i++) { + $url[] = devel_generate_word(mt_rand(6 / $i, 8)); + } + return implode('/', $url); +} + +function _redirect_generate_querystring() { + module_load_include('inc', 'devel_generate'); + + $query = array(devel_generate_word(mt_rand(1, 3)) => devel_generate_word(mt_rand(2, 4))); + return $query; +} diff --git a/profiles/wcm_base/modules/contrib/redirect/redirect.info b/profiles/wcm_base/modules/contrib/redirect/redirect.info new file mode 100644 index 00000000..b04e0a38 --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/redirect.info @@ -0,0 +1,21 @@ +name = Redirect +description = Allows users to redirect from old URLs to new URLs. +core = 7.x +files[] = redirect.controller.inc +files[] = redirect.test +files[] = views/redirect.views.inc +;files[] = views/redirect_handler_field_redirect_type.inc +files[] = views/redirect_handler_filter_redirect_type.inc +files[] = views/redirect_handler_field_redirect_source.inc +files[] = views/redirect_handler_field_redirect_redirect.inc +files[] = views/redirect_handler_field_redirect_operations.inc +files[] = views/redirect_handler_field_redirect_link_edit.inc +files[] = views/redirect_handler_field_redirect_link_delete.inc +configure = admin/config/search/redirect/settings + +; Information added by Drupal.org packaging script on 2015-07-08 +version = "7.x-1.0-rc3" +core = "7.x" +project = "redirect" +datestamp = "1436393342" + diff --git a/profiles/wcm_base/modules/contrib/redirect/redirect.install b/profiles/wcm_base/modules/contrib/redirect/redirect.install new file mode 100644 index 00000000..a8fea019 --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/redirect.install @@ -0,0 +1,422 @@ +<?php + +/** + * @file + * Install, update and uninstall functions for the redirect module. + */ + +/** + * Implements hook_schema(). + */ +function redirect_schema() { + $schema['redirect'] = array( + 'description' => 'Stores information on redirects.', + 'fields' => array( + 'rid' => array( + 'type' => 'serial', + 'not null' => TRUE, + 'description' => 'Primary Key: Unique redirect ID.', + ), + 'hash' => array( + 'type' => 'varchar', + 'length' => 64, + 'not null' => TRUE, + 'description' => 'A unique hash based on source, source_options, and language.', + ), + 'type' => array( + 'type' => 'varchar', + 'length' => 64, + 'not null' => TRUE, + 'default' => '', + 'description' => "The redirect type; if value is 'redirect' it is a normal redirect handled by the module.", + ), + 'uid' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'description' => 'The {users}.uid of the user who created the redirect.', + ), + 'source' => array( + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'description' => 'The source path to redirect from.', + ), + 'source_options' => array( + 'type' => 'text', + 'not null' => TRUE, + 'serialize' => TRUE, + 'description' => 'A serialized array of source options.', + ), + 'redirect' => array( + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'description' => 'The destination path to redirect to.', + ), + 'redirect_options' => array( + 'type' => 'text', + 'not null' => TRUE, + 'serialize' => TRUE, + 'description' => 'A serialized array of redirect options.', + ), + 'language' => array( + 'description' => 'The language this redirect is for; if blank, the alias will be used for unknown languages.', + 'type' => 'varchar', + 'length' => 12, + 'not null' => TRUE, + 'default' => 'und', + ), + 'status_code' => array( + 'type' => 'int', + 'size' => 'small', + 'not null' => TRUE, + 'description' => 'The HTTP status code to use for the redirect.', + ), + 'count' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'description' => 'The number of times the redirect has been used.', + ), + 'access' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'description' => 'The timestamp of when the redirect was last accessed.', + ), + 'status' => array( + 'type' => 'int', + 'size' => 'small', + 'not null' => TRUE, + 'default' => 1, + 'description' => 'Boolean indicating whether the redirect is enabled (visible to non-administrators).', + ), + ), + 'primary key' => array('rid'), + 'unique keys' => array( + 'hash' => array('hash'), + ), + 'indexes' => array( + 'expires' => array('type', 'access'), + 'status_source_language' => array( + 'status', + 'source', + 'language', + ), + ), + ); + + return $schema; +} + +/** + * Implements hook_install(). + */ +function redirect_install() { + // If the path redirect table exists, then set the schema to run the + // migration update function. + if (db_table_exists('path_redirect')) { + drupal_set_installed_schema_version('redirect', 6999); + } +} + +/** + * Implements hook_uninstall(). + */ +function redirect_uninstall() { + drupal_load('module', 'redirect'); + $variables = array_keys(redirect_variables()); + foreach ($variables as $variable) { + variable_del($variable); + } +} + +/** + * Add the {redirect}.count field. + */ +function redirect_update_1() { + $field = array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'description' => 'The number of times the redirect has been used.', + ); + db_add_field('redirect', 'count', $field); +} + +/** + * Add the {redirect}.uid field. + */ +function redirect_update_2() { + $field = array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'description' => 'The {users}.uid of the user who created the redirect.', + ); + db_add_field('redirect', 'uid', $field); + db_update('redirect') + ->fields(array('uid' => 1)) + ->execute(); +} + +/** + * Enable bootstrap status for the module. + */ +function redirect_update_3() { + db_update('system') + ->fields(array('bootstrap' => 1)) + ->condition('type', 'module') + ->condition('name', 'redirect') + ->execute(); +} + +/** + * Change empty redirect types to 'redirect'. + */ +function redirect_update_4() { + db_update('redirect') + ->fields(array('type' => 'redirect')) + ->condition('type', '') + ->execute(); +} + +/** + * Rename {redirect}.last_used to {redirect}.access. + */ +function redirect_update_5() { + if (db_field_exists('redirect', 'last_used')) { + db_drop_index('redirect', 'expires'); + db_change_field('redirect', 'last_used', 'access', array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'description' => 'The timestamp of when the redirect was last accessed.', + )); + db_add_index('redirect', 'expires', array('type', 'access')); + } +} + +/** + * Add an index on the source and language columns in the redirect table. + */ +function redirect_update_6() { + if (!db_index_exists('redirect', 'source_language')) { + db_add_index('redirect', 'source_language', array('source', 'language')); + } +} + +/** + * Migrate data and variables from the Drupal 6 path_redirect module. + */ +function redirect_update_7000(&$sandbox) { + if (!isset($sandbox['progress']) && db_table_exists('path_redirect')) { + $sandbox['progress'] = 0; + $sandbox['current_rid'] = 0; + $sandbox['max'] = db_query('SELECT COUNT(rid) FROM {path_redirect}')->fetchField(); + $sandbox['skipped'] = array(); + } + + if (empty($sandbox['max'])) { + $sandbox['#finished'] = 1; + return t('No redirects to migrate.'); + } + + // Ensure the redirect module is loaded since we need to use its functions. + drupal_load('module', 'redirect'); + + $query = db_query_range("SELECT * FROM {path_redirect} WHERE rid > :rid ORDER BY rid", 0, 25, array(':rid' => $sandbox['current_rid'])); + foreach ($query as $old_redirect) { + $redirect = _redirect_migrate_path_redirect_redirect($old_redirect); + + if (empty($redirect->success)) { + $sandbox['skipped'][$old_redirect->rid] = t('RID @rid: @from to @to', array( + '@rid' => $old_redirect->rid, + '@from' => redirect_url($redirect->source, $redirect->source_options), + '@to' => redirect_url($redirect->redirect, $redirect->redirect_options), + )); + } + $sandbox['progress']++; + $sandbox['current_rid'] = $old_redirect->rid; + } + + $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max']; + + if ($sandbox['#finished'] >= 1) { + // Once finished, drop the old table. + db_drop_table('path_redirect'); + + // Migrate variables. + _redirect_migrate_path_redirect_variables(); + + // Remove the path_redirect entry from the system table. + db_delete('system') + ->condition('name', 'path_redirect') + ->execute(); + + // Show a message about how many redirects were migrated, and how many + // were skipped. + $skipped = count($sandbox['skipped']); + $migrated = $sandbox['progress'] - $skipped; + // @todo The following strings should be using t(). + $return = "Migrated $migrated redirects."; + if (!empty($sandbox['skipped'])) { + $return .= " The following $skipped redirects were not migrated since there were already existing redirects for the path and language combination:" . theme('item_list', array('items' => $sandbox['skipped'])); + } + return $return; + } +} + +/** + * Rebuild the registry and clear the entity info cache. + */ +function redirect_update_7100() { + if (!class_exists('RedirectController')) { + registry_rebuild(); + entity_info_cache_clear(); + } +} + +/** + * Add status field. + */ +function redirect_update_7101() { + db_add_field('redirect', 'status', array( + 'type' => 'int', + 'size' => 'small', + 'not null' => TRUE, + 'default' => 1, + 'description' => 'Boolean indicating whether the redirect is enabled (visible to non-administrators).', + )); + db_drop_index('redirect', 'source_language'); + db_add_index('redirect', 'status_source_language', array( + 'status', + 'source', + 'language', + )); +} + +/** + * Disable redirects that could cause infinite loops. + */ +function redirect_update_7102() { + $rids = db_query("SELECT r.rid FROM {redirect} r INNER JOIN {url_alias} u ON r.source = u.alias AND r.redirect = u.source AND r.language = u.language")->fetchCol(); + if ($rids) { + // Disable redirects + $count = db_update('redirect') + ->fields(array('status' => 0)) + ->condition('rid', $rids) + ->execute(); + + $disabled_redirects_message = format_plural($count, + '1 circular redirect causing infinite loop was disabled.', + '@count circular redirects causing infinite loop were disabled.'); + + return $disabled_redirects_message; + } + else { + return t('No circular redirects were found that could cause infinite loops.'); + } +} + +/** + * Migrate a path redirect redirect to a redirect redirect. + */ +function _redirect_migrate_path_redirect_redirect($old_redirect) { + $redirect = new stdClass(); + redirect_object_prepare($redirect); + + $source_parsed = redirect_parse_url($old_redirect->source); + $redirect->source = $source_parsed['url']; + if (!empty($source_parsed['query'])) { + $redirect->source_options['query'] = $source_parsed['query']; + } + + $redirect_parsed = redirect_parse_url($old_redirect->redirect) + array('query' => drupal_get_query_array($old_redirect->query), 'fragment' => $old_redirect->fragment); + $redirect->redirect = $redirect_parsed['url']; + if (!empty($redirect_parsed['query'])) { + $redirect->redirect_options['query'] = $redirect_parsed['query']; + } + if (!empty($redirect_parsed['fragment'])) { + $redirect->redirect_options['fragment'] = $redirect_parsed['fragment']; + } + if (!empty($redirect_parsed['https'])) { + $redirect->redirect_options['https'] = TRUE; + } + + // Make sure empty language codes get migrated to use the new constant. + $redirect->language = empty($old_redirect->language) ? LANGUAGE_NONE : $old_redirect->language; + + // Default status codes get a value of 0. + if ($old_redirect->type != variable_get('redirect_default_status_code', 301)) { + $redirect->status_code = (int) $old_redirect->type; + } + + redirect_hash($redirect); + if (redirect_load_by_hash($redirect->hash)) { + // If a redirect with the same hash already exists, then it needs to be + // skipped. + $redirect->success = FALSE; + } + else { + // Add the redirect to the database. + db_insert('redirect') + ->fields(array( + 'hash' => $redirect->hash, + 'type' => 'redirect', + 'uid' => 1, + 'source' => $redirect->source, + 'source_options' => serialize($redirect->source_options), + 'redirect' => $redirect->redirect, + 'redirect_options' => serialize($redirect->redirect_options), + 'language' => $redirect->language, + 'status_code' => $redirect->status_code, + 'status' => 1, + 'count' => 0, + 'access' => $old_redirect->last_used, + )) + ->execute(); + + // Migrating this redirect succeeded. + $redirect->success = TRUE; + } + + return $redirect; +} + +/** + * Migrate path redirect variables to redirect variables. + */ +function _redirect_migrate_path_redirect_variables() { + // Port path_redirect variables. + $variables = array( + 'path_redirect_default_status' => 'redirect_default_status_code', + 'path_redirect_purge_inactive' => 'redirect_purge_inactive', + 'path_redirect_retain_query_string' => 'redirect_passthrough_querystring', + 'path_redirect_auto_redirect' => 'redirect_auto_redirect', + 'path_redirect_redirect_warning' => 'redirect_warning', + 'path_redirect_allow_bypass' => NULL, + ); + foreach ($variables as $old_variable => $new_variable) { + if (!empty($new_variable)) { + $old_value = variable_get($old_variable); + $new_value = variable_get($new_variable); + + // Only if the old variable exists, and the new variable hasn't been set + // yet, do we set the new variable with the old value. + if (isset($old_value) && !isset($new_value)) { + variable_set($new_variable, $old_value); + } + } + + // Delete the old path redirect variable. + variable_del($old_variable); + } +} diff --git a/profiles/wcm_base/modules/contrib/redirect/redirect.js b/profiles/wcm_base/modules/contrib/redirect/redirect.js new file mode 100644 index 00000000..fedbaede --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/redirect.js @@ -0,0 +1,29 @@ + +(function ($) { + +Drupal.behaviors.redirectFieldsetSummaries = { + attach: function (context) { + $('fieldset.redirect-list', context).drupalSetSummary(function (context) { + if ($('table.redirect-list tbody td.empty', context).length) { + return Drupal.t('No redirects'); + } + else { + var enabled_redirects = $('table.redirect-list tbody tr.redirect-enabled', context).length; + var disabled_redirects = $('table.redirect-list tbody tr.redirect-disabled', context).length; + var text = ''; + if (enabled_redirects > 0) { + var text = Drupal.formatPlural(enabled_redirects, '1 enabled redirect', '@count enabled redirects'); + } + if (disabled_redirects > 0) { + if (text.length > 0) { + text = text + '<br />'; + } + text = text + Drupal.formatPlural(disabled_redirects, '1 disabled redirect', '@count disabled redirects'); + } + return text; + } + }); + } +}; + +})(jQuery); diff --git a/profiles/wcm_base/modules/contrib/redirect/redirect.module b/profiles/wcm_base/modules/contrib/redirect/redirect.module new file mode 100644 index 00000000..993eeed0 --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/redirect.module @@ -0,0 +1,1674 @@ +<?php + +/** + * @defgroup redirect_api Redirection API + * @{ + * Functions related to URL redirects. + * + * @} End of "defgroup redirect_api". + */ + +/** + * Modules should return this value from hook_redirect_access() to allow access + * to a redirect. + */ +define('REDIRECT_ACCESS_ALLOW', 'allow'); + +/** + * Modules should return this value from hook_redirect_access() to deny access + * to a redirect. + */ +define('REDIRECT_ACCESS_DENY', 'deny'); + +/** + * Modules should return this value from hook_redirect_access() to not affect + * redirect access. + */ +define('REDIRECT_ACCESS_IGNORE', NULL); + +/** + * Implements hook_entity_info(). + */ +function redirect_entity_info() { + $info['redirect'] = array( + 'label' => t('Redirect'), + 'base table' => 'redirect', + 'controller class' => 'RedirectController', + 'entity keys' => array( + 'id' => 'rid', + 'bundle' => 'type', + ), + 'fieldable' => FALSE, + 'uuid' => FALSE, + 'redirect' => FALSE, + ); + + return $info; +} + +/** + * Implements hook_hook_info(). + */ +function redirect_hook_info() { + $hooks = array( + 'redirect_load', + 'redirect_load_by_source_alter', + 'redirect_access', + 'redirect_prepare', + 'redirect_validate', + 'redirect_presave', + 'redirect_insert', + 'redirect_update', + 'redirect_delete', + 'redirect_alter', + ); + + return array_fill_keys($hooks, array('group' => 'redirect')); +} + +/** + * Implements hook_permission(). + */ +function redirect_permission() { + $permissions['administer redirects'] = array( + 'title' => t('Administer URL redirections'), + ); + return $permissions; +} + +/** + * Implements hook_help(). + */ +function redirect_help($path, $arg) { + $output = ''; + switch ($path) { + case 'admin/config/search/redirect/404': + $output = '<p>' . t('This page lists all paths that have resulted in 404 errors and do not yet have any redirects assigned to them.') . '</p>'; + break; + case 'admin/reports/page-not-found': + break; + } + return $output; +} + +/** + * Implements hook_menu(). + */ +function redirect_menu() { + $items['admin/config/search/redirect'] = array( + 'title' => 'URL redirects', + 'description' => 'Redirect users from one URL to another.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('redirect_list_form'), + 'access arguments' => array('administer redirects'), + 'file' => 'redirect.admin.inc', + ); + $items['admin/config/search/redirect/list'] = array( + 'title' => 'List', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -10, + ); + $items['admin/config/search/redirect/add'] = array( + 'title' => 'Add redirect', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('redirect_edit_form'), + 'access callback' => 'redirect_access', + 'access arguments' => array('create', 'redirect'), + 'file' => 'redirect.admin.inc', + 'type' => MENU_LOCAL_ACTION, + ); + $items['admin/config/search/redirect/edit/%redirect'] = array( + 'title' => 'Edit redirect', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('redirect_edit_form', 5), + 'access callback' => 'redirect_access', + 'access arguments' => array('update', 5), + 'file' => 'redirect.admin.inc', + ); + $items['admin/config/search/redirect/delete/%redirect'] = array( + 'title' => 'Delete redirect', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('redirect_delete_form', 5), + 'access callback' => 'redirect_access', + 'access arguments' => array('delete', 5), + 'file' => 'redirect.admin.inc', + ); + $items['admin/config/search/redirect/settings'] = array( + 'title' => 'Settings', + 'description' => 'Configure behavior for URL redirects.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('redirect_settings_form'), + 'access arguments' => array('administer redirects'), + 'file' => 'redirect.admin.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => 50, + ); + + // If the database logging module is enabled, add special 404 listing pages. + if (module_exists('dblog')) { + $items['admin/config/search/redirect/404'] = array( + 'title' => 'Fix 404 pages', + 'description' => 'Add redirects for 404 pages.', + 'page callback' => 'redirect_404_list', + 'access arguments' => array('administer redirects'), + 'file' => 'redirect.admin.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => 20, + ); + $items['admin/reports/page-not-found/redirect'] = array( + 'title' => 'Fix 404 pages with URL redirects', + 'page callback' => 'drupal_goto', + 'page arguments' => array('admin/config/search/redirect/404'), + 'access arguments' => array('administer redirects'), + 'type' => MENU_LOCAL_ACTION, + ); + } + + // Devel generate integration. + if (module_exists('devel_generate')) { + $items['admin/config/development/generate/redirects'] = array( + 'title' => 'Generate redirects', + 'description' => 'Generate a given number of redirects. Optionally delete current redirects.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('redirect_generate_form'), + 'access arguments' => array('administer redirects'), + 'file' => 'redirect.generate.inc', + ); + $items['admin/config/search/redirect/generate'] = $items['admin/config/development/generate/redirects']; + $items['admin/config/search/redirect/generate']['type'] = MENU_LOCAL_ACTION; + } + + return $items; +} + +function redirect_set_current_redirect($redirect) { + $static = &drupal_static(__FUNCTION__); + $static = $redirect; +} + +function redirect_get_current_redirect() { + $redirect = drupal_static('redirect_set_current_redirect', NULL); + + // If a redirect has not been set with redirect_set_current_redirect(), then + // attempt to find a redirect matching the current path, query string, and + // language code. + if (!isset($redirect)) { + $redirect = redirect_load_by_source(current_path(), $GLOBALS['language']->language, drupal_get_query_parameters()); + } + + // @todo Add an alter hook here? + return $redirect; +} + +/** + * Implements hook_url_inbound_alter(). + */ +function redirect_url_inbound_alter(&$path, $original_path, $path_language) { + // If the current path global does not exist, then drupal_get_path_alias() + // will fail. This condition only happens when $path is the front page. + // @todo Remove when http://drupal.org/node/1329914 is fixed in core. + if (empty($_GET['q'])) { + $_GET['q'] = variable_get('site_frontpage', 'node'); + return; + } + + // If the inbound path has been changed, then attempt to find a redirect + // matching the original path and save it for processing later in + // redirect_init(). For example, if the Sub-pathauto module changes the path + // 'foo/redirect' to 'node/1/redirect', and there is a redirect enabled for + // the path 'foo/redirect', then redirect_init() would normally fail since it + // would not find a match. + if ($path != $original_path && $original_path == current_path()) { + $current_langcode = !empty($path_language) ? $path_language : $GLOBALS['language']->language; + $current_query = drupal_get_query_parameters(); + if ($redirect = redirect_load_by_source($original_path, $current_langcode, $current_query)) { + redirect_set_current_redirect($redirect); + } + } + + // Redirect to canonical URLs. + // Commented out per https://www.drupal.org/node/2048137. + //if ($path && variable_get('redirect_canonical', 1)) { + //$alias = drupal_get_path_alias($path, $path_language); + //if ($alias != $path && $alias != $original_path) { + //return redirect_redirect(array('redirect' => $alias, 'type' => 'global')); + //} + + // Redirect from default entity paths to the proper entity path. + //if ($path_entity = redirect_load_entity_from_path($path)) { + // if ($uri = entity_uri($path_entity['entity_type'], $path_entity['entity'])) { + // if ($path != $uri['path']) { + // return redirect_redirect(array('redirect' => $uri['path'], 'redirect_options' => $uri['options'], 'type' => 'global')); + // } + // } + //} + //} +} + +/** + * Implements hook_entity_info_alter(). + */ +function redirect_entity_info_alter(&$info) { + $default_paths = array( + 'node' => 'node/%node', + 'user' => 'user/%user', + 'taxonomy_term' => 'taxonomy/term/%taxonomy_term', + ); + + foreach ($default_paths as $entity_type => $default_path) { + if (isset($info[$entity_type]) && !isset($info[$entity_type]['default path'])) { + $info[$entity_type]['default path'] = $default_path; + } + } + + // Disable support for some entity types that cause problems. + $unsupported_entity_types = array( + 'comment', + 'media', + ); + foreach ($unsupported_entity_types as $unsupported_entity_type) { + if (isset($info[$unsupported_entity_type])) { + $info[$unsupported_entity_type]['redirect'] = FALSE; + } + } +} + +/** + * Check if an entity type supports redirects. + * + * @param $entity_type + * An entity type. + * + * @return + * TRUE if the entity type has an uri callback and supports redirects, or + * FALSE otherwise. + */ +function redirect_entity_type_supports_redirects($entity_type) { + $types = &drupal_static(__FUNCTION__); + + if (!isset($types)) { + $types = array(); + foreach (entity_get_info() as $type => $entity_info) { + $types[$type] = !empty($entity_info['uri callback']) && (!isset($entity_info['redirect']) || !empty($entity_info['redirect'])); + } + } + + return isset($types[$entity_type]) ? $types[$entity_type] : FALSE; +} + +/** + * Implements hook_init(). + */ +function redirect_init() { + if (!redirect_can_redirect()) { + return; + } + + // Fetch the current redirect. + if ($redirect = redirect_get_current_redirect()) { + redirect_redirect($redirect); + } + + $redirect_global = FALSE; + $request_uri = $original_uri = ltrim(request_uri(), '/'); + + // Redirect from non-clean URLs to clean URLs. + if (variable_get('redirect_global_clean', 1) && variable_get('clean_url', 0) && strpos($request_uri, '?q=') !== FALSE) { + //$redirect_global = TRUE; + //$request_uri = str_replace('?q=', '', $request_uri); + } + + if (strpos($request_uri, 'index.php') !== FALSE) { + //$redirect_global = TRUE; + //$request_uri = str_replace('index.php', '', $request_uri); + } + + //$request_uri = ltrim($request_uri, '/'); + //$parsed = parse_url($request_uri); + + if ($redirect_global && $request_uri != $original_uri) { + redirect_redirect(array(/*'redirect' => $request_uri,*/ 'type' => 'global')); + } +} + +/** + * Implements hook_cron(). + */ +function redirect_cron() { + // Purge inactive self-managed redirects from the database. + redirect_purge_inactive_redirects(); +} + +/** + * Implements hook_exit(). + */ +function redirect_exit($destination = NULL) { + // If the current page is being cached, track it. + if (drupal_get_http_header('Location') && $rid = drupal_get_http_header('X-Redirect-ID')) { + // Ensure the database is loaded. This is only the next bootstrap step + // after DRUPAL_BOOTSTRAP_DATABASE + drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE); + db_update('redirect') + ->fields(array('access' => REQUEST_TIME)) + ->expression('count', 'count + 1') + ->condition('rid', $rid) + ->execute(); + } +} + +/** + * Implements hook_entity_delete(). + */ +function redirect_entity_delete($entity, $entity_type) { + if (redirect_entity_type_supports_redirects($entity_type)) { + redirect_delete_by_entity_path($entity_type, $entity); + } +} + +/** + * Implements hook_path_update(). + */ +function redirect_path_update(array $path) { + if (!variable_get('redirect_auto_redirect', TRUE)) { + return; + } + elseif (isset($path['redirect']) && !$path['redirect']) { + return; + } + + if (!empty($path['original']['pid']) && $path['original']['pid'] == $path['pid'] && $path['original']['alias'] != $path['alias']) { + // Disable all redirects having the same source as this alias. + redirect_disable_by_path($path['alias'], $path['language']); + $redirect = new stdClass(); + redirect_object_prepare($redirect); + $redirect->source = $path['original']['alias']; + $redirect->redirect = $path['source']; + $redirect->language = $path['original']['language']; + // Check if the redirect exists before saving. + $hash = redirect_hash($redirect); + $existing = redirect_load_by_hash($hash); + if (!$existing) { + redirect_save($redirect); + } + // If the existing redirect is disabled, re-enable it. + elseif (isset($existing->status) && $existing->status == 0) { + $existing->status = 1; + redirect_save($existing); + } + } +} + +/** + * Implements hook_path_insert(). + */ +function redirect_path_insert(array $path) { + if (!empty($path['alias'])) { + // Disable all redirects having the same source as this alias. + redirect_disable_by_path($path['alias'], $path['language']); + } +} + +/** + * Implements hook_path_delete(). + */ +function redirect_path_delete($path) { + if (!variable_get('redirect_auto_redirect', TRUE)) { + return; + } + elseif (isset($path['redirect']) && !$path['redirect']) { + return; + } + elseif (empty($path)) { + // @todo Remove this condition and allow $path to use an array type hint + // when http://drupal.org/node/1025904 is fixed. + return; + } + + // Redirect from a deleted alias to the system path. + //if (!redirect_load_by_source($path['alias'], $path['language'])) { + // $redirect = new stdClass(); + // redirect_object_prepare($redirect); + // $redirect->source = $path['alias']; + // $redirect->redirect = $path['source']; + // $redirect->language = $path['language']; + // redirect_save($redirect); + //} +} + +/** + * Implements hook_views_api(). + */ +function redirect_views_api() { + return array( + 'api' => 2, + 'path' => drupal_get_path('module', 'redirect') . '/views', + ); +} + +/** + * Implements hook_page_build(). + * + * Adds an action on 404 pages to create a redirect. + */ +function redirect_page_build(&$page) { + if (redirect_is_current_page_404() && user_access('administer redirects')) { + if (!isset($page['content']['system_main']['actions'])) { + $page['content']['system_main']['actions'] = array( + '#theme' => 'links', + '#links' => array(), + '#attributes' => array('class' => array('action-links')), + '#weight' => -100, + ); + } + // We cannot simply use current_path() because if a 404 path is set, then + // that value overrides whatever is in $_GET['q']. The + // drupal_deliver_html_page() function thankfully puts the original current + // path into $_GET['destination']. + $destination = drupal_get_destination(); + $page['content']['system_main']['actions']['#links']['add_redirect'] = array( + 'title' => t('Add URL redirect from this page to another location'), + 'href' => 'admin/config/search/redirect/add', + 'query' => array('source' => $destination['destination']) + drupal_get_destination(), + ); + } +} + +/** + * Implements hook_form_FORM_ID_alter(). + * + * Adds support for creating redirects if a node URL alias is changed. + */ +function redirect_form_node_form_alter(&$form, $form_state) { + if (!empty($form['path']['pid']['#value']) && !isset($form['path']['original'])) { + $form['path']['original'] = array('#type' => 'value', '#value' => path_load($form['path']['pid']['#value'])); + } +} + +/** + * Implements hook_form_FORM_ID_alter(). + * + * Adds support for creating redirects if a taxonomy term URL alias is changed. + */ +function redirect_form_taxonomy_form_term_alter(&$form, $form_state) { + if (!empty($form['path']['pid']['#value']) && !isset($form['path']['original'])) { + $form['path']['original'] = array('#type' => 'value', '#value' => path_load($form['path']['pid']['#value'])); + } +} + +/** + * Implements hook_form_FORM_ID_alter(). + * + * Adds support for creating redirects if an URL alias is changed. + */ +function redirect_form_path_admin_form_alter(&$form, $form_state) { + if (!empty($form['pid']['#value']) && !isset($form['original'])) { + $form['original'] = array('#type' => 'value', '#value' => path_load($form['pid']['#value'])); + } +} + +/** + * Load an URL redirect from the database. + * + * @param $rid + * The URL redirect ID. + * @param $reset + * Whether to reset the redirect_load_multiple cache. + * + * @return + * An URL redirect object, or FALSE if loading failed. + * + * @ingroup redirect_api + */ +function redirect_load($rid, $reset = FALSE) { + $redirects = entity_load('redirect', array($rid), array(), $reset); + return !empty($redirects) ? reset($redirects) : FALSE; +} + +/** + * Load an URL redirect from the database by {redirect}.hash. + * + * @param $hash + * The hash of the URL redirect. + * @param $reset + * Whether to reset the redirect_load_multiple cache. + * + * @return + * An URL redirect object, or FALSE if loading failed. + * + * @ingroup redirect_api + */ +function redirect_load_by_hash($hash, $reset = FALSE) { + $redirects = entity_load('redirect', FALSE, array('hash' => $hash), $reset); + return !empty($redirects) ? reset($redirects) : FALSE; +} + +/** + * Fetches multiple URL redirect IDs from the database by {redirect}.source. + * + * @param $source + * The source of the URL redirect. + * @param $language + * Language of the source URL. + * @param $enabled_only + * Boolean that indicates whether to only load enabled redirects. + * + * @return array + * An indexed array of IDs, or an empty array if there is no result set. + */ +function redirect_fetch_rids_by_path($source, $language, $enabled_only = FALSE) { + // Run a case-insensitive query for matching RIDs first. + $rid_query = db_select('redirect'); + $rid_query->addField('redirect', 'rid'); + // Prevent errors if redirect_update_7101() has not yet been run. + if ($enabled_only && db_field_exists('redirect', 'status')) { + $rid_query->condition('status', 1); + } + if ($source != variable_get('site_frontpage', 'node')) { + $rid_query->condition('source', db_like($source), 'LIKE'); + } + else { + $source_condition = db_or(); + $source_condition->condition('source', db_like($source), 'LIKE'); + $source_condition->condition('source', ''); + $rid_query->condition($source_condition); + } + $rid_query->condition('language', array($language, LANGUAGE_NONE)); + $rids = $rid_query->execute()->fetchCol(); + return $rids; +} + + +/** + * Load multiple URL redirects from the database by {redirect}.source. + * + * @param $source + * The source of the URL redirect. + * @param $language + * Language of the source URL. + * @param $query + * Array of URL query parameters. + * @param $enabled_only + * Boolean that indicates whether to only load enabled redirects. + * + * @return + * The first matched URL redirect object, or FALSE if there aren't any. + * + * @see redirect_load_multiple() + * @see _redirect_uasort() + * @see redirect_compare_array_recursive() + * + * @ingroup redirect_api + */ +function redirect_load_by_source($source, $language = LANGUAGE_NONE, array $query = array(), $enabled_only = TRUE) { + $rids = redirect_fetch_rids_by_path($source, $language, $enabled_only); + if ($rids && $redirects = redirect_load_multiple($rids)) { + // Narrow down the list of candidates. + foreach ($redirects as $rid => $redirect) { + if (!empty($redirect->source_options['query'])) { + if (empty($query) || !redirect_compare_array_recursive($redirect->source_options['query'], $query)) { + unset($redirects[$rid]); + continue; + } + } + + // Add a case sensitive matches condition to be used in sorting. + if ($source !== $redirect->source) { + $redirects[$rid]->weight = 1; + } + } + + if (!empty($redirects)) { + // Sort the redirects in the proper order. + uasort($redirects, '_redirect_uasort'); + + // Allow other modules to alter the redirect candidates before selecting the top one. + $context = array('language' => $language, 'query' => $query); + drupal_alter('redirect_load_by_source', $redirects, $source, $context); + + return !empty($redirects) ? reset($redirects) : FALSE; + } + } + + return FALSE; +} + +/** + * Load multiple URL redirects from the database. + * + * @param $rids + * An array of redirect IDs. + * @param $conditions + * An array of conditions on the {redirect} table in the form 'field' => + * $value. + * @param $reset + * Whether to reset the redirect_load_multiple cache. + * + * @return + * An array of URL redirect objects indexed by redirect IDs. + * + * @ingroup redirect_api + */ +function redirect_load_multiple($rids = array(), array $conditions = array(), $reset = FALSE) { + return entity_load('redirect', $rids, $conditions, $reset); +} + +/** + * Determine whether the current user may perform the given operation on the + * specified redirect. + * + * @param $op + * The operation to be performed on the redirect. Possible values are: + * - "create" + * - "update" + * - "delete" + * @param $redirect + * The redirect object on which the operation is to be performed, or redirect + * type (e.g. 'feedburner') for the "create" operation. + * @param $account + * Optional, a user object representing the user for whom the operation is to + * be performed. Determines access for a user other than the current user. + * + * @return + * TRUE if the operation may be performed, FALSE otherwise. + */ +function redirect_access($op, $redirect, $account = NULL) { + global $user; + + $rights = &drupal_static(__FUNCTION__, array()); + + if (!$redirect || !in_array($op, array('create', 'update', 'delete'), TRUE)) { + // If there was no redirect to check against, or the $op was not one of the + // supported ones, we return access denied. + return FALSE; + } + // If no user object is supplied, the access check is for the current user. + if (empty($account)) { + $account = $user; + } + + $cid = isset($redirect->rid) ? $redirect->rid : $redirect; + + // Return cached value if access already checked for this redirect, user and op. + if (isset($rights[$account->uid][$cid][$op])) { + return $rights[$account->uid][$cid][$op]; + } + + // Administrators can access all redirects. + if (user_access('administer redirects', $account)) { + $rights[$account->uid][$cid][$op] = TRUE; + return TRUE; + } + + // We grant access to the redirect if both of the following conditions are met: + // - No modules say to deny access. + // - At least one module says to grant access. + $access = module_invoke_all('redirect_access', $op, $redirect, $account); + if (in_array(REDIRECT_ACCESS_DENY, $access, TRUE)) { + $rights[$account->uid][$cid][$op] = FALSE; + return FALSE; + } + elseif (in_array(REDIRECT_ACCESS_ALLOW, $access, TRUE)) { + $rights[$account->uid][$cid][$op] = TRUE; + return TRUE; + } + + return FALSE; +} + +/** + * Validate a redirect. + */ +function redirect_validate($redirect, $form, &$form_state) { + $redirect = (object) $redirect; + + // check that there there are no redirect loops + if (url($redirect->source) == url($redirect->redirect)) { + form_set_error('redirect', t('You are attempting to redirect the page to itself. This will result in an infinite loop.')); + } + + redirect_hash($redirect); + if ($existing = redirect_load_by_hash($redirect->hash)) { + if ($redirect->rid != $existing->rid) { + form_set_error('source', t('A redirect already exists for the source path %source. Do you want to <a href="@edit-page">edit the existing redirect</a>?', array('%source' => redirect_url($redirect->source, $redirect->source_options), '@edit-page' => url('admin/config/search/redirect/edit/'. $existing->rid)))); + } + } + + // Allow other modules to validate the redirect. + foreach (module_implements('redirect_validate') as $module) { + $function = $module . '_redirect_validate'; + $function($redirect, $form, $form_state); + } +} + +function redirect_object_prepare($redirect, $defaults = array()) { + $defaults += array( + 'rid' => NULL, + 'type' => 'redirect', + 'uid' => $GLOBALS['user']->uid, + 'source_options' => array(), + 'redirect_options' => array(), + 'language' => LANGUAGE_NONE, + 'status_code' => 0, + 'count' => 0, + 'access' => 0, + 'hash' => '', + 'status' => 1, + ); + + foreach ($defaults as $key => $default) { + if (!isset($redirect->{$key})) { + $redirect->{$key} = $default; + } + } + + module_invoke_all('redirect_prepare', $redirect); +} + +/** + * Save an URL redirect. + * + * @param $redirect + * The URL redirect object to be saved. If $redirect->rid is omitted (or + * $redirect->is_new is TRUE), a new redirect will be added. + * + * @ingroup redirect_api + */ +function redirect_save($redirect) { + $transaction = db_transaction(); + + try { + if (!empty($redirect->rid) && !isset($redirect->original)) { + $redirect->original = entity_load_unchanged('redirect', $redirect->rid); + } + + // Determine if we will be inserting a new node. + if (!isset($redirect->is_new)) { + $redirect->is_new = empty($redirect->rid); + } + + // The changed timestamp is always updated for bookkeeping purposes. + //$redirect->changed = time(); + + redirect_hash($redirect); + if ($redirect->is_new || $redirect->hash != $redirect->original->hash) { + // Only new or changed redirects reset the last used value. + $redirect->count = 0; + $redirect->access = 0; + } + + // Allow other modules to alter the redirect before saving. + module_invoke_all('redirect_presave', $redirect); + module_invoke_all('entity_presave', $redirect, 'redirect'); + + // Save the redirect to the database and invoke the post-save hooks. + if ($redirect->is_new) { + drupal_write_record('redirect', $redirect); + module_invoke_all('redirect_insert', $redirect); + module_invoke_all('entity_insert', $redirect, 'redirect'); + } + else { + drupal_write_record('redirect', $redirect, array('rid')); + module_invoke_all('redirect_update', $redirect); + module_invoke_all('entity_update', $redirect, 'redirect'); + } + + // Clear internal properties. + unset($redirect->is_new); + unset($redirect->original); + + // Clear the static loading cache. + entity_get_controller('redirect')->resetCache(array($redirect->rid)); + + // Ignore slave server temporarily to give time for the + // saved node to be propagated to the slave. + db_ignore_slave(); + } + catch (Exception $e) { + $transaction->rollback(); + watchdog_exception('redirect', $e); + throw $e; + } +} + +/** + * Implements hook_redirect_insert(). + */ +function redirect_redirect_insert($redirect) { + redirect_page_cache_clear($redirect); +} + +/** + * Implements hook_redirect_update(). + */ +function redirect_redirect_update($redirect) { + redirect_page_cache_clear($redirect); + + // Clear the page cache for the original redirect as well. + if (!empty($redirect->original) && $redirect->original->source != $redirect->source) { + redirect_page_cache_clear($redirect->original); + } +} + +/** + * Implements hook_redirect_delete(). + */ +function redirect_redirect_delete($redirect) { + redirect_page_cache_clear($redirect); +} + +/** + * Delete a single URL redirect. + * + * @param $rid + * The ID of the redirect to delete. + * + * @ingroup redirect_api + */ +function redirect_delete($rid) { + return redirect_delete_multiple(array($rid)); +} + +/** + * Delete any redirects associated with a path or any of its sub-paths. + * + * Given a source like 'node/1' this function will delete any redirects that + * have that specific source or any sources that match 'node/1/%'. + * + * @param $path + * An string with an internal Drupal path. + * + * @ingroup redirect_api + */ +function redirect_delete_by_path($path) { + $query = db_select('redirect'); + $query->addField('redirect', 'rid'); + $query_or = db_or(); + $query_or->condition('source', db_like($path), 'LIKE'); + $query_or->condition('source', db_like($path . '/') . '%', 'LIKE'); + $query_or->condition('redirect', db_like($path), 'LIKE'); + $query_or->condition('redirect', db_like($path . '/') . '%', 'LIKE'); + $query->condition($query_or); + $rids = $query->execute()->fetchCol(); + + if ($rids) { + return redirect_delete_multiple($rids); + } +} + +/** + * Disable any redirects associated with a path. + * + * Given a source like 'node/1' this function will delete any redirects that + * have that specific source. + * + * @param $path + * An string with an internal Drupal path. + * + * @param @langauge + * The langcode of the path. + * + * @ingroup redirect_api + */ +function redirect_disable_by_path($path, $language) { + $rids = redirect_fetch_rids_by_path($path, $language, FALSE); + + if ($rids) { + return redirect_change_status_multiple($rids, 0); + } +} + +/** + * Delete an entity URL alias and any of its sub-paths. + * + * This function also checks to see if the default entity URI is different from + * the current entity URI and will delete any of the default aliases. + * + * @param $entity_type + * A string with the entity type. + * @param $entity + * An entity object. + * + * @ingroup redirect_api + */ +function redirect_delete_by_entity_path($entity_type, $entity) { + $uri = entity_uri($entity_type, $entity); + if (!empty($uri['path'])) { + redirect_delete_by_path($uri['path']); + } + + //$info = entity_get_info($entity_type); + //if (isset($info['default path'])) { + // list($id) = entity_extract_ids($entity_type, $entity); + // $default_path = str_replace('[id]', $id, $info['default path']); + // if ($uri['path'] !== $default_path) { + // redirect_delete_by_path($default_path); + // } + //} +} + +/** + * Change the status of multiple URL redirects. + * + * @param array $rids + * An array of redirect IDs to disable. + * @param int|string $status + * The status to set the redirect to: either disabled (0) or enabled (1). + * + * @ingroup redirect_api + */ +function redirect_change_status_multiple(array $rids, $status) { + if ($status !== 0 && $status !== 1 && $status !== '0' && $status !== '1') { + watchdog('Cannot change redirect status to %status', array('%status' => $status)); + drupal_set_message(t('Cannot change redirect status to %status', array('%status' => $status))); + return; + } + if (!empty($rids)) { + $redirects = redirect_load_multiple($rids, array(), TRUE); + + foreach ($redirects as $rid => $redirect) { + if (isset($redirect->status) && $redirect->status == $status) { + // We no-op if the redirect is not actually changing status. + // So if a disabled redirect is disabled, neither redirect_save() is + // triggered, nor do we log any message. + continue; + } + + $redirect->status = $status; + redirect_save($redirect); + + if ($status) { + $redirect_link = l($redirect->redirect, $redirect->redirect) . '=> ' . l($redirect->source, $redirect->source); + watchdog('redirect', 'Enabled redirect: !redirect_source_link', array('!redirect_link' => $redirect_link)); + } + else { + $redirect_link = l($redirect->redirect, $redirect->redirect) . '=> ' . l($redirect->source, $redirect->source); + watchdog('redirect', 'Disabled redirect: !redirect_source_link', array('!redirect_link' => $redirect_link)); + } + } + } +} + +/** + * Delete multiple URL redirects. + * + * @param $rids + * An array of redirect IDs to delete. + * + * @ingroup redirect_api + */ +function redirect_delete_multiple(array $rids) { + $transaction = db_transaction(); + if (!empty($rids)) { + $redirects = redirect_load_multiple($rids); + + try { + // Let modules react to the individual redirects being deleted. + foreach ($redirects as $rid => $redirect) { + module_invoke_all('redirect_delete', $redirect); + module_invoke_all('entity_delete', $redirect, 'redirect'); + } + + db_delete('redirect') + ->condition('rid', $rids, 'IN') + ->execute(); + } + catch (Exception $e) { + $transaction->rollback(); + watchdog_exception('redirect', $e); + throw $e; + } + + // Clear the redirect_load_multiple cache. + entity_get_controller('redirect')->resetCache(); + } +} + +/** + * Purge inactive redirects from the database. + * + * @param $types + * An array of redirect types to remove. Default is only the self-managed + * 'redirect'. If not provided all redirect types will be eligible for + * removal. + * @param $interval + * The number of seconds to subtract from the current time and used to + * find the inactive redirects. + * + * @return + * An array of redirect IDs that were deleted or FALSE if none were. + */ +function redirect_purge_inactive_redirects(array $types = array('redirect'), $interval = NULL) { + if (!isset($interval)) { + $interval = variable_get('redirect_purge_inactive', 0); + } + + if (!$interval) { + return FALSE; + } + + if (variable_get('redirect_page_cache', 0) && !variable_get('page_cache_invoke_hooks', TRUE)) { + // If serving redirects from the page cache is enabled and hooks are not + // executed during page caching, then we cannot track when a redirect is + // used. Therefore, we cannot remove unused redirects. + watchdog('redirect', 'Due to existing settings, could not track when a redirect is used, so could not remove unused redirects.'); + return FALSE; + } + + $query = db_select('redirect'); + $query->addField('redirect', 'rid'); + if (!empty($types)) { + $query->condition('type', $types); + } + $query->condition('access', REQUEST_TIME - $interval, '<'); + $query->addTag('redirect_purge'); + $rids = $query->execute()->fetchCol(); + + if (count($rids)) { + redirect_delete_multiple($rids); + watchdog('redirect', format_plural(count($rids), 'Removed 1 inactive redirect from the database.', 'Removed @count inactive redirects from the database.')); + return $rids; + } +} + +/** + * Perform an URL redirect. + * + * @param $redirect + * An optional URL redirect array. + * + * @ingroup redirect_api + */ +function redirect_redirect($redirect = NULL) { + if (!isset($redirect)) { + $redirect = new stdClass(); + } + redirect_object_prepare($redirect, array('redirect' => current_path(), 'type' => 'manual', 'callback' => 'redirect_goto', 'cache' => TRUE)); + + if (empty($redirect->status_code)) { + $redirect->status_code = variable_get('redirect_default_status_code', 301); + } + + if (variable_get('redirect_passthrough_querystring', 1)) { + // Preserve the current query parameters in the redirect. + $redirect->redirect_options += array('query' => array()); + $redirect->redirect_options['query'] += drupal_get_query_parameters(); + } + + // Prevent the destination query parameter from overriding this redirect. + //if (isset($_GET['destination'])) { + // Simply unset the parameter since it has already been passed into + // $options['query'] in the previous code. + // unset($_GET['destination']); + //} + + // Allow other modules to alter the redirect before passing to drupal_goto(). + drupal_alter('redirect', $redirect); + + // Continue if the redirect has not been disabled by hook_redirect_alter(). + if (isset($redirect->redirect) && isset($redirect->callback) && $redirect->redirect !== FALSE && function_exists($redirect->callback)) { + // Prevent circular redirects. + if ($GLOBALS['base_root'] . request_uri() == url($redirect->redirect, array('absolute' => TRUE) + $redirect->redirect_options)) { + return FALSE; + } + // Perform the actual redirect. + $callback = $redirect->callback; + $callback($redirect); + } +} + +/** + * Redirect callback; perform an URL redirect. + */ +function redirect_goto($redirect) { + $redirect->redirect_options['absolute'] = TRUE; + $url = url($redirect->redirect, $redirect->redirect_options); + drupal_add_http_header('Location', $url); + drupal_add_http_header('Status', redirect_status_code_options($redirect->status_code)); + + if (!empty($redirect->rid)) { + // Add a custom header for the redirect ID so when the redirect is served + // from the page cache, we can track it. + drupal_add_http_header('X-Redirect-ID', $redirect->rid); + } + + if (!variable_get('redirect_page_cache', 0) || !variable_get('cache', 0) || !drupal_page_is_cacheable() || empty($redirect->cache)) { + drupal_exit($url); + } + + // @see drupal_exit() + if (drupal_get_bootstrap_phase() == DRUPAL_BOOTSTRAP_FULL) { + if (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update') { + module_invoke_all('exit', $url); + } + drupal_session_commit(); + if (variable_get('cache', 0)) { + // We must output something to allow the request to be cached. + echo ' '; + if ($cache = drupal_page_set_cache()) { + // When caching this redirect for the first time we still need to ensure + // that the correct cache headers are sent. + // @see drupal_page_footer() + drupal_serve_page_from_cache($cache); + } + } + } + + exit; +} + +function redirect_hash($redirect) { + $hash = array( + 'source' => $redirect->source, + 'language' => $redirect->language, + ); + if (!empty($redirect->source_options['query'])) { + $hash['source_query'] = $redirect->source_options['query']; + } + drupal_alter('redirect_hash', $hash, $redirect); + redirect_sort_recursive($hash, 'ksort'); + $redirect->hash = drupal_hash_base64(serialize($hash)); + return $redirect->hash; +} + +/** + * Clear a page from the page cache. + */ +function redirect_page_cache_clear($redirect = NULL) { + if (!variable_get('redirect_page_cache', 0)) { + return; + } + + if (isset($redirect)) { + $path = url($redirect->source, array('absolute' => TRUE)); + // Use a wildcard to catch paths with query strings. + cache_clear_all($path, 'cache_page', TRUE); + } + else { + // Clear the entire page cache. + cache_clear_all('*', 'cache_page', TRUE); + } +} + +/** + * Given a path determine if it is an entity default path. + * + * @param $path + * The internal path. The id of the entity should be in the string as '[id]'. + * @return + * An array with the entity type and the loaded entity object. + */ +function redirect_load_entity_from_path($path) { + $entity_paths = &drupal_static(__FUNCTION__); + + if (!isset($entity_paths)) { + $entity_paths = array(); + foreach (entity_get_info() as $entity_type => $entity_info) { + if (isset($entity_info['default path'])) { + $default_path = $entity_info['default path']; + $default_path = preg_quote($default_path, '/'); + $default_path = str_replace(preg_quote('%' . $entity_type, '/'), '(\d+)', $default_path); + $entity_paths[$entity_type] = $default_path; + } + } + } + + foreach ($entity_paths as $entity_type => $default_path) { + if (preg_match("/^{$default_path}$/", $path, $matches)) { + if ($entity = entity_load($entity_type, array($matches[1]))) { + return array('entity_type' => $entity_type, 'entity' => reset($entity)); + } + break; + } + } +} + +/** + * Check the ability to perform redirects with the current request context. + * + * This function checks the following conditions: + * - If the PHP entry point is the root index.php file. + * - If PHP is not running as CLI. + * - If the site is not offline or in install/update mode. + * - If the curerent page is not an admin page (check can be disabled). + * - If the current request does not have any POST data since a redirect + * may interrupt form submission. + * + * @return + * TRUE if redirections can be performed, or FALSE otherwise. + */ +function redirect_can_redirect() { + $can_redirect = &drupal_static(__FUNCTION__); + + if (!isset($can_redirect)) { + $path = current_path(); + $can_redirect = TRUE; + + if (!preg_match('/index\.php$/', $_SERVER['SCRIPT_NAME'])) { + // Do not redirect if the root script is not /index.php. + $can_redirect = FALSE; + } + elseif (!empty($_POST)) { + // Do not redirect if this is a post request with data. + $can_redirect = FALSE; + } + elseif (drupal_is_cli()) { + // If this is a command line request (Drush, etc), skip processing. + $can_redirect = FALSE; + } + elseif ((variable_get('maintenance_mode', 0) || defined('MAINTENANCE_MODE')) && !user_access('access site in maintenance mode')) { + // Do not redirect in offline or maintenance mode. + $can_redirect = FALSE; + } + elseif (!variable_get('redirect_global_admin_paths', 0) && path_is_admin($path)) { + // Do not redirect on admin paths. + $can_redirect = FALSE; + } + } + + return $can_redirect; +} + +/** + * Compare that all values and associations in one array match another array. + * + * We cannot use array_diff_assoc() here because we need to be recursive. + * + * @param $match + * The array that has the values. + * @param $haystack + * The array that will be searched for values. + * @return + * TRUE if all the elements of $match were found in $haystack, or FALSE + * otherwise. + */ +function redirect_compare_array_recursive($match, $haystack) { + foreach ($match as $key => $value) { + if (!array_key_exists($key, $haystack)) { + return FALSE; + } + elseif (is_array($value)) { + if (!is_array($haystack[$key])) { + return FALSE; + } + elseif (!redirect_compare_array_recursive($value, $haystack[$key])) { + return FALSE; + } + } + elseif ($value != $haystack[$key]) { + return FALSE; + } + } + return TRUE; +} + +/** + * Sort an array recusively. + * + * @param $array + * The array to sort, by reference. + * @param $callback + * The sorting callback to use (e.g. 'sort', 'ksort', 'asort'). + * + * @return + * TRUE on success or FALSE on failure. + */ +function redirect_sort_recursive(&$array, $callback = 'sort') { + $result = $callback($array); + foreach ($array as $key => $value) { + if (is_array($value)) { + $result &= redirect_sort_recursive($array[$key], $callback); + } + } + return $result; +} + +/** + * Load a language object by its language code. + * + * @todo Remove when http://drupal.org/node/660736 is fixed in Drupal core. + * + * @param $language + * A language code. If not provided the default language will be returned. + * @return + * A language object. + */ +function redirect_language_load($language = LANGUAGE_NONE) { + $languages = &drupal_static(__FUNCTION__); + + if (!isset($languages)) { + $languages = language_list(); + $languages[LANGUAGE_NONE] = NULL; + } + + return isset($languages[$language]) ? $languages[$language] : NULL; +} + +/** + * Build the URL of a redirect for display purposes only. + */ +function redirect_url($path, array $options = array(), $clean_url = NULL) { + if (!isset($clean_url)) { + $clean_url = variable_get('clean_url', 0); + } + + if ($path == '') { + $path = '<front>'; + } + + if (!isset($options['alter']) || !empty($options['alter'])) { + drupal_alter('redirect_url', $path, $options); + } + + // The base_url might be rewritten from the language rewrite in domain mode. + if (!isset($options['base_url'])) { + if (isset($options['https']) && variable_get('https', FALSE)) { + if ($options['https'] === TRUE) { + $options['base_url'] = $GLOBALS['base_secure_url']; + $options['absolute'] = TRUE; + } + elseif ($options['https'] === FALSE) { + $options['base_url'] = $GLOBALS['base_insecure_url']; + $options['absolute'] = TRUE; + } + } + else { + $options['base_url'] = $GLOBALS['base_url']; + } + } + + if (empty($options['absolute']) || url_is_external($path)) { + $url = $path; + } + else { + $url = $options['base_url'] . base_path() . $path; + } + + if (isset($options['query'])) { + $url .= $clean_url ? '?' : '&'; + $url .= drupal_http_build_query($options['query']); + } + if (isset($options['fragment'])) { + $url .= '#' . $options['fragment']; + } + + return $url; +} + +function redirect_variables() { + return array( + 'redirect_default_status_code' => 301, + 'redirect_auto_redirect' => TRUE, + 'redirect_warning' => FALSE, + 'redirect_passthrough_querystring' => 1, + 'redirect_page_cache' => 0, + 'redirect_purge_inactive' => 0, + 'redirect_global_home' => 1, + 'redirect_global_clean' => 1, + 'redirect_global_canonical' => 1, + 'redirect_global_admin_paths' => 0, + ); +} + +//function redirect_get_redirect_info() { +// $info = &drupal_static(__FUNCTION__); +// +// if (!isset($info)) { +// if ($cache = cache_get('redirect:info')) { +// $info = $cache->data; +// } +// else { +// $info = module_invoke_all('redirect_info'); +// drupal_alter('redirect_info', $info); +// cache_set('redirect:info', $info); +// } +// } +// +// return $info; +//} + +function redirect_parse_url($url) { + $original_url = $url; + $url = trim($url, " \t\n\r\0\x0B\/"); + $parsed = parse_url($url); + + if (isset($parsed['fragment'])) { + $url = substr($url, 0, -strlen($parsed['fragment'])); + $url = trim($url, '#'); + } + if (isset($parsed['query'])) { + $url = substr($url, 0, -strlen($parsed['query'])); + $url = trim($url, '?&'); + $parsed['query'] = drupal_get_query_array($parsed['query']); + } + + // Convert absolute to relative. + if (isset($parsed['scheme']) && isset($parsed['host'])) { + $base_secure_url = rtrim($GLOBALS['base_secure_url'] . base_path(), '/'); + $base_insecure_url = rtrim($GLOBALS['base_insecure_url'] . base_path(), '/'); + if (strpos($url, $base_secure_url) === 0) { + $url = str_replace($base_secure_url, '', $url); + $parsed['https'] = TRUE; + } + elseif (strpos($url, $base_insecure_url) === 0) { + $url = str_replace($base_insecure_url, '', $url); + } + } + + $url = trim($url, '/'); + + // Convert to frontpage paths. + if ($url == '<front>') { + $url = ''; + } + + //$parsed['url'] = http_build_query($url, HTTP_URL_STRIP_QUERY | HTTP_URL_STRIP_FRAGMENT); + $parsed['url'] = $url; + + // Allow modules to alter the parsed URL. + drupal_alter('redirect_parse_url', $parsed, $original_url); + + return $parsed; +} + +function redirect_status_code_options($code = NULL) { + $codes = array( + 300 => t('300 Multiple Choices'), + 301 => t('301 Moved Permanently'), + 302 => t('302 Found'), + 303 => t('303 See Other'), + 304 => t('304 Not Modified'), + 305 => t('305 Use Proxy'), + 307 => t('307 Temporary Redirect'), + ); + return isset($codes[$code]) ? $codes[$code] : $codes; +} + +/** + * Returns if the current page request is a page not found (404 status error). + * + * Why the fuck do we have to do this? Why is there not an easier way??? + * + * @return + * TRUE if the current page is a 404, or FALSE otherwise. + */ +function redirect_is_current_page_404() { + return drupal_get_http_header('Status') == '404 Not Found'; +} + +/** + * uasort callback; Compare redirects based on language neutrality and rids. + */ +function _redirect_uasort($a, $b) { + $a_weight = isset($a->weight) ? $a->weight : 0; + $b_weight = isset($b->weight) ? $b->weight : 0; + if ($a_weight != $b_weight) { + // First sort by weight (case sensitivity). + return $a_weight > $b_weight; + } + elseif ($a->language != $b->language) { + // Then sort by language specific over language neutral. + return $a->language == LANGUAGE_NONE; + } + elseif (!empty($a->source_options['query']) != !empty($b->source_options['query'])) { + // Then sort by redirects that do not have query strings over ones that do. + return empty($a->source_options['query']); + } + else { + // Lastly sort by the highest redirect ID. + return $a->rid < $b->rid; + } +} + +/** + * Implements hook_form_FORM_ID_alter() on behalf of locale.module. + */ +function locale_form_redirect_edit_form_alter(&$form, &$form_state) { + $form['language'] = array( + '#type' => 'select', + '#title' => t('Language'), + '#options' => array(LANGUAGE_NONE => t('All languages')) + locale_language_list('name'), + '#default_value' => $form['language']['#value'], + '#description' => t('A redirect set for a specific language will always be used when requesting this page in that language, and takes precedence over redirects set for <em>All languages</em>.'), + ); +} + +/** + * Implements hook_field_attach_form(). + * + * @todo Investigate using hook_entity_load() to load all entity redirects. + * @todo Figure out how to support entity URIs that contain query strings. + */ +function redirect_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) { + list($id) = entity_extract_ids($entity_type, $entity); + if (!empty($form['redirect']) || empty($id)) { + return; + } + + // Check if this entity type supports redirects. + if (!redirect_entity_type_supports_redirects($entity_type)) { + return; + } + + $uri = entity_uri($entity_type, $entity); + if (empty($uri['path'])) { + // If the entity has no source path, then we cannot lookup the existing + // redirects. + return; + } + + $info = entity_get_info($entity_type); + $form['redirect'] = array( + '#type' => 'fieldset', + '#title' => t('URL redirects'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#access' => user_access('administer redirects'), + '#weight' => 30, + '#attributes' => array('class' => array('redirect-list')), + ); + + // Only support vertical tabs if there is a vertical tab element. + foreach (element_children($form) as $key) { + if (isset($form[$key]['#type']) && $form[$key]['#type'] == 'vertical_tabs') { + $form['redirect']['#group'] = $key; + $form['redirect']['#attached']['js']['vertical-tabs'] = drupal_get_path('module', 'redirect') . '/redirect.js'; + } + } + + $redirect = array( + 'redirect' => $uri['path'], + 'redirect_options' => array_diff_key($uri['options'], array('entity_type' => '', 'entity' => '')), + 'language' => $langcode, + ); + + $form['redirect']['actions'] = array( + '#theme' => 'links', + '#links' => array(), + '#attributes' => array('class' => array('action-links')), + ); + if (redirect_access('create', 'redirect')) { + $form['redirect']['actions']['#links']['add'] = array( + 'title' => t('Add URL redirect to this @entitytype', array('@entitytype' => drupal_strtolower($info['label']))), + 'href' => 'admin/config/search/redirect/add', + 'query' => array_filter($redirect) + drupal_get_destination(), + ); + } + + // We don't have to put our include in $form_state['build_info']['files'] + // since the build array will already be cached. + module_load_include('inc', 'redirect', 'redirect.admin'); + $redirects = redirect_load_multiple(FALSE, array('redirect' => $uri['path'])); + $header = array('source', 'status', 'status_code', 'language', 'count', 'access', 'operations'); + $form['redirect'] += redirect_list_table($redirects, $header); +} + +/** + * Implements hook_field_extra_fields(). + */ +function redirect_field_extra_fields() { + $entity_info = entity_get_info(); + foreach (array_keys($entity_info) as $entity_type) { + if (!redirect_entity_type_supports_redirects($entity_type)) { + // Redirect is explicitly disabled for this entity type. + continue; + } + foreach (array_keys($entity_info[$entity_type]['bundles']) as $bundle) { + if (!isset($entity_info[$entity_type]['bundles'][$bundle]['uri callback']) && !isset($entity_info[$entity_type]['uri callback'])) { + // The bundle or base entity must have an URI callback defined otherwise + // we cannot use the entity_uri() function to lookup the entity's source + // path. + continue; + } + $info[$entity_type][$bundle]['form']['redirect'] = array( + 'label' => t('URL redirects'), + 'description' => t('Redirect module form elements'), + 'weight' => 30, + ); + } + } + return $info; +} + +/** + * Fetch an array of redirect bulk operations. + * + * @see hook_redirect_operations() + * @see hook_redirect_operations_alter() + */ +function redirect_get_redirect_operations() { + $operations = &drupal_static(__FUNCTION__); + + if (!isset($operations)) { + $operations = module_invoke_all('redirect_operations'); + drupal_alter('redirect_operations', $operations); + } + + return $operations; +} + +/** + * Implements hook_redirect_operations(). + */ +function redirect_redirect_operations() { + $operations['delete'] = array( + 'action' => t('Delete'), + 'action_past' => t('Deleted'), + 'callback' => 'redirect_delete_multiple', + 'confirm' => TRUE, + ); + $operations['disable'] = array( + 'action' => t('Disable'), + 'action_past' => t('Disabled'), + 'callback' => 'redirect_change_status_multiple', + 'callback arguments' => array(0), + 'confirm' => TRUE, + ); + $operations['enable'] = array( + 'action' => t('Enable'), + 'action_past' => t('Enabled'), + 'callback' => 'redirect_change_status_multiple', + 'callback arguments' => array(1), + 'confirm' => TRUE, + ); + return $operations; +} diff --git a/profiles/wcm_base/modules/contrib/redirect/redirect.test b/profiles/wcm_base/modules/contrib/redirect/redirect.test new file mode 100644 index 00000000..33c6d23d --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/redirect.test @@ -0,0 +1,287 @@ +<?php + +/** + * @file + * Unit tests for the redirect module. + */ + +class RedirectTestHelper extends DrupalWebTestCase { + function setUp(array $modules = array()) { + array_unshift($modules, 'redirect'); + parent::setUp($modules); + } + + protected function assertRedirect($redirect) { + $source_url = url($redirect->source, array('absolute' => TRUE) + $redirect->source_options); + $redirect_url = url($redirect->redirect, array('absolute' => TRUE) + $redirect->redirect_options); + $this->drupalGet($source_url); + $this->assertEqual($this->getUrl(), $redirect_url, t('Page %source was redirected to %redirect.', array('%source' => $source_url, '%redirect' => $redirect_url))); + + // Reload the redirect. + if (!empty($redirect->rid)) { + return redirect_load($redirect->rid); + } + } + + protected function assertNoRedirect($redirect) { + $source_url = url($redirect->source, array('absolute' => TRUE) + $redirect->source_options); + $this->drupalGet($source_url); + $this->assertEqual($this->getUrl(), $source_url, t('Page %url was not redirected.', array('%url' => $source_url))); + } + + /** + * Add an URL redirection + * + * @param $source + * A source path. + * @param $redirect + * A redirect path. + */ + protected function addRedirect($source_path, $redirect_path, array $redirect = array()) { + $source_parsed = redirect_parse_url($source_path); + $redirect['source'] = $source_parsed['url']; + if (isset($source_parsed['query'])) { + $redirect['source_options']['query'] = $source_parsed['query']; + } + + $redirect_parsed = redirect_parse_url($redirect_path); + $redirect['redirect'] = $redirect_parsed['url']; + if (isset($redirect_parsed['query'])) { + $redirect['redirect_options']['query'] = $redirect_parsed['query']; + } + if (isset($redirect_parsed['fragment'])) { + $redirect['redirect_options']['fragment'] = $redirect_parsed['fragment']; + } + + $redirect_object = new stdClass(); + redirect_object_prepare($redirect_object, $redirect); + redirect_save($redirect_object); + return $redirect_object; + } + + protected function assertPageCached($url, array $options = array()) { + $options['absolute'] = TRUE; + $url = url($url, $options); + $cache = cache_get($url, 'cache_page'); + $this->assertTrue($cache, t('Page %url was cached.', array('%url' => $url))); + return $cache; + } + + protected function assertPageNotCached($url, array $options = array()) { + $options['absolute'] = TRUE; + $url = url($url, $options); + $cache = cache_get($url, 'cache_page'); + $this->assertFalse($cache, t('Page %url was not cached.', array('%url' => $url))); + } + + protected function assertHeader($name, $expected, $headers = NULL) { + if (!isset($headers)) { + $headers = $this->drupalGetHeaders(); + $name = strtolower($name); + } + return $this->assertIdentical($headers[$name], $expected); + } +} + +class RedirectUnitTest extends RedirectTestHelper { + public static function getInfo() { + return array( + 'name' => 'Redirect unit tests', + 'description' => 'Test basic functions and functionality.', + 'group' => 'Redirect', + ); + } + + /** + * Test the redirect_compare_array_recursive() function. + */ + function testCompareArrayRecursive() { + $haystack = array('a' => 'aa', 'b' => 'bb', 'c' => array('c1' => 'cc1', 'c2' => 'cc2')); + $cases = array( + array('query' => array('a' => 'aa', 'b' => 'invalid'), 'result' => FALSE), + array('query' => array('b' => 'bb', 'b' => 'bb'), 'result' => TRUE), + array('query' => array('b' => 'bb', 'c' => 'invalid'), 'result' => FALSE), + array('query' => array('b' => 'bb', 'c' => array()), 'result' => TRUE), + array('query' => array('b' => 'bb', 'c' => array('invalid')), 'result' => FALSE), + array('query' => array('b' => 'bb', 'c' => array('c2' => 'invalid')), 'result' => FALSE), + array('query' => array('b' => 'bb', 'c' => array('c2' => 'cc2')), 'result' => TRUE), + ); + foreach ($cases as $index => $case) { + $this->assertEqual($case['result'], redirect_compare_array_recursive($case['query'], $haystack)); + } + } + + /** + * Test redirect_sort_recursive(). + */ + function testSortRecursive() { + $test_cases = array( + array( + 'input' => array('b' => 'aa', 'c' => array('c2' => 'aa', 'c1' => 'aa'), 'a' => 'aa'), + 'expected' => array('a' => 'aa', 'b' => 'aa', 'c' => array('c1' => 'aa', 'c2' => 'aa')), + 'callback' => 'ksort', + ), + ); + foreach ($test_cases as $index => $test_case) { + $output = $test_case['input']; + redirect_sort_recursive($output, $test_case['callback']); + $this->assertIdentical($output, $test_case['expected']); + } + } + + /** + * Test redirect_parse_url(). + */ + function testParseURL() { + //$test_cases = array( + // array( + // 'input' => array('b' => 'aa', 'c' => array('c2' => 'aa', 'c1' => 'aa'), 'a' => 'aa'), + // 'expected' => array('a' => 'aa', 'b' => 'aa', 'c' => array('c1' => 'aa', 'c2' => 'aa')), + // ), + //); + //foreach ($test_cases as $index => $test_case) { + // $output = redirect_parse_url($test_case['input']); + // $this->assertIdentical($output, $test_case['expected']); + //} + } +} + +class RedirectFunctionalTest extends RedirectTestHelper { + private $admin_user; + + public static function getInfo() { + return array( + 'name' => 'Redirect functional tests', + 'description' => 'Test interface functionality.', + 'group' => 'Redirect', + ); + } + + function setUp(array $modules = array()) { + parent::setUp($modules); + + $this->admin_user = $this->drupalCreateUser(array('administer redirects', 'access site reports', 'access content', 'create article content', 'edit any article content', 'create url aliases')); + $this->drupalLogin($this->admin_user); + } + + function test404Interface() { + // Check that 404 pages do get add redirect links for admin users. + $this->drupalGet('invalid-path1'); + $this->drupalGet('invalid-path2'); + $this->assertLink('Add URL redirect from this page to another location'); + + // Check that 403 pages do not get the add redirect link at all. + $this->drupalGet('admin/config/system/actions'); + $this->assertNoLink('Add URL redirect from this page to another location'); + + $this->drupalGet('admin/reports/page-not-found'); + $this->clickLink('Fix 404 pages with URL redirects'); + + // Check that normal users do not see the add redirect link on 404 pages. + $this->drupalLogout(); + $this->drupalGet('invalid-path3'); + $this->assertNoLink('Add an URL redirect from this page to another location'); + } + + function testPageCache() { + // Set up cache variables. + variable_set('cache', 1); + $edit = array( + 'redirect_page_cache' => TRUE, + 'redirect_purge_inactive' => 604800, + ); + $this->drupalPost('admin/config/search/redirect/settings', $edit, 'Save configuration'); + $this->assertText('The configuration options have been saved.'); + $this->drupalLogout(); + + // Add a new redirect. + $redirect = $this->addRedirect('redirect', 'node'); + $this->assertEqual($redirect->access, 0); + $this->assertEqual($redirect->count, 0); + $this->assertPageNotCached('redirect'); + + // Perform the redirect and check that last_used + $redirect = $this->assertRedirect($redirect); + $this->assertEqual($redirect->count, 1); + $this->assertTrue($redirect->access > 0); + $cache = $this->assertPageCached('redirect'); + $this->assertHeader('Location', url('node', array('absolute' => TRUE)), $cache->data['headers']); + $this->assertHeader('X-Redirect-ID', $redirect->rid, $cache->data['headers']); + + // Set a redirect to not used in a while and disable running bootstrap + // hooks during cache page serve. Running cron to remove inactive redirects + // should not remove since they cannot be tracked. + $redirect->access = 1; + redirect_save($redirect); + variable_set('page_cache_invoke_hooks', FALSE); + $this->cronRun(); + $this->assertRedirect($redirect); + + $redirect->access = 1; + redirect_save($redirect); + variable_set('page_cache_invoke_hooks', TRUE); + $this->cronRun(); + $this->assertNoRedirect($redirect); + } + + function testPathChangeRedirects() { + // Create an initial article node with a path alias. + $node = $this->drupalCreateNode(array('type' => 'article', 'path' => array('alias' => 'first-alias'))); + + // Change the node's alias will create an automatic redirect from 'first-alias' to the node. + $this->drupalPost("node/{$node->nid}/edit", array('path[alias]' => 'second-alias'), t('Save')); + $this->drupalGet('first-alias'); + $this->assertText($node->title); + + $this->drupalPost("node/{$node->nid}/edit", array('path[alias]' => 'first-alias'), t('Save')); + $this->assertResponse(200, "Changing node's alias back to 'first-alias' does not break page load with a circular redirect."); + $this->assertNoText('Infinite redirect loop prevented.'); + $this->drupalGet('second-alias'); + $this->assertText($node->title); + + $this->drupalPost("node/{$node->nid}/edit", array('path[alias]' => 'second-alias'), t('Save')); + $this->assertResponse(200, "Changing node's alias back to 'second-alias' does not break page load with a circular redirect."); + $this->assertNoText('Infinite redirect loop prevented.'); + // Check that first-alias redirect has been re-enabled. + $this->drupalGet('first-alias'); + $this->assertText($node->title); + } + + function testPathAddOverwriteRedirects() { + // Create an initial article node with a path alias. + $first_node = $this->drupalCreateNode(array('type' => 'article', 'path' => array('alias' => 'first-alias'))); + // Change the node's alias will create an automatic redirect from 'first-alias' to the node. + $this->drupalPost("node/{$first_node->nid}/edit", array('path[alias]' => 'second-alias'), t('Save')); + + // Now create a second article node with the same alias as the redirect + // created above. + $second_node = $this->drupalCreateNode(array('type' => 'article', 'path' => array('alias' => 'first-alias'))); + + // Visit the path 'first-alias' which should be an alias for $second_node. + $this->drupalGet('first-alias'); + $this->assertNoText($first_node->title, 'Adding a new path alias that matches an existing redirect disables the redirect.'); + $this->assertText($second_node->title, 'Adding a new path alias that matches an existing redirect disables the redirect.'); + } + + function testDisableEnableRedirect() { + // Add a new redirect. + $redirect = $this->addRedirect('redirect', 'node'); + // Check that it is enabled. + $this->assertEqual($redirect->status, 1); + + // Disable the redirect. + $edit = array('status' => FALSE); + $this->drupalPost("admin/config/search/redirect/edit/{$redirect->rid}", $edit, t('Save')); + $redirect = redirect_load($redirect->rid); + // Check that it has been disabled. + $this->assertEqual($redirect->status, 0); + $this->drupalGet("admin/config/search/redirect/edit/{$redirect->rid}"); + $this->assertNoFieldChecked('edit-status', 'status is unchecked'); + $this->assertNoRedirect($redirect); + + // Re-enable the redirect. + $edit = array('status' => 1); + $this->drupalPost("admin/config/search/redirect/edit/{$redirect->rid}", $edit, t('Save')); + $this->assertRedirect($redirect); + } +} diff --git a/profiles/wcm_base/modules/contrib/redirect/views/redirect.views.inc b/profiles/wcm_base/modules/contrib/redirect/views/redirect.views.inc new file mode 100644 index 00000000..86cdc1b4 --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/views/redirect.views.inc @@ -0,0 +1,219 @@ +<?php + +/** + * @file + * Views integration and data for the redirect module. + */ + +/** + * Implements hook_views_data(). + */ +function redirect_views_data() { + // Basic table information. + $data['redirect']['table']['group'] = t('Redirect'); + + // Advertise this table as a possible base table + $data['redirect']['table']['base'] = array( + 'field' => 'rid', + 'title' => t('URL redirects'), + 'help' => t('Listings of URL redirects.'), + 'weight' => 10, + ); + + // {redirect}.rid + $data['redirect']['rid'] = array( + 'title' => t('Redirect ID'), + 'help' => t('The internal ID of the redirect.'), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'filter' => array( + 'handler' => 'views_handler_filter_numeric', + 'allow empty' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_numeric', + ), + ); + + // {redirect}.type + $data['redirect']['type'] = array( + 'title' => t('Type'), + 'help' => t('The type of redirect.'), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'redirect_handler_filter_redirect_type', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_string', + ), + ); + + // {redirect}.uid + $data['users']['table']['join']['redirect'] = array( + 'left_field' => 'uid', + 'field' => 'uid', + ); + $data['redirect']['uid'] = array( + 'title' => t('User ID'), + 'help' => t('ID of user who created the URL redirect.'), + 'field' => array( + 'handler' => 'views_handler_field_user', + 'click sortable' => TRUE, + ), + 'argument' => array( + 'handler' => 'views_handler_argument_user_uid', + 'name field' => 'name', + ), + 'filter' => array( + 'title' => t('Name'), + 'handler' => 'views_handler_filter_user_name', + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'relationship' => array( + 'handler' => 'views_handler_relationship', + 'base' => 'users', + 'base field' => 'uid', + 'label' => t('user'), + ), + ); + $data['redirect']['uid_current'] = array( + 'real field' => 'uid', + 'title' => t('Current user'), + 'help' => t('Filter the view to the currently logged in user.'), + 'filter' => array( + 'handler' => 'views_handler_filter_user_current', + 'type' => 'yes-no', + ), + ); + + // {redirect}.source + $data['redirect']['source'] = array( + 'title' => t('Source URL'), + 'help' => t('The source URL which generates a redirect'), + 'field' => array( + 'handler' => 'redirect_handler_field_redirect_source', + 'click sortable' => TRUE, + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_string', + ), + ); + + // {redirect}.redirect + $data['redirect']['redirect'] = array( + 'title' => t('Redirect URL'), + 'help' => t('The destination URL'), + 'field' => array( + 'handler' => 'redirect_handler_field_redirect_redirect', + 'click sortable' => TRUE, + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_string', + ), + ); + + // Language field + if (module_exists('locale')) { + $data['redirect']['language'] = array( + 'title' => t('Language'), + 'help' => t('The language the redirect is for.'), + 'field' => array( + 'handler' => 'views_handler_field_locale_language', + 'click sortable' => TRUE, + ), + 'filter' => array( + 'handler' => 'views_handler_filter_locale_language', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_locale_language', + ), + ); + } + + // {redirect}.count + $data['redirect']['count'] = array( + 'title' => t('Clicks'), + 'help' => t('Number of times this URL redirect has been followed.'), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'filter' => array( + 'handler' => 'views_handler_filter_numeric', + 'allow empty' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_numeric', + ), + ); + + // {redirect}.access + $data['redirect']['access'] = array( + 'title' => t('Last accessed date'), + 'help' => t('The date/time the URL redirect was last accessed.'), + 'field' => array( + 'handler' => 'views_handler_field_date', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_date', + ), + ); + + $data['redirect']['operations'] = array( + 'field' => array( + 'title' => t('Operations'), + 'help' => t('Provide links to operations the user can perform for the URL redirect.'), + 'handler' => 'redirect_handler_field_redirect_operations', + ), + ); + + $data['redirect']['edit_redirect'] = array( + 'field' => array( + 'title' => t('Edit link'), + 'help' => t('Provide a simple link to edit the URL redirect.'), + 'handler' => 'redirect_handler_field_redirect_link_edit', + ), + ); + + $data['redirect']['delete_redirect'] = array( + 'field' => array( + 'title' => t('Delete link'), + 'help' => t('Provide a simple link to delete the URL redirect.'), + 'handler' => 'redirect_handler_field_redirect_link_delete', + ), + ); + + return $data; +} diff --git a/profiles/wcm_base/modules/contrib/redirect/views/redirect.views_default.inc b/profiles/wcm_base/modules/contrib/redirect/views/redirect.views_default.inc new file mode 100644 index 00000000..ec663bd6 --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/views/redirect.views_default.inc @@ -0,0 +1,16 @@ +<?php + +/** + * Implements hook_views_default_views(). + */ +function redirect_views_default_views() { + $views = array(); + $files = file_scan_directory(drupal_get_path('module', 'redirect') . '/views', '/\.view$/'); + foreach ($files as $path => $file) { + require $path; + if (isset($view)) { + $views[$view->name] = $view; + } + } + return $views; +} diff --git a/profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_field_redirect_link_delete.inc b/profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_field_redirect_link_delete.inc new file mode 100644 index 00000000..0d28927c --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_field_redirect_link_delete.inc @@ -0,0 +1,41 @@ +<?php + +/** + * @file + * Redirect field handler for edit links. + */ + +class redirect_handler_field_redirect_link_delete extends views_handler_field { + function construct() { + parent::construct(); + $this->additional_fields['rid'] = 'rid'; + } + + function option_definition() { + $options = parent::option_definition(); + $options['text'] = array('default' => '', 'translatable' => TRUE); + return $options; + } + + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + $form['text'] = array( + '#type' => 'textfield', + '#title' => t('Text to display'), + '#default_value' => $this->options['text'], + ); + } + + function query() { + $this->ensure_my_table(); + $this->add_additional_fields(); + } + + function render($values) { + $rid = $values->{$this->aliases['rid']}; + if (($redirect = redirect_load($rid)) && redirect_access('delete', $redirect)) { + $text = !empty($this->options['text']) ? $this->options['text'] : t('Delete'); + return l($text, "admin/config/search/redirect/delete/" . $rid, array('query' => drupal_get_destination())); + } + } +} diff --git a/profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_field_redirect_link_edit.inc b/profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_field_redirect_link_edit.inc new file mode 100644 index 00000000..87247026 --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_field_redirect_link_edit.inc @@ -0,0 +1,41 @@ +<?php + +/** + * @file + * Redirect field handler for edit links. + */ + +class redirect_handler_field_redirect_link_edit extends views_handler_field { + function construct() { + parent::construct(); + $this->additional_fields['rid'] = 'rid'; + } + + function option_definition() { + $options = parent::option_definition(); + $options['text'] = array('default' => '', 'translatable' => TRUE); + return $options; + } + + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + $form['text'] = array( + '#type' => 'textfield', + '#title' => t('Text to display'), + '#default_value' => $this->options['text'], + ); + } + + function query() { + $this->ensure_my_table(); + $this->add_additional_fields(); + } + + function render($values) { + $rid = $values->{$this->aliases['rid']}; + if (($redirect = redirect_load($rid)) && redirect_access('update', $redirect)) { + $text = !empty($this->options['text']) ? $this->options['text'] : t('Edit'); + return l($text, "admin/config/search/redirect/edit/" . $rid, array('query' => drupal_get_destination())); + } + } +} diff --git a/profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_field_redirect_operations.inc b/profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_field_redirect_operations.inc new file mode 100644 index 00000000..23af5075 --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_field_redirect_operations.inc @@ -0,0 +1,68 @@ +<?php + +/** + * @file + * Redirect field handler for redirect operations. + */ + +class redirect_handler_field_redirect_operations extends views_handler_field { + function construct() { + parent::construct(); + $this->additional_fields['rid'] = 'rid'; + } + + function option_definition() { + $options = parent::option_definition(); + $options['edit_text'] = array('default' => '', 'translatable' => TRUE); + $options['delete_text'] = array('default' => '', 'translatable' => TRUE); + return $options; + } + + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + $form['edit_text'] = array( + '#type' => 'textfield', + '#title' => t('Text to display for edit links'), + '#default_value' => $this->options['edit_text'], + ); + $form['delete_text'] = array( + '#type' => 'textfield', + '#title' => t('Text to display for delete links'), + '#default_value' => $this->options['delete_text'], + ); + } + + function query() { + $this->ensure_my_table(); + $this->add_additional_fields(); + } + + function render($values) { + $rid = $values->{$this->aliases['rid']}; + $redirect = redirect_load($rid); + $destination = drupal_get_destination(); + + $operations = array(); + if (redirect_access('update', $redirect)) { + $operations['edit'] = array( + 'title' => !empty($this->options['edit_text']) ? $this->options['edit_text'] : t('Edit'), + 'href' => 'admin/config/search/redirect/edit/' . $rid, + 'query' => $destination, + ); + } + if (redirect_access('delete', $redirect)) { + $operations['delete'] = array( + 'title' => !empty($this->options['delete_text']) ? $this->options['delete_text'] : t('Delete'), + 'href' => 'admin/config/search/redirect/delete/' . $rid, + 'query' => $destination, + ); + } + + if (!empty($operations)) { + return theme('links', array('links' => $operations, 'attributes' => array('class' => array('links', 'inline', 'nowrap')))); + } + else { + return ''; + } + } +} diff --git a/profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_field_redirect_redirect.inc b/profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_field_redirect_redirect.inc new file mode 100644 index 00000000..09930c80 --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_field_redirect_redirect.inc @@ -0,0 +1,66 @@ +<?php + +/** + * @file + * Redirect field handler for {redirect}.redirect. + */ + +class redirect_handler_field_redirect_redirect extends views_handler_field { + function construct() { + parent::construct(); + $this->additional_fields['redirect'] = 'redirect'; + $this->additional_fields['redirect_options'] = 'redirect_options'; + } + + function option_definition() { + $options = parent::option_definition(); + $options['text'] = array('default' => '', 'translatable' => TRUE); + $options['absolute'] = array('default' => FALSE); + $options['alter']['contains']['make_link']['default'] = TRUE; + return $options; + } + + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + + // This field will never be empty + $form['empty']['#access'] = FALSE; + $form['empty_zero']['#access'] = FALSE; + $form['hide_empty']['#access'] = FALSE; + + $form['alter']['make_link']['#description'] = t('If checked, this field will be made into a link.'); + $form['alter']['absolute']['#access'] = FALSE; + $form['alter']['path']['#access'] = FALSE; + + $form['text'] = array( + '#type' => 'textfield', + '#title' => t('Text to display'), + '#default_value' => $this->options['text'], + ); + $form['absolute'] = array( + '#type' => 'checkbox', + '#title' => t('Use absolute link (begins with "http://")'), + '#default_value' => $this->options['absolute'], + '#description' => t('If you want to use this as in "output this field as link" in "link path", you have to enabled this option.'), + ); + } + + function render($values) { + $redirect = $values->{$this->aliases['redirect']}; + $redirect_options = unserialize($values->{$this->aliases['redirect_options']}); + $redirect_options['absolute'] = !empty($this->options['absolute']); + + $url = redirect_url($redirect, $redirect_options); + $text = !empty($this->options['text']) ? $this->options['text'] : $url; + + if (!empty($this->options['alter']['make_link'])) { + $this->options['alter']['path'] = $url; + $this->options['alter']['absolute'] = $redirect_options['absolute']; + } + else { + $text = check_plain($text); + } + + return $text; + } +} diff --git a/profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_field_redirect_source.inc b/profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_field_redirect_source.inc new file mode 100644 index 00000000..b462d9a9 --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_field_redirect_source.inc @@ -0,0 +1,66 @@ +<?php + +/** + * @file + * Redirect field handler for {redirect}.source. + */ + +class redirect_handler_field_redirect_source extends views_handler_field { + function construct() { + parent::construct(); + $this->additional_fields['source'] = 'source'; + $this->additional_fields['source_options'] = 'source_options'; + } + + function option_definition() { + $options = parent::option_definition(); + $options['text'] = array('default' => '', 'translatable' => TRUE); + $options['absolute'] = array('default' => FALSE); + $options['alter']['contains']['make_link']['default'] = TRUE; + return $options; + } + + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + + // This field will never be empty + $form['empty']['#access'] = FALSE; + $form['empty_zero']['#access'] = FALSE; + $form['hide_empty']['#access'] = FALSE; + + $form['alter']['make_link']['#description'] = t('If checked, this field will be made into a link.'); + $form['alter']['absolute']['#access'] = FALSE; + $form['alter']['path']['#access'] = FALSE; + + $form['text'] = array( + '#type' => 'textfield', + '#title' => t('Text to display'), + '#default_value' => $this->options['text'], + ); + $form['absolute'] = array( + '#type' => 'checkbox', + '#title' => t('Use absolute link (begins with "http://")'), + '#default_value' => $this->options['absolute'], + '#description' => t('If you want to use this as in "output this field as link" in "link path", you have to enabled this option.'), + ); + } + + function render($values) { + $source = $values->{$this->aliases['source']}; + $source_options = unserialize($values->{$this->aliases['source_options']}); + $source_options['absolute'] = !empty($this->options['absolute']); + + $url = redirect_url($source, $source_options); + $text = !empty($this->options['text']) ? $this->options['text'] : $url; + + if (!empty($this->options['alter']['make_link'])) { + $this->options['alter']['path'] = $url; + $this->options['alter']['absolute'] = $source_options['absolute']; + } + else { + $text = check_plain($text); + } + + return $text; + } +} diff --git a/profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_filter_redirect_type.inc b/profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_filter_redirect_type.inc new file mode 100644 index 00000000..a559ac36 --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/views/redirect_handler_filter_redirect_type.inc @@ -0,0 +1,20 @@ +<?php + +/** + * @file + * Filter by redirect type. + */ + +class redirect_handler_filter_redirect_type extends views_handler_filter_in_operator { + function get_value_options() { + if (!isset($this->value_options)) { + $this->value_title = t('Redirect type'); + $options = array(); + $types = db_query("SELECT DISTINCT type FROM {redirect}")->fetchCol(); + foreach ($types as $type) { + $options[$type] = t(drupal_ucfirst($type)); + } + $this->value_options = $options; + } + } +} diff --git a/profiles/wcm_base/modules/contrib/redirect/views/redirects.view b/profiles/wcm_base/modules/contrib/redirect/views/redirects.view new file mode 100644 index 00000000..fd9e777f --- /dev/null +++ b/profiles/wcm_base/modules/contrib/redirect/views/redirects.view @@ -0,0 +1,177 @@ +<?php + +$view = new view(); +$view->name = 'redirects'; +$view->description = 'Displays a list of redirects on user and admin pages.'; +$view->tag = ''; +$view->base_table = 'redirect'; +$view->human_name = 'Redirects'; +$view->core = 0; +$view->api_version = '3.0'; +$view->disabled = TRUE; /* Edit this to true to make a default view disabled initially */ + +/* Display: Defaults */ +$handler = $view->new_display('default', 'Defaults', 'default'); +$handler->display->display_options['use_more_always'] = FALSE; +$handler->display->display_options['access']['type'] = 'perm'; +$handler->display->display_options['access']['perm'] = 'administer redirects'; +$handler->display->display_options['cache']['type'] = 'none'; +$handler->display->display_options['query']['type'] = 'views_query'; +$handler->display->display_options['exposed_form']['type'] = 'basic'; +$handler->display->display_options['pager']['type'] = 'full'; +$handler->display->display_options['pager']['options']['items_per_page'] = '25'; +$handler->display->display_options['pager']['options']['offset'] = '0'; +$handler->display->display_options['pager']['options']['id'] = '0'; +$handler->display->display_options['style_plugin'] = 'table'; +$handler->display->display_options['style_options']['columns'] = array( + 'source' => 'source', + 'redirect' => 'redirect', + 'language' => 'language', + 'count' => 'count', + 'access' => 'access', + 'edit_redirect' => 'edit_redirect', + 'delete_redirect' => 'delete_redirect', +); +$handler->display->display_options['style_options']['default'] = '-1'; +$handler->display->display_options['style_options']['info'] = array( + 'source' => array( + 'sortable' => 1, + 'align' => '', + 'separator' => '', + ), + 'redirect' => array( + 'sortable' => 1, + 'align' => '', + 'separator' => '', + ), + 'language' => array( + 'sortable' => 1, + 'align' => '', + 'separator' => '', + ), + 'count' => array( + 'sortable' => 1, + 'align' => '', + 'separator' => '', + ), + 'access' => array( + 'sortable' => 1, + 'align' => '', + 'separator' => '', + ), + 'edit_redirect' => array( + 'align' => '', + 'separator' => '', + ), + 'delete_redirect' => array( + 'align' => '', + 'separator' => '', + ), +); +$handler->display->display_options['style_options']['sticky'] = TRUE; +/* No results behavior: Global: Text area */ +$handler->display->display_options['empty']['area']['id'] = 'area'; +$handler->display->display_options['empty']['area']['table'] = 'views'; +$handler->display->display_options['empty']['area']['field'] = 'area'; +$handler->display->display_options['empty']['area']['content'] = 'No URL redirects found.'; +$handler->display->display_options['empty']['area']['format'] = '1'; +/* Field: Redirect: Redirect ID */ +$handler->display->display_options['fields']['rid']['id'] = 'rid'; +$handler->display->display_options['fields']['rid']['table'] = 'redirect'; +$handler->display->display_options['fields']['rid']['field'] = 'rid'; +$handler->display->display_options['fields']['rid']['exclude'] = TRUE; +/* Field: Redirect: Source URL */ +$handler->display->display_options['fields']['source']['id'] = 'source'; +$handler->display->display_options['fields']['source']['table'] = 'redirect'; +$handler->display->display_options['fields']['source']['field'] = 'source'; +$handler->display->display_options['fields']['source']['absolute'] = 0; +/* Field: Redirect: Redirect URL */ +$handler->display->display_options['fields']['redirect']['id'] = 'redirect'; +$handler->display->display_options['fields']['redirect']['table'] = 'redirect'; +$handler->display->display_options['fields']['redirect']['field'] = 'redirect'; +$handler->display->display_options['fields']['redirect']['alter']['path'] = 'node'; +$handler->display->display_options['fields']['redirect']['alter']['absolute'] = TRUE; +$handler->display->display_options['fields']['redirect']['absolute'] = 0; +/* Field: Redirect: Language */ +$handler->display->display_options['fields']['language']['id'] = 'language'; +$handler->display->display_options['fields']['language']['table'] = 'redirect'; +$handler->display->display_options['fields']['language']['field'] = 'language'; +$handler->display->display_options['fields']['language']['empty'] = 'All'; +/* Field: Redirect: Clicks */ +$handler->display->display_options['fields']['count']['id'] = 'count'; +$handler->display->display_options['fields']['count']['table'] = 'redirect'; +$handler->display->display_options['fields']['count']['field'] = 'count'; +/* Field: Redirect: Last accessed date */ +$handler->display->display_options['fields']['access']['id'] = 'access'; +$handler->display->display_options['fields']['access']['table'] = 'redirect'; +$handler->display->display_options['fields']['access']['field'] = 'access'; +$handler->display->display_options['fields']['access']['label'] = 'Last accessed'; +$handler->display->display_options['fields']['access']['empty'] = 'Never'; +$handler->display->display_options['fields']['access']['empty_zero'] = TRUE; +$handler->display->display_options['fields']['access']['date_format'] = 'time ago'; +/* Field: Redirect: Operations */ +$handler->display->display_options['fields']['operations']['id'] = 'operations'; +$handler->display->display_options['fields']['operations']['table'] = 'redirect'; +$handler->display->display_options['fields']['operations']['field'] = 'operations'; +/* Filter criterion: Redirect: Type */ +$handler->display->display_options['filters']['type']['id'] = 'type'; +$handler->display->display_options['filters']['type']['table'] = 'redirect'; +$handler->display->display_options['filters']['type']['field'] = 'type'; +$handler->display->display_options['filters']['type']['value'] = array( + 'redirect' => 'redirect', +); + +/* Display: Page: User redirects */ +$handler = $view->new_display('page', 'Page: User redirects', 'page_user'); +$handler->display->display_options['defaults']['hide_admin_links'] = FALSE; +$handler->display->display_options['defaults']['arguments'] = FALSE; +/* Contextual filter: Redirect: User ID */ +$handler->display->display_options['arguments']['uid']['id'] = 'uid'; +$handler->display->display_options['arguments']['uid']['table'] = 'redirect'; +$handler->display->display_options['arguments']['uid']['field'] = 'uid'; +$handler->display->display_options['arguments']['uid']['default_action'] = 'default'; +$handler->display->display_options['arguments']['uid']['default_argument_type'] = 'user'; +$handler->display->display_options['arguments']['uid']['default_argument_options']['user'] = FALSE; +$handler->display->display_options['arguments']['uid']['summary']['format'] = 'default_summary'; +$handler->display->display_options['path'] = 'user/%/redirects'; +$handler->display->display_options['menu']['type'] = 'tab'; +$handler->display->display_options['menu']['title'] = 'Redirects'; +$handler->display->display_options['menu']['weight'] = '0'; + +/* Display: Page: Admin redirects */ +$handler = $view->new_display('page', 'Page: Admin redirects', 'page_admin'); +$handler->display->display_options['defaults']['hide_admin_links'] = FALSE; +$handler->display->display_options['path'] = 'admin/config/search/redirect/list'; +$handler->display->display_options['menu']['type'] = 'default tab'; +$handler->display->display_options['menu']['title'] = 'List'; +$handler->display->display_options['menu']['weight'] = '0'; +$handler->display->display_options['menu']['name'] = 'main-menu'; +$handler->display->display_options['tab_options']['weight'] = '0'; +$translatables['redirects'] = array( + t('Defaults'), + t('more'), + t('Apply'), + t('Reset'), + t('Sort by'), + t('Asc'), + t('Desc'), + t('Items per page'), + t('- All -'), + t('Offset'), + t('« first'), + t('‹ previous'), + t('next ›'), + t('last »'), + t('No URL redirects found.'), + t('Redirect ID'), + t('Source URL'), + t('Redirect URL'), + t('Language'), + t('All'), + t('Clicks'), + t('Last accessed'), + t('Never'), + t('Operations'), + t('Page: User redirects'), + t('Page: Admin redirects'), +); diff --git a/profiles/wcm_base/modules/custom/ocio_buckeye_alert/css/buckeye-alert.css b/profiles/wcm_base/modules/custom/ocio_buckeye_alert/css/buckeye-alert.css index b7cb2dc0..542d2031 100644 --- a/profiles/wcm_base/modules/custom/ocio_buckeye_alert/css/buckeye-alert.css +++ b/profiles/wcm_base/modules/custom/ocio_buckeye_alert/css/buckeye-alert.css @@ -6,7 +6,7 @@ #buckeye_alert p {padding:0.8em 0; margin:0;} #buckeye_alert a {color:#fff; text-decoration:underline;} -#buckeye_alert_msg p {font-size:1.2em;} +#buckeye_alert_msg p {font-size:1.1em;} #buckeye_alert_extra p {font-size:1em; padding-top:0;} #buckeye_alert {font-family:'proximanova',Arial,sans-serif; font-weight:700;} diff --git a/profiles/wcm_base/modules/custom/ocio_buckeye_alert/ocio_buckeye_alert.module b/profiles/wcm_base/modules/custom/ocio_buckeye_alert/ocio_buckeye_alert.module index 7d4b06aa..a64b5179 100644 --- a/profiles/wcm_base/modules/custom/ocio_buckeye_alert/ocio_buckeye_alert.module +++ b/profiles/wcm_base/modules/custom/ocio_buckeye_alert/ocio_buckeye_alert.module @@ -5,6 +5,17 @@ * ocio_buckeye_alert.module */ +/** + * Implements hook_permission(). + */ +function ocio_buckeye_alert_permission() { + return array( + 'administer buckeye alerts' => array( + 'title' => t('Administer Buckeye Alerts'), + ), + ); +} + /** * implements hook_menu() */ @@ -16,7 +27,7 @@ function ocio_buckeye_alert_menu() { 'description' => 'Configure the Buckeye Alerts module', 'page callback' => 'drupal_get_form', 'page arguments' => array('ocio_buckeye_alert_form'), - 'access arguments' => array('access administration pages'), + 'access arguments' => array('administer buckeye alerts'), 'type' => MENU_NORMAL_ITEM, ); diff --git a/profiles/wcm_base/modules/custom/ocio_permissions/ocio_permissions.features.user_permission.inc b/profiles/wcm_base/modules/custom/ocio_permissions/ocio_permissions.features.user_permission.inc index 6066bc8c..71eaea72 100644 --- a/profiles/wcm_base/modules/custom/ocio_permissions/ocio_permissions.features.user_permission.inc +++ b/profiles/wcm_base/modules/custom/ocio_permissions/ocio_permissions.features.user_permission.inc @@ -415,6 +415,15 @@ function ocio_permissions_user_default_permissions() { 'module' => 'breakpoints', ); + // Exported permission: 'administer buckeye alerts'. + $permissions['administer buckeye alerts'] = array( + 'name' => 'administer buckeye alerts', + 'roles' => array( + 'administrator' => 'administrator', + ), + 'module' => 'ocio_buckeye_alert', + ); + // Exported permission: 'administer consumers'. $permissions['administer consumers'] = array( 'name' => 'administer consumers', @@ -568,6 +577,15 @@ function ocio_permissions_user_default_permissions() { 'module' => 'linkit', ); + // Exported permission: 'administer mailsystem'. + $permissions['administer mailsystem'] = array( + 'name' => 'administer mailsystem', + 'roles' => array( + 'administrator' => 'administrator', + ), + 'module' => 'mailsystem', + ); + // Exported permission: 'administer manualcrop settings'. $permissions['administer manualcrop settings'] = array( 'name' => 'administer manualcrop settings', @@ -2303,6 +2321,16 @@ function ocio_permissions_user_default_permissions() { 'module' => 'fieldable_panels_panes', ); + // Exported permission: 'edit mimemail user settings'. + $permissions['edit mimemail user settings'] = array( + 'name' => 'edit mimemail user settings', + 'roles' => array( + 'administrator' => 'administrator', + 'authenticated user' => 'authenticated user', + ), + 'module' => 'mimemail', + ); + // Exported permission: 'edit node machine name'. $permissions['edit node machine name'] = array( 'name' => 'edit node machine name', @@ -3320,6 +3348,15 @@ function ocio_permissions_user_default_permissions() { 'module' => 'search', ); + // Exported permission: 'send arbitrary files'. + $permissions['send arbitrary files'] = array( + 'name' => 'send arbitrary files', + 'roles' => array( + 'administrator' => 'administrator', + ), + 'module' => 'mimemail', + ); + // Exported permission: 'switch shortcut sets'. $permissions['switch shortcut sets'] = array( 'name' => 'switch shortcut sets', diff --git a/profiles/wcm_base/modules/custom/ocio_permissions/ocio_permissions.info b/profiles/wcm_base/modules/custom/ocio_permissions/ocio_permissions.info index 963638de..1af4754b 100644 --- a/profiles/wcm_base/modules/custom/ocio_permissions/ocio_permissions.info +++ b/profiles/wcm_base/modules/custom/ocio_permissions/ocio_permissions.info @@ -28,16 +28,19 @@ dependencies[] = fitvids dependencies[] = flexslider dependencies[] = image dependencies[] = linkit +dependencies[] = mailsystem dependencies[] = manualcrop dependencies[] = media dependencies[] = media_internet dependencies[] = media_wysiwyg dependencies[] = menu +dependencies[] = mimemail dependencies[] = module_filter dependencies[] = navbar dependencies[] = node dependencies[] = oauth_common dependencies[] = ocio_admin_menu +dependencies[] = ocio_buckeye_alert dependencies[] = ocio_field_bases dependencies[] = ocio_landing_page dependencies[] = ocio_main_menu @@ -112,6 +115,7 @@ features[user_permission][] = administer advanced pane settings features[user_permission][] = administer blocks features[user_permission][] = administer book outlines features[user_permission][] = administer breakpoints +features[user_permission][] = administer buckeye alerts features[user_permission][] = administer consumers features[user_permission][] = administer content types features[user_permission][] = administer contexts @@ -129,6 +133,7 @@ features[user_permission][] = administer fitvids features[user_permission][] = administer flexslider features[user_permission][] = administer image styles features[user_permission][] = administer linkit +features[user_permission][] = administer mailsystem features[user_permission][] = administer manualcrop settings features[user_permission][] = administer media browser features[user_permission][] = administer menu @@ -296,6 +301,7 @@ features[user_permission][] = edit fieldable text features[user_permission][] = edit fieldable tile_pane features[user_permission][] = edit fieldable tile_pane_plus_text_area features[user_permission][] = edit fieldable video +features[user_permission][] = edit mimemail user settings features[user_permission][] = edit node machine name features[user_permission][] = edit own article content features[user_permission][] = edit own audio files @@ -392,6 +398,7 @@ features[user_permission][] = rebuild tablefield features[user_permission][] = rename features features[user_permission][] = revert revisions features[user_permission][] = search content +features[user_permission][] = send arbitrary files features[user_permission][] = switch shortcut sets features[user_permission][] = switch users features[user_permission][] = use advanced search diff --git a/profiles/wcm_base/modules/custom/ocio_url_aliases/ocio_url_aliases.features.user_permission.inc b/profiles/wcm_base/modules/custom/ocio_url_aliases/ocio_url_aliases.features.user_permission.inc new file mode 100644 index 00000000..0f54adc9 --- /dev/null +++ b/profiles/wcm_base/modules/custom/ocio_url_aliases/ocio_url_aliases.features.user_permission.inc @@ -0,0 +1,23 @@ +<?php +/** + * @file + * ocio_url_aliases.features.user_permission.inc + */ + +/** + * Implements hook_user_default_permissions(). + */ +function ocio_url_aliases_user_default_permissions() { + $permissions = array(); + + // Exported permission: 'administer redirects'. + $permissions['administer redirects'] = array( + 'name' => 'administer redirects', + 'roles' => array( + 'administrator' => 'administrator', + ), + 'module' => 'redirect', + ); + + return $permissions; +} diff --git a/profiles/wcm_base/modules/custom/ocio_url_aliases/ocio_url_aliases.info b/profiles/wcm_base/modules/custom/ocio_url_aliases/ocio_url_aliases.info index c551611a..af98ddc3 100644 --- a/profiles/wcm_base/modules/custom/ocio_url_aliases/ocio_url_aliases.info +++ b/profiles/wcm_base/modules/custom/ocio_url_aliases/ocio_url_aliases.info @@ -8,9 +8,11 @@ dependencies[] = ctools dependencies[] = features dependencies[] = path dependencies[] = pathauto +dependencies[] = redirect dependencies[] = strongarm features[ctools][] = strongarm:strongarm:1 features[features_api][] = api:2 +features[user_permission][] = administer redirects features[variable][] = pathauto_file_audio_pattern features[variable][] = pathauto_file_document_pattern features[variable][] = pathauto_file_image_pattern @@ -26,3 +28,14 @@ features[variable][] = pathauto_taxonomy_term_panopoly_categories_pattern features[variable][] = pathauto_taxonomy_term_pattern features[variable][] = pathauto_update_action features[variable][] = pathauto_user_pattern +features[variable][] = redirect_auto_redirect +features[variable][] = redirect_default_status_code +features[variable][] = redirect_global_admin_paths +features[variable][] = redirect_global_canonical +features[variable][] = redirect_global_clean +features[variable][] = redirect_global_deslash +features[variable][] = redirect_global_home +features[variable][] = redirect_page_cache +features[variable][] = redirect_passthrough_querystring +features[variable][] = redirect_purge_inactive +features[variable][] = redirect_warning diff --git a/profiles/wcm_base/modules/custom/ocio_url_aliases/ocio_url_aliases.make b/profiles/wcm_base/modules/custom/ocio_url_aliases/ocio_url_aliases.make new file mode 100644 index 00000000..5ffece1d --- /dev/null +++ b/profiles/wcm_base/modules/custom/ocio_url_aliases/ocio_url_aliases.make @@ -0,0 +1,11 @@ +; OCIO Usr Config Makefile + +api = 2 +core = 7.x + + +;modules + +projects[redirect][version] = 1.0-rc3 +projects[redirect][subdir] = contrib + diff --git a/profiles/wcm_base/modules/custom/ocio_url_aliases/ocio_url_aliases.strongarm.inc b/profiles/wcm_base/modules/custom/ocio_url_aliases/ocio_url_aliases.strongarm.inc index 281ce121..2842dae3 100644 --- a/profiles/wcm_base/modules/custom/ocio_url_aliases/ocio_url_aliases.strongarm.inc +++ b/profiles/wcm_base/modules/custom/ocio_url_aliases/ocio_url_aliases.strongarm.inc @@ -77,7 +77,7 @@ function ocio_url_aliases_strongarm() { $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */ $strongarm->api_version = 1; $strongarm->name = 'pathauto_punctuation_hyphen'; - $strongarm->value = 1; + $strongarm->value = '1'; $export['pathauto_punctuation_hyphen'] = $strongarm; $strongarm = new stdClass(); @@ -105,7 +105,7 @@ function ocio_url_aliases_strongarm() { $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */ $strongarm->api_version = 1; $strongarm->name = 'pathauto_update_action'; - $strongarm->value = '1'; + $strongarm->value = '2'; $export['pathauto_update_action'] = $strongarm; $strongarm = new stdClass(); @@ -115,5 +115,82 @@ function ocio_url_aliases_strongarm() { $strongarm->value = 'people/[user:name]'; $export['pathauto_user_pattern'] = $strongarm; + $strongarm = new stdClass(); + $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */ + $strongarm->api_version = 1; + $strongarm->name = 'redirect_auto_redirect'; + $strongarm->value = 1; + $export['redirect_auto_redirect'] = $strongarm; + + $strongarm = new stdClass(); + $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */ + $strongarm->api_version = 1; + $strongarm->name = 'redirect_default_status_code'; + $strongarm->value = '301'; + $export['redirect_default_status_code'] = $strongarm; + + $strongarm = new stdClass(); + $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */ + $strongarm->api_version = 1; + $strongarm->name = 'redirect_global_admin_paths'; + $strongarm->value = 0; + $export['redirect_global_admin_paths'] = $strongarm; + + $strongarm = new stdClass(); + $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */ + $strongarm->api_version = 1; + $strongarm->name = 'redirect_global_canonical'; + $strongarm->value = 1; + $export['redirect_global_canonical'] = $strongarm; + + $strongarm = new stdClass(); + $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */ + $strongarm->api_version = 1; + $strongarm->name = 'redirect_global_clean'; + $strongarm->value = 1; + $export['redirect_global_clean'] = $strongarm; + + $strongarm = new stdClass(); + $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */ + $strongarm->api_version = 1; + $strongarm->name = 'redirect_global_deslash'; + $strongarm->value = 0; + $export['redirect_global_deslash'] = $strongarm; + + $strongarm = new stdClass(); + $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */ + $strongarm->api_version = 1; + $strongarm->name = 'redirect_global_home'; + $strongarm->value = 1; + $export['redirect_global_home'] = $strongarm; + + $strongarm = new stdClass(); + $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */ + $strongarm->api_version = 1; + $strongarm->name = 'redirect_page_cache'; + $strongarm->value = 0; + $export['redirect_page_cache'] = $strongarm; + + $strongarm = new stdClass(); + $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */ + $strongarm->api_version = 1; + $strongarm->name = 'redirect_passthrough_querystring'; + $strongarm->value = 1; + $export['redirect_passthrough_querystring'] = $strongarm; + + $strongarm = new stdClass(); + $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */ + $strongarm->api_version = 1; + $strongarm->name = 'redirect_purge_inactive'; + $strongarm->value = '0'; + $export['redirect_purge_inactive'] = $strongarm; + + $strongarm = new stdClass(); + $strongarm->disabled = FALSE; /* Edit this to true to make a default strongarm disabled initially */ + $strongarm->api_version = 1; + $strongarm->name = 'redirect_warning'; + $strongarm->value = FALSE; + $export['redirect_warning'] = $strongarm; + return $export; } diff --git a/profiles/wcm_base/themes/ocio_omega_1/layouts/ocio-full/ocio-full-layout.tpl.php b/profiles/wcm_base/themes/ocio_omega_1/layouts/ocio-full/ocio-full-layout.tpl.php index c417e300..0c9a7dc8 100755 --- a/profiles/wcm_base/themes/ocio_omega_1/layouts/ocio-full/ocio-full-layout.tpl.php +++ b/profiles/wcm_base/themes/ocio_omega_1/layouts/ocio-full/ocio-full-layout.tpl.php @@ -38,7 +38,7 @@ <?php print render($page['workbench']); ?> <?php if (!$is_front && !empty($title)): ?> <?php print render($title_prefix); ?> - <h1 class="title" id="page-title"><?php print $title; ?></h1> + <h1 <?php print $title_attributes; ?>><?php print $title; ?></h1> <?php print render($title_suffix); ?> <?php endif; ?> diff --git a/profiles/wcm_base/themes/ocio_omega_2/css/layouts/ocio-2/ocio-2.layout.no-query.css b/profiles/wcm_base/themes/ocio_omega_2/css/layouts/ocio-2/ocio-2.layout.no-query.css index 7371ad9b..6d60ac25 100644 --- a/profiles/wcm_base/themes/ocio_omega_2/css/layouts/ocio-2/ocio-2.layout.no-query.css +++ b/profiles/wcm_base/themes/ocio_omega_2/css/layouts/ocio-2/ocio-2.layout.no-query.css @@ -1,12 +1,14 @@ /******************************************************************************* - * ocio-x.layout.scss + * ocio-default.layout.scss * - * Styles for the OCIO 2 layout. + * Styles for the OCIO Default layout. ******************************************************************************/ +/*** THIS Theme uses its own grid variables ***/ .l-constrained, .l-region--highlighted, .l-region--footer { - width: 95%; + padding: 0 4%; margin: 0 auto; *zoom: 1; + padding: 0 10%; } .l-constrained:after, .l-region--highlighted:after, .l-region--footer:after { content: ""; @@ -14,6 +16,10 @@ clear: both; } +img, media { + max-width: 100%; +} + /* Header */ .l-region--header { padding: 20px 0; @@ -37,8 +43,8 @@ } /* Sidebars */ -.l-region--sidebar-first, -.l-region--sidebar-second { +.l-region--sidebar-1, +.l-region--sidebar-2 { padding: 20px 1.5em; } @@ -47,29 +53,25 @@ padding: 20px 0; } -.l-constrained, .l-region--highlighted, .l-region--footer { - width: 90%; -} - /* Header */ .l-branding { - width: 23.40426%; + width: 23.72881%; float: left; margin-right: -100%; - margin-left: 0%; + margin-left: 0; clear: none; } .l-region--navigation { - width: 48.93617%; + width: 49.15254%; float: left; margin-right: -100%; - margin-left: 25.53191%; + margin-left: 25.42373%; clear: none; } .l-region--header { - width: 23.40426%; + width: 23.72881%; float: right; margin-left: 0; margin-right: 0; @@ -79,17 +81,17 @@ /* Sidebars */ .has-two-sidebars .l-content, .has-one-sidebar .l-content { - width: 65.95745%; + width: 66.10169%; float: left; margin-right: -100%; - margin-left: 0%; + margin-left: 0; clear: none; } -.has-two-sidebars .l-region--sidebar-first, -.has-two-sidebars .l-region--sidebar-second, -.has-one-sidebar .l-region--sidebar-first, -.has-one-sidebar .l-region--sidebar-second { - width: 31.91489%; +.has-two-sidebars .l-region--sidebar-1, +.has-two-sidebars .l-region--sidebar-2, +.has-one-sidebar .l-region--sidebar-1, +.has-one-sidebar .l-region--sidebar-2 { + width: 32.20339%; float: right; margin-left: 0; margin-right: 0; @@ -97,20 +99,37 @@ clear: right; } -.l-constrained, .l-region--highlighted, .l-region--footer { - width: 80%; +/* Footer */ +.l-region--footer-1 { + width: 57.62712%; + float: left; + margin-right: -100%; + margin-left: 0; + clear: none; +} + +.l-region--footer-2 { + width: 40.67797%; + float: right; + margin-left: 0; + margin-right: 0; + clear: none; +} + +.l-region--footer-3 { + clear: both; } /* Sidebars */ .has-one-sidebar .l-content { - width: 65.95745%; + width: 66.10169%; float: left; margin-right: -100%; - margin-left: 0%; + margin-left: 0; clear: none; } -.has-one-sidebar .l-region--sidebar-first { - width: 31.91489%; +.has-one-sidebar .l-region--sidebar-1 { + width: 32.20339%; float: right; margin-left: 0; margin-right: 0; @@ -119,23 +138,23 @@ } .has-two-sidebars .l-content { - width: 48.93617%; + width: 49.15254%; float: left; margin-right: -100%; - margin-left: 0%; + margin-left: 0; clear: none; } -.has-two-sidebars .l-region--sidebar-first, -.has-two-sidebars .l-region--sidebar-second { - width: 23.40426%; +.has-two-sidebars .l-region--sidebar-1, +.has-two-sidebars .l-region--sidebar-2 { + width: 23.72881%; float: left; margin-right: -100%; - margin-left: 51.06383%; + margin-left: 50.84746%; clear: none; clear: none; } -.has-two-sidebars .l-region--sidebar-second { - width: 23.40426%; +.has-two-sidebars .l-region--sidebar-2 { + width: 23.72881%; float: right; margin-left: 0; margin-right: 0; diff --git a/profiles/wcm_base/themes/ocio_omega_2/css/ocio-2.no-query.css b/profiles/wcm_base/themes/ocio_omega_2/css/ocio-2.no-query.css index fd89e2ad..80c1b505 100644 --- a/profiles/wcm_base/themes/ocio_omega_2/css/ocio-2.no-query.css +++ b/profiles/wcm_base/themes/ocio_omega_2/css/ocio-2.no-query.css @@ -52,7 +52,7 @@ body .ui-accordion .ui-accordion-content { } .l-page .l-main .pane-title, .l-page .l-main h1.page-title, -.l-page .l-main h1#page-title { +.l-page .l-main h1 { display: block; margin: 0; background-color: #ededed; @@ -70,7 +70,7 @@ body .ui-accordion .ui-accordion-content { padding: 1.3rem 1.7rem 0.8rem; } .l-page .l-main h1.page-title, -.l-page .l-main h1#page-title { +.l-page .l-main h1 { font-size: 36px; font-size: 3.6rem; } diff --git a/profiles/wcm_base/themes/ocio_omega_2/css/ocio-2.styles.css b/profiles/wcm_base/themes/ocio_omega_2/css/ocio-2.styles.css index c09b8b94..e4774bc0 100644 --- a/profiles/wcm_base/themes/ocio_omega_2/css/ocio-2.styles.css +++ b/profiles/wcm_base/themes/ocio_omega_2/css/ocio-2.styles.css @@ -63,7 +63,7 @@ body .ui-accordion .ui-accordion-content { } .l-page .l-main .pane-title, .l-page .l-main h1.page-title, -.l-page .l-main h1#page-title { +.l-page .l-main h1 { display: block; margin: 0; background-color: #ededed; @@ -81,7 +81,7 @@ body .ui-accordion .ui-accordion-content { padding: 1.3rem 1.7rem 0.8rem; } .l-page .l-main h1.page-title, -.l-page .l-main h1#page-title { +.l-page .l-main h1 { font-size: 36px; font-size: 3.6rem; } diff --git a/profiles/wcm_base/themes/ocio_omega_2/layouts/ocio-2/ocio-2-layout.tpl.php b/profiles/wcm_base/themes/ocio_omega_2/layouts/ocio-2/ocio-2-layout.tpl.php index a26050fb..0c98b0f1 100644 --- a/profiles/wcm_base/themes/ocio_omega_2/layouts/ocio-2/ocio-2-layout.tpl.php +++ b/profiles/wcm_base/themes/ocio_omega_2/layouts/ocio-2/ocio-2-layout.tpl.php @@ -34,7 +34,7 @@ <div class="l-content" role="main"> <?php if (!$is_front && !empty($title)): ?> <?php print render($title_prefix); ?> - <h1 class="title" id="page-title"><?php print $title; ?></h1> + <h1 <?php print $title_attributes; ?>><?php print $title; ?></h1> <?php print render($title_suffix); ?> <?php endif; ?> diff --git a/profiles/wcm_base/themes/ocio_omega_2/sass/components/_main-content.scss b/profiles/wcm_base/themes/ocio_omega_2/sass/components/_main-content.scss index 2728fa79..946f2523 100644 --- a/profiles/wcm_base/themes/ocio_omega_2/sass/components/_main-content.scss +++ b/profiles/wcm_base/themes/ocio_omega_2/sass/components/_main-content.scss @@ -23,12 +23,12 @@ .pane-title, h1.page-title, - h1#page-title { + h1 { @include color-box($red); } h1.page-title, - h1#page-title { + h1 { @include font-size(3.6); } diff --git a/profiles/wcm_base/themes/ocio_omega_2/sass/layouts/ocio-2/ocio-2.layout.no-query.scss b/profiles/wcm_base/themes/ocio_omega_2/sass/layouts/ocio-2/ocio-2.layout.no-query.scss index ccc66df8..be46c97a 100644 --- a/profiles/wcm_base/themes/ocio_omega_2/sass/layouts/ocio-2/ocio-2.layout.no-query.scss +++ b/profiles/wcm_base/themes/ocio_omega_2/sass/layouts/ocio-2/ocio-2.layout.no-query.scss @@ -2,4 +2,4 @@ $breakpoint-no-queries: true; $breakpoint-no-query-fallbacks: true; // Re import everything but without media queries. -@import "ocio-default.layout"; +@import "ocio-2.layout"; diff --git a/profiles/wcm_base/themes/ocio_omega_3/layouts/ocio-3/ocio-3-layout.tpl.php b/profiles/wcm_base/themes/ocio_omega_3/layouts/ocio-3/ocio-3-layout.tpl.php index 2e483363..e63d8307 100644 --- a/profiles/wcm_base/themes/ocio_omega_3/layouts/ocio-3/ocio-3-layout.tpl.php +++ b/profiles/wcm_base/themes/ocio_omega_3/layouts/ocio-3/ocio-3-layout.tpl.php @@ -32,7 +32,7 @@ <div class="l-content" role="main"> <?php if (!$is_front && !empty($title)): ?> <?php print render($title_prefix); ?> - <h1 class="title" id="page-title"><?php print $title; ?></h1> + <h1 <?php print $title_attributes; ?>><?php print $title; ?></h1> <?php print render($title_suffix); ?> <?php endif; ?> diff --git a/profiles/wcm_base/themes/ocio_omega_base/css/ocio-omega-base.no-query.css b/profiles/wcm_base/themes/ocio_omega_base/css/ocio-omega-base.no-query.css index b208ae34..a7afacba 100644 --- a/profiles/wcm_base/themes/ocio_omega_base/css/ocio-omega-base.no-query.css +++ b/profiles/wcm_base/themes/ocio_omega_base/css/ocio-omega-base.no-query.css @@ -1426,27 +1426,31 @@ body .ui-accordion .ui-accordion-content { } .flexslider .flex-meta { position: absolute; - bottom: 0; width: 100%; - background-color: rgba(0, 0, 0, 0.6); - padding: 1.3em 1.1em 1.1em; -} -.flexslider .flex-meta .flex-title { - font-size: 40px; - font-size: 4rem; - line-height: 1em; + padding: 0.4em 0; + text-align: center; + z-index: 99; + font-size: 22px; + font-size: 2.2rem; + line-height: 120%; + background-color: rgba(0, 0, 0, 0.5); color: #fff; - font-weight: 700; - text-transform: uppercase; - display: block; + bottom: 0; + font-size: 26px; + font-size: 2.6rem; + font-size: 30px; + font-size: 3rem; } +.flexslider .flex-meta .flex-title, .flexslider .flex-meta .flex-summary { - font-size: 20px; - font-size: 2rem; - color: #ededed; - font-weight: 400; display: block; - margin: 0.3em 0 -0.3em; +} +.flexslider .flex-meta .flex-title { + font-weight: bold; +} +.flexslider .flex-meta .flex-summary { + font-size: 0.8em; + line-height: 1.1em; } .flexslider .flex-direction-nav a { color: rgba(0, 0, 0, 0.8); @@ -1468,6 +1472,47 @@ body .ui-accordion .ui-accordion-content { filter: alpha(opacity="80"); } +/* +#block-views-featured-slideshow-block { + &, + &.white { + color: white; + } + + &.dk-gray { + color: $dk-gray; + } + + &.black { + color: black; + } + + &.center-top .flex-meta { + top: 1em; + } + + &.center-middle .flex-meta { + bottom: 45%; + } + + & .flex-meta, + &.center-bottom .flex-meta { + bottom: 1.2em; + + + + @include breakpoint($wide, true) { + padding-left: 6em; + padding-right: 6em; + } + + @include breakpoint($x-wide, true) { + padding-left: 10em; + padding-right: 10em; + } + } +} +*/ .block--mm-widgets .item, .pane-mm-widgets-live-pane .item { margin: 1.5em 0; @@ -2166,12 +2211,10 @@ div.workbench-info-block #edit-submit { .node-type-ocio-landing-page .block--ds-extras-ds-hero .field--name-field-banner-image-text.center-middle, .node-type-ocio-landing-page .l-region--hero-wrapper .field--name-field-banner-image-text.center-middle { bottom: 45%; - top: 1em; } .node-type-ocio-landing-page .block--ds-extras-ds-hero .field--name-field-banner-image-text.center-bottom, .node-type-ocio-landing-page .l-region--hero-wrapper .field--name-field-banner-image-text.center-bottom { bottom: 1.2em; - top: 1em; } .l-footer-wrapper { diff --git a/profiles/wcm_base/themes/ocio_omega_base/css/ocio-omega-base.styles.css b/profiles/wcm_base/themes/ocio_omega_base/css/ocio-omega-base.styles.css index 669f93cf..7a33d5ae 100644 --- a/profiles/wcm_base/themes/ocio_omega_base/css/ocio-omega-base.styles.css +++ b/profiles/wcm_base/themes/ocio_omega_base/css/ocio-omega-base.styles.css @@ -1426,11 +1426,6 @@ body .ui-accordion .ui-accordion-content { margin-bottom: 3em; } -@media (max-width: 47.5em) { - .flexslider { - display: none; - } -} .flexslider { background: none repeat scroll 0 0 #fff; border: 0 none; @@ -1440,27 +1435,39 @@ body .ui-accordion .ui-accordion-content { } .flexslider .flex-meta { position: absolute; - bottom: 0; width: 100%; - background-color: rgba(0, 0, 0, 0.6); - padding: 1.3em 1.1em 1.1em; -} -.flexslider .flex-meta .flex-title { - font-size: 40px; - font-size: 4rem; - line-height: 1em; + padding: 0.4em 0; + text-align: center; + z-index: 99; + font-size: 22px; + font-size: 2.2rem; + line-height: 120%; + background-color: rgba(0, 0, 0, 0.5); color: #fff; - font-weight: 700; - text-transform: uppercase; - display: block; + bottom: 0; } +.flexslider .flex-meta .flex-title, .flexslider .flex-meta .flex-summary { - font-size: 20px; - font-size: 2rem; - color: #ededed; - font-weight: 400; display: block; - margin: 0.3em 0 -0.3em; +} +.flexslider .flex-meta .flex-title { + font-weight: bold; +} +.flexslider .flex-meta .flex-summary { + font-size: 0.8em; + line-height: 1.1em; +} +@media (min-width: 25.875em) { + .flexslider .flex-meta { + font-size: 26px; + font-size: 2.6rem; + } +} +@media (min-width: 47.5em) { + .flexslider .flex-meta { + font-size: 30px; + font-size: 3rem; + } } .flexslider .flex-direction-nav a { color: rgba(0, 0, 0, 0.8); @@ -1482,6 +1489,47 @@ body .ui-accordion .ui-accordion-content { filter: alpha(opacity="80"); } +/* +#block-views-featured-slideshow-block { + &, + &.white { + color: white; + } + + &.dk-gray { + color: $dk-gray; + } + + &.black { + color: black; + } + + &.center-top .flex-meta { + top: 1em; + } + + &.center-middle .flex-meta { + bottom: 45%; + } + + & .flex-meta, + &.center-bottom .flex-meta { + bottom: 1.2em; + + + + @include breakpoint($wide, true) { + padding-left: 6em; + padding-right: 6em; + } + + @include breakpoint($x-wide, true) { + padding-left: 10em; + padding-right: 10em; + } + } +} +*/ .block--mm-widgets .item, .pane-mm-widgets-live-pane .item { margin: 1.5em 0; @@ -2177,22 +2225,10 @@ div.workbench-info-block #edit-submit { .node-type-ocio-landing-page .l-region--hero-wrapper .field--name-field-banner-image-text.center-middle { bottom: 45%; } -@media (max-width: 47.5em) { - .node-type-ocio-landing-page .block--ds-extras-ds-hero .field--name-field-banner-image-text.center-middle, - .node-type-ocio-landing-page .l-region--hero-wrapper .field--name-field-banner-image-text.center-middle { - top: 1em; - } -} .node-type-ocio-landing-page .block--ds-extras-ds-hero .field--name-field-banner-image-text.center-bottom, .node-type-ocio-landing-page .l-region--hero-wrapper .field--name-field-banner-image-text.center-bottom { bottom: 1.2em; } -@media (max-width: 47.5em) { - .node-type-ocio-landing-page .block--ds-extras-ds-hero .field--name-field-banner-image-text.center-bottom, - .node-type-ocio-landing-page .l-region--hero-wrapper .field--name-field-banner-image-text.center-bottom { - top: 1em; - } -} @media (min-width: 47.5em) { .node-type-ocio-landing-page .block--ds-extras-ds-hero .field--name-field-banner-image-text, .node-type-ocio-landing-page .l-region--hero-wrapper .field--name-field-banner-image-text { diff --git a/profiles/wcm_base/themes/ocio_omega_base/sass/components/_featured-slideshow.scss b/profiles/wcm_base/themes/ocio_omega_base/sass/components/_featured-slideshow.scss index 0e4bd4f3..8b6aee68 100644 --- a/profiles/wcm_base/themes/ocio_omega_base/sass/components/_featured-slideshow.scss +++ b/profiles/wcm_base/themes/ocio_omega_base/sass/components/_featured-slideshow.scss @@ -1,10 +1,3 @@ -@include breakpoint($small){ - .flexslider { - display:none; - } -} - - .flexslider { background: none repeat scroll 0 0 #fff; border: 0 none; @@ -14,26 +7,33 @@ .flex-meta { position: absolute; - bottom: 0; width: 100%; - background-color: rgba(0, 0, 0, 0.6); - padding: 1.3em 1.1em 1.1em; + padding: 0.4em 0; + text-align: center; + z-index: 99; + @include font-size(2.2); + line-height: 120%; + background-color: rgba(0, 0, 0, 0.5); + color: #fff; + bottom: 0; - .flex-title { - @include font-size(4); - line-height: 1em; - color: $white; - font-weight: 700; - text-transform: uppercase; + .flex-title, + .flex-summary { display: block; } + .flex-title { + font-weight: bold; + } .flex-summary { - @include font-size(2); - color: $lt-gray; - font-weight: 400; - display: block; - margin: 0.3em 0 -0.3em; + font-size: 0.8em; + line-height: 1.1em; + } + @include breakpoint($big-phone, true) { + @include font-size(2.6); + } + @include breakpoint($tab, true) { + @include font-size(3); } } @@ -62,3 +62,44 @@ } } } +/* +#block-views-featured-slideshow-block { + &, + &.white { + color: white; + } + + &.dk-gray { + color: $dk-gray; + } + + &.black { + color: black; + } + + &.center-top .flex-meta { + top: 1em; + } + + &.center-middle .flex-meta { + bottom: 45%; + } + + & .flex-meta, + &.center-bottom .flex-meta { + bottom: 1.2em; + + + + @include breakpoint($wide, true) { + padding-left: 6em; + padding-right: 6em; + } + + @include breakpoint($x-wide, true) { + padding-left: 10em; + padding-right: 10em; + } + } +} +*/ diff --git a/profiles/wcm_base/themes/ocio_omega_base/sass/components/nodes/_landing-page.scss b/profiles/wcm_base/themes/ocio_omega_base/sass/components/nodes/_landing-page.scss index c5c1711f..20e8ad6e 100644 --- a/profiles/wcm_base/themes/ocio_omega_base/sass/components/nodes/_landing-page.scss +++ b/profiles/wcm_base/themes/ocio_omega_base/sass/components/nodes/_landing-page.scss @@ -54,18 +54,10 @@ &.center-middle { bottom: 45%; - - @include breakpoint($small, true) { - top: 1em; - } } &.center-bottom { bottom: 1.2em; - - @include breakpoint($small, true) { - top: 1em; - } } //vary side padding by breakpoint diff --git a/profiles/wcm_base/themes/ocio_omega_base/template.php b/profiles/wcm_base/themes/ocio_omega_base/template.php index f3c4fe12..c735df93 100644 --- a/profiles/wcm_base/themes/ocio_omega_base/template.php +++ b/profiles/wcm_base/themes/ocio_omega_base/template.php @@ -156,8 +156,3 @@ function ocio_omega_base_preprocess_panels_pane(&$vars) { } } } - -function ocio_omega_base_process_panels_pane(&$vars) { - $pane = $vars['pane']; - -} diff --git a/profiles/wcm_base/wcm_base.info b/profiles/wcm_base/wcm_base.info index b449fe58..2e47e19a 100644 --- a/profiles/wcm_base/wcm_base.info +++ b/profiles/wcm_base/wcm_base.info @@ -52,6 +52,7 @@ dependencies[] = ds_extras dependencies[] = ds_format dependencies[] = ds_forms dependencies[] = ds_ui +dependencies[] = file_entity_swf dependencies[] = flexslider dependencies[] = flexslider_views dependencies[] = mailsystem diff --git a/profiles/wcm_base/wcm_base.make b/profiles/wcm_base/wcm_base.make index 2184cd72..ce8ec3e0 100644 --- a/profiles/wcm_base/wcm_base.make +++ b/profiles/wcm_base/wcm_base.make @@ -47,6 +47,9 @@ projects[features_extra][subdir] = contrib projects[fieldable_panels_panes][version] = 1.7 projects[fieldable_panels_panes][subdir] = contrib +projects[file_entity_swf][version] = 1.0-rc2 +projects[file_entity_swf][subdir] = contrib + projects[google_analytics][version] = 2.1 projects[google_analytics][subdir] = contrib -- GitLab