# HG changeset patch # User danieleb # Date 1379672301 -3600 # Node ID a75ead64973025dc646dbb8a01d5fbd8d58dc3cd # Parent d72257b2ddc28212ee75fbe5ea040e146138bdd3 added biblio, admin_menu and reference modules diff -r d72257b2ddc2 -r a75ead649730 .gitignore --- a/.gitignore Fri Sep 20 10:32:27 2013 +0100 +++ b/.gitignore Fri Sep 20 11:18:21 2013 +0100 @@ -4,3 +4,7 @@ # Ignore paths that contain user-generated content. sites/*/files sites/*/private + +# Ignore system files +.DS_Store +.*~ \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/CHANGELOG.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/CHANGELOG.txt Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,366 @@ + +Admin Menu 7.x-3.x, xxxx-xx-xx +------------------------------ +#1177202 by das-peter, dereine, sun: Fixed copying and re-injection of child + router items breaks badly. Change them by reference instead. + Requires latest Views 3.x code. +#1212064 by sun: Updated admin_views default views for VBO 3.x. +#1196590 by sun: Fixed errors and notices for admin_views with Views 3. +#1144768 by idlewilder, sun: Fixed devel modules to skip are not displayed. +#1079374 by WillHall: Fixed JS Error: unrecognized expression: [href=/]. +#1114132 by joelstein, sun: Added Field UI to list of developer modules. +#1008380 by bdragon, sun: Updated admin_views for D7. +#1146644 by sun: Fixed PHP 5.3 compability in tests. +#442560 by sun: Fixed 'defer' script attribute breaks Drupal.behaviors in FF3.6. +#1022902 by matglas86, sun: Updated for changed core Toolbar styles. + + +Admin Menu 7.x-3.0-RC1, 2010-01-07 +---------------------------------- +#990774 by sun: Updated for $closure renamed to $page_bottom. +#991906 by johnv, sun: Added configure to .info file. +#947198 by sun: Added hint about disabling Toolbar. +by sun: Updated administrative settings form for D7 UX guidelines. +by sun: Disabled "Rebuild system links" button on settings form. +#420816 by sun, smk-ka: Improved on-demand loading of dynamic paths. +#420816 by tim.plunkett: Fixed dynamic Field UI paths for vocabularies. +#871774 by swentel: Fixed developer modules toggle still uses referer_uri(). +#671760 by sun: Updated for new preprocess defaults. +#731462 by sun: Updated for system_rebuild_theme_data(). +by sun: Re-added a "Rebuild system links" button to settings form. +#420816 by tim.plunkett: Updated taxonomy path map for machine names. +#857688 by sun: Updated for reverted system_settings_form(). +#420816 by smk-ka, sun: Added merging of menu trees containing dynamic paths. +by sun: Fixed tests and minor admin_menu_toolbar styling issues. +by sun: Fixed various styling issues for admin_menu and admin_menu_toolbar. +by sun: Updated for Schema API, DBTNG, coding standards. +by sun: Updated for new admin/modules path. +#701424 by hutch: Updated for new admin/people/people path. +by sun: Removed orphan menu rewrite function. +#667858 by sun: Don't remove the current user from the switch user list. +#631550 by sun: Updated for fixed MENU_VISIBLE_IN_BREADCRUMB behavior. +#658344 by dereine, sun: Updated for removed drupal_session_count(). +by sun: Added separate permission to flush cashes. +by sun: Updated for changed Devel settings form. +by sun: Updated for new {system}.info module data. +#614730 by azriprajwala, sun: Updated for hook_theme() key changes. +by sun: Updated for all theme functions should take a single argument. +by sun: Reverted removal of registry cache flushing option. +#578520 by sun: Fixed destination query parameter is processed wrongly. +#578520 by sun: Updated for $query in url() should always be an array. +by Dave Reid: Updated for PHP 5 date constants. +by sun: Updated for new database API. +by smk-ka: Removed remnants of the registry. Fixed flush admin menu cache + command. +#567618 by smk-ka: Revised test cases. Abstracted out base web test class. +by sun: Updated for removed registry, new admin paths. +#326539 by sun: Updated for class attribute array. +#519782 by sun: Updated for hook_footer() replaced by hook_page_alter(). +#525638 by Razorraser: Updated for admin/build renamed to admin/structure. +by Dave Reid: Updated for hook_permission(). +#482314 by Dave Reid: Updated for node_type_get_types(). +#437506 by yched, Dave Reid: Updated for menu_router_build(). +#376816 by sun: Updated for compatibility for other JavaScript libraries. +#337820 by Dave Reid: Updated for new user/logout path. +#340546 by Dave Reid: Updated for drupal_add_js(). +#340531 by Dave Reid: Updated for module_list(). +#266358 by sun: Updated for drupal_add_css(). +#320526 by yettyn, sun: Updated to UNSTABLE-2 (DBTNG queries, permissions, etc). +by sun: Changed admin_menu_wipe() to admin_menu_flush_caches(). +by sun: Updated content-type edit menu item locations. +by sun: Fixed sess_count() changed to drupal_session_count(). + + +Admin Menu 6.x-3.x, xxxx-xx-xx +------------------------------ +#588936 by fenstrat: Fixed Toolbar shortcuts not visible. +#860390 by Kevin Rogers: Fixed .info file parsing error on uncertain platform. +#551484 by sun: Fixed stale hook_admin_menu_output_alter() docs. + + +Admin Menu 6.x-3.0-ALPHA4, 2010-03-11 +------------------------------------- +#730156 by sun: Fixed Administration views. +by sun: Fixed missing .element-hidden style in D6 for permissions tweak. +#645526 by TravisCarden: Fixed stale local tasks markup after moving them. +#366442 by sun: Added tweak to collapse modules on permissions page. +#655926 by donquixote, sun: Improved performance of delayed mouseout. +#557062 by sun: Fixed admin_menu_toolbar JS/CSS loaded before admin_menu's. +#599462 by sun, koyama: Added background-color to avoid unintentional override. +#601918 by BWPanda: Fixed admin_menu.css overrides admin_menu_toolbar.css. +#586228 by Island Usurper: Fixed for PHP 5.3. +#554124 by Dave Reid: Added missing toolbar.png. +#557062 by Dave Reid: Fixed undefined Drupal.admin error when including + admin_menu_toolbar.js before admin_menu.js. +#511744 by smk-ka, sun: Fixed /admin page links are broken. +by smk-ka: Added missing variables to hook_uninstall(). +#571038 by smk-ka: Removed call to admin_menu_wipe() and cleaned install file. +#552190 by Bartezz: Fixed missing t() for user logout link. + + +Admin Menu 6.x-3.0-ALPHA3, 2009-08-16 +------------------------------------- +#502500 by sun: Added "Create content" menu. +#538714 by sun: Fixed wrong re-parenting in Drupal's menu system. +#550132 by sun: Fixed (temporarily) admin_views menu items. +by sun: Added Administration views sub-module, converting all administrative + listing pages in Drupal core into real, ajaxified, and alterable views. +#547206 by sun: Fixed menu link descriptions lead to mouseover clashes. +#540954 by Rob Loach: Added String Overrides to list of developer modules. +#540762 by Deslack: Added Malay translation. + + +Admin Menu 6.x-3.0-ALPHA2, 2009-08-02 +------------------------------------- +#527908 by sun: Changed theme_admin_menu_links() to use $element['#children']. +#527908 by markus_petrux, sun: Changed admin menu into a renderable array. +#420812 by sun, smk-ka: Added support for hook_js(). +by sun: Fixed destination query string of current page not applied to links. +by sun: Changed Drupal.admin.attachBehaviors() to accept local JS settings. +#276751 by sun: Revamped rendering of menu additions/widgets. +#500866 by sun: Updated for removed t() from getInfo() in tests. +#402058 by sun: Added Administration menu toolbar module. +by markus_petrux, sun: Added API documentation. +#461264 by sun: Added site/domain as CSS class. +#451270 by smk-ka, sun: Changed visual indication for uid1. +by sun: Minor code clean-up. +#490670 by sun: Fixed missing menu after installation/upgrade. +#515718 by joelstein, sun: Added rules_admin module to developer modules list. +#352065 by sun: Added setting to select developer modules to keep enabled. +#511854 by psynaptic: Fixed logout link. +#424960 by markus_petrux, sun: Fixed gzip compression for cached output. +by sun: Fixed opacity of links in sub-menus. +#479922 by sun: Fixed fieldsets not collapsed on admin/build/modules/list*. +#495148 by sun: Fixed MENU_NORMAL_ITEMs do not appear in administration menu. +by sun: Fixed tests for new content-type locations. +#345984 by markus_petrux, sun: Fixed old menu links not removed on upgrade. +#276751 by sun: Major rewrite. Fixed menu items cannot be moved, altered, or + added as well as various performance issues. +by sun: Added variable to allow to disable caching (rewrite). + + +Admin Menu 6.x-3.0-ALPHA1, 2009-06-10 +------------------------------------- +#236657 by sun: Updated for corrected arguments of system_clear_cache_submit(). +#483870 by sun: Fixed compatibility with new Admin module. +#483152 by sun: Fixed admin_menu caches not flushed when clean URLs are toggled. +#479922 by danep: Fixed fieldsets not collapsed on admin/build/modules/list. +#469716 by sun: Fixed wrong AJAX callback URL under various conditions. +#471504 by wulff: Updated Danish translation. +by sun: Fixed admin_menu_suppress() does not suppress margin-top. +#451270 by sun: Added visual indication when working as uid 1. +by Dave Reid: Updated for getInfo() in tests. +#420828 by sun: Added dynamic replacements for cached administration menu. +#420840 by sun: Fixed Drupal.behaviors.adminMenu must be only executed once. +#345984 by markus_petrux, sun: Added client-side caching of administration menu. + Attention: A new era of Drupal user experience starts here. This is the very + first issue of a series of improvements targeting plain awesomeness. +#349169 by sun: Fixed Devel switch user links contain multiple path prefixes. +#345984 by sun: Code clean-up in preparation for client-side caching. +#415196 by psynaptic: Updated for CSS coding standards. +#406672 by mr.j, sun: Fixed "Move local tasks" option leaves stale UL. +by sun: Major code clean-up and sync across 3.x branches. +#349505 by smk-ka, sun: Performance: Added caching of entire menu output. +#315342 by wulff: Added "My account" link (by splitting the "Log out" item). +#384100 by kepol, sun: Fixed content-type items displayed in wrong place. +#373339 by sun: Fixed double-escaped 'Edit ' link titles. +#373372 by sun: Turned procedural JavaScript into admin menu behaviors. +by sun: Fixed admin menu tests (and updated to 6.x for SimpleTest 2.x). +#359158 by nitrospectide, sun: Fixed Devel Themer breaks admin menu. +#365335 by sun: Fixed not all variables removed after uninstall. + + +Admin Menu 6.x-1.3, 2009-01-24 +------------------------------ +#362454 by sun: Fixed Drupal.settings.admin_menu is undefined JS error in some + browsers. + + +Admin Menu 6.x-1.2, 2009-01-20 +------------------------------ +#358697 by sun: Added docs about admin_menu_suppress() to README.txt. +#342684 by darumaki, sun: Added notice about Opera configuration to README.txt. +#350932 by sun: Fixed "Run updates" link repeated per language/site. +#342298 by gustz: Updated Spanish translation. +#346106 by sun: Fixed XHTML-Strict validation for admin menu icon. +#287448 by sun: Fixed unnecessary menu rebuild for users without permission to + use admin menu. +#342002 by AltaVida: Fixed improper test for node/add paths. +#272920 by keith.smith: Changed all text strings throughout the module. +#322731 by sun: Fixed improper use of t() in module install file. +#282030 by sun: Fixed "Run updates" item visible for unprivileged users. +#322877 by sun: Added tweak to move page tabs into administration menu. +#287468 by sun: Fixed module paths directly below "admin" get the wrong parent. +#310423 by sun: Added optional position: fixed configuration setting. +#292657 by smk-ka: Improved rendering performance. +#234149 by yhager, sun: Fixed RTL support for IE. +#323726 by danez1972: Added Spanish translation. +#325057 by sun: Updated README.txt. +#234149 by yhager, levavie, sun: Added RTL support. +#325057 by sun: Added links to flush specific caches. +#324334 by AltaVida: Fixed usernames with spaces not in Devel user switch links. +#319382 by betz: Added Dutch translation. + + +Admin Menu 6.x-1.1, 2008-09-12 +------------------------------ +#295476 by pwolanin, use for icon path to fix front-page path-change + bug and pathauto conflict, add wipe button to admin form. +#301370 by sun: Disabled module fieldset collapsing behavior by default. +#288672 by sun: Fixed JS hover behavior not working in IE. +#290803 by sun: Fixed missing devel_themer in devel modules; added some others. +#286636 by sun: Fixed menus do not drop down in IE6. +#249537 by pwolanin, sun: Added admin_menu_suppress() to allow other modules to + disable the display of admin_menu on certain pages (f.e. popups). +#268211 by sun: Fixed invalid issue queue links for custom modules and + sub-modules of projects. +#261461 by sun: Added FAQ entry for displaying other menus like admin_menu. +#264067 by sun: Added FAQ entry for huge amount of anonymous users displayed. +#280002 by pwolanin: Clean up .test setUp function. +#242377 by sun: Fixed sub-level menu items exceed total document height. + + +Admin Menu 6.x-1.0, 2008-06-26 +------------------------------ +#266308 by sun: Fixed jQuery 1.0.x incompatible selector for collapsing modules. +#268373 by sun: Added hook_update to cleanup for alpha/beta testers. +#268373 by sun: Added menu callback to disable/enable developer modules. +#132524 by pwolanin: Fixed admin_menu links are re-inserted each time menu links + are rebuilt. +by smk-ka: Performance: Use 'defer' attribute for JavaScript to delay execution. +#266099 by sun: Fixed description of "Apply margin-top" configuration setting. +#266308 by sun: Usability: Added Utility module features to collapse module + fieldsets on Modules page. +#251341 by sun: Added docs about display drupal links permission. + + +Admin Menu 6.x-1.0-BETA, 2008-06-08 +----------------------------------- +#132524 by sun: Fixed support for sub-content-types below node/add. +#132524 by pwolanin: Added support for localizable menu links. +#132524 by pwolanin, sun: Fixed menu links adjustments. +#132524 by pwolanin: Added simpletest. +#132524 by pwolanin: Major rewrite to better use Drupal 6 menu system. +#132524 by sun: Moved gettext translation files into translations. +#132524 by sun: Committing pre-alpha code for D6 due to public demand. + + +Admin Menu 5.x-2.x, xxxx-xx-xx +------------------------------ +#246221 by sun: Fixed user counter displays different values than Who's online + block. +#239022 by mikl: Added Danish translation. +#234444 by smk-ka: Fixed admin_menu icon does not respect theme settings. +#198240 by sun: Fixed admin_menu displayed in print output. + + +Admin Menu 5.x-2.4, 2008-02-24 +------------------------------ +#214740 by sun: Regression: Fixed directly applied marginTop not supported by IE. +#214725 by sun: Fixed wrong CSS id in admin_menu.js (missed in 5.x-2.3). + + +Admin Menu 5.x-2.3, 2008-02-24 +------------------------------ +#214725 by sun: Fixed CSS id and classes should not contain underscores. +#209390 by sun: Added note about interaction with user role permissions. +#214740 by jjeff, sun: Added module settings to configure margin-top CSS. +#200737 by sun: Changed admin_menu (fav)icon to use theme setting, if defined. +#203116 by smk-ka: Improved performance of non-cached admin_menu by storing + already processed URLs in the cache. +#224605 by sun: 'Add ' items do not appear without 'administer + nodes' permission. +#210615 by robertgarrigos: Fixed Mozilla Mac: Collapsible fieldsets display + error. + + +Admin Menu 5.x-2.2, 2007-01-08 +------------------------------ +#204884 by jjeff: Usability: Override theme font family declaration. +#204935 by jjeff: Added mouseout delay for hovered menus (yay!). +#193941 by downgang: Fixed margin in IE6 using Garland theme. +#197306 by sun: Fixed 'Run updates' leads to wrong url with clean URLs disabled. +Moved images into sub-folder. +by smk-ka: Fixed icon title for user counter not displayed & coding style. +Fixed user count not displayed without 'administer users' permission. + + +Admin Menu 5.x-2.1, 2007-12-02 +------------------------------ +Fixed adding menu items with negative weight not always working. +Fixed admin_menu_copy_items() is overwriting already existing items. +Fixed display menu item ids in devel settings does not work. + + +Admin Menu 5.x-2.0, 2007-12-02 +------------------------------ +Added devel_admin_menu() for fast access to clear-cache, variable editor and + switch_user. +Added username to logout button. +Added hook_admin_menu() to allow other modules to alter admin_menu. +#194189 by sun: Added counter for current anonymous/authenticated users. +Added Drupal.org project issue queue links for all enabled contrib modules. +#189701 by sun: Changed admin_menu icon to be a menu. +#193925 by sun: Removed obsolete menu slicing code. +#193669 by smk-ka: Moved admin_menu builder functions into include file. + + +Admin Menu 5.x-1.2, 2007-11-18 +------------------------------ +#176969 by smk-ka: Fixed performance issues with path(auto) module by + introducing a menu cache for admin_menu. +#179648 by sun: Inject admin_menu into theme. + Fixes several CSS bugs in various themes and also activation of admin_menu + immediately after installation. +#191213 by Standard: Fixed block info shouldn't contain the word "block". +#187816 by sun: Fixed "Add" not translatable. +#186218 by sun: Fixed admin menu icon too big in Safari. +#182563 by sun: Fixed wrong datatype for array_search in _admin_menu_get_children(). +#183496 by sun: Fixed invalid argument supplied for foreach in admin_menu_copy_items(). + + +Admin Menu 5.x-1.1, 2007-10-10 +------------------------------ +#178876 by sun: Fixed 3rd-level submenus expand without hover over. +#153455 by sun: Fixed add product node sub-elements are empty. +Fixed path_to_theme() call breaking blocks page. +#177582 by sun: Fixed bluebreeze theme compatibility. + + +Admin Menu 5.x-1.0, 2007-09-06 +------------------------------ +#156952 by sun: Fixed admin menu inaccessible due to margins. +#149229 by sun: Fixed admin menu not expanding in IE7. +#172545 by sun: Use opacity instead of -moz-opacity. +#132867 Fixed z-index too low. +- Fixed admin menu block selectors to override any other theme styles. +#155589 by sun: Added permission to access administration menu. +- Fixed a PHP warning when there are no content types defined in the system, as + node/add then has no child menu items. +#155312 by sun: Fixed menu item tooltip clashes. +Added support for custom stylesheets per theme. +Removed 4.7.x compatibility. + + +Admin Menu 4.7-1.3, 2007-03-30 +------------------------------ +#126601 Fixed Users can see inaccessible items. +#121027 Fixed Page not found entries for menu-collapsed.png. + + +Admin Menu 4.7-1.2, 2007-03-04 +------------------------------ +- Fixed menu item adjustments +- Fixed IE / Safari support +- Fixed base_path for IE support +- Added create content options to content management menu + + +Admin Menu 4.7-1.1, 2007-01-24 +------------------------------ +First stable release, compatible to Drupal 4.7.x and 5.x. + + +Admin Menu 4.7-1.0, 2007-01-16 +------------------------------ +Initial release of admin_menu module. Already supporting Drupal 5.0. diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/LICENSE.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/LICENSE.txt Fri Sep 20 11:18:21 2013 +0100 @@ -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. + + + Copyright (C) + + 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. + + , 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 -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/README.txt Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,188 @@ + +-- SUMMARY -- + +The Administration menu module displays the entire administrative menu tree (and +most local tasks) in a drop-down menu, providing administrators one- or +two-click access to most pages. Other modules may also add menu links to the +menu using hook_admin_menu_output_alter(). + +For a full description of the module, visit the project page: + http://drupal.org/project/admin_menu + +To submit bug reports and feature suggestions, or to track changes: + http://drupal.org/project/issues/admin_menu + + +-- REQUIREMENTS -- + +None. + + +-- INSTALLATION -- + +* Install as usual, see http://drupal.org/node/70151 for further information. + +* You likely want to disable Toolbar module, since its output clashes with + Administration menu. + + +-- CONFIGURATION -- + +* Configure user permissions in Administration » People » Permissions: + + - Use the administration pages and help (System module) + + The top-level administration categories require this permission to be + accessible. The administration menu will be empty unless this permission is + granted. + + - Access administration menu + + Users in roles with the "Access administration menu" permission will see + the administration menu at the top of each page. + + - Display Drupal links + + Users in roles with the "Display drupal links" permission will receive + links to drupal.org issue queues for all enabled contributed modules. The + issue queue links appear under the administration menu icon. + + Note that the menu items displayed in the administration menu depend on the + actual permissions of the viewing user. For example, the "People" menu item + is not displayed to a user who is not a member of a role with the "Administer + users" permission. + +* Customize the menu settings in Administration » Configuration and modules » + Administration » Administration menu. + +* To prevent administrative menu items from appearing twice, you may hide the + "Management" menu block. + + +-- CUSTOMIZATION -- + +* To override the default administration menu icon, you may: + + 1) Disable it via CSS in your theme: + + body #admin-menu-icon { display: none; } + + 2) Alter the image by overriding the theme function: + + Copy the entire theme_admin_menu_icon() function into your template.php, + rename it to phptemplate_admin_menu_icon() or THEMENAME_admin_menu_icon(), + and customize the output according to your needs. + + Remember that the output of the administration menu is cached. To see changes + from your theme override function, you must clear your site cache (via + the "Flush all caches" link on the menu). + +* To override the font size, add the following line to your theme's stylesheet: + + body #admin-menu { font-size: 10px; } + + +-- TROUBLESHOOTING -- + +* If the menu does not display, check the following: + + - Are the "Access administration menu" and "Use the administration pages and help" + permissions enabled for the appropriate roles? + + - Does html.tpl.php of your theme output the $page_bottom variable? + +* If the menu is rendered behind a Flash movie object, add this property to your + Flash object(s): + + + + See http://drupal.org/node/195386 for further information. + + +-- FAQ -- + +Q: When the administration menu module is enabled, blank space is added to the + bottom of my theme. Why? + +A: This is caused by a long list of links to module issue queues at Drupal.org. + Use Administer >> User management >> Permissions to disable the "display + drupal links" permission for all appropriate roles. Note that since UID 1 + automatically receives all permissions, the list of issue queue links cannot + be disabled for UID 1. + + +Q: After upgrading to 6.x-1.x, the menu disappeared. Why? + +A: You may need to regenerate your menu. Visit + http://example.com/admin/build/modules to regenerate your menu (substitute + your site name for example.com). + + +Q: Can I configure the administration menu module to display another menu (like + the Navigation menu, for instance)? + +A: No. As the name implies, administration menu module is for administrative + menu links only. However, you can copy and paste the contents of + admin_menu.css into your theme's stylesheet and replace #admin-menu with any + other menu block id (#block-menu-1, for example). + + +Q: Sometimes, the user counter displays a lot of anonymous users, but no spike + of users or requests appear in Google Analytics or other tracking tools. + +A: If your site was concurrently spidered by search-engine robots, it may have + a significant number of anonymous users for a short time. Most web tracking + tools like Google Analytics automatically filter out these requests. + + +Q: I enabled "Aggregate and compress CSS files", but admin_menu.css is still + there. Is this normal? + +A: Yes, this is the intended behavior. the administration menu module only loads + its stylesheet as needed (i.e., on page requests by logged-on, administrative + users). + + +Q: Why are sub-menus not visible in Opera? + +A: In the Opera browser preferences under "web pages" there is an option to fit + to width. By disabling this option, sub-menus in the administration menu + should appear. + + +Q: How can the administration menu be hidden on certain pages? + +A: You can suppress it by simply calling the following function in PHP: + + module_invoke('admin_menu', 'suppress'); + + However, this needs to happen as early as possible in the page request, so + placing it in the theming layer (resp. a page template file) is too late. + Ideally, the function is called in hook_init() in a custom module. If you do + not have a custom module, placing it into some conditional code at the top of + template.php may work out, too. + + +-- CONTACT -- + +Current maintainers: +* Daniel F. Kudwien (sun) - http://drupal.org/user/54136 +* Peter Wolanin (pwolanin) - http://drupal.org/user/49851 +* Stefan M. Kudwien (smk-ka) - http://drupal.org/user/48898 +* Dave Reid (Dave Reid) - http://drupal.org/user/53892 + +Major rewrite for Drupal 6 by Peter Wolanin (pwolanin). + +This project has been sponsored by: +* UNLEASHED MIND + Specialized in consulting and planning of Drupal powered sites, UNLEASHED + MIND offers installation, development, theming, customization, and hosting + to get you started. Visit http://www.unleashedmind.com for more information. + +* Lullabot + Friendly Drupal experts providing professional consulting & education + services. Visit http://www.lullabot.com for more information. + +* Acquia + Commercially Supported Drupal. Visit http://acquia.com for more information. + diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/admin_devel/admin_devel.info --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/admin_devel/admin_devel.info Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,12 @@ +name = Administration Development tools +description = Administration and debugging functionality for developers and site builders. +package = Administration +core = 7.x +scripts[] = admin_devel.js + +; Information added by drupal.org packaging script on 2013-01-31 +version = "7.x-3.0-rc4" +core = "7.x" +project = "admin_menu" +datestamp = "1359651687" + diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/admin_devel/admin_devel.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/admin_devel/admin_devel.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,40 @@ +(function($) { + +/** + * jQuery debugging helper. + * + * Invented for Dreditor. + * + * @usage + * $.debug(var [, name]); + * $variable.debug( [name] ); + */ +jQuery.extend({ + debug: function () { + // Setup debug storage in global window. We want to look into it. + window.debug = window.debug || []; + + args = jQuery.makeArray(arguments); + // Determine data source; this is an object for $variable.debug(). + // Also determine the identifier to store data with. + if (typeof this == 'object') { + var name = (args.length ? args[0] : window.debug.length); + var data = this; + } + else { + var name = (args.length > 1 ? args.pop() : window.debug.length); + var data = args[0]; + } + // Store data. + window.debug[name] = data; + // Dump data into Firebug console. + if (typeof console != 'undefined') { + console.log(name, data); + } + return this; + } +}); +// @todo Is this the right way? +jQuery.fn.debug = jQuery.debug; + +})(jQuery); diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/admin_devel/admin_devel.module --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/admin_devel/admin_devel.module Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,33 @@ + 'submit', + '#value' => t('Rebuild system links'), + '#submit' => array('admin_devel_form_admin_menu_theme_settings_alter_rebuild_submit'), + // @todo Not necessarily ready for mass-consumption yet. + '#access' => FALSE, + ); +} + +/** + * Form submit handler to wipe and rebuild all 'module' = 'system' menu links. + */ +function admin_devel_form_admin_menu_theme_settings_alter_rebuild_submit($form, &$form_state) { + // Delete all auto-generated menu links derived from menu router items. + db_delete('menu_links') + ->condition('module', 'system') + ->execute(); + // Rebuild menu links from current menu router items. + menu_rebuild(); + + drupal_set_message(t('System links derived from menu router paths have been rebuilt.')); +} diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/admin_menu-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/admin_menu-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,64 @@ + +#admin-menu { + text-align: right; +} +#admin-menu .dropdown .admin-menu-users a { + background-position: 10% center; + padding-left: 22px; + padding-right: 0; +} +#admin-menu .dropdown .admin-menu-action, +#admin-menu .dropdown .admin-menu-search { + float: left; +} +#admin-menu .dropdown .admin-menu-action a { + border-left: none; + border-right: 1px solid #323232; +} + +/* All lists */ +#admin-menu a { + text-align: right; +} +#admin-menu .dropdown a { + border-left: 1px solid #323232; + border-right: 0; +} +#admin-menu .dropdown .admin-menu-tab a { + border-left: 1px solid #52565E; + border-right: 0; +} +#admin-menu .dropdown li li a { + border-left: 0; +} + +/* All list items */ +#admin-menu .dropdown li { + float: right; +} +#admin-menu .dropdown li li { +} + +/* Second-level lists */ +#admin-menu .dropdown li ul { + left: auto; + right: -999em; +} + +/* Third-and-above-level lists */ +#admin-menu .dropdown li li.expandable ul { + margin-left: 0; + margin-right: 160px; +} + +/* Lists nested under hovered list items */ +#admin-menu .dropdown li.admin-menu-action:hover ul { + left: 0 !important; + right: auto; +} + +/* Second-and-more-level hovering */ +#admin-menu .dropdown li li.expandable { + background-image: url(images/arrow-rtl.png); + background-position: 5px 6px; +} diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/admin_menu.admin.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/admin_menu.admin.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,62 @@ +(function($) { + +/** + * Live preview of Administration menu components. + */ +Drupal.behaviors.adminMenuLivePreview = { + attach: function (context, settings) { + $('input[name^="admin_menu_components"]', context).once('admin-menu-live-preview') + .change(function () { + var target = $(this).attr('rel'); + $(target).toggle(this.checked); + }) + .trigger('change'); + } +}; + +/** + * Automatically enables required permissions on demand. + * + * Many users do not understand that two permissions are required for the + * administration menu to appear. Since Drupal core provides no facility for + * this, we implement a simple manual confirmation for automatically enabling + * the "other" permission. + */ +Drupal.behaviors.adminMenuPermissionsSetupHelp = { + attach: function (context, settings) { + $('#permissions', context).once('admin-menu-permissions-setup', function () { + // Retrieve matrix/mapping - these need to use the same indexes for the + // same permissions and roles. + var $roles = $(this).find('th:not(:first)'); + var $admin = $(this).find('input[name$="[access administration pages]"]'); + var $menu = $(this).find('input[name$="[access administration menu]"]'); + + // Retrieve the permission label - without description. + var adminPermission = $.trim($admin.eq(0).parents('td').prev().children().get(0).firstChild.textContent); + var menuPermission = $.trim($menu.eq(0).parents('td').prev().children().get(0).firstChild.textContent); + + $admin.each(function (index) { + // Only proceed if both are not enabled already. + if (!(this.checked && $menu[index].checked)) { + // Stack both checkboxes and attach a click event handler to both. + $(this).add($menu[index]).click(function () { + // Do nothing when disabling a permission. + if (this.checked) { + // Figure out which is the other, check whether it still disabled, + // and if so, ask whether to auto-enable it. + var other = (this == $admin[index] ? $menu[index] : $admin[index]); + if (!other.checked && confirm(Drupal.t('Also allow !name role to !permission?', { + '!name': $roles[index].textContent, + '!permission': (this == $admin[index] ? menuPermission : adminPermission) + }))) { + other.checked = 'checked'; + } + } + }); + } + }); + }); + } +}; + +})(jQuery); diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/admin_menu.api.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/admin_menu.api.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,164 @@ + Content types. + // The key denotes the dynamic path to expand to multiple menu items. + $map['admin/structure/types/manage/%node_type'] = array( + // Link generated items directly to the "Content types" item. + 'parent' => 'admin/structure/types', + // Create expansion arguments for the '%node_type' placeholder. + 'arguments' => array( + array( + '%node_type' => array_keys(node_type_get_types()), + ), + ), + ); + return $map; +} + +/** + * Add to the administration menu content before it is rendered. + * + * Only use this hook to add new data to the menu structure. Use + * hook_admin_menu_output_alter() to *alter* existing data. + * + * @param array $content + * A structured array suitable for drupal_render(), potentially containing: + * - menu: The administrative menu of links below the path 'admin/*'. + * - icon: The icon menu. + * - account: The user account name and log out link. + * - users: The user counter. + * Additionally, these special properties: + * - #components: The actual components contained in $content are configurable + * and depend on the 'admin_menu_components' configuration value. #components + * holds a copy of that for convenience. + * - #complete: A Boolean indicating whether the complete menu should be built, + * ignoring the current configuration in #components. + * Passed by reference. + * + * @see hook_admin_menu_output_alter() + * @see admin_menu_links_menu() + * @see admin_menu_links_icon() + * @see admin_menu_links_user() + * @see theme_admin_menu_links() + */ +function hook_admin_menu_output_build(&$content) { + // In case your implementation provides a configurable component, check + // whether the component should be displayed: + if (empty($content['#components']['shortcut.links']) && !$content['#complete']) { + return; + } + + // Add new top-level item to the menu. + if (isset($content['menu'])) { + $content['menu']['myitem'] = array( + '#title' => t('My item'), + // #attributes are used for list items (LI). + '#attributes' => array('class' => array('mymodule-myitem')), + '#href' => 'mymodule/path', + // #options are passed to l(). + '#options' => array( + 'query' => drupal_get_destination(), + // Apply a class on the link (anchor). + 'attributes' => array('class' => array('myitem-link-anchor')), + ), + // #weight controls the order of links in the resulting item list. + '#weight' => 50, + ); + } + // Add link to the icon menu to manually run cron. + if (isset($content['icon'])) { + $content['icon']['myitem']['cron'] = array( + '#title' => t('Run cron'), + '#access' => user_access('administer site configuration'), + '#href' => 'admin/reports/status/run-cron', + ); + } +} + +/** + * Change the administration menu content before it is rendered. + * + * Only use this hook to alter existing data in the menu structure. Use + * hook_admin_menu_output_build() to *add* new data. + * + * @param array $content + * A structured array suitable for drupal_render(). Passed by reference. + * + * @see hook_admin_menu_output_build() + */ +function hook_admin_menu_output_alter(&$content) { +} + +/** + * Return content to be replace via JS in the cached menu output. + * + * @param bool $complete + * A Boolean indicating whether all available components of the menu will be + * output and the cache will be skipped. + * + * @return array + * An associative array whose keys are jQuery selectors and whose values are + * strings containing the replacement content. + */ +function hook_admin_menu_replacements($complete) { + $items = array(); + // If the complete menu is output, then it is uncached and will contain the + // current counts already. + if (!$complete) { + // Check whether the users count component is enabled. + $components = variable_get('admin_menu_components', array()); + if (!empty($components['admin_menu.users']) && ($user_count = admin_menu_get_user_count())) { + // Replace the counters in the cached menu output with current counts. + $items['.admin-menu-users a'] = $user_count; + } + } + return $items; +} + +/** + * Inform about additional module-specific caches that can be cleared. + * + * Administration menu uses this hook to gather information about available + * caches that can be flushed individually. Each returned item forms a separate + * menu link below the "Flush all caches" link in the icon menu. + * + * @return array + * An associative array whose keys denote internal identifiers for a + * particular caches (which can be freely defined, but should be in a module's + * namespace) and whose values are associative arrays containing: + * - title: The name of the cache, without "cache" suffix. This label is + * output as link text, but also for the "!title cache cleared." + * confirmation message after flushing the cache; make sure it works and + * makes sense to users in both locations. + * - callback: The name of a function to invoke to flush the individual cache. + */ +function hook_admin_menu_cache_info() { + $caches['update'] = array( + 'title' => t('Update data'), + 'callback' => '_update_cache_clear', + ); + return $caches; +} diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/admin_menu.color.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/admin_menu.color.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,46 @@ + +/** + * @file + * Administration menu color override. + */ + +#admin-menu { + background-color: #911; + background-image: url(images/bkg-red.png); +} +#admin-menu li.admin-menu-action a { + border-left-color: #a91f1f; +} + +/* All lists */ +#admin-menu ul a { + border-right-color: #a91f1f; +} +#admin-menu ul li.admin-menu-tab a { + border-right-color: #52565E; +} +#admin-menu li li a { + border-top-color: #801f1f; +} + +/* All list items */ +#admin-menu li li { + background-color: #991f1f; +} + +/* Second-and-more-level hovering */ +#admin-menu li li.expandable { + background-color: #b93f3f; +} +#admin-menu li li:hover, +#admin-menu li li.iehover { + background-color: #690f0f; +} +#admin-menu li li.expandable:hover a, +#admin-menu li li.expandable:hover li.expandable:hover a { + border-color: #801f1f; +} +#admin-menu li li.expandable:hover li a, +#admin-menu li li.expandable:hover li.expandable:hover li a { + border-color: #801f1f; +} diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/admin_menu.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/admin_menu.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,250 @@ + +/** + * @file + * Administration menu. + * + * Implementation of Sons of Suckerfish Dropdowns. + * + * @see www.htmldog.com/articles/suckerfish + */ + +#admin-menu { + background: #101010 url(images/bkg.png) bottom left repeat-x; + font-size: 9px; + font-family: "lucida grande", tahoma, verdana, arial, sans-serif; + left: 0; + position: absolute; + text-align: left; + top: 0; + width: 100%; +} +#admin-menu-wrapper { + overflow: hidden; +} +#admin-menu .dropdown .admin-menu-icon a { + padding: 1px 8px 4px; +} +#admin-menu .dropdown .admin-menu-icon ul a { + padding: 4px 8px; +} +#admin-menu .dropdown .admin-menu-icon img { + vertical-align: bottom; +} +#admin-menu .dropdown .admin-menu-users a { + background: transparent url(images/icon_users.png) 90% center no-repeat; + padding-right: 22px; +} +#admin-menu .dropdown .admin-menu-action, +#admin-menu .dropdown .admin-menu-search { + float: right; +} +#admin-menu .dropdown .admin-menu-action a { + border-left: 1px solid #323232; + border-right: none; +} +body.admin-menu { + margin-top: 20px !important; +} + +/* All lists */ +#admin-menu, +#admin-menu .dropdown { + line-height: 1.4em; + list-style: none; + margin: 0; + padding: 0; + z-index: 999; +} +#admin-menu .dropdown { + position: static; +} +#admin-menu a, +#admin-menu li > span { + background: transparent none; + border: none; + color: #EEE; + font-weight: normal; + text-align: left; /* LTR */ + text-decoration: none; +} +#admin-menu .dropdown a, +#admin-menu .dropdown li > span { + border-right: 1px solid #323232; /* LTR */ + display: block; + padding: 4px 8px; +} +#admin-menu .dropdown .admin-menu-tab a { + border-right: 1px solid #52565E; /* LTR */ +} +#admin-menu .dropdown li li a { + border-right: none; /* LTR */ + border-top: 1px solid #323232; +} + +/* All list items */ +#admin-menu .dropdown li { + background-image: none; + float: left; /* LTR */ + height: 100%; + list-style-image: none; + list-style-type: none; + margin: 0 !important; + padding: 0; +} +#admin-menu .dropdown .admin-menu-tab { + background: url(images/bkg_tab.png) repeat-x left bottom; + padding-bottom: 1px; +} +#admin-menu .dropdown li li { + background: #202020; + filter: Alpha(opacity=88); + opacity: 0.88; + width: 160px; /* Required for Opera */ +} +#admin-menu .dropdown li li li { + filter: Alpha(opacity=100); + opacity: 1; +} + +/* Second-level lists */ +/* Note: We must hide sub-lists or scrollbars might appear (display: none is not read by screen readers). */ +#admin-menu .dropdown li ul { + background: none; + display: none; + left: -999em; /* LTR */ + line-height: 1.2em; + margin: 0; + position: absolute; + width: 160px; +} + +/* Third-and-above-level lists */ +#admin-menu .dropdown li li.expandable ul { + margin: -20px 0 0 160px; /* LTR */ +} + +#admin-menu .dropdown li:hover ul ul, +#admin-menu .dropdown li:hover ul ul ul, +#admin-menu .dropdown li:hover ul ul ul ul, +#admin-menu .dropdown li:hover ul ul ul ul ul, +#admin-menu .dropdown li.iehover ul ul, +#admin-menu .dropdown li.iehover ul ul ul, +#admin-menu .dropdown li.iehover ul ul ul ul, +#admin-menu .dropdown li.iehover ul ul ul ul ul { + display: none; + left: -999em; /* LTR */ +} + +/* Lists nested under hovered list items */ +#admin-menu .dropdown li:hover ul, +#admin-menu .dropdown li li:hover ul, +#admin-menu .dropdown li li li:hover ul, +#admin-menu .dropdown li li li li:hover ul, +#admin-menu .dropdown li li li li li:hover ul, +#admin-menu .dropdown li.iehover ul, +#admin-menu .dropdown li li.iehover ul, +#admin-menu .dropdown li li li.iehover ul, +#admin-menu .dropdown li li li li.iehover ul, +#admin-menu .dropdown li li li li li.iehover ul { + display: block; + left: auto; /* LTR */ +} +#admin-menu .dropdown li.admin-menu-action:hover ul { + right: 0; /* LTR */ +} + +/* Second-and-more-level hovering */ +#admin-menu .dropdown li li.expandable { + background: #45454A url(images/arrow.png) no-repeat 145px 6px; +} +#admin-menu .dropdown li li:hover, +#admin-menu .dropdown li li.iehover { + background-color: #111; +} +#admin-menu .dropdown li li:hover a, +#admin-menu .dropdown li li:hover li:hover a, +#admin-menu .dropdown li li:hover li:hover li:hover a { + color: #FFF; +} +#admin-menu .dropdown li li.expandable:hover a, +#admin-menu .dropdown li li.expandable:hover li.expandable:hover a { + border-color: #444; + color: #EEE; +} +#admin-menu .dropdown li li.expandable:hover li a, +#admin-menu .dropdown li li.expandable:hover li.expandable:hover li a { + border-color: #323232; +} +#admin-menu .dropdown li li:hover li a, +#admin-menu .dropdown li li.iehover li a, +#admin-menu .dropdown li li.iehover li.iehover li a { + color: #EEE; +} +#admin-menu .dropdown li li.iehover a, +#admin-menu .dropdown li li.iehover li.iehover a, +#admin-menu .dropdown li li.iehover li.iehover li.iehover a { + color: #FFF; + width: 90%; /* IE */ +} + +/* Search form */ +#admin-menu .admin-menu-search .form-item { + margin: 0; + padding: 0; +} +#admin-menu .admin-menu-search input { + background: #fff none center right no-repeat; + border: none; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + font-size: 10px; + margin: 1px 0; + outline: none; + padding: 2px 22px 2px 4px; + width: 158px; +} + +#admin-menu .dropdown .admin-menu-search-results { + display: block !important; + left: auto !important; + top: 100%; +} +#admin-menu .admin-menu-search-results, +#admin-menu .admin-menu-search-results li { + width: 186px; +} + +#admin-menu li.highlight { + background-color: #eee !important; +} +#admin-menu li.highlight > a { + border-color: #ccc !important; + color: #111 !important; +} + +/* #210615: Mozilla on Mac fix */ +html.js fieldset.collapsible div.fieldset-wrapper { + overflow: visible; +} + +/* Hide the menu on print output. */ +@media print { + #admin-menu { + display: none !important; + } + body.admin-menu { + margin-top: 0 !important; + } +} + +/** + * Tweaks permissions, if enabled. + */ +tr.admin-menu-tweak-permissions-processed { + cursor: pointer; + cursor: hand; +} +tr.admin-menu-tweak-permissions-processed td.module { + border-top: 0; +} diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/admin_menu.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/admin_menu.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1033 @@ + $data) { + // Convert named placeholders to anonymous placeholders, since the menu + // system stores paths using anonymous placeholders. + $replacements = array_fill_keys(array_keys($data['arguments'][0]), '%'); + $data['parent'] = strtr($data['parent'], $replacements); + $new_map[strtr($path, $replacements)] = $data; + } + $expand_map = $new_map; + unset($new_map); + + // Retrieve dynamic menu link tree for the expansion mappings. + // @todo Skip entire processing if initial $expand_map is empty and directly + // return $tree? + if (!empty($expand_map)) { + $tree_dynamic = admin_menu_tree_dynamic($expand_map); + } + else { + $tree_dynamic = array(); + } + + // Merge local tasks with static menu tree. + $tree = menu_tree_all_data($menu_name); + admin_menu_merge_tree($tree, $tree_dynamic, array()); + + return $tree; +} + +/** + * Load menu link trees for router paths containing dynamic arguments. + * + * @param $expand_map + * An array containing menu router path placeholder expansion argument + * mappings. + * + * @return + * An associative array whose keys are the parent paths of the menu router + * paths given in $expand_map as well as the parent paths of any child link + * deeper down the tree. The parent paths are used in admin_menu_merge_tree() + * to check whether anything needs to be merged. + * + * @see hook_admin_menu_map() + */ +function admin_menu_tree_dynamic(array $expand_map) { + $p_columns = array(); + for ($i = 1; $i <= MENU_MAX_DEPTH; $i++) { + $p_columns[] = 'p' . $i; + } + + // Fetch p* columns for all router paths to expand. + $router_paths = array_keys($expand_map); + $plids = db_select('menu_links', 'ml') + ->fields('ml', $p_columns) + ->condition('router_path', $router_paths) + ->execute() + ->fetchAll(PDO::FETCH_ASSOC); + + // Unlikely, but possible. + if (empty($plids)) { + return array(); + } + + // Use queried plid columns to query sub-trees for the router paths. + $query = db_select('menu_links', 'ml'); + $query->join('menu_router', 'm', 'ml.router_path = m.path'); + $query + ->fields('ml') + ->fields('m', array_diff(drupal_schema_fields_sql('menu_router'), drupal_schema_fields_sql('menu_links'))); + + // The retrieved menu link trees have to be ordered by depth, so parents + // always come before their children for the storage logic below. + foreach ($p_columns as $column) { + $query->orderBy($column, 'ASC'); + } + + $db_or = db_or(); + foreach ($plids as $path_plids) { + $db_and = db_and(); + // plids with value 0 may be ignored. + foreach (array_filter($path_plids) as $column => $plid) { + $db_and->condition($column, $plid); + } + $db_or->condition($db_and); + } + $query->condition($db_or); + $result = $query + ->execute() + ->fetchAllAssoc('mlid', PDO::FETCH_ASSOC); + + // Store dynamic links grouped by parent path for later merging and assign + // placeholder expansion arguments. + $tree_dynamic = array(); + foreach ($result as $mlid => $link) { + // If contained in $expand_map, then this is a (first) parent, and we need + // to store by the defined 'parent' path for later merging, as well as + // provide the expansion map arguments to apply to the dynamic tree. + if (isset($expand_map[$link['path']])) { + $parent_path = $expand_map[$link['path']]['parent']; + $link['expand_map'] = $expand_map[$link['path']]['arguments']; + } + // Otherwise, just store this link keyed by its parent path; the expand_map + // is automatically derived from parent paths. + else { + $parent_path = $result[$link['plid']]['path']; + } + + $tree_dynamic[$parent_path][] = $link; + } + + return $tree_dynamic; +} + +/** + * Walk through the entire menu tree and merge in expanded dynamic menu links. + * + * @param &$tree + * A menu tree structure as returned by menu_tree_all_data(). + * @param $tree_dynamic + * A dynamic menu tree structure as returned by admin_menu_tree_dynamic(). + * @param $expand_map + * An array containing menu router path placeholder expansion argument + * mappings. + * + * @see hook_admin_menu_map() + * @see admin_menu_tree_dynamic() + * @see menu_tree_all_data() + */ +function admin_menu_merge_tree(array &$tree, array $tree_dynamic, array $expand_map) { + foreach ($tree as $key => $data) { + $path = $data['link']['router_path']; + + // Recurse into regular menu tree. + if ($tree[$key]['below']) { + admin_menu_merge_tree($tree[$key]['below'], $tree_dynamic, $expand_map); + } + // Nothing to merge, if this parent path is not in our dynamic tree. + if (!isset($tree_dynamic[$path])) { + continue; + } + + // Add expanded dynamic items. + foreach ($tree_dynamic[$path] as $link) { + // If the dynamic item has custom placeholder expansion parameters set, + // use them, otherwise keep current. + if (isset($link['expand_map'])) { + // If there are currently no expansion parameters, we may use the new + // set immediately. + if (empty($expand_map)) { + $current_expand_map = $link['expand_map']; + } + else { + // Otherwise we need to filter out elements that differ from the + // current set, i.e. that are not in the same path. + $current_expand_map = array(); + foreach ($expand_map as $arguments) { + foreach ($arguments as $placeholder => $value) { + foreach ($link['expand_map'] as $new_arguments) { + // Skip the new argument if it doesn't contain the current + // replacement placeholders or if their values differ. + if (!isset($new_arguments[$placeholder]) || $new_arguments[$placeholder] != $value) { + continue; + } + $current_expand_map[] = $new_arguments; + } + } + } + } + } + else { + $current_expand_map = $expand_map; + } + + // Skip dynamic items without expansion parameters. + if (empty($current_expand_map)) { + continue; + } + + // Expand anonymous to named placeholders. + // @see _menu_load_objects() + $path_args = explode('/', $link['path']); + $load_functions = unserialize($link['load_functions']); + if (is_array($load_functions)) { + foreach ($load_functions as $index => $function) { + if ($function) { + if (is_array($function)) { + list($function,) = each($function); + } + // Add the loader function name minus "_load". + $placeholder = '%' . substr($function, 0, -5); + $path_args[$index] = $placeholder; + } + } + } + $path_dynamic = implode('/', $path_args); + + // Create new menu items using expansion arguments. + foreach ($current_expand_map as $arguments) { + // Create the cartesian product for all arguments and create new + // menu items for each generated combination thereof. + foreach (admin_menu_expand_args($arguments) as $replacements) { + $newpath = strtr($path_dynamic, $replacements); + // Skip this item, if any placeholder could not be replaced. + // Faster than trying to invoke _menu_translate(). + if (strpos($newpath, '%') !== FALSE) { + continue; + } + $map = explode('/', $newpath); + $item = admin_menu_translate($link, $map); + // Skip this item, if the current user does not have access. + if (empty($item)) { + continue; + } + // Build subtree using current replacement arguments. + $new_expand_map = array(); + foreach ($replacements as $placeholder => $value) { + $new_expand_map[$placeholder] = array($value); + } + admin_menu_merge_tree($item, $tree_dynamic, array($new_expand_map)); + $tree[$key]['below'] += $item; + } + } + } + // Sort new subtree items. + ksort($tree[$key]['below']); + } +} + +/** + * Translate an expanded router item into a menu link suitable for rendering. + * + * @param $router_item + * A menu router item. + * @param $map + * A path map with placeholders replaced. + */ +function admin_menu_translate($router_item, $map) { + _menu_translate($router_item, $map, TRUE); + + // Run through hook_translated_menu_link_alter() to add devel information, + // if configured. + $router_item['menu_name'] = 'management'; + // @todo Invoke as usual like _menu_link_translate(). + admin_menu_translated_menu_link_alter($router_item, NULL); + + if ($router_item['access']) { + // Override mlid to make this item unique; since these items are expanded + // from dynamic items, the mlid is always the same, so each item would + // replace any other. + // @todo Doing this instead leads to plenty of duplicate links below + // admin/structure/menu; likely a hidden recursion problem. + // $router_item['mlid'] = $router_item['href'] . $router_item['mlid']; + $router_item['mlid'] = $router_item['href']; + // Turn menu callbacks into regular menu items to make them visible. + if ($router_item['type'] == MENU_CALLBACK) { + $router_item['type'] = MENU_NORMAL_ITEM; + } + + // @see _menu_tree_check_access() + $key = (50000 + $router_item['weight']) . ' ' . $router_item['title'] . ' ' . $router_item['mlid']; + return array($key => array( + 'link' => $router_item, + 'below' => array(), + )); + } + + return array(); +} + +/** + * Create the cartesian product of multiple varying sized argument arrays. + * + * @param $arguments + * A two dimensional array of arguments. + * + * @see hook_admin_menu_map() + */ +function admin_menu_expand_args($arguments) { + $replacements = array(); + + // Initialize line cursors, move out array keys (placeholders) and assign + // numeric keys instead. + $i = 0; + $placeholders = array(); + $new_arguments = array(); + foreach ($arguments as $placeholder => $values) { + // Skip empty arguments. + if (empty($values)) { + continue; + } + $cursor[$i] = 0; + $placeholders[$i] = $placeholder; + $new_arguments[$i] = $values; + $i++; + } + $arguments = $new_arguments; + unset($new_arguments); + + if ($rows = count($arguments)) { + do { + // Collect current argument from each row. + $row = array(); + for ($i = 0; $i < $rows; ++$i) { + $row[$placeholders[$i]] = $arguments[$i][$cursor[$i]]; + } + $replacements[] = $row; + + // Increment cursor position. + $j = $rows - 1; + $cursor[$j]++; + while (!array_key_exists($cursor[$j], $arguments[$j])) { + // No more arguments left: reset cursor, go to next line and increment + // that cursor instead. Repeat until argument found or out of rows. + $cursor[$j] = 0; + if (--$j < 0) { + // We're done. + break 2; + } + $cursor[$j]++; + } + } while (1); + } + + return $replacements; +} + +/** + * Build the administration menu as renderable menu links. + * + * @param $tree + * A data structure representing the administration menu tree as returned from + * menu_tree_all_data(). + * + * @return + * The complete administration menu, suitable for theme_admin_menu_links(). + * + * @see theme_admin_menu_links() + * @see admin_menu_menu_alter() + */ +function admin_menu_links_menu($tree) { + $links = array(); + foreach ($tree as $data) { + // Skip items that are inaccessible, invisible, or link to their parent. + // (MENU_DEFAULT_LOCAL_TASK), and MENU_CALLBACK-alike items that should only + // appear in the breadcrumb. + if (!$data['link']['access'] || $data['link']['type'] & MENU_LINKS_TO_PARENT || $data['link']['type'] == MENU_VISIBLE_IN_BREADCRUMB || $data['link']['hidden'] == 1) { + continue; + } + // Hide 'Administer' and make child links appear on this level. + // @todo Make this configurable. + if ($data['link']['router_path'] == 'admin') { + if ($data['below']) { + $links = array_merge($links, admin_menu_links_menu($data['below'])); + } + continue; + } + // Omit alias lookups. + $data['link']['localized_options']['alias'] = TRUE; + // Remove description to prevent mouseover tooltip clashes. + unset($data['link']['localized_options']['attributes']['title']); + + // Make action links (typically "Add ...") appear first in dropdowns. + // They might appear first already, but only as long as there is no link + // that comes alphabetically first (e.g., a node type with label "Ad"). + if ($data['link']['type'] & MENU_IS_LOCAL_ACTION) { + $data['link']['weight'] -= 1000; + } + + $links[$data['link']['href']] = array( + '#title' => $data['link']['title'], + '#href' => $data['link']['href'], + '#options' => $data['link']['localized_options'], + '#weight' => $data['link']['weight'], + ); + + // Recurse to add any child links. + $children = array(); + if ($data['below']) { + $children = admin_menu_links_menu($data['below']); + $links[$data['link']['href']] += $children; + } + + // Handle links pointing to category/overview pages. + if ($data['link']['page_callback'] == 'system_admin_menu_block_page' || $data['link']['page_callback'] == 'system_admin_config_page') { + // Apply a marker for others to consume. + $links[$data['link']['href']]['#is_category'] = TRUE; + // Automatically hide empty categories. + // Check for empty children first for performance. Only when non-empty + // (typically 'admin/config'), check whether children are accessible. + if (empty($children) || !element_get_visible_children($children)) { + $links[$data['link']['href']]['#access'] = FALSE; + } + } + } + return $links; +} + +/** + * Build icon menu links; mostly containing maintenance helpers. + * + * @see theme_admin_menu_links() + */ +function admin_menu_links_icon() { + $destination = drupal_get_destination(); + + $links = array( + '#theme' => 'admin_menu_links', + '#wrapper_attributes' => array('id' => 'admin-menu-icon'), + '#weight' => -100, + ); + $links['icon'] = array( + '#title' => theme('admin_menu_icon'), + '#attributes' => array('class' => array('admin-menu-icon')), + '#href' => '', + '#options' => array( + 'html' => TRUE, + ), + ); + // Add link to manually run cron. + $links['icon']['cron'] = array( + '#title' => t('Run cron'), + '#weight' => 50, + '#access' => user_access('administer site configuration'), + '#href' => 'admin/reports/status/run-cron', + ); + // Add link to run update.php. + $links['icon']['update'] = array( + '#title' => t('Run updates'), + '#weight' => 50, + // @see update_access_allowed() + '#access' => $GLOBALS['user']->uid == 1 || !empty($GLOBALS['update_free_access']) || user_access('administer software updates'), + '#href' => base_path() . 'update.php', + '#options' => array( + 'external' => TRUE, + ), + ); + // Add link to drupal.org. + $links['icon']['drupal.org'] = array( + '#title' => 'Drupal.org', + '#weight' => 100, + '#access' => user_access('display drupal links'), + '#href' => 'http://drupal.org', + ); + // Add links to project issue queues. + foreach (module_list(FALSE, TRUE) as $module) { + $info = drupal_parse_info_file(drupal_get_path('module', $module) . '/' . $module . '.info'); + if (!isset($info['project']) || isset($links['icon']['drupal.org'][$info['project']])) { + continue; + } + $links['icon']['drupal.org'][$info['project']] = array( + '#title' => t('@project issue queue', array('@project' => $info['name'])), + '#weight' => ($info['project'] == 'drupal' ? -10 : 0), + '#href' => 'http://drupal.org/project/issues/' . $info['project'], + '#options' => array( + 'query' => array('version' => (isset($info['core']) ? $info['core'] : 'All')), + ), + ); + } + // Add items to flush caches. + $links['icon']['flush-cache'] = array( + '#title' => t('Flush all caches'), + '#weight' => 20, + '#access' => user_access('flush caches'), + '#href' => 'admin_menu/flush-cache', + '#options' => array( + 'query' => $destination + array('token' => drupal_get_token('admin_menu/flush-cache')), + ), + ); + $caches = module_invoke_all('admin_menu_cache_info'); + foreach ($caches as $name => $cache) { + $links['icon']['flush-cache'][$name] = array( + '#title' => $cache['title'], + '#href' => 'admin_menu/flush-cache/' . $name, + '#options' => array( + 'query' => $destination + array('token' => drupal_get_token('admin_menu/flush-cache/' . $name)), + ), + ); + } + + // Add link to toggle developer modules (performance). + $saved_state = variable_get('admin_menu_devel_modules_enabled', NULL); + $links['icon']['toggle-modules'] = array( + '#title' => isset($saved_state) ? t('Enable developer modules') : t('Disable developer modules'), + '#weight' => 88, + '#access' => user_access('administer modules'), + '#href' => 'admin_menu/toggle-modules', + '#options' => array( + 'query' => $destination + array('token' => drupal_get_token('admin_menu/toggle-modules')), + ), + ); + + // Add Devel module menu links. + if (module_exists('devel')) { + $devel_tree = menu_build_tree('devel'); + $devel_links = admin_menu_links_menu($devel_tree); + if (element_get_visible_children($devel_links)) { + $links['icon']['devel'] = array( + '#title' => t('Development'), + '#weight' => 30, + ) + $devel_links; + } + } + + return $links; +} + +/** + * Builds the account links. + * + * @see theme_admin_menu_links() + */ +function admin_menu_links_account() { + $links = array( + '#theme' => 'admin_menu_links', + '#wrapper_attributes' => array('id' => 'admin-menu-account'), + '#weight' => 100, + ); + $links['account'] = array( + '#title' => format_username($GLOBALS['user']), + '#weight' => -99, + '#attributes' => array('class' => array('admin-menu-action', 'admin-menu-account')), + '#href' => 'user/' . $GLOBALS['user']->uid, + ); + $links['logout'] = array( + '#title' => t('Log out'), + '#weight' => -100, + '#attributes' => array('class' => array('admin-menu-action')), + '#href' => 'user/logout', + ); + // Add Devel module switch user links. + $switch_links = module_invoke('devel', 'switch_user_list'); + if (!empty($switch_links) && count($switch_links) > 1) { + foreach ($switch_links as $uid => $link) { + $links['account'][$link['title']] = array( + '#title' => $link['title'], + '#description' => $link['attributes']['title'], + '#href' => $link['href'], + '#options' => array( + 'query' => $link['query'], + 'html' => !empty($link['html']), + ), + ); + } + } + return $links; +} + +/** + * Builds user counter. + * + * @see theme_admin_menu_links() + */ +function admin_menu_links_users() { + $links = array( + '#theme' => 'admin_menu_links', + '#wrapper_attributes' => array('id' => 'admin-menu-users'), + '#weight' => 150, + ); + // Add link to show current authenticated/anonymous users. + $links['user-counter'] = array( + '#title' => admin_menu_get_user_count(), + '#description' => t('Current anonymous / authenticated users'), + '#weight' => -90, + '#attributes' => array('class' => array('admin-menu-action', 'admin-menu-users')), + '#href' => (user_access('administer users') ? 'admin/people/people' : 'user'), + ); + return $links; +} + +/** + * Build search widget. + * + * @see theme_admin_menu_links() + */ +function admin_menu_links_search() { + $links = array( + '#theme' => 'admin_menu_links', + '#wrapper_attributes' => array('id' => 'admin-menu-search'), + '#weight' => 180, + ); + $links['search'] = array( + '#type' => 'textfield', + '#title' => t('Search'), + '#title_display' => 'attribute', + '#attributes' => array( + 'placeholder' => t('Search'), + 'class' => array('admin-menu-search'), + ), + ); + return $links; +} + +/** + * Form builder function for module settings. + */ +function admin_menu_theme_settings() { + $form['admin_menu_margin_top'] = array( + '#type' => 'checkbox', + '#title' => t('Adjust top margin'), + '#default_value' => variable_get('admin_menu_margin_top', 1), + '#description' => t('Shifts the site output down by approximately 20 pixels from the top of the viewport. If disabled, absolute- or fixed-positioned page elements may be covered by the administration menu.'), + ); + $form['admin_menu_position_fixed'] = array( + '#type' => 'checkbox', + '#title' => t('Keep menu at top of page'), + '#default_value' => variable_get('admin_menu_position_fixed', 1), + '#description' => t('Displays the administration menu always at the top of the browser viewport (even when scrolling the page).'), + ); + // @todo Re-confirm this with latest browser versions. + $form['admin_menu_position_fixed']['#description'] .= '
' . t('In some browsers, this setting may result in a malformed page, an invisible cursor, non-selectable elements in forms, or other issues.') . ''; + + $form['advanced'] = array( + '#type' => 'vertical_tabs', + '#title' => t('Advanced settings'), + ); + + $form['plugins'] = array( + '#type' => 'fieldset', + '#title' => t('Plugins'), + '#group' => 'advanced', + ); + $form['plugins']['admin_menu_components'] = array( + '#type' => 'checkboxes', + '#title' => t('Enabled components'), + '#options' => array( + 'admin_menu.icon' => t('Icon menu'), + 'admin_menu.menu' => t('Administration menu'), + 'admin_menu.search' => t('Search bar'), + 'admin_menu.users' => t('User counts'), + 'admin_menu.account' => t('Account links'), + ), + ); + $form['plugins']['admin_menu_components']['#default_value'] = array_keys(array_filter(variable_get('admin_menu_components', $form['plugins']['admin_menu_components']['#options']))); + + $process = element_info_property('checkboxes', '#process', array()); + $form['plugins']['admin_menu_components']['#process'] = array_merge(array('admin_menu_settings_process_components'), $process); + $form['#attached']['js'][] = drupal_get_path('module', 'admin_menu') . '/admin_menu.admin.js'; + + $form['tweaks'] = array( + '#type' => 'fieldset', + '#title' => t('System tweaks'), + '#group' => 'advanced', + ); + $form['tweaks']['admin_menu_tweak_modules'] = array( + '#type' => 'checkbox', + '#title' => t('Collapse module groups on the %modules page', array( + '%modules' => t('Modules'), + '!modules-url' => url('admin/modules'), + )), + '#default_value' => variable_get('admin_menu_tweak_modules', 0), + ); + if (module_exists('util')) { + $form['tweaks']['admin_menu_tweak_modules']['#description'] .= '
' . t('If the Utility module was installed for this purpose, it can be safely disabled and uninstalled.') . ''; + } + $form['tweaks']['admin_menu_tweak_permissions'] = array( + '#type' => 'checkbox', + '#title' => t('Collapse module groups on the %permissions page', array( + '%permissions' => t('Permissions'), + '@permissions-url' => url('admin/people/permissions'), + )), + '#default_value' => variable_get('admin_menu_tweak_permissions', 0), + ); + $form['tweaks']['admin_menu_tweak_tabs'] = array( + '#type' => 'checkbox', + '#title' => t('Move local tasks into menu'), + '#default_value' => variable_get('admin_menu_tweak_tabs', 0), + '#description' => t('Moves the tabs on all pages into the administration menu. Only possible for themes using the CSS classes tabs primary and tabs secondary.'), + ); + + $form['performance'] = array( + '#type' => 'fieldset', + '#title' => t('Performance'), + '#group' => 'advanced', + ); + $form['performance']['admin_menu_cache_client'] = array( + '#type' => 'checkbox', + '#title' => t('Cache menu in client-side browser'), + '#default_value' => variable_get('admin_menu_cache_client', 1), + ); + // Fetch all available modules manually, since module_list() only returns + // currently enabled modules, which makes this setting pointless if developer + // modules are currently disabled. + $all_modules = array(); + $result = db_query("SELECT name, filename, info FROM {system} WHERE type = 'module' ORDER BY name ASC"); + foreach ($result as $module) { + if (file_exists($module->filename)) { + $info = unserialize($module->info); + $all_modules[$module->name] = $info['name']; + } + } + $devel_modules = variable_get('admin_menu_devel_modules', _admin_menu_developer_modules()); + $devel_modules = array_intersect_key($all_modules, array_flip($devel_modules)); + $form['performance']['admin_menu_devel_modules_skip'] = array( + '#type' => 'checkboxes', + '#title' => t('Developer modules to keep enabled'), + '#default_value' => variable_get('admin_menu_devel_modules_skip', array()), + '#options' => $devel_modules, + '#access' => !empty($devel_modules), + '#description' => t('The selected modules will not be disabled when the link %disable-developer-modules below the icon in the menu is invoked.', array( + '%disable-developer-modules' => t('Disable developer modules'), + )), + ); + + return system_settings_form($form); +} + +/** + * #process callback for component plugin form element in admin_menu_theme_settings(). + */ +function admin_menu_settings_process_components($element) { + // Assign 'rel' attributes to all options to achieve a live preview. + // Unfortunately, #states relies on wrapping .form-wrapper classes, so it + // cannot be used here. + foreach ($element['#options'] as $key => $label) { + if (!isset($element[$key]['#attributes']['rel'])) { + $id = preg_replace('/[^a-z]/', '-', $key); + $element[$key]['#attributes']['rel'] = '#' . $id; + } + } + return $element; +} + +/** + * Form validation handler for admin_menu_theme_settings(). + */ +function admin_menu_theme_settings_validate(&$form, &$form_state) { + // Change the configured components to Boolean values. + foreach ($form_state['values']['admin_menu_components'] as $component => &$enabled) { + $enabled = (bool) $enabled; + } +} + +/** + * Implementation of hook_form_FORM_ID_alter(). + * + * Extends Devel module with Administration menu developer settings. + */ +function _admin_menu_form_devel_admin_settings_alter(&$form, $form_state) { + // Shift system_settings_form buttons. + $weight = isset($form['buttons']['#weight']) ? $form['buttons']['#weight'] : 0; + $form['buttons']['#weight'] = $weight + 1; + + $form['admin_menu'] = array( + '#type' => 'fieldset', + '#title' => t('Administration menu settings'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + $display_options = array('mid', 'weight', 'pid'); + $display_options = array(0 => t('None'), 'mlid' => t('Menu link ID'), 'weight' => t('Weight'), 'plid' => t('Parent link ID')); + $form['admin_menu']['admin_menu_display'] = array( + '#type' => 'radios', + '#title' => t('Display additional data for each menu item'), + '#default_value' => variable_get('admin_menu_display', 0), + '#options' => $display_options, + '#description' => t('Display the selected items next to each menu item link.'), + ); + $form['admin_menu']['admin_menu_show_all'] = array( + '#type' => 'checkbox', + '#title' => t('Display all menu items'), + '#default_value' => variable_get('admin_menu_show_all', 0), + '#description' => t('If enabled, all menu items are displayed regardless of your site permissions. Note: Do not enable on a production site.'), + ); +} + +/** + * Menu callback; Enable/disable developer modules. + * + * This can save up to 150ms on each uncached page request. + */ +function admin_menu_toggle_modules() { + if (!isset($_GET['token']) || !drupal_valid_token($_GET['token'], current_path())) { + return MENU_ACCESS_DENIED; + } + + $rebuild = FALSE; + $saved_state = variable_get('admin_menu_devel_modules_enabled', NULL); + if (isset($saved_state)) { + // Re-enable modules that were enabled before. + module_enable($saved_state); + variable_del('admin_menu_devel_modules_enabled'); + drupal_set_message(t('Enabled these modules: !module-list.', array('!module-list' => implode(', ', $saved_state)))); + $rebuild = TRUE; + } + else { + // Allow site admins to override this variable via settings.php. + $devel_modules = variable_get('admin_menu_devel_modules', _admin_menu_developer_modules()); + // Store currently enabled modules in a variable. + $devel_modules = array_intersect(module_list(FALSE, FALSE), $devel_modules); + $devel_modules = array_diff($devel_modules, variable_get('admin_menu_devel_modules_skip', array())); + if (!empty($devel_modules)) { + variable_set('admin_menu_devel_modules_enabled', $devel_modules); + // Disable developer modules. + module_disable($devel_modules); + drupal_set_message(t('Disabled these modules: !module-list.', array('!module-list' => implode(', ', $devel_modules)))); + $rebuild = TRUE; + } + else { + drupal_set_message(t('No developer modules are enabled.')); + } + } + if ($rebuild) { + // Make sure everything is rebuilt, basically a combination of the calls + // from system_modules() and system_modules_submit(). + drupal_theme_rebuild(); + menu_rebuild(); + cache_clear_all('schema', 'cache'); + cache_clear_all(); + drupal_clear_css_cache(); + drupal_clear_js_cache(); + // Synchronize to catch any actions that were added or removed. + actions_synchronize(); + // Finally, flush admin_menu's cache. + admin_menu_flush_caches(); + } + drupal_goto(); +} + +/** + * Helper function to return a default list of developer modules. + */ +function _admin_menu_developer_modules() { + return array( + 'admin_devel', + 'cache_disable', + 'coder', + 'content_copy', + 'context_ui', + 'debug', + 'delete_all', + 'demo', + 'devel', + 'devel_node_access', + 'devel_themer', + 'field_ui', + 'fontyourface_ui', + 'form_controller', + 'imagecache_ui', + 'journal', + 'l10n_client', + 'l10n_update', + 'macro', + 'rules_admin', + 'stringoverrides', + 'trace', + 'upgrade_status', + 'user_display_ui', + 'util', + 'views_ui', + 'views_theme_wizard', + ); +} + +/** + * Flush all caches or a specific one. + * + * @param $name + * (optional) Name of cache to flush. + */ +function admin_menu_flush_cache($name = NULL) { + if (!isset($_GET['token']) || !drupal_valid_token($_GET['token'], current_path())) { + return MENU_ACCESS_DENIED; + } + if (isset($name)) { + $caches = module_invoke_all('admin_menu_cache_info'); + if (!isset($caches[$name])) { + return MENU_NOT_FOUND; + } + } + else { + $caches[$name] = array( + 'title' => t('Every'), + 'callback' => 'drupal_flush_all_caches', + ); + } + // Pass the cache to flush forward to the callback. + $function = $caches[$name]['callback']; + $function($name); + + drupal_set_message(t('!title cache cleared.', array('!title' => $caches[$name]['title']))); + + // The JavaScript injects a destination request parameter pointing to the + // originating page, so the user is redirected back to that page. Without + // destination parameter, the redirect ends on the front page. + drupal_goto(); +} + +/** + * Implements hook_admin_menu_cache_info(). + */ +function admin_menu_admin_menu_cache_info() { + $caches['admin_menu'] = array( + 'title' => t('Administration menu'), + 'callback' => '_admin_menu_flush_cache', + ); + return $caches; +} + +/** + * Implements hook_admin_menu_cache_info() on behalf of System module. + */ +function system_admin_menu_cache_info() { + $caches = array( + 'assets' => t('CSS and JavaScript'), + 'cache' => t('Page and else'), + 'menu' => t('Menu'), + 'registry' => t('Class registry'), + 'theme' => t('Theme registry'), + ); + foreach ($caches as $name => $cache) { + $caches[$name] = array( + 'title' => $cache, + 'callback' => '_admin_menu_flush_cache', + ); + } + return $caches; +} + +/** + * Implements hook_admin_menu_cache_info() on behalf of Update module. + */ +function update_admin_menu_cache_info() { + $caches['update'] = array( + 'title' => t('Update data'), + 'callback' => '_update_cache_clear', + ); + return $caches; +} + +/** + * Flush all caches or a specific one. + * + * @param $name + * (optional) Name of cache to flush. + * + * @see system_admin_menu_cache_info() + */ +function _admin_menu_flush_cache($name = NULL) { + switch ($name) { + case 'admin_menu': + admin_menu_flush_caches(); + break; + + case 'menu': + menu_rebuild(); + break; + + case 'registry': + registry_rebuild(); + // Fall-through to clear cache tables, since registry information is + // usually the base for other data that is cached (e.g. SimpleTests). + case 'cache': + // Don't clear cache_form - in-progress form submissions may break. + // Ordered so clearing the page cache will always be the last action. + // @see drupal_flush_all_caches() + $core = array('cache', 'cache_bootstrap', 'cache_filter', 'cache_page'); + $cache_tables = array_merge(module_invoke_all('flush_caches'), $core); + foreach ($cache_tables as $table) { + cache_clear_all('*', $table, TRUE); + } + break; + + case 'assets': + // Change query-strings on css/js files to enforce reload for all users. + _drupal_flush_css_js(); + + drupal_clear_css_cache(); + drupal_clear_js_cache(); + + // Clear the page cache, since cached HTML pages might link to old CSS and + // JS aggregates. + cache_clear_all('*', 'cache_page', TRUE); + break; + + case 'theme': + system_rebuild_theme_data(); + drupal_theme_rebuild(); + break; + } +} + +/** + * Preprocesses variables for theme_admin_menu_icon(). + */ +function template_preprocess_admin_menu_icon(&$variables) { + // Image source might have been passed in as theme variable. + if (!isset($variables['src'])) { + if (theme_get_setting('toggle_favicon')) { + $variables['src'] = theme_get_setting('favicon'); + } + else { + $variables['src'] = base_path() . 'misc/favicon.ico'; + } + } + // Strip the protocol without delimiters for transient HTTP/HTTPS support. + // Since the menu is cached on the server-side and client-side, the cached + // version might contain a HTTP link, whereas the actual page is on HTTPS. + // Relative paths will work fine, but theme_get_setting() returns an + // absolute URI. + $variables['src'] = preg_replace('@^https?:@', '', $variables['src']); + $variables['src'] = check_plain($variables['src']); + $variables['alt'] = t('Home'); +} + +/** + * Renders an icon to display in the administration menu. + * + * @ingroup themeable + */ +function theme_admin_menu_icon($variables) { + return '' . $variables['alt'] . ''; +} + diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/admin_menu.info --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/admin_menu.info Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,16 @@ +name = Administration menu +description = "Provides a dropdown menu to most administrative tasks and other common destinations (to users with the proper permissions)." +package = Administration +core = 7.x +configure = admin/config/administration/admin_menu +; Requires menu_build_tree() conditions; available after 7.10. +; @see http://drupal.org/node/1025582 +dependencies[] = system (>7.10) +files[] = tests/admin_menu.test + +; Information added by drupal.org packaging script on 2013-01-31 +version = "7.x-3.0-rc4" +core = "7.x" +project = "admin_menu" +datestamp = "1359651687" + diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/admin_menu.install --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/admin_menu.install Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,122 @@ +fields(array('weight' => 100)) + ->condition('type', 'module') + ->condition('name', 'admin_menu') + ->execute(); +} + +/** + * Implements hook_uninstall(). + */ +function admin_menu_uninstall() { + // Delete variables. + variable_del('admin_menu_components'); + variable_del('admin_menu_devel_modules'); + variable_del('admin_menu_devel_modules_enabled'); + variable_del('admin_menu_devel_modules_skip'); + variable_del('admin_menu_margin_top'); + variable_del('admin_menu_position_fixed'); + variable_del('admin_menu_tweak_modules'); + variable_del('admin_menu_tweak_tabs'); + variable_del('admin_menu_show_all'); + variable_del('admin_menu_display'); + variable_del('admin_menu_cache_server'); + variable_del('admin_menu_cache_client'); +} + +/** + * Ensure that admin_menu is rebuilt after upgrading to D6. + */ +function admin_menu_update_6000() { + // Drop the {admin_menu} table in admin_menu_update_6000() on sites that used + // one of the later patches in #132524. + if (db_table_exists('admin_menu')) { + db_drop_table('admin_menu'); + } +} + +/** + * Wipe and rebuild so we can switch the icon path to . + */ +function admin_menu_update_6001() { + db_delete('menu_links')->condition('module', 'admin_menu')->execute(); + menu_cache_clear('admin_menu'); +} + +/** + * Add {cache_admin_menu} table. + */ +function admin_menu_update_7300() { + if (!db_table_exists('cache_admin_menu')) { + $schema = drupal_get_schema_unprocessed('system', 'cache'); + db_create_table('cache_admin_menu', $schema); + } +} + +/** + * Increase the module weight. + * + * @see admin_menu_install() + */ +function admin_menu_update_7302() { + db_update('system') + ->fields(array('weight' => 100)) + ->condition('type', 'module') + ->condition('name', 'admin_menu') + ->execute(); +} + +/** + * Remove local tasks from {menu_links} table. + */ +function admin_menu_update_7303() { + db_delete('menu_router') + ->condition('path', 'admin/%', 'LIKE') + ->condition('type', MENU_IS_LOCAL_TASK, '&') + ->execute(); +} + +/** + * Remove obsolete 'admin_menu' menu and all orphan links in it. + */ +function admin_menu_update_7304() { + // Remove the custom menu used by 6.x-1.x. + if (db_table_exists('menu_custom')) { + db_delete('menu_custom')->condition('menu_name', 'admin_menu')->execute(); + } + + // 6.x-1.x cloned the entire link structure below the path 'admin' into a + // separate 'menu_name' "admin_menu" with 'module' "admin_menu". 6.x-3.x and + // early alpha versions of 7.x-3.x still did something similar. All of these + // records are obsolete. Removal of the 'module' records (without different + // menu_name) is particularly important, since they would otherwise appear + // as duplicate links. + db_delete('menu_links') + ->condition(db_or() + ->condition('module', 'admin_menu') + ->condition('menu_name', 'admin_menu') + ) + ->execute(); +} diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/admin_menu.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/admin_menu.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,397 @@ +(function($) { + +Drupal.admin = Drupal.admin || {}; +Drupal.admin.behaviors = Drupal.admin.behaviors || {}; +Drupal.admin.hashes = Drupal.admin.hashes || {}; + +/** + * Core behavior for Administration menu. + * + * Test whether there is an administration menu is in the output and execute all + * registered behaviors. + */ +Drupal.behaviors.adminMenu = { + attach: function (context, settings) { + // Initialize settings. + settings.admin_menu = $.extend({ + suppress: false, + margin_top: false, + position_fixed: false, + tweak_modules: false, + tweak_permissions: false, + tweak_tabs: false, + destination: '', + basePath: settings.basePath, + hash: 0, + replacements: {} + }, settings.admin_menu || {}); + // Check whether administration menu should be suppressed. + if (settings.admin_menu.suppress) { + return; + } + var $adminMenu = $('#admin-menu:not(.admin-menu-processed)', context); + // Client-side caching; if administration menu is not in the output, it is + // fetched from the server and cached in the browser. + if (!$adminMenu.length && settings.admin_menu.hash) { + Drupal.admin.getCache(settings.admin_menu.hash, function (response) { + if (typeof response == 'string' && response.length > 0) { + $('body', context).append(response); + } + var $adminMenu = $('#admin-menu:not(.admin-menu-processed)', context); + // Apply our behaviors. + Drupal.admin.attachBehaviors(context, settings, $adminMenu); + // Allow resize event handlers to recalculate sizes/positions. + $(window).triggerHandler('resize'); + }); + } + // If the menu is in the output already, this means there is a new version. + else { + // Apply our behaviors. + Drupal.admin.attachBehaviors(context, settings, $adminMenu); + } + } +}; + +/** + * Collapse fieldsets on Modules page. + */ +Drupal.behaviors.adminMenuCollapseModules = { + attach: function (context, settings) { + if (settings.admin_menu.tweak_modules) { + $('#system-modules fieldset:not(.collapsed)', context).addClass('collapsed'); + } + } +}; + +/** + * Collapse modules on Permissions page. + */ +Drupal.behaviors.adminMenuCollapsePermissions = { + attach: function (context, settings) { + if (settings.admin_menu.tweak_permissions) { + // Freeze width of first column to prevent jumping. + $('#permissions th:first', context).css({ width: $('#permissions th:first', context).width() }); + // Attach click handler. + $modules = $('#permissions tr:has(td.module)', context).once('admin-menu-tweak-permissions', function () { + var $module = $(this); + $module.bind('click.admin-menu', function () { + // @todo Replace with .nextUntil() in jQuery 1.4. + $module.nextAll().each(function () { + var $row = $(this); + if ($row.is(':has(td.module)')) { + return false; + } + $row.toggleClass('element-hidden'); + }); + }); + }); + // Collapse all but the targeted permission rows set. + if (window.location.hash.length) { + $modules = $modules.not(':has(' + window.location.hash + ')'); + } + $modules.trigger('click.admin-menu'); + } + } +}; + +/** + * Apply margin to page. + * + * Note that directly applying marginTop does not work in IE. To prevent + * flickering/jumping page content with client-side caching, this is a regular + * Drupal behavior. + */ +Drupal.behaviors.adminMenuMarginTop = { + attach: function (context, settings) { + if (!settings.admin_menu.suppress && settings.admin_menu.margin_top) { + $('body:not(.admin-menu)', context).addClass('admin-menu'); + } + } +}; + +/** + * Retrieve content from client-side cache. + * + * @param hash + * The md5 hash of the content to retrieve. + * @param onSuccess + * A callback function invoked when the cache request was successful. + */ +Drupal.admin.getCache = function (hash, onSuccess) { + if (Drupal.admin.hashes.hash !== undefined) { + return Drupal.admin.hashes.hash; + } + $.ajax({ + cache: true, + type: 'GET', + dataType: 'text', // Prevent auto-evaluation of response. + global: false, // Do not trigger global AJAX events. + url: Drupal.settings.admin_menu.basePath.replace(/admin_menu/, 'js/admin_menu/cache/' + hash), + success: onSuccess, + complete: function (XMLHttpRequest, status) { + Drupal.admin.hashes.hash = status; + } + }); +}; + +/** + * TableHeader callback to determine top viewport offset. + * + * @see toolbar.js + */ +Drupal.admin.height = function() { + var $adminMenu = $('#admin-menu'); + var height = $adminMenu.outerHeight(); + // In IE, Shadow filter adds some extra height, so we need to remove it from + // the returned height. + if ($adminMenu.css('filter') && $adminMenu.css('filter').match(/DXImageTransform\.Microsoft\.Shadow/)) { + height -= $adminMenu.get(0).filters.item("DXImageTransform.Microsoft.Shadow").strength; + } + return height; +}; + +/** + * @defgroup admin_behaviors Administration behaviors. + * @{ + */ + +/** + * Attach administrative behaviors. + */ +Drupal.admin.attachBehaviors = function (context, settings, $adminMenu) { + if ($adminMenu.length) { + $adminMenu.addClass('admin-menu-processed'); + $.each(Drupal.admin.behaviors, function() { + this(context, settings, $adminMenu); + }); + } +}; + +/** + * Apply 'position: fixed'. + */ +Drupal.admin.behaviors.positionFixed = function (context, settings, $adminMenu) { + if (settings.admin_menu.position_fixed) { + $adminMenu.addClass('admin-menu-position-fixed'); + $adminMenu.css('position', 'fixed'); + } +}; + +/** + * Move page tabs into administration menu. + */ +Drupal.admin.behaviors.pageTabs = function (context, settings, $adminMenu) { + if (settings.admin_menu.tweak_tabs) { + var $tabs = $(context).find('ul.tabs.primary'); + $adminMenu.find('#admin-menu-wrapper > ul').eq(1) + .append($tabs.find('li').addClass('admin-menu-tab')); + $(context).find('ul.tabs.secondary') + .appendTo('#admin-menu-wrapper > ul > li.admin-menu-tab.active') + .removeClass('secondary'); + $tabs.remove(); + } +}; + +/** + * Perform dynamic replacements in cached menu. + */ +Drupal.admin.behaviors.replacements = function (context, settings, $adminMenu) { + for (var item in settings.admin_menu.replacements) { + $(item, $adminMenu).html(settings.admin_menu.replacements[item]); + } +}; + +/** + * Inject destination query strings for current page. + */ +Drupal.admin.behaviors.destination = function (context, settings, $adminMenu) { + if (settings.admin_menu.destination) { + $('a.admin-menu-destination', $adminMenu).each(function() { + this.search += (!this.search.length ? '?' : '&') + Drupal.settings.admin_menu.destination; + }); + } +}; + +/** + * Apply JavaScript-based hovering behaviors. + * + * @todo This has to run last. If another script registers additional behaviors + * it will not run last. + */ +Drupal.admin.behaviors.hover = function (context, settings, $adminMenu) { + // Hover emulation for IE 6. + if ($.browser.msie && parseInt(jQuery.browser.version) == 6) { + $('li', $adminMenu).hover( + function () { + $(this).addClass('iehover'); + }, + function () { + $(this).removeClass('iehover'); + } + ); + } + + // Delayed mouseout. + $('li.expandable', $adminMenu).hover( + function () { + // Stop the timer. + clearTimeout(this.sfTimer); + // Display child lists. + $('> ul', this) + .css({left: 'auto', display: 'block'}) + // Immediately hide nephew lists. + .parent().siblings('li').children('ul').css({left: '-999em', display: 'none'}); + }, + function () { + // Start the timer. + var uls = $('> ul', this); + this.sfTimer = setTimeout(function () { + uls.css({left: '-999em', display: 'none'}); + }, 400); + } + ); +}; + +/** + * Apply the search bar functionality. + */ +Drupal.admin.behaviors.search = function (context, settings, $adminMenu) { + // @todo Add a HTML ID. + var $input = $('input.admin-menu-search', $adminMenu); + // Initialize the current search needle. + var needle = $input.val(); + // Cache of all links that can be matched in the menu. + var links; + // Minimum search needle length. + var needleMinLength = 2; + // Append the results container. + var $results = $('
').insertAfter($input); + + /** + * Executes the search upon user input. + */ + function keyupHandler() { + var matches, $html, value = $(this).val(); + // Only proceed if the search needle has changed. + if (value !== needle) { + needle = value; + // Initialize the cache of menu links upon first search. + if (!links && needle.length >= needleMinLength) { + // @todo Limit to links in dropdown menus; i.e., skip menu additions. + links = buildSearchIndex($adminMenu.find('li:not(.admin-menu-action, .admin-menu-action li) > a')); + } + // Empty results container when deleting search text. + if (needle.length < needleMinLength) { + $results.empty(); + } + // Only search if the needle is long enough. + if (needle.length >= needleMinLength && links) { + matches = findMatches(needle, links); + // Build the list in a detached DOM node. + $html = buildResultsList(matches); + // Display results. + $results.empty().append($html); + } + } + } + + /** + * Builds the search index. + */ + function buildSearchIndex($links) { + return $links + .map(function () { + var text = (this.textContent || this.innerText); + // Skip menu entries that do not contain any text (e.g., the icon). + if (typeof text === 'undefined') { + return; + } + return { + text: text, + textMatch: text.toLowerCase(), + element: this + }; + }); + } + + /** + * Searches the index for a given needle and returns matching entries. + */ + function findMatches(needle, links) { + var needleMatch = needle.toLowerCase(); + // Select matching links from the cache. + return $.grep(links, function (link) { + return link.textMatch.indexOf(needleMatch) !== -1; + }); + } + + /** + * Builds the search result list in a detached DOM node. + */ + function buildResultsList(matches) { + var $html = $(''; + } + return $output; +} + +/** + * Function used by uasort to sort structured arrays by #weight AND #title. + */ +function admin_menu_element_sort($a, $b) { + // @see element_sort() + $a_weight = isset($a['#weight']) ? $a['#weight'] : 0; + $b_weight = isset($b['#weight']) ? $b['#weight'] : 0; + if ($a_weight == $b_weight) { + // @see element_sort_by_title() + $a_title = isset($a['#title']) ? $a['#title'] : ''; + $b_title = isset($b['#title']) ? $b['#title'] : ''; + return strnatcasecmp($a_title, $b_title); + } + return ($a_weight < $b_weight) ? -1 : 1; +} + +/** + * Implements hook_translated_menu_link_alter(). + * + * Here is where we make changes to links that need dynamic information such + * as the current page path or the number of users. + */ +function admin_menu_translated_menu_link_alter(&$item, $map) { + global $user, $base_url; + static $access_all; + + if ($item['menu_name'] != 'admin_menu') { + return; + } + + // Check whether additional development output is enabled. + if (!isset($access_all)) { + $access_all = variable_get('admin_menu_show_all', 0) && module_exists('devel'); + } + // Prepare links that would not be displayed normally. + if ($access_all && !$item['access']) { + $item['access'] = TRUE; + // Prepare for http://drupal.org/node/266596 + if (!isset($item['localized_options'])) { + _menu_item_localize($item, $map, TRUE); + } + } + + // Don't waste cycles altering items that are not visible + if (!$item['access']) { + return; + } + + // Add developer information to all links, if enabled. + if ($extra = variable_get('admin_menu_display', 0)) { + $item['title'] .= ' ' . $extra[0] . ': ' . $item[$extra]; + } +} + +/** + * Implements hook_flush_caches(). + * + * Flushes client-side caches. + * + * @param int $uid + * (optional) A user ID to limit the cache flush to. + */ +function admin_menu_flush_caches($uid = NULL) { + // A call to menu_rebuild() will trigger potentially thousands of calls into + // menu_link_save(), for which admin_menu has to implement the corresponding + // CRUD hooks, in order to take up any menu link changes, since any menu link + // change could affect the admin menu (which essentially is an aggregate) and + // since there is no other way to get notified about stale caches. The cache + // only needs to be flushed once though, so we prevent a ton of needless + // subsequent calls with this static. + // @see http://drupal.org/node/918538 + $was_flushed = &drupal_static(__FUNCTION__, array()); + // $uid can be NULL. PHP automatically converts that into '' (empty string), + // which is different to uid 0 (zero). + if (isset($was_flushed[$uid])) { + return; + } + $was_flushed[$uid] = TRUE; + + $cid = 'admin_menu:'; + if (isset($uid)) { + $cid .= $uid . ':'; + } + // Flush cached output of admin_menu. + cache_clear_all($cid, 'cache_menu', TRUE); + // Flush client-side cache hashes. + drupal_static_reset('admin_menu_cache_get'); + // db_table_exists() required for SimpleTest. + if (db_table_exists('cache_admin_menu')) { + cache_clear_all(isset($uid) ? $cid : '*', 'cache_admin_menu', TRUE); + } +} + +/** + * Implements hook_form_alter(). + */ +function admin_menu_form_alter(&$form, &$form_state, $form_id) { + $global_flush_ids = array( + 'admin_menu_theme_settings' => 1, + // Update links for clean/non-clean URLs. + 'system_clean_url_settings' => 1, + // Incorporate changed user permissions. + 'user_admin_permissions' => 1, + // Removing a role potentially means less permissions. + 'user_admin_role_delete_confirm' => 1, + // User name and roles may be changed on the user account form. + 'user_profile_form' => 1, + ); + if (isset($global_flush_ids[$form_id])) { + $form['#submit'][] = 'admin_menu_form_alter_flush_cache_submit'; + + // Optionally limit the cache flush to a certain user ID. + $form_state['admin_menu_uid'] = NULL; + if ($form_id == 'user_profile_form') { + $form_state['admin_menu_uid'] = $form_state['user']->uid; + } + } + + // UX: Add a confirmation to the permissions form to ask the user whether to + // auto-enable the 'access administration menu' permission along with + // 'access administration pages'. + if ($form_id == 'user_admin_permissions') { + $form['#attached']['js'][] = drupal_get_path('module', 'admin_menu') . '/admin_menu.admin.js'; + } +} + +/** + * Form submission handler to flush Administration menu caches. + */ +function admin_menu_form_alter_flush_cache_submit($form, &$form_state) { + admin_menu_flush_caches($form_state['admin_menu_uid']); +} + +/** + * Implements hook_form_FORM_ID_alter(). + * + * Extends Devel module with Administration menu developer settings. + */ +function admin_menu_form_devel_admin_settings_alter(&$form, &$form_state) { + form_load_include($form_state, 'inc', 'admin_menu'); + _admin_menu_form_devel_admin_settings_alter($form, $form_state); +} diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/admin_menu.uid1.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/admin_menu.uid1.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,9 @@ + +/** + * @file + * Administration menu color override for uid1. + */ + +#admin-menu li.admin-menu-account > a { + background: #911 url(images/bkg-red.png) bottom left repeat-x; +} diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/admin_menu_toolbar/admin_menu_toolbar.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/admin_menu_toolbar/admin_menu_toolbar.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,145 @@ + +/** + * @file + * Toolbar style for Administration menu. + * + * Important: We cannot re-use toolbar.png from Toolbar module, since we cannot + * reliably determine the path to it. + * + * @todo Separate shortcut functionality into own module/widget. + */ + +/* Adjust margin/height */ +html body.admin-menu { + margin-top: 29px !important; +} +html body.admin-menu-with-shortcuts { + margin-top: 65px !important; +} +/* Displace the core Toolbar, if concurrently output. */ +body div#toolbar.toolbar { + top: 30px; +} + +/** + * Base styles. + * + * We use a keyword for the toolbar font size to make it display consistently + * across different themes, while still allowing browsers to resize the text. + */ +#admin-menu { + font: normal small "Lucida Grande", Verdana, sans-serif; + -moz-box-shadow: 0 -10px 20px 13px #000; + -webkit-box-shadow: 0 -10px 20px 13px #000; + box-shadow: 0 -10px 20px 13px #000; + right: 0; + width: auto; +} +#admin-menu-wrapper { + font-size: .846em; + padding: 5px 10px 0; +} + +#admin-menu .dropdown a { + color: #fafafa; +} + +/* Remove border from all lists and actions */ +#admin-menu .dropdown .admin-menu-action a { + border-left: 0; +} +#admin-menu .dropdown .admin-menu-icon > a { + padding: 2px 10px 3px; +} + +/** + * Administration menu. + */ +#admin-menu .dropdown .admin-menu-icon > a span { + vertical-align: text-bottom; + width: 11px; + height: 14px; + display: block; + background: url(toolbar.png) no-repeat 0 -45px; + text-indent: -9999px; +} +#admin-menu > div > .dropdown > li > a { + border-right: 0; + margin-bottom: 4px; + padding: 2px 10px 3px; +} +#admin-menu .dropdown .admin-menu-toolbar-category > a, +#admin-menu .dropdown .admin-menu-action > a { + border-radius: 10px; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; +} +#admin-menu .dropdown .admin-menu-toolbar-category > a.active-trail { + text-shadow: #333 0 1px 0; + background: url(toolbar.png) 0 0 repeat-x; +} +#admin-menu .dropdown .admin-menu-toolbar-category > a:hover { + background-color: #444; +} +#admin-menu .dropdown .admin-menu-tab a { + border-right: 0; +} +#admin-menu .dropdown li li.expandable ul { + margin: -22px 0 0 160px; +} + +/** + * Shortcuts toggle. + */ +#admin-menu .shortcut-toggle { + cursor: pointer; + background: url(toolbar.png) 0 -20px no-repeat; + display: block; + float: right; + margin: 0 0 0 1.3em; + text-indent: -9999px; + overflow: hidden; + width: 25px; + height: 25px; +} +#admin-menu .shortcut-toggle:focus, +#admin-menu .shortcut-toggle:hover { + background-position: -50px -20px; +} +#admin-menu .shortcut-toggle.active { + background-position: -25px -20px; +} +#admin-menu .shortcut-toggle.active:focus, +#admin-menu .shortcut-toggle.active:hover { + background-position: -75px -20px; +} + +/** + * Shortcuts widget. + */ +#admin-menu .shortcut-toolbar { + background-color: #666; + clear: both; + display: none; + margin: 0 -10px; + overflow: hidden; + /* Align with icon; @see shortcut.css */ + padding-left: 5px; +} +#admin-menu .shortcut-toolbar.active { + display: block; +} +/* Override theme list style; @see shortcut.css */ +#admin-menu .shortcut-toolbar ul { + margin: 0; +} +/* @see toolbar.css */ +#admin-menu .shortcut-toolbar li { + float: left; + list-style-image: none; + list-style-type: none; +} +#admin-menu .shortcut-toolbar a { + display: block; +} + diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/admin_menu_toolbar/admin_menu_toolbar.info --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/admin_menu_toolbar/admin_menu_toolbar.info Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,12 @@ +name = Administration menu Toolbar style +description = A better Toolbar. +package = Administration +core = 7.x +dependencies[] = admin_menu + +; Information added by drupal.org packaging script on 2013-01-31 +version = "7.x-3.0-rc4" +core = "7.x" +project = "admin_menu" +datestamp = "1359651687" + diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/admin_menu_toolbar/admin_menu_toolbar.install --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/admin_menu_toolbar/admin_menu_toolbar.install Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,37 @@ +fields(array('weight' => 101)) + ->condition('type', 'module') + ->condition('name', 'admin_menu_toolbar') + ->execute(); +} + +/** + * Set module weight to a value higher than admin_menu. + * + * At this point, admin_menu should have a weight of 100. To account for + * customized weights, we increase the weight relatively. + * + * @see admin_menu_toolbar_install() + */ +function admin_menu_toolbar_update_6300() { + $weight = db_query("SELECT weight FROM {system} WHERE type = 'module' AND name = 'admin_menu'")->fetchField(); + $weight++; + db_update('system') + ->fields(array('weight' => $weight)) + ->condition('type', 'module') + ->condition('name', 'admin_menu_toolbar') + ->execute(); +} + diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/admin_menu_toolbar/admin_menu_toolbar.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/admin_menu_toolbar/admin_menu_toolbar.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,56 @@ +(function($) { + +Drupal.admin = Drupal.admin || {}; +Drupal.admin.behaviors = Drupal.admin.behaviors || {}; + +/** + * @ingroup admin_behaviors + * @{ + */ + +/** + * Apply active trail highlighting based on current path. + * + * @todo Not limited to toolbar; move into core? + */ +Drupal.admin.behaviors.toolbarActiveTrail = function (context, settings, $adminMenu) { + if (settings.admin_menu.toolbar && settings.admin_menu.toolbar.activeTrail) { + $adminMenu.find('> div > ul > li > a[href="' + settings.admin_menu.toolbar.activeTrail + '"]').addClass('active-trail'); + } +}; + +/** + * Toggles the shortcuts bar. + */ +Drupal.admin.behaviors.shortcutToggle = function (context, settings, $adminMenu) { + var $shortcuts = $adminMenu.find('.shortcut-toolbar'); + if (!$shortcuts.length) { + return; + } + var storage = window.localStorage || false; + var storageKey = 'Drupal.admin_menu.shortcut'; + var $body = $(context).find('body'); + var $toggle = $adminMenu.find('.shortcut-toggle'); + $toggle.click(function () { + var enable = !$shortcuts.hasClass('active'); + $shortcuts.toggleClass('active', enable); + $toggle.toggleClass('active', enable); + if (settings.admin_menu.margin_top) { + $body.toggleClass('admin-menu-with-shortcuts', enable); + } + // Persist toggle state across requests. + storage && enable ? storage.setItem(storageKey, 1) : storage.removeItem(storageKey); + this.blur(); + return false; + }); + + if (!storage || storage.getItem(storageKey)) { + $toggle.trigger('click'); + } +}; + +/** + * @} End of "ingroup admin_behaviors". + */ + +})(jQuery); diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/admin_menu_toolbar/admin_menu_toolbar.module --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/admin_menu_toolbar/admin_menu_toolbar.module Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,118 @@ + TRUE); + + $attached['css'][$path . '/admin_menu_toolbar.css'] = $options; + $attached['js'][$path . '/admin_menu_toolbar.js'] = $options; + + // @todo Stop-gap fix until cached rendering is resolved. + // @see http://drupal.org/node/1567622 + if (module_exists('shortcut')) { + $attached['css'][drupal_get_path('module', 'shortcut') . '/shortcut.css'] = $options; + } + + $settings = array(); + // Add current path to support menu item highlighting. + // @todo Compile real active trail here? + $args = explode('/', $_GET['q']); + if ($args[0] == 'admin' && !empty($args[1])) { + $settings['activeTrail'] = url($args[0] . '/' . $args[1]); + } + elseif (drupal_is_front_page()) { + $settings['activeTrail'] = url(''); + } + + $attached['js'][] = array( + 'data' => array('admin_menu' => array('toolbar' => $settings)), + 'type' => 'setting', + ); +} + +/** + * Implements hook_admin_menu_output_build(). + */ +function admin_menu_toolbar_admin_menu_output_build(&$content) { + if (empty($content['#components']['shortcut.links']) && !$content['#complete']) { + return; + } + // Add shortcuts toggle. + $content['shortcut-toggle'] = array( + '#access' => module_exists('shortcut'), + '#weight' => -200, + '#type' => 'link', + '#title' => t('Show shortcuts'), + '#href' => '', + '#options' => array( + 'attributes' => array('class' => 'shortcut-toggle'), + ), + ); + + // Add shortcuts bar. + $content['shortcut'] = array( + '#access' => module_exists('shortcut'), + '#weight' => 200, + '#prefix' => '
', + '#suffix' => '
', + ); + $content['shortcut']['shortcuts'] = array( + // Shortcut module's CSS relies on Toolbar module's markup. + // @see http://drupal.org/node/1217038 + '#prefix' => '
', + '#suffix' => '
', + // @todo Links may contain .active-trail classes. + '#pre_render' => array('shortcut_toolbar_pre_render'), + ); +} + +/** + * Implements hook_admin_menu_output_alter(). + */ +function admin_menu_toolbar_admin_menu_output_alter(&$content) { + // Add a class to top-level items for styling. + if (isset($content['menu'])) { + foreach (element_children($content['menu']) as $link) { + $content['menu'][$link]['#attributes']['class'][] = 'admin-menu-toolbar-category'; + } + } + + // Alter icon. + if (isset($content['icon'])) { + unset($content['icon']['icon']['#theme']); + $content['icon']['icon']['#title'] = '' . t('Home') . ''; + $content['icon']['icon']['#attributes']['class'][] = 'admin-menu-toolbar-category'; + } + + // Alter user account link. + if (isset($content['account'])) { + $content['account']['account']['#title'] = t('Hello @username', array('@username' => $content['account']['account']['#title'])); + $content['account']['account']['#options']['html'] = TRUE; + } +} + diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/admin_menu_toolbar/toolbar.png Binary file modules/admin_menu/admin_menu_toolbar/toolbar.png has changed diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/images/arrow-rtl.png Binary file modules/admin_menu/images/arrow-rtl.png has changed diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/images/arrow.png Binary file modules/admin_menu/images/arrow.png has changed diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/images/bkg-red.png Binary file modules/admin_menu/images/bkg-red.png has changed diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/images/bkg.png Binary file modules/admin_menu/images/bkg.png has changed diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/images/bkg_tab.png Binary file modules/admin_menu/images/bkg_tab.png has changed diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/images/icon_users.png Binary file modules/admin_menu/images/icon_users.png has changed diff -r d72257b2ddc2 -r a75ead649730 modules/admin_menu/tests/admin_menu.test --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/admin_menu/tests/admin_menu.test Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,520 @@ + 'access administration pages', + 'admin_menu' => 'access administration menu', + ); + + function setUp() { + // Enable admin menu module and any other modules. + $modules = func_get_args(); + $modules = isset($modules[0]) ? $modules[0] : $modules; + $modules[] = 'admin_menu'; + parent::setUp($modules); + + // Disable client-side caching. + variable_set('admin_menu_cache_client', FALSE); + // Disable Clean URLs to ensure drupal.org testbot compatibility. + variable_set('clean_url', 0); + } + + /** + * Check that an element exists in HTML markup. + * + * @param $xpath + * An XPath expression. + * @param array $arguments + * (optional) An associative array of XPath replacement tokens to pass to + * DrupalWebTestCase::buildXPathQuery(). + * @param $message + * The message to display along with the assertion. + * @param $group + * The type of assertion - examples are "Browser", "PHP". + * + * @return + * TRUE if the assertion succeeded, FALSE otherwise. + */ + protected function assertElementByXPath($xpath, array $arguments = array(), $message, $group = 'Other') { + $elements = $this->xpath($xpath, $arguments); + return $this->assertTrue(!empty($elements[0]), $message, $group); + } + + /** + * Check that an element does not exist in HTML markup. + * + * @param $xpath + * An XPath expression. + * @param array $arguments + * (optional) An associative array of XPath replacement tokens to pass to + * DrupalWebTestCase::buildXPathQuery(). + * @param $message + * The message to display along with the assertion. + * @param $group + * The type of assertion - examples are "Browser", "PHP". + * + * @return + * TRUE if the assertion succeeded, FALSE otherwise. + */ + protected function assertNoElementByXPath($xpath, array $arguments = array(), $message, $group = 'Other') { + $elements = $this->xpath($xpath, $arguments); + return $this->assertTrue(empty($elements), $message, $group); + } + + /** + * Asserts that links appear in the menu in a specified trail. + * + * @param array $trail + * A list of menu link titles to assert in the menu. + */ + protected function assertLinkTrailByTitle(array $trail) { + $xpath = array(); + $args = array(); + $message = ''; + foreach ($trail as $i => $title) { + $xpath[] = '/li/a[text()=:title' . $i . ']'; + $args[':title' . $i] = $title; + $message .= ($i ? ' » ' : '') . check_plain($title); + } + $xpath = '//div[@id="admin-menu"]/div/ul' . implode('/parent::li/ul', $xpath); + $this->assertElementByXPath($xpath, $args, $message . ' link found.'); + } + + /** + * Asserts that no link appears in the menu for a specified trail. + * + * @param array $trail + * A list of menu link titles to assert in the menu. + */ + protected function assertNoLinkTrailByTitle(array $trail) { + $xpath = array(); + $args = array(); + $message = ''; + foreach ($trail as $i => $title) { + $xpath[] = '/li/a[text()=:title' . $i . ']'; + $args[':title' . $i] = $title; + $message .= ($i ? ' » ' : '') . check_plain($title); + } + $xpath = '//div[@id="admin-menu"]/div/ul' . implode('/parent::li/ul', $xpath); + $this->assertNoElementByXPath($xpath, $args, $message . ' link not found.'); + } +} + +/** + * Tests menu links depending on user permissions. + */ +class AdminMenuPermissionsTestCase extends AdminMenuWebTestCase { + public static function getInfo() { + return array( + 'name' => 'Menu link access permissions', + 'description' => 'Tests appearance of menu links depending on user permissions.', + 'group' => 'Administration menu', + ); + } + + function setUp() { + parent::setUp(array('node')); + } + + /** + * Test that the links are added to the page (no JS testing). + */ + function testPermissions() { + module_enable(array('contact')); + $this->resetAll(); + + // Anonymous users should not see the menu. + $this->drupalGet(''); + $this->assertNoElementByXPath('//div[@id="admin-menu"]', array(), t('Administration menu not found.')); + + // Create a user who + // - can access content overview + // - cannot access drupal.org links + // - cannot administer Contact module + $permissions = $this->basePermissions + array( + 'access content overview', + ); + $admin_user = $this->drupalCreateUser($permissions); + $this->drupalLogin($admin_user); + + // Check that the user can see the admin links, but not the drupal links. + $this->assertElementByXPath('//div[@id="admin-menu"]', array(), 'Administration menu found.'); + $this->assertElementByXPath('//div[@id="admin-menu"]//a[contains(@href, :path)]', array(':path' => 'admin/content'), 'Content link found.'); + $this->assertNoElementByXPath('//div[@id="admin-menu"]//a[@href=:path]', array(':path' => 'http://drupal.org'), 'Icon » Drupal.org link not found.'); + $this->assertNoElementByXPath('//div[@id="admin-menu"]//a[contains(@href, :path)]', array(':path' => 'admin/structure/contact'), 'Structure » Contact link not found.'); + + // Create a user "reversed" to the above; i.e., who + // - cannot access content overview + // - can access drupal.org links + // - can administer Contact module + $permissions = $this->basePermissions + array( + 'display drupal links', + 'administer contact forms', + ); + $admin_user2 = $this->drupalCreateUser($permissions); + $this->drupalLogin($admin_user2); + $this->assertElementByXPath('//div[@id="admin-menu"]', array(), 'Administration menu found.'); + $this->assertNoElementByXPath('//div[@id="admin-menu"]//a[contains(@href, :path)]', array(':path' => 'admin/content'), 'Content link not found.'); + $this->assertElementByXPath('//div[@id="admin-menu"]//a[@href=:path]', array(':path' => 'http://drupal.org'), 'Icon » Drupal.org link found.'); + $this->assertElementByXPath('//div[@id="admin-menu"]//a[contains(@href, :path)]', array(':path' => 'admin/structure/contact'), 'Structure » Contact link found.'); + } + + /** + * Tests handling of links pointing to category/overview pages. + */ + function testCategories() { + // Create a user with minimum permissions. + $admin_user = $this->drupalCreateUser($this->basePermissions); + $this->drupalLogin($admin_user); + + // Verify that no category links appear. + $this->assertNoLinkTrailByTitle(array(t('Structure'))); + $this->assertNoLinkTrailByTitle(array(t('Configuration'))); + + // Create a user with access to one configuration category. + $permissions = $this->basePermissions + array( + 'administer users', + ); + $admin_user = $this->drupalCreateUser($permissions); + $this->drupalLogin($admin_user); + + // Verify that only expected category links appear. + $this->assertNoLinkTrailByTitle(array(t('Structure'))); + $this->assertLinkTrailByTitle(array(t('People'))); + $this->assertLinkTrailByTitle(array(t('Configuration'))); + $this->assertLinkTrailByTitle(array(t('Configuration'), t('People'))); + // Random picks are sufficient. + $this->assertNoLinkTrailByTitle(array(t('Configuration'), t('Media'))); + $this->assertNoLinkTrailByTitle(array(t('Configuration'), t('System'))); + } + + /** + * Tests that user role and permission changes are properly taken up. + */ + function testPermissionChanges() { + // Create a user who is able to change permissions. + $permissions = $this->basePermissions + array( + 'administer permissions', + ); + $admin_user = $this->drupalCreateUser($permissions); + $this->drupalLogin($admin_user); + + // Extract the user role ID that was created for above permissions. + $rid = key(array_diff_key($admin_user->roles, array(DRUPAL_AUTHENTICATED_RID => 0))); + + // Verify that Configuration does not appear. + $this->assertNoLinkTrailByTitle(array(t('Configuration'))); + // Grant the 'administer site configuration' permission to ourselves. + $edit = array( + $rid . '[administer site configuration]' => TRUE, + ); + $this->drupalPost('admin/people/permissions', $edit, t('Save permissions')); + // Verify that Configuration appears. + $this->assertLinkTrailByTitle(array(t('Configuration'))); + + // Verify that Structure » Content types does not appear. + $this->assertNoLinkTrailByTitle(array(t('Structure'), t('Content types'))); + // Create a new role. + $edit = array( + 'name' => 'test', + ); + $this->drupalPost('admin/people/permissions/roles', $edit, t('Add role')); + // It should be safe to assume that the new role gets the next ID. + $test_rid = $rid + 1; + // Grant the 'administer content types' permission for the role. + $edit = array( + $test_rid . '[administer content types]' => TRUE, + ); + $this->drupalPost('admin/people/permissions/' . $test_rid, $edit, t('Save permissions')); + // Verify that Structure » Content types does not appear. + $this->assertNoLinkTrailByTitle(array(t('Structure'), t('Content types'))); + + // Assign the role to ourselves. + $edit = array( + 'roles[' . $test_rid . ']' => TRUE, + ); + $this->drupalPost('user/' . $admin_user->uid . '/edit', $edit, t('Save')); + // Verify that Structure » Content types appears. + $this->assertLinkTrailByTitle(array(t('Structure'), t('Content types'))); + + // Delete the role. + $this->drupalPost('admin/people/permissions/roles/edit/' . $test_rid, array(), t('Delete role')); + $this->drupalPost(NULL, array(), t('Delete')); + // Verify that Structure » Content types does not appear. + $this->assertNoLinkTrailByTitle(array(t('Structure'), t('Content types'))); + } +} + +/** + * Tests appearance, localization, and escaping of dynamic links. + */ +class AdminMenuDynamicLinksTestCase extends AdminMenuWebTestCase { + public static function getInfo() { + return array( + 'name' => 'Dynamic links', + 'description' => 'Tests appearance, localization, and escaping of dynamic links.', + 'group' => 'Administration menu', + ); + } + + function setUp() { + parent::setUp(array('node')); + } + + /** + * Tests node type links. + */ + function testNode() { + $type = $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article')); + // Create a content-type with special characters. + $type = $this->drupalCreateContentType(array('type' => 'special', 'name' => 'Cool & Special')); + + $permissions = $this->basePermissions + array( + 'administer content types', + 'create article content', + 'create special content', + ); + $this->admin_user = $this->drupalCreateUser($permissions); + $this->drupalLogin($this->admin_user); + + // Verify that dynamic links are displayed. + $this->drupalGet(''); + $this->assertElementByXPath('//div[@id="admin-menu"]', array(), t('Administration menu found.')); + $this->assertElementByXPath('//div[@id="admin-menu"]//a[contains(@href, :path)]', array(':path' => 'admin/structure/types'), "Structure » Content types link found."); + + // Verify link title output escaping. + $this->assertNoRaw('Cool & Special'); + $this->assertRaw(check_plain('Cool & Special')); + + // Verify Manage content type links. + $links = array( + 'admin/structure/types/manage/article' => 'Article', + 'admin/structure/types/manage/special' => 'Cool & Special', + ); + foreach ($links as $path => $title) { + $this->assertElementByXPath('//div[@id="admin-menu"]//a[contains(@href, :path) and text()=:title]', array( + ':path' => $path, + ':title' => $title, + ), "Structure » Content types » $title link found."); + } + + // Verify Add content links. + $links = array( + 'node/add/article' => 'Article', + 'node/add/special' => 'Cool & Special', + ); + foreach ($links as $path => $title) { + $this->assertElementByXPath('//div[@id="admin-menu"]//a[contains(@href, :path) and text()=:title]', array( + ':path' => $path, + ':title' => $title, + ), "Add content » $title link found."); + } + } + + /** + * Tests Add content links. + */ + function testNodeAdd() { + $type = $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article')); + + // Verify that "Add content" does not appear for unprivileged users. + $permissions = $this->basePermissions + array( + 'access content', + ); + $this->web_user = $this->drupalCreateUser($permissions); + $this->drupalLogin($this->web_user); + $this->assertNoText(t('Add content')); + + // Verify "Add content" appears below "Content" for administrative users. + $permissions = $this->basePermissions + array( + 'access content overview', + 'access content', + 'create article content', + ); + $this->admin_user = $this->drupalCreateUser($permissions); + $this->drupalLogin($this->admin_user); + $this->assertLinkTrailByTitle(array( + t('Content'), + t('Add content'), + )); + + // Verify "Add content" appears on the top-level for regular users. + $permissions = $this->basePermissions + array( + 'access content', + 'create article content', + ); + $this->web_user = $this->drupalCreateUser($permissions); + $this->drupalLogin($this->web_user); + $this->assertLinkTrailByTitle(array( + t('Add content'), + )); + } +} + +/** + * Tests appearance of different types of links. + */ +class AdminMenuLinkTypesTestCase extends AdminMenuWebTestCase { + public static function getInfo() { + return array( + 'name' => 'Link types', + 'description' => 'Tests appearance of different types of links.', + 'group' => 'Administration menu', + ); + } + + function setUp() { + parent::setUp(array('help')); + + $permissions = module_invoke_all('permission'); + $permissions = array_keys($permissions); + $this->admin_user = $this->drupalCreateUser($permissions); + $this->drupalLogin($this->admin_user); + } + + /** + * Tests appearance of different router item link types. + */ + function testLinkTypes() { + // Verify that MENU_NORMAL_ITEMs appear. + $this->assertLinkTrailByTitle(array( + t('Configuration'), + t('System'), + t('Site information'), + )); + + // Verify that MENU_LOCAL_TASKs appear. + $this->assertLinkTrailByTitle(array(t('People'), t('Permissions'))); + $this->assertLinkTrailByTitle(array(t('Appearance'), t('Settings'))); + $this->assertLinkTrailByTitle(array(t('Modules'), t('Uninstall'))); + + // Verify that MENU_LOCAL_ACTIONs appear. + $this->assertLinkTrailByTitle(array( + t('People'), + t('Add user'), + )); + + // Verify that MENU_DEFAULT_LOCAL_TASKs do NOT appear. + $this->assertNoLinkTrailByTitle(array(t('Modules'), t('List'))); + $this->assertNoLinkTrailByTitle(array(t('People'), t('List'))); + $this->assertNoLinkTrailByTitle(array(t('People'), t('Permissions'), t('Permissions'))); + $this->assertNoLinkTrailByTitle(array(t('Appearance'), t('List'))); + + // Verify that MENU_VISIBLE_IN_BREADCRUMB items (exact type) do NOT appear. + $this->assertNoLinkTrailByTitle(array(t('Modules'), t('Uninstall'), t('Uninstall'))); + $this->assertNoLinkTrailByTitle(array(t('Help'), 'admin_menu')); + + // Verify that special "Index" link appears below icon. + $this->assertElementByXPath('//div[@id="admin-menu"]//a[contains(@href, :path) and text()=:title]', array( + ':path' => 'admin/index', + ':title' => t('Index'), + ), "Icon » Index link found."); + } +} + +/** + * Tests customized menu links. + */ +class AdminMenuCustomizedTestCase extends AdminMenuWebTestCase { + public static function getInfo() { + return array( + 'name' => 'Customized links', + 'description' => 'Tests customized menu links.', + 'group' => 'Administration menu', + ); + } + + function setUp() { + parent::setUp(array('menu')); + + $this->admin_user = $this->drupalCreateUser($this->basePermissions + array( + 'administer menu', + )); + $this->drupalLogin($this->admin_user); + } + + /** + * Test disabled custom links. + */ + function testCustomDisabled() { + $type = $this->drupalCreateContentType(); + $node = $this->drupalCreateNode(array('type' => $type->type)); + $text = $this->randomName(); + $xpath = $this->buildXPathQuery('//div[@id=:id]//a[contains(text(), :text)]', array( + ':id' => 'admin-menu', + ':text' => $text, + )); + + // Verify that the link does not appear in the menu. + $this->drupalGet('node'); + $elements = $this->xpath($xpath); + $this->assertFalse($elements, 'Custom link not found.'); + + // Add a custom link to the node to the menu. + $edit = array( + 'link_path' => 'node/' . $node->nid, + 'link_title' => $text, + 'parent' => 'management:' . $this->queryMlidByPath('admin'), + ); + $this->drupalPost('admin/structure/menu/manage/management/add', $edit, t('Save')); + + // Verify that the link appears in the menu. + $this->drupalGet('node'); + $elements = $this->xpath($xpath); + $this->assertTrue($elements, 'Custom link found.'); + + // Disable the link. + $edit = array( + 'enabled' => FALSE, + ); + $this->drupalPost('admin/structure/menu/item/' . $this->queryMlidByPath('node/' . $node->nid) . '/edit', $edit, t('Save')); + + // Verify that the disabled link does not appear in the menu. + $this->drupalGet('node'); + $elements = $this->xpath($xpath); + $this->assertFalse($elements, 'Disabled custom link not found.'); + } + + /** + * Tests external links. + */ + function testCustomExternal() { + // Add a custom link to the node to the menu. + $edit = array( + 'link_path' => 'http://example.com', + 'link_title' => 'Example', + 'parent' => 'management:' . $this->queryMlidByPath('admin'), + ); + $this->drupalPost('admin/structure/menu/manage/management/add', $edit, t('Save')); + + // Verify that the link appears in the menu. + $this->drupalGet(''); + $elements = $this->xpath('//div[@id=:id]//a[@href=:href and contains(text(), :text)]', array( + ':id' => 'admin-menu', + ':href' => $edit['link_path'], + ':text' => $edit['link_title'], + )); + $this->assertTrue($elements, 'External link found.'); + } + + /** + * Returns the menu link ID for a given link path in the management menu. + */ + protected function queryMlidByPath($path) { + return db_query('SELECT mlid FROM {menu_links} WHERE menu_name = :menu AND link_path = :path', array( + ':menu' => 'management', + ':path' => $path, + ))->fetchField(); + } +} + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/LICENSE.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/LICENSE.txt Fri Sep 20 11:18:21 2013 +0100 @@ -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. + + + Copyright (C) + + 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. + + , 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 -r d72257b2ddc2 -r a75ead649730 modules/biblio/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/README.txt Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,143 @@ + + biblio.module + +Author: Ron Jerome +Released under the GPL + + +Description: +============ +This module extends the node data type with additional fields to manage lists +of scholarly publications. + +It closely follows the EndNote model, thus both importing from and exporting +to Endote are supported. Other formats such as bibtex and RIS are also supported. + +Bibliographic information is displayed in lists with links to detailed +information on each publication. + +The lists can be sorted, filtered and ordered in many different ways. + + + + +Requirements: +============= +Drupal 7.x, Upgrades supported from any Biblio version after 6.x-1.9 + +Installation: +============= +Create a directory called biblio in the sites/all/modules directory, then place all of the +files packaged with this module in that directory. + +This module will auto-install the required database tables the first time you +enable it on the admin/modules page. This will also setup a number of pre-defined +publication types. These types can be changed or deleted on the +admin/config/content/biblio/types page. + +Robots.txt +========== +In order to limit recursive searches by web bots, it is recommended that you add the following +to your robots.txt file. Note: if you change the base url for biblio you will have to make the +corresponding change here. i.e. if you base url for biblio is "publications" then replace "biblio" +with "publications" in the directives below. + +# Biblio +Disallow: /biblio/export/ +Disallow: /biblio?* +Disallow: /biblio?page=*&* +Allow: /biblio?page=* + + +Settings: +========= +A number of settings are available at admin/config/content/biblio. They control how +the author names are displayed, whether export links are added to pages and the +number of entries per page to display. + +The 'admin/config/content/biblio/fields' page allows the the site administrator to set +the default field titles and set which fields are common to all publication +types. When a new publication type is added, it will contain all the common +fields and any that are specifically activated (custom is checked). This also +allows the admin to over ride any of the default settings for any given type. + +Access Control: +=============== +Three permissions are controlable on the admin/access page. I think they are fairly +self evident, they control who can create biblio entries, edit entries and who can +import from file. + +Adding/importing records: +========================= +Bibliographic entries can be added to the database in one of two ways, individualy +from the node/add/biblio link, or by importing records from one of the supported file +formats. Administrators can go to 'admin/config/content/biblio/import' and fill in +the form to upload and import publication data from files. + + +Features: +========= +By default, the /biblio page will list all of the entries in the database sorted +by Year in descending order. If you wish to sort by "Title" or "Type", you may +do so by clicking on the appropriate links at the top of the page. To reverse +the sort order, simply click the link a second time. + + +Filtering Search Results: +========================= +If you wish to filter the results, click on the "Filter" tab at the top of the +page. To add a filter, click the radio button to the left of the filter type +you wish to apply, then select the filter criteria from the drop down list +on the right, then click the filter button. + +It is possible to create complex filters by returning to the "Filter" tab and +adding additional filters. Simply follow the steps outlined above and press +the "Refine" button. + +All filters can be removed by clicking the Clear All Filters link at the top +of the result page, or on the "Filter" tab they can be removed one at a time +using the "Undo" button, or you can remove them all using the "Clear All" button + +You may also construct URLs which filter. For example, /biblio/year/2005 will +show all of the entries for 2005. /biblio/year/2005/author/smith will show all +of entries from 2005 for smith. + + +Exporting Search Results: +========================= +Assuming this option has been enabled by the administrator, you can export +search results directly into EndNote. The link at the top of the result page +will export all of the search results, and the links on individual entries will +export the information related to that single entry. + +Clicking on one of the export links should cause your browser to ask you +whether you want to Open, or Save To Disk, the file endnote.enw. If you choose +to open it, Endnote should start and ask you which library you would like +store the results in. Alternatively, you can save the file to disk and manually +import it into EndNote. + + +The information is exported in either EndNote "Tagged" format similar to this... + + %0 Book + %A John Smith + %D 1959 + %T The Works of John Smith + ... + +Or Endnote 7 XML format which is similar to this... + + + + + 10 + 1959 + The Works of John Smith + + John Smith + + + + + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/biblio.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/biblio.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,338 @@ +#biblio-filter ul { + padding: 1px; + margin: 1px; + width: 100%; +} + +#biblio-buttons { + float: left; + margin-left: 0.5em; + margin-top: 1em; + /* clear: right; */ +} + +.biblio-alpha-line { + text-align: center; +} + +dl.bibliomultiselect dd.b,dl.bibliomultiselect dd.b .form-item,dl.bibliomultiselect dd.b select + { + font-family: inherit; + font-size: inherit; + width: 14em; +} + +dl.bibliomultiselect dd.a,dl.bibliomultiselect dd.a .form-item { + width: 8em; +} + +dl.bibliomultiselect dt,dl.bibliomultiselect dd { + float: left; + line-height: 1.75em; + padding: 0; + margin: 0 1em 0 0; +} + +dl.bibliomultiselect .form-item { + height: 1.75em; + margin: 0; +} +#biblio-authors table, #biblio-tertiary-authors table { + width: 100%; +} +#biblio-authors .form-text { + width: 95%; +} +#biblio-authors td.biblio-contributor, +#biblio-secondary-authors td.biblio-contributor, +#biblio-tertiary-authors td.biblio-contributor, +#biblio-subsidiary-authors td.biblio-contributor, +#biblio-corp-authors td.biblio-contributor{ + width: 98%; +} +#biblio-authors #biblio-tertiary-authors .draggable a.tabledrag-handle { + padding: 0; +} + +.biblio-head { + width: 97%; + color: Black; + font-weight: normal; + background-color: #EAEAEA; + border: medium solid; + border-left-color: #F0F8FF; + border-right-color: Gray; + border-bottom-color: Gray; + border-top-color: #F0F8FF; + padding: 3px; +} + +.biblio-head a:link,.biblio-head a.active,.biblio-head a:visited,.biblio-head a:focus,.biblio-head a:hover + { + color: black; +} + +.biblio-current-filters { + background-color: #ffe1e1; +} + +.biblio-separator-bar { + color: #000000; + font-weight: bold; + background-color: #e1e1e1; + border: 1px solid #ccc; + padding: 0.5em; + margin: 1em 0 1em 0; +} + +.biblio-toolbar { + width: 97%; + color: Red; + font-weight: bold; + background-color: Silver; + border: medium solid; + border-left-color: #F0F8FF; + border-right-color: Gray; + border-bottom-color: Gray; + border-top-color: #F0F8FF; + padding: 3px; +} + +.biblio-entry { + margin: 1em 0 1em 0; +} + +.biblio-style-mla { + text-indent: -25px; + padding-left: 25px; +} + +.biblio-publisher { + font-style: oblique; + font-weight: bold; +} + +.biblio-title { + font-weight: bold; + text-decoration: none; + font-style: normal; + line-height: normal; + text-align: left; + font-family: "@Arial Unicode MS", Arial, sans-serif; + color: #336599; +} + +a:active { + +} + +.biblio-authors a { + font-weight: normal; + text-decoration: none; + font-style: normal; +} + +.biblio_type-1 { + background-color: #F2F2D9; +} + +.biblio_type-2 { + background-color: #D9E6F2; +} + +.biblio_type-3 { + background-color: #E5F2D9; +} + +.biblio_type-4 { + background-color: #D9F2E6; +} + +.biblio_type-5 { + background-color: #F2E6D9; +} + +.biblio_type-6 { + background-color: #D9E6F2; +} + +.biblio_type-7 { + background-color: #D9E6F2; +} + +.biblio_type-8 { + background-color: #D9E6F2; +} + +.biblio_type-9 { + background-color: #D9E6F2; +} + +.biblio-export { + text-align: right; + text-decoration: none; + float: right; +} + +.biblio-abstract-link { + text-align: left; + text-decoration: none; + font-style: normal; + font-weight: normal; + font-size: 75%; +} + +.biblio-export-links { + float: right; + text-align: left; + text-decoration: none; + font-style: normal; + font-weight: normal; + font-size: 75%; + line-height: 100%; +} + +ul.biblio-export-buttons,ul.biblio-export-buttons li { + background: transparent; + list-style-image: none; + list-style-type: none; + display: inline; + border-bottom: 0px; + border-right: 1px; + padding: 0; + margin: 0.1em; +} + +.biblio-annotation { + text-align: left; + text-decoration: none; + margin-left: 2.5em; + margin-top: 0.5em; + margin-right: 2.5em; +} + +.biblio-sort { + text-decoration: none; + text-align: left; +} + +.biblio-openurl-text { + text-align: right; + text-decoration: none; + float: right; +} + +.biblio-left-td { + text-align: right; + vertical-align: top; + width: 20%; +} + +#biblio-header { + display: block; +} +/* +#biblio-header ul.tabs { + border-bottom: 1px solid #BBBBBB; + padding: 0 0 1.765em 1em; +} + +#biblio-header ul li { + padding: 0 0 0 0; + float: left; + display: block; +} + +#biblio-header ul.tabs li a .a { + float: left; + height: 20px; + padding: 2px 0em 3px 0em; + margin: 0px; + padding: 0px; + background-image: url(main-tab1.png); + background-repeat: no-repeat; + background-position: 100% 0px; +} + +#biblio-header ul.tabs li a .a .b { + display: block; + margin: 0px; + height: 20px; + padding: 0px 1em 3px; + background-image: url(main-tab2.png); + background-repeat: no-repeat; + background-position: 0% 0px; +} + +#biblio-header ul.tabs li.active a { + background-color: transparent; + border-width: 0px; +} + +#biblio-header ul.tabs li.active a .a { + background-position: 100% -60px; +} + +#biblio-header ul.tabs li.active a .a .b { + background-position: 0% -60px; +} + +#biblio-header ul.tabs li a:hover { + border-width: 0px; + text-decoration: none !important; +} + +#biblio-header ul.tabs li a:hover .a { + background-position: 100% -30px; +} + +#biblio-header ul.tabs li a:hover .a .b { + background-position: 0% -30px; +} + +#biblio-header ul.tabs li.active a:hover { + background-color: #fff; + border-width: 0px; +} + +#biblio-header ul.tabs li.active a:hover .a { + background-position: 100% -60px; +} + +#biblio-header ul.tabs li.active a:hover .a .b { + background-position: 0% -60px; +} +*/ +.exposed-filters .filters { + float: left; /* LTR */ + margin-right: 1em; /* LTR */ + width: 25em; /* IE6 */ +} +.exposed-filters .form-item { + margin: 0 0 0.1em 0; + padding: 0; +} +.exposed-filters .form-item label { + float: left; /* LTR */ + font-weight: normal; + width: 10em; +} +.exposed-filters .form-select { + width: 14em; +} +/* Current filters */ +.exposed-filters .current-filters { + margin-bottom: 1em; +} +.exposed-filters .current-filters .placeholder { + font-style: normal; + font-weight: bold; +} +.exposed-filters .additional-filters { + float: left; /* LTR */ + margin-right: 1em; /* LTR */ +} +.biblio-highlight { + background-color: #FFF4F4; + border: 2px solid #494949; +} \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/biblio.info --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/biblio.info Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,39 @@ +name = Biblio +description = Maintains bibliographic lists. +core = 7.x +dependencies[] = taxonomy +package = Biblio + +configure = admin/config/content/biblio +files[] = tests/biblio.test +files[] = tests/keyword.test +files[] = tests/contributor.test +files[] = tests/import.export.test + +files[] = includes/Name.php +files[] = includes/Parser.php + +files[] = views/biblio_handler_citation.inc +files[] = views/biblio_handler_field_keyword.inc +files[] = views/biblio_handler_field_biblio_keyword_data_word.inc +files[] = views/biblio_handler_field_biblio_keyword_kid.inc +files[] = views/biblio_handler_field_biblio_type.inc +files[] = views/biblio_handler_field_contributor.inc +files[] = views/biblio_handler_field.inc +files[] = views/biblio_handler_field_markup.inc +files[] = views/biblio_handler_filter_biblio_contributor_auth_type.inc +files[] = views/biblio_handler_filter_biblio_keyword_kid.inc +files[] = views/biblio_handler_filter_biblio_keyword_word.inc +files[] = views/biblio_handler_filter_biblio_type.inc +files[] = views/biblio_handler_filter_contributor_lastname.inc +files[] = views/biblio_handler_filter_contributor_uid.inc +files[] = views/biblio_handler_filter_contributor.inc +files[] = views/biblio_handler_sort_contributor_lastname.inc +files[] = views/biblio_handler_argument_many_to_one.inc +files[] = views/biblio_handler_field_export_link.inc +; Information added by drupal.org packaging script on 2013-07-20 +version = "7.x-1.0-rc7" +core = "7.x" +project = "biblio" +datestamp = "1374290470" + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/biblio.install --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/biblio.install Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,2218 @@ + 'biblio', + 'name' => $t('Biblio'), + 'base' => 'biblio', + 'description' => $t('Use Biblio for scholarly content, such as journal papers and books.'), + 'body_label' => $t('Full text') + ); + + // Complete the node type definition by setting any defaults not explicitly + // declared above. + // http://api.drupal.org/api/function/node_type_set_defaults/7 + $content_type = node_type_set_defaults($biblio); + node_add_body_field($content_type); + + // Save the content type + node_type_save($content_type); + + drupal_set_time_limit(300); + + $result[] = _add_db_field_data(); + + $result[] = _add_publication_types(); + + $result[] = _add_custom_field_data(); + + //_enable_biblio_keyword_vocabulary(); + + $result[] = _set_system_weight(); + + + +// if (count($result) == count(array_filter($result))) { +// drupal_set_message(t('The biblio module has successfully added its tables to the database.')); +// } +// else { +// drupal_set_message(t('Drupal encountered some errors while attempting to install the database tables for the biblio module.'), 'error'); +// } +} + +function biblio_enable() { +//TODO taxonomy + //if (module_exists('taxonomy')) _enable_biblio_vocabularies(); + _set_system_weight(); + //_enable_biblio_collection_vocabulary(); + // _add_biblio_keywords(); +} + +function _enable_biblio_vocabularies() { + $vids = variable_get('biblio_vocabularies', array()); + foreach ($vids as $vid ) { + if (($voc = taxonomy_vocabulary_load($vid))) { + $voc = (array) $voc; + $voc['nodes']['biblio'] = 1; + taxonomy_save_vocabulary($voc); + } + } +} + +function biblio_disable() { + $vids = array(); +//TODO taxonomy +/* + if (module_exists('taxonomy')) { + $voc = taxonomy_get_vocabularies(); + foreach ($voc as $vid => $vocabulary) { + if (isset($vocabulary->nodes['biblio'])) { + $vids[] = $vid; + } + } + variable_set('biblio_vocabularies', $vids); + } +*/ +} + +function biblio_uninstall() { + $batch = array( + 'title' => t('Remove all Biblio nodes'), + 'operations' => array( + array('biblio_batch_uninstall', array()), + ), + 'progress_message' => t('Deleteing Biblio nodes...'), + 'finished' => 'biblio_batch_uninstall_finished', + 'file' => drupal_get_path('module', 'biblio') . '/biblio.install' + ); + + batch_set($batch); +} +function biblio_batch_uninstall(&$context) { + + $limit = 5; + if (empty($context['sandbox'])) { + $context['sandbox']['progress'] = 0; + $context['sandbox']['current_node'] = 0; + $context['sandbox']['max'] = db_query("SELECT COUNT(DISTINCT nid) FROM {node} WHERE type='biblio'")->fetchField(); + $context['sandbox']['itters'] = $context['sandbox']['max'] / $limit; + $context['sandbox']['eta'] = 0; + } + // Bail out if the cache is empty. + if ($context['sandbox']['max'] == 0) { + $context['finished'] = 1; + return; + } + + timer_start('biblio_delete'); + + $result = db_select('node') + ->fields('node', array('nid')) + ->condition('nid', $context['sandbox']['current_node'], '>') + ->condition('type', 'biblio') + ->orderBy('nid') + ->range(0, $limit) + ->execute(); + + foreach ($result as $row) { + $node = node_delete($row->nid); + if (function_exists('search_wipe')) { + search_wipe($row->nid, 'node'); + } + $context['sandbox']['progress']++; + $context['sandbox']['current_node'] = $row->nid; + } + + $looptime = timer_stop('biblio_delete'); + $context['sandbox']['eta'] += $looptime['time']; + $itters = $context['sandbox']['progress'] / $limit; + if ($itters) { + $average_time = $context['sandbox']['eta'] / $itters; + $eta = (($context['sandbox']['itters'] * $average_time) - ($average_time * $itters)) / 1000; + if ($eta >= 60) { + $min = (int) $eta / 60; + } + else { + $min = 0; + } + $sec = $eta % 60; + $eta = sprintf("%d:%02d", $min, $sec); + $progress = sprintf("%d / %d", $context['sandbox']['progress'], $context['sandbox']['max'] ); + $context['message'] = t('
Biblio nodes deleted: %progress
Time remaining: %eta min.
' , array('%progress' => $progress, '%eta' => $eta)); + } + if ($context['sandbox']['progress'] != $context['sandbox']['max']) { + $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max']; + } +} + + +function biblio_batch_uninstall_finished($success, $results, $operations) { + if ($success) { +//TODO taxonomy +/* + if (module_exists('taxonomy')) { + $voc = taxonomy_get_vocabularies(); + foreach ($voc as $vid => $vocabulary) { + if ($vocabulary->module == 'biblio') taxonomy_del_vocabulary($vid); + } + } +*/ + $vars = db_query("SELECT * FROM {variable} WHERE name LIKE 'biblio_%'"); + foreach ($vars as $var) { + variable_del($var->name); + } + } +} + +function biblio_requirements($phase) { + $requirements = array(); + $message = ''; + // Ensure translations don't break at install time + $t = get_t(); + + // Report Drupal version + if ($phase == 'runtime') { + $dir = drupal_get_path('module', 'biblio'); + $files = file_scan_directory($dir, '/..*.inc$/', array('recurse' => FALSE)); + if (count($files) > 1) { + $message = $t('There is a problem with your Biblio installation! There should not be any ".inc" files in the %biblio directory. You probably forgot to delete the old biblio files when you upgraded the module. You should remove the following files from that directory...', array('%biblio' => $dir)); + $message .= "
    "; + foreach ($files as $file) { + $message .= "
  • " . $file->filename; + } + $message .= "
"; + $requirements['biblio'] = array( + 'title' => $t('Biblio'), + 'value' => BIBLIO_VERSION, + 'severity' => empty($message) ? REQUIREMENT_OK : REQUIREMENT_WARNING, + 'description' => $message, + ); + } + + } + return $requirements; +} + +function _biblio_helper_modules($mode) { + + $modules = _biblio_get_helper_modules(); + switch ($mode) { + case 'install': + module_enable($modules); + break; + case 'uninstall': + foreach ($modules as $module) { + drupal_uninstall_modules($module); + } + break; + } +} + +function _biblio_get_helper_modules() { + return array( + 'biblio_bibtex', + 'biblio_crossref', + 'biblio_marc', + 'biblio_pm', + 'biblio_ris', + 'biblio_tagged', + 'biblio_xml', + 'biblio_citeproc', + 'biblio_rtf', + ); + +} + +function _set_system_weight() { + db_update('system') + ->fields(array( + 'weight' => 9, + )) + ->condition('name', 'biblio') + ->execute(); + return; +} + +function _enable_biblio_keyword_vocabulary() { + +//TODO taxonomy +/* + if ($vocabulary = taxonomy_vocabulary_load(variable_get('biblio_keyword_vocabulary', 0))) { + // Existing install. Add back forum node type, if the biblio + // vocabulary still exists. Keep all other node types intact there. + $vocabulary = (array) $vocabulary; + $vocabulary['nodes']['biblio'] = 1; + taxonomy_save_vocabulary($vocabulary); + } + + + + return $vocabulary['vid']; +*/ +} + +function _enable_biblio_collection_vocabulary() { +//TODO taxonomy +/* + if ($vocabulary = taxonomy_vocabulary_load(variable_get('biblio_collection_vocabulary', 0))) { + // Existing install. Add back forum node type, if the biblio + // vocabulary still exists. Keep all other node types intact there. + $vocabulary = (array) $vocabulary; + $vocabulary['nodes']['biblio'] = 1; + taxonomy_save_vocabulary($vocabulary); + } + else { + // Create the forum vocabulary if it does not exist. Assign the vocabulary + // a low weight so it will appear first in forum topic create and edit + // forms. + $vocabulary = array( + 'name' => 'Biblio Collections', + 'description' => 'You may organize your publications into collections by adding a collection names to this vocabulary', + 'help' => '', + 'nodes' => array('biblio' => 1), + 'hierarchy' => 0, + 'relations' => 1, + 'tags' => 0, + 'multiple' => 1, + 'required' => 0, + 'weight' => 0, + 'module' => 'biblio', + ); + taxonomy_save_vocabulary($vocabulary); + variable_set('biblio_collection_vocabulary', $vocabulary['vid']); + $default_collection = array( + 'name' => t('Default'), + 'description' => t("This is the collection that all biblio entries will be a part of if no other collection is selected. Deleting this term will render all your biblio entries inaccessable. (You've been warned!)" ), + 'parent' => array(), + 'relations' => array(), + 'synonyms' => '', + 'weight' => 0, + 'vid' => variable_get('biblio_collection_vocabulary', 0), + ); + taxonomy_save_term($default_collection); + } + return $vocabulary['vid']; +*/ +} + +/** + * Copies keywords from the biblio_keyword column of the biblio table + * to a taxonomy vocabulary + * + * @return none + */ +function _add_biblio_keywords() { +//TODO taxonomy +/* + set_time_limit(300); + $kw_sep = variable_get('biblio_keyword_sep', ','); + $vid = ($vid = variable_get('biblio_keyword_vocabulary', 0))? $vid:_enable_biblio_keyword_vocabulary(); + if ($vid ) { + $db_result = db_query("SELECT b.biblio_keywords, b.nid, b.vid FROM {biblio} b"); + $result = array(); + foreach ($db_result as $row) { + foreach (explode($kw_sep, $row->biblio_keywords) as $keyword) { + $result[] = array('value' => trim($keyword), 'nid' => $row->nid, 'vid' => $row->vid); + } + db_query('DELETE tn.* FROM {term_node} tn INNER JOIN {term_data} td ON tn.tid = td.tid WHERE nid = %d AND td.vid = %d', $row->nid, $vid); + } + $inserted = array(); + $count = 0; + foreach ($result as $keywords) { + // See if the term exists in the chosen vocabulary + // and return the tid; otherwise, add a new record. + $possibilities = taxonomy_get_term_by_name($keywords['value']); + $term_tid = NULL; // tid match, if any. + foreach ($possibilities as $possibility) { + if ($possibility->vid == $vid) { + $term_tid = $possibility->tid; + } + } + + if (!$term_tid) { + $term = array('vid' => $vid, 'name' => $keywords['value']); + $status = taxonomy_save_term($term); + $term_tid = $term['tid']; + } + + // Defend against duplicate, differently cased tags + if (!isset($inserted[$keywords['vid']][$term_tid])) { + db_query('INSERT INTO {term_node} (nid, vid, tid) VALUES (%d, %d, %d)', $keywords['nid'], $keywords['vid'], $term_tid); + $inserted[$keywords['vid']][$term_tid] = TRUE; + $count++; + } + } + return array('success' => TRUE, 'query' => 'Added ' . $count . ' keywords to the biblio/taxonomy keyword vocabulary'); + } + return array('success' => FALSE, 'query' => 'Biblio keyword vocabulary not available'); +*/ +} + +function biblio_schema() { + $schema['biblio'] = array( + 'fields' => array( + 'nid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'description' => '', + ), + 'vid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'description' => '', + ), + 'biblio_type' => array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'description' => '', + ), + 'biblio_number' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '128', + 'description' => '', + ), + 'biblio_other_number' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '128', + 'description' => '', + ), + 'biblio_sort_title' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '64', + 'description' => 'A normalized version of the title, used for sorting on titles. (only first 64 characters saved)', + ), + 'biblio_secondary_title' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '255', + 'description' => '', + ), + 'biblio_tertiary_title' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '255', + 'description' => '', + ), + 'biblio_edition' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '255', + 'description' => '', + ), + 'biblio_publisher' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '255', + 'description' => '', + ), + 'biblio_place_published' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '255', + 'description' => '', + ), + 'biblio_year' => array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 9999, + 'description' => '', + ), + 'biblio_volume' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '128', + 'description' => '', + ), + 'biblio_pages' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '128', + 'description' => '', + ), + 'biblio_date' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '64', + 'description' => '', + ), + 'biblio_isbn' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '128', + 'description' => '', + ), + 'biblio_lang' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '24', + 'default' => 'eng', + 'description' => '', + ), + 'biblio_abst_e' => array( + 'type' => 'text', + 'not null' => FALSE, + 'description' => '', + ), + 'biblio_abst_f' => array( + 'not null' => FALSE, + 'type' => 'text', + 'description' => '', + ), + 'biblio_full_text' => array( + 'type' => 'int', + 'not null' => FALSE, + 'default' => 0, + 'description' => '', + ), + 'biblio_url' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '255', + 'description' => '', + ), + 'biblio_issue' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '128', + 'description' => '', + ), + 'biblio_type_of_work' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '128', + 'description' => '', + ), + 'biblio_accession_number' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '128', + 'description' => '', + ), + 'biblio_call_number' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '128', + 'description' => '', + ), + 'biblio_notes' => array( + 'type' => 'text', + 'not null' => FALSE, + 'description' => '', + ), + 'biblio_custom1' => array( + 'type' => 'text', + 'not null' => FALSE, + 'description' => '', + ), + 'biblio_custom2' => array( + 'type' => 'text', + 'not null' => FALSE, + 'description' => '', + ), + 'biblio_custom3' => array( + 'type' => 'text', + 'not null' => FALSE, + 'description' => '', + ), + 'biblio_custom4' => array( + 'type' => 'text', + 'not null' => FALSE, + 'description' => '', + ), + 'biblio_custom5' => array( + 'type' => 'text', + 'not null' => FALSE, + 'description' => '', + ), + 'biblio_custom6' => array( + 'type' => 'text', + 'not null' => FALSE, + 'description' => '', + ), + 'biblio_custom7' => array( + 'type' => 'text', + 'not null' => FALSE, + 'description' => '', + ), + 'biblio_research_notes' => array( + 'type' => 'text', + 'not null' => FALSE, + 'description' => '', + ), + 'biblio_number_of_volumes' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '128', + 'description' => '', + ), + 'biblio_short_title' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '255', + 'description' => '', + ), + 'biblio_alternate_title' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '255', + 'description' => '', + ), + 'biblio_original_publication' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '255', + 'description' => '', + ), + 'biblio_reprint_edition' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '255', + 'description' => '', + ), + 'biblio_translated_title' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '255', + 'description' => '', + ), + 'biblio_section' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '128', + 'description' => '', + ), + 'biblio_citekey' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '255', + 'description' => '', + ), + 'biblio_coins' => array( + 'type' => 'text', + 'not null' => FALSE, + 'description' => '', + ), + 'biblio_doi' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '255', + 'description' => '', + ), + 'biblio_issn' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '128', + 'description' => '', + ), + 'biblio_auth_address' => array( + 'type' => 'text', + 'not null' => FALSE, + 'description' => '', + ), + 'biblio_remote_db_name' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '255', + 'description' => '', + ), + 'biblio_remote_db_provider' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '255', + 'description' => '', + ), + 'biblio_label' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '255', + 'description' => '', + ), + 'biblio_access_date' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '255', + 'description' => '', + ), + 'biblio_refereed' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '20', + 'description' => '', + ), + 'biblio_md5' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '32', + 'description' => '', + ), + 'biblio_formats' => array( + 'type' => 'blob', + 'not null' => FALSE, + 'description' => '', + 'serialize' => TRUE, + ), + ), + 'foreign keys' => array( + 'node_revision' => array( + 'table' => 'node_revision', + 'columns' => array('vid' => 'vid'), + ), + 'node' => array( + 'table' => 'node', + 'columns' => array('nid' => 'nid'), + ), + 'biblio_type' => array( + 'table' => 'biblio_types', + 'columns' => array('biblio_type' => 'tid'), + ), + ), + 'primary key' => array( + 'vid' + ), + 'indexes' => array( + 'nid' => array('nid'), + 'md5' => array('biblio_md5'), + 'year' => array('biblio_year'), + 'title_sort' => array('biblio_sort_title'), + 'date' => array('biblio_date') + ), + ); + + $schema['biblio_fields'] = array( + 'fields' => array( + 'fid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => '{biblio_fields}.fid of the node', + ), + 'name' => array( + 'type' => 'varchar', + 'length' => '128', + 'not null' => TRUE, + 'default' => '' + ), + 'type' => array( + 'type' => 'varchar', + 'length' => '128', + 'not null' => TRUE, + 'default' => 'textfield' + ), + 'size' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 60, + ), + 'maxsize' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 255, + ), + ), + 'primary key' => array('fid'), + ); + + $schema['biblio_field_type'] = array( + 'description' => 'Relational table linking {biblio_fields} with {biblio_field_type_data}', + 'fields' => array( + 'tid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => '{biblio_types}.tid of the node', + ), + 'fid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => '{biblio_fields}.fid of the node', + ), + 'ftdid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => '{biblio_field_type_data}.ftdid of the node, points to the current data, default or custom', + ), + 'cust_tdid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => 'This always points to the custom data for this field. Stored so we can switch back an forth between default and custom', + ), + 'common' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + ), + 'vtab' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + ), + 'autocomplete' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + ), + 'required' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => 'Is input required for this field' + ), + 'weight' => array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'description' => 'The weight (location) of the field on the input form' + ), + 'visible' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => 'Determines if the field is visible on the input form' + ), + + ), + 'primary key' => array('tid', 'fid'), + 'indexes' => array( + 'tid' => array('tid') + ), + ); + + $schema['biblio_field_type_data'] = array( + 'description' => 'Data used to build the form elements on the input form', + 'fields' => array( + 'ftdid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => '{biblio_field_type_data}.ftdid of the node', + ), + 'title' => array( + 'type' => 'varchar', + 'length' => '128', + 'not null' => TRUE, + 'default' => '', + 'description' => 'The title, which will be displayed on the form, for a given field' + ), + 'hint' => array( + 'type' => 'varchar', + 'length' => '255', + 'not null' => FALSE, + 'description' => 'The hint text printed below the input widget' + ), + ), + 'primary key' => array('ftdid'), + ); + + $schema['biblio_types'] = array( + 'fields' => array( + 'tid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'description' => '{biblio_types}.tid of the publication type', + ), + 'name' => array( + 'type' => 'varchar', + 'length' => '64', + 'not null' => TRUE, + 'default' => '', + 'description' => 'The name of the publication type' + ), + 'description' => array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '255', + 'description' => 'Description of the publication type' + ), + 'weight' => array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'description' => 'Controls the order the types are listed in' + ), + 'visible' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 1, + 'description' => 'Determines if the publication type is visible in the list' + ), + ), + 'primary key' => array('tid'), + + ); + + + + $schema['biblio_contributor'] = array( + 'description' => 'Relational table linking authors to biblio entries', + 'fields' => array( + 'nid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => '{node}.nid of the node', + ), + 'vid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => '{node}.vid of the node', + ), + 'cid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => '{biblio_contributor_data}.cid of the node', + ), + 'auth_type' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 1, + 'description' => '{biblio_contributor_type}.auth_type of the node', + ), + 'auth_category' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 1, + 'description' => '', + ), + 'rank' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => 'Position of the author name on the publication (first,second,third...)', + ), + 'merge_cid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'unsigned' => TRUE, + 'description' => '', + ), + ), + 'foreign keys' => array( + 'node_revision' => array( + 'table' => 'node_revision', + 'columns' => array('vid' => 'vid'), + ), + 'node' => array( + 'table' => 'node', + 'columns' => array('nid' => 'nid'), + ), + 'biblio_contributor_data' => array( + 'table' => 'biblio_contributor_data', + 'columns' => array('cid' => 'cid'), + ), + 'biblio_contributor_type' => array( + 'table' => 'biblio_contributor_type', + 'columns' => array('auth_type' => 'auth_type'), + ), + 'biblio_contributor_category' => array( + 'table' => 'biblio_contributor_type', + 'columns' => array('auth_category' => 'auth_category'), + ), + ), + 'primary key' => array( + 'vid', + 'cid', + 'auth_type', + 'rank' + ), + ); + + $schema['biblio_contributor_data'] = array( + 'description' => 'Contains Author information for each publication', + 'fields' => array( + 'cid' => array( + 'type' => 'serial', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'description' => 'Primary Key: Author ID', + ), + 'aka' => array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'unsigned' => TRUE, + 'description' => 'Also known as, links this author entry with others so you can have variation on the name, but listing by cid will find all other (aka) author entries', + ), + 'alt_form' => array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'unsigned' => TRUE, + 'description' => 'Alternate form of an author name, this value points to the desired form (cid), this form is kept in the database so that future imports of the same name will not create a new author.', + ), + 'drupal_uid' => array( + 'type' => 'int', + 'not null' => FALSE, + 'unsigned' => TRUE, + 'description' => 'Drupal User ID', + ), + 'name' => array( + 'type' => 'varchar', + 'length' => '255', + 'not null' => TRUE, + 'default' => '', + 'description' => 'Full name', + ), + 'lastname' => array( + 'type' => 'varchar', + 'length' => '255', + 'not null' => TRUE, + 'default' => '', + 'description' => 'Author last name', + ), + 'firstname' => array( + 'type' => 'varchar', + 'length' => '128', + 'not null' => FALSE, + 'default' => '', + 'description' => 'Author first name', + ), + 'prefix' => array( + 'type' => 'varchar', + 'length' => '128', + 'not null' => FALSE, + 'default' => '', + 'description' => 'Author name prefix', + ), + 'suffix' => array( + 'type' => 'varchar', + 'length' => '128', + 'not null' => FALSE, + 'default' => '', + 'description' => 'Author name suffix', + ), + 'initials' => array( + 'type' => 'varchar', + 'length' => '10', + 'not null' => FALSE, + 'default' => '', + 'description' => 'Author initials (including first name initial)', + ), + 'affiliation' => array( + 'type' => 'varchar', + 'length' => '255', + 'not null' => FALSE, + 'default' => '', + 'description' => 'Author affiliation or address', + ), + 'literal' => array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'unsigned' => TRUE, + 'description' => 'Determines if the author name is allowed to be reformated by the variaous styles or should be used literally.', + ), + 'md5' => array( + 'type' => 'varchar', + 'length' => '32', + 'not null' => FALSE, + 'description' => '', + ) + ), + 'foreign keys' => array( + 'biblio_contributor' => array( + 'table' => 'biblio_contributor', + 'columns' => array('cid' => 'cid'), + ), + 'node_author' => array( + 'table' => 'users', + 'columns' => array('drupal_uid' => 'uid'), + ), + ), + 'primary key' => array('cid'), + 'indexes' => array( + 'lastname' => array('lastname'), + 'firstname' => array('firstname'), + 'initials' => array('initials') + ) + ); + $schema['biblio_contributor_type'] = array( + 'description' => 'Contains definitions of the contributor types', + 'fields' => array( + 'auth_category' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => 'There are 5 catagoies of author: Primary, Secondary, Tertiery, Subsidary and Corporate ', + ), + 'biblio_type' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => '', + ), + 'auth_type' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => 'This is the pulication type specific verion of a particular catagory', + ), + ), + 'foreign keys' => array( + 'biblio' => array( + 'table' => 'biblio', + 'columns' => array('biblio_type' => 'biblio_type'), + ), + 'biblio_contributor_type' => array( + 'table' => 'biblio_contributor', + 'columns' => array('auth_type' => 'auth_type'), + ), + 'biblio_contributor_category' => array( + 'table' => 'biblio_contributor', + 'columns' => array('auth_category' => 'auth_category'), + ), + ), + 'primary key' => array('auth_category', 'biblio_type', 'auth_type'), + ); + + $schema['biblio_contributor_type_data'] = array( + 'description' => 'Data used to build the form elements on the input form', + 'fields' => array( + 'auth_type' => array( + 'type' => 'serial', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'description' => '{biblio_contributor_type_data} ctdid of the node', + ), + 'title' => array( + 'type' => 'varchar', + 'length' => '128', + 'not null' => TRUE, + 'default' => '', + 'description' => 'The title, which will be displayed on the form, for a given field' + ), + 'hint' => array( + 'type' => 'varchar', + 'length' => '255', + 'not null' => FALSE, + 'description' => 'The hint text printed below the input widget' + ), + ), + 'primary key' => array('auth_type'), + ); + + $schema['biblio_keyword'] = array( + 'description' => 'Relational table linking keywords to biblio nodes', + 'fields' => array( + 'kid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => 'Primary Key: The {biblio_keyword_data}.kid of the keyword of the node.', + ), + 'nid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => 'The {node}.nid of the node.', + ), + 'vid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => 'Primary Key: The {node}.vid of the node.', + ), + ), + 'foreign keys' => array( + 'node_revision' => array( + 'table' => 'node_revision', + 'columns' => array('vid' => 'vid'), + ), + 'node' => array( + 'table' => 'node', + 'columns' => array('nid' => 'nid'), + ), + 'keyword' => array( + 'table' => 'biblio_keyword_data', + 'columns' => array('kid' => 'kid'), + ), + ), + 'primary key' => array('kid', 'vid'), + 'indexes' => array( + 'vid' => array('vid'), + 'nid' => array('nid'), + ), + ); + + $schema['biblio_keyword_data'] = array( + 'description' => 'Stores the keywords related to nodes.', + 'fields' => array( + 'kid' => array( + 'type' => 'serial', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'description' => 'Primary Key: The id of the keyword assigned to the node', + ), + 'word' => array( + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + 'description' => 'The keyword', + ), + ), + 'primary key' => array('kid'), + 'indexes' => array( + 'kword' => array('word'), + ), + ); + $schema['biblio_collection'] = array( + 'description' => 'Relational table grouping biblio nodes into collections', + 'fields' => array( + 'cid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => 'Primary Key: The {biblio_collection_data}.cid of the collection', + ), + 'vid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => 'Primary Key: The {node}.vid of the node.', + ), + 'pid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => 'The parent id of the collection', + ), + 'nid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => 'The {node}.nid of the node.', + ), + ), + 'primary key' => array('cid', 'vid'), + 'indexes' => array( + 'pid' => array('pid'), + 'nid' => array('nid'), + ), + ); + $schema['biblio_collection_type'] = array( + 'description' => 'Descriptions of the collections.', + 'fields' => array( + 'cid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => 'Primary Key: The id of the collection', + ), + 'name' => array( + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + 'description' => 'The name of the collection', + ), + 'description' => array( + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + 'description' => 'The description of the collection', + ), + ), + 'primary key' => array('cid'), + 'indexes' => array( + 'name' => array('name'), + ), + ); + $schema['biblio_duplicates'] = array( + 'description' => 'Relational table linking possible duplicate biblio nodes', + 'fields' => array( + 'vid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => 'Primary Key: The {biblio}.nid of the original node', + ), + 'did' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => 'The {biblio}.nid of the newly imported node which may be a duplicate.', + ), + 'type' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => 'The type of duplicate 0=biblio, 1=author.', + ), + ), + 'primary key' => array('vid', 'did'), + 'indexes' => array( + 'did' => array('vid'), + ), + ); + + $schema['biblio_import_cache'] = array( + 'description' => 'tables used for caching data imported from file and then batch processed', + 'fields' => array( + 'id' => array( + 'type' => 'serial', + 'not null' => TRUE, + 'unsigned' => TRUE), + 'session_id' => array( + 'type' => 'varchar', + 'length' => 45, + 'not null' => TRUE), + 'data' => array( + 'description' => 'A collection of data to cache.', + 'type' => 'blob', + 'not null' => FALSE, + 'size' => 'big'), + ), + 'primary key' => array('id')); + + $schema['biblio_type_maps'] = array( + 'description' => 'Table used to store the mapping information between various file formats and the biblio schema', + 'fields' => array( + 'format' => array( + 'description' => 'The import/export file format', + 'type' => 'varchar', + 'length' => 128, + 'not null' => TRUE), + 'type_map' => array( + 'description' => 'The mapping between the publication types in the file format and biblio', + 'type' => 'blob', + 'not null' => FALSE, + 'size' => 'big'), + 'type_names' => array( + 'description' => 'The human readable names of the publication types', + 'type' => 'blob', + 'not null' => FALSE, + 'size' => 'big'), + 'field_map' => array( + 'description' => 'The mapping between the fields in the file format and biblio', + 'type' => 'blob', + 'not null' => FALSE, + 'size' => 'big'), + 'export_map' => array( + 'description' => 'which fields are exported', + 'type' => 'blob', + 'not null' => FALSE, + 'size' => 'big'), + ), + 'primary key' => array('format')); + + $schema['biblio_vtabs'] = array( + 'description' => 'Table used to store the information to create the vertical tabs on the input form', + 'fields' => array( + 'tab_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => '' + ), + 'weight' => array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + 'description' => '' + ), + 'title' => array( + 'type' => 'varchar', + 'length' => 128, + 'not null' => TRUE, + 'default' => '', + 'description' => 'The title of the tab', + ), + 'description' => array( + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + 'description' => 'The description of the tab', + ), + ), + 'primary key' => array('tab_id')); + + return ($schema); + +} + +function biblio_reset_types() { + $result = array(); + + db_drop_table('biblio_field_type_data'); + db_drop_table('biblio_field_type'); + db_drop_table('biblio_fields'); + db_drop_table('biblio_contributor_type'); + db_drop_table('biblio_contributor_type_data'); + + db_query('DELETE FROM {biblio_types} WHERE tid>999'); + db_query('UPDATE {biblio_types} SET visible=1 WHERE visible=0'); + + $schema = biblio_schema(); + db_create_table('biblio_field_type_data', $schema['biblio_field_type_data']); + db_create_table('biblio_field_type', $schema['biblio_field_type']); + db_create_table('biblio_fields', $schema['biblio_fields']); + db_create_table('biblio_contributor_type', $schema['biblio_contributor_type']); + db_create_table('biblio_contributor_type_data', $schema['biblio_contributor_type_data']); + + variable_set('biblio_last_ftdid', 100); // reset custom field type id too + //_add_db_field_data_XML(); + _add_db_field_data(); + _add_custom_field_data(); +} + +function _biblio_add_vtabs() { + $vtabs = array( + array('tab_id' => 1, 'weight' => 1, 'title' => 'Authors', 'description' => ''), + array('tab_id' => 2, 'weight' => 2, 'title' => 'Publication', 'description' => ''), + array('tab_id' => 3, 'weight' => 3, 'title' => 'Publisher', 'description' => ''), + array('tab_id' => 4, 'weight' => 4, 'title' => 'Identifiers', 'description' => ''), + array('tab_id' => 5, 'weight' => 5, 'title' => 'Locators', 'description' => 'URL\'s etc'), + array('tab_id' => 6, 'weight' => 6, 'title' => 'Keywords', 'description' => ''), + array('tab_id' => 7, 'weight' => 7, 'title' => 'Notes', 'description' => ''), + array('tab_id' => 8, 'weight' => 8, 'title' => 'Alternate Titles', 'description' => ''), + array('tab_id' => 9, 'weight' => 9, 'title' => 'Other', 'description' => ''), + ); + + foreach ($vtabs as $record) { + db_insert('biblio_vtabs')->fields($record)->execute(); + } + + +} + +function _add_publication_types() { + $types[] = array(100, 'Book', NULL, 1); + $types[] = array(101, 'Book Chapter', NULL, 2); + $types[] = array(102, 'Journal Article', NULL, 3); + $types[] = array(131, 'Journal', NULL, 3); + $types[] = array(103, 'Conference Paper', NULL, 4); + $types[] = array(104, 'Conference Proceedings', NULL, 5); + $types[] = array(105, 'Newspaper Article', NULL, 6); + $types[] = array(106, 'Magazine Article', NULL, 7); + $types[] = array(107, 'Web Article', NULL, 8); + $types[] = array(132, 'Website', NULL, 8); + $types[] = array(133, 'Web service', NULL, 8); + $types[] = array(134, 'Web project page', NULL, 8); + $types[] = array(108, 'Thesis', NULL, 9); + $types[] = array(109, 'Report', NULL, 10); + $types[] = array(110, 'Film', NULL, 11); + $types[] = array(111, 'Broadcast', NULL, 12); + $types[] = array(112, 'Artwork', NULL, 13); + $types[] = array(113, 'Software', NULL, 14); + $types[] = array(114, 'Audiovisual', NULL, 15); + $types[] = array(115, 'Hearing', NULL, 16); + $types[] = array(116, 'Case', NULL, 17); + $types[] = array(117, 'Bill', NULL, 18); + $types[] = array(118, 'Statute', NULL, 19); + $types[] = array(119, 'Patent', NULL, 20); + $types[] = array(120, 'Personal', NULL, 21); + $types[] = array(121, 'Manuscript', NULL, 22); + $types[] = array(122, 'Map', NULL, 23); + $types[] = array(123, 'Chart', NULL, 24); + $types[] = array(124, 'Unpublished', NULL, 25); + $types[] = array(125, 'Database', NULL, 26); + $types[] = array(126, 'Government Report', NULL, 27); + $types[] = array(127, 'Classical' , NULL, 28); + $types[] = array(128, 'Legal Ruling', NULL, 29); + $types[] = array(129, 'Miscellaneous', NULL, 30); + $types[] = array(130, 'Miscellaneous Section', NULL, 31); + $types[] = array(135,'Presentation', NULL, 8); + + foreach ($types as $record) { + db_insert('biblio_types')->fields(array( + 'tid' => $record[0], + 'name' => $record[1], + 'description' => $record[2], + 'weight' => $record[3], + ))->execute(); + + } + return; +} + +function _add_db_field_data_XML() { + $next_ctdid=10; //first contributor_type_data id + $schema = biblio_schema(); + $fieldnames = array_keys($schema['biblio_fields']['fields']); + $field_type_fieldnames = array_keys($schema['biblio_field_type']['fields']); + $field_type_data_fieldnames = array_keys($schema['biblio_field_type_data']['fields']); + db_query("/*!40000 ALTER TABLE {biblio_field_type_data} DISABLE KEYS */;"); + db_query("/*!40000 ALTER TABLE {biblio_fields} DISABLE KEYS */;"); + for ($type = 1; $type <= 5; $type++) { + for ($biblio_type = 100; $biblio_type <= 130; $biblio_type++) { + db_query("INSERT INTO {biblio_contributor_type} (auth_category, biblio_type, auth_type) VALUES (%d, %d, %d)", $type, $biblio_type, $type); + } + } + _id_by_name(NULL, NULL, NULL, array('tablename' => 'biblio_field_type_data', 'name_column' => 'title', 'id_column' => 'ftdid')); + + $xml_file = drupal_get_path('module', 'biblio') . '/field_data.xml'; + $xml = simplexml_load_file($xml_file); + foreach ($xml->field as $field) { + $link_data = array(0, $field['fid'], $field['fid'], $field['fid'], $field->common, $field->autocomplete, $field->required, $field->weight, $field->visible); + db_query("INSERT INTO {biblio_field_type} (" . implode(", ", $field_type_fieldnames) . ") + VALUES (%d, %d, %d, %d, %d, %d, %d, %d, %d)", $link_data); + for ($t = 100; $t <= 130; $t++) { + $values = array($t, $field['fid'], $field['fid'], $field['fid'], $field->common, $field->autocomplete, $field->required, $field->weight, $field->visible); + db_query("INSERT INTO {biblio_field_type} (" . implode(", ", $field_type_fieldnames) . ") + VALUES('" . implode("', '", $values) . "')"); + } + $ftd = array($field['fid'], $field->default_name, $field->hint); + db_query("INSERT INTO {biblio_field_type_data} (" . implode(", ", $field_type_data_fieldnames) . ") + VALUES('" . implode("', '", $ftd) . "')"); + $field_data = array($field['fid'], $field->field_name, $field->type, $field->width, $field->maxlength); + db_query("INSERT INTO {biblio_fields} (" . implode(", ", $fieldnames) . ") + VALUES('" . implode("', '", $field_data) . "')"); + foreach ($field->name as $name) { + if ($name != "~" ) { //&& $field->type != 'contrib_widget') { + $ftd[0] = ($existing_id = _id_by_name('biblio_field_type_data', $name)) ? $existing_id : variable_get('biblio_last_ftdid', 100); // ftdid + $ftd[1] = trim($name); // title + $ftd[2] = ""; // hint + db_query("UPDATE {biblio_field_type} + SET ftdid = %d, cust_tdid = %d, visible = %d + WHERE tid = %d AND fid = %d ", $ftd[0], $ftd[0], 1, $name['tid'], $field['fid'] ); + if (!$existing_id) { + // if this title doesn't alreay exist, then insert it into the table + db_query("INSERT INTO {biblio_field_type_data} (" . implode(", ", $field_type_data_fieldnames) . ") + VALUES (%d, '%s', '%s')", $ftd); + _id_by_name('biblio_field_type_data', $name, $ftd[0]); // cache the new id value for future use + variable_set('biblio_last_ftdid', $ftd[0] +1); //increment the field type data id by one. + } + + } + elseif ($name == "~" ) { + // turn the visibility off for this (~) type + db_query("UPDATE {biblio_field_type} + SET visible = 0 + WHERE tid = %d AND fid = %d ", $name['tid'], $field['fid'] ); + } + if ($field->type == 'contrib_widget' && $name != "~" ) { + db_query("UPDATE {biblio_contributor_type} SET auth_type=%d where auth_category=%d and biblio_type=%d", $ftd[0], $field->contrib_type, $name['tid']); + } + } + } + + + + db_query("/*!40000 ALTER TABLE {biblio_field_type_data} ENABLE KEYS */;"); + db_query("/*!40000 ALTER TABLE {biblio_fields} ENABLE KEYS */;"); + + return $result; +} + +function _add_db_field_data() { + if (db_driver() == 'mysql' or db_driver() == 'mysqli') { + db_query("/*!40000 ALTER TABLE {biblio_field_type_data} DISABLE KEYS */;"); + db_query("/*!40000 ALTER TABLE {biblio_fields} DISABLE KEYS */;"); + } + $csv_file = drupal_get_path('module', 'biblio') . '/misc/biblio.field.link.data.csv'; + + if ($handle = fopen($csv_file, "r")) { + $header = fgetcsv($handle, 10000, ","); // the first line has the field names + while (($row = fgetcsv($handle, 10000, ",")) !== FALSE) { + $column = 0; + // add link data for default biblio type (0) and all other defined types (100-130) + foreach (array_merge(array(0), range(100, 136)) as $t) { + db_insert('biblio_field_type')->fields(array( + 'tid' => $t, + 'fid' => $row[0], + 'ftdid' => $row[0], + 'cust_tdid' => $row[0], + 'common' => $row[3], + 'autocomplete' => $row[4], + 'required' => $row[5], + 'weight' => $row[6], + 'visible' => $row[7], + 'vtab' => $row[12] + ))->execute(); + } + + db_insert('biblio_field_type_data')->fields(array( + 'ftdid' => $row[0], + 'title' => $row[1], + 'hint' => $row[2] + ))->execute(); + + db_insert('biblio_fields')->fields(array( + 'fid' => $row[0], + 'name' => $row[8], + 'type' => $row[9], + 'size' => $row[10], + 'maxsize' => $row[11] + ))->execute(); + + // add contributor type data + if ($row[9] == 'contrib_widget') { + // use field name without trailing 's' as initial guess for author type + $auth_type = (substr($row[1], -1, 1) == 's') ? substr($row[1], 0, -1) : $row[1]; + + db_insert('biblio_contributor_type_data')->fields(array( + 'auth_type' => $row[0], + 'title' => $auth_type + ))->execute(); + + db_insert('biblio_contributor_type')->fields(array( + 'auth_category' => $row[0], + 'biblio_type' => 0, + 'auth_type' => $row[0] + ))->execute(); + } + } + fclose($handle); + $result = array('success' => TRUE, 'query' => 'Added field titles and default values'); + + } + else { + $result = array('success' => FALSE, 'query' => 'Could not open ' . $csv_file); + } + + if (db_driver() == 'mysql' or db_driver() == 'mysqli') { + db_query("/*!40000 ALTER TABLE {biblio_field_type_data} ENABLE KEYS */;"); + db_query("/*!40000 ALTER TABLE {biblio_fields} ENABLE KEYS */;"); + } + return $result; +} + +function _add_custom_field_data() { + + $next_ctdid=10; //first contributor_type_data id + $schema = biblio_schema(); + $fieldnames = array_keys($schema['biblio_field_type_data']['fields']); + + $query = "SELECT fid, name FROM {biblio_fields} "; + $res = db_query($query); + foreach ($res as $row) { + $fieldmap[$row->name] = $row->fid; + } + + $csv_file = drupal_get_path('module', 'biblio') . '/misc/biblio.field.type.data.csv'; + + if ($handle = fopen($csv_file, "r")) { + $header = fgetcsv($handle, 10000, ","); // the first line has the field names + $generic = fgetcsv($handle, 10000, ","); // the second line has the default titles if none given + // build cache lookups + _id_by_name(NULL, NULL, NULL, array('tablename' => 'biblio_field_type_data', 'name_column' => 'title', 'id_column' => 'ftdid')); + _id_by_name(NULL, NULL, NULL, array('tablename' => 'biblio_contributor_type_data', 'name_column' => 'title', 'id_column' => 'auth_type')); + // map contributor field titles to field ids + $res = db_query("SELECT fid,name FROM {biblio_fields} WHERE type='contrib_widget'"); + $contributor_categories = array(); + foreach ($res as $row ) { + $contributor_categories[$row->name] = $row->fid; + } + // process all rows of the file + while (($row = fgetcsv($handle, 10000, ",")) !== FALSE) { + $column = 0; + if (empty($row[1])) continue; + + foreach ($header as $key => $field_name) { + if (!empty($field_name) && $field_name != 'tid') { + if (!empty($row[$column]) && $row[$column] != "~" && isset($fieldmap[$field_name])) { + $ftd[0] = ($existing_id = _id_by_name('biblio_field_type_data', $row[$column])) ? $existing_id : variable_get('biblio_last_ftdid', 100); // ftdid + $ftd[1] = trim($row[$column]); // title + $ftd[2] = ""; // hint + + db_update('biblio_field_type') + ->fields(array( 'ftdid' => $ftd[0], 'cust_tdid' => $ftd[0], 'visible' => 1)) + ->condition(db_and()->condition('tid', $row[1])->condition('fid', $fieldmap[$field_name])) + ->execute(); + + if (!$existing_id) { + // if this title doesn't alreay exist, then insert it into the table + db_insert('biblio_field_type_data') + ->fields(array('ftdid' => $ftd[0], 'title' => $ftd[1], 'hint' => $ftd[2])) + ->execute(); + + _id_by_name('biblio_field_type_data', $row[$column], $ftd[0]); // cache the new id value for future use + variable_set('biblio_last_ftdid', $ftd[0] +1); //increment the field type data id by one. + } + + // also populate biblio_contributor_type tables + if ((substr($field_name, -7, 7) == 'authors') && $row[$column] != '~' ) { + $type = $contributor_categories[$field_name]; + $title = trim($row[$column]); + $biblio_type = $row[1]; + $ctdid = ($eid = _id_by_name('biblio_contributor_type_data', $title)) ? $eid : $next_ctdid; + db_update('biblio_contributor_type') + ->fields(array( + 'auth_type' => $ctdid)) + ->condition(db_and()->condition('auth_category', $type)->condition('biblio_type', $biblio_type)) + ->execute(); + + if (!$eid) { + db_insert('biblio_contributor_type_data') + ->fields(array('auth_type' => $ctdid, 'title' => $title)) + ->execute(); + + _id_by_name('biblio_contributor_type_data', $title, $ctdid); // cache the new id value for future use + $next_ctdid++; + } + } + } + elseif ($row[$column] == "~" && isset($fieldmap[$field_name])) { + // turn the visibility off for this (~) type + + db_update('biblio_field_type') + ->fields(array('visible' => 0)) + ->condition(db_and()->condition('tid', $row[1])->condition('fid', $fieldmap[$field_name])) + ->execute(); + + } + elseif (empty($row[$column]) && isset($fieldmap[$field_name])) { + // use the default field title when the title is blank + db_update('biblio_field_type') + ->fields(array('visible' => 1)) + ->condition(db_and()->condition('tid', $row[1])->condition('fid', $fieldmap[$field_name])) + ->execute(); + } + } + $column++; + } + } + fclose($handle); + $result = array('success' => TRUE, 'query' => 'Added type specific field titles'); + } + else { + $result = array('success' => FALSE, 'query' => 'Could not open ' . $csv_file); + } + + return $result; +} +function _id_by_name($table, $name, $id = NULL, $build = NULL) { + static $result = NULL; + if (!empty($build)) { //refresh cache from table + unset($result[$build['tablename']]); + $res = db_query("SELECT " . $build['name_column'] . ", " . $build['id_column'] . " FROM {" . $build['tablename'] . "}", array(), array('fetch' => PDO::FETCH_ASSOC)); + foreach ($res as $row ) { + $result[$build['tablename']][$row[$build['name_column']]] = $row[$build['id_column']]; + } + return; + } + $name = trim($name); + if (isset($result[$table][$name])) return $result[$table][$name]; + if ($id) $result[$table][$name] = $id; + return FALSE; +} +/* + * Removed updates 1 - 27 since they were from 5.x biblio + */ + +/* + * Removed updates 6000 - 6023 only upgrades from biblio 6.x-1.9 are supported + */ +/* add the new field -refereed- on the biblio table +*/ +function biblio_update_6024() { + + db_add_field('biblio', 'biblio_refereed', array('type' => 'varchar', 'length' => '20')); + + /* add the field data for -refereed- on the biblo_fields table + you need to get the last inserted record from biblio_fields and increment it by one + so you don't step on customized fields added via the user online interface */ + + $sql = 'SELECT fid FROM {biblio_fields} ORDER BY fid DESC'; + $lastfid = db_query_range($sql, 0, 1)->fetchField(); + $newfid = $lastfid + 1; + + db_query("INSERT INTO {biblio_fields} (fid, name, type, size, maxsize) VALUES + ($newfid, 'biblio_refereed', 'select', 0, 125)"); + + /*use the same fid and insert an entry in the biblio_field_type_data */ + db_query("INSERT INTO {biblio_field_type_data} + (ftdid, title, hint) VALUES ($newfid, 'Refereed Designation', NULL)"); + + /* get a list of unique tids from the biblio_field_type table. You want to + insert a tid,fid using the new fid for every available tid */ + + $newsql = "SELECT DISTINCT tid FROM {biblio_field_type} ORDER BY tid DESC"; + + $tidlist = db_query($newsql); + foreach ($tidlist as $tid) { + $newtid = $tid->tid ; + db_query('INSERT INTO {biblio_field_type} + (tid, fid, ftdid, cust_tdid, common, autocomplete, required, weight, visible) + VALUES (%d, %d, %d, %d, %d, %d, %d, %d, %d)', + $newtid, $newfid, $newfid, $newfid, 1, 1, 0, 1, 1); + } +} + +function biblio_update_6025() { + $schema = biblio_schema(); + db_create_table('biblio_type_maps', $schema['biblio_type_maps']); +} + +function biblio_update_6026() { + // move custom block titles stored in variable "biblio_block_title" to the block table if the title has not already been overriden + $custom_title = variable_get('biblio_block_title', ''); + if (!empty($custom_title)) { + $db_result = db_query("SELECT bid,title FROM {blocks} b where module='biblio' "); + foreach ($db_result as $block) { + if (empty ($block->title)) { + $block->title = $custom_title; + db_query("UPDATE {blocks} SET title='" . $block->title . "' WHERE bid=" . $block->bid); + } + } + variable_del('biblio_block_title'); + } +} + +function biblio_update_6027() { + // renunmber the author rank such that it is zero based accross all categories + // this only needs to be done for entries that actually have auth_categories other than 1 + require_once(drupal_get_path('module', 'biblio') . '/includes/biblio.contributors.inc'); + $result = array(); + $count = 0; + $db_result = db_query("SELECT DISTINCT(vid),nid FROM {biblio_contributor} WHERE auth_category IN (2,3,4,5) "); + $count_success = db_query("SELECT COUNT(DISTINCT(vid)) FROM {biblio_contributor} WHERE auth_category IN (2,3,4,5) ")->fetchField(); + foreach ($db_result as $node) { + $contributors = biblio_load_contributors($node->vid); + _save_contributors($contributors, $node->nid, $node->vid, $update = FALSE) ; + $count++; + } +} + +function biblio_update_6028() { +/* + * Caching is not used in 7.x CiteProc + * + $table = drupal_get_schema_unprocessed('system', 'cache'); + $table['description'] = 'Cache table for biblio to store pre-built csl objects'; + $table['fields']['serialized']['default'] = 1; +*/ +} + +function biblio_update_6029() { + $spec = array( + 'type' => 'blob', + 'not null' => FALSE, + 'default' => NULL, + 'size' => 'big', + 'description' => 'Stores the mapping between biblio fields and external file formats', + ); + db_add_field('biblio_type_maps', 'export_map', $spec); +} + +function biblio_update_6030() { + + $spec = array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'unsigned' => TRUE, + 'description' => 'Determines if the author name is allowed to be reformated by the variaous styles or should be used literally.', + ); + db_add_field('biblio_contributor_data', 'literal', $spec); + +} + +function biblio_update_6031() { + $result = array(); + $types[] = array(131, 'Journal', NULL, 3); + $types[] = array(132, 'Web site', NULL, 8); + $types[] = array(133, 'Web service','e.g. Google, Yahoo', 8); + $types[] = array(134, 'Web project page', NULL, 8); + $types[] = array(135, 'Presentation', NULL, 8); + $types[] = array(136, 'Newspaper', NULL, 8); + + foreach ($types as $record) { + db_query("INSERT INTO {biblio_types} (tid, name, description, weight) VALUES ('" . implode("', '", $record) . "')"); + } + + db_query("DELETE FROM {biblio_types} WHERE tid=-1"); + + return $result; +} + +function biblio_update_6032() { + $spec = array( + 'type' => 'varchar', + 'length' => '255', + 'not null' => TRUE, + 'default' => '', + 'description' => 'Full name', + ); + db_change_field('biblio_contributor_data', 'name', 'name', $spec); +} +function biblio_update_6033() { + $spec = array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '64', + 'description' => 'A normalized version of the title, used for sorting on titles. (only first 64 characters saved)', + ); + db_add_field('biblio', 'biblio_sort_title', $spec); +} + +function biblio_update_7000() { + + _biblio_helper_modules('install'); + +} +/** + * Add new column to biblio_contributor_data table + */ +function biblio_update_7001() { + if (!db_field_exists('biblio_contributor_data', 'literal')) { + $spec = array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'unsigned' => TRUE, + 'description' => 'Determines if the author name is allowed to be reformated by the variaous styles or should be used literally.', + ); + db_add_field('biblio_contributor_data', 'literal', $spec); + } +} +/** + * + * Adds export_map column to biblio_type_maps table + */ +function biblio_update_7002() { + if (!db_field_exists('biblio_type_maps', 'export_map')) { + biblio_update_6029(); + } +} +/** + * + * Adds some new publication types + */ +function biblio_update_7003() { + $result = db_query('SELECT tid FROM {biblio_types} WHERE tid = :tid', array(':tid' => 136))->fetchField(); + if (!$result) { + biblio_update_6031(); + } +} + +function _biblio_update_field_link_data($range, $vtabs = FALSE) { + $csv_file = drupal_get_path('module', 'biblio') . '/misc/biblio.field.link.data.csv'; + + if ($handle = fopen($csv_file, "r")) { + $header = fgetcsv($handle, 10000, ","); // the first line has the field names + while (($row = fgetcsv($handle, 10000, ",")) !== FALSE) { + if ($vtabs) { + // add link data for default biblio type (0) and all other defined types (100-130) + foreach (array_merge(array(0), range($range[0], $range[1])) as $t) { + db_update('biblio_field_type') + ->fields(array( + 'vtab' => $row[12] + )) + ->condition(db_and()->condition('tid', $t)->condition('fid', $row[0])) + ->execute(); + } + } + else { + foreach (range($range[0], $range[1]) as $t) { + db_insert('biblio_field_type')->fields(array( + 'tid' => $t, + 'fid' => $row[0], + 'ftdid' => $row[0], + 'cust_tdid' => $row[0], + 'common' => $row[3], + 'autocomplete' => $row[4], + 'required' => $row[5], + 'weight' => $row[6], + 'visible' => $row[7], + 'vtab' => $row[12] + ))->execute(); + } + } + } + } + +} + +/** + * Add information to manage vtabs on input form. +*/ +function biblio_update_7005() { + $spec = array( + 'type' => 'int', + 'not null' => TRUE, + 'unsigned' => TRUE, + 'default' => 0, + ); + db_add_field('biblio_field_type', 'vtab', $spec); + _biblio_update_field_link_data(array(100, 130), TRUE); + cache_clear_all(); +} + +function biblio_update_7006() { + $result = db_query('SELECT fid FROM {biblio_field_type} WHERE tid = :tid', array(':tid' => 136))->fetchField(); + if (!$result) { + _biblio_update_field_link_data(array(131, 136)); + cache_clear_all(); + } +} +/** + * Increases the size of the {biblio_contributor_data}.name column to 255 characters +*/ +function biblio_update_7007() { + $spec = array( + 'type' => 'varchar', + 'length' => '255', + 'not null' => TRUE, + 'default' => '', + 'description' => 'Full name', + ); + db_change_field('biblio_contributor_data', 'name', 'name', $spec); +} +/** + * Adds new "biblio_sort_title" column to the biblio table, which is used for title sorting. +*/ +function biblio_update_7008() { + if (!db_field_exists('biblio', 'biblio_sort_title')) { + biblio_update_6033(); + } +} + +/** + * Populates the new "biblio_sort_title" column, which is used for title sorting. +*/ +function biblio_update_7009(&$sandbox) { + $sandbox['#finished'] = 0; + module_load_include('inc', 'biblio', '/includes/biblio.util'); + + if (!isset($sandbox['max'])) { + $sandbox['max'] = db_query('SELECT COUNT(DISTINCT vid) FROM {node} n WHERE n.type = :type', array(':type' => 'biblio'))->fetchField(); + $sandbox['current_vid'] = 0; + } + + $nodes = db_select('node', 'n') + ->fields('n', array('vid', 'title')) + ->condition('vid', $sandbox['current_vid'], '>') + ->condition('type', 'biblio') + ->range(0, 20) + ->orderBy('vid', 'ASC') + ->execute(); + + foreach ($nodes as $node) { + $node->biblio_sort_title = biblio_normalize_title($node->title); + db_update('biblio') + ->fields(array('biblio_sort_title' => $node->biblio_sort_title)) + ->condition('vid', $node->vid) + ->execute(); + + $sandbox['progress']++; + $sandbox['current_vid'] = $node->vid; + } + + $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']); +} +/** + * Removes "biblio_inlinemode_in_links" variable + */ +function biblio_update_7010() { + variable_del('biblio_inlinemode_in_links'); +} +/** + * Add a body field instance + */ +function biblio_update_7011() { + $content_type = node_type_load('biblio'); + node_add_body_field($content_type, 'Full text'); +} +/** + * Update biblio_field_type table + */ +function biblio_update_7012() { + + // there was a problem with update 7006 and it might no have done anything so lets try again. + biblio_update_7006(); +} + +function biblio_update_7013() { + db_add_index('biblio', 'title_sort', array('biblio_sort_title')); + db_add_index('biblio', 'date', array('biblio_date')); + +} + +/** + * + * Widen the biblio_date column to 64 characters + */ +function biblio_update_7014() { + $spec = array( + 'type' => 'varchar', + 'not null' => FALSE, + 'length' => '64', + 'description' => '', + ); + db_change_field('biblio', 'biblio_date', 'biblio_date', $spec); + +} +/** + * + * Add biblio_formats column to biblio table to hold the format information for each text area + */ +function biblio_update_7015() { + if (!db_field_exists('biblio', 'biblio_formats')) { + $spec = array( + 'type' => 'blob', + 'not null' => FALSE, + 'description' => '', + 'serialize' => TRUE, + ); + db_add_field('biblio', 'biblio_formats', $spec); + } +} +/** + * Convert textarea fields to text_format + */ +function biblio_update_7016() { + db_update('biblio_fields') + ->fields(array('type' => 'text_format')) + ->condition('type', 'textarea') + ->execute(); +} + +/** + * Remove views export handlers in sub-modules (if they still exist) + */ +function biblio_update_7017() { + $dirs = array('bibtexParse', 'endnote', 'RIS', 'rtf'); + foreach ($dirs as $dir) { + $path = drupal_get_path('module', 'biblio') . '/modules/' . $dir . '/views'; + if (is_dir($path)) { + $message = t('You have an inconsistancy in your installation, the directory: @path, should not exist!', array('@path' => $path)); + drupal_set_message($message, 'error'); + } + } + if (module_exists('views')) { // rebuild the data tables + views_invalidate_cache(); + } +} +/** + * + * Widen the biblio_contributor_data.lastname column to 255 characters + */ +function biblio_update_7018() { + $spec = array( + 'type' => 'varchar', + 'length' => '255', + 'not null' => TRUE, + 'default' => '', + 'description' => 'Author last name', + ); + db_change_field('biblio_contributor_data', 'lastname', 'lastname', $spec); + +} +/** + * + * Change biblio_contributor_data.cid to a signed int + */ + +function biblio_update_7019() { + +} + +/** + * + * Change the primary key of the biblio_contributor_data table + */ +function biblio_update_7020() { + $driver = db_driver(); + if ($driver == 'mysql') { + db_query('ALTER TABLE `biblio_contributor_data` DROP PRIMARY KEY , ADD PRIMARY KEY ( `cid` )'); + } + if ($driver == 'pgsql') { + db_drop_primary_key('biblio_contributor_data'); + db_add_primary_key('biblio_contributor_data', array('cid')); + } +} +/** + * + * Add alt_form column to the biblio_contributor_data table + */ +function biblio_update_7021() { + if (!db_field_exists('biblio_contributor_data', 'alt_form')) { + $spec = array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'unsigned' => TRUE, + 'description' => 'Alternate form of an author name, this value points to the desired form (cid), this form is kept in the database so that future imports of the same name will not create a new author.', + ); + db_add_field('biblio_contributor_data', 'alt_form', $spec); + } +} +/** + * + * Add merge_cid column to the biblio_contributor_data table + */ +function biblio_update_7022() { + if (!db_field_exists('biblio_contributor', 'merge_cid')) { + $spec = array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'unsigned' => TRUE, + 'description' => '', + ); + db_add_field('biblio_contributor', 'merge_cid', $spec); + } +} + +/** + * + * Re-apply update 7014 in case the install happened after 7014 was implemented. The main scheme definition was not changed at that time to match the update resulting a schema mismatch. + * + */ +function biblio_update_7023() { + biblio_update_7014(); +} +/** + * + * Re-apply update 7022 in case the install happened after 7022 was implemented. The main scheme definition was not changed at that time to match the update resulting a schema mismatch. + * + */ + +function biblio_update_7024() { + biblio_update_7022(); +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/biblio.module --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/biblio.module Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,2259 @@ +auth_category][$row->biblio_type][] = $row->auth_type; + } + } + // fall back to defaults, if no author types are defined for this biblio_type + $result = isset($auth_types[$auth_category][$biblio_type])?$auth_types[$auth_category][$biblio_type]:$auth_types[$auth_category][0]; + return $result; +} +function _biblio_get_auth_type($auth_category, $biblio_type) { + $result = (array)_biblio_get_auth_types($auth_category, $biblio_type); + // return first element of the array + return empty($result) ? NULL : current($result); +} + +/** + * Translate field titles and hints through the interface translation system, if + * the i18nstrings module is enabled. + */ +function _biblio_localize_fields(&$fields) { + if (function_exists('i18n_string')) { + foreach ($fields as $key => $row) { + $fields[$key]['title'] = i18n_string("biblio:field:{$row['ftdid']}:title", $fields[$key]['title']); + $fields[$key]['hint'] = i18n_string("biblio:field:{$row['ftdid']}:hint", $fields[$key]['hint']); + } + } +} + +/** + * Translate a publication type through the interface translation system, if + * the i18nstrings module is enabled. + * + * @param integer $tid + * The biblio publication type identifier. + * + * @param string $value + * The string to translate. + * + * @param string $field + * The publication type field to translate (either 'name' or 'description'). + * + * @return + * Translated value. + */ +function _biblio_localize_type($tid, $value, $field = 'name') { + if (function_exists('i18n_string')) { + return i18n_string("biblio:type:$tid:$field", $value); + } + return $value; +} + +/** + * Implementation of hook_locale(). + */ +function biblio_locale($op = 'groups', $group = NULL) { + switch ($op) { + case 'groups': + return array('biblio' => t('Biblio')); + + case 'refresh': + if ($group == 'biblio') { + biblio_locale_refresh_fields(); + biblio_locale_refresh_types(); + } + break; + } +} + +/** + * Refresh all translatable field strings. + * + * @param integer $tid + * Biblio publication type id whose field strings are to be refreshed. If not + * specified, strings for all fields will be refreshed. + */ +function biblio_locale_refresh_fields($tid = NULL) { + if (function_exists('i18n_string')) { + if (isset($tid)) { + $result = db_query('SELECT d.* FROM {biblio_field_type} b INNER JOIN {biblio_field_type_data} d ON b.ftdid = d.ftdid WHERE tid = :tid', array(':tid' => $tid)); + } + else { + $result = db_query('SELECT * FROM {biblio_field_type_data}'); + } + $options = array('translate' => FALSE, 'update' => TRUE); + foreach ($result as $row) { + i18n_string("biblio:field:{$row->ftdid}:title", $row->title, $options); + i18n_string("biblio:field:{$row->ftdid}:hint", $row->hint, $options); + } + } +} + +/** + * Refresh all publication type strings. + * + * @param integer $tid + * Biblio publication type id whose field strings are to be refreshed. If not + * specified, strings for all fields will be refreshed. + */ +function biblio_locale_refresh_types($tid = NULL) { + if (function_exists('i18n_string')) { + if (isset($tid)) { + $result = db_query('SELECT * FROM {biblio_types} WHERE tid = :tid', array(':tid' => $tid)); + } + else { + $result = db_query('SELECT * FROM {biblio_types} WHERE tid > 0'); + } + $options = array('translate' => FALSE, 'update' => TRUE); + foreach ($result as $row ) { + i18n_string("biblio:type:{$row->tid}:name", $row->name, $options); + i18n_string("biblio:type:{$row->tid}:description", $row->description, $options); + } + } +} + +function biblio_init() { + global $user, $conf; + drupal_add_css(drupal_get_path('module', 'biblio') . '/biblio.css'); + + if ($user->uid === 0) { // Prevent caching of biblio pages for anonymous users so session variables work and thus filering works + $base = variable_get('biblio_base', 'biblio'); + if (drupal_match_path($_GET['q'], "$base\n$base/*")) + $conf['cache'] = FALSE; + } +} + +function biblio_cron() { + require_once(drupal_get_path('module', 'biblio') .'/includes/biblio.contributors.inc'); + require_once(drupal_get_path('module', 'biblio') .'/includes/biblio.keywords.inc'); + + $interval = variable_get('biblio_orphan_clean_interval', 24*60*60); //defaults to once per day + + if (time() >= variable_get('biblio_orphan_clean_next_execution', 0)) { + biblio_delete_orphan_authors(); + biblio_delete_orphan_keywords(); + variable_set('biblio_orphan_clean_next_execution', time() + $interval); + } +} + +function biblio_theme($existing, $type, $theme, $path) { + $path = drupal_get_path('module', 'biblio'); + return array( + 'biblio_alpha_line' => array( + 'file' => '/includes/biblio_theme.inc', + 'variables' => array( + 'type' => 'author', + 'current' => NULL, + 'path' => NULL), + ), + 'biblio_admin_keyword_edit_form' => array( + 'file' => '/includes/biblio.admin.inc', + 'render element' => 'form', + ), + 'biblio_admin_author_types_form' => array( + 'file' => '/includes/biblio.admin.inc', + 'render element' => 'form', + ), + 'biblio_admin_type_mapper_form' => array( + 'file' => '/includes/biblio.admin.inc', + 'render element' => 'form', + ), + 'biblio_admin_io_mapper_form'=> array( + 'file' => '/includes/biblio.admin.inc', + 'render element' => 'form', + ), + 'biblio_admin_io_mapper_add_form'=> array( + 'file' => '/includes/biblio.admin.inc', + 'render element' => 'form', + ), + 'biblio_admin_field_mapper_form' => array( + 'file' => '/includes/biblio.admin.inc', + 'render element' => 'form', + ), + 'biblio_admin_types_edit_form' => array( + 'file' => '/includes/biblio_theme.inc', + 'render element' => 'form', + ), + 'biblio_admin_types_form' => array( + 'file' => '/includes/biblio_theme.inc', + 'render element' => 'form', + ), + 'biblio_field_tab' => array( + 'file' => '/includes/biblio_theme.inc', + 'render element' => 'form', + ), + 'biblio_admin_author_edit_form' => array( + 'file' => '/includes/biblio_theme.inc', + 'render element' => 'form', + ), + 'biblio_admin_author_edit_merge_table' => array( + 'file' => '/includes/biblio_theme.inc', + 'render element' => 'form', + ), + 'biblio_openurl' => array( + 'file' => '/includes/biblio_theme.inc', + 'variables' => array('openURL'), + ), + 'biblio_style' => array( + 'file' => '/includes/biblio_theme.inc', + 'variables' => array( + 'node' => NULL, + 'style_name' => 'classic', + ), + ), + 'biblio_long' => array( + 'file' => '/includes/biblio_theme.inc', + 'variables' => array( + 'node' => NULL, + 'base' => 'biblio', + 'style_name' => 'classic'), + ), + 'biblio_tabular' => array( + 'file' => '/includes/biblio_theme.inc', + 'variables' => array( + 'node' => NULL, + 'base' => 'biblio', + 'teaser' => FALSE), + ), + 'biblio_entry' => array( + 'file' => '/includes/biblio_theme.inc', + 'variables' => array( + 'node', + 'style_name' => 'classic', + ), + ), + 'biblio_format_authors' => array( + 'file' => '/includes/biblio_theme.inc', + 'variables' => array( + 'contributors' => NULL, + 'options' => array(), + ), + ), + 'biblio_page_number' => array( + 'file' => '/includes/biblio_theme.inc', + 'variables' => array( + 'orig_page_info' => NULL, + 'page_range_delim' => "-", + 'single_page_prefix' => '', + 'page_range_prefix' => '', + 'total_pages_prefix' => '', + 'single_page_suffix' => '', + 'page_range_suffix' => '', + 'total_pages_suffix' => '', + 'shorten_page_range_end' => FALSE), + ), + 'biblio_author_link' => array( + 'file' => '/includes/biblio_theme.inc', + 'variables' => array( + 'author'), + ), + 'biblio_filters' => array( + 'file' => '/includes/biblio_theme.inc', + 'render element' => 'form', + ), + 'form_filter' => array( + 'file' => '/includes/biblio_theme.inc', + 'render element' => 'form', + ), + 'biblio_export_links' => array( + 'file' => '/includes/biblio_theme.inc', + 'variables' => array( + 'node' => NULL, + 'filter' => array()), + ), + 'biblio_download_links' => array( + 'file' => '/includes/biblio_theme.inc', + 'variables' => array('node'), + ), + 'google_scholar_link' => array( + 'file' => '/includes/biblio_theme.inc', + 'variables' => array('node'), + ), + 'biblio_contributors' => array( + 'file' => '/includes/biblio_theme.inc', + 'render element' => 'form', + ), + 'biblio_sort_tabs' => array( + 'file' => 'includes/biblio_theme.inc', + 'variables' => array(), + ) + ); +} + +function biblio_autocomplete($field, $string = '') { + $matches = array(); + switch ($field) { + case 'contributor': + case 'a': + $result = db_query_range("SELECT name FROM {biblio_contributor_data} WHERE LOWER(lastname) LIKE LOWER(:name) OR LOWER(firstname) LIKE LOWER(:firstname) ORDER BY lastname ASC ", 0, 10, array(':name' => $string . '%', ':firstname' => $string . '%')); + foreach ($result as $data ) { + $matches[$data->name] = check_plain($data->name); + } + break; + case 'biblio_keywords': + case 'k': + $sep = check_plain(variable_get('biblio_keyword_sep', ',')); + $sep_pos = strrpos($string, $sep); //find the last separator + $start = trim(drupal_substr($string, 0, $sep_pos)); // first part of the string upto the last separator + $end_sep = ($sep_pos) ? $sep_pos + 1 :$sep_pos; + $end = trim(drupal_substr($string, $end_sep)) . '%'; // part of the string after the last separator + $result = db_query_range("SELECT * FROM {biblio_keyword_data} WHERE LOWER(word) LIKE LOWER(:end) ORDER BY word ASC ", 0, 10, array(':end' => $end)); + foreach ($result as $data) { + // now glue the word found onto the end of the original string... + $keywords = ($sep_pos) ? $start . ', ' . check_plain($data->word) : check_plain($data->word); + $matches[$keywords] = $keywords; + } + break; + + default: + $field = drupal_strtolower($field); + $string = '%' . drupal_strtolower($string) . '%'; + $query = db_select('biblio', 'b') + ->fields('b', array($field)) + ->condition($field, $string, 'LIKE') + ->orderBy($field, 'ASC') + ->range(0, 10); + $result = $query->execute(); + + foreach ($result as $data) { + $matches[$data->$field] = check_plain($data->$field); + } + } + print drupal_json_encode($matches); + exit(); +} + +function biblio_help_page() { + $base = variable_get('biblio_base', 'biblio'); + $text = "

" . t('General:') . "

"; + $text .= "

" . t('By default, the !url page will list all of the entries in the database sorted by Year in descending order. If you wish to sort by "Title" or "Type", you may do so by clicking on the appropriate links at the top of the page. To reverse the sort order, simply click the link a second time.', array( + '!url' => l('', + $base + ))) . "

"; + $text .= "

" . t('Filtering Search Results:') . "

"; + $text .= "

" . t('If you wish to filter the results, click on the "Filter" tab at the top of the page. To add a filter, click the radio button to the left of the filter type you wish to apply, then select the filter criteria from the drop down list on the right, then click the filter button.') . "

"; + $text .= "

" . t('It is possible to create complex filters by returning to the Filter tab and adding additional filters. Simply follow the steps outlined above and press the "Refine" button.') . "

"; + $text .= "

" . t('All filters can be removed by clicking the Clear All Filters link at the top of the result page, or on the Filter tab they can be removed one at a time using the Undo button, or you can remove them all using the Clear All button.') . "

"; + $text .= "

" . t('You may also construct URLs which filter. For example, /biblio/year/2005 will show all of the entries for 2005. /biblio/year/2005/author/smith will show all of entries from 2005 for smith.') . "

"; + $text .= "

" . t('Exporting Search Results:') . "

"; + $text .= "

" . t('Assuming this option has been enabled by the administrator, you can export search results directly into EndNote. The link at the top of the result page will export all of the search results, and the links on individual entries will export the information related to that single entry.') . "

"; + $text .= "

" . t('The information is exported in EndNote "Tagged" format similar to this...') . "

" . t('
+                  %0  Book
+                  %A  John Smith
+                  %D  1959
+                  %T  The Works of John Smith
+                  ...') . '

'; + $text .= "

" . t('Clicking on one of the export links should cause your browser to ask you whether you want to Open, or Save To Disk, the file endnote.enw. If you choose to open it, Endnote should start and ask you which library you would like store the results in. Alternatively, you can save the file to disk and manually import it into EndNote.') . "

"; + return ($text); +} +/** + * Implementation of hook_help(). + * + * Throughout Drupal, hook_help() is used to display help text at the top of + * pages. Some other parts of Drupal pages get explanatory text from these hooks + * as well. We use it here to provide a description of the module on the + * module administration page. + */ + +function biblio_help($path, $arg) { + switch ($path) { + case 'admin/help#biblio' : + return biblio_help_page(); + case 'admin/modules#description' : + // This description is shown in the listing at admin/modules. + return t('Manages a list of scholarly papers on your site'); + case 'node/add#biblio' : + // This description shows up when users click "create content." + return t('This allows you to add a bibliographic entry to the database'); + } +} + +function biblio_node_info() { + return array( + 'biblio' => array( + 'name' => t('Biblio'), + 'base' => 'biblio', + 'description' => t('Use Biblio for scholarly content, such as journal papers and books.'), + ) + ); +} + +function biblio_node_access($node, $op, $account) { + if (is_string($node)) { + return NODE_ACCESS_IGNORE; + } + + if ($node->type != 'biblio') { // we only care about biblio nodes + return NODE_ACCESS_IGNORE; + } + switch ($op) { + case 'view': + if (((variable_get('biblio_view_only_own', 0)) && $account->uid != $node->uid) || + !user_access('access biblio content')){ + return NODE_ACCESS_DENY; + } + break; + case 'update': + case 'delete': + if (user_access('edit by all biblio authors') && isset($node->biblio_contributors) && is_array($node->biblio_contributors)) { + foreach ($node->biblio_contributors as $key => $author) { + if ((isset($author['drupal_uid']) && $author['drupal_uid'] == $account->uid) || + (isset($account->data['biblio_contributor_id']) && $author['cid'] == $account->data['biblio_contributor_id'])) { + return NODE_ACCESS_ALLOW; + } + } + } + break; + default: + } + return NODE_ACCESS_IGNORE; +} + +function biblio_access($op, $node = '') { + global $user; + + switch ($op) { + case 'admin': + return user_access('administer biblio'); + case 'import': + return user_access('import from file'); + case 'export': + return user_access('show export links'); + case 'edit_author': + if (user_access('administer biblio') || user_access('edit biblio authors')) return NODE_ACCESS_ALLOW; + break; + case 'download': + if (user_access('show download links') || (user_access('show own download links') && ($user->uid == $node->uid))) return NODE_ACCESS_ALLOW; + break; + case 'rss': + return variable_get('biblio_rss', 0); + default: + } + return NODE_ACCESS_IGNORE; +} +/** + * Implementation of hook_permission(). + * + * Since we are limiting the ability to create new nodes to certain users, + * we need to define what those permissions are here. We also define a permission + * to allow users to edit the nodes they created. + */ +function biblio_permission() { + return array( + 'administer biblio' => array( + 'title' => t('Administer Biblio'), + 'description' => t('Allows full control (create, update, delete) of all Biblio nodes'), + ), + 'access biblio content' => array( + 'title' => t('Access Biblio content'), + 'description' => t('Allows the user to view Biblio nodes'), + ), +// 'create biblio' => array( +// 'title' => t('Create Biblio'), +// 'description' => t('Allows the user to create new Biblio nodes'), +// ), +// 'edit all biblio entries' => array( +// 'title' => t('Edit all Biblio entries'), +// 'description' => t('Allows the user to edit ALL biblio entries regardless of who "owns" them, otherwise they are restricted to on'), +// ), + 'edit by all biblio authors' => array( + 'title' => t('Edit by all Biblio authors'), + 'description' => t('Allows any/all of the authors associated with a biblio entry to edit the biblio entry. This requires the Drupal UserID be mapped to a Biblio author ID'), + ), + 'edit biblio authors' => array( + 'title' => t('Edit Biblio authors'), + 'description' => t('Allows the user to edit author information'), + ), + 'import from file' => array( + 'title' => t('Import from file'), + 'description' => t('Allows the user to import bibliographic data from files such as BibTex, RIS, EndNote'), + ), + 'show export links' => array( + 'title' => t('Show export links'), + 'description' => t('Allows users to see links which allow export of bibliographic data for an individual entry or the entire result set'), + ), + 'show download links' => array( + 'title' => t('Show download links'), + 'description' => t('Allows users to see links to any attachements associated with the Biblio entry'), + ), + 'show own download links' => array( + 'title' => t('Show own download links'), + 'description' => t('Allows user to only see download links on entries for which they are the owner.'), + ), + 'show filter tab' => array( + 'title' => t('Show filter tab'), + 'description' => t('This determines if the "Filter" tab on the Biblio list page will be shown to the user'), + ), + 'show sort links' => array( + 'title' => t('Show sort links'), + 'description' => t('This determines if the "Sort" links on the Biblio list page will be shown to the user'), + ), + 'view full text' => array( + 'title' => t('Show full text'), + 'description' => t('This determines if the user will be able to access the "Full Text" of the article if it is available'), + ), + ); +} + +/** + * Implementation of hook_user(). + */ +function biblio_form_user_profile_form_alter(&$form, &$form_state, $form_id) { + if ($form['#user_category'] == 'account') { + $account = $form['#user']; + include_once drupal_get_path('module', 'biblio') . '/includes/biblio.admin.inc'; + $show_form = variable_get('biblio_show_user_profile_form', '1') || + variable_get('biblio_show_crossref_profile_form', '1') || + variable_get('biblio_show_openurl_profile_form', '1'); + + $admin_show_form = ($account->uid == 1 || (user_access('administer users') && user_access('administer biblio'))) ? TRUE : FALSE; + if ($admin_show_form || $show_form) { + $form['biblio_fieldset'] = array( + '#type' => 'fieldset', + '#title' => t('Biblio settings'), + '#weight' => 5, + '#collapsible' => TRUE, + '#collapsed' => FALSE, + ); + if ($admin_show_form || variable_get('biblio_show_user_profile_form', '1')) { + $form['biblio_fieldset'] += _biblio_get_user_profile_form($account); + } + else { + $form['biblio_fieldset'] += _biblio_drupal_author_user_map($account); + } + if ($admin_show_form || variable_get('biblio_show_openurl_profile_form', '1')) { + $form['biblio_fieldset'] += _biblio_get_user_openurl_form($account); + } + if ($admin_show_form || variable_get('biblio_show_crossref_profile_form', '1')) { + $form['biblio_fieldset'] += _biblio_get_user_doi_form($account); + } + } + } +} + +function biblio_forms() { + $forms['biblio_admin_author_types_form_new'] = array( + 'callback' => 'biblio_admin_author_types_form', + ); + $forms['biblio_admin_author_types_form_edit'] = array( + 'callback' => 'biblio_admin_author_types_form', + ); + return $forms; + +} +/** + * Implementation of hook_menu(). + * + * Here we define some built in links for the biblio module, links exposed are: + * + * + */ +function biblio_menu() { + global $user; + $items = array(); + $base = variable_get('biblio_base', 'biblio'); + $base_title = check_plain(variable_get('biblio_base_title', 'Biblio')); + $items["$base"] = array( + 'title' => $base_title, + 'page callback' => 'biblio_page', + 'access callback' => 'user_access', + 'access arguments' => array('access biblio content'), + 'file' => '/includes/biblio.pages.inc', + ); + $items["$base/authors"] = array( + 'title' => 'Authors', + 'page callback' => 'biblio_author_page', + 'access callback' => 'user_access', + 'access arguments' => array('access biblio content'), + 'file' => '/includes/biblio.pages.inc', + 'weight' => 1, + ); + $items["$base/keywords"] = array( + 'title' => 'Keywords', + 'page callback' => 'biblio_keyword_page', + 'access callback' => 'user_access', + 'access arguments' => array('access biblio content'), + 'file' => '/includes/biblio.pages.inc', +// 'type' => MENU_LOCAL_TASK, + 'weight' => 2, + ); + $items["$base/import"] = array( + 'title' => 'Import', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_import_form'), + 'file' => '/includes/biblio.import.export.inc', + 'access callback' => 'user_access', + 'access arguments' => array('import from file'), + // 'type' => MENU_LOCAL_TASK, + 'weight' => 10, + ); + $items["$base/user/%"] = array( + 'title' => 'My publications', + 'page callback' => 'biblio_profile_page', + 'page arguments' => array(2), + 'access callback' => '_biblio_profile_access', + 'access arguments' => array(2, 'menu'), + 'parent' => '', + 'file' => '/includes/biblio.pages.inc', + ); + /* + $items["$base/backup"] = array( + 'title' => '', + 'page callback' => 'biblio_backup', + 'access callback' => 'user_access', + 'access arguments' => array('access content'), + 'file' => 'biblio.import.export.inc', + 'type' => MENU_CALLBACK + ); + */ + $items["$base/pot"] = array( + 'title' => '', + 'page callback' => 'biblio_dump_db_data_for_pot', + 'access callback' => 'user_access', + 'access arguments' => array('access biblio content'), + 'type' => MENU_CALLBACK + ); + + $wildcard = 2 + (count(explode("/", $base)) - 1); + + $items["$base/authors/%/edit"] = array( + 'title' => 'Edit author information', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_author_edit_form', $wildcard), + 'access callback' => 'biblio_access', + 'access arguments' => array('edit_author'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_CALLBACK + ); + $items["$base/keywords/%/edit"] = array( + 'title' => '', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_keyword_edit_form', $wildcard), + 'access callback' => 'user_access', + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_CALLBACK + ); + $items["$base/keyword/%/delete"] = array( + 'title' => 'Delete', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_keyword_delete_confirm', $wildcard), + 'access callback' => 'user_access', + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'weight' => 1, + 'type' => MENU_CALLBACK + ); + $items["$base/view/%"] = array( + 'page callback' => 'biblio_view_node', + 'page arguments' => array($wildcard), + 'access callback' => 'user_access', + 'access arguments' => array('access biblio content'), + 'file' => '/includes/biblio.pages.inc', + 'type' => MENU_CALLBACK + ); + + $items["user/%user/$base"] = array( + 'title' => 'Publications', + 'page callback' => 'biblio_profile_page', + 'page arguments' => array(1, 'profile', 'no_filters'), + 'access callback' => '_biblio_profile_access', + 'access arguments' => array(1, 'profile'), + 'file' => '/includes/biblio.pages.inc', + 'type' => MENU_LOCAL_TASK + ); + // The next two "LOCAL TASKS" are for the admin/config/content/biblio page + $items['admin/config/content/biblio'] = array( + 'title' => 'Biblio settings', + 'description' => 'Configure default behavior of the Biblio module.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_settings'), + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + ); + + $items['admin/config/content/biblio/basic'] = array( + 'title' => 'Preferences', + 'description' => 'Configure default behavior of the Biblio module.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_settings'), + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => -10 + ); + $items['admin/config/content/biblio/import'] = array( + 'title' => 'Data import', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_import_form'), + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.import.export.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => 1 + ); + $items['admin/config/content/biblio/export'] = array( + 'title' => 'Export', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_export_form'), + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.import.export.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => 2 + ); + $items['admin/config/content/biblio/fields'] = array( + 'title' => 'Fields', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_types_edit_form'), + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => -9 + ); + $items['admin/config/content/biblio/fields/common'] = array( + 'title' => 'Common', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_types_edit_form'), + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -10 + ); + $items['admin/config/content/biblio/iomap'] = array( + 'title' => 'Import/Export Mapping', + 'page callback' => 'biblio_admin_io_mapper_page', + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => -1 + ); + $items['admin/config/content/biblio/iomap/formats'] = array( + 'title' => 'Import/Export Mapping', + 'page callback' => 'biblio_admin_io_mapper_page', + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -100 + ); + $formats = module_invoke_all('biblio_mapper_options'); + foreach ($formats as $key => $format) { + $items['admin/config/content/biblio/iomap/edit/' . $key] = array( + 'title' => $format['title'], + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_io_mapper_form', 6), + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'tab_parent' => 'admin/config/content/biblio/iomap', + 'type' => MENU_LOCAL_TASK, + 'weight' => -1 + ); + } + $items['admin/config/content/biblio/iomap/%/%/add'] = array( + 'title' => '', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_io_mapper_add_form', 5, 6), + 'access arguments' => array('administer biblio'), + 'tab_parent' => 'admin/config/content/biblio/iomap', + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_CALLBACK, + 'weight' => -1 + ); + $items['admin/config/content/biblio/pubtype'] = array( + 'title' => 'Publication types', + 'page callback' => 'biblio_admin_types_form', + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => -9 + ); + $items['admin/config/content/biblio/pubtype/list'] = array( + 'title' => 'List', + 'page callback' => 'biblio_admin_types_form', + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -10 + ); + $items['admin/config/content/biblio/pubtype/delete/%'] = array( + 'title' => '', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_types_delete_form', 6), + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_CALLBACK + ); + $items['admin/config/content/biblio/pubtype/new'] = array( + 'title' => 'Add New Type', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_types_add_form'), + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => -9 + ); + $items['admin/config/content/biblio/pubtype/reset'] = array( + 'page callback' => 'biblio_admin_types_reset', + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_CALLBACK, + ); + $items['admin/config/content/biblio/fields/reset'] = array( + 'title' => 'Reset all types to defaults', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_types_reset_form'), + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_LOCAL_TASK + ); + $items['admin/config/content/biblio/pubtype/hide'] = array( + 'title' => '', + 'page callback' => 'biblio_admin_types_hide', + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_CALLBACK + ); + $items['admin/config/content/biblio/pubtype/show'] = array( + 'title' => '', + 'page callback' => 'biblio_admin_types_show', + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_CALLBACK + ); + $items['admin/config/content/biblio/author'] = array( + 'title' => 'Authors', + 'page callback' => 'biblio_author_page', + 'access callback' => 'user_access', + 'access arguments' => array('access biblio content'), + 'file' => '/includes/biblio.pages.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => -7 + ); + $items['admin/config/content/biblio/author/list'] = array( + 'title' => 'List', + 'page callback' => 'biblio_author_page', + 'access callback' => 'user_access', + 'access arguments' => array('access biblio content'), + 'file' => '/includes/biblio.pages.inc', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -7 + ); + $items['admin/config/content/biblio/author/%/edit'] = array( + 'title' => 'Edit author information', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_author_edit_form', 5), + 'access callback' => 'biblio_access', + 'access arguments' => array('edit_author'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_CALLBACK, + 'weight' => -6 + ); + $items['admin/config/content/biblio/author/orphans'] = array( + 'title' => 'Orphaned Authors', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_orphans_form'), + 'access arguments' => array('administer biblio'), + 'description' => 'Delete orphaned biblio authors.', + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => -6 + ); + $items['admin/config/content/biblio/author/type'] = array( + 'title' => 'Author Types', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_author_types_form', 7, 6), + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => -5 + ); + + $items['admin/config/content/biblio/author/type/new'] = array( + 'title' => 'Add New Author Type', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_author_types_form_new', 'new'), + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => -9 + ); + $items['admin/config/content/biblio/author/type/%/edit'] = array( + 'title' => 'Edit Author Type', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_author_types_form_edit', 'edit', 6), + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_CALLBACK, + 'weight' => -9 + ); + $items['admin/config/content/biblio/author/type/%/delete'] = array( + 'title' => 'Delete', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_author_type_delete_confirm', 6), + 'access callback' => 'user_access', + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'weight' => 1, + 'type' => MENU_CALLBACK + ); + $items['admin/config/content/biblio/keywords'] = array( + 'title' => 'Keywords', + 'page callback' => 'biblio_keyword_page', + 'access callback' => 'user_access', + 'access arguments' => array('access biblio content'), + 'file' => '/includes/biblio.pages.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => -7 + ); + $items['admin/config/content/biblio/keywords/list'] = array( + 'title' => 'List', + 'page callback' => 'biblio_keyword_page', + 'access callback' => 'user_access', + 'access arguments' => array('access biblio content'), + 'file' => '/includes/biblio.pages.inc', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -7 + ); + $items['admin/config/content/biblio/keywords/%/edit'] = array( + 'title' => 'Edit keyword information', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_keyword_edit_form', 5), + 'access callback' => 'user_access', + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_CALLBACK, + 'weight' => -6 + ); + $items['admin/config/content/biblio/keywords/orphans'] = array( + 'title' => 'Orphaned Keywords', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_keyword_orphans_form'), + 'access arguments' => array('administer biblio'), + 'description' => 'Delete orphaned biblio keywords.', + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => -6 + ); + /* $items['admin/config/content/biblio/authors/reset'] = array( + 'title' => t('Reset all Author types to defaults'), + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_author_type_reset_form'), + 'access arguments' => array('administer biblio'), + 'file' => '/includes/biblio.admin.inc', + 'type' => MENU_LOCAL_TASK + ); + */ + $items['biblio/autocomplete'] = array( + 'title' => 'Autocomplete ', + 'page callback' => 'biblio_autocomplete', + 'access callback' => 'user_access', + 'access arguments' => array('access biblio content'), + 'type' => MENU_CALLBACK + ); +/* $items["$base/list"] = array( + 'title' => 'List', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -10 + ); + $items["$base/filter"] = array( + 'title' => 'Filter', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_form_filter'), + 'access callback' => 'user_access', + 'access arguments' => array('show filter tab'), + 'type' => MENU_LOCAL_TASK, + 'file' => '/includes/biblio.pages.inc', + 'weight' => -9 + ); +*/ + $items["$base/filter/clear"] = array( + 'title' => '', + 'page callback' => 'biblio_filter_clear', + 'access callback' => 'user_access', + 'access arguments' => array('access biblio content'), + 'type' => MENU_CALLBACK + ); + $items["$base/help"] = array( + 'title' => 'Help', + 'page callback' => 'biblio_help_page', + 'access callback' => 'user_access', + 'access arguments' => array('access biblio content'), + 'type' => MENU_CALLBACK + ); + $items["$base/export"] = array( + 'title' => '', + 'page callback' => 'biblio_export', + 'access callback' => 'user_access', + 'access arguments' => array('show export links'), + 'file' => '/includes/biblio.import.export.inc', + 'type' => MENU_CALLBACK + ); + $items["$base/citekey"] = array( + 'title' => '', + 'page callback' => 'biblio_citekey_view', + 'access arguments' => array('access biblio content'), + 'file' => '/includes/biblio.pages.inc', + 'type' => MENU_CALLBACK + ); + $items["$base/recent/rss.xml"] = array( + 'title' => 'RSS feed', + 'page callback' => 'biblio_recent_feed', + 'access callback' => 'biblio_access', + 'access arguments' => array('rss'), + 'type' => MENU_CALLBACK + ); + return $items; +} + +function biblio_filter_clear() { + $options = array(); + $_SESSION['biblio_filter'] = array(); + $base = variable_get('biblio_base', 'biblio'); + if (isset($_GET['sort'])) { + $options['sort'] = $_GET['sort']; + } + if (isset($_GET['order'])) { + $options['order'] = $_GET['order']; + } + drupal_goto($base, $options); +} + +function biblio_remove_brace($title_string) { + //$title_string = utf8_encode($title_string); + $matchpattern = '/\{\$(?:(?!\$\}).)*\$\}|(\{[^}]*\})/'; + $output = preg_replace_callback($matchpattern, 'biblio_remove_brace_callback', $title_string); + return $output; +} + +function biblio_remove_brace_callback($match) { + if (isset($match[1])) { + $braceless = str_replace('{', '', $match[1]); + $braceless = str_replace('}', '', $braceless); + return $braceless; + } + return $match[0]; +} + +function biblio_node_revision_delete($node) { + if ($node->type == 'biblio') { + db_delete('biblio') + ->condition('vid', $node->vid) + ->execute(); + + db_delete('biblio_contributor') + ->condition(db_and()->condition('nid', $node->nid)->condition('vid', $node->vid)) + ->execute(); + + db_delete('biblio_keyword') + ->condition(db_and()->condition('nid', $node->nid)->condition('vid', $node->vid)) + ->execute(); + } +} + +function biblio_node_insert($node) { + if ($node->type == 'biblio') { + if (variable_get('biblio_index', 0)) { + _node_index_node($node); + search_update_totals(); + } + } +} + +function biblio_node_update($node) { + if ($node->type == 'biblio') { + if (variable_get('biblio_index', 0)) { + // _node_index_node performs a node_load without resetting the node_load cache, + // so it would index the old version. We reset the cache here. + // Don't assign node_load to $node because node_load resets e.g. the menus mlid etc. + $mynode = node_load($node->nid, NULL, TRUE); + _node_index_node($mynode); + search_update_totals(); + } + } +} + +function biblio_node_view($node, $view_mode) { + if ($node->type == 'biblio') { + switch ($view_mode) { + case 'full': + if (variable_get('biblio_hide_bibtex_braces', 0) && !empty($a4)) { + drupal_set_title(filter_xss($node->title, biblio_get_allowed_tags())); + } + //fall through + case 'teaser': + $show_link = variable_get('biblio_lookup_links', array('google' => TRUE)); + if (!empty($show_link['google'])) { + $node->content['links']['biblio_google_scholar'] = array( + '#links' => array(theme('google_scholar_link', array('node' => $node))), + '#attributes' => array('class' => array('links', 'inline')), + ); + } + } + } +} + +function biblio_query_node_access_alter(QueryAlterableInterface $query) { + global $user; + if (user_access('access biblio content', $user)) return; + $tables = $query->getTables(); + foreach ($tables as $alias => $table_info) { + if (!($table_info instanceof SelectQueryInterface)) { + if ( $table_info['table'] == 'node') { + $query->condition($alias .'.type', 'biblio', '<>'); + break; + } + } + } + +} + +function biblio_user_presave(&$edit, $account, $catagory) { + $keys = array_keys($edit); + foreach ($keys as $key) { + if (strpos($key, 'biblio_') !== FALSE && isset($edit[$key])) { + if (isset($account->data['biblio_id_change_count']) && $account->data['biblio_id_change_count'] > 2 + && $key == 'biblio_contributor_id' && $edit[$key] != 0 ) { + $edit[$key] = 0; + } + $edit['data'][$key] = $edit[$key]; + if ($key == 'biblio_contributor_id' ) { + if ($edit[$key] != 0 && $edit[$key] != $account->data[$key]) { + $edit['biblio_id_change_count']++; + } + db_update('biblio_contributor_data')->condition('drupal_uid', $account->uid)->fields(array('drupal_uid' => 0))->execute(); + db_update('biblio_contributor_data')->condition('cid', $edit['biblio_contributor_id'])->fields(array('drupal_uid' => $account->uid))->execute(); + } + } + } +} + +/** + * Implementation of hook_form(). + * + * Create the form for collecting the information + * specific to this node type. This hook requires us to return some HTML + * that will be later placed inside the form. + */ +function biblio_form($node, &$form_state) { + global $user; + $path = drupal_get_path('module', 'biblio'); + if (variable_get('biblio_button_hide', 1) == 1) { + drupal_add_js($path . '/misc/biblio.nodeformbuttonhide.js', 'file'); + } + $fields = array(); + $form['biblio_tabs'] = $tabs = array(); + + $tid = !empty($form_state['biblio_type']) ? $form_state['biblio_type'] : + ( isset($node->biblio_type) ? $node->biblio_type : 0); + + $step_two = !empty($tid); + + /* publication type */ + $param['options'] = array("enctype" => "multipart/form-data"); + $result = db_query('SELECT t.* FROM {biblio_types} as t WHERE tid > -2 AND visible = 1'); + foreach ($result as $option) { + $results[$option->tid] = $option->name; + } + asort($results); + $options[0] = t('Select Type...'); + $options += $results; + $form['biblio_type'] = array( + '#type' => 'select', + '#title' => t('Publication Type'), + '#default_value' => $tid, + '#options' => $options, + '#description' => NULL, + '#weight' => 2, + '#attributes' => array('onchange' => 'document.getElementById(\'edit-biblio-next\').click()'), + '#executes_submit_callback' => TRUE, + '#limit_validation_errors' => array(), + '#multiple' => FALSE, + '#required' => TRUE + ); + + $form['biblio_next'] = array( + '#type' => 'submit', + '#value' => $step_two ? t('Change Publication Type') : t('Next'), + '#limit_validation_errors' => array(), + '#weight' => -10, + '#submit' => array(), + ); + if (isset($_COOKIE['has_js']) && !$_COOKIE['has_js']) { + unset($form['biblio_next']['#attributes']); + } + + if ($step_two) { + $form['title'] = array( + '#type' => 'textfield', + '#title' => t('Title'), + '#required' => TRUE, + '#default_value' => trim((isset($form_state['values']['title'])?$form_state['values']['title']: $node->title)), + '#maxlength' => 255, + '#size' => 120, + '#weight' => 1 + ); + // Build the field array used to make the form + $result = db_query("SELECT * FROM {biblio_fields} b + INNER JOIN {biblio_field_type} bt ON b.fid = bt.fid + INNER JOIN {biblio_field_type_data} btd ON btd.ftdid=bt.ftdid + WHERE bt.tid=:tid ORDER BY bt.weight ASC", array(':tid' => $tid), array('fetch' => PDO::FETCH_ASSOC)); + + foreach ($result as $row) { + $fields[$row['name']] = $row; + } + _biblio_localize_fields($fields); + + $tabs = array( + '#type' => 'vertical_tabs', + '#weight' => 10, + ); + $tabs += biblio_node_form_vtabs(); + + $tabs['biblio_authors'] = array( + '#type' => 'fieldset', + '#group' => 'biblio_tabs', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => 'Authors', + '#description' => t('Enter a single name per line using a format such as "Smith, John K" or "John K Smith" or "J.K. Smith"'), + ); + + $tabs['biblio_authors'] += biblio_contributor_widget($node, $form_state); + + $form_state['biblio_fields'] = $fields; + + foreach ($fields as $key => $fld) { + $options = ''; + if ($key == 'biblio_keywords' ) { + $sep = check_plain(variable_get('biblio_keyword_sep', ',')); + // is the kewords are in array form, then implode them into a string. + if (isset($form_state['values']['biblio_keywords']) && + is_array($form_state['values']['biblio_keywords'])) { + require_once(drupal_get_path('module', 'biblio') . '/includes/biblio.keywords.inc'); + $form_state['values']['biblio_keywords'] = biblio_implode_keywords($form_state['values']['biblio_keywords']); + } + if (!empty($node->$key) && is_array($node->$key)) { + require_once(drupal_get_path('module', 'biblio') . '/includes/biblio.keywords.inc'); + $node->$key = biblio_implode_keywords($node->$key); + } + if (empty($fld['hint'])) { + $fld['hint'] = t('Separate keywords using the " @sep " character', array('@sep' => $sep)); + } + } + + $element = array( + '#default_value' => (isset($form_state['values'][$key]) ? $form_state['values'][$key] : (isset($node->$key)?$node->$key:'')), + '#type' => $fld['type'], + '#title' => check_plain($fld['title']), + '#size' => $fld['size'], + '#rows' => 10, +// '#required' => $fld['required'], + '#maxlength' => $fld['maxsize'], + '#weight' => $fld['weight'] / 10, + '#autocomplete_path' => ($fld['autocomplete']) ? 'biblio/autocomplete/' . $fld['name'] : '', + '#description' => check_plain($fld['hint']), + '#format' => isset($node->biblio_formats[$key]) ? $node->biblio_formats[$key] : filter_default_format(), + ); + + if ($key == 'biblio_refereed' ) { + $element['#options'] = array( + '' => t('None'), + 'Refereed' => t('Refereed'), + 'Non-Refereed' => t('Non-Refereed'), + 'Does Not Apply' => t('Does Not Apply'), + 'Unknown' => t('Unknown'), + ); + $element['#description'] = t('If you are not sure, set this to Unknown or Does Not Apply'); + } + + if ( $fld['common'] || $fld['visible'] ) { + $tabs[$fld['vtab']][$key] = $element; + } + + } + } + foreach (element_children($tabs) as $key) { + $tab_children = element_children($tabs[$key]); + if (empty($tab_children) && $key != 'biblio_full_text') { + unset($tabs[$key]); + } + } + // $form['format'] = filter_form($node->format, 20); + //$biblio_form['#tree'] = TRUE; + $form['#validate']= array('biblio_node_form_validate'); + $form['#cache'] = TRUE; + $form['biblio_tabs'] += $tabs; + + return $form; +} + +function biblio_node_form_vtab_info() { + return array( + array('tab_id' => 1, 'weight' => 10, 'title' => 'Abstract', 'description' => ''), + array('tab_id' => 'biblio_full_text', 'weight' => 11, 'title' => 'Full text', 'description' => ''), + array('tab_id' => 2, 'weight' => 12, 'title' => 'Publication', 'description' => ''), + array('tab_id' => 3, 'weight' => 13, 'title' => 'Publisher', 'description' => ''), + array('tab_id' => 4, 'weight' => 14, 'title' => 'Identifiers', 'description' => ''), + array('tab_id' => 5, 'weight' => 15, 'title' => 'Locators', 'description' => 'URL\'s etc'), + array('tab_id' => 6, 'weight' => 16, 'title' => 'Keywords', 'description' => ''), + array('tab_id' => 7, 'weight' => 17, 'title' => 'Notes', 'description' => ''), + array('tab_id' => 8, 'weight' => 18, 'title' => 'Alternate Titles', 'description' => ''), + array('tab_id' => 9, 'weight' => 19, 'title' => 'Other', 'description' => ''), + ); +} + +function biblio_node_form_vtabs() { + $vtabs = biblio_node_form_vtab_info(); + + foreach ($vtabs as $tab) { + $form[$tab['tab_id']] = array( + '#type' => 'fieldset', + '#group' => 'biblio_tabs', + '#collapsible' => TRUE, + '#collapsed' => FALSE, + '#title' => t($tab['title']), + '#description' => '', + '#weight' => $tab['weight'] + ); + } + return $form; +} +function biblio_contributor_widget($node, &$form_state) { + $init_count = variable_get('biblio_init_auth_count', 4); + $contributor_count = 0; + if (isset($form_state['values']['biblio_contributors'])) { + $contributors = $form_state['values']['biblio_contributors']; + } + elseif (isset($node->biblio_contributors)) { + $contributors = $node->biblio_contributors; + } + else { + $contributors = array(); + } + + $ctypes = db_query('SELECT * FROM {biblio_contributor_type_data}'); + + foreach ($ctypes as $ctype ) { + $options['roles'][$ctype->auth_type] = $ctype->title; + } + $options['categories'] = array( + 1 => t('Primary'), + 2 => t('Secondary'), + 3 => t('Tertiary'), + 4 => t('Subsidiary'), + 5 => t('Corporate/Institutional') + ); + + // Container for just the contributors. + $wrapper = array(); + $wrapper['biblio_contributors'] = array( + '#tree' => TRUE, + '#theme' => 'biblio_contributors', + '#prefix' => '
', + '#suffix' => '
', + ); + foreach ($contributors as $author) { + $wrapper['biblio_contributors'][] = biblio_contributor_form($author, $options); + $contributor_count++; + } + + if (isset($form_state['biblio_contrib_count'])) { + $form_count = max(max($init_count, $contributor_count), $form_state['biblio_contrib_count']); + } + else { + $form_count = max($init_count, $contributor_count); + $form_state['biblio_contrib_count'] = $form_count; + } + if ($form_count > $contributor_count) { + $author = array(); + for ($i = 0; $i < ($form_count - $contributor_count); $i++) { + $wrapper['biblio_contributors'][] = biblio_contributor_form($author, $options); + } + } + $wrapper['add_more'] = array( + '#type' => 'submit', + '#value' => t('More contributors'), + '#description' => t("If there aren't enough boxes above, click here to add more."), + '#weight' => 1, + '#submit' => array('biblio_contributors_add_more'), // If no javascript action. + '#limit_validation_errors' => array(), + '#ajax' => array( + 'callback' => 'biblio_contributors_add_more_callback', + 'wrapper' => 'biblio-contributors-wrapper', + ), + ); + + return $wrapper; +} + +function biblio_contributor_form($contributor, $options) { + $form = array('#tree' => TRUE); + + $form['name'] = array( + '#type' => 'textfield', + '#maxlength' => 255, + '#autocomplete_path' => 'biblio/autocomplete/contributor', + '#default_value' => isset($contributor['name']) ? $contributor['name'] : '', + ); + $form['auth_category'] = array( + '#type' => 'select', + '#default_value' => isset($contributor['auth_category']) ? $contributor['auth_category'] : '', + '#options' => $options['categories'], + '#multiple' => FALSE, + ); + $form['auth_type'] = array( + '#type' => 'select', + '#default_value' => isset($contributor['auth_type']) ? $contributor['auth_type'] : '', + '#options' => $options['roles'], + '#multiple' => FALSE, + ); + $form['cid'] = array( + '#type' => 'hidden', + '#default_value' => isset($contributor['cid']) ? $contributor['cid'] : '', + ); + $form['rank'] = array( + '#type' => 'textfield', + '#size' => 6, + '#default_value' => isset($contributor['rank']) ? $contributor['rank'] : '', + ); + return $form; +} + +function biblio_contributors_add_more_callback($form, &$form_state) { + return $form['biblio_tabs']['biblio_authors']['biblio_contributors']; +} + +function biblio_contributors_add_more($form, &$form_state) { + $form_state['biblio_contrib_count'] += variable_get('biblio_contrib_fields_delta', 2); + $form_state['rebuild'] = TRUE; +} + +function biblio_form_node_form_alter(&$form, &$form_state, $form_id) { + if ($form_id == 'biblio_node_form') { + $form['#pre_render'][] = 'biblio_node_form_pre_render'; + if (!isset($form['biblio_tabs']['biblio_full_text']) && isset($form['body'])) { + unset($form['body']); + } + if (empty($form_state['biblio_type']) && + empty($form['vid']['#value'])) { + foreach (element_children($form) as $form_element) { + if (strstr($form_element, 'biblio_')) continue; + if (strstr($form_element, 'form_')) continue; + if (isset($form[$form_element]['#type']) && $form[$form_element]['#type'] != 'value') { + $form[$form_element]['#access'] = FALSE; + } + } + } + + } +} +function biblio_node_form_pre_render($form) { + if (isset($form['biblio_tabs']['biblio_full_text']) && isset($form['body'])) { + $form['biblio_tabs']['biblio_full_text']['body'] = $form['body']; + unset($form['body']); + } + return $form; +} +/** + * Implementation of hook_validate(). + * + * + * Errors should be signaled with form_set_error(). + */ +function biblio_node_form_validate($form, &$form_state) { + if ($form_state['triggering_element']['#value'] == t('Next') + || $form_state['triggering_element']['#value'] == t('Change Publication Type')) { + $form_state['rebuild'] = TRUE; + $form_state['biblio_type'] = $form_state['values']['biblio_type']; + if ($form_state['values']['biblio_type'] == 0) { + form_set_error('biblio_type', t('Please select a publication type.')); + } + return; + } + $format = new stdClass(); + foreach (_biblio_get_formatted_fields() as $field) { + if (isset($form_state['values'][$field]['format'])) { + $format->format = $form_state['values'][$field]['format']; + if (!filter_access($format)) { + form_set_error($field, t('You do not have access to the !format format', array('!format' => $format->format))); + } + } + } + if (isset($form_state['values']['biblio_keywords'])) { + require_once(drupal_get_path('module', 'biblio') . '/includes/biblio.keywords.inc'); + if (!is_array($form_state['values']['biblio_keywords'])) { + $form_state['values']['biblio_keywords'] = biblio_explode_keywords($form_state['values']['biblio_keywords']); + } + foreach ($form_state['values']['biblio_keywords'] as $keyword) { + if (strlen($keyword) > 255) { + form_set_error('biblio_keywords', t('No single keyword can be greater than 255 characters in length, the word: @kw exceeds this length', array('@kw' => $keyword ))); + } + } + } + + + if (isset($form_state['biblio_fields'])) { + $vtabs = biblio_node_form_vtab_info(); + foreach($vtabs as $tab) { + $tabs[$tab['tab_id']] = $tab['title']; + } + + foreach ($form_state['biblio_fields'] as $key => $fld) { + if ($fld['required'] && isset($form_state['values'][$key]) && empty($form_state['values'][$key])) { + $tab = $tabs[$fld['vtab']]; + form_set_error($key, t('The @fld field (on the @tab tab) is required', array('@fld' => $fld['title'], '@tab' => $tab))); + } + } + } + +} + +function _biblio_numeric_year($year) { + if (!is_numeric($year)) { + if (drupal_strtoupper($year) == drupal_strtoupper(t("In Press"))) return 9998; + if (drupal_strtoupper($year) == drupal_strtoupper(t("Submitted"))) return 9999; + } + else { + return $year; + } +} + +function _biblio_text_year($year) { + if ($year == 9998) return check_plain(variable_get('biblio_inpress_year_text', t('In Press'))); + if ($year == 9999) return check_plain(variable_get('biblio_no_year_text', t('Submitted'))); + return $year; +} + +function _biblio_get_formatted_fields() { + $fields = &drupal_static(__FUNCTION__); + if (!isset($fields)) { + $query = db_select('biblio_fields', 'bf'); + $result = $query->fields('bf', array('name')) + ->condition('type', 'text_format') + ->execute(); + foreach ($result as $field) { + $fields[] = $field->name; + } + } + return (array) $fields; +} +/** + * Prepare a node for submit to database. Contains code common to insert and update. + * @param $node + * @return none + */ +function _biblio_prepare_submit(&$node) { + $node->biblio_sort_title = biblio_normalize_title($node->title); + if(!isset($node->biblio_year)) $node->biblio_year = 9999; + $node->biblio_year = _biblio_numeric_year($node->biblio_year); + + if (variable_get('biblio_auto_citekey', 1) && empty($node->biblio_citekey)) { + $node->biblio_citekey = biblio_citekey_generate($node); + } + foreach (_biblio_get_formatted_fields() as $field) { + if (isset($node->$field) && is_array($node->$field)) { + $node->biblio_formats[$field] = $node->{$field}['format']; + $node->$field = $node->{$field}['value']; + } + else { + $node->biblio_formats[$field] = filter_default_format(); + } + } +} +/** + * Implementation of hook_insert(). + * + * As a new node is being inserted into the database, we need to do our own + * database inserts. + */ +function biblio_insert($node) { + module_load_include('inc', 'biblio', 'includes/biblio.util'); + module_load_include('inc', 'biblio', 'includes/biblio.contributors'); + module_load_include('inc', 'biblio', 'includes/biblio.keywords'); + _biblio_prepare_submit($node); + biblio_insert_contributors($node); + biblio_insert_keywords($node); + $node->biblio_coins = biblio_coins($node); + $duplicate = biblio_hash($node); + drupal_write_record('biblio', $node); + if (isset($duplicate) && $duplicate != $node->nid) { // if this is a potential duplcate, write the nids of the pre-existing and new nodes + $dup_map = array('vid' => $duplicate, 'did' => $node->nid); + drupal_write_record('biblio_duplicates', $dup_map); + } + +} +/** + * Implementation of hook_update(). + * + * As an existing node is being updated in the database, we need to do our own + * database updates. + */ +function biblio_update($node) { + module_load_include('inc', 'biblio', 'includes/biblio.util'); + module_load_include('inc', 'biblio', 'includes/biblio.contributors'); + module_load_include('inc', 'biblio', 'includes/biblio.keywords'); + _biblio_prepare_submit($node); + biblio_update_contributors($node); + biblio_update_keywords($node); + $node->biblio_coins = biblio_coins($node); + + // Update the node in the database: + if (!empty($node->revision)) { + drupal_write_record('biblio', $node); + } + else { + drupal_write_record('biblio', $node, 'vid'); + } + + +} +/** + * Implementation of hook_delete(). + * + * When a node is deleted, we need to clean up related tables. + */ +function biblio_delete($node) { + module_load_include('inc', 'biblio', 'includes/biblio.contributors'); + module_load_include('inc', 'biblio', 'includes/biblio.keywords'); + //first remove data from the biblio table + + db_delete('biblio') + ->condition('nid', $node->nid) + ->execute(); + //now remove the entries from the contributor linking table + biblio_delete_contributors($node); + biblio_delete_keywords($node); +} +/** + * Implementation of hook_load(). + * + * This hook is called + * every time a node is loaded, and allows us to do some loading of our own. + * + */ +function biblio_load($nodes) { + module_load_include('inc', 'biblio', 'includes/biblio.util'); + module_load_include('inc', 'biblio', 'includes/biblio.contributors'); + module_load_include('inc', 'biblio', 'includes/biblio.keywords'); + $vids = array(); + foreach ($nodes as $nid => $node) $vids[] = $node->vid; + + $result = db_query('SELECT b.*, bt.name as biblio_type_name + FROM {biblio} b + LEFT JOIN {biblio_types} bt on b.biblio_type = bt.tid + WHERE b.vid IN (:vids)', array(':vids' => $vids), array('fetch' => PDO::FETCH_ASSOC)); + $contributors = biblio_load_contributors_multiple($vids); + $keywords = biblio_load_keywords_multiple($vids); + + foreach ($result as $record) { + if ((isset($record['biblio_url']) || isset($record['biblio_accession_number'])) && + variable_get('biblio_fix_isi_links', 0)) { + biblio_fix_isi_links($record); + } + + foreach ($record as $key => $value) { + $nodes[$record['nid']]->$key = $value; + } + + $nodes[$record['nid']]->biblio_year = _biblio_text_year($record['biblio_year']); + $nodes[$record['nid']]->biblio_contributors = isset($contributors[$record['vid']]) ? $contributors[$record['vid']] : array(); + $nodes[$record['nid']]->biblio_keywords = isset($keywords[$record['vid']]) ? $keywords[$record['vid']] : array(); + + if (empty($record['biblio_coins'])) { + $nodes[$record['nid']]->biblio_coins = biblio_coins($nodes[$record['nid']]); + } + if ($record['biblio_formats'] != NULL) { + $nodes[$record['nid']]->biblio_formats = unserialize($record['biblio_formats']); + } + else { + $nodes[$record['nid']]->biblio_formats = array(); + } + + } +} +function biblio_citekey_generate($node) { + $php = check_plain(variable_get('biblio_citekey_phpcode', '')); + if (empty($php)) { + $prefix = variable_get('biblio_citekey_prefix', ''); + $primary_field = variable_get('biblio_citekey_field1', 'nid'); + $secondary_field = variable_get('biblio_citekey_field2', 'nid'); + $citekey = (!empty($node->$primary_field)) ? $node->$primary_field : ((!empty($node-> $secondary_field)) ? $node-> $secondary_field : $node->nid); + return check_plain($prefix . $citekey); + } + else { + ob_start(); + $return = eval($php); + ob_end_clean(); + return check_plain(strip_tags((string)$return)); + } +} + +/** + * Implementation of hook_view(). + * + */ +function biblio_view($node, $buildmode = 'full') { + global $user; + $links = array(); + $style = biblio_get_style(); + $base = variable_get('biblio_base', 'biblio'); + $base_title = check_plain(variable_get('biblio_base_title', 'Biblio')); + + switch ($buildmode) { + case 'full': + case 'print': + if (variable_get('biblio_hide_bibtex_braces', 0) && !isset($node->view )) { + $node->title = biblio_remove_brace($node->title); + drupal_set_title(filter_xss($node->title, biblio_get_allowed_tags())); + } // fall through... + case 'search_index': + switch (variable_get('biblio_node_layout', 'tabular')) { + case 'orig' : + case 'ft' : + $node->content['body']['#markup'] = theme('biblio_long', array('node' => $node, 'base' => $base, 'style_name' => $style)); + break; + case 'cite': + $node->content['body']['#markup'] = theme('biblio_style', array('node' => $node, 'base' => $base, 'style_name' => $style)); + break; + case 'tabular' : + default : + $node->content['body']['#markup'] = theme('biblio_tabular', array('node' => $node, 'base' => $base)); + break; + } + break; + case 'teaser': + $node->content['teaser']['#markup'] = theme('biblio_style', array('node' => $node, 'base' => $base, 'style_name' => $style)); + break; + } + + return $node; +} +/** + * Implementation of hook_block(). + * + * Generates a block containing the latest poll. + */ +function biblio_block_info() { + $blocks['recent'] = array( + 'info' => t('Recent publications'), + ); + return $blocks; +} + +function biblio_block_configure($delta = '') { + $form = array(); + $form['block'] = array( + '#type' => 'fieldset', + '#collapsible' => FALSE, + '#collapsed' => FALSE, + '#title' => t('Options'), + '#description' => '', + ); + $form['block']['biblio_rowsperblock'] = array( + '#type' => 'textfield', + '#title' => t('Number of results in the "Recent Publications" block'), + '#default_value' => variable_get('biblio_rowsperblock', 4), + '#size' => 2, + '#maxlength' => 2, + '#description' => t('This sets the number of results that will be displayed in the "New Publications" block.') + ); + $form['block']['biblio_block_order'] = array( + '#type' => 'radios', + '#title' => t('Order by'), + '#default_value' => variable_get('biblio_block_order', 'n.created'), + '#options' => array( + 'n.created' => t('Date Created'), + 'b.biblio_year' => t('Year Published') + ) + ); + return $form; +} + +function biblio_block_save($delta = '', $edit = array()) { + if ($delta == 'recent') { + variable_set('biblio_rowsperblock', $edit['biblio_rowsperblock']); + variable_set('biblio_block_order', $edit['biblio_block_order']); + } +} + +function biblio_block_view($delta = '') { + switch ($delta) { + case 'recent': + $num_in_block = variable_get('biblio_rowsperblock', 4); + $block_order = variable_get('biblio_block_order', 'n.created'); + + $query = db_select('node', 'n') + ->fields('n', array('nid', 'title')) + ->condition(db_and() + ->condition('n.type', 'biblio') + ->condition('n.status', 1)) + ->orderBy($block_order, 'DESC') + ->range(0, $num_in_block); + if ($block_order == 'b.biblio_year') { + $query->leftJoin('biblio', 'b', 'n.vid=b.vid'); + } + $result = $query->execute(); + + $base = variable_get('biblio_base', 'biblio'); + $block['subject'] = t('Recent Publications'); + $block['content'] = '
    '; + $options['html'] = TRUE; + + foreach ($result as $pub) { + $block['content'] .= '
  • ' . l(filter_xss($pub->title, biblio_get_allowed_tags()), "node/$pub->nid", $options) . '
  • '; + } + $block['content'] .= '
'; + if (variable_get('biblio_rss', 0)) { + $block['content'] .= theme('feed_icon', array( + 'url' => url("$base/recent/rss.xml", array('absolute' => TRUE)), + 'title' => t('Recent Publications'))); + } + $block['content'] .= l(t('More...'), $base); + $block['content'] .= '
'; + + return $block; + break; + } +} + +function biblio_recent_feed() { + $numberInFeed = variable_get('biblio_rss_number_of_entries', 10); + + $query = db_select('node', 'n') + ->fields('n', array('nid', 'title')) + ->condition(db_and() + ->condition('n.type', 'biblio') + ->condition('n.status', 1)) + ->orderBy('n.created', 'DESC') + ->range(0, $numberInFeed); + $result = $query->execute(); + + $siteName = variable_get('site_name', 'Drupal'); + $base = variable_get('biblio_base', 'biblio'); + + $channel['title'] = $siteName . ' - ' . t("Recently Added Publications"); + $channel['link'] = url($base, array('absolute' => TRUE)); + $channel['description'] = t("This feed lists the %num most recently added publications on %site", array('%num' => $numberInFeed, '%site' => $siteName)); + $nids = array(); + + foreach ($result as $row) { + $nids[] = $row->nid; + } + node_feed($nids, $channel); +} + +function biblio_filter_feed($rss_info, $nids) { + $base = variable_get('biblio_base', 'biblio'); + $channel['title'] = $rss_info['title']; + $channel['link'] = url($base . $rss_info['link'], array('absolute' => TRUE)); + $channel['description'] = $rss_info['description']; + node_feed($nids, $channel); +} + +function biblio_get_db_fields() { + $fields = array(); + $fields[] = 'nid'; + $fields[] = 'vid'; + $fields[] = 'biblio_type'; + $result = db_query('SELECT name FROM {biblio_fields} ', array(), array('fetch' => PDO::FETCH_ASSOC)); + foreach ($result as $field ) { + $fields[] = $field['name']; + } + return $fields; +} + +/******************************************* + * Filter + * Largely inspired from the footnote module + * + *******************************************/ +function _biblio_citekey_print($citekey) { + + $nid = db_query("SELECT nid FROM {biblio} WHERE biblio_citekey = :key", array(':key' => $citekey))->fetchField(); + if ($nid) { + $style = biblio_get_style(); + $base = variable_get('biblio_base', 'biblio'); + $node = node_load($nid); + return theme('biblio_style', array('node' => $node, 'base' => $base, 'style' => $style)); + } + else { + return t("Citekey @cite not found", array('@cite' => $citekey)); + } +} +function biblio_filter_info() { + $filters['biblio_filter_reference'] = array( + 'title' => t('Biblio module references <bib> or [bib]'), + 'description' => t('Use <bib>citekey</bib> or [bib]citebkey[/bib]to insert automatically numbered references.'), + 'prepare callback' => '_biblio_filter_reference_prepare', + 'process callback' => '_biblio_filter_reference_process', + 'tips callback' => '_biblio_filter_reference_tips', + ); + $filters['biblio_filter_inline_reference'] = array( + 'title' => t('Biblio module inline references <ibib> or [ibib]'), + 'description' => t('Use <bib>citekey</bib> or [bib]citebkey[/bib]to insert automatically numbered references.'), + 'prepare callback' => '_biblio_filter_inline_reference_prepare', + 'process callback' => '_biblio_filter_inline_reference_process', + 'tips callback' => '_biblio_filter_inline_reference_tips', + ); + return $filters; +} + +function _biblio_filter_reference_tips($filter, $format, $long = FALSE) { + if (!$long) { + // This string will be shown in the content add/edit form + return t('Use <bib>citekey</bib> or [bib]citekey[/bib] to insert automatically numbered references.'); + } + else { + return t('You can cite references directly into texts with <bib>citekey</bib> or [bib]citekey[/bib]. This will be replaced with a running number (the publication reference) and the publication referenced by the citekey within the <bib> tags will be printed at the bottom of the page (the reference).'); + } +} + +function _biblio_filter_inline_reference_tips($filter, $format, $long = FALSE) { + return t('This creates an in line reference to another publication.'); +} + +function _biblio_filter_reference_prepare($text, $filter, $format, $langcode, $cache, $cache_id) { + return $text; +} + +function _biblio_filter_inline_reference_prepare($text, $filter, $format, $langcode, $cache, $cache_id) { + return $text; +} + +function _biblio_filter_reference_process($text, $filter, $format, $langcode, $cache, $cache_id) { + $pattern = array('|\[bib](.*?)\[/bib]|s', '|(.*?)|s'); + if (variable_get('biblio_footnotes_integration', 0) && module_exists('footnotes')) { // this is used with footnote module integration to replace the tags with tags + $text = preg_replace_callback($pattern, '_biblio_filter_footnote_callback', $text); + return $text; + } + else { + $text = preg_replace_callback($pattern, '_biblio_filter_replace_callback', $text); + //Replace tag with the list of footnotes. + //If tag is not present, by default add the footnotes at the end. + //Thanks to acp on drupal.org for this idea. see http://drupal.org/node/87226 + $footer = ''; + $footer = _biblio_filter_replace_callback(NULL, 'output footer'); + if (preg_match('//', $text) > 0) { + $text = preg_replace('//', $footer, $text, 1); + return $text; + } + else { + return $text . "\n\n" . $footer; + } + } +} + +function _biblio_filter_inline_reference_process($text, $filter, $format, $langcode, $cache, $cache_id) { + $pattern = array('|\[ibib](.*?)\[/ibib]|s', '|(.*?)|s'); + $text = preg_replace_callback($pattern, '_biblio_inline_filter_replace_callback', $text); + return $text; +} + +function _biblio_inline_filter_replace_callback($matches) { + $text = _biblio_citekey_print($matches[1]) ; + return $text; +} + +function _biblio_filter_footnote_callback($matches, $square_brackets = FALSE) { + if ($square_brackets) { + $text = '[fn]' . _biblio_citekey_print($matches[1]) . ""; + } + else { + $text = '' . _biblio_citekey_print($matches[1]) . ""; + } + return $text; +} +/** + * Helper function called from preg_replace_callback() above + * + * Uses static vars to temporarily store footnotes found. + * In my understanding, this is not threadsafe?! + */ +function _biblio_filter_replace_callback($matches, $op = '') { + static $n = 0; + static $store_matches = array(); + $str = ''; + if ($op == 'output footer') { + if ($n > 0) { + $str = '

' . t('References') . '

'; + $str .= '
    '; + for ($m = 1; $m <= $n; $m++) { + $str .= '
  1. ' . _biblio_citekey_print($store_matches[$m -1]) . "
  2. \n\n"; + } + $str .= '
'; + } + $n = 0; + $store_matches = array(); + return $str; + } + //default op: act as called by preg_replace_callback() + $ref = array_search($matches[1], $store_matches); + if ($ref === FALSE) { + $n++; + array_push($store_matches, $matches[1]); //$stores_matches[$matches[1]] = $n; + $ref = $n; + } + else { + $ref++; + } + $allowed_tags = array(); + $title = filter_xss($matches[1], biblio_get_allowed_tags()); + //html attribute cannot contain quotes + $title = str_replace('"', """, $title); + //remove newlines. Browsers don't support them anyway and they'll confuse line break converter in filter.module + $title = str_replace("\n", " ", $title); + $title = str_replace("\r", "", $title); + //return ''. $n .''; + //$text = '['. $n .'] '; + //$text = '['. $n .']'; + //$text .= ''._biblio_citekey_print($title) .''; + $text = '[' . $ref . ']'; + if (module_exists('hovertip')) { + $text = '[' . $ref . ']'; + $text .= '' . _biblio_citekey_print($title) . ''; + } + else { + $text = '[' . $ref . ']'; + + } + return $text; +} + +function hook_taxonomy_vocabulary_delete($vocabulary) { + if ($vocabulary->vid == variable_get('biblio_keyword_vocabulary', FALSE)) { + variable_del('biblio_keyword_freetagging'); + variable_del('biblio_keyword_vocabulary'); + } +} + +function biblio_term_path($term) { + $base = variable_get('biblio_base', 'biblio'); + if ($term->vid == variable_get('biblio_collection_vocabulary', 0) ) { + return ("$base/collection/$term->name"); + } + elseif ($term->vid == variable_get('biblio_keyword_vocabulary', 0) ) { + return ("$base/term_id/$term->tid"); + } + else return; +} + +function biblio_hash($node) { + static $sums = array(); + $duplicate = NULL; + if (empty($sums)) { + $res = db_query("SELECT nid, biblio_md5 FROM {biblio} "); + foreach ($res as $md5) { + $sums[$md5->biblio_md5] = $md5->nid; + } + } + + $hash_string = str_replace(' ', '', drupal_strtolower($node->title)); + if (isset($node->biblio_contributors[0]['lastname'])) { + $hash_string .= str_replace(' ', '', drupal_strtolower($node->biblio_contributors[0]['lastname'])); + } + $hash_string .= $node->biblio_year; + + $sum = md5($hash_string); + + if (isset ($sums[$sum])) { + $duplicate = $sums[$sum]; + } + else { + $sums[$sum] = $node->nid; + } + $node->biblio_md5 = $sum; + return $duplicate; //return the nid of the potential duplicate +} + +function _biblio_profile_access($user, $type = 'profile') { + if ($type == 'profile') { + $key = 'biblio_show_profile'; + } + elseif ($type == 'menu' && !empty($user) && $user->uid > 0) { + $key = 'biblio_my_pubs_menu'; + } + else { + return FALSE; + } + // if user cannot override site settings or user hasn't yet made its selection, we use site default + if (!variable_get('biblio_show_user_profile_form', '1') || !isset($user->data[$key])) { + return variable_get($key, '0'); // return site default + } + else { + return $user->data[$key]; // return user setting + } +} +/* + * Helper function to get either the user or system style + */ +function biblio_get_style() { + global $user; + if (isset($user->data['biblio_user_style']) && $user->data['biblio_user_style'] != "system") { + return $user->data['biblio_user_style']; + } + return module_exists('biblio_citeproc') ? variable_get('biblio_citeproc_style', 'ieee.csl') : variable_get('biblio_style', 'cse'); +} + +function biblio_get_styles() { + $styles = array(); + if (module_exists('biblio_citeproc')) { + $result = db_select('biblio_citeproc_styles', 'csl') + ->fields('csl', array('filename', 'title')) + ->orderBy('title', 'ASC') + ->execute(); + foreach ($result as $style) { + $styles[$style->filename] = $style->title; + } + } + else { + $dir = drupal_get_path('module', 'biblio') . '/styles'; + $files = file_scan_directory($dir, '/biblio_style_..*.inc$/'); + foreach ($files as $file) { + include_once $file->uri; + $function = $file->name . '_info'; + if (function_exists($function)) { + $styles = array_merge($styles, call_user_func($function)); //build and array of the short and long names + } + } + ksort($styles); + } + return $styles; +} + +/** + * Implementation of hook_views_api(). + */ +function biblio_views_api() { + return array( + 'api' => 2, + 'path' => drupal_get_path('module', 'biblio') . '/views', + ); +} + +function biblio_fix_isi_links(&$node) { + $isi = check_plain(variable_get('biblio_isi_url', 'http://apps.isiknowledge.com/InboundService.do?Func=Frame&product=WOS&action=retrieve&SrcApp=EndNote&Init=Yes&SrcAuth=ResearchSoft&mode=FullRecord&UT=')); + if (isset($node['biblio_url']) && preg_match ('/Go\s*to\s*ISI/', $node['biblio_url'])) { + $node['biblio_url'] = str_replace('://', $isi, $node['biblio_url']); + } + if (isset($node['biblio_accession_number']) && preg_match ('/^ISI:/', $node['biblio_accession_number'])) { + $node['biblio_accession_number'] = str_replace("ISI:", $isi, $node['biblio_accession_number']); + } +} + +function biblio_get_allowed_tags() { + return array('a', 'b', 'i', 'u', 'sub', 'sup', 'span'); +} + +function biblio_get_title_url_info($node) { + return array('link' => ((variable_get('biblio_link_title_url', 0) && !empty($node->biblio_url)) ? $node->biblio_url : "node/$node->nid" ), + 'options' => + array('attributes' => (variable_get('biblio_links_target_new_window', FALSE)) ? array('target' => '_blank') : array(), + 'html' => TRUE), + ); +} + + +/** + * @param string $type (can be one of "type_names", "type_map" or "field_map") + * @param string $format (tagged, ris, endnote_xml8 etc...) + * @return array $map + */ +function biblio_get_map($type, $format) { + $result = db_select('biblio_type_maps', 'btm') + ->fields('btm', array($type)) + ->condition('format', $format) + ->execute() + ->fetchField(); + + $map = unserialize($result); + + if ($type == 'export_map' && empty($map)) { + $schema = drupal_get_schema('biblio'); + $fieldnames = array_keys($schema['fields']); + asort($fieldnames); + $map = array_fill_keys($fieldnames, 1); + } + + drupal_alter('biblio_map', $map, $type, $format); + return $map; +} + +function biblio_save_map($maps) { + db_insert('biblio_type_maps') + ->fields($maps) + ->execute(); +} +/** + * @param string $type (can be one of "type_names", "type_map" or "field_map") + * @param string $format (tagged, ris, endnote_xml8 etc...) + * @param array $map + */ +function biblio_set_map($type, $format, $map) { + $map[$type] = serialize($map); + $map['format'] = $format; + drupal_write_record('biblio_type_maps', $map, 'format'); +} + +function biblio_reset_map($type, $format) { + module_invoke_all($format . '_map_reset', $type); +} + +function biblio_field_extra_fields() { + module_load_include('inc', 'biblio', 'includes/biblio.fields'); + return _biblio_field_extra_fields(); +} + +//Fixes node export importing issue #826506 +function biblio_node_export_node_alter($node, $original_node) { + if ($node->type == 'biblio' && isset($node->biblio_contributors) && is_array($node->biblio_contributors)) { + foreach ($node->biblio_contributors as $n => $value) { + unset($node->biblio_contributors[$n]['cid']); + } + } +} + +function biblio_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) { + module_load_include('inc', 'biblio', 'includes/biblio.feeds'); + return _biblio_feeds_processor_targets_alter($targets, $entity_type, $bundle_name); +} + +function biblio_feeds_importer_default() { + module_load_include('inc', 'biblio', 'includes/biblio.feeds'); + $defaults = array(); + if (module_exists('feeds_oai_pmh')) { + $defaults += _biblio_feeds_oai_importer_default(); + } + + return $defaults; + } + +function biblio_ctools_plugin_api() { + list($module, $api) = func_get_args(); + if ($module == "feeds" && $api == "feeds_importer_default") { + return array("version" => 1); + } +} \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/biblio.tokens.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/biblio.tokens.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,89 @@ + '', 'vid' => '', 'biblio_formats' => '')); + $node_token['biblio']= array( + 'name' => t('Biblio'), + 'description' => t('Tokens related to the Biblio content type.'), + 'type' => 'biblio' + ); + foreach ($fields as $key => $value) { + $name = str_replace('biblio_', '', $key); + $name = str_replace('_', ' ', $name); + $name = ucwords($name); + $biblio_tokens[$key] = array( + 'name' => t($name), + 'description' => (isset($value['description'])) ? t("!desc" , array('!desc' => $value['description'])) : '', + ); + } + + $biblio_tokens['biblio_first_author'] = array( + 'name' => t("Author - First"), + 'description' => 'First author of the publication', + ); + $biblio_tokens['biblio_type_name'] = array( + 'name' => t("Type Name"), + 'description' => t('The name of the publication type (i.e. Journal, Book, etc.'), + ); + + + $types['biblio'] = array( + 'name' => t('Biblio'), + 'description' => t('Tokens related to Biblio node type.'), + 'needs-data' => 'node', + ); + +/* + $types['biblio-authors'] = array( + 'name' => t('Biblio Authors'), + 'description' => t('Tokens related to Biblio node type.'), + 'needs-data' => 'node', + ); + $types['biblio-keywords'] = array( + 'name' => t('Biblio Keywords'), + 'description' => t('Tokens related to Biblio node type.'), + 'needs-data' => 'node', + ); +*/ + + return array( + 'types' => $types, + 'tokens' => array( + 'biblio' => $biblio_tokens, + 'node' => $node_token), + ); +} + +/** + * @param unknown_type $type + * @param unknown_type $tokens + * @param unknown_type $data + * @param unknown_type $options + * @return multitype:NULL + */ +function biblio_tokens($type, $tokens, $data = array(), $options = array()) { + $replacements = array(); + if ($type == 'node' && !empty($data['node']) && $data['node']->type == 'biblio') { + $sanitize = !empty($options['sanitize']); + $node = $data['node']; + foreach (token_find_with_prefix($tokens, 'biblio') as $name => $original) { + switch ($name) { + case 'biblio_first_author': + $replacements[$original] = $sanitize ? check_plain($node->biblio_contributors[0]['lastname']) : $node->biblio_contributors[0]['lastname']; + break; + case 'biblio_type_name': + $type = db_query('SELECT name FROM {biblio_types} as t WHERE t.tid = :tid', array(':tid' => $node->biblio_type))->fetchField(); + $replacements[$original] = $sanitize ? check_plain($type) : $type; + break; + default: + $replacements[$original] = $sanitize ? check_plain($node->$name) : $node->$name; + } + } + } + + return $replacements; +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/changelog.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/changelog.html Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,326 @@ + + + + +Biblio Change Log + + + +

7.x-dev

+New features... +
    +
  • Added MARC format export to the Biblio MARC module.
  • +
  • #1853022 added option to display file attachments as text or icons.
  • +
  • Added cron process to Biblio PubMed to periodically check for updates to existing PubMed entries.
  • +
  • Added edit and upload functions for CSL style files on the "admin/config/content/biblio/citeproc/styles" page.
  • +
  • #1485856 Contributor and Keyword orphan cleanup is now done using cron rather than on biblio update.
  • +
  • Added #1443250 Formatted text fields now respect the format setting when rendered in Views
  • +
  • Added a field mapper GUI for the CiteProc module at admin/config/content/biblio/citeproc/map
  • +
  • Added a "highlight" feature to the "authors" page which allows privileged users to toggle highlighting of potential duplicate authors
  • +
  • #1140366 Patch: PubMed XML Bulk Import
  • +
+ +Bugs Fixed... +
    +
  • #1888776 Fixed: Warning message when importing a journal article via DOI
  • +
  • #1889886 Fixed: property of non-object in biblio_handler_citation->render()
  • +
  • #1890094 Fixed: Keyword - Taxonomy integration. Taxonomy term reference were not being created.
  • +
  • #1815032 Fixed: Array to string conversion in biblio_token_info() in 7.x-1.0-dev
  • +
  • #1862788 Fixed: Can not add additional authors to link list
  • +
  • #1806214 Fixed: Feeds module needs input to be an array or it cuts input to first string $value[0]
  • +
  • #1802264 Fixed: Views filter "Biblio: Drupal UserID" does not list any Drupal users
  • +
  • #1202840 Fixed: Shouldn't print "p. " when the pages field is left empty (CiteProc module)
  • +
  • #1798244 Fixed: Publisher field not rendered in CiteProc
  • +
  • #1781126 Fixed: Superfluous quotation marks (CiteProc module)
  • +
  • #1794636 Fixed: Missing t() in page title
  • +
  • #1780414 Fixed: Enforce RIS permitted character set during RIS import - Remove non-printing characters and other "gremlins"
  • +
  • #1786014 Fixed: Undefined index: biblio_notes.
  • +
  • #1509872 Fixed: PubMed import fails for long lastnames.
  • +
  • #1497040 Fixed: Views "Author lastname" sort handler so you can select the author "rank" (1st, 2nd, 3rd) to sort on.
  • +
  • #1449612 Fixed: Class attribute passed to theme not an array
  • +
  • #741212 Fixed: Wrong node count on author/keyword overview pages, when using revisions
  • +
  • #1206278 Fixed: Author order not saved when updating an existing Biblio
  • +
  • #972312 Fixed: casting issue in biblio_save_node() (implmented node_object_prepare)
  • +
  • #1138636 Fixed: Show filefield attachment link in list view
  • +
  • #1049218 Fixed: Bad URL for sort by links
  • +
  • #1177038 Fixed: Call to undefined function mb_regex_encoding()
  • +
  • #1166300 Fixed: Notice: Undefined index: class in _biblio_sort_tab() (line 569
  • +
  • #1145172 Fixed: Call to undefined function curl_init()
  • +
  • #1138636 Fixed: Show filefield attachment link in list view
  • +
  • #1140366 Patch: PubMed XML Bulk Import
  • +
  • #1139432 Fixed: Biblio Incompatible With Field-fix Branch of Token Module
  • +
  • #1135326 Fixed: Notice: Undefined offset
  • +
  • #1127514 Patch removes issue numbers from (non journal) chicago style listings.
  • +
  • #830770 Fixed: Biblio list output not showing filefield path aliases
  • +
  • #1104928 Fixed: PubMed Link Setting
  • +
  • #1104718 Fixed: PubMed Import multi-paragraph abstracts
  • +
  • #1055494 Fixed: Undefined variable: export_map
  • +
  • #1037350 Fixed: Notice re: biblio_contributor_id on user edit page
  • +
  • #1030254 Fixed: Undefined index: tagged in biblio_tagged_biblio_export_link()
  • +
  • #1015100 Fixed: Small nit about $output in biblio_style_classic()
  • +
  • #999776 Fixed: various errors with endnote (XML) import)
  • +
  • #951124 Fixed: RIS import / implemented import from node form
  • +
  • #987556 Fixed: CSE citation style no delimiter for first author's initials
  • +
  • #978022 Fixed: Parentheses should be removed from Google Scholar link
  • +
  • #978096 Fixed: Missing Magazine Article in tagged endnote publication type mapping
  • +
  • #946362 Fixed: Encoding issue in author formatter
  • +
  • #946492 Fixed: Subsidiary authors not imported by tagged EndNote parser
  • +
  • #288957RIS parser handles BT tag incorrect for types other than BOOK
  • +
  • #734682Theming error - $base not supplied
  • +
  • updated German translation (biblio.de.po) by Niels Hackius
  • +
  • #502562 "CrossRef OpenURL Account ID" descriptive text on user profile page enhanced to avoid confusion between different types of CrossRef accounts
  • +
  • #681730Rendering biblio as citation style for views omits status
  • +
  • #670394fixed MLA Style issue: missing punctuation for Book Chapter type
  • +
  • #616754 style_vancouver warning
  • +
  • #614970 fixed extra "biblio-title-vancouver" spans in Vancouver style
  • +
  • #614598 fixed Missing } in biblio.module causes errors using multisite
  • +
+ +

6.x-dev

+New features... + +Bugs Fixed... +
    +
  • # row titles in theme_biblio_tabular() not translated
  • +
  • #146758 fixed missing initialization of the keyword separator string
  • +
  • # fixed spans being filtered out of biblio listings
  • +
  • #611712 fixed Empty href attributes in OpenURL links
  • +
  • # fixed "keyword" page so that keywords from "unpublished" nodes are not listed (with the exception of the Admin user UID=1, who will still see them )
  • +
  • # fixed "authors" page so that authors from "unpublished" nodes are not listed (with the exception of the Admin user UID=1, who will still see them)
  • +
  • # fixed extra period after title in some styles
  • +
  • #146760proper handling of name suffixes
  • +
  • # fixed Import: Invalid argument supplied for foreach () in biblio.import.export.inc on line 267
  • +
  • # fixed falformed paragraph tag
  • +
  • #597286searching bibligraphy adds around result
  • +
  • #584616Import: Invalid argument supplied for foreach () in biblio.import.export.inc
  • +
  • #592750Error when Block Settings is ordered by Year Published following upgrade from 6.x-1.6 to 6.x-1.7
  • +
+ +

6.x-1.7

+New features... +
    +
  • New settings available in "Styling" to allow admin to change the text that is displayed when there is no year of publication available (9999) or the "In Press" text (9998)
  • +
  • Reworked the SQL query used for the list display to improve speed at which the list display is sorted. This is especially noticable on large datasets.
  • +
  • Reworked export functions such that the data is streamed to the client node by node thus reducing the memory footprint required to export large datasets.
  • +
  • Thanks to Filipe Rocha for the Portuguese translation file (biblio.pt-pt.po)
  • +
  • Added links to file attachments in the Tagged, bibtex and EndNote 8 export file formats
  • +
  • Thanks to Turczi Attil for the Hungarian translation file (biblio.hu.po)
  • +
+Bugs Fixed... +
    +
  • fixed potential XSS vulnerability
  • +
  • #585332 fixed Can't use the print module in the biblio list page
  • +
  • disabled default views so they do not over ride some of the built in paths
  • +
  • #570640 fixed author ordering problem when "More Authors" are added on the input form
  • +
  • #561722 fixed Order Vocabularies by Weight on Import Screen(s)
  • +
  • #561800 fixed Incorrectly placed curly bracket } around table name in db_query
  • +
  • #551362 fixed problem with author and keyword edit links when base url has more than one level
  • +
  • #502140 fixed typo which prevented removal of BibTex braces in the title with Views display
  • +
  • #536062 fixed bug which would overwrite page title if the page had a "View" containing a biblio node
  • +
  • fixed bug which prevented the "Alpha" line from being displayed on the "Authors" page when there were no authors to display
  • +
+
+

6.x-1.6

+New features... +
    +
  • Added configurable "type" mapping #520828. This feature allows mapping between various input file format publication types and Biblio publication types.
  • +
  • Added a per-user setting for OpenURL information #528930
  • +
  • EndNote XML files are now formated in the latest XML format by default, good for versions 8 and newer of EndNote.
  • +
  • Added new setting in the OpenURL section to set the Site ID (sid) of the OpenURL link
  • +
+Bugs Fixed... +
    +
  • fixed potential XSS vulnerability
  • +
  • #514882 fixed MLA style looks for incorrect year field
  • +
  • #------ fixed incorrect link in keyword edit page
  • +
  • #513930fixed Missing '</ul>' tag in biblio_theme.inc, and also refactored the entire link building process so that the links on the "node" display are built by the same code as the links on the "bibliographic" display
  • +
  • #504702fixed The first [bib] causes a line break with hovertips enabled
  • +
  • #501932fixed warning generated when new "type" is created and no fields are set "visible", also change the default for new types so that ALL fields will be visible rather than invisible.
  • +
  • #497594removed the manditory requirement for the year of publication to be supplied
  • +
  • #502140fixed Views citation handler does not remove BibTeX brackets
  • +
  • #501932fixed Biblio Search returns error
  • +
  • #477438fixed issue with CrossRef XML parser where it would truncate data with embedded HTML tags, also added the retention of font style (bold, italic, underline, subscript, superscript) information.
  • +
  • #477438fixed issue with EndNote XML parser where it would truncate data with embedded styles, also added the retention of font style information.
  • +
  • #------ fixed issue with author formatting which could cause extra periods before and after initials
  • +
  • #------ removed some debug code which was left in the Crossref xml parser by mistake
  • +
  • #492214by scottrigby: biblio: authors views field sql error
  • +
  • #486462 Fixed: Arrow images not showing when Drupal is not installed at DocumentRoot
  • +
  • #486790 "Edit" links on admin/settings/biblio/author/list are broken
  • +
  • #488214 theme_biblio_long makes bad author links
  • +
  • #486312 User cannot edit biblio entries unless it has 'administer nodes' permission
  • +
  • #477878 Fixed Views biblio_year field with "In Press" and "Submitted" values
  • +
  • #483650 Google Scholar links not shown in "node" view
  • +
  • #467928 Wrong tool tip on Google Scholar link
  • +
+
+

6.x-1.5

+New features... +
    +
  • Added Views handlers for sorting, filtering and arguments on most fields.
  • +
  • Added new settings in the ISI Web of Knowledge section on the admin/settings/biblio page. Turning this on automatically converts EndNote "Go to ISI" links to valid ISI search links. (ISI subscription required)
  • +
  • Added new settings in the links section on the admin/settings/biblio page. You choose to carry "inline" mode through to all subsequent links. Inline mode is used primarily by people accessing biblio data from custom code, so the average user will not need this.
  • +
  • Added new settings in the links section on the admin/settings/biblio page. You can now toggle the export links on/off individually as well as the Google Scholar link
  • +
  • Added links from each entry to Google Scholar. Following the link does a Google Scholar search using the title and first authors name.
  • +
  • Added a new feature (and setting to turn it on/off) which will allow you to retain BibTex protected capitalization braces in title strings, they will be stripped out on display, but will still be in place when exported in BibTex format.
  • +
  • Added a new permission called "access biblio content" which will allow you to restrict access to any of the biblio pages (biblio, biblio/authors, biblio/keywords etc.) A user MUST have this permission to see anything from the biblio module!
  • +
  • Added a section to the user profile page to allow entry of CrossRef login information used for DOI lookup
  • +
  • Added a new option when selecting taxonomy terms from a vocabulary, you can now choose to copy them to the biblio keyword database or not. There is a check box on the input and import forms and there is also a new check box in the "Keywords" section of the admin/settings page which sets the default for this option.
  • +
  • Added a setting in the links section to toggle the hyperlinks on the author names.
  • +
+Bugs Fixed... +
    +
  • #150002 Go to ISI Link
  • +
  • #477502 Unescape XML Entities in import from crossref
  • +
  • #477432 crossref_unix_parser pulls in extra dois
  • +
  • #477448 crossref_unix_parser on multiple isbns
  • +
  • #282996 FileField support for Biblio?
  • +
  • #469502 problem with viewinline
  • +
  • #465834 issn and section fields too small for patent type
  • +
  • #472062 Biblio and i18n - Problem with assigned language when importing nodes
  • +
  • #471436 Problem with Taxonomy and Biblio Keywords
  • +
  • #469328 What to do if Author is an Organization (CSE and APA styles only)
  • +
  • #464572 Undefined function taxonomy_vocabulary_load()-installation error
  • +
  • #461474 BibTex - ISSN field
  • +
  • #461464 BibTex - Inproceedings and inbook - booktitle replaced by series
  • +
  • #461426 BibTex - @incollection interpreted as @book
  • +
  • #461422 BibTex - export - no doi
  • +
  • #456750 Content Access Permissions are ignored
  • +
  • #459374 Use of $form_state['storage'] to hold a string/integer (as opposed to an array)
  • +
  • #459684 DOI import fails, CrossRef registration required now
  • +
  • #455216 Compilation failed: POSIX named classes.. in biblio_theme.inc
  • +
  • #456360 Export and Import in Bibtext format changes the citekey
  • +
  • #455402 Changes to Biblio Filter
  • +
  • #455022 Extend admin pages to set the 'biblio_author_links' variable
  • +
  • fixed problem with missing sort arrow images when filtering
  • +
  • #460240fixed keyword export in BibTex and EndNote Tagged formats
  • +
  • #453708 Duplicate bibtex export
  • +
  • #453298 "Number of items in the RSS feed" not working...
  • +
  • #450522 Limit on author initials is not respected in Vancouver style
  • +
  • #450030 Minor error on edit authors
  • +
+
+

6.x-1.4

+Bugs Fixed... +
    +
  • #448732 can't save any biblio: "Call to undefined function biblio_explode_keywords()"
  • +
  • #448306 preg_replace() error
  • +
+
+

6.x-1.3

+New features... +
    +
  • Added "DOI Lookup" option on the input form. Entering a valid DOI name (number) here will query crossref.org and poplulate the input form with all the data it gets. You are then presented with the populated form to make further additions/changes prior to saving it to the database.
  • +
  • Added "BibTex cut and paste" option to the input form. Pasting a valid bibTex string into the box will populate the input form with the data and similar to the DOI lookup above, allows you to preview and make changes prior to saving it in the database.
  • +
  • Added a new user permission called "edit biblio authors" which allows the user to edit biblio author information but not other biblio settings, unlike "administer biblio" which gives them the right to edit all biblio settings.
  • +
  • Changed "Views" integration such that Blblio is no longer a "Base" type of view. You should now use the "Node" view type to create a view containing biblio information.
  • +
  • Added an option to toggle sort links between text and tab type display.
  • +
  • Changed Keyword/Taxonomy freetag handling... The Taxonomy freetag input box is no longer displayed on the input form. All keywords/taxonomy freetags should be entered into the biblio Keywords input box and (if required) the taxonomy freetags will be updated when the keywords are saved. This keeps the keywords and freetags in sync and avoids the confustion of having two input boxes (one for keywords and one for freetags).
  • +
+Bugs Fixed... +
    +
  • #444428 simple mispelled words
  • +
  • #437440 Citation Key cannot be longer than 16
  • +
  • #435058 Keywords field length exceeded
  • +
  • #439152 Export by keyword
  • +
  • #356322 Biblio nodes not XHTML-compliant
  • +
  • #355572 Filtering by author should be more lenient / "smart"
  • +
  • #340570 inline biblio_db_search layout is broken
  • +
  • #442916 Shortening forenames does not use betweenInitialsDelim option
  • +
  • #440248 Typo in HTML in _biblio_filter_replace_callback()
  • +
  • #438930 edit_authors permission
  • +
  • #441104 schema module reports a mismatch
  • +
  • #439086 Biblio Keywords and Biblio free tags
  • +
  • #435058 Keywords field length exceeded
  • +
  • #433198 Shortening forename of authors containing UTF-8 special characters does not work
  • +
  • #431688 Interaction between url filter and standard sorting filters
  • +
  • #425852 Biblio page title setting ignored
  • +
  • #429226 Quotes around title in Vancouver style
  • +
  • #421546 Keywords vanish when previewing
  • +
+
+

6.x-1.2

+New features... +
    +
  • Added option to automatically delete authors "orphaned" by the update or deletion of an entry
  • +
  • User selectable bibliographic styles, authorized users can choose a style other than the system default on their "edit user" page
  • +
  • Author "Link" allows 2 or more authors to be linked together (intended to deal with name changes due to marriage, but could be used for other purposes)
  • +
+Bugs Fixed... +
    +
  • #376808 Delete orphaned authors automatically?
  • +
  • #415478 Sorting by type without bars
  • +
  • #414870 "more" link in the Block for new publications
  • +
  • #414380 Only one keyword is shown
  • +
  • #412720 Broken download links when filtering with clean URLs (e.g. /biblio/year/2009)
  • +
  • #410610 "Hyperlink titles using supplied URL if available" feature does not seem to work.
  • +
  • #409952 All Fields appear (even when unchecked) after upgrade from Biblio 5x to 6x
  • +
  • #376802 Search index not updated when editing a node
  • +
  • #404842 Tabs and styling
  • +
  • #404522 Redirection after batch import
  • +
  • #397104 Search function sucks :-)
  • +
  • #403484 Slightly malformed RIS files are not imported
  • +
  • #404080 Typo in hook_menu prevents author type editing
  • +
  • #402468 Filter by author, sort both first and secondary authors
  • +
  • #401938 First name / Last name order switched
  • +
+
+

6.x-1.1

+New features... +
    +
  • MARC format file import
  • +
  • New bibliographic output sytles (AMA, Chicago, MLA, Vancouver)
  • +
  • Authors page (biblio/authors) which displays all authors in the database linked to publication lists filtered by that author. ("edit" links are provided for privileged users)
  • +
  • Author edit/merge form (merge allows you to merge all instances of the same author which have been entered slightly +differently. i.e. Smith, J and John Smith are the same person so you merge the two entries into one.)
  • +
  • Orphaned author page(admin/settings/biblio/author/orphans), allows you to remove authors who are not associated with any publications from the database
  • +
  • Keywords page (biblio/keywords) which displays all keywords in the database linked to publication list filtered by that keyword. ("edit" links are provided for privileged users)
  • +
  • Orphaned keyword page (admin/settings/biblio/keyword/orphans) allows you to find and remove orphaned keywords (keywords which are no longer associated with any publications)
  • +
  • added 'tabledrag' to admin/settings/biblio/defaults and admin/settings/biblio/types/edit/xxx which allows you to change the order of the fields on the input form by just dragging them to the desired location
  • +
  • input your own PHP code to generate cite keys
  • +
+Bugs Fixed... +
    +
  • #398472 Drupal UserID-Author Mapping problems
  • +
  • #396654 Export single reference fails - SQL error
  • +
  • #398226 Fatal error: Cannot break/continue 1 level in biblio.module on line 277
  • +
  • #396096 Caching problem: no filters for anonymous users
  • +
+
+

6.x-1.0

+Bugs Fixed... +
    +
  • [#141602]
  • +
  • [#381190]
  • +
  • [#385830]
  • +
  • [#387788]
  • +
  • [#388722]
  • +
  • [#183517]
  • +
  • [#376852]
  • +
  • [#372820]
  • +
  • [#381070]
  • +
  • [#376852]
  • +
  • [#372038]
  • +
  • [#375085]
  • +
  • innumerable D5 -> D6 upgrade fixes provided by Robert Haschke (http://drupal.org/user/409889)
  • +
  • [#371867]
  • +
  • [#372770]
  • +
  • [#373107]
  • +
  • [#373129]
  • +
  • [#372915]
  • +
  • [#372238]
  • +
  • [#372024]
  • +
  • [#354676] fixed inconsistency between page title and breadcrumb
  • +
  • [#355480] fixed issue with setting user id on import by none admin users
  • +
  • [#357298] fixed another userID related issue
  • +
  • [#336344] fixed problem with taxonomy tags not being added to imported entries
  • +
  • [#356322] added danep's patch to correct XHTML validation warnings
  • +
  • [#355621] fixed PHP4 compatibility problem
  • +
  • [#275410] fixed issue where "My Publications" tab on profile pages could not be turned off
  • +
  • [#359752] fixed issue related to profile and inline modes
  • +
  • [#360391] fixed problem creating database on install with aliased
  • +
  • [#365425] fixed Importing bibtex omits Conference title
  • +
  • [#365435] fixed URL search doesn't show search keywords
  • +
  • [#362696] RIS Import omits Journal Abbreviation field (JA)
  • +
+ + \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/includes/Name.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/includes/Name.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,102 @@ +setStr($str); + } + + /** + * Checks encoding, normalizes whitespace/punctuation, and sets the name string. + * + * @param String $str a utf8-encoding string. + * @return Bool True on success + */ + public function setStr($str) + { + if (!drupal_validate_utf8($str)){ + throw new Exception("Name is not encoded in UTF-8"); + } + $this->str = $str; + $this->norm(); + return true; + } + + public function getStr() + { + return $this->str; + } + + + /** + * Uses a regex to chop off and return part of the namestring + * There are two parts: first, it returns the matched substring, + * and then it removes that substring from $this->str and normalizes. + * + * @param string $regex matches the part of the namestring to chop off + * @param integer $submatchIndex which of the parenthesized submatches to use + * @param string $regexFlags optional regex flags + * @return string the part of the namestring that got chopped off + */ + public function chopWithRegex($regex, $submatchIndex = 0, $regexFlags = '') + { + $regex = $regex . "ui" . $regexFlags; // unicode + case-insensitive + preg_match($regex, $this->str, $m); + $subset = (isset($m[$submatchIndex])) ? $m[$submatchIndex] : ''; + + if ($subset){ + $this->str = preg_replace($regex, ' ', $this->str, -1, $numReplacements); + if ($numReplacements > 1){ + throw new Exception("The regex being used to find the name: '$this->str' has multiple matches."); + } + $this->norm(); + return $subset; + } + else { + return ''; + } + } + + /* + * Flips the front and back parts of a name with one another. + * Front and back are determined by a specified character somewhere in the + * middle of the string. + * + * @param String $flipAroundChar the character(s) demarcating the two halves you want to flip. + * @return Bool True on success. + */ + public function flip($flipAroundChar) + { + $substrings = preg_split("/$flipAroundChar/u", $this->str); + if (count($substrings) == 2){ + $this->str = $substrings[1] . " " . $substrings[0]; + $this->norm(); + } + else if (count($substrings) > 2) { + throw new Exception("Can't flip around multiple '$flipAroundChar' characters in: '$this->str'."); + } + return true; // if there's 1 or 0 $flipAroundChar found + } + + /** + * Removes extra whitespace and punctuation from $this->str + * Strips whitespace chars from ends, strips redundant whitespace, converts whitespace chars to " ". + * + * @return Bool True on success + */ + private function norm() + { + $this->str = preg_replace( "#^\s*#u", "", $this->str ); + $this->str = preg_replace( "#\s*$#u", "", $this->str ); + $this->str = preg_replace( "#\s+#u", " ", $this->str ); + $this->str = preg_replace( "#,$#u", " ", $this->str ); + return true; + } +} +?> diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/includes/Parser.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/includes/Parser.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,214 @@ +getLast() . ", " . $parser->getFirst(); + * //returns "Smith, John" + * + * + */ +class HumanNameParser_Parser { + private $name; + private $nameParts = array(); + private $leadingInit; + private $first; + private $nicknames; + private $middle; + private $last; + private $suffix; + private $category; + private $type; + private $literal; + + private $suffixes; + private $prefixes; + + /* + * Constructor + * + * @param mixed $name Either a name as a string or as a Name object. + */ + public function __construct($name = NULL) + { + $this->suffixes = array('esq','esquire','jr','sr','2','ii','iii','iv'); + $this->prefixes = array('bar','ben','bin','da','dal','de la', 'de', 'del','der','di', + 'ibn','la','le','san','st','ste','van', 'van der', 'van den', 'vel','von'); + $this->setName($name); + } + + public function parseName($name = NULL, $category = NULL) { + $this->literal = 0; + $this->category = 1; + $this->type = 1; + if (is_array($name) && isset($name['name'])) { + if (isset($name['auth_category']) && !empty($name['auth_category']) && empty($category)) { + $this->category = $name['auth_category']; + } + elseif (!empty($category)) { + $this->category = $category; + } + if (isset($name['auth_type']) && !empty($name['auth_type'])) { + $this->type = $name['auth_type']; + } + $this->nameParts = $name; + $this->setName($name['name'], $category); + } + else { + $this->nameParts['name'] = $name; + $this->setName($name, $category); + } + + return $this->getArray(); + } + /** + * Sets name string and parses it. + * Takes Name object or a simple string (converts the string into a Name obj), + * parses and loads its constituant parts. + * + * @param mixed $name Either a name as a string or as a Name object. + */ + public function setName($name = NULL, $category = NULL){ + if ($name) { + $this->category == $category; + + if (is_object($name) && get_class($name) == "HumanNameParser_Name") { // this is mostly for testing + $this->name = $name; + } + elseif (is_array($name) && isset($name['name'])) { + $this->name = new HumanNameParser_Name($name['name']); + $this->nameParts = $name; + } + else { + $this->name = new HumanNameParser_Name($name); + } + + $this->leadingInit = ""; + $this->first = ""; + $this->nicknames = ""; + $this->middle = ""; + $this->last = ""; + $this->suffix = ""; + + if ($this->category == 5 || $this->type == 5) { + $this->last = $name; + $this->literal = TRUE; + } + else { + $this->parse(); + } + + } + } + + public function getleadingInit() { + return $this->leadingInit; + } + public function getFirst() { + return $this->first; + } + public function getNicknames() { + return $this->nicknames; + } + + public function getMiddle() { + return $this->middle; + } + + public function getLast() { + return $this->last; + } + + public function getSuffix() { + return $this->suffix; + } + public function getName(){ + return $this->name; + } + + /** + * returns all the parts of the name as an array + * + * @param String $arrType pass 'int' to get an integer-indexed array (default is associative) + * @return array An array of the name-parts + */ + public function getArray($arrType = 'assoc') { + $arr = array(); + $arr['prefix'] = $this->leadingInit; + $arr['firstname'] = $this->first; + $arr['nicknames'] = $this->nicknames; + $arr['initials'] = substr($this->middle, 0, 10); + $arr['lastname'] = $this->last; + $arr['suffix'] = $this->suffix; + $arr['md5'] = md5(json_encode($arr)); + $arr['literal'] = $this->literal; + + if ($arrType == 'assoc') { + return array_merge($this->nameParts, $arr); + } + else if ($arrType == 'int'){ + return array_values($arr); + } + else { + throw new Exception("Array must be associative ('assoc') or numeric ('num')."); + } + } + + /* + * Parse the name into its constituent parts. + * + * Sequentially captures each name-part, working in from the ends and + * trimming the namestring as it goes. + * + * @return boolean true on success + */ + private function parse() + { + $suffixes = implode("\.*|", $this->suffixes) . "\.*"; // each suffix gets a "\.*" behind it. + $prefixes = implode(" |", $this->prefixes) . " "; // each prefix gets a " " behind it. + + // The regex use is a bit tricky. *Everything* matched by the regex will be replaced, + // but you can select a particular parenthesized submatch to be returned. + // Also, note that each regex requres that the preceding ones have been run, and matches chopped out. + $nicknamesRegex = "/ ('|\"|\(\"*'*)(.+?)('|\"|\"*'*\)) /"; // names that starts or end w/ an apostrophe break this + $suffixRegex = "/,* *($suffixes)$/"; + $lastRegex = "/(?!^)\b([^ ]+ y |$prefixes)*[^ ]+$/"; + $leadingInitRegex = "/^(.\.*)(?= \p{L}{2})/"; // note the lookahead, which isn't returned or replaced + $firstRegex = "/^[^ ]+/"; // + + // get nickname, if there is one + $this->nicknames = $this->name->chopWithRegex($nicknamesRegex, 2); + + // get suffix, if there is one + $this->suffix = $this->name->chopWithRegex($suffixRegex, 1); + + // flip the before-comma and after-comma parts of the name + $this->name->flip(","); + + // get the last name + $this->last = $this->name->chopWithRegex($lastRegex, 0); + if (!$this->last){ + throw new Exception("Couldn't find a last name in '{$this->name->getStr()}'."); + } + + // get the first initial, if there is one + $this->leadingInit = $this->name->chopWithRegex($leadingInitRegex, 1); + + // get the first name + $this->first = $this->name->chopWithRegex($firstRegex, 0); + if (!$this->first && $this->category != 5){ + throw new Exception("Couldn't find a first name in '{$this->name->getStr()}'"); + } + + // if anything's left, that's the middle name + $this->middle = $this->name->getStr(); + return true; + } + + + + + +} +?> diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/includes/biblio.admin.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/includes/biblio.admin.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,2925 @@ + 'vertical_tabs', + '#weight' => 0, + ); + + $form['general'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => t('General'), + '#group' => 'biblio_settings', + '#weight' => 0, + '#description' => '' + ); + + $form['general']['biblio_rev'] = array( + '#markup' => $version, + + ); + + $form['general']['biblio_base'] = array( + '#type' => 'textfield', + '#title' => t('Base URL'), + '#size' => 20, + '#default_value' => variable_get('biblio_base', 'biblio'), + '#description' => t('This sets the base URL used to access the biblio module (e.g. /biblio ).') + ); + $form['#biblio_base'] = $form['general']['biblio_base']['#default_value']; + $form['general']['biblio_base_title'] = array( + '#type' => 'textfield', + '#title' => t('Biblio page title'), + '#size' => 20, + '#default_value' => variable_get('biblio_base_title', 'Biblio'), + '#description' => t('The page title shown on the base URL.') + ); + + $form['general']['biblio_rowsperpage'] = array( + '#type' => 'textfield', + '#title' => t('Number of results per page'), + '#default_value' => variable_get('biblio_rowsperpage', 25), + '#size' => 6, + '#maxlength' => 6, + '#description' => t('This sets the number of results that will be displayed per page.') + ); + $form['general']['biblio_view_only_own'] = array( + '#type' => 'checkbox', + '#title' => t('Restrict users such that they can only view their own biblio entries'), + '#return_value' => 1, + '#default_value' => variable_get('biblio_view_only_own', 0), + '#description' => t('This option restricts the users capability to view biblio entries. They will only be able to see the entries which they have created and own.') + ); + $form['general']['biblio_button_hide'] = array( + '#type' => 'checkbox', + '#title' => t('Hide next button in node form'), + '#return_value' => 1, + '#default_value' => variable_get('biblio_button_hide', 1), + '#description' => t('If checkbox is set a javascript adds the accesible system class "element-invisible" to the next button in node form. The next button is not needed if javascript is available and listening on changes.') + ); + $form['authors'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => t('Authors'), + '#group' => 'biblio_settings', + '#weight' => 10, + '#description' => '' + ); + $form['authors']['biblio_auto_orphaned_author_delete'] = array( + '#type' => 'checkbox', + '#title' => t('Automatically delete orphaned authors'), + '#return_value' => 1, + '#default_value' => variable_get('biblio_auto_orphaned_author_delete', 0), + '#description' => t('Orphaned authors are those which are no longer linked to any entries as the result of a biblio update or delete. This requires a functioning "cron" process.') + ); + $form['authors']['biblio_orphan_clean_interval'] = array( + '#type' => 'radios', + '#title' => t('Orphaned author cleaning frequency'), + '#default_value' => variable_get('biblio_orphan_clean_interval', 24 * 60 * 60), + '#options' => array( + 0 => t('Every CRON run'), + 3600 => t('Hourly'), + 86400 => t('Daily'), + 604800 => t('Weeekly'), + ), + '#description' => t('How frequently should we check for and delete orphans.'), + '#states' => array( + 'invisible' => array( + 'input[name="biblio_auto_orphaned_author_delete"]' => array('checked' => FALSE), + ), + ), + ); + $form['authors']['biblio_init_auth_count'] = array( + '#type' => 'textfield', + '#title' => t('Number of contributor fields to initially display on the input form'), + '#size' => 2, + '#maxlength' => 2, + '#default_value' => variable_get('biblio_init_auth_count', 4), + '#description' => t('Increasing this value will increase the number of input fields displayed in the contributors section of the input form') + ); + $form['authors']['biblio_contrib_fields_delta'] = array( + '#type' => 'textfield', + '#title' => t('Number of fields added by the "Add more" button on the contributor input form'), + '#size' => 2, + '#maxlength' => 2, + '#default_value' => variable_get('biblio_contrib_fields_delta', 2), + '#description' => t('This number of blank fields will be added to the contributors section of the input form each time the "Add more" button is pressed.') + ); + $form['bibtex'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => t('BibTex settings'), + '#group' => 'biblio_settings', + '#weight' => 20, + '#description' => '' + ); + $form['bibtex']['biblio_hide_bibtex_braces'] = array( + '#type' => 'checkbox', + '#title' => t('Retain bibtex\'s {Protected} capitalization in the title string, but hide the braces on display'), + '#return_value' => 1, + '#default_value' => variable_get('biblio_hide_bibtex_braces', 0), + '#description' => '' + ); + + $result = db_query("SELECT b.name, bftd.title FROM {biblio_fields} b + INNER JOIN {biblio_field_type} bt ON bt.fid=b.fid + INNER JOIN {biblio_field_type_data} bftd ON bftd.ftdid=bt.ftdid + WHERE bt.tid=0 ORDER by bftd.title ASC "); + $schema = drupal_get_schema('biblio'); + $keys = array_keys($schema['fields']); + $options = array(); + $options['nid'] = t('Node ID'); + foreach ($result as $row) { + $options[$row->name] = $row->title; + } + $form['citekey'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => t('Citekey'), + '#description' => t('You can alter citekey related settings here.'), + '#group' => 'biblio_settings', + '#weight' => 30, + + ); + $form['citekey']['biblio_display_citation_key'] = array( + '#type' => 'checkbox', + '#title' => t('Show citation key in results'), + '#return_value' => 1, + '#default_value' => variable_get('biblio_display_citation_key', 0), + '#description' => t('This will output the citekey as the first item in the citation string') + ); + $form['citekey']['biblio_auto_citekey'] = array( + '#type' => 'checkbox', + '#title' => t('Auto generate citekeys if not given'), + '#return_value' => 1, + '#default_value' => variable_get('biblio_auto_citekey', 1), + '#description' => t('This option will cause "citekey" entries to be automatically generated if a value is not provided.') + ); + $form['citekey']['biblio_citekey_prefix'] = array( + '#type' => 'textfield', + '#title' => t('Citekey prefix'), + '#default_value' => variable_get('biblio_citekey_prefix', ''), + '#size' => 10, + '#maxlength' => 10, + '#description' => t('This text will be combined with the field choosen below to form the auto generated citekey.') + ); + $form['citekey']['biblio_citekey_field1'] = array( + '#type' => 'select', + '#title' => t('Primary Citekey field'), + '#default_value' => variable_get('biblio_citekey_field1', 'nid'), + '#options' => $options, + '#description' => t('Select the field to be used when generating citekeys.') + ); + $form['citekey']['biblio_citekey_field2'] = array( + '#type' => 'select', + '#title' => t('Secondary Citekey field'), + '#default_value' => variable_get('biblio_citekey_field2', 'nid'), + '#options' => $options, + '#description' => t('If the field above has no value this field will be used.') + ); + // Allow only users to modify PHP code which have PHP block visibility permissions + if (user_access('use PHP for block visibility')) { + $form['citekey']['biblio_citekey_phpcode'] = array( + '#type' => 'textarea', + '#title' => t('PHP code for citekey generation'), + '#default_value' => variable_get('biblio_citekey_phpcode', ''), + '#description' => t('Advanced usage only: PHP code that returns the citekey. Should not include <?php ?> delimiters.') + ); + } + + $form['biblio_crossref'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => t('CrossRef Login Information'), + '#group' => 'biblio_settings', + '#weight' => 40, + ); + $link_attrs = array('attributes' => array('target' => '_blank'), + 'absolue' => TRUE); + $form['biblio_crossref']['biblio_show_crossref_profile_form'] = array( + '#type' => 'checkbox', + '#title' => t('Allow users to override these settings on their "My account" page') , + '#return_value' => 1, + '#description' => t('If this is selected, a form similar to this section will be available to the user when they edit their own account information. This will allow them to override the global preferences set here.') , + '#default_value' => variable_get('biblio_show_crossref_profile_form', '1') + ); + $form['biblio_crossref']['biblio_crossref_pid'] = array( + '#type' => 'textfield', + '#title' => t('CrossRef OpenURL Account ID'), + '#default_value' => variable_get('biblio_crossref_pid', ''), + '#description' => t('Enter your complimentary CrossRef OpenURL account ID which you can obtain here !url, OR enter your full CrossRef (colon separated) account:password combination.', array('!url' => l(t('OpenURL Account Request Form'), 'http://www.crossref.org/requestaccount/', $link_attrs))) + ); + + $form['footnotes'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => t('Footnotes'), + '#description' => t('You can integrate with the !url module here.', array('!url' => l('footnotes', url("http://www.drupal.org/project/footnotes", array('query' => NULL, 'fragment' => NULL, 'absolute' => TRUE))))), + '#group' => 'biblio_settings', + '#weight' => 50, + ); + if (!module_exists('footnotes')) { + $additional_text = '
' . t('Depends on') . ': ' . t('Footnotes') . ' (' . t('disabled') . ')
'; + $disabled = TRUE; + variable_set('biblio_footnotes_integration', 0); + } + else { + $additional_text = '
' . t('Depends on') . ': ' . t('Footnotes') . ' (' . t('enabled') . ')
'; + $disabled = FALSE; + } + $form['footnotes']['biblio_footnotes_integration'] = array( + '#type' => 'checkbox', + '#title' => t('Integration with the footnotes module') . $additional_text, + '#disabled' => $disabled, + '#return_value' => 1, + '#default_value' => variable_get('biblio_footnotes_integration', 0), + '#description' => t('This will convert <bib> tags into <fn> tags. This will cause intermingled <bib> and <fn> tags to be sequentially numbered. For this to work, you must put the <bib> filter ahead of the <fn> filter in the filter chain. If this option is not set, <bib> and <fn> tags will be handled separately.') + ); + $form['isi_wok'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => t('ISI Web of Knowledge'), + '#description' => '', + '#group' => 'biblio_settings', + '#weight' => 60, + ); + $form['isi_wok']['biblio_fix_isi_links'] = array( + '#type' => 'checkbox', + '#title' => t('Automatically replace "Go to ISI" links with the URL below'), + '#return_value' => 1, + '#default_value' => variable_get('biblio_fix_isi_links', 0), + '#description' => t('This option automatically replaces any fake "Go to ISI" links with the supplied URL to ISI Web of Knowledge. Note a subscription with ISI is required for these links to function.') + ); + $form['isi_wok']['biblio_isi_url'] = array( + '#type' => 'textfield', + '#title' => t('ISI Web of Knowledge URL'), + '#size' => 128, + '#maxlength' => 512, + '#default_value' => variable_get('biblio_isi_url', 'http://apps.isiknowledge.com/InboundService.do?Func=Frame&product=WOS&action=retrieve&SrcApp=EndNote&Init=Yes&SrcAuth=ResearchSoft&mode=FullRecord&UT='), + '#description' => t('Enter the URL which will replace the "Go to ISI" fake links imported from EndNote') + ); + $form['keywords'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => t('Keywords'), + '#description' => '', + '#group' => 'biblio_settings', + '#weight' => 70, + ); + $form['keywords']['biblio_keyword_sep'] = array( + '#type' => 'textfield', + '#title' => t('Keyword separator'), + '#size' => 2, + '#default_value' => variable_get('biblio_keyword_sep', ','), + '#description' => t('Enter the character which will be used to separate multiple keywords in the keyword field') + ); + $form['keywords']['biblio_keyword_orphan_autoclean'] = array( + '#type' => 'checkbox', + '#title' => t('Automatically remove orphaned keywords'), + '#return_value' => 1, + '#default_value' => variable_get('biblio_keyword_orphan_autoclean', 1), + '#description' => t('This option automatically deletes keywords which are no longer associated with any publications (primarily due to the due to the removal of a publication or editing a keyword).') + ); + $taxo_mesg = '
' . t('Depends on') . ': ' . t('Taxonomy') . ' (' . t('disabled') . ')
'; + $form['keywords']['biblio_copy_taxo_terms_to_keywords'] = array( + '#type' => 'checkbox', + '#title' => t('Copy any selected taxonomy terms to the biblio keyword database'), + '#return_value' => 1, + '#default_value' => module_exists('taxonomy') ? variable_get('biblio_copy_taxo_terms_to_keywords', 0) : 0, + '#disabled' => (!module_exists('taxonomy')), + '#description' => module_exists('taxonomy') ? t('If this option is selected, the selected taxonomy terms will be copied to the @base_title keyword database and be displayed as keywords (as well as taxonomy terms) for this entry.', array('@base_title', variable_get('biblio_base_title', 'Biblio'))) : $taxo_mesg + ); + $form['keywords']['biblio_keyword_freetagging'] = array( + '#type' => 'checkbox', + '#title' => t('Use keywords from biblio entries as taxonomy "free tags"'), + '#return_value' => 1, + '#default_value' => module_exists('taxonomy') ? variable_get('biblio_keyword_freetagging', 0) : 0, + '#disabled' => (!module_exists('taxonomy')), + '#description' => module_exists('taxonomy') ? t('This option allows user to add keywords (free tags) to describe their documents. These keywords will be registered as taxonomy.') : $taxo_mesg + ); + $vocabularies = module_invoke('taxonomy', 'get_vocabularies'); + // ... and print a form to select the terms in each of them + $taxo_options = array(); + $taxo_options[0]= '<' . t('none') . '>'; + if (count($vocabularies)) { + foreach ($vocabularies as $voc) { + $taxo_options[$voc->vid] = $voc->name; + } + $form['keywords']['biblio_keyword_vocabulary'] = array( + '#type' => 'select', + '#title' => t('Vocabulary'), + '#default_value' => variable_get('biblio_keyword_vocabulary', 0), + '#options' => $taxo_options, + '#description' => t('Select vocabulary (category) to use for free tags.'), + '#multiple' => FALSE, + // '#disabled' => (!variable_get('biblio_keyword_freetagging', 0)), + // '#size' => $multiple ? min(9, count($taxo_options)) : 0, + '#weight' => 15, + '#states' => array( + 'invisible' => array( + 'input[name="biblio_keyword_freetagging"]' => array('checked' =>FALSE), + ), + ), + ); + } + + $form['links'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => t('Links'), + '#group' => 'biblio_settings', + '#weight' => 80, + ); + $form['links']['export'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => FALSE, + '#title' => t('Export Links') + ); + $options = array(); + $export_defaults = array(); + $options = module_invoke_all('biblio_export_options'); + if (!empty($options)) { + $export_defaults = array_combine(array_keys($options), array_keys($options)); + } + $form['links']['export']['biblio_export_links'] = array( + '#type' => 'checkboxes', + '#title' => t('Show export links'), + '#default_value' => array_merge($export_defaults, variable_get('biblio_export_links', $export_defaults)), + '#options' => $options, + '#description' => t('You can select which export links to display here.') + ); + $form['links']['file_attachments'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => FALSE, + '#title' => t('File Attachments') + ); + $form['links']['file_attachments']['biblio_file_link_type'] = array( + '#type' => 'radios', + '#title' => t('File attachment display'), + '#default_value' => variable_get('biblio_file_link_type', 'text'), + '#options' => array( + 'text' => t('Text'), + 'icon' => t('Icon'), + ), + '#description' => t('Display file attachments as either the file name or an icon') + ); + + $form['links']['google'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => FALSE, + '#title' => t('Lookup Links') + ); + + $options = module_invoke_all('biblio_lookup_link_settings'); + $options += array('google' => 'Google Scholar'); + $lookup_defaults = array_combine(array_keys($options), array_keys($options)); + + $form['links']['google']['biblio_lookup_links'] = array( + '#type' => 'checkboxes', + '#title' => t('Show lookup links'), + '#default_value' => array_merge($lookup_defaults, variable_get('biblio_lookup_links', $lookup_defaults)), + '#options' => $options, + '#description' => t('You can select which lookup links to display here.') + ); + + $form['links']['biblio_download_links_to_node'] = array( + '#type' => 'checkbox', + '#title' => t('Download links in "List" view link to "Node" view'), + '#return_value' => 1, + '#default_value' => variable_get('biblio_download_links_to_node', 0), + '#description' => t('If selected, the download links in the "List" view will link to the full "Node" view rather than the file itself, the file can then be downloaded from the node view') + ); + $form['links']['biblio_links_target_new_window'] = array( + '#type' => 'checkbox', + '#title' => t('Links open in new browser'), + '#return_value' => 1, + '#default_value' => variable_get('biblio_links_target_new_window', 0), + '#description' => t('This causes related URLs to open in a new browser window') + ); + + $form['links']['biblio_link_title_url'] = array( + '#type' => 'checkbox', + '#title' => t('Hyperlink titles using supplied URL if available'), + '#return_value' => 1, + '#default_value' => variable_get('biblio_link_title_url', 0), + '#description' => t('Selecting this links the titles to the supplied URL (if available) rather than the "node" view.') + ); + $form['links']['author'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => FALSE, + '#title' => t('Author Links') + ); + $form['links']['author']['biblio_author_links'] = array( + '#type' => 'checkbox', + '#title' => t('Hyperlink author names'), + '#return_value' => 1, + '#default_value' => variable_get('biblio_author_links', 1), + '#description' => t('This creates a hyperlink on author names which, when clicked, will select entries which contain that author') + ); + $form['links']['author']['biblio_author_link_profile'] = array( + '#type' => 'checkbox', + '#title' => t('Hyperlink author names to author profile page'), + '#return_value' => 1, + '#default_value' => variable_get('biblio_author_link_profile', 0), + '#description' => t('This creates a hyperlink on author names which, when clicked, will take the user to the authors profile page') + ); + $form['links']['author']['biblio_author_link_profile_path'] = array( + '#type' => 'textfield', + '#title' => t('Path to profile page'), + '#default_value' => variable_get('biblio_author_link_profile_path', 'user/[user:uid]'), + '#description' => t('Do not include a leading "/"') + ); + + $form['links']['author']['token_tree'] = array( + '#theme' => 'token_tree', + '#token_types' => array('user'), + ); + + $form['openurl'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => t('OpenURL'), + '#description' => t('You can set an openurl link here'), + '#group' => 'biblio_settings', + '#weight' => 90, + ); + $form['openurl']['biblio_show_openurl_profile_form'] = array( + '#type' => 'checkbox', + '#title' => t('Allow users to override these settings on their "My account" page') , + '#return_value' => 1, + '#description' => t('If this is selected, a form similar to this section will be available to the user when they edit their own account information. This will allow them to override the global preferences set here.') , + '#default_value' => variable_get('biblio_show_openurl_profile_form', '1') + ); + + $form['openurl']['biblio_baseopenurl'] = array( + '#type' => 'textfield', + '#title' => t('OpenURL Base URL'), + '#size' => 95, + '#default_value' => variable_get('biblio_baseopenurl', ''), + '#description' => t('This sets your institution\'s base OpenURL gateway, which is used to generate OpenURL links. To implement a "Universal" OpenURL system, try using OCLC\'s OpenURL Resolver Registry gateway: http://worldcatlibraries.org/registry/gateway') + ); + $sid = "Biblio:" . variable_get('site_name', 'Drupal'); + $form['openurl']['biblio_openurl_sid'] = array( + '#type' => 'textfield', + '#title' => t('OpenURL Site ID'), + '#size' => 95, + '#default_value' => variable_get('biblio_openurl_sid', $sid), + '#description' => t('This sets your institution\'s site name, some link resolvers will require a specific Site ID in order to process your requests.') + ); + $form['openurl']['biblio_openurlimage'] = array( + '#type' => 'textfield', + '#title' => t('OpenURL Image'), + '#size' => 95, + '#default_value' => variable_get('biblio_openurlimage', ''), + '#description' => t('Enter a path to your image here, this image will be used as button which when clicked will find the entry via the OpenURL link') + ); + // Add profile page settings... this is done in a fucntion so it can be reused elsewhere + $form['biblio_profile'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => t('Profile pages'), + '#group' => 'biblio_settings', + '#weight' => 100, + ); + $form['biblio_profile'] += _biblio_get_user_profile_form(); + // + if (!module_exists('search')) { + $search_text = '
' . t('Depends on') . ': ' . t('Search') . ' (' . t('disabled') . ')
'; + $search_disabled = TRUE; + variable_set('biblio_footnotes_integration', 0); + } + else { + $search_text = '
' . t('Depends on') . ': ' . t('Search') . ' (' . t('enabled') . ')
'; + $search_disabled = FALSE; + } + $form['search'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#description' => $search_text, + '#title' => t('Search'), + '#group' => 'biblio_settings', + '#weight' => 110, + ); + $form['search']['biblio_search'] = array( + '#type' => 'checkbox', + '#disabled' => $search_disabled, + '#title' => t('Enable a search box on the biblio page.'), + '#return_value' => 1, + '#default_value' => variable_get('biblio_search', 0), + '#description' => t('Shows a search box on the biblio page that returns drupal search results in the biblio style.') + ); + $form['search']['biblio_search_button_text'] = array( + '#type' => 'textfield', + '#title' => t('Search button text'), + '#disabled' => $search_disabled, + '#size' => 95, + '#default_value' => variable_get('biblio_search_button_text', t('Biblio search')), + '#description' => t('This allows you to customize the text on the search button, it defaults to "Biblio search".') + ); + $form['search']['biblio_index'] = array( + '#type' => 'checkbox', + '#disabled' => $search_disabled, + '#title' => t('Re-/Index a biblio node when creating or updating.'), + '#return_value' => 1, + '#default_value' => variable_get('biblio_index', 0), + '#description' => t('A biblio node must be indexed for the drupal search to know its content. You need to check this option if you want to search for a biblio node that you just created or updated. Otherwise you must wait for the cron job to reindex nodes.') + ); + $form['sort'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => t('Sorting'), + '#description' => t('You can set the default sorting and ordering for the /biblio page here.'), + '#group' => 'biblio_settings', + '#weight' => 120, + ); + $form['sort']['biblio_sort'] = array( + '#type' => 'select', + '#title' => t('Sort by'), + '#default_value' => variable_get('biblio_sort', 'year'), + '#options' => array( + 'author' => t('Author'), + 'keyword' => t('Keyword'), + 'title' => t('Title'), + 'type' => t('Type'), + 'year' => t('Year') + ), + '#description' => t('This is the initial default sort.'), + ); + $stop_words = 'a,an,is,on,the'; + $form['sort']['biblio_stop_words'] = array( + '#type' => 'textfield', + '#title' => t('Words to remove from the beginning of titles prior to sorting'), + '#size' => 60, + '#default_value' => variable_get('biblio_stop_words', $stop_words), + '#description' => t('A comma separated list of (case insensitive) words to strip from the title for sorting purposes. NOTE: quotation and punctuation are stripped automatically.') + ); + + $form['sort']['biblio_sort_tabs'] = array( + '#type' => 'checkboxes', + '#title' => t('Show sort links'), + '#default_value' => variable_get('biblio_sort_tabs', array('author', 'title', 'type', 'year')), + '#options' => array( + 'author' => t('Author'), + 'keyword' => t('Keyword (Warning: sorting by keyword may produce many duplicates due to the fact that an entry is listed for each keyword attached to it.)'), + 'title' => t('Title'), + 'type' => t('Type'), + 'year' => t('Year') + ), + '#description' => t('You turn the sorting links at the top of the /biblio page here.') + ); + $form['sort']['biblio_sort_tabs_style'] = array( + '#type' => 'checkbox', + '#title' => t('Show sort links as "tabs"'), + '#default_value' => variable_get('biblio_sort_tabs_style', 0), + '#return_value' => 1, + '#description' => t('This changes the sort links from text links to tabs') + ); + $form['sort']['biblio_order'] = array( + '#type' => 'radios', + '#title' => t('Order'), + '#default_value' => variable_get('biblio_order', 'DESC'), + '#options' => array( + 'DESC' => t('Descending'), + 'ASC' => t('Ascending') + ) + ); + $form['style'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => t('Styling'), + '#description' => t('You can set the default style for the /biblio page here.'), + '#group' => 'biblio_settings', + '#weight' => 130, + ); + $form['style']['biblio_no_year_text'] = array( + '#type' => 'textfield', + '#title' => t('Text to display if no year of publication is available'), + '#size' => 95, + '#default_value' => variable_get('biblio_no_year_text', t('Submitted')), + '#description' => t('The text that is displayed when no date of publication is given or it is deliberately set to 9999, it defaults to "Submitted".') + ); + $form['style']['biblio_inpress_year_text'] = array( + '#type' => 'textfield', + '#title' => t('Text to display if year of publication is set to 9998'), + '#size' => 95, + '#default_value' => variable_get('biblio_inpress_year_text', t('In Press')), + '#description' => t('The text that is displayed when the date of publication is deliberately set to 9998, it defaults to "In Press".') + ); + if (module_exists('biblio_citeproc')) { + $form['style']['biblio_citeproc_style'] = array( + '#type' => 'select', + '#title' => t('Style'), + '#default_value' => variable_get('biblio_citeproc_style', 'ieee.csl'), + '#options' => biblio_get_styles(), + '#description' => t('Set the bibliographic style of the "list" view.') + ); + } + else { + $form['style']['biblio_style'] = array( + '#type' => 'select', + '#title' => t('Style'), + '#default_value' => variable_get('biblio_style', 'cse'), + '#options' => biblio_get_styles(), + '#description' => t('Set the bibliographic style of the "list" view.') + ); + } + $form['style']['biblio_node_layout'] = array( + '#type' => 'radios', + '#title' => t('Node Layout'), + '#default_value' => variable_get('biblio_node_layout', 'tabular'), + '#options' => array( + 'orig' => t('Original'), + 'ft' => t('Only Fulltext if available'), + 'tabular' => t('Tabular'), + 'cite' => t('Bibliographic style choosen above') + ), + '#description' => t('This alters the layout of the "node" (full) view.') + ); + $form['style']['biblio_annotations'] = array( + '#type' => 'select', + '#title' => t('Annotations'), + '#default_value' => variable_get('biblio_annotations', 'none'), + '#options' => array( + 'none' => t('none'), + 'biblio_notes' => t('notes'), + 'biblio_custom1' => t('custom1'), + 'biblio_custom2' => t('custom2'), + 'biblio_custom3' => t('custom3'), + 'biblio_custom4' => t('custom4'), + 'biblio_custom5' => t('custom5'), + 'biblio_custom6' => t('custom6'), + 'biblio_custom7' => t('custom7') + ), + '#description' => t('Select a field from which an annotation will be displayed below biblo entry in "short" listings'), + '#multiple' => FALSE, + '#size' => 0 + ); + $form['syndication'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => t('Syndication'), + '#description' => t('You can set the RSS defaults here.'), + '#group' => 'biblio_settings', + '#weight' => 140, + ); + $form['syndication']['biblio_rss'] = array( + '#type' => 'checkbox', + '#title' => t('Allow RSS feeds of new biblio entries'), + '#return_value' => 1, + '#default_value' => variable_get('biblio_rss', 0), + '#description' => t('This will create an rss feed of the 10 most recent biblio entries. It will be available at /biblio/rss.xml') + ); + $form['syndication']['biblio_rss_number_of_entries'] = array( + '#type' => 'textfield', + '#title' => t('Number of items in the RSS feed.'), + '#default_value' => variable_get('biblio_rss_number_of_entries', 10), + '#size' => 6, + '#maxlength' => 6, + '#description' => t('Limits the number of items in the /biblio/rss.xml feed to this number.') + ); + + $form = system_settings_form($form); + $form['#submit'][] = 'biblio_admin_settings_form_submit'; + // our submit handler is added after the call to system settings form so that it gets + // called after system_settings_form_submit, and thus the variables have been stored already + // and the menu will be rebuilt correctly. + return ($form); +} +/** + * Form handler for biblio_admin_settings + * + */ +function biblio_admin_settings_form_submit($form, &$form_state) { +// if ($form_state['values']['biblio_keyword_freetagging'] && $form_state['values']['biblio_keyword_vocabulary']) { +// if ($vocabulary = taxonomy_vocabulary_load(variable_get('biblio_keyword_vocabulary', 0))) { +// $vocabulary = (array) $vocabulary; +// $vocabulary['nodes']['biblio'] = 1; +// taxonomy_save_vocabulary($vocabulary); +// } +// } + + if (($form['#biblio_base'] != $form_state['values']['biblio_base']) || + ($form['biblio_profile']['#biblio_show_profile'] != $form_state['values']['biblio_show_profile']) || + ($form['biblio_profile']['#biblio_my_pubs_menu'] != $form_state['values']['biblio_my_pubs_menu']) ) + { + menu_rebuild(); + } +} +/** + * Form constructor for the Publication type edit form. + * + * @param int $tid + * The publication type. + * @return array $form + */ +function biblio_admin_types_edit_form($form, &$form_state, $tid = 0) { + // $form['#theme'] = 'biblio_admin_types_edit_form'; + // $form['#tree'] = TRUE; + $form['#cache'] = TRUE; + $tid = (isset($form_state['pub_type']) ? $form_state['pub_type'] : (int)$tid); + $msg = '
' . t('On this page you can set type specific "Titles" and "Hints" which will display on the input form.'); + if ($tid) { + $msg .= ' ' . t('Checking the "Visible" box will add the field to the input form, checking "Required" will force the user to supply a value for this field and the weight value changes the order which it is rendered on the form with smaller values floating to the top of the form. +

Fields which are grayed out on this page have been set to "common" on the !linktobiblioadmin page.

', array('!linktobiblioadmin' => l("admin/config/content/biblio/fields", "admin/config/content/biblio/fields"))); + + } + else { + $msg .= ' ' . t('Checking the "Common" box will add the field to all the different publication types. Checking "Required" will force the user to supply a value for the field, checking "Autocomplete" will enable AJAX type auto complete look up for the field when the user is entering data and the weight value changes the order which it is rendered on the form with smaller values floating to the top of the form.'); + } + $msg .= t('Finally, for each author field you can choose a set of author roles. Assigning different roles to authors within the same field, e.g. primary and secondary authors within the authors field, allows to theme them differently.'); + $msg .= '
'; + + $form['#redirect'] = 'admin/config/content/biblio/fields'; + $form['help'] = array( + '#type' => 'fieldset', + '#title' => t('Help'), + '#collapsible' => TRUE, + '#collapsed' => TRUE + ); + $form['help']['message'] = array( + '#markup' => $msg + ); + // get author types + $result = db_query("SELECT * FROM {biblio_contributor_type_data} b"); + $contrib_options = array(); + foreach ($result as $contrib_type) { + $contrib_options[$contrib_type->auth_type] = $contrib_type->title; + $contrib_hints[$contrib_type->auth_type] = $contrib_type->hint; + } + + // first get all of the field info + if ($tid) { + $result = db_query("SELECT bf.*, bftd.*, bft.vtab, bft.common, bft.visible, bft.autocomplete, bft.weight, bft.required, bt.name AS type_name + FROM {biblio_fields} AS bf + INNER JOIN {biblio_field_type} AS bft ON bft.fid=bf.fid + INNER JOIN {biblio_field_type_data} AS bftd ON bftd.ftdid=bft.ftdid + INNER JOIN {biblio_types} AS bt ON bt.tid=bft.tid + WHERE bft.tid=:tid", array(':tid' => $tid), array('fetch' => PDO::FETCH_ASSOC)); + } + else { + $result = db_query("SELECT bf.*, bftd.*, bft.vtab, bft.common, bft.visible, bft.autocomplete, bft.weight, bft.required + FROM {biblio_fields} AS bf + INNER JOIN {biblio_field_type} AS bft ON bft.fid=bf.fid + INNER JOIN {biblio_field_type_data} AS bftd ON bftd.ftdid=bft.ftdid + WHERE bft.tid=:tid", array(':tid' => $tid), array('fetch' => PDO::FETCH_ASSOC)); + } + + foreach ($result as $row) { + $fields[$row['fid']] = $row; + } + + $types = db_query("SELECT * from {biblio_types} WHERE visible=1 ORDER BY name ASC"); + $types_options[0] = t('Common'); + foreach ($types as $type) { + $types_options[$type->tid] = $type->name; + } + + $form['pub_type'] = array( + '#title' => t('Publication type'), + '#type' => 'select', + '#options' => $types_options, + '#attributes' => array('onchange' => 'document.getElementById(\'edit-change-type\').click()'), + '#default_value' => $tid, + ); + + $no_js = (!isset($_COOKIE['has_js']) || empty($_COOKIE['has_js'])); + + $form['change_type'] = array( + '#type' => 'submit', + '#value' => t('Change Publication Type'), + '#weight' => -10, + '#prefix' => $no_js ? '' : '
', + '#suffix' => $no_js ? '' : '
', + ); + + $form['biblio_tabs'] = array( + '#type' => 'vertical_tabs', + '#weight' => 0, + ); + + $form['biblio_tabs'] += biblio_node_form_vtabs(); + + // $form['configured_flds'] = array('#tree' => 1); + if ($tid) { // show an existing type + $typename = $fields[1]['type_name']; + $form['type_name'] = array( + '#title' => t('Publication type name'), + '#type' => 'textfield', + '#maxlength' => 64, + '#default_value' => $typename, + '#required' => TRUE, + ); + $form['top_message'] = array( + '#value' => t('Field settings related to @type publications', array('@type' => $typename)) + ); + $form['type_id'] = array( + '#type' => 'value', + '#title' => 'tid', + '#value' => $tid + ); + } + else { + $form['top_message'] = array( + '#value' => t('Field settings common to all publication types') + ); + + } + uasort($fields, "biblio_form_sort"); // resort the fields since the weight may have changed + $vis_comm = $tid ? 'visible' : 'common'; + $options["$vis_comm"] = ''; + $options['required'] = ''; + if ($tid == 0) { + $options['autocomplete'] = ''; + } + foreach ($fields as $key => $fld) { + if ($fld['type'] == 'contrib_widget') { + continue; + } + $def_values[$fld['name']] = array(); + if ($tid) { + if ($fld['visible'] ) { + array_push($def_values[$fld['name']], 'visible'); + } + if ($fld['required']) { + array_push($def_values[$fld['name']], 'required'); + } + } + else { + if ($fld['common']) { + array_push($def_values[$fld['name']], 'common'); + } + if ($fld['required']) { + array_push($def_values[$fld['name']], 'required'); + } + if ($fld['autocomplete']) { + array_push($def_values[$fld['name']], 'autocomplete'); + } + } + $disabled = $tid ? ($fld['common'] ? 1 : 0) : 0; + $form_state['tab_defaults'][$key]['common'] = $disabled; + + $tab_data[$fld['vtab']][$key]['#parents'] = array('biblio_tabs', $key); + $tab_data[$fld['vtab']][$key]['name'] = array( + '#type' => 'markup', + '#markup' => check_plain($fld['name']), + '#weight' => $fld['weight'] + ); + $tab_data[$fld['vtab']][$key]['title'] = array( + '#type' => 'textfield', + '#default_value' => $fld['title'], + '#size' => 15, + '#weight' => $fld['weight'], + '#disabled' => $disabled + ); + $form_state['tab_defaults'][$key]['title']['default'] = $fld['title']; //we need store the default to see if it's changed later + $form_state['tab_defaults'][$key]['title']['disabled'] = $disabled; + + $tab_data[$fld['vtab']][$key]['hint'] = array( + '#type' => 'textfield', + '#default_value' => $fld['hint'], + '#size' => 20, + '#weight' => $fld['weight'], + '#disabled' => $disabled + ); + $form_state['tab_defaults'][$key]['hint']['default'] = $fld['hint']; + $form_state['tab_defaults'][$key]['hint']['disabled'] = $disabled; + + $tab_data[$fld['vtab']][$key]['weight'] = array( + '#type' => 'textfield', + '#default_value' => $fld['weight'], + '#size' => 2, + '#weight' => $fld['weight'], + //'#disabled' => $disabled + ); + $tab_data[$fld['vtab']][$key]['checkboxes'] = array( + '#type' => 'checkboxes', + '#options' => $options, + '#default_value' => $def_values[$fld['name']], + '#weight' => $fld['weight'], + //'#disabled' => $disabled + ); + $tab_data[$fld['vtab']][$key]['ftdid'] = array( + '#type' => 'value', + '#value' => $fld['ftdid'] + ); + + } + if ($tid) { + $header = array('', t('Field Name'), t('Title'), t('Hint'), t('Visible'), t('Required'), ''); + } + else { + $header = array('', t('Field Name'), t('Default Title'), t('Hint'), t('Common'), t('Required'), t('Autocomplete'), ''); + } + + foreach ($tab_data as $key => $rows) { + $form['biblio_tabs'][$key][] = array( + '#theme' => 'biblio_field_tab', + '#header' => $header, + 'rows' => $rows, + ); + } + + $form['biblio_tabs']['#tree'] = TRUE; + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Save') + ); + + return $form; +} + +/** + * Form handler for biblio_admin_types_edit_form + */ +function biblio_admin_types_edit_form_submit($form, &$form_state) { + if ($form_state['triggering_element']['#value'] == t('Change Publication Type')) { + $form_state['rebuild'] = TRUE; + $form_state['pub_type'] = $form_state['values']['pub_type']; + $form_state['input'] = array(); + return; + } + $tid = isset($form_state['values']['type_id']) ? $form_state['values']['type_id'] : 0; + + if ($tid) { + // save publication type name + $type_name_record = array( + 'tid' => $tid, + 'name' => $form_state['values']['type_name'], + ); + + db_update('biblio_types') + ->fields($type_name_record) + ->condition('tid', $tid) + ->execute(); + biblio_locale_refresh_types($tid); + } + + $hide_other_fields = isset($form_state['values']['hide_other_fields']) ? $form_state['values']['hide_other_fields'] : 0; + variable_set('biblio_hide_other_fields', $hide_other_fields); + + // save other field data + foreach ($form_state['values']['biblio_tabs'] as $fid => $values) { + $update = FALSE; + $val = array(); + $link = array(); + if (is_int($fid)) { + $common = $form_state['tab_defaults'][$fid]['common']; + $link['fid'] = $fid; + $link['tid'] = $tid; + foreach ($values as $name => $value) { + $disabled = !empty($form_state['tab_defaults'][$fid][$name]['disabled']) ? TRUE : FALSE; + if (!$disabled) { + $default_value = isset($form_state['tab_defaults'][$fid][$name]['default']) ? $form_state['tab_defaults'][$fid][$name]['default'] : ''; + if ($name == 'checkboxes') { + $link['visible'] = (!empty($value['visible'])) ? 1 : 0; + $link['required'] = (!empty($value['required'])) ? 1 : 0; + if ($tid == 0) { + $link['common'] = (!empty($value['common'])) ? 1 : 0; + $link['autocomplete'] = (!empty($value['autocomplete'])) ? 1 : 0; + } + } + elseif ($name == 'weight') { + $link['weight'] = $value; + } + else { + $val[$name] = $common ? $default_value : $value; + if (!$update) { + $update = ($default_value != $val[$name]) ? $form_state['values']['biblio_tabs'][$fid]['ftdid'] : FALSE; + } + } + } + } + if ($update == $fid && $link['tid']) { // we just changed a default value, so create a new entry in biblio_field_type_data + $new_ftdid = variable_get('biblio_last_ftdid', 100); + variable_set('biblio_last_ftdid', $new_ftdid + 1); + $val['ftdid'] = $new_ftdid; + $link['ftdid'] = $new_ftdid; + $link['cust_tdid'] = $new_ftdid; + drupal_write_record('biblio_field_type_data', $val); + + } + elseif ($update >= 100 && $link['tid']) { // we are updating an existing entry + $val['ftdid'] = $form_state['values']['biblio_tabs'][$fid]['ftdid']; + drupal_write_record('biblio_field_type_data', $val, 'ftdid'); + + } + elseif ($update == $fid) { // changing the defaults + $val['ftdid'] = $fid; + drupal_write_record('biblio_field_type_data', $val, 'ftdid'); + } + + drupal_write_record('biblio_field_type', $link, array('fid', 'tid')); + + if ($tid == 0) { + if ($link['common']) { + // $query = "UPDATE {biblio_field_type} SET ftdid = %d, common = %d, visible = %d WHERE fid = %d"; + // db_query($query, array($fid, 1, 1, $fid)); + db_update('biblio_field_type') + ->fields(array('ftdid' => $fid, 'common' => 1, 'visible' => 1)) + ->condition('fid', $fid) + ->execute(); + } + else { // not common, so change pointer back to customizations if available + $query = "UPDATE {biblio_field_type} SET ftdid = cust_tdid, common = :comm WHERE fid = :fid"; + db_query($query, array(':comm' => 0, ':fid' => $fid)); + // db_update('biblio_field_type') + // ->fields(array('ftdid' => $fid, 'common' => 0, 'visible' => 1)) + // ->condition('fid', $fid) + // ->execute(); + } + // set the autocomplete bit on this field for all the types + // $query = "UPDATE {biblio_field_type} SET autocomplete = %d WHERE fid = %d"; + // db_query($query, array($link['autocomplete'], $fid)); + db_update('biblio_field_type') + ->fields(array('autocomplete' => $link['autocomplete'])) + ->condition('fid', $fid) + ->execute(); + } + } + } + drupal_set_message(t("The changes have been saved.")); + + // Clear the cached pages and menus: + //menu_rebuild(); + + // Refresh translatable field strings. + biblio_locale_refresh_fields($tid); +} + +/** + * Outputs a page containing "edit" links for each enabled import/export module. + * + * Each link goes to a page allowing the user to modifiy the field mapping for + * each of the import/export formats. + */ +function biblio_admin_io_mapper_page() { + $formats = module_invoke_all('biblio_mapper_options'); + asort($formats); + + foreach ($formats as $key => $value) { + $rows[] = array( + $value['title'], + l(t('edit'), 'admin/config/content/biblio/iomap/edit/' . $key), + ); + } + + if (count($rows) == 0) { + drupal_set_message(t('There are no import/export modules enabled. Please go to the !l page and enable at least one.', + array('!l' => l(t('modules'), "admin/modules")))); + } + + $header = array(t('Format'), t('Action')); + return theme('table', array('header' => $header, 'rows' => $rows)); +} + +/** + * @param unknown_type $format + * @param unknown_type $exportable + * @return Ambigous Ambigous , multitype:string > + */ +function biblio_admin_io_mapper_form($form, $form_state, $format, $exportable = TRUE) { + $formats = module_invoke_all('biblio_mapper_options'); + $form = array(); + if (isset($formats[$format])) { + $form['title'] = array( + '#prefix' => '

', + '#markup' => check_plain($formats[$format]['title']) . ' ' . t('file format mapping'), + '#suffix' => '

', + ); + $form['fileformat_title'] = array( + '#type' => 'hidden', + '#value' => $formats[$format]['title'], + ); + + } + $form['fileformat'] = array( + '#type' => 'hidden', + '#value' => $format, + ); + $form['fileformat_export'] = array( + '#type' => 'hidden', + '#value' => isset($formats[$format]['export']) ? $formats[$format]['export'] : $exportable, + ); + + $form['typemap'] = array( + '#type' => 'fieldset', + '#title' => t('Publication types'), + '#collapsible' => TRUE, + '#collapsed' => FALSE + ); + $form['typemap']['#theme'] = 'biblio_admin_type_mapper_form'; + $form['typemap']['#tree'] = TRUE; + $form['typemap'] += biblio_admin_type_mapper_form($format); + + $form['fieldmap'] = array( + '#type' => 'fieldset', + '#title' => t('Data fields'), + '#collapsible' => TRUE, + '#collapsed' => FALSE + ); + $form['fieldmap']['#theme'] = 'biblio_admin_field_mapper_form'; + $form['fieldmap']['#tree'] = TRUE; + $form['fieldmap'] += biblio_admin_field_mapper_form($format, $exportable); + + return $form; +} +/** + * @param unknown_type $variables + * @return unknown + */ +function theme_biblio_admin_io_mapper_form($variables) { + $form = $variables['form']; + $header = $rows = array(); + $output = drupal_render($form['title']); + $rows[] = array('data' => array( + array('data' => drupal_render($form['typemap']), 'style' => 'vertical-align:top'), + array('data' => drupal_render($form['fieldmap']), 'style' => 'vertical-align:top'), + ) + ); + $output .= theme('table', array('header' => $header, 'rows' => $rows)); + $output .= drupal_render_children($form); + + return $output; +} + +/** + * @param unknown_type $format + * @param unknown_type $type + * @return multitype:string NULL multitype:string + */ +function biblio_admin_io_mapper_add_form($form, &$form_state, $format, $type) { + $formats = module_invoke_all('biblio_mapper_options'); + + if ($type == 'pubtype') { + $title = 'Publication Type'; + $desc = t('This is the name of the type identifier, exactly as it appears in the file'); + $submit = array('biblio_admin_io_mapper_add_form_pubtype_submit'); + } + if ($type == 'field') { + $title = 'Field name'; + $desc = t('This is the name of the field identifier, exactly as it appears in the file'); + $submit = array('biblio_admin_io_mapper_add_form_field_submit'); + } + $form['fileformat'] = array( + '#type' => 'hidden', + '#value' => $format, + ); + $form['fileformat_title'] = array( + '#type' => 'hidden', + '#value' => $formats[$format]['title'], + ); + $form['type_name'] = array( + '#type' => 'textfield', + '#title' => 'Publication Type', + '#required' => TRUE, + '#description' => t('This is the name of the type identifier, exactly as it appears in the file'), + ); + $form['type_desc'] = array( + '#type' => 'textfield', + '#title' => 'Description' + ); + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Add'), + '#submit' => $submit, + ); + + return $form; +} + +/** + * @param unknown_type $variables + * @return unknown + */ +function theme_biblio_admin_io_mapper_add_form($variables) { + $output = ''; + $form = $variables['form']; + $title = $form['fileformat_title']['#value']; + drupal_set_title(t('Add new publication type to %title file type', array('%title' => $title))); + $output .= drupal_render($form['type_name']); + $output .= drupal_render($form['type_desc']); + $output .= drupal_render($form['submit']); + $output .= drupal_render_children($form); + return $output; +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_io_mapper_add_form_pubtype_submit($form, &$form_state) { + $names = biblio_get_map('type_names', $form_state['values']['fileformat']); + $names[$form_state['values']['type_name']] = $form_state['values']['type_desc']; + biblio_set_map('type_names', $form_state['values']['fileformat'], $names); + $form_state['redirect'] = 'admin/config/content/biblio/iomap/edit/' . $form_state['values']['fileformat']; +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_io_mapper_add_form_field_submit($form, &$form_state) { + $names = biblio_get_map('field_map', $form_state['values']['fileformat']); + $names[$form_state['values']['type_name']] = ''; + biblio_set_map('field_map', $form_state['values']['fileformat'], $names); +} + +/** + * @param unknown_type $format + * @return Ambigous + */ +function biblio_admin_type_mapper_form($format) { + $formats = module_invoke_all('biblio_mapper_options'); + $form['#file_format_title'] = isset($formats[$format]) ? $formats[$format]['title'] : ''; + $form['#file_format'] = $format; + $names = biblio_get_map('type_names', $format); + $map = biblio_get_map('type_map', $format); + ksort($names); + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Save publication type mapping'), + '#submit' => array('biblio_admin_type_mapper_form_submit'), + ); + $form['reset'] = array( + '#type' => 'submit', + '#value' => t('Reset publication type mapping to default'), + '#submit' => array('biblio_admin_type_mapper_form_reset_submit'), + ); + + $result = db_query('SELECT t.* FROM {biblio_types} as t WHERE t.tid > 0'); + + foreach ($result as $type) { + $biblio_type_options[$type->tid] = $type->name; + } + + $biblio_type_options[0] = t('-none-'); + asort($biblio_type_options); + + $biblio_type_select = array( + '#type' => 'select', + '#options' => $biblio_type_options, + ); + foreach ($names as $key => $value) { + $biblio_type_select['#default_value'] = (isset($map[$key]) ? $map[$key] : 0); + $form['type'][$key] = array( + 'format' => array('#markup' => "" . check_plain($key) . " (" . check_plain($value) . ")"), + 'biblio' => $biblio_type_select, + ); + + } + return $form; +} + +/** + * @param unknown_type $variables + * @return unknown + */ +function theme_biblio_admin_type_mapper_form($variables) { + $form = $variables['form']; + $title = $form['#file_format_title']; + + foreach (element_children($form['type']) as $key ) { + $rows[] = array( + drupal_render($form['type'][$key]['format']), + drupal_render($form['type'][$key]) + ); + } + $rows[] = array( + l('[' . t('Add New') . " $title " . t('Publication Type') . ']', 'admin/config/content/biblio/iomap/' . $form['#file_format'] . '/pubtype/add') , + l('[' . t('Add New Biblio Publication Type') . ']', 'admin/config/content/biblio/pubtype/new') + ); + $header = array( + $title . ' ' . t('Publication Types'), + t('Biblio Publication Type') + ); + $output = theme('table', array('header' => $header, 'rows' => $rows)); + + $output .= drupal_render($form['submit']); + $output .= drupal_render($form['reset']); + + $output .= drupal_render_children($form); + return $output; +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_type_mapper_form_submit($form, $form_state) { + foreach ($form_state['values']['typemap']['type'] as $key => $value) { + if (is_array($value)) { + $map[$key]=$value['biblio']; + } + } + biblio_set_map('type_map', $form_state['values']['fileformat'], $map); +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_type_mapper_form_reset_submit($form, $form_state) { + biblio_reset_map('type_map', $form_state['values']['fileformat']); + biblio_reset_map('type_names', $form_state['values']['fileformat']); +} + +/** + * @param unknown_type $format + * @param unknown_type $exportable + * @return Ambigous Ambigous , multitype:string > + */ +function biblio_admin_field_mapper_form($format, $exportable = TRUE) { + $formats = module_invoke_all('biblio_mapper_options'); + $form['#file_format_title'] = isset($formats[$format]) ? $formats[$format]['title'] : ''; + $form['#file_format'] = $format; + $exportable = isset($formats[$format]['export']) ? $formats[$format]['export'] : $exportable; + $form['#file_format_export'] = $exportable; + $map = biblio_get_map('field_map', $format); + $export_map = biblio_get_map('export_map', $format); + ksort($map); + + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Save field mapping'), + '#submit' => array('biblio_admin_field_mapper_form_submit'), + ); + $form['reset'] = array( + '#type' => 'submit', + '#value' => t('Reset field mapping to default'), + '#submit' => array('biblio_admin_field_mapper_form_reset_submit'), + ); + + $schema = drupal_get_schema('biblio'); + $fieldnames = array_keys($schema['fields']); + asort($fieldnames); + $biblio_field_options[''] = t('-none-'); + $biblio_field_options['title'] = 'title'; + foreach ($fieldnames as $field) { + $biblio_field_options[$field] = $field; + } + + $biblio_field_select = array( + '#type' => 'select', + '#options' => $biblio_field_options, + ); + + foreach ($map as $key => $value) { + $biblio_field_select['#default_value'] = $map[$key]; + $form['type'][$key] = array( + 'format' => array('#markup' => "" . $key . ""), + 'biblio' => $biblio_field_select, + '#tree' => 1, + ); + if ($exportable) { + $form['type'][$key]['export'] = array( + '#type' => 'checkbox', + '#default_value' => isset($export_map[$value]) ? $export_map[$value] : '' + ); + } + + } + return $form; +} + +/** + * @param unknown_type $variables + * @return unknown + */ +function theme_biblio_admin_field_mapper_form($variables) { + $form = $variables['form']; + $title = $form['#file_format_title']; + + foreach (element_children($form['type']) as $key ) { + $row = array(); + $row[] = drupal_render($form['type'][$key]['format']); + $row[] = drupal_render($form['type'][$key]['biblio']); + if ($form['#file_format_export']) { + $row[] = drupal_render($form['type'][$key]); + } + $rows[] = $row; + } + $header = array( + $title . ' ' . t('field identifier'), + t('Biblio schema field'), + ); + if ($form['#file_format_export']) { + $header[] = t('Export'); + } + $output = theme('table', array('header' => $header, 'rows' => $rows)); + //$output .= l('[' . t('Add New') . " $title " . t('Publication Type') . ']','admin/config/content/biblio/fields/typemap/' . $form['#file_format'] . '/add') . ' '; + //$output .= l('[' . t('Add New Biblio Publication Type') . ']','admin/config/content/biblio/fields/type/new') . '
'; + $output .= drupal_render_children($form); + + return $output; +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_field_mapper_form_submit($form, $form_state) { + foreach ($form_state['values']['fieldmap']['type'] as $key => $value) { + if (is_array($value)) { + $map[$key] = $value['biblio']; + if ($form_state['values']['fileformat_export']) { + $export_map[$value['biblio']] = $value['export']; + } + } + } + biblio_set_map('field_map', $form_state['values']['fileformat'], $map); + if ($form_state['values']['fileformat_export']) { + biblio_set_map('export_map', $form_state['values']['fileformat'], $export_map); + } + + // elseif ($form_state['values']['op'] == t('Add')) { + // $names = biblio_get_map('type_names', $form_state['values']['fileformat']); + // $names[$form_state['values']['type_name']] = $form_state['values']['type_desc']; + // variable_set('biblio_'.$form_state['values']['fileformat'] .'_type_names', $names); + // } + +} +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_field_mapper_form_reset_submit($form, $form_state) { + biblio_reset_map('field_map', $form_state['values']['fileformat']); + biblio_reset_map('export_map', $form_state['values']['fileformat']); +} + +/** + * @return unknown + */ +function biblio_admin_types_form() { + $output = ''; + $result = db_query('SELECT t.* FROM {biblio_types} as t WHERE t.tid > 0 ORDER BY name ASC'); + //$rows[] = array('',t('Fields Common To All Types'),l('edit', 'admin/config/content/biblio/types/edit'),''); + foreach ($result as $row ) { + if ($row->tid < 999) { + $rows[] = array( + $row->tid, + check_plain($row->name), + ($row->visible) ? l(t('edit'), 'admin/config/content/biblio/fields/' . $row->tid) : '', ($row->visible) ? l(t('hide'), 'admin/config/content/biblio/pubtype/hide/' . $row->tid) : l(t('show'), 'admin/config/content/biblio/pubtype/show/' . $row->tid) + ); + } + else { + $rows[] = array( + $row->tid, + check_plain($row->name), + l(t('edit'), 'admin/config/content/biblio/fields/' . $row->tid), l(t('delete'), 'admin/config/content/biblio/pubtype/delete/' . $row->tid) + ); + } + } + $header = array( + t('Type Id'), + t('Type Name'), array( + 'data' => t('Operations'), + 'colspan' => '2' + ) + ); + $output .= theme('table', array('header' => $header, 'rows' => $rows)); + $output .= l(t('Reset to defaults'), 'admin/config/content/biblio/pubtype/reset'); + return $output; +} +/** + * @param unknown_type $form + * @param unknown_type $form_state + * @return multitype:string number NULL + */ +function biblio_admin_types_add_form($form, &$form_state) { + $form['name'] = array( + '#type' => 'textfield', + '#title' => t('Type Name'), + '#size' => 20, + '#weight' => 1, + '#required' => TRUE, + '#maxlength' => 64 + ); + $form['description'] = array( + '#type' => 'textfield', + '#title' => t('Description'), + '#size' => 60, + '#weight' => 2, + '#maxlength' => 255 + ); + $form['type_button'] = array( + '#type' => 'submit', + '#value' => t('Create New Type'), + '#weight' => 3 + ); + + + return $form; +} +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_types_add_form_submit($form, &$form_state) { + $values['name'] = $form_state['values']['name']; + $values['description'] = $form_state['values']['description']; + $values['tid'] = variable_get('biblio_max_user_tid', '999') + 1; + + db_insert('biblio_types') + ->fields($values) + ->execute(); + + variable_set('biblio_max_user_tid', $values['tid']); + $result = db_query('SELECT * FROM {biblio_field_type} WHERE tid=0', array(), array('fetch' => PDO::FETCH_ASSOC)); + foreach ($result as $row) { + $row['tid'] = $values['tid']; + $row['visible'] = 1; + db_insert('biblio_field_type') + ->fields($row) + ->execute(); + } + // Fill contributor types. Use the first 4 defaults. + for ($type = 1; $type <= 4; $type++) { + $ct_vals = array( + 'auth_category' => $type, + 'biblio_type' => $values['tid'], + 'auth_type' => $type, + ); + + db_insert('biblio_contributor_type') + ->fields($ct_vals) + ->execute(); + } + + // Refresh publication type string for translation. + biblio_locale_refresh_types($values['tid']); + $form_state['redirect'] = 'admin/config/content/biblio/pubtype'; + +} + +function biblio_admin_types_reset() { + module_load_include('install', 'biblio'); + + db_delete('biblio_types') + ->execute(); + _add_publication_types(); + drupal_goto('admin/config/content/biblio/pubtype'); +} +/** + * + */ +function biblio_admin_types_hide() { + $args = func_get_args(); + if ($args[0] > 0 && is_numeric($args[0])) { + db_update('biblio_types') + ->fields(array( + 'visible' => 0)) + ->condition('tid', $args[0]) + ->execute(); + } + drupal_goto('admin/config/content/biblio/pubtype'); +} +/** + * + */ +function biblio_admin_types_show() { + $args = func_get_args(); + if ($args[0] > 0 && is_numeric($args[0])) { + db_update('biblio_types') + ->fields(array( + 'visible' => 1)) + ->condition('tid', $args[0]) + ->execute(); + } + drupal_goto('admin/config/content/biblio/pubtype'); +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + * @param unknown_type $tid + * @return unknown + */ +function biblio_admin_types_delete_form($form, &$form_state, $tid) { + $existing_msg = ''; + if (isset($tid) && is_numeric($tid)) { + $row = db_query('SELECT t.* FROM {biblio_types} as t WHERE t.tid = :tid ', array(':tid'=> $tid))->fetchObject(); + $num_rows = db_query('SELECT COUNT(*) FROM {biblio} as b WHERE b.biblio_type = :btype', array(':btype' => $row->tid))->fetchField(); + if ($num_rows) { + $existing_msg = t('There are @count biblio entries of this type, you should change the type of these entries before proceeding otherwise they will be deleted', array( + '@count' => $num_rows + )); + } + $form['tid'] = array( + '#type' => 'value', + '#value' => $row->tid + ); + $output = confirm_form($form, t('Are you sure you want to delete the custom biblio type: %title ?', array( + '%title' => $row->name + )) . $existing_msg, isset($_GET['destination']) ? $_GET['destination'] : 'admin/config/content/biblio/pubtype', t('This action cannot be undone.'), t('Delete'), t('Cancel')); + return $output; + } + else { + drupal_goto('admin/config/content/biblio/pubtype'); + } +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_types_delete_form_submit($form, &$form_state) { + $query = db_select('biblio_field_type', 'bft'); + $result = $query->fields('bft', array('ftdid')) + ->condition('tid', $form_state['values']['tid']) + ->condition('ftdid', 100, '>') + ->execute(); + foreach ($result as $field) { + $ftdids[] = $field->ftdid; + } + + db_delete('biblio_field_type_data') + ->condition('ftdid', $ftdids, 'IN') + ->execute(); + + db_delete('biblio_types') + ->condition('tid', $form_state['values']['tid']) + ->execute(); + + db_delete('biblio_field_type') + ->condition('tid', $form_state['values']['tid']) + ->execute(); + + $form_state['redirect'] = 'admin/config/content/biblio/pubtype'; +} + +/** + * @return unknown + */ +function biblio_admin_types_reset_form() { + $form['reset'] = array( + '#type' => 'value', + '#value' => 'reset' + ); + $output = confirm_form($form, t('Are you sure you want to reset ALL the field definitions to the defaults?'), isset($_GET['destination']) ? $_GET['destination'] : 'admin/config/content/biblio/fields', t('By doing this, you will loose all customizations you have made to the field titles, this action cannot be undone!'), t('Reset!'), t('Cancel')); + return $output; +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_types_reset_form_submit($form, & $form_state) { + module_load_include('install', 'biblio'); + biblio_reset_types(); + $form_state['redirect'] = 'admin/config/content/biblio/fields'; +} +/* + * This functin is used by both the admin/config/content/biblio page and user profile page + * - if $user is set, then it is being called from the user profile page + */ +function _biblio_get_user_profile_form($profile_user = FALSE) { + $form = array(); + $allow_edit = variable_get('biblio_show_user_profile_form', '1'); + $allow_edit = $allow_edit || user_access('administer biblio'); + + if (!$profile_user) { + $form['biblio_show_user_profile_form'] = array( + '#type' => 'checkbox', + '#title' => t('Allow users to override these settings on their "My account" page') , + '#return_value' => 1, + '#description' => t('If this is selected, a form similar to this section will be available to the user when they edit their own account information. This will allow them to override the global preferences set here.') , + '#default_value' => variable_get('biblio_show_user_profile_form', '1') + ); + } + $form['biblio_show_profile'] = array( + '#type' => 'checkbox', + '#title' => ($profile_user) ? t('Show my publications on my profile page') : t('Show publications on users profile pages'), + '#return_value' => 1, + '#disabled' => !$allow_edit, + '#description' => ($profile_user) ? t('Selecting this will create a listing of your publications on your profile page') : t('This sets the site wide default, users may change this in their profile') + ); + if ($profile_user) { + $form['biblio_show_profile']['#default_value'] = (isset($profile_user->data['biblio_show_profile'])) ? $profile_user->data['biblio_show_profile'] : variable_get('biblio_show_profile', '0'); + } + else { + $form['biblio_show_profile']['#default_value'] = variable_get('biblio_show_profile', '0'); + } + $form['#biblio_show_profile'] = $form['biblio_show_profile']['#default_value']; + $form['biblio_my_pubs_menu'] = array( + '#type' => 'checkbox', + '#title' => t('Show "My publications" item in the navigation menu'), + '#disabled' => !$allow_edit, + '#return_value' => 1, + '#description' => '' + ); + if ($profile_user) { + $form['biblio_my_pubs_menu']['#default_value'] = ((isset($profile_user->data['biblio_my_pubs_menu'])) ? $profile_user->data['biblio_my_pubs_menu'] : variable_get('biblio_my_pubs_menu', '0')); + } + else { + $form['biblio_my_pubs_menu']['#default_value'] = variable_get('biblio_my_pubs_menu', '0'); + } + $form['#biblio_my_pubs_menu'] = $form['biblio_my_pubs_menu']['#default_value']; + + if ($profile_user) { + $form += _biblio_drupal_author_user_map($profile_user, $allow_edit); + } + + $options = array(); + $options['system'] = t('System default'); + $options = array_merge($options, biblio_get_styles() ); + $form['biblio_user_style'] = array( + '#type' => 'select', + '#title' => t('Style'), + '#default_value' => (isset($profile_user->data['biblio_user_style']) ? $profile_user->data['biblio_user_style'] : 'system'), + '#options' => $options, + '#description' => t('Set the bibliographic style of the "list" view.') + ); + + return $form; +} + +function _biblio_drupal_author_user_map($profile_user, $allow_edit = TRUE) { + global $user; + + $db_result = db_query("SELECT cd.lastname, cd.firstname, cd.initials, cd.cid FROM {biblio_contributor_data} cd + ORDER by cd.lastname ASC "); + $options = array(); + $options[0] = t('(None)'); + + foreach ($db_result as $row) { + $options[$row->cid] = "$row->lastname, $row->firstname $row->initials "; + } + if (isset($profile_user->data['biblio_id_change_count']) && $profile_user->data['biblio_id_change_count'] > 2) { + $allow_edit = 0; + $msg = t('This control has been disabled because the author mapping has been changed more than 3 times, please see your system administrator to have it reset.'); + } + else { + $msg = t('This will link your profile to the selected author from the biblio database, then all publications containing this author to be displayed on your "Publications" tab.'); + } + $form['biblio_contributor_id'] = array( + '#type' => 'select', + '#title' => t('Link My Profile with this Author from the Biblio database:'), + '#default_value' => isset($profile_user->data['biblio_contributor_id']) ? $profile_user->data['biblio_contributor_id'] : 0, + '#disabled' => ($user->uid == 1 || user_access('administer biblio')) ? FALSE : !$allow_edit, + '#options' => $options, + '#description' => $msg, + ); + $form['biblio_id_change_count'] = array( + '#type' => 'textfield', + '#size' => 2, + '#title' => t('Drupal UserID to Biblio AuthorID mapping change count:'), + '#default_value' => isset($profile_user->data['biblio_id_change_count']) ? $profile_user->data['biblio_id_change_count'] : 0, + '#disabled' => ($user->uid == 1 || user_access('administer biblio')) ? FALSE : TRUE, + '#description' => 'When this value is >= 3, you will no longer be able to change your author id mapping. Contact your system administrator to reset this value.', + ); + + return $form; +} +/** + * @param unknown_type $user + * @return multitype:string number NULL + */ +function _biblio_get_user_doi_form($user) { + $form['biblio_doi'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => t('CrossRef Login Information') + ); + $link_attrs = array('attributes' => array('target' => '_blank'), + 'absolue' => TRUE); + $form['biblio_doi']['biblio_crossref_pid'] = array( + '#type' => 'textfield', + '#title' => t('CrossRef OpenURL Account ID'), + '#default_value' => isset($user->data['biblio_crossref_pid']) ? $user->data['biblio_crossref_pid'] : '', + '#return_value' => 1, + '#description' => t('Enter your complimentary CrossRef OpenURL account ID which you can obtain here !url, OR enter your full CrossRef (colon separated) account:password combination.', array('!url' => l(t('OpenURL Account Request Form'), 'http://www.crossref.org/requestaccount/', $link_attrs))) + ); + return $form; +} +/** + * @param unknown_type $user + * @return multitype:string number NULL + */ +function _biblio_get_user_openurl_form($user) { + $form['openurl'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => t('OpenURL'), + '#description' => t('You can set an openurl link here') + ); + $form['openurl']['biblio_baseopenurl'] = array( + '#type' => 'textfield', + '#title' => t('OpenURL Base URL'), + '#size' => 95, + '#default_value' => !empty($user->data['biblio_baseopenurl']) ? $user->data['biblio_baseopenurl'] : '', + '#description' => t('This sets your base OpenURL gateway, which is used to generate OpenURL links. To implement a "Universal" OpenURL system, try using OCLC\'s OpenURL Resolver Registry gateway: http://worldcatlibraries.org/registry/gateway') + ); + $sid = "Biblio:" . variable_get('site_name', 'Drupal'); + $form['openurl']['biblio_openurl_sid'] = array( + '#type' => 'textfield', + '#title' => t('OpenURL Site ID'), + '#size' => 95, + '#default_value' => !empty($user->data['biblio_openurl_sid']) ? $user->data['biblio_openurl_sid'] : '', + '#description' => t('This sets your site name, some link resolvers will require a specific Site ID in order to process your requests.') + ); + return $form; +} +/* This function parses the module directory for 'style' files, loads them and + * calls the info fuction to get some basic information like the short and long + * names of the style +*/ +function biblio_form_sort($a, $b) { + $a_weight = (is_array($a) && isset($a['weight'])) ? $a['weight'] : 0; + $b_weight = (is_array($b) && isset($b['weight'])) ? $b['weight'] : 0; + if ($a_weight == $b_weight) { + return 0; + } + return ($a_weight < $b_weight) ? -1 : 1; +} +/** + * @param unknown_type $name + * @return string + */ +function biblio_admin_get_query($name) { + switch ($name) { + case "author_dup" : + return ('SELECT lastname, firstname, initials, COUNT(lastname) as cnt FROM {biblio_contributor_data} GROUP BY lastname, firstname, initials HAVING COUNT(*)>1 ORDER BY lastname ASC, firstname ASC, initials ASC '); + break; + case "author_by_name" : + return ("SELECT lastname, cid FROM {biblio_contributor_data} where lastname LIKE '%s'"); + break; + case 'author_pub_count' : +// return ('SELECT bd.lastname, b.cid,COUNT(*) AS cnt FROM {biblio_contributor} b, {biblio_contributor_data} bd WHERE bd.cid=b.cid GROUP BY b.cid HAVING cnt > 0 ORDER BY lastname ASC'); + return ('SELECT bd.lastname, b.cid,COUNT(*) AS cnt FROM {biblio_contributor} b, {biblio_contributor_data} bd WHERE bd.cid=b.cid GROUP BY b.cid, bd.lastname HAVING COUNT(*) > 0 ORDER BY lastname ASC'); + break; + } +} + + +/** + * @param unknown_type $form + * @param unknown_type $form_state + * @param unknown_type $op + * @param unknown_type $id + * @return void|multitype:string multitype:string number NULL multitype:string number multitype:string NULL multitype:string number boolean NULL NULL + */ +function biblio_admin_author_types_form($form, &$form_state, $op = NULL, $id = NULL) { + + switch ($op) { + case 'edit': + $type = db_query("SELECT * FROM {biblio_contributor_type_data} WHERE auth_type=:atype", array(':atype' => $id))->fetchObject(); + $form['auth_type'] = array( + '#type' => 'hidden', + '#value' => $type->auth_type); + //fall through and use the same form used for a new entry + case 'new': + $form['title'] = array( + '#type' => 'textfield', + '#title' => t('Type Name'), + '#size' => 20, + '#weight' => 1, + '#default_value' => ($op == 'new' ? '' : $type->title), + '#required' => TRUE, + '#maxlength' => 64 + ); + $form['hint'] = array( + '#type' => 'textfield', + '#title' => t('Description'), + '#size' => 60, + '#weight' => 2, + '#default_value' => ($op == 'new' ? '' : $type->hint), + '#maxlength' => 255 + ); + $form['type_button'] = array( + '#type' => 'submit', + '#value' => ($op == 'new')? t('Create New Type') : t('Save'), + '#weight' => 3, + '#submit' => array('biblio_admin_author_types_form_submit') + ); + $form['cancel_button'] = array( + '#type' => 'submit', + '#value' => t('Cancel'), + '#weight' => 4, + ); + $form['#theme'] = ''; + return $form; + break; + case 'hide': + break; + default: + return; + } +} + +/** + * @param unknown_type $variables + * @return string + */ +function theme_biblio_admin_author_types_form($variables) { + $form = $variables['form']; + // We need this complex query to realize author_types which are not in use (cid is NULL) + $query = db_select('biblio_contributor_type_data', 'ctd'); + $query->fields('ctd', array('auth_type', 'title', 'hint')) + ->leftJoin('biblio_contributor', 'bc', 'ctd.auth_type = bc.auth_type'); + $db_result = $query->groupBy('ctd.auth_type') + ->groupBy('ctd.title') + ->groupBy('ctd.hint') + ->orderBy('ctd.auth_type') + ->execute(); + + foreach ($db_result as $row) { + $ops = l(t('edit'), 'admin/config/content/biblio/author/type/' . $row->auth_type . '/edit' ); + if (!isset($row->cid) && $row->auth_type >= 10) { // allow delete only if type not in use + $ops .= '  '; + $ops .= l(t('delete'), 'admin/config/content/biblio/author/type/' . $row->auth_type . '/delete/'); + } + $rows[] = array( + $row->auth_type, + check_plain($row->title), + check_plain($row->hint), + $ops, + ); + } + $header = array( + t('Type Id'), + t('Contributor Type'), + t('Description'), + array('data' => t('Operations'), 'colspan' => '2') + ); + $output = '

[ ' . l(t('Add New Type'), 'admin/config/content/biblio/author/type/new') . ' ]'; + $output .= theme('table', array('header' => $header, 'rows' => $rows)); + $output .= '

[ ' . l(t('Add New Type'), 'admin/config/content/biblio/author/type/new') . ' ]'; + // $output .= ' [ ' . l(t('Reset all types to defaults'), 'admin/config/content/biblio/authors/reset') . ' ]'; + + return $output; +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_author_types_form_submit($form, &$form_state) { + + if ($form_state['triggering_element']['#value'] == t('Save') || $form_state['triggering_element']['#value'] == t('Create New Type')) { + $record->title = $form_state['values']['title']; + $record->hint = $form_state['values']['hint']; + switch ($form['#id']) { + case 'biblio-admin-author-types-form-new': + $record->title = $form_state['values']['title']; + $record->hint = $form_state['values']['hint']; + drupal_write_record('biblio_contributor_type_data', $record); + break; + case 'biblio-admin-author-types-form-edit': + $record->auth_type = $form_state['values']['auth_type']; + drupal_write_record('biblio_contributor_type_data', $record, 'auth_type'); + break; + } + } + $form_state['redirect'] = 'admin/config/content/biblio/author/type'; + +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + * @param unknown_type $type_id + */ +function biblio_admin_author_type_delete_confirm($form, &$form_state, $type_id) { + $base = variable_get('biblio_base', 'biblio'); + $type_data = db_query('SELECT * FROM {biblio_contributor_type_data} bctd WHERE bctd.auth_type = :tid ', array(':tid' => $type_id))->fetchObject(); + $form['auth_type'] = array( + '#type' => 'value', + '#value' => $type_data->auth_type, + ); + + return confirm_form($form, + t('Are you sure you want to delete the author type: %title ?', array('%title' => $type_data->title)), + isset($_GET['destination']) ? $_GET['destination'] : 'admin/config/content/biblio/author/type', + t('This action cannot be undone.'), + t('Delete'), + t('Cancel') + ); + +} +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_author_type_delete_confirm_submit($form, &$form_state) { + + db_delete('biblio_contributor_type_data') + ->condition('auth_type', $form_state['values']['auth_type']) + ->execute(); + + db_delete('biblio_contributor_type') + ->condition('auth_type', $form_state['values']['auth_type']) + ->execute(); + + $form_state['redirect'] = 'admin/config/content/biblio/author/type'; +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + * @param unknown_type $author_id + * @return void|multitype:string NULL + */ +function biblio_admin_author_edit_form($form, &$form_state, $author_id) { + module_load_include('inc', 'biblio', 'includes/biblio.contributors'); + $merge_options = $linked = array(); + if (!isset($form_state['biblio_add_merge_author'])) { + $form_state['biblio_add_merge_author'] = array(); + } + $base = variable_get('biblio_base', 'biblio'); + + $author = db_query('SELECT * FROM {biblio_contributor_data} b WHERE b.cid = :aid ', array(':aid' => $author_id))->fetchObject(); + if (!$author) { + drupal_not_found(); + return; + } + $base = variable_get('biblio_base', 'biblio'); + $menu = menu_get_active_title(); + $path = (strpos($_GET['q'], 'config'))? 'admin/config/content/biblio/author/' : $base . '/authors/'; + + // $form['#tree'] = TRUE; + $form['cid'] = array( + '#type' => 'value', + '#value' => $author_id, + ); + $users = db_query('SELECT uid,name FROM {users} WHERE uid>0 ORDER BY name'); + $options[0] = t('(None)'); + foreach ($users as $user) { + $options[$user->uid] = $user->name; + } + $form['drupal_uid'] = array( + '#type' => 'select', + '#title' => t('Drupal User ID'), + '#options' => $options, + '#default_value' => $author->drupal_uid, + '#weight' => 12, + '#required' => FALSE, + '#description' => t('If this author has a an account (Drupal User ID) on this web site, you may select it here. This will help to link the authors publications with other content.') + ); + $form['name'] = array( + '#type' => 'textfield', + '#title' => t('Complete Name'), + '#default_value' => $author->name, + '#size' => 100, + '#weight' => 1, + '#required' => TRUE, + '#disabled' => TRUE, + '#maxlength' => 255, + '#description' => t('The value in this box will be constructed from the individual name parts fields above.') + ); + $form_state['current_name'] = $author->name; + + $form['literal'] = array( + '#type' => 'checkbox', + '#title' => t('Do not reformat'), + '#default_value' => $author->literal, + '#weight' => 1.5, + '#required' => FALSE, + '#description' => t('Selecting this will prevent the styles from trying to reformat the contributor name. The text in the "Complete Name" field will be used as is.') + ); + $form['prefix'] = array( + '#type' => 'textfield', + '#title' => t('Prefix'), + '#default_value' => $author->prefix, + '#size' => 20, + '#weight' => 2, + '#required' => FALSE, + '#maxlength' => 128 + ); + $form['firstname'] = array( + '#type' => 'textfield', + '#title' => t('First Name'), + '#default_value' => $author->firstname, + '#size' => 20, + '#weight' => 3, + '#required' => FALSE, + '#maxlength' => 128 + ); + $form['initials'] = array( + '#type' => 'textfield', + '#title' => t('Initials'), + '#default_value' => $author->initials, + '#size' => 20, + '#weight' => 4, + '#required' => FALSE, + '#maxlength' => 10 + ); + $form['lastname'] = array( + '#type' => 'textfield', + '#title' => t('Last Name'), + '#default_value' => $author->lastname, + '#size' => 20, + '#weight' => 5, + '#required' => FALSE, + '#maxlength' => 255 + ); + $form['suffix'] = array( + '#type' => 'textfield', + '#title' => t('Suffix'), + '#default_value' => $author->suffix, + '#size' => 20, + '#weight' => 6, + '#required' => FALSE, + '#maxlength' => 128 + ); + $form['affiliation'] = array( + '#type' => 'textfield', + '#title' => t('Affiliation'), + '#default_value' => $author->affiliation, + '#size' => 100, + '#weight' => 7, + '#required' => FALSE, + '#maxlength' => 256, + '#description' => t('University, Company or Organization that the author is affiliated with.') + ); + + $query = db_select('biblio_contributor_data', 'bcd'); + $authors = $query->fields('bcd') + ->condition('cid', $author_id, '<>') + ->orderBy('lastname') + ->execute(); + + $query = db_select('biblio_contributor', 'bc'); + $merged_authors = $query->fields('bc') + ->condition('merge_cid', 0, '>') + ->execute(); + foreach ($merged_authors as $auth) { + $merged[$auth->merge_cid] = $auth->cid; + } + + $linked = biblio_get_linked_contributors($author->cid); + + $radio_options = array('link' => '', 'merge' => ''); + $candidate = FALSE; + $candidates = array(); + + $this_soundx = soundex($author->lastname); + + foreach ($authors as $other_author) { + $merge_def = $link_def = 0; + $link_disable = $merge_disable = $retain_disable = FALSE; + + if ((soundex($other_author->lastname) == $this_soundx) || + (isset($merged[$other_author->cid]) && $merged[$other_author->cid] == $author->cid) || + in_array($other_author->cid, $form_state['biblio_add_merge_author'])) { + $candidate = TRUE; + $merge_def = ($other_author->alt_form && $other_author->aka) ? $author->cid : FALSE; + $retain_def = $other_author->alt_form ? $author->cid : FALSE; + $retain_disable = $other_author->alt_form ? TRUE : FALSE; + } + + if (in_array($other_author->cid, $linked)) { + $candidate = TRUE; + $link_def = $author->cid; + $retain_def = 0; + } + + if ($candidate) { + $candidate = FALSE; + $form_state['biblio_add_merge_author'][$other_author->cid] = $other_author->cid; + + $candidates[$other_author->cid]['name'] = array( + '#markup' => l($other_author->lastname . ($other_author->firstname ? ', ' . $other_author->firstname : ($other_author->initials?', ' . $other_author->initials:'')), $path . $other_author->cid . '/edit/'), + '#markup' => l($other_author->name , $path . $other_author->cid . '/edit/'), + ); + $candidates[$other_author->cid]['link'] = array( + '#type' => 'checkbox', + '#return_value' => $author->cid, + '#default_value' => $link_def, + '#disabled' => $link_disable, + '#parents' => array('candidates', $other_author->cid, 'link'), + '#states' => array( + 'disabled' => array( + ':input[name="candidates[' . $other_author->cid . '][merge]"]' => array('checked' => true), + ), + ), + ); + $candidates[$other_author->cid]['merge'] = array( + '#type' => 'checkbox', + '#return_value' => $author->cid, + '#default_value' => $merge_def, + '#disabled' => $merge_disable, + '#parents' => array('candidates', $other_author->cid, 'merge'), + '#states' => array( + 'disabled' => array( + ':input[name="candidates[' . $other_author->cid . '][link]"]' => array('checked' => true), + ), + ), + ); + $candidates[$other_author->cid]['retain'] = array( + '#type' => 'checkbox', + '#return_value' => $author->cid, + '#default_value' => $retain_def, + '#disabled' => $retain_disable, + '#parents' => array('candidates', $other_author->cid, 'retain'), + '#states' => array( + 'enabled' => array( + ':input[name="candidates[' . $other_author->cid . '][merge]"]' => array('checked' => true), + ), + 'unchecked' => array( + ':input[name="candidates[' . $other_author->cid . '][merge]"]' => array('unchecked' => true), + ), + ), + ); + } + } + + $form['merge'] = array( + '#type' => 'fieldset', + '#theme' => 'biblio_admin_author_edit_merge_table', + '#title' => t('Author Link / Merge'), + '#description' => t('Select other author names which will be linked or merged. Merging removes all the selected authors, then replaces any references to these authors with the author being edited above. You should only do this if you are sure the other authors represent the same author as the one being edited. IF you do not select "Retain as alternate form" then THIS CANNOT BE UNDONE!'), + '#weight' => 5, + '#collapsible' => TRUE, + '#collapsed' => !count($candidates), + '#header' => array(t('Author name'), t('Link'), t('Merge'), t('Retain as "alternate form"')), + 'candidates' => $candidates, + '#prefix' => '

', + '#suffix' => '
', + + ); + $form['merge']['more_authors_search'] = array( + '#type' => 'textfield', + '#title' => t('Other authors which could be linked to this author'), + '#autocomplete_path' => 'biblio/autocomplete/contributor', + '#weight' => 12, + '#required' => FALSE, + ); + $form['merge']['more_authors_add'] = array( + '#type' => 'submit', + '#value' => t('Add author'), + '#weight' => 15, + '#submit' => array('biblio_admin_author_edit_add_candidate'), + '#ajax' => array( + 'callback' => 'biblio_admin_author_edit_add_candidate_callback', + 'wrapper' => 'biblio-author-edit-merge-table', + ), + + ); + + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Save') + ); + $form['cancel'] = array( + '#type' => 'submit', + '#value' => t('Cancel') + ); + + return $form; +} + +function biblio_admin_author_edit_add_candidate($form, &$form_state) { + module_load_include('inc', 'biblio', 'includes/biblio.contributors'); + if (!empty($form_state['values']['more_authors_search'])) { + if ($cid = biblio_get_cid_by_name($form_state['values']['more_authors_search'])) { + if ($cid == $form_state['values']['cid']) { // we don't want to merge with ourselves :-( + drupal_set_message(t('You cannot merge an author with itself'), 'error'); + } + elseif (in_array($cid, $form_state['biblio_add_merge_author'])) { + drupal_set_message(t('Author already exists in the merge list'), 'warning'); + } + else { + $form_state['biblio_add_merge_author'][$cid] = $cid; + } + } + else { + drupal_set_message(t('The Author was not found in the database. You must select an Author from the "auto-complete" list of the Keyword search box.'), 'error'); + } + } + else { + drupal_set_message(t('Cannot add an empty value'), 'error'); + } + + $form_state['rebuild'] = TRUE; + +} + +function biblio_admin_author_edit_add_candidate_callback($form, $form_state) { + return $form['merge']; +} + +/** + * @param array $form + * @param array $form_state + */ +function biblio_admin_author_edit_form_merge_validate($form, &$form_state) { +} + +/** + * @param array $form + * @param array $form_state + */ +function biblio_admin_author_edit_form_merge_link($form_state) { + $op = $form_state['triggering_element']['#value']; + $merge_authors = array(); + $cid = $form_state['values']['cid']; + + foreach ($form_state['values']['candidates'] as $ccid => $options) { + + if ($options['link']) { + db_update('biblio_contributor_data') + ->fields(array( + 'aka' => $options['link'], + 'alt_form' => 0, + )) + ->condition('cid', $ccid) + ->execute(); + } + else { + db_update('biblio_contributor_data') + ->fields(array( + 'aka' => 0, + 'alt_form' => 0, + )) + ->condition(db_or()->condition('cid', $cid)->condition('cid', $ccid)) + ->execute(); + } + + if ($options['merge']) { + db_update('biblio_contributor') + ->fields(array( + 'cid' => $cid, + 'merge_cid' => $ccid)) + ->condition('cid', $ccid) + ->execute(); + } + else { + db_update('biblio_contributor') + ->fields(array( + 'cid' => $ccid, + 'merge_cid' => 0)) + ->condition('merge_cid', $ccid) + ->execute(); + } + + if ($options['merge'] && $options['retain']) { + db_update('biblio_contributor_data') + ->fields(array( + 'alt_form' => $options['retain'] ? $options['retain'] : 0, + 'aka' => $options['retain'] ? $cid : 0)) + ->condition('cid', $ccid) + ->execute(); + } + elseif ($options['merge'] && !$options['retain']) { + db_delete('biblio_contributor_data') + ->condition('cid', $ccid) + ->execute(); + } + } +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_author_edit_form_link_validate($form, &$form_state) { + +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_author_edit_form_link_submit($form, &$form_state) { + module_load_include('inc', 'biblio', 'includes/biblio.contributors'); + $linked_authors = array(); + $link_authors = ''; + + if (isset($form_state['values']['linked_authors']) ) { + $linked_authors = $form_state['values']['linked_authors']; + } + + if (isset($form_state['values']['link_authors']) ) { + $link_authors = $form_state['values']['link_authors']; + } + + foreach ($linked_authors as $key => $value) { + if ($value == 0) { + db_update('biblio_contributor_data') + ->fields(array('aka' => $value)) + ->condition('cid', $key) + ->execute(); + } + } + + if (!empty($link_authors)) { + if ( ($cid = biblio_get_cid_by_name($link_authors))) { + db_update('biblio_contributor_data') + ->fields(array('aka' => $form_state['values']['cid'])) + ->condition('cid', $cid) + ->execute(); + } + } + +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_author_edit_form_validate($form, &$form_state) { + foreach ($form_state['values'] as $key => $value) { + if (is_string($value)) $form_state['values'][$key] = trim($value); + } +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_author_edit_form_submit($form, &$form_state) { + $op = $form_state['values']['op']; + switch ($op) { + case t('Save'): + if ($form_state['values']['drupal_uid'] == 0 ) { + $uid = $form['drupal_uid']['#default_value']; + $cid = 0; + } + else { + $uid = $form_state['values']['drupal_uid']; + $cid = $form_state['values']['cid'] ; + } + if ($uid) { + db_update('biblio_contributor_data') + ->fields(array('drupal_uid' => 0)) + ->condition('drupal_uid', $uid) + ->execute(); + $result = db_query('SELECT data FROM {users} WHERE uid = :uid', array(':uid' => $uid))->fetchField(); + $data = unserialize($result); + $data['biblio_contributor_id'] = $cid; + $v = serialize($data); + db_update('users') + ->fields(array('data' => $v)) + ->condition('uid', $uid) + ->execute(); + } + + $form_state['values']['name'] = + (!empty($form_state['values']['prefix']) ? $form_state['values']['prefix'] . ' ' :'') . + (!empty($form_state['values']['firstname']) ? $form_state['values']['firstname'] . ' ' :'') . + (!empty($form_state['values']['initials']) ? $form_state['values']['initials'] . ' ' :'') . + (!empty($form_state['values']['lastname']) ? $form_state['values']['lastname'] . ' ' :'') . + (!empty($form_state['values']['suffix']) ? $form_state['values']['suffix'] :'') ; + $form_state['values']['name'] = trim($form_state['values']['name']); + $form_state['values']['md5'] = md5($form_state['values']['name']); + + drupal_write_record('biblio_contributor_data', $form_state['values'], 'cid'); + + if (isset($form_state['values']['candidates']) && !empty($form_state['values']['candidates'])) { + biblio_admin_author_edit_form_merge_link($form_state); + } + break; + case t('Cancel'): + break; + } +} + + +/** + * + * @param $form + * @param $form_state + * @return array + */ +function biblio_admin_orphans_form($form, &$form_state) { + module_load_include('inc', 'biblio', 'includes/biblio.contributors'); + $orphans = $options = $names = array(); + + $base = variable_get('biblio_base', 'biblio'); + + $orphans = biblio_get_orphan_authors(); + + foreach ($orphans as $author) { + $options[$author->cid] = array( + 'author' => array( + 'data' => array( + '#type' => 'link', + '#title' => $author->name, + '#href' => $base . '/authors/' . $author->cid . '/edit', + ), + ), + 'affiliation' => check_plain($author->affiliation), + ); + $names[$author->cid] = $author->name; + } + $form['names'] = array('#type' => 'hidden', '#value' => $names); + + $header = array( + 'author' => t('Author name'), + 'affiliation' => t('Author affiliation') + ); + + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Delete Selected'), + '#disabled' => (!count($options)), + '#submit' => array('biblio_admin_orphans_form_submit'), + ); + $form['delete_all'] = array( + '#type' => 'submit', + '#value' => t('Delete ALL'), + '#disabled' => (!count($options)), + '#submit' => array('biblio_admin_orphans_form_submit'), + ); + $form['authors'] = array( + '#type' => 'tableselect', + '#header' => $header, + '#options' => $options, + '#empty' => t('No orphaned authors.'), + ); + + return $form; +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_orphans_form_validate($form, &$form_state) { + $check_count = array_filter($form_state['values']['authors']); + if ($form_state['triggering_element']['#value'] == t('Delete Selected') && count($check_count) == 0) { + form_set_error('', t('No items selected.')); + } +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_orphans_form_submit($form, &$form_state) { + $authors = $names = array(); + // Filter out unchecked authors + if ($form_state['triggering_element']['#value'] == t('Delete Selected')) { + $authors = array_filter($form_state['values']['authors']); + } + elseif ($form_state['triggering_element']['#value'] == t('Delete ALL')) { + $authors = drupal_map_assoc(array_keys($form_state['values']['authors'])); + } + + $names = array_intersect_key($form_state['values']['names'], $authors); + $del_names = implode('; ', $names); + + db_delete('biblio_contributor_data') + ->condition('cid', $authors, 'IN') + ->execute(); + + drupal_set_message(t('The orphaned authors (@author_list) have been deleted.', array('@author_list' => $del_names))); + +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + * @return multitype:NULL + */ +function biblio_admin_keyword_orphans_form($form, $form_state) { + $orphans = $keywords = $options = array(); + + $base = variable_get('biblio_base', 'biblio'); + + $header = array( + 'keyword' => t('Keyword') + ); + + $query = db_select('biblio_keyword', 'bk'); + $active_kids = $query + ->fields('bk', array('kid')) + ->groupBy('kid') + ->execute() + ->fetchCol(); + + $query = db_select('biblio_keyword_data', 'bkd'); + $all_kids = $query + ->fields('bkd', array('kid')) + ->groupBy('kid') + ->execute() + ->fetchCol(); + + $orphans = array_diff($all_kids, $active_kids); + + if (count($orphans)) { + $query = db_select('biblio_keyword_data', 'bkd')->extend('PagerDefault')->limit(50); + $query->fields('bkd'); // SELECT * FROM {biblio_contributor_data} + $query->condition('kid', $orphans, 'IN'); + $result = $query->execute(); //pager_query('SELECT * FROM {biblio_keyword_data} WHERE kid NOT IN (SELECT kid FROM {biblio_keyword} GROUP BY kid)', 50); + foreach ($result as $keyword) { + $options[$keyword->kid] = array( + 'keyword' => array( + 'data' => array( + '#type' => 'link', + '#title' => $keyword->word, + '#href' => $base . '/keywords/' . $keyword->kid . '/edit', + ), + ), + ); + } + } + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Delete'), + '#disabled' => (!count($options)), + '#submit' => array('biblio_admin_keyword_orphans_form_submit'), + ); + $form['words'] = array( + '#type' => 'tableselect', + '#header' => $header, + '#options' => $options, + '#empty' => t('No orphaned keywords.'), + ); + + $form['pager'] = array('#markup' => theme('pager')); + + return $form; +} +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_keyword_orphans_form_validate($form, &$form_state) { + $check_count = array_filter($form_state['values']['words']); + if (count($check_count) == 0) { + form_set_error('', t('No items selected.')); + } +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_keyword_orphans_form_submit($form, &$form_state) { + + $keywords = array_filter($form_state['values']['words']); + db_delete('biblio_keyword_data') + ->condition('kid', $keywords, 'IN') + ->execute(); + + drupal_set_message(t('%count orphaned keywords have been deleted.', array('%count' => count($keywords)))); + +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + * @param unknown_type $keyword_id + * @return multitype:string number NULL + */ +function biblio_admin_keyword_edit_form($form, &$form_state, $keyword_id) { + $options = array(); + $keywords = array(); + $destination = NULL; + + $keyword = db_query('SELECT * FROM {biblio_keyword_data} bkd WHERE bkd.kid = :kid ', array(':kid' => $keyword_id))->fetchObject(); + + $base = variable_get('biblio_base', 'biblio'); +// $path = (strpos($_GET['q'], 'config')) ? 'admin/config/content/biblio/keywords' : $base . '/keywords'; + + if (isset($_GET['destination'])) { + $destination = $_GET['destination']; + } + if (!$destination && isset($form_state['complete form']['#action'])) { + $action = drupal_parse_url($form_state['complete form']['#action']); + $destination = isset($action['query']['destination']) ? $action['query']['destination'] : NULL; + } + if (!$destination) $destination = $base . '/keywords'; + + $form_state['redirect'] = $destination; + + $form['kid'] = array( + '#type' => 'value', + '#value' => $keyword_id + ); + $form['word'] = array( + '#type' => 'textfield', + '#title' => t('Keyword'), + '#default_value' => $keyword->word, + '#size' => 100, + '#weight' => -10, + '#required' => TRUE, + '#maxlength' => 255 + ); + + + $result = db_query("SELECT kd.word, kd.kid, count(*) as use_count FROM {biblio_keyword_data} kd + LEFT JOIN {biblio_keyword} bk on bk.kid = kd.kid + WHERE LOWER(word) LIKE LOWER(:word) + AND kd.kid <> :kid + GROUP BY kd.kid, kd.word", array(':word' => '%%' . drupal_substr($keyword->word, 0, 5) . '%%', ':kid' => $keyword_id)); + + foreach ($result as $keyword) { + $keywords[] = $keyword; + } + + if (isset($form_state['biblio_add_merge_keywords'])) { + $keywords = array_merge($keywords, $form_state['biblio_add_merge_keywords']); + } + + foreach ($keywords as $keyword) { + $options[$keyword->kid] = array( + 'keyword' => array( + 'data' => array( + '#type' => 'link', + '#title' => $keyword->word . ' (' . $keyword->use_count .')', + '#href' => $destination . '/'. $keyword->kid . '/edit', + '#options' => array('query' => array('destination' => $destination)), + ), + ), + ); + } + + $form['merge'] = array( + '#type' => 'fieldset', + '#title' => t('Keyword Merge'), + '#description' => t('If you wish to consolodate references to multiple keywords into single reference to: !kw, select the others from the list below. This will remove the selected keywords from the database and replace references to them with a reference to: !kw. You should only do this if you are sure the other keywords represent the same keyword as the one being edited.', array('!kw' => $keyword->word)), + '#weight' => 5, + '#collapsible' => TRUE, + '#collapsed' => FALSE, + // '#theme' => 'biblio_admin_keyword_merge_fieldset' + ); + + $header = array('keyword' => t('Similar keywords ')); + + $form['merge']['merge_words'] = array( + '#type' => 'tableselect', + '#header' => $header, + '#options' => $options, + '#empty' => t('No similar keywords automatically detected, use the search box below to manually add others.'), + '#prefix' => '
', + '#suffix' => '
', + + ); + $form['merge']['search'] = array( + '#type' => 'textfield', + '#title' => t('Keyword search'), + '#autocomplete_path' => 'biblio/autocomplete/biblio_keywords', + '#description' => t('Use this field to find other keywords you would like to merge with: !kw, then click the "Add to merge list" button. (The merge will not happen until the "Save" button is clicked)', array('!kw' => $keyword->word)) + ); + $form['merge']['add'] = array( + '#type' => 'submit', + '#value' => t('Add to merge list'), + '#submit' => array('biblio_add_merge_keyword'), + '#ajax' => array( + 'callback' => 'biblio_add_merge_keyword_callback', + 'wrapper' => 'biblio-keyword-merge-table', + ), + ); + + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Save'), + '#weight' => 6, + ); + $form['delete'] = array( + '#type' => 'submit', + '#value' => t('Delete'), + '#weight' => 7, + ); + $form['cancel'] = array( + '#type' => 'submit', + '#value' => t('Cancel'), + '#weight' => 8, + ); + + return $form; +} +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_add_merge_keyword_callback($form, &$form_state) { + return $form['merge']['merge_words']; +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_add_merge_keyword($form, &$form_state) { + + if (!empty($form_state['values']['search'])) { + module_load_include('inc', 'biblio', 'includes/biblio.keywords'); + if ($word = biblio_get_keyword_by_name($form_state['values']['search'])) { + if ($word->kid == $form_state['values']['kid']) { // we don't want to merge with ourselves :-( + drupal_set_message(t('You cannot merge a keyword with itself'), 'error'); + } + elseif (isset($form_state['biblio_add_merge_keywords'][$word->kid])) { + drupal_set_message(t('Keyword already exists in the merge list'), 'warning'); + } + else { + $form_state['biblio_add_merge_keywords'][$word->kid] = $word; + } + } + else { + drupal_set_message(t('The keyword was not found in the database. You must select a keyword from the "auto-complete" list of the Keyword search box.'), 'error'); + } + } + else { + drupal_set_message(t('Cannot add an empty value'), 'error'); + } + + $form_state['rebuild'] = TRUE; +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + * @param unknown_type $keyword_id + */ +function biblio_admin_keyword_delete_confirm($form, &$form_state, $keyword_id) { + $base = variable_get('biblio_base', 'biblio'); + $keyword = db_query('SELECT * FROM {biblio_keyword_data} bkd WHERE bkd.kid = :kid ', array(':kid' => $keyword_id))->fetchObject(); + $form['kid'] = array( + '#type' => 'value', + '#value' => $keyword_id, + ); + + return confirm_form($form, + t('Are you sure you want to delete the keyword: %word from ALL publications?', array('%word' => $keyword->word)), + isset($_GET['destination']) ? $_GET['destination'] : $base . '/keywords', + t('This action cannot be undone.'), + t('Delete'), + t('Cancel') + ); + +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_keyword_delete_confirm_submit($form, &$form_state) { + $base = variable_get('biblio_base', 'biblio'); + module_load_include('inc', 'biblio', 'includes/biblio.keywords'); + biblio_delete_keyword($form_state['values']['kid']); + $form_state['redirect'] = $base . '/keywords'; +} + +/** + * @param unknown_type $form + * @param unknown_type $form_state + */ +function biblio_admin_keyword_edit_form_submit($form, &$form_state) { + switch ($form_state['values']['op']) { + + case t('Save'): + drupal_write_record('biblio_keyword_data', $form_state['values'], 'kid'); + if (isset($form_state['values']['merge_words'])) { + $kids = array_filter($form_state['values']['merge_words']); + if (count($kids)) { + db_update('biblio_keyword') + ->fields(array('kid' => $form_state['values']['kid'])) + ->condition('kid', $kids, 'IN') + ->execute(); + + db_delete('biblio_keyword_data') + ->condition('kid', $kids, 'IN') + ->execute(); + } + } + break; + case t('Delete'): + $base = variable_get('biblio_base', 'biblio'); + unset($_GET['destination']); + $form_state['redirect'] = "$base/keyword/" . $form_state['values']['kid'] . '/delete'; + break; + case t('Cancel'): + $base = variable_get('biblio_base', 'biblio'); + $form_state['redirect'] = $base . '/keywords'; + break; + } +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/includes/biblio.contributors.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/includes/biblio.contributors.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,625 @@ + $aid))->fetchField(); + if ($aka == 0) { + $query = db_select('biblio_contributor_data', 'bcd'); + $cids = $query->fields('bcd', array('cid')) + ->condition(db_and()->condition('bcd.aka', $aid, '=')->condition('bcd.alt_form', 0, '=')) + ->execute() + ->fetchCol(); + } + else { + $query = db_select('biblio_contributor_data', 'bcd'); + $and = db_and()->condition('bcd.aka', $aka, '=')->condition('bcd.alt_form', 0, '=')->condition('bcd.cid', $aid, '<>'); + $cids = $query->fields('bcd', array('cid')) + ->condition(db_or()->condition('bcd.cid', $aka)->condition('bcd.aka', $aid)->condition($and)) + ->execute() + ->fetchCol(); + } + $related[$aid] = $cids; + } + return $related[$aid]; +} + +function biblio_get_contributor($aid) { + $contributor = &drupal_static(__FUNCTION__); + + if (!isset($contributor[$aid])) { + $contributor[$aid] = db_query('SELECT * FROM {biblio_contributor_data} WHERE cid = :cid', array(':cid' => $aid))->fetchObject(); + } + + return $contributor[$aid]; +} + +/** + * @param array $contributors + * @param int $category + * @return array $authors + */ +function biblio_get_contributor_category($contributors, $category) { + $authors = array(); + foreach ($contributors as $author) { + if ($author['auth_category'] == $category) { + $authors[] = $author; + } + } + return $authors; +} + +/** + * Get an author id from the database using the "name" field as a key. + * If the "cid" value is negative, this means we found an "alternate" form of + * the name, which should have an "aka" value which points to the preferred form. + * + * @param string $name + * @return int + */ +function biblio_get_cid_by_name($name) { + $cid = 0; + $auth = biblio_get_contributor_by_name($name); + if ($auth) { + if ($auth->cid > 0) { + $cid = $auth->cid; + } + if ($auth->aka > 0 && $auth->alt_form > 0) { + $cid = $auth->aka; + } + } + return $cid; +} + +/** + * @param unknown_type $name + * @return unknown + */ +function biblio_get_contributor_by_name($name) { + $contributors = &drupal_static(__FUNCTION__); + $name = trim($name); + if (!isset($contributors[$name]) || $contributors[$name] === FALSE) { + $query = db_select('biblio_contributor_data', 'bcd'); + $contributors[$name] = $query->fields('bcd')->condition('bcd.name', $name)->execute()->fetchObject(); + } + + return $contributors[$name]; +} + +/** + * @param unknown_type $vid + * @return Ambigous + */ +function biblio_get_first_contributor($vid) { + static $contributor = array(); + if (!isset($contributor[$vid])) { + $query = db_select('biblio_contributor', 'bc'); + $query->join('biblio_contributor_data', 'bcd', 'bc.cid=bcd.cid'); + $query->fields('bcd'); + $query->condition('bc.vid', $vid); + $query->condition('bc.rank', 0); + $contributor[$vid] = $query->execute()->fetchObject(); + } + + return $contributor[$vid]; +} + +/** + * @param $vid + * @return unknown_type + */ +function biblio_load_contributors($vid) { + $vids = (isset($vid) ? array($vid) : array()); + return biblio_load_contributors_multiple($vids); +} + +/** + * @param unknown_type $vids + * @param unknown_type $auth_category + * @return multitype:|Ambigous + */ +function biblio_load_contributors_multiple($vids = array(), $auth_category = 0) { + $contributors = array(); + if (empty($vids)) return $contributors; + + $query = db_select('biblio_contributor', 'bc'); + $query->innerJoin('biblio_contributor_data', 'bcd', 'bcd.cid = bc.cid'); + $query->fields('bc'); + $query->fields('bcd'); + $query->orderby('bc.vid'); + $query->orderby('bc.rank'); + if (count($vids) == 1) { + $query->condition('bc.vid', $vids[0]); + } + else { + $query->condition('bc.vid', $vids, 'IN'); + } + if ($auth_category) { + $query->condition('bc.auth_category', $auth_category); + } + $query->addMetaData('base_table', 'biblio_contributor'); + $query->addTag('node_access'); + $result = $query->execute(); + + foreach ($result as $creator) { + $contributors[$creator->vid][] = (array)$creator; + } + + return $contributors; +} +/** + * Add separate author named "et al" to the end of the author array + * + * @param $authors - author array to augment + * @param $type - auth_type + * @return TRUE if author was added, FALSE if "etal" was already there + */ +function biblio_authors_add_etal(&$authors, $type) { + $etal = "et al"; $max_rank = 0; + foreach ($authors as $author) { // et al author should be added only once per type + if ($author['auth_type'] != $type) continue; + if ($author['name'] == $etal) { + return FALSE; + } + $max_rank = max($max_rank, $author['rank']); + } + $authors[] = biblio_parse_author(array('name' => $etal, 'auth_type' => $type, 'lastname' => $etal, 'rank' => $max_rank + 1)); + return TRUE; +} + +/** + * @param unknown_type $node + * @return unknown + */ +function biblio_delete_contributors($node) { + $count = db_delete('biblio_contributor') + ->condition('nid', $node->nid) + ->execute(); + return $count; +} + +/** + * @param unknown_type $node + * @return unknown + */ +function biblio_delete_contributors_revision($node) { + $count = db_delete('biblio_contributor') + ->condition('vid', $node->vid) + ->execute(); + return $count; +} + +/** + * @param unknown_type $cid + */ +function biblio_delete_contributor($cid) { + db_delete('biblio_contributor') + ->condition('cid', $cid) + ->execute(); + + return db_delete('biblio_contributor_data') + ->condition('cid', $cid) + ->execute(); + +} +/** + * @param unknown_type $cid + * @param unknown_type $vid + */ +function biblio_delete_contributor_revision($cid, $vid) { + return db_delete('biblio_contributor') + ->condition('cid', $cid) + ->condition('vid', $vid) + ->execute(); + +} + +/** + * Get the number of orphaned authors in the database + * + * @return number + */ +function biblio_count_orphan_authors() { + $cids = biblio_get_orphan_author_ids(); + return count($cids); +} + +/** + * Get an array of authors which are not associated with any biblio entires. + * @return array + */ +function biblio_get_orphan_authors() { + $authors = array(); + $cids = biblio_get_orphan_author_ids(); + + if (count($cids)) { + $query = db_select('biblio_contributor_data', 'bcd'); + $result = $query->fields('bcd') + ->condition('cid', $cids, 'IN') + ->orderBy('lastname') + ->execute(); + + foreach ($result as $author) { + $authors[] = $author; + } + } + return $authors; +} + +/** + * Get an array of author id's which are not associated with any biblio entries + * + * @return array + */ +function biblio_get_orphan_author_ids() { + $orphans = array(); + $active_cids = array(); + $all_cids = array(); + + $query = db_select('biblio_contributor', 'bc'); + $active_cids = $query + ->fields('bc', array('cid')) + ->groupBy('cid') + ->execute() + ->fetchCol(); + + $query = db_select('biblio_contributor_data', 'bcd'); + $all_cids = $query + ->fields('bcd', array('cid')) + ->condition(db_and()->condition('bcd.cid', 0, '>')->condition('bcd.alt_form', 0, '=')) + ->execute() + ->fetchCol(); + + $orphans = array_diff($all_cids, $active_cids); + + return $orphans; +} + +/** + * @param unknown_type $force + */ +function biblio_delete_orphan_authors($force = FALSE) { + if (variable_get('biblio_auto_orphaned_author_delete', 0) || $force) { + $orphans = biblio_get_orphan_author_ids(); + if (!empty($orphans)) { + db_delete('biblio_contributor_data') + ->condition('cid', $orphans, 'IN') + ->execute(); + } + } +} + +/** + * @param unknown_type $node + * @return Ambigous + */ +function biblio_insert_contributors($node) { + if (!empty($node->biblio_contributors)) { + return _save_contributors($node->biblio_contributors, $node->nid, $node->vid); + } +} + +/** + * @param unknown_type $node + */ +function biblio_update_contributors($node) { + if (!empty($node->biblio_contributors)) { + _save_contributors($node->biblio_contributors, $node->nid, $node->vid, TRUE); + } + return; + +} + +/** + * @param unknown_type $author + */ +function biblio_save_contributor(&$author) { + foreach ($author as $key => $value) { + $author[$key] = trim($value); + } + return drupal_write_record('biblio_contributor_data', $author); +} + +/** + * @param unknown_type $author + * @return boolean + */ +function biblio_update_contributor(&$author) { + if (!isset($author['cid'])) return FALSE; + return drupal_write_record('biblio_contributor_data', $author, 'cid'); +} + +/** + * @param unknown_type $authors + */ +function _biblio_contributor_sort(&$authors) { + foreach ($authors as $key => $author) { + if (!isset($author['rank']) || empty($author['rank'])) { + $authors[$key]['rank'] = $key; + } + } + usort($authors, '_biblio_contributor_usort'); +} + +/** + * @param unknown_type $a + * @param unknown_type $b + * @return number + */ +function _biblio_contributor_usort($a, $b) { + if (empty($a['name'])) return 1; + if (empty($b['name'])) return -1; + return ($a['rank'] < $b['rank']) ? -1 : 1; +} +/** + * Save contributors to the database + * @param $authors + * @param $nid + * @param $vid + * @param $update + * @return success of database operations + */ +function _save_contributors(&$contributors, $nid, $vid, $update = FALSE) { + $rank = 0; + + db_delete('biblio_contributor') + ->condition(db_and()->condition('nid', $nid)->condition('vid', $vid)) + ->execute(); + + // re-sort the authors by rank because the rank may have changed due to tabledrag on the input form + _biblio_contributor_sort($contributors); + + $name_parser = new HumanNameParser_Parser(); + + foreach ($contributors as $key => $author) { + if (!empty($author['name'])) { + if (isset($author['cid']) && !empty($author['cid'])) { + // check to make sure the name wasn't changed + // this should only happen via the node/add/biblio input form + $auth = biblio_get_contributor($author['cid']); + if (!empty($auth) && isset($auth->name) && $auth->name != $author['name']) { + //if the name has changed, NULL the cid so a new entry is created + $author['cid'] = NULL; + } + else { + $contributors[$key] = array_merge($author, (array)$auth); + } + } + // if we don't have a cid, lets see if we can find and exact match + // to the name and use that cid + if (!isset($author['cid']) || empty($author['cid'])) { + $auth = biblio_get_contributor_by_name($author['name']); + if (!empty($auth) && isset($auth->cid)) { + $author['cid'] = $auth->cid; + $contributors[$key] = array_merge($author, (array)$auth); + } + } + + // if we still don't have a cid, then create a new entry in the biblio_contirbutor_data table + if (empty($author['cid'])) { + try { + $author = $name_parser->parseName($author); + } + catch (Exception $e) { + $link = l('in node ' . $nid, 'node/' . $nid); + $message = $e->getMessage() . ' ' . $link; + drupal_set_message($message , 'error'); + watchdog('biblio', $message, array(), WATCHDOG_ERROR); + } + + $contributors[$key] = $author; + biblio_save_contributor($author); + } + + // we should now have a cid, if not we are in big trouble... + if (empty ($author['cid'])) { + //throw error that author was not saved + } + + $link_array = array( + 'nid' => $nid, + 'vid' => $vid, + 'cid' => $author['cid'], + 'rank' => $rank++, + 'auth_type' => !empty($author['auth_type']) ? $author['auth_type'] : $author['auth_category'], + 'auth_category' => $author['auth_category'], + ); + + if (!drupal_write_record('biblio_contributor', $link_array)) return FALSE; + } + } + //TODO check if it is necessary to reset aka here... + // db_query("UPDATE {biblio_contributor_data} SET aka = cid WHERE aka = 0 OR aka IS NULL"); + // db_update('biblio_contributor_data') + // ->fields(array('aka', ) + return TRUE; // successfully saved all contributors +} +/* + Released through http://bibliophile.sourceforge.net under the GPL licence. + Do whatever you like with this -- some credit to the author(s) would be appreciated. + + A collection of PHP classes to manipulate bibtex files. + + If you make improvements, please consider contacting the administrators at bibliophile.sourceforge.net so that your improvements can be added to the release package. + + Mark Grimshaw 2004/2005 + http://bibliophile.sourceforge.net + + 28/04/2005 - Mark Grimshaw. + Efficiency improvements. + + 11/02/2006 - Daniel Reidsma. + Changes to preg_matching to account for Latex characters in names such as {\"{o}} + */ +// For a quick command-line test (php -f PARSECREATORS.php) after installation, uncomment these lines: +/*********************** + $authors = "Mark \~N. Grimshaw and Bush III, G.W. & M. C. H{\\'a}mmer Jr. and von Frankenstein, Ferdinand Cecil, P.H. & Charles Louis Xavier Joseph de la Vallee P{\\\"{o}}ussin"; + $creator = new PARSECREATORS(); + $creatorArray = $creator->parse($authors); + print_r($creatorArray); + ***********************/ +/* Create writer arrays from bibtex input. + 'author field can be (delimiters between authors are 'and' or '&'): + 1. + 2. , + 3. , , + */ +/** + * @param $author_array + * @return unknown_type + */ +function biblio_parse_author($author_array, $cat = 0) { + + if (isset($author_array['auth_category']) && $author_array['auth_category'] == 5) { + $author_array['firstname'] = ''; + $author_array['initials'] = ''; + $author_array['lastname'] = trim($author_array['name']); + $author_array['prefix'] = ''; + $author_array['literal'] = 1; + } + else { + $value = trim($author_array['name']); + $appellation = $prefix = $surname = $firstname = $initials = ''; + $prefix = ""; + $value = preg_replace("/\s{2,}/", ' ', $value); // replace multiple white space by single space + $author = explode(",", $value); + $size = sizeof($author); + // No commas therefore something like Mark Grimshaw, Mark Nicholas Grimshaw, M N Grimshaw, Mark N. Grimshaw + if ($size == 1) { + // Is complete surname enclosed in {...}, unless the string starts with a backslash (\) because then it is + // probably a special latex-sign.. + // 2006.02.11 DR: in the last case, any NESTED curly braces should also be taken into account! so second + // clause rules out things such as author="a{\"{o}}" + // + if (preg_match("/(.*) {([^\\\].*)}/", $value, $matches) && !(preg_match("/(.*) {\\\.{.*}.*}/", $value, $matches2))) { + $author = explode(" ", $matches[1]); + $surname = $matches[2]; + } + else { + $author = explode(" ", $value); + // last of array is surname (no prefix if entered correctly) + $surname = array_pop($author); + } + } + // Something like Grimshaw, Mark or Grimshaw, Mark Nicholas or Grimshaw, M N or Grimshaw, Mark N. + else + if ($size == 2) { + // first of array is surname (perhaps with prefix) + list ($surname, $prefix) = _grabSurname(array_shift($author)); + } + // If $size is 3, we're looking at something like Bush, Jr. III, George W + else { + // middle of array is 'Jr.', 'IV' etc. + $appellation = implode(' ', array_splice($author, 1, 1)); + // first of array is surname (perhaps with prefix) + list ($surname, $prefix) = _grabSurname(array_shift($author)); + } + $remainder = implode(" ", $author); + list ($firstname, $initials, $prefix2) = _grabFirstnameInitials($remainder); + if (!empty ($prefix2)) + $prefix .= $prefix2; + //var_dump($prefix); + //$surname = $surname . ' ' . $appellation; + $author_array['firstname'] = trim($firstname); + $author_array['initials'] = (strlen(trim($initials)) > 10) ? drupal_substr(trim($initials), 0, 10) : trim($initials); + $author_array['lastname'] = trim($surname); + $author_array['prefix'] = trim($prefix); + $author_array['suffix'] = trim($appellation); + } + $author_array['md5'] = _md5sum($author_array); + return $author_array; +} +/** + * @param $creator + * @return unknown_type + */ +function _md5sum($creator) { + $string = $creator['firstname'] . $creator['initials'] . $creator['prefix'] . $creator['lastname']; + $string = str_replace(' ', '', drupal_strtolower($string)); + return md5($string); +} +// grab firstname and initials which may be of form "A.B.C." or "A. B. C. " or " A B C " etc. +/** + * @param $remainder + * @return unknown_type + */ +function _grabFirstnameInitials($remainder) { + $prefix = array(); + $firstname = $initials = ''; + $array = explode(" ", $remainder); + foreach ($array as $value) { + $first_char = drupal_substr($value, 0, 1); + if ((ord($first_char) >= 97) && (ord($first_char) <= 122)) { + $prefix[] = $value; + } + elseif (preg_match("/[a-zA-Z]{2,}/", trim($value))) { + $firstname_array[] = trim($value); + } + else { + $initials_array[] = trim(str_replace(".", " ", trim($value))); + } + } + if (isset ($initials_array)) { + $initials = implode(" ", $initials_array); + } + if (isset ($firstname_array)) { + $firstname = implode(" ", $firstname_array); + } + if (!empty ($prefix)) { + $prefix = implode(" ", $prefix); + } + return array($firstname, $initials, $prefix); +} +// surname may have title such as 'den', 'von', 'de la' etc. - characterised by first character lowercased. Any +// uppercased part means lowercased parts following are part of the surname (e.g. Van den Bussche) +/** + * @param $input + * @return unknown_type + */ +function _grabSurname($input) { + $no_prefix = FALSE; + $surname = FALSE; + $prefix = FALSE; + + $surname_array = explode(" ", $input); + + foreach ($surname_array as $value) { + $first_char = substr($value, 0, 1); + if (!$no_prefix && (ord($first_char) >= 97) && (ord($first_char) <= 122)) { + $prefix[] = $value; + } + else { + $surname[] = $value; + $no_prefix = TRUE; + } + } + if (!empty($surname)) { + $surname = implode(" ", $surname); + } + if (!empty ($prefix)) { + $prefix = implode(" ", $prefix); + } + return array($surname, $prefix); +} +/** + * @return unknown_type + */ +function _loadMD5() { + static $md5 = array(); + static $count = 0; + $db_count = db_query("SELECT COUNT(*) FROM {biblio_contributor_data}")->fetchField(); + if ($db_count != $count) { //refresh the cached data as some new authors may have been added or removed + $count = $db_count; + $md5 = array(); + $result = db_query('SELECT md5,cid FROM {biblio_contributor_data} '); + foreach ($result as $row ) { + $md5[$row->cid] = $row->md5; + } + } + return (count($md5)) ? $md5 : NULL; +} + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/includes/biblio.feeds.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/includes/biblio.feeds.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,211 @@ + $spec) { + if (strstr($field, 'biblio_')) { + $type = $spec['type']; + $length = isset($spec['length']) ? ' ['. $spec['length'] . ']': ''; + $targets[$field] = array( + 'name' => $field . ' (' . $type . $length . ')', + 'description' =>'', + 'callback' => '_biblio_feeds_set__simple_target', + ); + } + } + $targets['biblio_type']['callback'] = '_biblio_feeds_set__type_target'; + $targets['biblio_contributor'] = array( + 'name' => t('biblio_contributor'), + 'description' => t('This is a contributor (author) contained in a biblio entry.'), + 'callback' => '_biblio_feeds_set__contrib_target', + // 'real_target' => 'my_node_field_two', // Specify real target field on node. + ); + $targets['biblio_keyword'] = array( + 'name' => t('biblio_keyword'), + 'description' => t('This is a keyword contained in a biblio entry.'), + 'callback' => '_biblio_feeds_set__keyword_target', + // 'real_target' => 'my_node_field_two', // Specify real target field on node. + ); + } +} + +function _biblio_feeds_set__type_target($source, $entity, $target, $value) { + static $types = array(); + + if (empty($value)) { + return; + } + + // Handle non-multiple value fields. + if (!is_array($value)) { + $value = array($value); + } + + if (isset($value[0]) && !empty($value[0])) { + if (intval($value[0]) > 0) { + // value[0] is the bibio type ID + if (empty($types)) { + $result = db_query('SELECT t.* FROM {biblio_types} as t WHERE t.tid > 0'); + foreach ($result as $row) { + $types[$row->tid] = $row->tid; + } + } + + $type_id = $value[0]; + $entity->biblio_type = (isset($types[$type_id])) ? $type_id : 129; + } + elseif (is_string($value[0])) { + // value[0] is the bibio type name + if (empty($types)) { + $result = db_query('SELECT t.* FROM {biblio_types} as t WHERE t.tid > 0'); + foreach ($result as $row) { + $types[$row->tid] = str_replace(" ","_", strtolower($row->name)); + } + } + + $type = array_search($value[0], $types); + $entity->biblio_type = (!empty($type)) ? $type : 129; + } + } +} + +function _biblio_feeds_set__simple_target($source, $entity, $target, $value) { + if (empty($value)) { + return; + } + + // Handle non-multiple value fields. + if (!is_array($value)) { + $value = array($value); + } + + if (isset($value[0]) && !empty($value[0])) { + $entity->$target = $value[0]; + if ($target == 'biblio_abst_e') { + $entity->biblio_formats[$target] = 'full_html'; + } + } +} + +function _biblio_feeds_set__contrib_target($source, $entity, $target, $value) { + if (is_string($value)) { + $value = explode('||', $value); + } + foreach ($value as $author) { + $entity->biblio_contributors[] = array( + 'name' => $author, + 'auth_category' => 1, + ); + } +} + +function _biblio_feeds_set__keyword_target($source, $entity, $target, $value) { + if (!empty($value)) { + $entity->biblio_keywords = $value; + } +} + +function _biblio_feeds_oai_importer_default() { + + $feeds_importer = new stdClass; + $feeds_importer->disabled = FALSE; /* Edit this to true to make a default feeds_importer disabled initially */ + $feeds_importer->api_version = 1; + $feeds_importer->id = 'biblio_oai_pmh'; + $feeds_importer->config = array( + 'name' => 'Biblio OAI-PMH', + 'description' => 'Import an OAI-PMH feed into the Biblio node type.', + 'fetcher' => array( + 'plugin_key' => 'FeedsOAIHTTPFetcher', + 'config' => array( + 'auto_detect_feeds' => FALSE, + 'use_pubsubhubbub' => FALSE, + 'last_fetched_timestamp' => '', + 'earliest_timestamp' => '', + 'use_dates' => FALSE, + 'to' => array(), + 'from' => array(), + ), + ), + 'parser' => array( + 'plugin_key' => 'FeedsOAIParser', + 'config' => array(), + ), + 'processor' => array( + 'plugin_key' => 'FeedsNodeProcessor', + 'config' => array( + 'content_type' => 'biblio', + 'expire' => '-1', + 'author' => 0, + 'mappings' => array( + 0 => array( + 'source' => 'title', + 'target' => 'title', + 'unique' => 0, + ), + 1 => array( + 'source' => 'publisher', + 'target' => 'biblio_publisher', + 'unique' => FALSE, + ), + 2 => array( + 'source' => 'subject', + 'target' => 'biblio_keyword', + 'unique' => FALSE, + ), + 3 => array( + 'source' => 'source', + 'target' => 'biblio_secondary_title', + 'unique' => FALSE, + ), + 4 => array( + 'source' => 'guid', + 'target' => 'guid', + 'unique' => 1, + ), + 5 => array( + 'source' => 'creator', + 'target' => 'biblio_contributor', + 'unique' => FALSE, + ), + 6 => array( + 'source' => 'description', + 'target' => 'biblio_abst_e', + 'unique' => FALSE, + ), + 7 => array( + 'source' => 'contributor', + 'target' => 'biblio_contributor', + 'unique' => FALSE, + ), + 8 => array( + 'source' => 'identifier', + 'target' => 'biblio_url', + 'unique' => FALSE, + ), + 9 => array( + 'source' => 'date', + 'target' => 'biblio_year', + 'unique' => FALSE, + ), + 10 => array( + 'source' => 'setspec_raw', + 'target' => 'biblio_type', + 'unique' => FALSE, + ), + ), + 'update_existing' => '0', + 'input_format' => 'plain_text', + ), + ), + 'content_type' => '', + 'update' => 0, + 'import_period' => '1800', + 'expire_period' => 3600, + 'import_on_create' => 1, + 'process_in_background' => 0, + ); + + return array( + 'biblio_oai' => $feeds_importer + ); +} \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/includes/biblio.fields.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/includes/biblio.fields.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,51 @@ + 0), array('fetch' => PDO::FETCH_ASSOC)); + + foreach ($result as $row) { + $fields[$row['name']] = $row; + } + _biblio_localize_fields($fields); + + $extras['node']['biblio']['form']['biblio_type'] = array( + 'label' => t('Publication Type'), + 'description' => t('Biblio module form.'), + 'weight' => -4 + ); + + foreach ($fields as $key => $fld) { + $label = check_plain($fld['title']); + if ($fld['type'] == 'textarea' || $fld['type'] == 'contrib_widget') { + $key = $key . '_field'; + $label = $label . ' (' . t('Fieldset') . ')'; + } + $extras['node']['biblio']['form'][$key] = array( + 'label' => $label, + 'description' => t('Biblio module form.'), + 'weight' => $fld['weight'] / 10 + ); + } + $extras['node']['biblio']['form']['other_fields'] = array( + 'label' => t('Other Biblio Fields') . ' (' . t('Fieldset') . ')', + 'description' => t('Biblio module form.'), + 'weight' => 0 + ); + + $extras['user']['user'] = array( + 'form' => array( + 'biblio_fieldset' => array( + 'label' => t('User specific Biblio settings'), + 'description' => t('Biblio module account form elements.'), + 'weight' => -10, + ), + ), + ); + + return $extras; +} \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/includes/biblio.import.export.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/includes/biblio.import.export.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,873 @@ + 0 '; + $result = db_query($sql); + foreach ($result as $user) { + $users[$user->uid] = $user->name . " ($user->mail)"; + } + asort($users); + $select = array( + '#type' => 'select', + '#title' => t("Set user ID of entries in this file to"), + '#options' => $users, + '#default_value' => $my_uid, + '#disabled' => (user_access('administer biblio')) ? FALSE : TRUE + ); + return $select; +} +/** + * Return a form used to import files into biblio. + * + * @return + * An array which will be used by the form builder to build the import form + */ +function biblio_import_form($form, &$form_state) { + global $user; + $msg = ''; + $biblio_vocabs = array(); + + if (biblio_access('import')) { // && !user_access('administer nodes')) { + $form['#attributes']['enctype'] = 'multipart/form-data'; + $form['biblio_import_file'] = array( + '#type' => 'file', + '#title' => t('Import file'), + '#default_value' => '', + '#size' => 60 + ); + + $import_options = module_invoke_all('biblio_import_options'); + if (count($import_options) > 1) { + $form['filetype'] = array( + '#type' => 'select', + '#title' => t('File Type'), + '#default_value' => 0, + '#options' => array( + '0' => t('Select type'), + ) + ); + + $form['filetype']['#options'] = array_merge($form['filetype']['#options'], $import_options); + asort($form['filetype']['#options']); + } + elseif (count($import_options) == 1) { + $form['biblio_import_file']['#description'] = t('Import type: @option', array('@option' => current($import_options))); + $form['filetype'] = array( + '#type' => 'value', + '#value' => key($import_options), + ); + } + elseif (count($import_options) == 0) { + $form['biblio_import_file']['#disabled'] = TRUE; + drupal_set_message(t("You won't be able to select a file until you enable at least one import module."), 'error'); + + } + + $form['batch_process'] = array( + '#type' => 'checkbox', + '#title' => t('Batch Process'), + '#default_value' => 1, + '#description' => t('You should use batch processing if your import file contains more than about 20 records, or if you are experiencing script timeouts during import'), + ); + $form ['userid'] = _biblio_admin_build_user_select($user->uid); + // Get the vocabularies attached to the biblio node type ... + foreach (field_info_instances('node', 'biblio') as $instance) { + $field = field_info_field_by_id($instance['field_id']); + if ($field['type'] == 'taxonomy_term_reference') { + foreach ($field['settings']['allowed_values'] as $delta => $tree) { + $biblio_vocabs[$tree['vocabulary']] = array('instance' => $instance, 'field' => $field); + } + } + } + + // ... and print a form to select the terms in each of them + $form['import_taxonomy'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => t('Taxonomy Settings'), + '#description' => t('Typically you don\'t have to do anything here, however if you wish, you may select terms to be assigned to imported records. This effectively adds a keyword to all entries being imported.')); + if (count($biblio_vocabs)) { + $vocabularies = module_invoke('taxonomy', 'get_vocabularies', 'biblio'); + if (variable_get('biblio_keyword_freetagging', 0)) { + $freetag_vocab = $vocabularies[variable_get('biblio_keyword_vocabulary', 0)]; + unset($vocabularies[variable_get('biblio_keyword_vocabulary', 0)]); + $msg = t('NOTE: Keyword "free tagging" is turned on, consequently all incomming keywords will be added to the @name vocabulary as specified in the "Keyword" section of the !url page.', array('@name' => $freetag_vocab->name, '!url' => l(t('admin/config/content/biblio'), 'admin/config/content/biblio'))); + } + else { + $msg = t('NOTE: Keyword "free tagging" is turned off, consequently keywords will NOT be added to the vocabulary as specified in the Taxonomy section of the !url page.', array('!url' => l(t('admin/config/content/biblio'), 'admin/config/content/biblio'))); + } + $i = 0; + $form += array('#parents' => array()); + $form['import_taxonomy']['vocabularies'] = array(); + $term_refs = array(); + + foreach ($vocabularies as $vocabulary) { + if (in_array($vocabulary->machine_name, array_keys($biblio_vocabs))) { + $term_refs[] = $biblio_vocabs[$vocabulary->machine_name]['instance']['field_name']; + $entity = new stdClass(); + $entity->type = 'biblio'; + $field = $biblio_vocabs[$vocabulary->machine_name]['field']; + $instance = $biblio_vocabs[$vocabulary->machine_name]['instance']; + $items = array(); + $form['import_taxonomy']['vocabularies'] += field_default_form('node', $entity, $field, $instance, 'und', $items, $form, $form_state); + } + } + if (!empty($term_refs)) { + $form['term_refs'] = array( + '#type' => 'hidden', + '#value' => $term_refs, + ); + $form['import_taxonomy']['copy_to_biblio'] = array( + '#type' => 'checkbox', + '#title' => t('Copy these terms to the biblio keyword database'), + '#return_value' => 1, + '#default_value' => variable_get('biblio_copy_taxo_terms_to_keywords', 0), + '#description' => t('If this option is selected, the selected taxonomy terms will be copied to the ' . check_plain(variable_get('biblio_base_title', 'Biblio')) . ' keyword database and be displayed as keywords (as well as taxonomy terms) for this entry.') + ); + } + } + else { + if (module_exists('taxonomy')) { + $vocab_msg = t('There are currently no "Term references" attached to the biblio node type. If you would like to associate a Taxonomy vocabulary with the Biblio node type, go the the !url page and add one or more "Term reference" fields.', array('!url' => l(t('admin/structure/types/manage/biblio/fields'), 'admin/structure/types/manage/biblio/fields'))); + } + else{ + $vocab_msg = '
' . t('Depends on') . ': ' . t('Taxonomy') . ' (' . t('disabled') . ')
'; + + } + $form['import_taxonomy']['vocabulary_message'] = array( + '#markup' => '

' . $vocab_msg . '

' + ); + } + $form['import_taxonomy']['freetagging_information'] = array( + '#markup' => '

' . $msg . '

' + ); + $form['button'] = array('#type' => 'submit', '#value' => t('Import')); + return $form; + } + else { + drupal_set_message(t("You are not authorized to access the biblio import page"), 'error'); + } +} + +/** + * Implementation of hook_validate() for the biblio_import_form. + */ +function biblio_import_form_validate($form, & $form_state) { + $op = $form_state['values']['op']; + $filetype = isset($form_state['values']['filetype']) ? $form_state['values']['filetype'] : 0; + if ($error = isset($_FILES['files']) ? $_FILES['files']['error']['biblio_import_file'] : '') { + switch ($error) { + case 1: form_set_error('biblio_import_form', t("The uploaded file exceeds the upload_max_filesize directive in php.ini.")); + break; + case 2: form_set_error('biblio_import_form', t("The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.")); + break; + case 3: form_set_error('biblio_import_form', t("The uploaded file was only partially uploaded.")); + break; + case 4: form_set_error('biblio_import_form', t("No file was uploaded.")); + break; + case 6: form_set_error('biblio_import_form', t("Missing a temporary folder.")); + break; + case 7: form_set_error('biblio_import_form', t("Failed to write file to disk.")); + break; + case 8: form_set_error('biblio_import_form', t("File upload stopped by extension.")); + } + } + + if ($op == t('Import') && $filetype == "0") { + form_set_error('biblio_import_form', t("You did not select the file type")); + } +} +/** + * Implementation of hook_submit() for the biblio_import_form. + */ +function biblio_import_form_submit($form, & $form_state) { + global $user; + $batch_proc = FALSE; + $extensions = 'xml bib enw mrc ris txt'; + $validators['file_validate_extensions'] = array(); + $validators['file_validate_extensions'][0] = $extensions; + if ($form_state['values']['op'] == t('Import') && isset ($form_state['values']['filetype'])) { + if ($import_file = file_save_upload('biblio_import_file', $validators)) { + if ($form_state['values']['batch_process'] == 1) { + $batch_proc = TRUE; // we will use batch import for larger files. + } + // Concatenate all the terms of the different vocabularies + // in a single array to be sent to biblio_import + $terms = array(); + if (isset($form_state['values']['term_refs'])) { + foreach ($form_state['values']['term_refs'] as $key) { + if (isset($form_state['values'][$key]) && !empty($form_state['values'][$key])) { + foreach ($form_state['values'][$key]['und'] as $id => $item) { + if (!is_array($item) || (empty($item['tid']) && (string) $item['tid'] !== '0')) { + unset($form_state['values'][$key]['und'][$id]); + } + } + if (empty($form_state['values'][$key]['und'])) { + unset($form_state['values'][$key]); + } + else { + $terms[$key] = $form_state['values'][$key]; + } + } + // } + + //FIXME if (count($terms) && $key == 'copy_to_biblio') $terms['copy_to_biblio'] = $form_state['values'][$key]; + } + } + + // Added the $terms argument + // the array of terms to be attached to the node(s) + $userid = (isset($form_state['values']['userid'])) ? $form_state['values']['userid'] : $user->uid; + $filetype = $form_state['values']['filetype']; + $filesize = sprintf("%01.1f", $import_file->filesize / 1000); + $filesize = " ($filesize KB)"; + if ($batch_proc) { + $session_id = microtime(); + $batch_op = array( + 'title' => t('Importing @filename', array('@filename' => $import_file->filename . $filesize)), + 'operations' => array( + array('biblio_import', array($import_file, $filetype, $userid, $terms, $batch_proc, $session_id)), + array('biblio_import_batch_operations', array($session_id, $user, $userid, $terms)) + ), + 'progressive' => TRUE, + 'finished' => 'biblio_import_batch_finished', + 'init_message' => t('Parsing file...'), + 'progress_message' => t('Saving nodes...'), + 'file' => './' . drupal_get_path('module', 'biblio') . '/includes/biblio.import.export.inc' + ); + batch_set($batch_op); + + $base = variable_get('biblio_base', 'biblio'); + batch_process("$base/import"); + + } + else{ //not batch processing the file + $session_id = microtime(); + $context = array(); + biblio_import($import_file, $filetype, $userid, $terms, $batch_proc, $session_id, $context); + biblio_import_finalize(TRUE, $context['results']); + } + file_delete($import_file); + } + else { + drupal_set_message(t("File was NOT successfully uploaded"), 'error'); + } + } +} + +function biblio_import_batch_operations($session_id, $user, $userid, $terms, &$context) { + $limit = 10; + if (empty($context['sandbox'])) { + // Initiate multistep processing. + $context['results']['session_id'] = $session_id; + $context['results']['userid'] = $userid; + $context['results']['user'] = $user; + $context['results']['terms'] = $terms; + $context['sandbox']['progress'] = 0; + $context['sandbox']['current_id'] = 0; + $context['results']['nids'] = array(); + $context['sandbox']['max'] = db_query("SELECT COUNT(DISTINCT(id)) FROM {biblio_import_cache} WHERE session_id = :sessid", array(':sessid' => $session_id))->fetchField(); + $context['sandbox']['itters'] = $context['sandbox']['max'] / $limit; + $context['sandbox']['eta'] = 0; + } + // Bail out if the cache is empty. + if ($context['sandbox']['max'] == 0) { + return; + } + + // Process the next 20 nodes. + timer_start('biblio_import'); + + $result = db_query_range("SELECT id, data FROM {biblio_import_cache} WHERE id > :id AND session_id = :sessid ORDER BY id ASC", 0, $limit, array(':id' => $context['sandbox']['current_id'], ':sessid' => $session_id)); + foreach ($result as $row) { + if ($node = unserialize(base64_decode($row->data))) { + biblio_save_node($node, $terms); + $context['results']['nids'][] = $node->nid; + } + $context['sandbox']['progress']++; + $context['sandbox']['current_id'] = $row->id; + } + $looptime = timer_stop('biblio_import'); + $context['sandbox']['eta'] += $looptime['time']; + $itters = $context['sandbox']['progress'] / $limit; + if ($itters) { + $average_time = $context['sandbox']['eta'] / $itters; + $eta = (($context['sandbox']['itters'] * $average_time) - ($average_time * $itters)) / 1000; + if ($eta >= 60) { + $min = (int) $eta / 60; + } + else { + $min = 0; + } + $sec = $eta % 60; + $eta = sprintf("%d:%02d", $min, $sec); + $progress = sprintf("%d / %d", $context['sandbox']['progress'], $context['sandbox']['max'] ); + $context['message'] = t('
Nodes saved: %progress
Time remaining: %eta min.
' , array('%progress' => $progress, '%eta' => $eta)); + + } + // Multistep processing : report progress. + if ($context['sandbox']['progress'] <= $context['sandbox']['max']) { + $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max']; + } +} +function biblio_import_batch_finished($success, $results, $operations) { + + biblio_import_finalize($success, $results); + //clean up import cache... + db_delete('biblio_import_cache') + ->condition('session_id', $results['session_id']) + ->execute(); +} + +function biblio_import_finalize($success, $results) { + global $user; + $format = $results['format']; + $nids = $results['nids']; + $dups = $results['dups']; + $total = count($nids) + count($dups); + // drupal_set_message(t("%count of %total nodes were successfully imported.", array('%count' => count($nids), '%total' => $total)), (count($nids) != $total)?'warning':'status'); + + if ($success && (count($nids) || count($dups))) { + $message = t("The file @file was successfully uploaded.", array('@file' => $results['file']->filename)); + drupal_set_message($message, 'status'); + watchdog($format, $message); + $count = count($nids); + $message = format_plural($count, 'One of @total node imported.', '@count of @total nodes imported.', array('@total' => $total)); + drupal_set_message($message, 'status'); + watchdog($format, $message, array('@count' => $count, '@total' => $total), WATCHDOG_INFO); + if (count($dups)) { + $count = count($dups); + $message = format_plural($count, 'One duplicate node skipped.', '@count duplicate nodes skipped.'); + drupal_set_message($message, 'status'); + watchdog($format, $message, array('@count' => $count), WATCHDOG_INFO); + foreach ($dups as $nid) { + $message = ''; + $message = t('The item you are trying to import already exists in the database, see'); + $message .= ' ' . l('node/' . $nid, 'node/' . $nid); + + drupal_set_message($message, 'status'); + watchdog($format, $message, array(), WATCHDOG_ERROR); + } + } + } + else { + $count = count($nids); + $message = t('Import finished with an error!') . ' ' . format_plural($count, 'One node imported.', '@count nodes imported.'); + drupal_set_message($message, 'error'); + watchdog($format, $message, array('@count' => $count), WATCHDOG_ERROR); + } + + $userid = isset($results['userid']) ? $results['userid'] : $user->uid; + + if (user_access('administer biblio') && count($nids) && $user->uid != $userid) { + db_update('node') + ->fields(array('uid' => $results['userid'])) + ->condition('nid', $nids, 'IN') + ->execute(); + db_update('node_revision') + ->fields(array('uid' => $results['userid'])) + ->condition('nid', $nids, 'IN') + ->execute(); + } + +} + +function biblio_import_from_url($URL) { + $handle = fopen($URL, "r"); // fetch data from URL in read mode + $data = ""; + if ($handle) { + while (!feof($handle)) { + $data .= fread($handle, 4096); // read data in chunks + } + fclose($handle); + } + else { + $errorMessage = t("Error occurred: Failed to open %url", array('%url', $URL)); // network error + drupal_set_message($errorMessage, 'error'); + } + + return $data; +} + +function biblio_export_form() { + $form['pot'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => t('POT Export'), + '#description' => t('Here you may export a ".pot" file which contains the titles and hints from the database which are not normally captured by translation extractors)') + ); + $form['pot']['button'] = array( + '#type' => 'submit', + '#value' => t('Export translation data') + ); + + return $form; +} +function biblio_export_form_submit($form, & $form_state) { + if ($form_state['values']['op'] == t('Export translation data')) { + biblio_dump_db_data_for_pot(); + } + +} + +/** + * Import data from a file and return the node ids created. + * + * @param $userid + * The user id that will be assigned to each node imported + * @param $filename + * The name of the file containing the data to import + * @param $type + * The format of the file to be imported (tagged, XML, RIS, bibTEX) + * @param $terms + * the vocabulary that the imported nodes will be associated with + * @return + * An array of node id's of the items imported + */ +function biblio_import($import_file, $type, $userid = 1, $terms = NULL, $batch = FALSE, $session_id = NULL, &$context ) { + global $user; + $parsed = 0; + $nids = array(); + $dups = array(); + + if (isset($context['message'])) $context['message'] = t('Parsing file'); + switch ($type) { + case 'csv' : // comma separated variable file + // $file_content = @ file_get_contents($import_file->uri); + // $parsed = biblio_csv_import($file_content, $node_template, $node_array); + break; + case 'biblio_backup' : // a complete backup of all biblio information + $file_content = @ file_get_contents($import_file->uri); + $parsed = biblio_restore($file_content, $node_template, $node_array); + break; + default: + list($nids, $dups) = module_invoke($type, 'biblio_import', $import_file, $terms, $batch, $session_id); + break; + } + $context['results']['nids'] = $nids; + $context['results']['dups'] = $dups; + $context['results']['format'] = $type; + $context['results']['userid'] = $userid; + $context['results']['user'] = $user; + $context['results']['file'] = $import_file; + + return $batch ? NULL : $nids; +} +/** + * Export nodes in a given file format. + * + * @param $format + * The file format to export the nodes in (tagged, XML, bibTEX) + * @param $nid + * If not NULL, then export only the given nodeid, else we will + * use the session variable which holds the most recent query. If neither + * $nid or the session variable are set, then nothing is exported + * @param $version + * The version of EndNote XML to use. There is one format for ver. 1-7 and + * a different format for versions 8 and greater. + * @return + * none + */ +function biblio_export($format = "tagged", $nid = NULL, $popup = FALSE) { + $params = array(); + $nids = array(); + $arg_list = array(); + module_load_include('inc', 'biblio', 'includes/biblio.contributors'); + if ($nid === NULL ) { + module_load_include('inc', 'biblio', 'includes/biblio.pages'); + $uri = drupal_parse_url(request_uri()); + $arg_list += $uri['query']; + $arg_list['page_limit'] = 0; + list($nids,,) = biblio_build_query($arg_list); + } + elseif (!empty ($nid)) { + $nids[] = $nid; + } + elseif (!count($nids)) { + return; + } + + module_invoke('biblio_' . $format, 'biblio_export', $nids); + +} + +/** + * Save node imported from a file. + * + * @param $node_array + * a 2 dimensional array containing all the node information + * @return + * The node ids of the saved nodes + */ +function biblio_save_imported_nodes(& $node_array) { + $dup_count = 0; + if (function_exists('node_save')) { + foreach ($node_array as $imp_node) { + $node_ids[] = biblio_save_node($imp_node); + } + } +/* if ($dup_count) + drupal_set_message(t("Detected @dupcount duplicate node(s) when importing", array('@dupcount' => $dup_count)), 'error'); + + drupal_set_message(t("Succesfully imported @count entries.", array('@count' => count($node_ids))), 'status'); +*/ + return $node_ids; +} +function biblio_save_node($node, $terms = array(), $batch = FALSE, $session_id = NULL, $save_node = TRUE) { + global $user; + + if ($batch && $session_id) { // we are batch processing some import data + $cache['session_id'] = $session_id; + $cache['data'] = base64_encode(serialize($node));// base64_encode to avoid problems unserializing strings with embeded quotes. + drupal_write_record('biblio_import_cache', $cache); + return; + } + + $node->type = 'biblio'; + // Persist the node revision log since it will be overridden by + // node_object_prepare(). + $created = !empty($node->created)? $node->created : NULL; + $revision_log = !empty($node->log)? $node->log : NULL; + node_object_prepare($node); + $node->created = $created; + $node->log = $revision_log; + + if (!empty($terms)) { + foreach ($terms as $key => $value) { + $node->{$key} = $value; + } + } + + $node->language = 'und'; //start by setting the language to undefined and then try to refine it. + if (module_exists('locale')) { + $node->language = locale_language_url_fallback(); + } + if (module_exists('i18n') && variable_get('i18n_node_biblio', 0) && variable_get('language_content_type_biblio', 0) ) { + $node->language = module_invoke('i18n', 'default_language'); + } + + if (!isset($node->biblio_type)) { + $node->biblio_type = 129; // default to misc if not set. + } + + + if ($save_node) { // $save_node = TRUE, the normal save path + $validation_errors = array(); + $validation_errors = biblio_save_node_validate($node); + node_save($node); + if (!empty($validation_errors)) { + foreach ($validation_errors as $field => $value) { + $message = $field . ' ' . t('was truncated to fit into the database column'); + $link = l('node/' . $node->nid, 'node/' . $node->nid); + drupal_set_message($message . '; ' . $link, 'warning'); + watchdog('biblio - import', $message, array(), WATCHDOG_ALERT, $link); + } + } + return; // (isset($node->nid)) ? $node->nid : 0; + } + else { // $save_node = FALSE, primarily used to parse data and return it to the input form + return (array)$node; + } +} + +function biblio_save_node_validate($node) { + static $schema = array(); + $error = array(); + + if (empty($schema)) { + $schema['biblio'] = drupal_get_schema('biblio'); + } + if (isset($node->title) && strlen($node->title) > 255) { + $error['title'] = $node->title; + $node->title = substr($node->title, 0, 255); + } + if (isset($node->biblio_keywords) && is_array($node->biblio_keywords)) { + foreach ($node->biblio_keywords as $key => $word) { + if (strlen($word) > 255) { + $error['keyword'] = $word; + $node->biblio_keywords[$key] = substr($word, 0, 255); + } + } + } + if (isset($node->biblio_contributors) && is_array($node->biblio_contributors)) { + foreach ($node->biblio_contributors as $key => $author) { + if (strlen($author['name']) > 255) { + $error['author'] = $author['name']; + $node->biblio_contributors[$key]['name'] = substr($author['name'], 0, 255); + } + } + } + foreach ($schema['biblio']['fields'] as $field => $spec) { + if (isset($node->$field)) { + switch ($spec['type']) { + case 'varchar': + if (strlen($node->$field) > $spec['length']) { + $error[$field] = $node->$field; + $node->$field = substr($node->$field, 0, $spec['length']); + } + break; + } + } + } + return $error; +} + + +function biblio_csv_export_2($result, $bfields) { + // $query_biblio_fields = 'SELECT name, title FROM {biblio_fields}'; + // $res_biblio_fields = db_query($query_biblio_fields); + // while ($rec = db_fetch_object($res_biblio_fields)) { + // $bfields[$rec->name] = $rec->title; + // } + $bfields = biblio_get_db_fields('all'); + $query_biblio_types = 'SELECT tid, name FROM {biblio_types}'; + $res_biblio_types = db_query($query_biblio_types); + foreach ($res_biblio_types as $rec) { + $btypes[$rec->tid] = $rec->name; + } + switch (variable_get('biblio_csv_field_sep', 'tab')) { + case 'tab' : + $filedsep = "\t"; + break; + case 'comma' : + $filedsep = ','; + break; + } + switch (variable_get('biblio_csv_text_sep', 'dquote')) { + case 'dquote' : + $textsep = '"'; + break; + case 'quote' : + $textsep = '\''; + break; + } + $label = (variable_get('biblio_csv_col_head', 'label') == 'label' ? 1 : 0); // or 'col_name' + $linebreak = variable_get('biblio_linebreak_exp', 1); + foreach ($result as $rec) { + $node_id = $rec->nid; + $node_array[$node_id]['type'] = $btypes[$rec->biblio_type]; // there is no "label" for "type" + $col_array['type'] = 'Type'; + foreach (array_keys($bfields) as $fieldname) { + if (!empty ($rec-> $fieldname) && !in_array($fieldname, array( + 'biblio_citekey', + 'biblio_coins' + ))) { + $col_array[$fieldname] = $bfields[$fieldname]; // mark field as in use + $text = strtr($rec-> $fieldname, $textsep, "$textsep$textsep"); + if ($linebreak) { + $text = strtr($text, ';', "\n"); + } + $node_array[$node_id][$fieldname] = trim($text); + } + } + } //end while + if ($label) { // head line containing column names + $csv = $textsep . join("$textsep$filedsep$textsep", array_values($col_array)) . "$textsep\n"; + } + else { // original DB field names + $csv = $textsep . join("$textsep$filedsep$textsep", array_keys($col_array)) . "$textsep\n"; + } + // Enclosing text in "" is neccessary to enshure + // multi line fields (like author) are handled correctly. + // Therefore existing " must be excaped before. + $csv = '"' . join("\"\t\"", array_keys($col_array)) . "\"\n"; + foreach ($node_array as $line_array) { + $csv_line = ''; + foreach (array_keys($col_array) as $col) { + $csv_line .= "$filedsep$textsep" . $line_array[$col] . $textsep; + } + $csv .= substr($csv_line, 1) . "\n"; // cut off leading fieldsep and append EOL + } + drupal_add_http_header('Content-Type', 'text/plain; charset=utf-8'); + drupal_add_http_header('Content-Disposition', 'attachment; filename=biblio_export.csv'); + return $csv; +} +//function _biblio_cck_join($biblio_fields = array()) { // works not with php4 +function _biblio_cck_join(& $biblio_fields) { + $cck_join = ''; + $biblio_fields['nid'] = 'Node-ID'; // identify records for update operations + $query_cck_fields = "SELECT field_name, label from {node_field_instance} where type_name='biblio' and not (widget_type='image')"; + $res_cck_fields = db_query($query_cck_fields); + foreach ($$res_cck_fields as $rec) { + $cck_table = 'content_' . $rec->field_name; + $cck_field = $rec->field_name . '_value'; + $biblio_fields[$cck_field] = $rec->label; + $cck_join .= ' left join {' . $cck_table . '} on b.vid=' . $cck_table . '.vid'; + } + return $cck_join; +} + +function biblio_backup() { + + $csv_function = (!function_exists('fputcsv')) ? 'biblio_fputcsv' : 'fputcsv'; + $count_sql = "SELECT COUNT(*) + FROM {biblio} b, {node} n, {node_revision} nr + WHERE b.vid = n.vid and nr.vid = n.vid;"; + $field_type_sql = "SELECT * FROM {biblio_field_type} "; + $field_type_data_sql = "SELECT * FROM {biblio_field_type_data} "; + $field_fields_sql = "SELECT * FROM {biblio_fields} "; + $types_sql = "SELECT * FROM {biblio_types} "; + $sql = "SELECT b.*, + n.type, n.language, n.title, n.uid, n.status, n.created, + n.changed, n.comment, n.promote, n.moderate, n.sticky, + n.tnid, n.translate, + nr.title, nr.body, nr.teaser, nr.log, nr.timestamp, nr.format + FROM {biblio} b, {node} n, {node_revision} nr + WHERE b.vid = n.vid and nr.vid = n.vid;"; + + $biblio_count = db_result(db_query($count_sql)); + if ($biblio_count) { + drupal_add_http_header('Content-Type', 'text/plain; charset=utf-8'); + drupal_add_http_header('Content-Disposition', 'attachment; filename=Biblio-export.csv'); + $biblio_nodes = db_query($sql); + while ($node = db_fetch_array($biblio_nodes)) { + $results[] = $node; + } + print biblio_csv_export($results); + unset($results); + $result = db_query($field_type_data_sql, 'biblio_field_type_data.csv'); + while ($data = db_fetch_array($result)) { + $results[] = $data; + } + print biblio_csv_export($results); + unset($results); + $result = db_query($field_fields_sql, 'biblio_fields.csv'); + while ($data = db_fetch_array($result)) { + $results[] = $data; + } + print biblio_csv_export($results); + unset($results); + $result = db_query($types_sql, 'biblio_types.csv'); + while ($data = db_fetch_array($result)) { + $results[] = $data; + } + print biblio_csv_export($results); + unset($results); + $result = db_query($field_type_sql, 'biblio_field_type.csv'); + while ($data = db_fetch_array($result)) { + $results[] = $data; + } + print biblio_csv_export($results); + } +} + +function biblio_restore(& $csv_content, $mode = 'create') { + +} + +function biblio_csv_export($results) { + $csv = ''; + if (!is_array($results)) { + $result_array[] = (array) $results; + } + else { + $result_array = $results; + } + $fieldnames = NULL; + foreach ((array)$result_array as $rec) { + if (empty($fieldnames)) { + $fieldnames = array_keys($rec); + $csv .= biblio_strcsv($fieldnames); + } + $csv .= biblio_strcsv($rec); + } + return $csv; +} + +function biblio_strcsv($fields = array(), $delimiter = ',', $enclosure = '"') { + $str = ''; + $escape_char = '\\'; + foreach ($fields as $value) { + if (strpos($value, $delimiter) !== FALSE || strpos($value, $enclosure) !== FALSE || strpos($value, "\n") !== FALSE || strpos($value, "\r") !== FALSE || strpos($value, "\t") !== FALSE || strpos($value, ' ') !== FALSE) { + $str2 = $enclosure; + $escaped = 0; + $len = strlen($value); + for ($i = 0; $i < $len; $i++) { + if ($value[$i] == $escape_char) { + $escaped = 1; + } + else + if (!$escaped && $value[$i] == $enclosure) { + $str2 .= $enclosure; + } + else { + $escaped = 0; + } + $str2 .= $value[$i]; + } + $str2 .= $enclosure; + $str .= $str2 . $delimiter; + } + else { + $str .= $value . $delimiter; + } + } + $str = substr($str, 0, -1); + $str .= "\n"; + return $str; +} +function biblio_dump_db_data_for_pot() { + $query = "SELECT name, description FROM {biblio_types} "; + $result = db_query($query); + $strings = array(); + foreach ($result as $type) { + $strings[] = $type->name; + if (!empty($type->description)) $strings[] = $type->description; + } + $query = "SELECT title, hint FROM {biblio_field_type_data} "; + $result = db_query($query); + foreach ($result as$type_data) { + $strings[] = $type_data->title; + if (!empty($type_data->hint)) $strings[] = $type_data->hint; + } + $query = "SELECT title, hint FROM {biblio_contributor_type_data} "; + $result = db_query($query); + foreach ($result as $type_data ) { + $strings[] = $type_data->title; + if (!empty($type_data->hint)) $type_data->hint; + } + $strings = array_unique($strings); + foreach ($strings as $string) { + $output .= "t(\"$string\"\);\n"; + } + + drupal_add_http_header('Content-Type', 'text/plain; charset=utf-8'); + drupal_add_http_header('Content-Disposition', 'attachment; filename=biblio_db_values.pot'); + print $output; +} + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/includes/biblio.keywords.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/includes/biblio.keywords.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,486 @@ +kid; + } +} +/** + * @param $name + * @return array of keywords + */ +function biblio_get_keyword_by_name($name) { + static $keywords = array(); + if (!$kid = array_search($name, $keywords)) { + $term = db_query("SELECT kd.kid, kd.word, COUNT(*) as use_count FROM {biblio_keyword_data} kd + LEFT JOIN {biblio_keyword} bk on bk.kid = kd.kid + WHERE LOWER(kd.word) = LOWER(:name) + GROUP BY kd.kid, kd.word", array(':name' => trim($name)))->fetchObject(); + if ($term) { + $keywords[$term->kid] = $term; + return $keywords[$term->kid]; + } + else { + return FALSE; + } + } + + return $keywords[$kid]; +} + +/** + * @param $kid + * @return unknown_type + */ +function biblio_get_keyword_by_id($kid) { + static $keywords = array(); + + if (!isset($keywords[$kid])) { + $keywords[$kid] = db_query('SELECT * FROM {biblio_keyword_data} WHERE kid = :kid', array(':kid' => $kid))->fetchObject(); + } + + return $keywords[$kid]; + +} + +/** + * Load keywords for a single node + * + * @param $vid + * @return keywords for a given node->vid + */ +function biblio_load_keywords($vid) { + $vids = (isset($vid) ? array($vid) : array()); + return biblio_load_keywords_multiple($vids); +} + +/** + * Load keywords for multiple nodes + * + * @param array $vids + * @return multitype: + */ +function biblio_load_keywords_multiple($vids = array()) { + $keywords = array(); + if (empty($vids)) return $keywords; + + $query = db_select('biblio_keyword', 'bk'); + $query->innerJoin('biblio_keyword_data', 'bkd', 'bk.kid = bkd.kid'); + $query->addField('bk', 'vid'); + $query->fields('bkd', array('kid', 'word')); + $query->orderby('bk.vid'); + $query->orderby('bkd.word'); + if (count($vids) == 1) { + $query->condition('bk.vid', $vids[0]); + } + else { + $query->condition('bk.vid', $vids, 'IN'); + } + $query->addMetaData('base_table', 'biblio_keyword'); + $query->addTag('node_access'); + $result = $query->execute(); + + foreach ($result as $keyword) { + $keywords[$keyword->vid][$keyword->kid] = $keyword->word; + } + + return $keywords; +} +/** + * Update the keyword database from the supplied node + * + * @param stdClass $node + * @return + * An array of keyword ID's + */ +function biblio_update_keywords($node) { + $kids = biblio_insert_keywords($node, TRUE); + return $kids; +} + +/** + * Insert keywords into the database + * + * @param $node + * A node with keywords attached + * @param $update + * Set to TRUE if you are updating an existing node + * @return + * An array of keyword ID's from this node + */ +function biblio_insert_keywords($node, $update = FALSE) { + $kw_vocab = variable_get('biblio_keyword_vocabulary', 0); + $taxo_terms = $typed_keywords = array(); + $freetag_vocab = FALSE; + if (!is_array($node->biblio_keywords)) { + $typed_keywords = biblio_explode_keywords($node->biblio_keywords); + } + else { + $typed_keywords = $node->biblio_keywords; + } + + if ($update) { + $and = db_and()->condition('nid', $node->nid) + ->condition('vid', $node->vid); + db_delete('biblio_keyword') + ->condition($and) + ->execute(); + } + + if (empty($node->biblio_keywords)) return; + + $vocabularies = module_invoke('taxonomy', 'get_vocabularies'); + $vid = variable_get('biblio_keyword_vocabulary', 0); + + if (variable_get('biblio_keyword_freetagging', 0) && $vid) { + $freetag_vocab = $vocabularies[variable_get('biblio_keyword_vocabulary', 0)]; + } + + if (isset($node->taxonomy) && is_array($node->taxonomy) && variable_get('biblio_copy_taxo_terms_to_keywords', 0)) { //add any taxonomy terms to our keyword list + foreach ($node->taxonomy as $vid => $term) { + if ($vid == 'copy_to_biblio' && $term == 0 ) {// don't copy if user overrides the default to copy, just set the $taxo_terms to an empty array and break out of the for loop + $taxo_terms = array(); + break; + } + if (is_array($term) && !empty($term)) { + foreach ($term as $tid) { + if ($tid) { + $term_obj = taxonomy_term_load($tid); + $taxo_terms[$term_obj->tid] = $term_obj->name; + } + } + } + elseif ($term) { + $term_obj = taxonomy_term_load($term); + $taxo_terms[$term_obj->tid] = $term_obj->name; + } + } + } + + $keywords = array_merge($typed_keywords, $taxo_terms); + + foreach ($keywords as $keyword) { + $word = (is_object($keyword)) ? trim($keyword->word) : trim($keyword); + if (!strlen(trim($word))) continue; //skip if we have a blank + $kid = FALSE; + // See if the term exists + if ( ($kw = biblio_get_keyword_by_name($word)) ) { + $kid = $kw->kid; + } + if (!$kid) { + $kw = array('word' => trim($word)); + $status = biblio_save_keyword($kw); + $kid = $kw['kid']; + } + // Defend against duplicate, differently cased tags + if (!isset($inserted[$kid])) { + db_merge('biblio_keyword') + ->key(array('kid' => $kid, 'vid' => $node->vid)) + ->fields( + array( + 'kid' => $kid, + 'nid' => $node->nid, + 'vid' => $node->vid + ))->execute(); + $inserted[$kid] = TRUE; + } + } + + // now if we are saving keywords into a taxonomy freetagging vocabulary, then create the tags string and add it to the node object. + $vocabularies = module_invoke('taxonomy', 'get_vocabularies'); + $vid = variable_get('biblio_keyword_vocabulary', 0); + $freetagging = variable_get('biblio_keyword_freetagging', 0); + + if ($freetagging && $vid) { + $freetag_vocab = $vocabularies[$vid]; + $term_refs = biblio_get_term_ref_fields(); + $ft_field = 'field_' . $freetag_vocab->machine_name . '_ref'; + if (!isset($term_refs[$ft_field])) { + biblio_create_term_ref($freetag_vocab); + } + } + + + if ($freetagging && $freetag_vocab ) { + $tids = array(); + $lang = isset($freetag_vocab->language) ? $freetag_vocab->language : 'und'; + if (isset($node->{$ft_field}[$lang])) { + foreach ($node->{$ft_field}[$lang] as $tag) { + $tids[] = $tag['tid']; + } + } + + if (is_array($typed_keywords) && !empty($typed_keywords)) { + $query = new EntityFieldQuery(); + $query + ->entityCondition('entity_type', 'taxonomy_term') + ->propertyCondition('vid', $vid) + ->propertyCondition('name', $typed_keywords); + + $result = $query->execute(); + + if (isset($result['taxonomy_term'])) { + $existing_tids = array_keys($result['taxonomy_term']); + $existing_terms = taxonomy_term_load_multiple($existing_tids); + $existing_words = array(); + foreach ($existing_terms as $term) { + $existing_words[$term->name] = $term; + } + } + } + + foreach ($typed_keywords as $kw) { + if (isset($existing_words[$kw])) { + $term = $existing_words[$kw]; + } + else { + $term = new stdClass(); + $term->vid = $freetag_vocab->vid; + $term->name = $kw; + $term->vocabulary_machine_name = $freetag_vocab->machine_name; + taxonomy_term_save($term); + } + if (!in_array($term->tid, $tids)) { + $node->{$ft_field}[$lang][] = (array)$term; + } + } + } + + return array_keys($inserted); +} +/** + * @param $word + * @return + */ +function biblio_save_keyword(&$keyword) { + if (!empty($keyword['kid']) && $keyword['word']) { + drupal_write_record('biblio_keyword_data', $keyword, 'kid'); + $status = SAVED_UPDATED; + } + else { + drupal_write_record('biblio_keyword_data', $keyword); + $status = SAVED_NEW; + } + + return $status; +} + +/** + * @return multitype: + */ +function biblio_get_orphaned_keyword_ids() { + $orphans = $active_kids = $all_kids = array(); + + $query = db_select('biblio_keyword', 'bk'); + $active_kids = $query + ->fields('bk', array('kid')) + ->groupBy('kid') + ->execute() + ->fetchCol(); + + $query = db_select('biblio_keyword_data', 'bkd'); + $all_kids = $query + ->fields('bkd', array('kid')) + ->execute() + ->fetchCol(); + + $orphans = array_diff($all_kids, $active_kids); + + return $orphans; +} + +/** + * Deletes orphaned keywords + * + * Deletion only occurs if the Drupal Variable "biblio_keyword_orphan_autoclean" + * is true OR if the $force argument is TRUE + * + * @param bool $force + * Forces deletion to occur even if autoclean is turned off + * @return int $count + * The number of orphans removed + */ +function biblio_delete_orphan_keywords($force = FALSE) { + $count = 0; + + if (variable_get('biblio_keyword_orphan_autoclean', 0) || $force) { + $orphans = biblio_get_orphaned_keyword_ids(); + if (!empty($orphans)) { + $count = db_delete('biblio_keyword_data') + ->condition('kid', $orphans, 'IN') + ->execute(); + } + } + return $count; +} + +/** + * Delete all keywords references for a given node. + * + * The actual keywords remain in the biblio_keyword_data table + * + * @param $node + * @return + * The number of links removed + */ +function biblio_delete_keywords($node) { + $count = db_delete('biblio_keyword') + ->condition('nid', $node->nid) + ->execute(); + return $count; +} + +/** + * Delete "node revision to keyword" links from the biblio_keyword table + * + * @param $node + * @return + * The number of links removed + */ +function biblio_delete_revision_keywords($node) { + return db_delete('biblio_keyword') + ->condition('vid', $node->vid) + ->execute(); +} + +/** + * Delete multiple keywords. + * + * Removes from both the biblio_keyword and biblio_keyword_data tables + * This will remove the keywords referenced by the supplied ID's from + * ALL nodes which reference them. + * + * @param array $keywords + * An array of keyword id's to delete + * @return + * The number of keywords deleted + */ +function biblio_delete_multiple_keywords($keywords) { + $count = 0; + foreach ($keywords as $kid) { + $count += biblio_delete_keyword($kid); + } + return $count; +} +/** + * Delete a keyword from both the biblio_keyword and biblio_keyword_data tables + * This will remove the keyword referenced by the supplied ID from ALL nodes which reference them. + * + * @param $keyword_id + * The keyword id to delete + * @return + * The number of keywords deleted (should always be one) + */ +function biblio_delete_keyword($keyword_id) { + db_delete('biblio_keyword') + ->condition('kid', $keyword_id) + ->execute(); + + return db_delete('biblio_keyword_data') + ->condition('kid', $keyword_id) + ->execute(); +} + +/** + * @param unknown_type $string + * @return multitype:string + */ +function biblio_explode_keywords($string) { + $sep = variable_get('biblio_keyword_sep', ','); + $regexp = '%(?:^|' . $sep . '\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^"' . $sep . ']*))%x'; + preg_match_all($regexp, $string, $matches); + $keyword_array = array_unique($matches[1]); + + $keywords = array(); + foreach ($keyword_array as $keyword) { + // If a user has escaped a term (to demonstrate that it is a group, + // or includes a comma or quote character), we remove the escape + // formatting so to save the term into the database as the user intends. + $keyword = trim(str_replace('""', '"', preg_replace('/^"(.*)"$/', '\1', $keyword))); + if ($keyword != "") { + $keywords[] = $keyword; + } + } + return $keywords; +} +/** + * @param unknown_type $keywords + * @param unknown_type $sep + * @return Ambigous + */ +function biblio_implode_keywords($keywords, $sep = '') { + + if (empty($sep)) $sep = variable_get('biblio_keyword_sep', ','); + $string = ''; + foreach ($keywords as $kid => $keyword) { + $string .= strlen($string)?"$sep ":''; + if (strpos($keyword, $sep) !== FALSE) { + $string .= '"' . $keyword . '"'; + } + else { + $string .= $keyword; + } + } + return $string; +} + +function biblio_get_term_ref_fields() { + $termfields = array(); + foreach (field_info_instances('node', 'biblio') as $instance) { + $field = field_info_field_by_id($instance['field_id']); + if ($field['type'] == 'taxonomy_term_reference') { + $termfields[$field['field_name']] = $instance['label']; + } + } + return $termfields; +} + +function biblio_create_term_ref($vocabulary) { + $field_name = 'field_' . $vocabulary->machine_name . '_ref'; + + $field = array( + 'field_name' => $field_name, + 'type' => 'taxonomy_term_reference', + 'cardinality' => FIELD_CARDINALITY_UNLIMITED, + 'settings' => array( + 'allowed_values' => array( + array( + 'vocabulary' => $vocabulary->machine_name, + 'parent' => 0 + ), + ), + ), + ); + + field_create_field($field); + + + $instance = array( + 'field_name' => $field_name, + 'entity_type' => 'node', + 'label' => $vocabulary->name, + 'bundle' => 'biblio', + 'required' => FALSE, + 'widget' => array( + 'type' => 'options_select', + 'cardinality' => -1 + ), + 'display' => array( + 'default' => array('type' => 'hidden'), + 'teaser' => array('type' => 'hidden') + ) + ); + + field_create_instance($instance); +} \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/includes/biblio.pages.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/includes/biblio.pages.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1342 @@ +data['biblio_contributor_id']) && $user->data['biblio_contributor_id'] > 0 ) { + $arg_list = array( + 'f' => array( + 'author' => $user->data['biblio_contributor_id'], + ), + ); + } + elseif (isset($user->data['biblio_lastname']) && !empty($user->data['biblio_lastname'])) { + $arg_list = array( + 'f' => array( + 'author' => $user->data['biblio_lastname'], + ), + ); + } + else { + $arg_list = array( + 'f' => array( + 'uid' => $user->uid + ), + ); + } + $arg_list['page_limit'] = variable_get('biblio_rowsperpage', 25); + + list($nids, $extras, $rss_info) = biblio_build_query($arg_list); + + $render['biblio_page']['profile'] = biblio_page_content($nids, $extras); + + return $render; +} + +function biblio_page() { + $nodes = $nids = $extras = $rss_info = $info = $arg_list = $render = array(); + $base = variable_get('biblio_base', 'biblio'); + + $info['func_args'] = func_get_args(); + $info['uri'] = drupal_parse_url(request_uri()); + $arg_list = biblio_arg_handler($info); + $arg_list['page_limit'] = variable_get('biblio_rowsperpage', 25); + + list($nids, $extras, $rss_info) = biblio_build_query($arg_list); + if ($rss_info['feed']) { + biblio_filter_feed($rss_info, $nids); + return; + } + + if (variable_get('biblio_rss', 0)) { + drupal_add_html_head_link(array( + 'rel' => 'alternate', + 'type' => 'application/rss+xml', + 'title' => variable_get('site_name', 'Drupal') . ' RSS', + 'href' => url("$base/rss.xml") + )); + } + + drupal_set_title(t(check_plain(variable_get('biblio_base_title', 'Biblio')))); + $filter = (isset($arg_list['f'])) ? array('f' => $arg_list['f']) : array(); + + $render['biblio_page']['header'] = biblio_page_header($filter); + $render['biblio_page']['content'] = biblio_page_content($nids, $extras); + + // if no content AND we have a filter give a hint on what to do... + if (isset($render['biblio_page']['content']['section_0']) && !empty($render['biblio_page']['header']['filter_status'])) { + $render['biblio_page']['content']['hint']['#markup'] = t('!modify_link or !remove_link your filters and try again.', array('!modify_link' => l(t('Modify'), "$base/filter"), '!remove_link' => l(t('remove'), "$base/filter/clear"))); + } + + return $render; +} +function biblio_page_header($filter = array()) { + $header = array(); + $header = array( + '#prefix' => '
', + '#suffix' => '
', + '#weight' => -100, + ); + + // Search box. Has same permissions as the filter tab. + if (variable_get('biblio_search', 0) && user_access('show filter tab')) { + $header += array( + 'search_form' => drupal_get_form('biblio_search_form'), + ); + } + $header += array( + 'export_links' => array( + '#prefix' => '
', + '#node' => NULL, + '#filter' => $filter, + '#theme' => 'biblio_export_links', + '#suffix' => '
', + ), + ); + + if ( !biblio_access('export')) { + global $pager_total_items; + $header['export_links']['#markup'] = t('Found @count results', array('@count' => $pager_total_items[0])); + unset($header['export_links']['#theme']); + } + // Add some links to the top of the page to change the sorting/ordering... + if (user_access('show sort links')) { + $header += array( + 'sort_links' => array( + '#markup' => theme('biblio_sort_tabs') + ), + ); + } + $header += array( + 'filter_status' => array( + '#prefix' => '
', + '#suffix' => '
', + '#markup' => _biblio_filter_info_line($filter), + ), + ); + if (isset($_GET['s'])) { + if ( $_GET['s'] == 'title' || + $_GET['s'] == 'author' || + $_GET['s'] == 'keyword') { + if (strpos($_GET['q'], 'ag') || + strpos($_GET['q'], 'tg') || + strpos($_GET['q'], 'keyword')) { + $value = substr($_GET['q'], strrpos($_GET['q'], '/') + 1); + } + else { + $value = ''; + } + $header += array( + 'alpha_line' => array( + '#prefix' => '
', + '#suffix' => '
', + '#markup' => theme('biblio_alpha_line', array( + 'type' => $_GET['s'], + 'current' => $value, + 'path' => variable_get('biblio_base', 'biblio')) + ), + ), + ); + } + } + + return $header; +} + +function biblio_page_content($nids = array(), $extras = array()) { + $base = variable_get('biblio_base', 'biblio'); + $content = $raw_nodes = $nodes = array(); + $count = $section_id = 0; + + if (module_exists('popups')) { + popups_add_popups(); + } + + if (count($nids)) { + // $nids = array_unique($nids); + $raw_nodes = node_load_multiple($nids); + $langcode = $GLOBALS['language_content']->language; + field_attach_prepare_view('node', $raw_nodes, 'biblio_list', $langcode); + entity_prepare_view('node', $raw_nodes, $langcode); + + foreach ($nids as $key => $nid) { + if (!empty($extras)) { + $nodes[] = (object)array_merge((array)$raw_nodes[$nid], (array)$extras[$key]); + } + else { + $nodes[] = $raw_nodes[$nid]; + } + } + + } + + foreach ($nodes as $node) { + $count++; + if (is_array($node)) $node = (object)$node; + if (variable_get('biblio_hide_bibtex_braces', 0)) $node->title = biblio_remove_brace($node->title); + + // output new section if needed + if ($section = biblio_category_section($node)) { + $section_id++; + $content['section_'.$section_id] = $section; + } + + $content['section_'.$section_id][] = biblio_entry($node); + + } + + $content['pager']['#markup'] = theme('pager'); + if ($count == 0) { + $content['section_0']['#markup'] = "

" . t("No items found") . "

"; + } + return $content; +} + +function biblio_entry($node) { + $entry = array(); + $style = biblio_get_style(); + + /* + $select_box = array( + '#type' => 'checkbox', + '#return_value' => $node->nid, + '#default_value' => 0, + '#attributes' => array('class' => array('biblio-export-selector'),) + + ); +*/ + $prefix = '
'; + $suffix = '
'; + if (!$node->status) { + $prefix .= '
'; + $suffix .= '
'; + } +// $prefix .= theme('checkbox', array('element' => $select_box)); + + $entry = array( + '#prefix' => $prefix, + '#suffix' => $suffix, + ); + + $entry['entry']['#markup'] = theme('biblio_style', array('node' => $node, 'style_name' => $style)); + + $annotation_field = variable_get('biblio_annotations', 'none'); + if ($annotation_field != 'none' && $node-> $annotation_field) { + $entry['annotation'] = array( + '#prefix' => '
', + '#markup' => filter_xss($node->$annotation_field, biblio_get_allowed_tags()), + '#suffix' => '
', + ); + } + + $openurl_base = variable_get('biblio_baseopenurl', ''); + + if ($openurl_base) { + $entry['openurl'] = array( + '#markup' => theme('biblio_openurl', array('openURL' => biblio_openurl($node))), + ); + } + + if (biblio_access('export')) { + $base = variable_get('biblio_base', 'biblio'); + $entry['export_links'] = array( + '#markup' => theme('biblio_export_links', array('node' => $node)), + ); + } + + if (biblio_access('download', $node)) { + // add links to attached files (if any) + $entry['download_links'] = array( + '#markup' => theme('biblio_download_links', array('node' => $node)), + ); + } + + return $entry; +} + +/* + * biblio_db_search builds the SQL query which will be used to + * select and order "biblio" type nodes. The query results are + * then passed to biblio_show_results for output + * + * + */ +function biblio_build_query($arg_list) { + global $user; + static $bcc = 0; //biblio_contributor (bc) count , increase for every invocation + static $bkd = 0; + static $tcc = 0; //term counter, increase for every invocation + $rss_info['feed'] = FALSE; + $rss_info['title'] = variable_get('biblio_base_title', 'Biblio'); + $rss_info['link'] = ''; + $rss_info['description'] = ''; + + if ($arg_list['page_limit'] > 0) { + $query = db_select('node', 'n')->extend('PagerDefault'); + $query->limit($arg_list['page_limit']); + } + else { + $query = db_select('node', 'n'); + } + + //add a tag of "node_access" to ensure that only nodes to which the user has access are retrieved + $query->addTag('node_access'); + + $query->addField('n', 'nid'); + $type_name = $query->addField('bt', 'name', 'biblio_type_name'); + $query->leftJoin('biblio', 'b', 'n.vid=b.vid'); + $query->innerJoin('biblio_types', 'bt', 'b.biblio_type=bt.tid'); +// $query->distinct(); + + // POSIX regular expression matching, case insensitive + $match_op = (db_driver() == 'pgsql') ? '~*' : 'RLIKE'; + + $limit = ''; + if (variable_get('biblio_view_only_own', 0) ) { + $limit .= " AND n.uid = $user->uid "; + } + + if (isset($arg_list['s']) || isset($arg_list['sort'])) { + $sort = isset($arg_list['s']) ? $arg_list['s'] : $arg_list['sort']; + unset($arg_list['s']); + unset($arg_list['sort']); + } + else { + $sort = variable_get('biblio_sort', 'year'); + } + + if (isset($arg_list['o']) || isset($arg_list['order'])) { + if (isset($arg_list['o'])) { + $order = (strcasecmp($arg_list['o'], 'ASC')) ? 'DESC' : 'ASC'; + unset($arg_list['o']); + } + if (isset($arg_list['order'])) { + $order = (strcasecmp($arg_list['order'], 'ASC')) ? 'DESC' : 'ASC'; + unset($arg_list['order']); + } + } + else { + $order = strtolower(variable_get('biblio_order', 'DESC')); + } + +/* if (!isset($_SESSION['biblio_filter']) || !is_array($_SESSION['biblio_filter'])) { + $_SESSION['biblio_filter'] = array(); + } + + $session = &$_SESSION['biblio_filter']; + + if (!in_array('no_filters', $arg_list)) { + foreach ($session as $filter) { + $arg_list = array_merge($arg_list, $filter); + } + } +*/ + + + switch ($sort) { + case 'type': + //$sortby = "ORDER BY bt.name %s, b.biblio_year DESC "; + $query->addField('n', 'title'); + $query->orderBy($type_name, $order); + $query->orderBy('biblio_sort_title', $order); + break; + case 'title': + $query->addField('n', 'title'); + $query->orderBy('biblio_sort_title', $order); + break; + case 'author': + //$last_name = $query->addField('bcd', 'lastname'); + $query->innerJoin('biblio_contributor', 'bc', 'b.vid = bc.vid'); + $query->join('biblio_contributor_data', 'bcd', 'bc.cid = bcd.cid'); + $query->condition('bc.rank', 0); + $query->addField('bcd', 'lastname'); + $query->orderBy('bcd.lastname', $order); + // $query->condition('bc.auth_category', 1); + break; + case 'keyword': // added msh 070808 + $word = $query->addField('bkd', 'word', 'biblio_keyword'); + $query->orderBy($word, $order); + $query->innerJoin('biblio_keyword', 'bk', 'b.vid = bk.vid'); + $query->innerJoin('biblio_keyword_data', 'bkd', 'bk.kid = bkd.kid'); + break; + case 'year': + default: + $query->addField('b', 'biblio_year'); + $query->addField('b', 'biblio_date'); + $query->orderBy('biblio_year', $order); + $query->orderBy('biblio_sort_title'); + } //end switch + + + if (isset($arg_list['f']) && count($arg_list['f']) ) { + $fields = biblio_get_db_fields(); + foreach ($arg_list['f'] as $type => $value) { + $tables = array_keys($query->getTables()); + switch ($type) { + case 'no_filters': + break; + case 'rss.xml': + $rss_info['feed'] = TRUE; + $query->limit(variable_get('biblio_rss_number_of_entries', 10)); + break; + case 'term': + case 'term_id': + $query->innerJoin('taxonomy_index', "ti$tcc", "n.nid = ti$tcc.nid"); + if ($type == 'term') { + $query->innerJoin('taxonomy_term_data', 'td', "ti$tcc.tid = td.tid"); + $query->condition('td.name', $value); + } + elseif ($type == 'term_id') { + $query->condition("ti$tcc.tid", $value); + } + $tcc++; + break; + case 'tg': + $query->where("UPPER(substring(biblio_sort_title,1 ,1)) = :letter", array(':letter' => $value)); + break; + case 'ag': //selects entries whoose authors firstname starts with the letter provided + $query->where(" UPPER(substring(bcd.lastname,1,1)) = :letter ", array(':letter' => $value)); + //$where['bc-rank'] = "bc.rank=0"; + if ($sort != 'author') { + $query->innerJoin('biblio_contributor', 'bc', 'b.vid = bc.vid'); + $query->innerJoin('biblio_contributor_data', 'bcd', 'bc.cid = bcd.cid'); + } + break; + case 'cid': + case 'aid': + $bcc++; + $query->innerJoin('biblio_contributor', "bc$bcc", "n.vid = bc$bcc.vid"); + $query->condition("bc$bcc.cid", $value); + break; + case 'author': + module_load_include('inc', 'biblio', 'includes/biblio.contributors'); + $bcc++; + if (array_search('bc', $tables) === FALSE) { + $query->innerJoin('biblio_contributor', 'bc', 'n.vid = bc.vid'); + } + if (is_numeric($value)) { + $cids = biblio_get_linked_contributors($value); + $cids[] = $value; + $cid_count = 0; + $or = db_or(); + + foreach ($cids as $cid) { + $or->condition("bc.cid", $cid); + $cid_count++; + } + + if ($cid_count == 0) { + $query->condition("bc.cid", -1); + } + else { + $query->condition($or); + } + + } + else { + if (array_search('bcd', $tables) === FALSE) { + $query->innerJoin('biblio_contributor_data', 'bcd', 'bcd.cid = bc.cid'); + } + $query->condition('bcd.name', "[[:<:]]" . $value . "[[:>:]]", $match_op); + $rss_info['title'] = t("Publications by @value", array('@value' => $value)); + $rss_info['description'] = t("These publications by %author are part of the works listed at %sitename", array('%author' => $value, '%sitename' => variable_get('site_name', 'Drupal'))); + $rss_info['link'] = '/author/' . $value; + } + break; + case 'publisher': + $query->condition('b.biblio_publisher', "[[:<:]]" . $value . "[[:>:]]", $match_op); + break; + case 'year': + $query->condition('b.biblio_year', $value); + break; + case 'uid': + $query->addField('n', 'uid'); + $query->condition('n.uid', $value); + break; + case 'keyword': + $bkd++; + if (array_search('bk', $tables) === FALSE) { + $query->innerJoin('biblio_keyword', 'bk', 'n.vid = bk.vid'); + } + if (is_numeric($value)) { + $query->condition('bk.kid', $value); + } + else{ + if (array_search('bkd', $tables) === FALSE) { + $query->innerJoin('biblio_keyword_data', 'bkd', 'bkd.kid = bk.kid'); + } + if (strlen($value) == 1) { + // $query->condition('', $value, 'SUBSTR(bkd.word, 1, 1) ='); + $query->where(" UPPER(substring(bkd.word,1,1)) = :letter ", array(':letter' => $value)); + } + else { + $query->condition('bkd.word', "[[:<:]]" . $value . "[:>:]]", 'LIKE'); + } + $rss_info['title'] = t("Keyword @value", array('@value' => $value)); + $rss_info['description'] = t("These publications, containing the keyword: %keyword, are part of the works listed at %sitename", array('%keyword' => $value, '%sitename' => variable_get('site_name', 'Drupal'))); + $rss_info['link'] = '/keyword/' . $value; + } + break; + case 'citekey': + $query->condition('b.biblio_citekey', $value); + break; + case 'type': + $query->condition('b.biblio_type', $value); + break; + case 'search': + $search_nids = array(); + $search_nids = biblio_search_query($value); + if (empty($search_nids)) { + $search_nids[] = -1; // if we didn't find anything, then add one value of -1 since there will never be a node id == -1 + } + $query->condition('n.nid', $search_nids, 'IN'); + break; + default: + if (in_array("biblio_$type", $fields)) { + $query->condition("b.biblio_$type ", $value, 'LIKE'); + } + break; + } + } + } + + // show unpublished nodes to users with uid = 1 or with 'Administer Biblio' permissions + if ($user->uid != 1 && !biblio_access('admin')) { + $query->condition('n.status', 1); + } + + $result = $query->execute(); + $nids = array(); + $extras = array(); + + foreach ($result as $node) { + $nids[] = $node->nid; + if (isset($node->biblio_year)) unset($node->biblio_year); + $extras[] = $node; + } + + return array($nids, $extras, $rss_info); + +} + +function _biblio_filter_info_line($args = array()) { + $content = ''; + $filtercontent = ''; + $search_content = ''; + $base = variable_get('biblio_base', 'biblio'); + $session = &$_SESSION['biblio_filter']; + // if there are any filters in place, print them at the top of the list + $uri = drupal_parse_url(request_uri()); + $uri['path'] = variable_get('biblio_base', 'biblio'); + $filters = isset($uri['query']['f']) ? $uri['query']['f'] : (isset($args['f'])? $args['f']: array()); + if (count($filters)) { + $i = 0; + foreach ($filters as $type => $value) { + if ($type == 'search') { + $search_content = $value; + continue; + } + if ($type == 'term_id') { + $term = taxonomy_term_load($value); + $value = $term->name; + $type = t("Taxonomy term"); + } + if ($type == 'keyword') { + module_load_include('inc', 'biblio', 'includes/biblio.keywords'); + $type = t("Keyword"); + if (is_numeric($value)) { + $term = biblio_get_keyword_by_id($value); + if (isset($term->word)) { + $value = $term->word; + } + } + elseif (is_string($value) && strlen($value) == 1) { + $type = t("First letter of keyword"); + } + } + if ($type == 'uid' ) { + $user = user_load($value); + $value = $user->name; + $type = t("Drupal user"); + } + if ($type == 'aid' || ($type == 'author' && is_numeric($value))) { + module_load_include('inc', 'biblio', 'includes/biblio.contributors'); + $author = biblio_get_contributor($value); + $value = isset($author->name) ? $author->name : t('Unknown Author'); + $type = t("Author"); + } + if ($type == 'ag' ) { + //return; + $type = t("First letter of last name"); + } + if ($type == 'tg' ) { + //return; + $type = t("First letter of title"); + } + if ($type == 'type' && $value > 0) { + if (($pub_type = db_query('SELECT t.* FROM {biblio_types} as t WHERE t.tid=:tid', array(':tid' => $value))->fetchObject())) { + $value = drupal_ucfirst(_biblio_localize_type($pub_type->tid, $pub_type->name)); + $type = t("Type"); + } + } + $params = array('%a' => check_plain(ucwords($type)) , '%b' => check_plain($value) ); + $filtercontent .= ($i++ ? t(' and %a is %b', $params) : t('%a is %b', $params)) ; + } + if ($search_content) { + $content .= '
' . t('Search results for') . ''; + $content .= ' ' . check_plain($search_content) . ''; + if ($filtercontent) { + $content .= '
' . t('Filters') . ': '; + } + } + else { + $content .= '
' . t('Filters') . ': '; + } + $content .= $filtercontent; + + $link_options = array(); + if (isset($_GET['s'])) { + $link_options['query']['s'] = $_GET['s']; + } + if (isset($_GET['o'])) { + $link_options['query']['o'] = $_GET['o']; + } + unset($uri['query']['f']); + if ($search_content) { + $content .= '  ' . l('[' . t('Reset Search') . ']', "$base/filter/clear", $link_options); + } + else { + $content .= '  ' . l('[' . t('Clear All Filters') . ']', "$base/filter/clear", $uri); + } + $content .= '
'; + } + + return $content; +} + +function _biblio_category_separator_bar($node, $reset = FALSE) { + $_text = &drupal_static(__FUNCTION__, ''); + if ($reset) { + $_text = &drupal_static(__FUNCTION__, '', TRUE); + return; + } + $content = ''; + + if (isset($_GET['s'])) { + $sort = $_GET['s']; + } + else { + $sort = variable_get('biblio_sort', 'year'); + } + + switch ($sort) { + case 'title': + $title = $node->biblio_sort_title; + $first = drupal_substr(drupal_ucfirst(ltrim($title)), 0, 1); + if ( $first != $_text) { + if ($_text != '' ) { + $content .= theme_biblio_end_category_section(); + } + $_text = $first ; + $content .= theme_biblio_separator_bar($_text); + } + break; + case 'author': + if ( (isset($node->biblio_contributors[0]['lastname'])) && + (drupal_substr(drupal_ucfirst(ltrim($node->biblio_contributors[0]['lastname'])), 0, 1) != $_text)) + { + if ($_text != '' ) { + $content .= theme_biblio_end_category_section(); + } + $_text = drupal_substr(drupal_ucfirst(ltrim($node->biblio_contributors[0]['lastname'])), 0, 1) ; + $content .= theme_biblio_separator_bar($_text); + } + break; + case 'type': + if ($node->biblio_type_name != $_text) { + if ($_text != '' ) { + $content .= theme_biblio_end_category_section(); + } + $_text = $node->biblio_type_name; + // $name = db_result(db_query("SELECT name FROM {biblio_types} as t where t.tid=%d", $node->biblio_type)) ; + $content .= theme_biblio_separator_bar(_biblio_localize_type($node->biblio_type, $_text)); + } + break; + case 'keyword': // added msh 08 aug 07 + // $kw = array_shift($node->biblio_keyword); + $tok = $node->biblio_keyword; + if (empty($tok)) { + $tok = t("No Keywords"); + } + if ($tok != $_text) { + if ($_text != '' ) { + $content .= theme_biblio_end_category_section(); + } + $_text = $tok; + if ($_text != '') { + $content .= theme_biblio_separator_bar($_text); + } + } + break; + case 'year': + default: + if ($node->biblio_year != $_text) { + if ($_text != '' ) { + $content .= theme_biblio_end_category_section(); + } + $_text = $node->biblio_year; + $content .= theme_biblio_separator_bar($_text); + } + } //end switch + return $content; +} +function biblio_category_section($node, $reset = FALSE) { + $_text = &drupal_static(__FUNCTION__, ''); + if ($reset) { + $_text = &drupal_static(__FUNCTION__, '', TRUE); + return; + } + + $section = array(); + + if (isset($_GET['s'])) { + $sort = $_GET['s']; + } + else { + $sort = variable_get('biblio_sort', 'year'); + } + + switch ($sort) { + case 'title': + $title = $node->biblio_sort_title; + $first = drupal_substr(drupal_ucfirst(ltrim($title)), 0, 1); + if ( $first != $_text) { + $_text = $first ; + $section['bar'] = biblio_section_bar($_text); + } + break; + case 'author': + if ( (isset($node->biblio_contributors[0]['lastname'])) && + (drupal_substr(drupal_ucfirst(ltrim($node->biblio_contributors[0]['lastname'])), 0, 1) != $_text)) + { + $_text = drupal_substr(drupal_ucfirst(ltrim($node->biblio_contributors[0]['lastname'])), 0, 1) ; + $section['bar'] = biblio_section_bar($_text); + } + break; + case 'type': + if ($node->biblio_type_name != $_text) { + $_text = $node->biblio_type_name; + // $name = db_result(db_query("SELECT name FROM {biblio_types} as t where t.tid=%d", $node->biblio_type)) ; + $section['bar'] = biblio_section_bar(_biblio_localize_type($node->biblio_type, $_text)); + } + break; + case 'keyword': // added msh 08 aug 07 + // $kw = array_shift($node->biblio_keyword); + $tok = $node->biblio_keyword; + if (empty($tok)) { + $tok = t("No Keywords"); + } + if ($tok != $_text) { + $_text = $tok; + if ($_text != '') { + $section['bar'] = biblio_section_bar($_text); + } + } + break; + case 'year': + default: + if ($node->biblio_year != $_text) { + $_text = $node->biblio_year; + $section['bar'] = biblio_section_bar($_text); + } + } //end switch + if (!empty($section)) { + $section += array( + '#prefix' => '
', + '#suffix' => '
', + ); + } + return $section; +} + +function biblio_section_bar($text) { + return array( + '#prefix' => '
', + '#suffix' => '
', + '#markup' => check_plain($text), + ); +} + +/** + * Add a search field on the main biblio page. + */ +/** + * @param $form_state + * @return unknown_type + */ +function biblio_search_form($form, &$form_state) { + $base = variable_get('biblio_base', 'biblio'); + $searchform['biblio_search'] = array( + '#prefix' => '', + ); + $searchform['biblio_search']['keys'] = array( + '#type' => 'textfield', + '#title' => '', + '#default_value' => '', + '#size' => 25, + '#maxlength' => 255, + ); + $button_text = variable_get('biblio_search_button_text', 'Biblio search'); + $searchform['biblio_search']['submit'] = array( + '#type' => 'submit', + '#value' => t($button_text) + ); + + $form['search_form'] = array( + '#type' => 'fieldset', + '#title' => t('Search'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + 'searchform' => $searchform, + 'filterform' => biblio_form_filter(), + ); + + return $form; +} + +function biblio_search_form_submit($form, &$form_state) { + static $keys = ''; + $base = variable_get('biblio_base', 'biblio'); + $keys = trim($form_state['values']['keys']); + if (!empty($keys)) { + $uri = drupal_parse_url(request_uri()); + $uri['path'] = variable_get('biblio_base', 'biblio'); + $uri['query']['f']['search'] = $keys; + $form_state['redirect'] = array($uri['path'], $uri); + } + +} + +function biblio_search_query($keys) { + if (!empty($keys)) { + $query = db_select('search_index', 'i', array('target' => 'slave')) + ->extend('SearchQuery'); + // ->extend('PagerDefault'); + $query->join('node', 'n', 'n.nid = i.sid'); + $query->condition('n.status', 1) + ->addTag('node_access') + ->searchExpression($keys, 'node'); + + // Insert special keywords. + $query->setOption('type', 'n.type'); + $query->setOption('language', 'n.language'); + if ($query->setOption('term', 'ti.tid')) { + $query->join('taxonomy_index', 'ti', 'n.nid = ti.nid'); + } + // Only continue if the first pass query matches. + if (!$query->executeFirstPass()) { + return array(); + } + + // Add the ranking expressions. + _node_rankings($query); + + // Load results. + $find = $query->execute(); + + $nids = array(); + foreach ($find as $item) { + $nids[] = $item->sid; + } + return $nids; + } +} + + /** + * @param $arg + * @return unknown_type + */ +function _get_biblio_search_filter($arg = 'keys') { + if (variable_get('biblio_search', 0) && + !empty($_SESSION['biblio_filter']) && + is_array($_SESSION['biblio_filter']) && + is_array($_SESSION['biblio_filter'][0]) && + in_array('search', $_SESSION['biblio_filter'][0]) + ) { + switch ($arg) { + case 'keys': return $_SESSION['biblio_filter'][0][2]; break; + case 'nodelist': return $_SESSION['biblio_filter'][0][1]; break; + } + } +} + + +function _get_biblio_filters() { + + $fields = " b.biblio_year, t.name , t.tid "; + $order = " b.biblio_year DESC"; + $taxo_fields = "td.name as termname, td.tid as taxid, v.name as vocab_name"; + $taxo_order = "vocab_name ASC, termname ASC"; + $table = "{node} as n inner join {biblio} as b on n.vid=b.vid "; + $join = "left join {biblio_types} as t on b.biblio_type = t.tid"; + $taxo_join = array("inner join {taxonomy_index} as ti on n.nid = ti.nid", + "left join {taxonomy_term_data} as td on ti.tid = td.tid", + "left join {taxonomy_vocabulary} as v on v.vid = td.vid"); + + $taxo_joins = implode(' ', $taxo_join); + + $result = db_query("SELECT $fields FROM $table $join ORDER BY $order"); + $authors = db_query("SELECT DISTINCT firstname, initials, lastname, bcd.cid + FROM {biblio_contributor_data} as bcd + INNER JOIN {biblio_contributor} as bc on bc.cid = bcd.cid + ORDER BY lastname ASC"); + $keywords = db_query("SELECT word, kid FROM {biblio_keyword_data} ORDER BY word ASC"); + $taxoresult = db_query("SELECT $taxo_fields FROM $table $taxo_joins ORDER BY $taxo_order"); + $pub_years['any'] = t('any'); + $pub_type['any'] = t('any'); + $pub_authors['any'] = t('any'); + $pub_keywords['any'] = t('any'); + $pub_taxo['any'] = t('any'); + foreach ($result as $option) { + if (isset ($option->biblio_year)) { + $option->biblio_year = _biblio_text_year($option->biblio_year); + } + $pub_years[$option->biblio_year] = $option->biblio_year; + $pub_type[$option->tid] = _biblio_localize_type($option->tid, $option->name); + } + + foreach ($authors as $auth) { + $pub_authors[$auth->cid] = $auth->lastname . ((!empty($auth->firstname) || !empty($auth->initials))?', ' . $auth->firstname . ' ' . $auth->initials :''); + } + foreach ($keywords as $keyword) { + $pub_keywords[$keyword->kid] = $keyword->word; + } + foreach ($taxoresult as $tax) { + $pub_taxo["$tax->taxid"] = "$tax->vocab_name - $tax->termname"; + } + $author_select = isset($pub_authors) ? array('title' => t('Author'), 'options' => $pub_authors) : NULL; + $years_select = isset($pub_years) ? array('title' => t('Year'), 'options' => array_unique($pub_years)) : NULL; + $type_select = isset($pub_type) ? array('title' => t('Type'), 'options' => array_unique($pub_type)) : NULL; + $tax_select = isset($pub_taxo) ? array('title' => t('Term'), 'options' => array_unique($pub_taxo)) : NULL; + $keyword_select = isset($pub_keywords) ? array('title' => t('Keyword'), 'options' => $pub_keywords) : NULL; + + $filters = array( + 'author' => $author_select, + 'type' => $type_select, + 'term_id' => $tax_select, + 'year' => $years_select, + 'keyword' => $keyword_select, + ); + + return $filters; +} + +/** + * @return unknown_type + */ +function biblio_form_filter() { + $session = isset($_SESSION['biblio_filter']) ? $_SESSION['biblio_filter'] : array(); + $filters = _get_biblio_filters(); + + $i = 0; + $form['filters'] = array( + '#type' => 'fieldset', + '#title' => t('Show only items where'), + '#theme' => 'exposed_filters__node', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + + foreach ($session as $filter) { + $type = key($filter); + $value = $filter[$type]; + // list($type, $value) = $filter; + if ($type == 'search') { + $session = array(); + break; + } + if ($type == 'category') { + // Load term name from DB rather than search and parse options array. + $value = module_invoke('taxonomy', 'get_term', $value); + $value = $value->name; + } + else { + $value = $filters[$type]['options'][$value]; + } + $t_args = array('%property' => $filters[$type]['title'], '%value' => $value); + if ($i++) { + $form['filters']['current'][] = array('#markup' => t('and where %property is %value', $t_args)); + } + else { + $form['filters']['current'][] = array('#markup' => t('where %property is %value', $t_args)); + } + if (in_array($type, array('type', 'language'))) { + // Remove the option if it is already being filtered on. + unset($filters[$type]); + } + } + + $form['filters']['status'] = array( + '#type' => 'container', + '#attributes' => array('class' => array('clearfix')), + '#prefix' => ($i ? '
' . t('and where') . '
' : ''), + ); + $form['filters']['status']['filters'] = array( + '#type' => 'container', + '#attributes' => array('class' => array('filters')), + ); + foreach ($filters as $key => $filter) { + $form['filters']['status']['filters'][$key] = array( + '#type' => 'select', + '#options' => $filter['options'], + '#title' => $filter['title'], + '#default_value' => 'any', + ); + } + + $form['filters']['status']['actions'] = array( + '#type' => 'actions', + '#attributes' => array('class' => array('container-inline')), + ); + $form['filters']['status']['actions']['submit'] = array( + '#type' => 'submit', + '#value' => count($session) ? t('Refine') : t('Filter'), + '#submit' => array('biblio_form_filter_submit'), + ); + if (count($session)) { + $form['filters']['status']['actions']['undo'] = array( + '#type' => 'submit', + '#value' => t('Undo'), + '#submit' => array('biblio_form_filter_submit') + ); + $form['filters']['status']['actions']['reset'] = array( + '#type' => 'submit', + '#value' => t('Reset'), + '#submit' => array('biblio_form_filter_submit') + ); + } + + return $form; +} + + +/** + * @param $form + * @param $form_state + * @return unknown_type + */ +function biblio_form_filter_submit($form, &$form_state) { + // If the search filter was set, remove it now. + if (_get_biblio_search_filter()) { + $_SESSION['biblio_filter'] = array(); + } + $op = $form_state['values']['op']; + $filters = _get_biblio_filters(); + switch ($op) { + case t('Filter'): + case t('Refine'): + $uri = drupal_parse_url(request_uri()); + $uri['path'] = variable_get('biblio_base', 'biblio'); + foreach ($filters as $filter => $options) { + if (isset($form_state['values'][$filter]) && $form_state['values'][$filter] != 'any') { + // Flatten the options array to accommodate hierarchical/nested options. + $flat_options = form_options_flatten($filters[$filter]['options']); + // Only accept valid selections offered on the dropdown, block bad input. + if (isset($flat_options[$form_state['values'][$filter]])) { + $_SESSION['biblio_filter'][] = array($filter => $form_state['values'][$filter]); + $uri['query']['f'][$filter] = $form_state['values'][$filter]; + } + } + } + $form_state['redirect'] = array($uri['path'], $uri); + break; + case t('Undo'): + array_pop($_SESSION['biblio_filter']); + break; + case t('Reset'): + $_SESSION['biblio_filter'] = array(); + break; + } +} + + +/** + * @return unknown_type + */ +function biblio_citekey_view() { + $citekey = arg(2); + $nid = db_query("SELECT nid FROM {biblio} WHERE biblio_citekey = :citekey ORDER BY vid DESC", array(':citekey' => $citekey))->fetchObject(); + if ($nid->nid > 0) { + $node = node_load($nid->nid); + return node_page_view($node); + } + else { + return t("Sorry, citekey @cite not found", array('@cite' => $citekey)); + } + +} + + +function biblio_author_page() { + $path = drupal_get_path('module', 'biblio'); + drupal_add_js($path . '/misc/biblio.highlight.js', 'file'); + + $uri = drupal_parse_url(request_uri()); + $filter = isset($uri['query']['f']['author']) ? $uri['query']['f']['author'] : ''; + $authors = _biblio_get_authors($filter); + + return _biblio_format_author_page($uri['path'], $filter, $authors); +} + +function _biblio_get_authors($filter = NULL) { + global $user; + $where = array(); + $authors = array(); + $where_clause = ''; + $output = ''; + + if ($filter) { + $filter = strtoupper($filter); + $where['filter'] = "UPPER(SUBSTRING(lastname,1,1)) = :filter "; + $header_ext = t(' (whose last name starts with the letter "@letter") ', array('@letter' => $filter )); + } + else { + $query_ext = NULL; + $header_ext = NULL; + } + + if (!biblio_access('edit_author')) { + $where['access'] = 'n.status = 1 '; + }//show only published entries to everyone except admin + + if (count($where)) { + $where_clause = 'WHERE (' . implode(') AND (', $where) . ')'; + } + + $suspects = array(); + $query = db_select('biblio_contributor_data', 'bcd') + ->fields('bcd', array('lastname', 'firstname', 'initials', 'alt_form')) + ->groupBy('lastname') + ->groupBy('firstname') + ->groupBy('initials') + ->groupBy('alt_form') + ->having('COUNT(*) > 1'); + + if ($filter) { + $filter = strtoupper($filter); + $query->where("UPPER(SUBSTRING(lastname,1,1)) = :filter ", array(':filter' => $filter)); + } + $result = $query->execute(); + + foreach ($result as $author) { + $suspects[] = $author->lastname; + } + + $db_result = db_query('SELECT bd.cid, bd.drupal_uid, bd.name, bd.lastname, + bd.firstname, bd.prefix, bd.suffix, + bd.initials, bd.affiliation, bd.md5, bd.literal, + COUNT(*) AS cnt + FROM {biblio_contributor} b + LEFT JOIN {biblio_contributor_data} bd ON b.cid = bd.cid + INNER JOIN {node} n on n.vid = b.vid + ' . $where_clause . ' + GROUP BY bd.cid, bd.drupal_uid, bd.name, bd.lastname, + bd.firstname, bd.prefix, bd.suffix, + bd.initials, bd.affiliation, bd.md5, bd.literal + ORDER BY lastname ASC, SUBSTRING(firstname,1,1) ASC, + initials ASC', array(':filter' => $filter)); + + foreach ($db_result as $author) { + if (array_search($author->lastname, $suspects) !== FALSE) { + $author->suspect = TRUE; + } + $authors[] = $author; + } + + return $authors; +} + +function _biblio_format_author_page($path, $filter, $authors) { + $header_ext = $checkbox = ''; + $header = array(); + + if (biblio_access('edit_author')) { + if (!empty($filter)) { + $header_ext = ' ' . t('whose last name begins with the letter') . ': ' . $filter; + } + $checkbox = array( + '#title' => t('Highlight possible duplicates'), + '#type' => 'checkbox', + '#id' => 'biblio-highlight', + ); + $checkbox = '
' . drupal_render($checkbox) . '
'; + $header = array(array('data' => t('There are a total of @count authors in the database!header_ext.', array('@count' => count($authors), '!header_ext' => $header_ext)), 'align' =>'center', 'colspan' => 3)); + } + + $rows[] = array( + array('data' => + theme('biblio_alpha_line', array('type' => 'authors', 'current' => $filter, 'path' => $path)) . $checkbox, 'colspan' => 3)); + if (count($authors)) { + for ($i=0; $i < count($authors); $i+=3) { + $rows[] = array( array('data' => _biblio_format_author($authors[$i]) ), + array('data' => isset($authors[$i+1])?_biblio_format_author($authors[$i+1]):'' ), + array('data' => isset($authors[$i+2])?_biblio_format_author($authors[$i+2]):'' )); + } + } + + + return array( + '#theme' => 'table', + '#header' => $header, + '#rows' => $rows, + ); +} +/* + * Helper function to format the authors and add edit links if required + */ +function _biblio_format_author($author) { + if ($author->literal) { + $name = $author->name; + } + else { + $name = $author->lastname; + $name .= (!empty($author->firstname)) ? ', ' . drupal_substr($author->firstname, 0, 1) . '.' : + (!empty($author->initials) ? ', ' . $author->initials : ''); + } + + $uri['path'] = variable_get('biblio_base', 'biblio'); + $uri['query']['f']['author'] = $author->cid; + $uri['attributes'] = array(); + + if (isset($author->drupal_uid) && $author->drupal_uid > 0) { + $uri['attributes'] += array('class' => array('biblio-local-author')); + } + if (variable_get('biblio_links_target_new_window', null)){ + $uri['attributes'] += array('target'=>'_blank'); + $uri['html'] = TRUE; + } + + $name = l(trim($name), $uri['path'], $uri ); + + // $format = biblio_format_authors(array($author)); + $name .= ' (' . $author->cnt . ') ' . ((biblio_access('edit_author'))?_biblio_author_edit_links($author):''); + if (biblio_access('edit_author') && isset($author->suspect)) { + $name = '
' . $name . '
'; + } + + return $name; +} + +function _biblio_author_edit_links($author) { + static $path = ''; + $destination = drupal_get_destination(); + if (empty($path)) { + $path = (ord(substr($_GET['q'], -1)) > 97) ? $_GET['q'] . "/" : substr($_GET['q'], 0, -1); + $path = (strpos($path, 'list/')) ? str_replace('list/', '', $path) : $path; + } + return l(' [' . t('edit') . ']', $path . $author->cid . "/edit" ); +} + +function biblio_keyword_page() { + $uri = drupal_parse_url(request_uri()); +// $uri['path'] = variable_get('biblio_base', 'biblio'); + $filter = isset($uri['query']['f']['keyword']) ? $uri['query']['f']['keyword'] : ''; + $keywords = _biblio_get_keywords($filter); + return _biblio_format_keyword_page($uri, $filter, $keywords); +} + +function _biblio_get_keywords($filter = NULL) { + global $user; + $keywords = array(); + $where = array(); + $where_clause = ''; + if ($filter) { + $filter = strtoupper($filter); + $where[] = "UPPER(SUBSTRING(word,1,1)) = :filter "; + $header_ext = t(' (which start with the letter "@letter") ', array('@letter' => $filter )); + } + else { + $query_ext = NULL; + $header_ext = NULL; + } + + if ($user->uid != 1 ) { + $where[] = 'n.status = 1 '; + }//show only published entries to everyone except admin + + if (count($where)) { + $where_clause = count($where) > 1 ? 'WHERE (' . implode(') AND (', $where) . ')': 'WHERE ' . $where[0]; + } + + $db_result = db_query('SELECT bkd.kid, bkd.word, COUNT(*) AS cnt + FROM {biblio_keyword} bk + LEFT JOIN {biblio_keyword_data} bkd ON bkd.kid = bk.kid + INNER JOIN {node} n ON n.vid = bk.vid + '. $where_clause . ' + GROUP BY bkd.kid, bkd.word + ORDER BY word ASC', array(':filter' => $filter)); + + foreach ($db_result as $keyword) { + $keywords[] = $keyword; + } + return $keywords; +} + +function _biblio_format_keyword_page($uri, $filter, $keywords) { + $rows[] = array(array('data' => theme('biblio_alpha_line', array('type' => 'keywords', 'current' => $filter, 'path' => $uri['path'])), 'colspan' => 3)); + for ($i=0; $i < count($keywords); $i+=3) { + $rows[] = array( array('data' => _biblio_format_keyword($uri, $keywords[$i]) ), + array('data' => isset($keywords[$i+1]) ? _biblio_format_keyword($uri, $keywords[$i+1]) : '' ), + array('data' => isset($keywords[$i+2]) ? _biblio_format_keyword($uri, $keywords[$i+2]) : '' )); + } + //$header = array(array('data' => t('There are a total of @count keywords !header_ext in the database',array('@count' => count($keywords), '!header_ext' => $header_ext)), 'align' =>'center', 'colspan' => 3)); + $output = theme('table', array('rows' => $rows)); + return $output; +} +function _biblio_format_keyword($uri, $keyword) { + $base = variable_get('biblio_base', 'biblio'); + $uri['path'] = $base; + $uri['query']['f']['keyword'] = $keyword->kid; + $format = l(trim($keyword->word), $base, $uri); + $format .= ' (' . $keyword->cnt . ') ' ; + $destination = drupal_get_destination(); + $path = (ord(substr($_GET['q'], -1)) > 97) ? $_GET['q'] . "/" : substr($_GET['q'], 0, -1); + $edit_link = ' [' . l(t('edit'), $path . $keyword->kid . "/edit", array('query' => $destination)) . '] '; + $format .= (user_access('administer biblio')) ? $edit_link : ''; + + return $format; +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/includes/biblio.search.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/includes/biblio.search.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,303 @@ + 'Content', + 'path' => 'node', + 'conditions_callback' => 'sample_search_conditions_callback', + ); +} + +function sample_search_conditions_callback($keys) { + $conditions = array(); + + if (!empty($_REQUEST['keys'])) { + $conditions['keys'] = $_REQUEST['keys']; + } + if (!empty($_REQUEST['sample_search_keys'])) { + $conditions['sample_search_keys'] = $_REQUEST['sample_search_keys']; + } + if ($force_keys = variable_get('sample_search_force_keywords', '')) { + $conditions['sample_search_force_keywords'] = $force_keys; + } + return $conditions; +} + +function _biblio_search_access() { + return user_access('access content'); +} + +/** + * Take action when the search index is going to be rebuilt. + * + * Modules that use hook_update_index() should update their indexing + * bookkeeping so that it starts from scratch the next time + * hook_update_index() is called. + * + * @ingroup search + */ +function _biblio_search_reset() { + db_update('search_dataset') + ->fields(array('reindex' => REQUEST_TIME)) + ->condition('type', 'node') + ->execute(); +} + +/** + * Report the status of indexing. + * + * @return + * An associative array with the key-value pairs: + * - 'remaining': The number of items left to index. + * - 'total': The total number of items to index. + * + * @ingroup search + */ +function _biblio_search_status() { + $total = db_query('SELECT COUNT(*) FROM {node} WHERE status = 1')->fetchField(); + $remaining = db_query("SELECT COUNT(*) FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE n.status = 1 AND d.sid IS NULL OR d.reindex <> 0")->fetchField(); + return array('remaining' => $remaining, 'total' => $total); +} + +/** + * Add elements to the search settings form. + * + * @return + * Form array for the Search settings page at admin/config/search/settings. + * + * @ingroup search + */ +function _biblio_search_admin() { + // Output form for defining rank factor weights. + $form['content_ranking'] = array( + '#type' => 'fieldset', + '#title' => t('Content ranking'), + ); + $form['content_ranking']['#theme'] = 'node_search_admin'; + $form['content_ranking']['info'] = array( + '#value' => '' . t('The following numbers control which properties the content search should favor when ordering the results. Higher numbers mean more influence, zero means the property is ignored. Changing these numbers does not require the search index to be rebuilt. Changes take effect immediately.') . '' + ); + + // Note: reversed to reflect that higher number = higher ranking. + $options = drupal_map_assoc(range(0, 10)); + foreach (module_invoke_all('ranking') as $var => $values) { + $form['content_ranking']['factors']['node_rank_' . $var] = array( + '#title' => $values['title'], + '#type' => 'select', + '#options' => $options, + '#default_value' => variable_get('node_rank_' . $var, 0), + ); + } + return $form; +} + +/** + * Execute a search for a set of key words. + * + * Use database API with the 'PagerDefault' query extension to perform your + * search. + * + * If your module uses hook_update_index() and search_index() to index its + * items, use table 'search_index' aliased to 'i' as the main table in your + * query, with the 'SearchQuery' extension. You can join to your module's table + * using the 'i.sid' field, which will contain the $sid values you provided to + * search_index(). Add the main keywords to the query by using method + * searchExpression(). The functions search_expression_extract() and + * search_expression_insert() may also be helpful for adding custom search + * parameters to the search expression. + * + * See node_search_execute() for an example of a module that uses the search + * index, and user_search_execute() for an example that doesn't ues the search + * index. + * + * @param $keys + * The search keywords as entered by the user. + * @param $conditions + * An optional array of additional conditions, such as filters. + * + * @return + * An array of search results. To use the default search result + * display, each item should have the following keys': + * - 'link': Required. The URL of the found item. + * - 'type': The type of item (such as the content type). + * - 'title': Required. The name of the item. + * - 'user': The author of the item. + * - 'date': A timestamp when the item was last modified. + * - 'extra': An array of optional extra information items. + * - 'snippet': An excerpt or preview to show with the result (can be + * generated with search_excerpt()). + * - 'language': Language code for the item (usually two characters). + * + * @ingroup search + */ +function _biblio_search_execute($keys = NULL, $conditions = NULL) { + // Build matching conditions + $query = db_select('search_index', 'i', array('target' => 'slave'))->extend('SearchQuery')->extend('PagerDefault'); + $query->join('node', 'n', 'n.nid = i.sid'); + $query + ->condition('n.status', 1) + ->addTag('node_access') + ->searchExpression($keys, 'node'); + + // Insert special keywords. + $query->setOption('type', 'n.type'); + $query->setOption('language', 'n.language'); + if ($query->setOption('term', 'ti.tid')) { + $query->join('taxonomy_index', 'ti', 'n.nid = ti.nid'); + } + // Only continue if the first pass query matches. + if (!$query->executeFirstPass()) { + return array(); + } + + // Add the ranking expressions. + _node_rankings($query); + + // Load results. + $find = $query + ->limit(10) + ->execute(); + $results = array(); + foreach ($find as $item) { + // Build the node body. + $node = node_load($item->sid); + node_build_content($node, 'search_result'); + $node->body = drupal_render($node->content); + + // Fetch comments for snippet. + $node->rendered .= ' ' . module_invoke('comment', 'node_update_index', $node); + // Fetch terms for snippet. + $node->rendered .= ' ' . module_invoke('taxonomy', 'node_update_index', $node); + + $extra = module_invoke_all('node_search_result', $node); + + $results[] = array( + 'link' => url('node/' . $item->sid, array('absolute' => TRUE)), + 'type' => check_plain(node_type_get_name($node)), + 'title' => $node->title, + 'user' => theme('username', array('account' => $node)), + 'date' => $node->changed, + 'node' => $node, + 'extra' => $extra, + 'score' => $item->calculated_score, + 'snippet' => search_excerpt($keys, $node->body), + ); + } + return $results; +} + +/** + * Override the rendering of search results. + * + * A module that implements hook_search_info() to define a type of search + * may implement this hook in order to override the default theming of + * its search results, which is otherwise themed using theme('search_results'). + * + * Note that by default, theme('search_results') and theme('search_result') + * work together to create an ordered list (OL). So your hook_search_page() + * implementation should probably do this as well. + * + * @see search-result.tpl.php, search-results.tpl.php + * + * @param $results + * An array of search results. + * + * @return + * A renderable array, which will render the formatted search results with + * a pager included. + */ +function _biblio_search_page($results) { + $output['prefix']['#markup'] = '
    '; + + foreach ($results as $entry) { + $output[] = array( + '#theme' => 'search_result', + '#result' => $entry, + '#module' => 'my_module_name', + ); + } + $output['suffix']['#markup'] = '
' . theme('pager'); + + return $output; +} + +/** + * Preprocess text for search. + * + * This hook is called to preprocess both the text added to the search index and + * the keywords users have submitted for searching. + * + * Possible uses: + * - Adding spaces between words of Chinese or Japanese text. + * - Stemming words down to their root words to allow matches between, for + * instance, walk, walked, walking, and walks in searching. + * - Expanding abbreviations and acronymns that occur in text. + * + * @param $text + * The text to preprocess. This is a single piece of plain text extracted + * from between two HTML tags or from the search query. It will not contain + * any HTML entities or HTML tags. + * + * @return + * The text after preprocessing. Note that if your module decides not to alter + * the text, it should return the original text. Also, after preprocessing, + * words in the text should be separated by a space. + * + * @ingroup search + */ +function _biblio_search_preprocess($text) { + // Do processing on $text + return $text; +} + +/** + * Update the search index for this module. + * + * This hook is called every cron run if search.module is enabled, your + * module has implemented hook_search_info(), and your module has been set as + * an active search module on the Search settings page + * (admin/config/search/settings). It allows your module to add items to the + * built-in search index using search_index(), or to add them to your module's + * own indexing mechanism. + * + * When implementing this hook, your module should index content items that + * were modified or added since the last run. PHP has a time limit + * for cron, though, so it is advisable to limit how many items you index + * per run using variable_get('search_cron_limit') (see example below). Also, + * since the cron run could time out and abort in the middle of your run, you + * should update your module's internal bookkeeping on when items have last + * been indexed as you go rather than waiting to the end of indexing. + * + * @ingroup search + */ +function _biblio_update_index() { + $limit = (int)variable_get('search_cron_limit', 100); + + $result = db_query_range("SELECT n.nid FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE d.sid IS NULL OR d.reindex <> 0 ORDER BY d.reindex ASC, n.nid ASC", 0, $limit); + + foreach ($result as $node) { + $node = node_load($node->nid); + + // Save the changed time of the most recent indexed node, for the search + // results half-life calculation. + variable_set('node_cron_last', $node->changed); + + // Render the node. + node_build_content($node, 'search_index'); + $node->rendered = drupal_render($node->content); + + $text = '

' . check_plain($node->title) . '

' . $node->rendered; + + // Fetch extra data normally not visible + $extra = module_invoke_all('node_update_index', $node); + foreach ($extra as $t) { + $text .= $t; + } + + // Update index + search_index($node->nid, 'node', $text); + } +} +/** + * @} End of "addtogroup hooks". + */ diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/includes/biblio.util.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/includes/biblio.util.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,387 @@ + and the file's + // original author. + // Original Author: Richard Karnesky // + // Adapted for biblio: Ron Jerome + // fmt_info (type) + $fmt = "info:ofi/fmt:kev:mtx:"; + // 'dissertation' is compatible with the 1.0 spec, but not the 0.1 spec + if ($node->biblio_type == 108) { + $fmt .= "dissertation"; + } + elseif ($node->biblio_type == 102) { + $fmt .= "journal"; + } + elseif ($node->biblio_type == 100 || $node->biblio_type == 101) { + $fmt .= "book"; + } + // 'dc' (dublin core) is compatible with the 1.0 spec, but not the 0.1 spec. + // We default to this, as it is the most generic type. + else { + $fmt .= "dc"; + } + + $co = biblio_contextObject($node); + $coins = "ctx_ver=Z39.88-2004&rft_val_fmt=" . urlencode($fmt); + foreach ($co as $coKey => $coValue) { + // 'urlencode()' differs from 'rawurlencode() (i.e., RFC1738 encoding) + // in that spaces are encoded as plus (+) signs + $coKey = preg_replace("/au[0-9]*/", "au", $coKey); + $coins .= "&" . $coKey . "=" . urlencode($coValue); + } + $coinsSpan = ""; + return $coinsSpan; +} + +function biblio_contextObject($node) { + // Copyright: Matthias Steffens and the file's + // original author. + // Original Author: Richard Karnesky // + // Adapted for biblio: Ron Jerome + global $base_url; + $i = 0; + // $openurl_base = variable_get('biblio_baseopenurl', ''); + $co = array(); + // rfr_id +// $co["rfr_id"] = "info:sid/". ereg_replace("http://", "", $base_url); +// // genre (type) +// if (isset($node->biblio_type)) { +// if ($node->biblio_type == 102) +// $co["rft.genre"] = "article"; +// elseif ($node->biblio_type == 101) $co["rft.genre"] = "bookitem"; +// elseif ($node->biblio_type == 100) $co["rft.genre"] = "book"; +// elseif ($node->biblio_type == "Journal") $co["rft.genre"] = "journal"; +// } + // atitle, btitle, title (title, publication) + if (($node->biblio_type == 102) || ($node->biblio_type == 101)) { + if (!empty($node->title)) $co["rft.atitle"] = check_plain($node->title); + if (!empty($node->biblio_secondary_title)) { + $co["rft.title"] = check_plain($node->biblio_secondary_title); + if ($node->biblio_type == 101) + $co["rft.btitle"] = check_plain($node->biblio_secondary_title); + } + } + elseif (!empty($node->title)) { + $co["rft.title"] = check_plain($node->title); + } + if (($node->biblio_type == 100) && (!empty($node->biblio_secondary_title))) $co["rft.btitle"] = check_plain($node->biblio_secondary_title); + // stitle (abbrev_journal) + if (!empty($node->biblio_short_title)) $co["rft.stitle"] = check_plain($node->biblio_short_title); + // series (series_title) + if (!empty($node->biblio_tertiary_title)) $co["rft.series"] = check_plain($node->biblio_tertiary_title); + // issn + if (!empty($node->biblio_issn)) $co["rft.issn"] = check_plain($node->biblio_issn); + // isbn + if (!empty($node->biblio_isbn)) $co["rft.isbn"] = check_plain($node->biblio_isbn); + // date (year) + if (!empty($node->biblio_year)) $co["rft.date"] = check_plain($node->biblio_year); + // volume + if (!empty($node->biblio_volume)) $co["rft.volume"] = check_plain($node->biblio_volume); + // issue + if (!empty($node->biblio_issue)) $co["rft.issue"] = check_plain($node->biblio_issue); + // spage, epage, tpages (pages) + // NOTE: lifted from modsxml.inc.php--should throw some into a new include file + if (!empty($node->biblio_pages)) { + if (preg_match("/[0-9] *- *[0-9]/", $node->biblio_pages)) { + list ($pagestart, $pageend) = preg_split('/\s*[-]\s*/', $node->biblio_pages); + if ($pagestart < $pageend) { + $co["rft.spage"] = check_plain($pagestart); + $co["rft.epage"] = check_plain($pageend); + } + } + elseif ($node->biblio_type == 100) { //"Book Whole") { + $pagetotal = preg_replace('/^(\d+)\s*pp?\.?$/', "\\1", $node->biblio_pages); + $co["rft.tpages"] = check_plain($pagetotal); + } + else { + $co["rft.spage"] = check_plain($node->biblio_pages); + } + } + // aulast, aufirst, author (author) + if (!empty($node->biblio_contributors)) { + if (!empty($node->biblio_contributors[0]['lastname'])) { + $co["rft.aulast"] = check_plain($node->biblio_contributors[0]['lastname']); + } + if (!empty($node->biblio_contributors[0]['firstname'])) { + $co["rft.aufirst"] = check_plain($node->biblio_contributors[0]['firstname']); + } + elseif (!empty($node->biblio_contributors[0]['initials'])) { + $co["rft.auinit"] = check_plain($node->biblio_contributors[0]['initials']); + } + for($i = 1; $i < count($node->biblio_contributors); $i++) { + $author = $node->biblio_contributors[$i]; + if ($author['auth_category'] == 1) { + if (!empty($author['lastname'])) { + $au = $author['lastname']; + if (!empty($author['firstname']) || !empty($author['initials'])) $au .= ", "; + } + if (!empty($author['firstname'])) { + $au .= $author['firstname']; + } + elseif (!empty($author['initials'])) { + $au .= $author['initials']; + } + if (!empty($au)) $co["rft.au" . $i] = $au; + } + } + } + // pub (publisher) + if (!empty($node->biblio_publisher)) $co["rft.pub"] = check_plain($node->biblio_publisher); + // place + if (!empty($node->biblio_place_published)) $co["rft.place"] = check_plain($node->biblio_place_published); + // id (doi, url) + if (!empty($node->biblio_doi)) { + $co["rft_id"] = "info:doi/" . check_plain($node->biblio_doi); + } +// elseif (!empty($node->biblio_url)) { +// $co["rft_id"] = $node->biblio_url; +// } + + return $co; +} + +function biblio_coins_generate(& $node) { + if (!isset($node->vid)) { + $node->biblio_coins = biblio_coins($node); + return; + } + if ($node) { + $node->biblio_coins = biblio_coins($node); + db_update('biblio') + ->fields(array('biblio_coins' => $node->biblio_coins)) + ->condition('vid', $node->vid) + ->execute(); + } + else { + $result = db_query("SELECT nr.*, b.* + FROM {node} AS n + LEFT JOIN {node_revision} AS nr ON n.vid = nr.vid LEFT JOIN {biblio} AS b ON n.vid = b.vid + WHERE n.type = 'biblio' "); + + foreach ($result as $node) { + $node->biblio_coins = biblio_coins($node); + db_update('biblio') + ->fields(array('biblio_coins' => $node->biblio_coins)) + ->condition('vid', $node->vid) + ->execute(); + } + drupal_goto(''); + } +} + +function _strip_punctuation($text) { + return preg_replace("/[[:punct:]]/", '', $text); +} +/** + * Copyright (c) 2008, David R. Nadeau, NadeauSoftware.com. + * All rights reserved. + * + * Strip punctuation characters from UTF-8 text. + * + * Characters stripped from the text include characters in the following + * Unicode categories: + * + * Separators + * Control characters + * Formatting characters + * Surrogates + * Open and close quotes + * Open and close brackets + * Dashes + * Connectors + * Numer separators + * Spaces + * Other punctuation + * + * Exceptions are made for punctuation characters that occur withn URLs + * (such as [ ] : ; @ & ? and others), within numbers (such as . , % # '), + * and within words (such as - and '). + * + * Parameters: + * text the UTF-8 text to strip + * + * Return values: + * the stripped UTF-8 text. + * + * See also: + * http://nadeausoftware.com/articles/2007/9/php_tip_how_strip_punctuation_characters_web_page + */ +function _strip_punctuation_utf8( $text ) +{ + $urlbrackets = '\[\]\(\)'; + $urlspacebefore = ':;\'_\*%@&?!' . $urlbrackets; + $urlspaceafter = '\.,:;\'\-_\*@&\/\\\\\?!#' . $urlbrackets; + $urlall = '\.,:;\'\-_\*%@&\/\\\\\?!#' . $urlbrackets; + + $specialquotes = '\'"\*<>'; + + $fullstop = '\x{002E}\x{FE52}\x{FF0E}'; + $comma = '\x{002C}\x{FE50}\x{FF0C}'; + $arabsep = '\x{066B}\x{066C}'; + $numseparators = $fullstop . $comma . $arabsep; + + $numbersign = '\x{0023}\x{FE5F}\x{FF03}'; + $percent = '\x{066A}\x{0025}\x{066A}\x{FE6A}\x{FF05}\x{2030}\x{2031}'; + $prime = '\x{2032}\x{2033}\x{2034}\x{2057}'; + $nummodifiers = $numbersign . $percent . $prime; + + return preg_replace( + array( + // Remove separator, control, formatting, surrogate, + // open/close quotes. + '/[\p{Z}\p{Cc}\p{Cf}\p{Cs}\p{Pi}\p{Pf}]/u', + // Remove other punctuation except special cases + '/\p{Po}(?]*?>.*?@siu', + '@]*?>.*?@siu', + '@]*?.*?@siu', + '@]*?.*?@siu', + '@]*?.*?@siu', + '@]*?.*?@siu', + '@]*?.*?@siu', + '@]*?.*?@siu', + '@]*?.*?@siu', + // Add line breaks before and after blocks + '@
'; + } + else { + $output .= ''; + } + return $output; +} + +/** + * @param $node + * @return unknown_type + */ +function biblio_openurl($node) { + global $user; + $open_url = ''; + // Copyright: Matthias Steffens and the file's + // original author. + // Original Author: Richard Karnesky // + // Adapted for biblio: Ron Jerome + // global $open_url_resolver; // these variables are defined in 'ini.inc.php' + // global $hostInstitutionAbbrevName; + $open_url_resolver = !empty($user->data['biblio_baseopenurl']) ? $user->data['biblio_baseopenurl'] : ''; + if (empty($open_url_resolver)) $open_url_resolver = variable_get('biblio_baseopenurl', ''); + if (!empty($open_url_resolver)) { + $co = biblio_contextObject($node); + + $sid = "biblio:" . variable_get('site_name', 'Drupal'); + $user_sid = !empty($user->data['biblio_openurl_sid']) ? $user->data['biblio_openurl_sid'] : ''; + $co["sid"] = !empty($user_sid) ? $user_sid : variable_get('biblio_openurl_sid', $sid); + + $open_url = $open_url_resolver; + if (!preg_match("/\?/", $open_url_resolver)) { + $open_url .= "?"; + } + else { + $open_url .= "&"; + } + $open_url .= "ctx_ver=Z39.88-2004"; + foreach ($co as $coKey => $coValue) { + $coKey = preg_replace("/rft./", "", $coKey); + $coKey = preg_replace("/au[0-9]*/", "au", $coKey); + $open_url .= "&" . $coKey . "=" . rawurlencode($coValue); + } + } + return $open_url; +} + + +/** + * DEPRECIATED! this was the original output format which is not to flexable it will be removed + * TODO: remove this function + * @param $node + * @param $base + * @param $style + * @return unknown_type + */ +function theme_biblio_long($variables) { + $output = ''; + $node = $variables['node']; + if (module_exists('popups')) { + popups_add_popups(); + } + + $output .= filter_xss($node->biblio_coins, array('span')); + $layout = variable_get('biblio_node_layout', 'orig'); + + // Check body value. + $has_body = !empty($node->body); + + if (variable_get('biblio_node_layout', 'orig') == 'ft' && $has_body && user_access('view full text')) { + $output .= '
' . theme('biblio_style', $variables) . '
'; + $annotation_field = variable_get('biblio_annotations', 'none'); + if ($annotation_field != 'none' && $node-> $annotation_field) { + $output .= '
'; + $output .= filter_xss($node->$annotation_field, biblio_get_allowed_tags()); + $output .= '
'; + } + $output .= drupal_render(field_view_field('node', $node, 'body', array('label' => 'hidden'))); + if (biblio_access('export', $node)) { + $output .= theme('biblio_export_links', array('node' => $node)); + } + return $output; + } + foreach ((array)$node->biblio_contributors as $auth) { + if ($auth['auth_category'] == 1) { + $authors[] = theme('biblio_author_link', array('author' => $auth)); + } + } + $authors = implode('; ', (array)$authors); + $openurl_base = variable_get('biblio_baseopenurl', ''); + if ($openurl_base) + $output .= theme('biblio_openurl', array('openURL' => biblio_openurl($node))); + $output .= '

' . t("Publication Type") . ":

$node->biblio_type_name
\n"; + $output .= '

' . t("Authors") . ':

' . $authors . "
\n"; + $output .= '

' . t("Source") . ':

'; + $source = NULL; + if ($node->biblio_secondary_title) + $source .= check_plain($node->biblio_secondary_title); + if ($node->biblio_publisher) { + $source .= $source ? ", " : ""; + $source .= check_plain($node->biblio_publisher); + } + if ($node->biblio_volume) { + $source .= $source ? ", " : ""; + $source .= t('Volume') . ' ' . check_plain($node->biblio_volume); + } + if ($node->biblio_issue) { + $source .= $source ? ", " : ""; + $source .= t('Issue') . ' ' . check_plain($node->biblio_issue); + } + if ($node->biblio_number) { + $source .= $source ? ", " : ""; + $source .= t('Number') . ' ' . check_plain($node->biblio_number); + } + if ($node->biblio_place_published) { + $source .= $source ? ", " : ""; + $source .= check_plain($node->biblio_place_published); + } + if ($node->biblio_pages) { + $source .= $source ? ", " : ""; + $source .= 'p.' . check_plain($node->biblio_pages); + } + if (isset ($node->biblio_year)) { + $node->biblio_year = _biblio_text_year($node->biblio_year); + $source .= ' (' . check_plain($node->biblio_year) . ')'; + } + $output .= "$source
\n"; + if ($node->biblio_isbn) + $output .= '

' . t("ISBN") . ':

' . check_plain($node->biblio_isbn) . "\n"; + if ($node->biblio_call_number) + $output .= '

' . t("Call Number") . ':

' . check_plain($node->biblio_call_number) . "\n"; + if ($node->biblio_accession_number) + $output .= '

' . t("Accession Number") . ':

' . check_plain($node->biblio_accession_number) . "\n"; + if ($node->biblio_other_number) + $output .= '

' . t("Other Number") . ':

' . check_plain($node->biblio_other_number) . "\n"; + if ($node->biblio_url) { + $attrib = (variable_get('biblio_links_target_new_window', FALSE)) ? array('target' => '_blank') : array(); + $output .= '

' . t("URL") . ':

' . l($node->biblio_url, $node->biblio_url, $attrib) . "\n"; + } + if (!empty($node->biblio_keywords)) { + $output .= '

' . t("Keywords") . ':

' . _biblio_keyword_links( $node->biblio_keywords) . "\n"; + } + if ($node->biblio_abst_e) + $output .= '

' . t("Abstract") . ':

' . check_markup($node->biblio_abst_e) . "\n"; + if ($node->biblio_abst_f) + $output .= '

' . check_markup($node->biblio_abst_f) . "\n"; + if ($node->biblio_notes) + $output .= '

' . t("Notes") . ':

' . check_markup($node->biblio_notes) . "\n"; + if (!empty($node->body) && user_access('view full text') ) { + $output .= drupal_render(field_view_field('node', $node, 'body')); + } + + return $output; +} + +function _biblio_get_field_information($biblio_type, $only_visible = FALSE) { + $fields = array(); + $visible = $only_visible ? ' AND (bt.common = 1 OR bt.visible=1) ' : ''; + + $result = db_query("SELECT b.*, btd.*, btt.name AS type_name + FROM {biblio_fields} AS b + INNER JOIN {biblio_field_type} AS bt ON bt.fid = b.fid + INNER JOIN {biblio_field_type_data} AS btd ON btd.ftdid = bt.ftdid + INNER JOIN {biblio_types} as btt ON btt.tid = bt.tid + WHERE bt.tid = :tid $visible + ORDER BY bt.weight ASC", array(':tid' => $biblio_type), array('fetch' => PDO::FETCH_ASSOC)); + + foreach ($result as $row) { + $fields[$row['fid']] = $row; + } + + return $fields; +} + +/** + * @param $node + * @param $base + * @param $teaser + * @return unknown_type + */ +function theme_biblio_tabular($variables) { + module_load_include('inc', 'biblio', '/includes/biblio.contributors'); + $node = $variables['node']; + $base = $variables['base']; + static $citeproc; + + if (module_exists('popups')) { + popups_add_popups(); + } + $tid = $node->biblio_type; + $fields = _biblio_get_field_information($node->biblio_type, TRUE); + $rows[] = array( + array('data' => t('Title'), 'class' => array('biblio-row-title')), + array('data' => filter_xss($node->title, biblio_get_allowed_tags())) + ); + + if (!isset($node->biblio_type_name) && isset($node->biblio_type)) { // needed for preview + if (($pub_type = db_query('SELECT t.tid, t.name FROM {biblio_types} as t WHERE t.tid=:tid', array(':tid' => $node->biblio_type))->fetchObject())) { + $node->biblio_type_name = drupal_ucfirst(_biblio_localize_type($pub_type->tid, $pub_type->name)); + } + } + + $rows[] = array( + array('data' => t('Publication Type'), 'class' => array('biblio-row-title')), + array('data' => $node->biblio_type_name) + ); + + $attrib = (variable_get('biblio_links_target_new_window', FALSE)) ? array('target' => '_blank') : array(); + + $doi = ''; + if (!empty($node->biblio_doi)) { + $doi_url = ''; + if ( ($doi_start = strpos($node->biblio_doi, '10.')) !== FALSE) { + $doi = substr($node->biblio_doi, $doi_start); + $doi_url .= 'http://dx.doi.org/' . $doi; + $doi = l($doi, $doi_url, $attrib); + } + + } + + foreach ($fields as $key => $row) { + // handling the contributor categories like any other field orders them correctly by weight + if ($row['type'] == 'contrib_widget' && ($authors = biblio_get_contributor_category($node->biblio_contributors, $row['fid']))) { + $data = biblio_format_authors($authors); + } + elseif (empty ($node->$row['name']) || $row['name'] == 'biblio_coins') { + continue; + } + else { + switch ($row['name']) { + case 'biblio_keywords' : + $data = _biblio_keyword_links($node->$row['name'], $base); + break; + case 'biblio_url' : + $data = l($node->$row['name'], $node->$row['name'], $attrib); + break; + case 'biblio_doi' : + $data = $doi; + break; + default: + if ($row['type'] == 'text_format') { + $format = filter_default_format(); + if (!empty($node->biblio_formats) ) { + $formats = $node->biblio_formats; + $format = isset($formats[$row['name']]) ? $formats[$row['name']] : $format; + } + $data = check_markup($node->$row['name'], $format); + } + else { + $data = check_plain($node->$row['name']); + } + } + } + $rows[] = array( + array( + 'data' => t($row['title']), + 'class' => array('biblio-row-title') + ), + array( + 'data' => $data + ) + ); + } + if (isset($node->body) && !empty($node->body) && user_access('view full text')) { + $rows[] = array( + array('data' => t('Full Text'), 'valign' => 'top'), + array('data' => drupal_render(field_view_field('node', $node, 'body', array('label' => 'hidden')))), + ); + + } + // let other modules add rows if desired... + drupal_alter('biblio_node_table_rows', $rows, $node); + + $output = '
'; + $output .= filter_xss($node->biblio_coins, array('span')); + $header = array(); + $output .= theme('table', array('header' => $header, 'rows' => $rows)); + $output .= '
'; + + return $output; +} + +function _biblio_get_latin1_regex() { + $alnum = "[:alnum:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆäåáàâãçéèêëñöøóòôõüúùûíìîïæÿß"; + + // Matches ISO-8859-1 letters: + $alpha = "[:alpha:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆäåáàâãçéèêëñöøóòôõüúùûíìîïæÿß"; + + // Matches ISO-8859-1 control characters: + $cntrl = "[:cntrl:]"; + + // Matches ISO-8859-1 dashes & hyphens: + $dash = "-–"; + + // Matches ISO-8859-1 digits: + $digit = "[\d]"; + + // Matches ISO-8859-1 printing characters (excluding space): + $graph = "[:graph:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆäåáàâãçéèêëñöøóòôõüúùûíìîïæÿß"; + + // Matches ISO-8859-1 lower case letters: + $lower = "[:lower:]äåáàâãçéèêëñöøóòôõüúùûíìîïæÿß"; + + // Matches ISO-8859-1 printing characters (including space): + $print = "[:print:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆäåáàâãçéèêëñöøóòôõüúùûíìîïæÿß"; + + // Matches ISO-8859-1 punctuation: + $punct = "[:punct:]"; + + // Matches ISO-8859-1 whitespace (separating characters with no visual representation): + $space = "[\s]"; + + // Matches ISO-8859-1 upper case letters: + $upper = "[:upper:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆ"; + + // Matches ISO-8859-1 "word" characters: + $word = "_[:alnum:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆäåáàâãçéèêëñöøóòôõüúùûíìîïæÿß"; + + // Defines the PCRE pattern modifier(s) to be used in conjunction with the above variables: + // More info: + $patternModifiers = ""; + + return array($alnum, $alpha, $cntrl, $dash, $digit, $graph, $lower, + $print, $punct, $space, $upper, $word, $patternModifiers); + +} +/* + * Helper function for theme_biblio_format_authors() and theme_biblio_page_number() + */ +function _biblio_get_utf8_regex() { + + // Matches Unicode letters & digits: + $alnum = "\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}"; // Unicode-aware equivalent of "[:alnum:]" + + // Matches Unicode letters: + $alpha = "\p{Ll}\p{Lu}\p{Lt}\p{Lo}"; // Unicode-aware equivalent of "[:alpha:]" + + // Matches Unicode control codes & characters not in other categories: + $cntrl = "\p{C}"; // Unicode-aware equivalent of "[:cntrl:]" + + // Matches Unicode dashes & hyphens: + $dash = "\p{Pd}"; + + // Matches Unicode digits: + $digit = "\p{Nd}"; // Unicode-aware equivalent of "[:digit:]" + + // Matches Unicode printing characters (excluding space): + $graph = "^\p{C}\t\n\f\r\p{Z}"; // Unicode-aware equivalent of "[:graph:]" + + // Matches Unicode lower case letters: + $lower = "\p{Ll}\p{M}"; // Unicode-aware equivalent of "[:lower:]" + + // Matches Unicode printing characters (including space): + $print = "\P{C}"; // same as "^\p{C}", Unicode-aware equivalent of "[:print:]" + + // Matches Unicode punctuation (printing characters excluding letters & digits): + $punct = "\p{P}"; // Unicode-aware equivalent of "[:punct:]" + + // Matches Unicode whitespace (separating characters with no visual representation): + $space = "\t\n\f\r\p{Z}"; // Unicode-aware equivalent of "[:space:]" + + // Matches Unicode upper case letters: + $upper = "\p{Lu}\p{Lt}"; // Unicode-aware equivalent of "[:upper:]" + + // Matches Unicode "word" characters: + $word = "_\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}"; // Unicode-aware equivalent of "[:word:]" (or "[:alnum:]" plus "_") + + // Defines the PCRE pattern modifier(s) to be used in conjunction with the above variables: + // More info: + $patternModifiers = "u"; // the "u" (PCRE_UTF8) pattern modifier causes PHP/PCRE to treat pattern strings as UTF-8 + + return array($alnum, $alpha, $cntrl, $dash, $digit, $graph, $lower, + $print, $punct, $space, $upper, $word, $patternModifiers); +} + +function _biblio_get_regex_patterns() { + // Checks if PCRE is compiled with UTF-8 and Unicode support + if (!@preg_match('/\pL/u', 'a')) { + // probably a broken PCRE library + return _biblio_get_latin1_regex(); + } + else { + // Unicode safe filter for the value + return _biblio_get_utf8_regex(); + } +} + +function biblio_format_authors($authors) { + if (module_exists('biblio_citeproc')) { + static $auth_proc; + if (!isset($auth_proc)) { + module_load_include('inc', 'biblio_citeproc', 'CSL'); + $csl = ''; + $csl_doc = new DOMDocument(); + $csl_doc->loadXML($csl); + $auth_proc = new csl_rendering_element($csl_doc); + } + $data = $auth_proc->render($authors); + } + else { + $style_name = biblio_get_style(); + $style_function = "biblio_style_$style_name" . "_author_options"; + if (!function_exists($style_function)) { + module_load_include('inc', 'biblio', "/styles/biblio_style_$style_name"); + } + $author_options = $style_function(); + $author_options['numberOfAuthorsTriggeringEtAl'] = 100; //set really high so we see all authors + $data = theme('biblio_format_authors', array('contributors' => $authors, 'options' => $author_options)); + } + + return $data; +} +function theme_biblio_format_authors($variables) { + $contributors = $variables['contributors']; + $options = $variables['options']; + + if (empty($contributors)) return; + list($alnum, $alpha, $cntrl, $dash, $digit, $graph, $lower, + $print, $punct, $space, $upper, $word, $patternModifiers) = _biblio_get_regex_patterns(); + $base = variable_get('biblio_base', 'biblio'); + $author_links = variable_get('biblio_author_links', 1); + + $authorCount = count($contributors); // check how many authors we have to deal with + $output = ""; // this variable will hold the final author string + $includeStringAfterFirstAuthor = FALSE; + + if (empty($options['numberOfAuthorsTriggeringEtAl'])) $options['numberOfAuthorsTriggeringEtAl'] = $authorCount; + + if (empty($options['includeNumberOfAuthors'])) $options['includeNumberOfAuthors'] = $authorCount; + + foreach ($contributors as $rank => $author) { + if (empty($author['name'])) continue; + if (!isset($author['lastname']) && empty($author['literal'])) { + module_load_include('inc', 'biblio', '/includes/biblio.contributors'); + $author = biblio_parse_author($author, $author['auth_type']); // this is needed for form preview to fill in all fields + } + if (empty($author['literal'])) { + if (!empty($author['firstname'])) { + if ($options['shortenGivenNames']) {// if we're supposed to abbreviate given names + // within initials, reduce all full first names (-> defined by a starting uppercase character, followed by one ore more lowercase characters) + // to initials, i.e., only retain their first character + $author['firstname'] = preg_replace("/([$upper])[$lower]+/$patternModifiers", '\\1', $author['firstname']); + //$author['firstname'] = drupal_substr($author['firstname'], 0, 1); + // the next line caused extra betweenInitialsDelim to appear in some circumstances + //$author['firstname'] = preg_replace("/($space|$dash)?/$patternModifier", $options['betweenInitialsDelim'], $author['firstname']); + } + } + if (isset($author['initials'])) { + // within initials, remove any dots: + $author['initials'] = preg_replace("/([$upper])\.+/$patternModifiers", "\\1", $author['initials']); + //$author['initials'] = str_replace('.', '', $author['initials']); + + // within initials, remove any spaces *between* initials: + $author['initials'] = preg_replace("/(?<=[-$upper]) +(?=[-$upper])/$patternModifiers", "", $author['initials']); + //$author['initials'] = str_replace(' ', '', $author['initials']); + + // within initials, add a space after a hyphen, but only if ... + if (preg_match('/ $/', $options['betweenInitialsDelim'])) { // ... the delimiter that separates initials ends with a space + $author['initials'] = preg_replace("/-(?=[$upper])/$patternModifiers", "- ", $author['initials']); + } + // then, separate initials with the specified delimiter: + $delim = $options['betweenInitialsDelim']; + $author['initials'] = preg_replace("/([$upper])(?=[^$lower]+|$)/$patternModifiers", "\\1$delim", $author['initials']); + + $shortenInitials = (isset($options['numberOfInitialsToKeep'])) ? $options['numberOfInitialsToKeep'] : FALSE; + if ($shortenInitials) $author['initials'] = drupal_substr($author['initials'], 0, $shortenInitials); + + if ($options['shortenGivenNames'] && !empty($author['firstname'])) { + $author['firstname'] = $author['firstname'] . $options['betweenInitialsDelim'] . $author['initials']; + if ($shortenInitials) $author['firstname'] = drupal_substr($author['firstname'], 0, $shortenInitials); + } + elseif (!empty($author['firstname'])) { + $author['firstname'] = $author['firstname'] . ' ' . $author['initials']; + } + elseif (empty($author['firstname'])) { + $author['firstname'] = $author['initials']; + } + } + + // if there is a surname prefix like "van", "von" etc, stick it back before the last name. + if (!empty($author['prefix'])) $author['lastname'] = $author['prefix'] . ' ' . $author['lastname']; + if (!empty($author['suffix'])) $author['lastname'] = $author['lastname'] . ', ' . $author['suffix']; + + if (!empty($author['firstname'])) { + if ($rank == 0) { // -> first author + if ($options['initialsBeforeAuthorFirstAuthor']) { + $author['name'] = $author['firstname'] . $options['AuthorsInitialsDelimFirstAuthor'] . $author['lastname']; + } + else{ + $author['name'] = $author['lastname'] . $options['AuthorsInitialsDelimFirstAuthor'] . $author['firstname']; + } + } + else { // $rank > 0 // -> all authors except the first one + if ($options['initialsBeforeAuthorStandard']) { + $author['name'] = $author['firstname'] . $options['AuthorsInitialsDelimStandard'] . $author['lastname']; + } + else{ + $author['name'] = $author['lastname'] . $options['AuthorsInitialsDelimStandard'] . $author['firstname']; + } + } + } + else { + $author['name'] = $author['lastname']; + } + } + if ($author_links) { + $author['name'] = theme('biblio_author_link', array('author' => $author)); + } + else { + $author['name'] = check_plain($author['name']); + } + // append this author to the final author string: + if (($rank == 0) OR ($rank + 1) < $authorCount) {// -> first author, or (for multiple authors) all authors except the last one + if ($rank == 0) { // -> first author + $output .= $author['name']; + } + else {// -> for multiple authors, all authors except the first or the last one + $output .= $options['BetweenAuthorsDelimStandard'] . $author['name']; + } + // we'll append the string in '$customStringAfterFirstAuthors' to the number of authors given in '$includeNumberOfAuthors' if the total number of authors is greater than the number given in '$numberOfAuthorsTriggeringEtAl': + if ((($rank + 1) == $options['includeNumberOfAuthors']) AND ($authorCount > $options['numberOfAuthorsTriggeringEtAl'])) { + if (preg_match("/__NUMBER_OF_AUTHORS__/", $options['customStringAfterFirstAuthors'])) { + $customStringAfterFirstAuthors = preg_replace("/__NUMBER_OF_AUTHORS__/", ($authorCount - $options['includeNumberOfAuthors']), $options['customStringAfterFirstAuthors']); // resolve placeholder + } + $includeStringAfterFirstAuthor = TRUE; + break; + } + } + elseif (($authorCount > 1) AND (($rank + 1) == $authorCount)) {// -> last author (if multiple authors) + $output .= $options['BetweenAuthorsDelimLastAuthor'] . $author['name']; + } + } + + // do some final clean up: + //if ($options['encodeHTML']) + //$output = encodeHTML($output); // HTML encode higher ASCII characters within the newly arranged author contents + + if ($includeStringAfterFirstAuthor) { + $output .= $options['customStringAfterFirstAuthors']; // the custom string won't get HTML encoded so that it's possible to include HTML tags (such as '') within the string + } + $output = preg_replace("/ +/", " ", $output); // remove double spaces (which occur e.g., when both, $betweenInitialsDelim & $newAuthorsInitialsDelim..., end with a space) + $output = preg_replace("/ +([,.;:?!()]|$)/", "\\1", $output); // remove excess spaces before [,.;:?!()] and from the end of the author string + + return $output; +} + +function theme_biblio_author_link($variables) { + $base = variable_get('biblio_base', 'biblio'); + $author = $variables['author']; + $options = isset($variables['options']) ? $variables['options'] : array(); + + $link_to_profile = variable_get('biblio_author_link_profile', 0); + $link_to_profile_path = variable_get('biblio_author_link_profile_path', 'user/[user:uid]'); + + $uri = drupal_parse_url(request_uri()); + $uri = array_merge($uri, $options); + if (!isset($uri['attributes'])) { + $uri['attributes'] = array('rel' => 'nofollow'); + } + $path = $uri['path']; + + if (isset($author['drupal_uid']) && $author['drupal_uid'] > 0) { + $uri['attributes'] += array('class' => array('biblio-local-author')); + } + if (variable_get('biblio_links_target_new_window', null)){ + $uri['attributes'] += array('target'=>'_blank'); + $uri['html'] = TRUE; + } + + if ($link_to_profile && isset($author['drupal_uid']) && $author['drupal_uid'] > 0) { + $data['user'] = user_load($author['drupal_uid']); + $path = token_replace($link_to_profile_path, $data); + $alias = drupal_get_path_alias($path); + $path_profile = variable_get('biblio_show_profile', '0') ? "$path/$base" : $alias; + return l(trim($author['name']), $path_profile, $uri); + } + else { + $uri['path'] = variable_get('biblio_base', 'biblio'); + $uri['query']['f']['author'] = $author['cid']; + return l(trim($author['name']), $uri['path'], $uri ); + } + +} + +// Format page information: +// +// NOTES: - this function (and refbase in general) assumes following rules for the original formatting of page information in '$orig_page_info': +// - single-page items are given as a page range with identical start & end numbers (e.g. "127-127") +// - multi-page items are given as a page range where the end number is greater than the start number (e.g. "127-132") +// - for multi-page items where only the start page is known, a hyphen is appended to the start page (e.g. "127-") +// - total number of pages are given with a "pp" suffix (e.g. "498 pp"), see TODO +// - the given page info is left as is if it does not match any of the above rules (e.g. a single page number is ambiguous since it +// could mean a single page or the total number of pages) +// - the function attempts to deal with page locators that contain letters (e.g. "A1 - A3" or "4a-4c") but, ATM, locator parts (e.g. "A1") +// must contain at least one digit character & must not contain any whitespace +// +// TODO: - should we only use Unicode-aware regex expressions (i.e. always use '$space', '$digit' or '$word' instead of ' ', '\d' or '\w', etc)? +// - recognize & process total number of pages +// - for '$shortenPageRangeEnd=TRUE', add support for page locators that contain letters (e.g. "A1 - A3" or "4a-4c") +function theme_biblio_page_number($variables) { + $orig_page_info = $variables['orig_page_info']; + $page_range_delim = $variables['page_range_delim']; + $single_page_prefix = $variables['single_page_prefix']; + $page_range_prefix = $variables['page_range_prefix']; + $total_pages_prefix = $variables['total_pages_prefix']; + $single_page_suffix = $variables['single_page_suffix']; + $page_range_suffix = $variables['page_range_prefix']; + $total_pages_suffix = $variables['total_pages_prefix']; + $shorten_page_range_end = $variables['single_page_suffix']; + + list($alnum, $alpha, $cntrl, $dash, $digit, $graph, $lower, + $print, $punct, $space, $upper, $word, $patternModifiers) = _biblio_get_regex_patterns(); + + // Check original page info for any recognized page locators, and process them appropriately: + if (preg_match("/\w*\d+\w* *[$dash]+ *(?:\w*\d+\w*)?/$patternModifiers", $orig_page_info)) {// the original page info contains a page range (like: "127-127", "127-132", "A1 - A3", "4a-4c", or "127-" if only start page given) + // Remove any whitespace around dashes or hyphens that indicate a page range: + $orig_page_info = preg_replace("/(\w*\d+\w*) *([$dash]+) *(\w*\d+\w*)?(?=[^\w\d]|$)/$patternModifiers", "\\1\\2\\3", $orig_page_info); + + // Split original page info into its functional parts: + // NOTE: ATM, we simply split on any whitespace characters, then process all parts with page ranges + // (this will also reduce runs of whitespace to a single space) + $partsArray = preg_split("/ +/", $orig_page_info); + $partsCount = count($partsArray); + + for ($i=0; $i < $partsCount; $i++) { + // Format parts with page ranges: + // - single-page item: + if (preg_match("/(\w*\d+\w*)[$dash]+\\1(?=[^\w\d]|$)/$patternModifiers", $partsArray[$i])) // this part contains a page range with identical start & end numbers (like: "127-127") + $partsArray[$i] = preg_replace("/(\w*\d+\w*)[$dash]+\\1(?=[^\w\d]|$)/$patternModifiers", $single_page_prefix . "\\1" . $single_page_suffix, $partsArray[$i]); + + // - multi-page item: + elseif (preg_match("/\w*\d+\w*[$dash]+(?:\w*\d+\w*)?(?=[^\w\d]|$)/$patternModifiers", $partsArray[$i])) {// this part contains a page range (like: "127-132", or "127-" if only start page given) + // In case of '$shorten_page_range_end=TRUE', we abbreviate ending page numbers so that digits aren't repeated unnecessarily: + if ($shorten_page_range_end AND preg_match("/\d+[$dash]+\d+/$patternModifiers", $partsArray[$i])) {// ATM, only digit-only page locators (like: "127-132") are supported + // NOTE: the logic of this 'if' clause doesn't work if the original page info contains something like "173-190; 195-195" (where, for the first page range, '$endPage' would be "190;" and not "190") + list($startPage, $endPage) = preg_split("/[$dash]+/$patternModifiers", $partsArray[$i]); + + $countStartPage = strlen($startPage); + $countEndPage = strlen($endPage); + + if (($countStartPage == $countEndPage) AND ($startPage < $endPage)) { + for ($j=0; $j < $countStartPage; $j++) { + if (preg_match("/^" . substr($startPage, $j, 1) . "/", $endPage)) {// if the ending page number has a digit that's identical to the starting page number (at the same digit offset) + $endPage = substr($endPage, 1); // remove the first digit from the remaining ending page number + } + else { + break; + } + } + } + + $partsArray[$i] = $page_range_prefix . $startPage . $page_range_delim . $endPage . $page_range_suffix; + } + else {// don't abbreviate ending page numbers: + $partsArray[$i] = preg_replace("/(\w*\d+\w*)[$dash]+(\w*\d+\w*)?(?=[^\w\d]|$)/$patternModifiers", $page_range_prefix . "\\1" . $page_range_delim . "\\2" . $page_range_suffix, $partsArray[$i]); + } + } + } + + $newPageInfo = join(" ", $partsArray); // merge again all parts + } + else { + $newPageInfo = $orig_page_info; // page info is ambiguous, so we don't mess with it + } + + return $newPageInfo; +} + + +/** + * Applies a "style" function to a single node. + * + * @param $node A node + * @param $style_name The name of the style to apply + * @return A string containing the styled (HTML) node + */ +function theme_biblio_style($variables ) { + $node = $variables['node']; + $style_name = $variables['style_name']; + $styled_node = ''; + module_load_include('inc', 'biblio', "/styles/biblio_style_$style_name"); + + $style_function = "biblio_style_$style_name"; + if (function_exists($style_function)) { + $styled_node = $style_function ($node); + } + else { + drupal_set_message(t('The style function: @funct does not exist', array('@funct' => $style_function)), 'error'); + } + return ($styled_node . filter_xss($node->biblio_coins, array('span'))); +} + +/** + * @param $node + * @param $base + * @param $style + * @return unknown_type + */ +function theme_biblio_entry($variables) { + $node = $variables['node']; + $style_name = $variables['style_name']; + + $output = "\n" . '
' . "\n" ; + $output .= '
' . "\n" ; + if (!$node->status) { + $output .= '
'; + } + + // first add the styled entry... + $output .= theme('biblio_style', array('node' => $node, 'style_name' => $style_name)); + + // now add the various links +// if ($node->biblio_abst_e) { +// $output .= ''; +// $output .= l(" Abstract", "node/$node->nid") . "\n"; +// $output .= ''; +// } + $annotation_field = variable_get('biblio_annotations', 'none'); + if ($annotation_field != 'none' && $node-> $annotation_field) { + $output .= '
'; + $output .= filter_xss($node->$annotation_field, biblio_get_allowed_tags()); + $output .= '
'; + } + $openurl_base = variable_get('biblio_baseopenurl', ''); + + if ($openurl_base) { + $output .= theme('biblio_openurl', array('openURL' => biblio_openurl($node))); + } + + if (biblio_access('export')) { + $base = variable_get('biblio_base', 'biblio'); + $output .= theme('biblio_export_links', array('node' => $node)); + } + + if (biblio_access('download', $node)) { + // add links to attached files (if any) + $output .= theme('biblio_download_links', array('node' => $node)); + } + if (!$node->status) { + $output .= '
'; + } + + $output .= "\n
"; + + return $output; +} + +/** + * @param $form + * @return unknown_type + */ +function theme_biblio_filters($variables) { + $form = $variables['form']; + $output = ''; + if (isset($form['current'])) { + $output .= '
    '; + foreach (element_children($form['current']) as $key) { + $output .= '
  • ' . drupal_render($form['current'][$key]) . '
  • '; + } + $output .= '
'; + } + $output .= '
' . (isset($form['current']) ? '
' . t('and') . ' ' . t('where') . '
' : '') . '
'; + foreach (element_children($form['filter']) as $key) { + $output .= drupal_render($form['filter'][$key]); + } + $output .= '
'; + $output .= '
' . t('is') . '
'; + foreach (element_children($form['status']) as $key) { + $output .= drupal_render($form['status'][$key]); + } + $output .= '
'; + $output .= '
'; + $output .= '
' . drupal_render($form['buttons']) . '
'; + $output .= '
'; + return $output; +} + +/** + * @param $form + * @return unknown_type + */ +function theme_biblio_form_filter($variables) { + $form = $variables['form']; + + $output .= '
'; + $output .= drupal_render($form['filters']); + $output .= '
'; + $output .= drupal_render($form); + return $output; +} + +function theme_biblio_field_tab($variables) { + $form = $variables['form']; + $rows = array(); + $headers = $form['#header']; + drupal_add_tabledrag($form['#id'], 'order', 'sibling', 'weight'); + + foreach (element_children($form['rows']) as $key) { + // No need to print the field title every time. +// unset($form[$key]['name']['#title'], $form[$key]['auth_type']['#title'], $form[$key]['auth_category']['#title']); + // Add class to group weight fields for drag and drop. + $form['rows'][$key]['weight']['#attributes']['class'] = array('weight'); + + // Build the table row. + $row = array(''); + $row[] = array('data' => drupal_render($form['rows'][$key]['name'])); + $row[] = array('data' => drupal_render($form['rows'][$key]['title'])); + $row[] = array('data' => drupal_render($form['rows'][$key]['hint'])); + foreach (element_children($form['rows'][$key]['checkboxes']) as $oid) { + if (is_array($form['rows'][$key]['checkboxes'])) { + $row[] = array( + 'data' => drupal_render($form['rows'][$key]['checkboxes'][$oid]), + 'title' => $oid); + } + } + + + $row[] = drupal_render($form['rows'][$key]['weight']); + $rows[] = array('data' => $row, 'class' => array('draggable')); + } + $output = theme('table', array('header' => $headers, 'rows' => $rows, 'attributes' => array('id' => $form['#id']))); + $output .= drupal_render_children($form); + return $output; + +} +/** + * @param $form + * @return unknown_type + */ +function theme_biblio_admin_types_edit_form($variables) { + $form = $variables['form']; + $output = ''; + + $output .= drupal_render($form['help']); + $output .= drupal_render($form['pub_type']); + $output .= drupal_render($form['change_type']); + if (isset($form['type_name'])) { + $output .= drupal_render($form['type_name']); + } + $output .= drupal_render($form['biblio_tabs']); + $output .= drupal_render_children($form); + return $output; +} + +function theme_biblio_download_links($variables) { + static $langcode = NULL; + $file_links = array(); + $node = $variables['node']; + if (!isset($langcode)) { + $langcode = $GLOBALS['language_content']->language; + } + + $fields = field_attach_view('node', $node, 'full', $langcode); + foreach (element_children($fields) as $field) { + if($fields[$field]['#access'] && $fields[$field]['#field_type'] == 'file') { + foreach ($fields[$field]['#items'] as $delta => $item) { + if (module_exists('filefield_paths')) { + $alias = drupal_get_path_alias('filefield_paths/alias/' . $item['fid']); + } + $link_type = variable_get('biblio_file_link_type', 'text'); + if ($link_type == 'icon') { + $url = file_create_url($item['uri']); + $icon = theme('file_icon', array('file' => (object) $item)); + $options['html'] = TRUE; + $options['attributes']['title'] = check_plain($item['filename']); + $file_links[] = array( + l($icon, $url, $options), + format_size($item['filesize']), + ); + } + elseif ($link_type == 'text') { + $file_links[] = array( + theme('file_link', array('file' => (object) $item)), + format_size($item['filesize']), + ); + } + } + } + } + $files = ''; + if (count($file_links) > 0 && (user_access('show download links') || user_access('show own download links'))) { + $files .= ''; + // $files .= ' ' . t('Download') . ': '; + $file_count = 0; + foreach ($file_links as $file) { + $files .= $file[0] . ' (' . $file[1] . ')'; + + } + $files .= ''; + } + + return $files; +} + +/** + * Creates a group of links for the various export functions + * @param $nid the node id to export (if omitted, all nodes in the current view will be exported + * @return an un-ordered list of class "biblio-export-buttons" + */ +function theme_biblio_export_links($variables) { + global $pager_total_items; + $node = $variables['node']; + $filter = ($variables['node'] == NULL && isset($variables['filter'])) ? $variables['filter'] : array(); + $links = array(); + $output = ''; + + if (biblio_access('export')) { + $show_link = variable_get('biblio_lookup_links', array('google' => TRUE)); + $lookup_links = module_invoke_all('biblio_lookup_link', $node); + if ($show_link['google'] && !empty($node)) { + $lookup_links['biblio_google_scholar'] = theme('google_scholar_link', array('node' => $node)); + } + $nid = (isset($node->nid)) ? $node->nid : NULL; + $export_links = module_invoke_all('biblio_export_link', $nid, $filter); + $links = array_merge($lookup_links, $export_links); + } + if (empty($node) && !empty($links)) { + $output = t('Export @count results', array('@count' => $pager_total_items[0])) . ': '; + } + + return $output . theme('links', array('links' => $links, 'attributes' => array('class' => array('biblio-export-buttons')))); +} + + +function theme_google_scholar_link($variables) { + $node = $variables['node']; + $query = array(); + + $query['btnG'] = 'Search+Scholar'; + $query['as_q'] = '"' . str_replace(array(' ', '(', ')'), array('+'), $node->title) . '"'; // as_q = all the words + if (isset($node->biblio_contributors[0]['lastname'])) { + $query['as_sauthors'] = $node->biblio_contributors[0]['lastname']; + } + $query['as_occt'] = 'any'; + $query['as_epq'] = ''; // exact phrase + $query['as_oq'] = ''; // at least one of the words + $query['as_eq'] = ''; // without the words + $query['as_publication'] = ''; // published in + $query['as_ylo'] = ''; // lower date in date range + $query['as_yhi'] = ''; // upper date in date range + $query['as_sdtAAP'] = 1; //Search articles in all subject areas + $query['as_sdtp'] = 1; //include patents + + $attrs = array('title' => t("Click to search Google Scholar for this entry")); + if (variable_get('biblio_links_target_new_window', NULL)){ + $attrs = array_merge($attrs, array('target '=> '_blank')); + } + + $attrs = array_merge($attrs, array('rel' => 'nofollow')); + + return array( + 'title' => t('Google Scholar'), + 'href' => 'http://scholar.google.com/scholar', + 'attributes' => $attrs, + 'query' => $query, + ); +} + +/** + * @param $form + * @return unknown_type + */ +function theme_biblio_contributors($variables) { + $form = $variables['form']; + $rows = array(); + $headers = array('', t('Name'), t('Category'), t('Role'), t('Weight')); + drupal_add_tabledrag($form['#id'], 'order', 'sibling', 'rank'); + + foreach (element_children($form) as $key) { + // No need to print the field title every time. +// unset($form[$key]['name']['#title'], $form[$key]['auth_type']['#title'], $form[$key]['auth_category']['#title']); + // Add class to group weight fields for drag and drop. + $form[$key]['rank']['#attributes']['class'] = array('rank'); + + // Build the table row. + $row = array(''); + $row[] = array('data' => drupal_render($form[$key]['name']), + 'class' => array('biblio-contributor')); + $row[] = array('data' => drupal_render($form[$key]['auth_category']), + 'class' => array('biblio-contributor-category')); + $row[] = array('data' => drupal_render($form[$key]['auth_type']), + 'class' => array('biblio-contributor-type')); + $row[] = drupal_render($form[$key]['rank']); + $rows[] = array('data' => $row, 'class' => array('draggable')); + } + $output = theme('table', array('header' => $headers, 'rows' => $rows, 'attributes' => array('id' => $form['#id']))); + //$output .= drupal_render_children($form); + return $output; +} + +/** + * This function creates a string of letters (A - Z), which + * depending on the sorting are either linked to author or title + * filters i.e. clicking on the A when in the listing is sorted by + * authors will bring up a list of all the entries where the first + * character of the primary authors last name is "A" + * + * @param $type either "author or title" + * @return a chunk of HTML code as described above + */ +function theme_biblio_alpha_line($variables) { + $type = $variables['type']; + $all = ''; + $uri = drupal_parse_url(request_path()); + + //replace path in case we are in a multi-language environment, otherwise we end up with double language prefixes. + $languages = language_list('enabled'); + if (isset($languages[1])) { + $path_parts = empty($uri['path']) ? array() : explode('/', $uri['path']); + foreach ($languages[1] as $code => $lang) { + if ($path_parts[0] == $code) { + array_shift($path_parts); + break; + } + } + $uri['path'] = implode('/', $path_parts); + } + + $uri['attributes'] = array('rel' => 'nofollow'); + $all_uri = $uri; + $current = ''; + + switch ($type) { + case 'authors': + $filter = 'author'; + $current = isset($uri['query']['f']['author']) ? $uri['query']['f']['author'] : ''; + unset($all_uri['query']['f']['author']); + break; + case 'keywords': + case 'keyword': + $filter = 'keyword'; + $current = isset($uri['query']['f']['keyword']) ? $uri['query']['f']['keyword'] : ''; + unset($all_uri['query']['f']['keyword']); + break; + case 'author': + $current = isset($uri['query']['f']['ag']) ? $uri['query']['f']['ag'] : ''; + $filter = 'ag'; + if (!isset($uri['query']['s'])) $uri['query']['s'] = 'author'; + unset($all_uri['query']['f']['ag']); + break; + case 'title': + $current = isset($uri['query']['f']['tg']) ? $uri['query']['f']['tg'] : ''; + $filter = 'tg'; + unset($all_uri['query']['f']['tg']); + break; + default: + } + $output = '
'; +//TODO for Cyrillic use 1040 to 1071... e.g. Ь + + for ($i = 65; $i <= 90; $i++) { + if ($i == ord($current)) { + $output .= '[' . chr($i) . '] '; + } + else{ + $uri['query']['f'][$filter] = chr($i); + $output .= l(chr($i), $uri['path'], $uri) . ' '; + } + } + if ($current) { + if (empty($all_uri['query']['f'])) unset($all_uri['query']['f']); + $output .= '  ' . '[' . l(t('Show ALL'), $all_uri['path'], $all_uri) . ']'; + } + $output .= '
'; + return $output; +} + +/** + * Themes the author editing form + * + * @param $form + * @return rendered form + */ +function theme_biblio_admin_author_edit_form($variables) { + $form = $variables['form']; + $rows = array(); + $rows[] = array( + array('data' => drupal_render($form['prefix'])), + array('data' => drupal_render($form['firstname'])), + array('data' => drupal_render($form['initials'])), + array('data' => drupal_render($form['lastname'])), + array('data' => drupal_render($form['suffix']))); + $rows[] = array(array('data' => drupal_render($form['name']) . drupal_render($form['literal']), 'colspan' => 5)); + $rows[] = array(array('data' => drupal_render($form['affiliation']), 'colspan' => 5)); + $rows[] = array(array('data' => drupal_render($form['drupal_uid']), 'colspan' => 5)); + + $output = theme('table', array('rows' => $rows)); + $output .= drupal_render($form['merge']); + $output .= drupal_render($form['link']); + $output .= drupal_render_children($form); + return $output; + +} + +function theme_biblio_admin_author_edit_merge_table($variables) { + $form = $variables['form']; + $headers = $form['#header']; + $rows = array(); + + foreach (element_children($form['candidates']) as $key) { + + // Build the table row. + $row = array(); + $row[] = array('data' => drupal_render($form['candidates'][$key]['name'])); + $row[] = drupal_render($form['candidates'][$key]['link']); + $row[] = drupal_render($form['candidates'][$key]['merge']); + $row[] = drupal_render($form['candidates'][$key]['retain']); + $rows[] = $row; + } + + $output = theme('table', array('header' => $headers, 'rows' => $rows, 'attributes' => array('id' => $form['#id']))); + + $row = $rows = array(); + $row[] = array('data' => drupal_render($form['more_authors_search']) . drupal_render($form['more_authors_add'])); + $rows[] = $row; + $output .= theme('table', array('header' => array(), 'rows' => $rows, 'attributes' => array('id' => $form['#id']))); + + $output .= drupal_render_children($form); + + return $output; +} + +function _biblio_keyword_links($keywords, $base='biblio') { + $uri = drupal_parse_url(request_uri()); + $uri['path'] = variable_get('biblio_base', 'biblio');; + $uri['attributes'] = array('rel' => 'nofollow'); + $html = ""; + if (!is_array($keywords)) { + require_once(drupal_get_path('module', 'biblio') . '/includes/biblio.keywords.inc'); + $keywords = biblio_explode_keywords($keywords); + } + + $sep = variable_get('biblio_keyword_sep', ','); + foreach ($keywords as $kid => $keyword ) { + $uri['query']['f']['keyword'] = $kid; + $linked_keywords [] = l(trim($keyword), $base , $uri); + } + return implode("$sep ", $linked_keywords); +} + + +function template_preprocess_biblio_sort_tabs(&$vars) { + $vars['tabs_style'] = variable_get('biblio_sort_tabs_style', 0); + + $uri = drupal_parse_url(request_uri()); + $uri['path'] = $_GET['q']; + $uri['path'] = trim($uri['path'], '/'); + + $defaults = array( + 'author' => 'asc', + 'title' => 'asc', + 'type' => 'asc', + 'year' => 'desc', + 'keyword' => 'asc', + ); + + if (isset($uri['query']['s'])) { + $sort = $uri['query']['s']; + } + else { + $sort = variable_get('biblio_sort', 'year'); + } + + if (isset($uri['query']['o'])) { + $order = strtolower($uri['query']['o']); + } + else { + $order = strtolower(variable_get('biblio_order', 'desc')); + } + // flip it + $order = ($order == 'desc') ? 'asc' : 'desc'; + $path = drupal_get_path('module', 'biblio'); + $order_arrow = ($order == 'asc') ? theme('image', array('path' => $path.'/misc/arrow-asc.png', 'alt' => '(Asc)')): + theme('image', array('path' => $path.'/misc/arrow-desc.png', 'alt' => '(Desc)')); + + $sort_links = array_filter(variable_get('biblio_sort_tabs', array('author' => 'author', 'title' => 'title', 'type' => 'type', 'year' => 'year', 'keyword' => 'keyword'))); + ksort($sort_links); + + $links = array(); + foreach ($sort_links as $key => $title) { + $uri_copy = $uri; + $uri_copy['attributes'] = array("title" => t("Click a second time to reverse the sort order")); + $uri_copy['html'] = TRUE; + $uri_copy['text'] = t(ucfirst($title)); + $uri_copy['query']['s'] = $title; + if ($key === $title && $title == $sort) { + $uri_copy['query']['o'] = $order; + $uri_copy['attributes']['class'][] = "active"; + $uri_copy['active'] = TRUE; + $uri_copy['pfx'] = ' [ '; + $uri_copy['sfx'] = '] '; + $uri_copy['arrow'] = $order_arrow; + + } + elseif ($key === $title ) { + $uri_copy['query']['o'] = $defaults[$title]; + $uri_copy['active'] = FALSE; + $uri_copy['pfx'] = ' '; + $uri_copy['sfx'] = ' '; + $uri_copy['arrow'] = ''; + } + $links[] = $uri_copy; + } + $vars['links'] = $links; +} + +function theme_biblio_sort_tabs($vars) { + $links = $vars['links']; + $style = $vars['tabs_style']; + $output = ''; + + if ($style) { + $output = '
    '; + } + foreach ($links as $l) { + $output .= _biblio_sort_tab($l, $style); + } + + if ($style) { + $output .= '
'; + } + + return $output; +} + +function _biblio_sort_tab($tab, $tabs = FALSE) { + if ($tabs) { + $text = '' . $tab['text'] . $tab['arrow'] . ''; + $class = ($tab['active']) ? 'class="active"':''; + $link = l($text, $tab['path'], $tab); + return "
  • ". $link . '
  • '; + } + else { + return $tab['pfx'] . l($tab['text'], $tab['path'], $tab) . $tab['arrow'] . $tab['sfx']; + } + return; +} \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/includes/biblio_xml.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/includes/biblio_xml.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,68 @@ +appendChild(new DOMElement('biblio_collection')); + $biblio_collection->setAttribute("Schema", "6010"); + $comment = $biblio_collection->appendChild(new DOMComment('Generated by the Biblio module from Drupal (http://drupal.org/project/biblio)')); + $db_result = db_query("SELECT nr.nid, nr.vid FROM {node_revision} nr join node n on nr.nid=n.nid where n.type='biblio' order by nr.nid, nr.vid"); + while($n=db_fetch_object($db_result)) { + $node = node_load($n->nid,$n->vid); + if ($n->nid == $nid) { + $revision = $domnode->appendChild(new DOMElement('revision')); + $node = (array)$node; + AtoX($node, $dom, $revision); + }else{ + $domnode = $biblio_collection->appendChild(new DOMElement('node')); + $node = (array)$node; + AtoX($node, $dom, $domnode); + } + $nid = $n->nid; + + } + return $dom->saveXML(); +} + +function AtoX($array, $DOM=null, $root=null) { + foreach ($array as $key => $value) { + if ($key == 'biblio_contributors') $name = 'contributor'; + if (is_numeric($key)) $key = 'c_' . $key; + if (is_array($value ) && count($value)) { + $subroot = $root->appendChild($DOM->createElement($key)); + AtoX($value, $DOM, $subroot); + } + else { + if (!empty($value)) { + $root->appendChild($DOM->createElement($key, htmlspecialchars($value, ENT_QUOTES))); + } + } + } + + return $DOM; +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/misc/arrow-asc.png Binary file modules/biblio/misc/arrow-asc.png has changed diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/misc/arrow-desc.png Binary file modules/biblio/misc/arrow-desc.png has changed diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/misc/biblio.field.link.data.csv --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/misc/biblio.field.link.data.csv Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,54 @@ +fid,title,hint, common, autocomplete, required, weight, visible,field name,type,width,maxlength,vtab +1,Authors,,1,1,1,1,1,biblio_authors,contrib_widget,60,255,1 +2,Secondary Authors,,1,1,1,2,1,biblio_secondary_authors,contrib_widget,60,255,1 +3,Tertiary Authors,,1,1,1,3,1,biblio_tertiary_authors,contrib_widget,60,255,1 +4,Subsidiary Authors,,1,1,1,4,1,biblio_subsidiary_authors,contrib_widget,60,255,1 +5,Corporate Authors,,1,1,1,5,1,biblio_corp_authors,contrib_widget,60,255,1 +6,Secondary Title,,0,0,0,12,0,biblio_secondary_title,textfield,60,255,2 +7,Tertiary Title,,0,0,0,13,0,biblio_tertiary_title,textfield,60,255,8 +8,Accession Number,,1,0,0,151,1,biblio_accession_number,textfield,24,128,4 +9,ISBN Number,,1,0,0,150,1,biblio_isbn,textfield,24,128,4 +10,Call Number,,1,0,0,152,1,biblio_call_number,textfield,24,128,4 +11,Other Numbers,,1,0,0,153,1,biblio_other_number,textfield,10,128,4 +12,Other Author Affiliations,,0,0,0,24,0,biblio_other_author_affiliations,textfield,60,255,9 +13,Publisher,,0,0,0,19,0,biblio_publisher,textfield,60,255,3 +14,Place Published,,0,0,0,20,0,biblio_place_published,textfield,60,255,3 +15,Year of Publication,"Enter YYYY, Submitted or In Press",1,0,1,-45,1,biblio_year,textfield,4,20,2 +16,Edition,,0,0,0,15,0,biblio_edition,textfield,60,255,2 +17,Volume,,0,0,0,14,0,biblio_volume,textfield,10,128,2 +18,Number,,0,0,0,16,0,biblio_number,textfield,10,128,2 +19,Pagination,,0,0,0,17,0,biblio_pages,textfield,24,128,2 +20,Date Published,(mm/yyyy),0,0,0,18,0,biblio_date,textfield,16,16,2 +21,Publication Language,,0,0,0,23,0,biblio_lang,textfield,24,24,2 +22,Abstract,,1,0,0,155,1,biblio_abst_e,text_format,60,65535,1 +23,French Abstract,,0,0,0,156,0,biblio_abst_f,text_format,60,65535,9 +24,Keywords,,1,1,0,154,0,biblio_keywords,textfield,60,1000,6 +25,Type of Work,Masters Thesis,0,0,0,22,0,biblio_type_of_work,textfield,60,255,2 +26,URL,,1,0,0,158,1,biblio_url,textfield,60,255,5 +27,Notes,,0,0,0,157,0,biblio_notes,text_format,60,65535,7 +28,Issue,,0,0,0,15,0,biblio_issue,textfield,10,128,2 +29,Reseach Notes,,0,0,0,160,0,biblio_research_notes,text_format,60,65535,7 +30,Custom 1,,0,0,0,161,0,biblio_custom1,text_format,60,65535,9 +31,Custom 2,,0,0,0,162,0,biblio_custom2,text_format,60,65535,9 +32,Custom 3,,0,0,0,163,0,biblio_custom3,text_format,60,65535,9 +33,Custom 4,,0,0,0,164,0,biblio_custom4,text_format,60,65535,9 +34,Custom 5,,0,0,0,165,0,biblio_custom5,text_format,60,65535,9 +35,Custom 6,,0,0,0,167,0,biblio_custom6,text_format,60,65535,9 +36,Custom 7,,0,0,0,168,0,biblio_custom7,text_format,60,65535,9 +37,Number of Volumes,,0,0,0,15,0,biblio_number_of_volumes,textfield,10,128,2 +38,Short Title,,0,0,0,169,0,biblio_short_title,textfield,60,255,8 +39,Alternate Title,,0,0,0,170,0,biblio_alternate_title,textfield,60,255,8 +40,Translated Title,,0,0,0,170,0,biblio_translated_title,textfield,60,255,8 +41,Original Publication,,0,0,0,171,0,biblio_original_publication,textfield,60,255,8 +42,Reprint Edition,,0,0,0,172,0,biblio_reprint_edition,textfield,120,255,2 +43,Section,,0,0,0,15,0,biblio_section,textfield,10,128,2 +44,Citation Key,,0,0,0,175,0,biblio_citekey,textfield,16,255,4 +45,COinS Data,This will be automatically generated,0,0,0,176,0,biblio_coins,text_format,60,65535,9 +46,ISSN Number,,0,0,0,150,0,biblio_issn,textfield,24,128,4 +47,DOI,,1,0,0,159,1,biblio_doi,textfield,60,255,5 +48,Author Address,,0,0,0,178,0,biblio_auth_address,text_format,60,65535,9 +49,Remote Database Name,,0,0,0,176,0,biblio_remote_db_name,textfield,60,255,9 +50,Remote Database Provider,,0,0,0,177,0,biblio_remote_db_provider,textfield,60,255,9 +51,Label,,0,0,0,178,0,biblio_label,textfield,60,255,9 +52,Access Date,,0,0,0,179,0,biblio_access_date,textfield,60,255,9 +53,Refereed Designation,,0,0,0,180,0,biblio_refereed,select,0,128,9 diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/misc/biblio.field.type.data.csv --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/misc/biblio.field.type.data.csv Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,40 @@ +,tid,biblio_year,title,biblio_secondary_title,biblio_tertiary_title,biblio_short_title,biblio_secondary_authors,biblio_tertiary_authors,biblio_subsidiary_authors,biblio_corp_authors,biblio_alternate_title,biblio_place_published,biblio_publisher,biblio_volume,biblio_number_of_volumes,biblio_number,biblio_issue,biblio_pages,biblio_section,biblio_edition,biblio_date,biblio_type_of_work,biblio_issn,,biblio_original_publication,biblio_reprint_edition,,biblio_custom1,biblio_custom2,biblio_custom3,biblio_custom4,biblio_custom5,biblio_custom6,biblio_custom7,biblio_abst_e,biblio_refereed +Generic ,,Year ,Title ,Secondary Title ,Tertiary Title ,Short Title ,Editor ,Tertiary Author ,Subsidiary Author ,Corporate Author,Alternate Title ,Place Published ,Publisher ,Volume ,Number of Volumes ,Number ,Issue,Pages ,Section ,Edition ,Date ,Type of Work ,ISBN/ISSN ,Electronic Resource Number ,Original Publication ,Reprint Edition ,Reviewed Item ,Custom 1 ,Custom 2 ,Custom 3 ,Custom 4 ,Custom 5 ,Custom 6 ,Custom 7 ,Abstract ,Refereed Designation +Ancient Text ,,,,Publication Title ,Volume Title ,,Editor ,~,Translator ,,Abbreviated Publication ,City ,,,,,~,,~,,,,ISBN ,,,,Reviewed Item ,~,~,~,~,~,~,~,, +Artwork ,112,,,~,~,,~,~,~,,,City ,,~,~,~,~,Description ,~,~,,,~,,~,~,,~,~,~,~,~,~,~,, +Audiovisual Material ,114,,,Series Title ,~,,Series Editor ,~,Performers ,,,City ,,~,Extent of Work ,Number ,~,~,~,,,Type ,ISBN ,,Contents ,~,,Cast ,Credits ,~,~,Format ,~,~,, +Bill ,117,,,Code ,Legislative Body ,,~,~,Sponsor ,,~,~,~,Code Volume ,~,Bill Number ,~,Code Pages ,Code Section ,Session ,,~,~,,History ,~,,~,~,~,~,~,~,~,, +Book ,100,,,Series Title ,~,,Series Editor ,~,Translator ,,Abbreviation ,City ,,,,Series Volume ,~,Number of Pages ,~,,~,~,ISBN ,,,,~,~,~,~,~,~,~,~,, +Book Section ,101,,,Book Title ,Series Title ,,Editor ,Series Editor ,Translator ,,Abbreviation ,City ,,,,Series Volume ,~,,Chapter ,,~,~,ISBN ,,,,,~,~,~,~,~,~,~,, +Case ,116,,Case Name ,Reporter ,~,Abbreviated Case Name ,~,~,Counsel ,,~,~,Court ,Reporter Volume ,Reporter Abbreviation ,~,~,First Page ,Page Cited ,~,Date Decided ,~,~,,History ,~,~,~,~,~,~,~,~,~,, +Classical Work ,127,,,Series Title ,~,,Series Editor ,~,Translator ,,,City ,,,,Series Volume ,~,Number of Pages ,~,,~,Type ,ISSN/ISBN ,,,,~,~,~,~,~,~,~,~,, +Computer Program ,113,,,Series Title ,~,,Series Editor ,~,~,,,City ,,~,~,~,~,Description ,~,Version ,~,Type ,ISBN ,,Contents ,~,~,Computer ,~,~,~,~,~,~,, +Conference Paper ,103,,,Conference Name ,~,~,Editor ,~,~,,~,Conference Location ,,~,~,~,~,~,~,~,,~,~,,~,~,~,~,~,~,~,~,~,~,, +Conference Proceeding ,104,Year of Conference ,,Conference Name ,Series Title ,,Editor ,Series Editor ,Sponsor ,,~,Conference Location ,,,,~,~,,~,,,~,ISBN ,,~,~,~,~,~,~,~,~,~,~,, +Chart or Table ,123,,,Image Source Program ,Name of File ,~,~,~,~,,~,City ,,Image Size ,~,,~,Description ,~,Version ,,Type of Image ,~,,~,~,~,~,~,~,~,~,~,~,, +Dictionary ,,,,Dictionary Title ,~,,Editor ,~,Translator ,,Abbreviation ,City ,,,,,~,,~,,~,~,ISBN ,,,,,~,~,~,~,~,~,~,, +Edited Book ,,,,Series Title ,~,,Series Editor ,~,Translator ,,,City ,,,,Series Volume ,~,Number of Pages ,~,,~,~,ISBN ,,,,,~,~,~,~,~,~,~,, +Electronic Article ,,,,Periodical Title ,~,~,,~,~,,,~,~,,~,~,,,~,~,Date Accessed ,~,ISSN ,,~,~,~,~,~,~,~,~,~,~,, +Electronic Book ,,,,Secondary Title ,~,~,Editor ,~,~,,~,~,,,~,~,~,~,~,~,Date Accessed ,Type of Medium ,ISBN ,,~,~,~,~,~,~,~,~,~,~,, +Equation ,,,,Image Source Program ,Name of File ,~,~,~,~,,~,City ,,Image Size ,~,,~,Description ,~,Version ,,Type of Image ,~,,~,~,~,~,~,~,~,~,~,~,, +Encyclopedia ,,,,Encyclopedia Title ,~,,Editor ,~,Translator ,,Abbreviation ,City ,,,,~,~,,~,,,~,ISBN ,,,,,~,~,~,~,~,~,~,, +Figure ,,,,Image Source Program ,Name of File ,~,~,~,~,,~,City ,,Image Size ,~,,~,Description ,~,Version ,,Type of Image ,~,,~,~,~,~,~,~,~,~,~,~,, +Film or Broadcast ,110,Year Released ,,Series Title ,~,,Series Director ,Producer ,Performers ,,,Country ,,~,~,~,~,Running Time ,~,,Date Released ,Medium ,~,,~,~,~,Cast ,Credits ,~,Genre ,Format ,~,~,Synopsis , +Government Document ,126,,,~,Series Title ,~,Department ,~,~,,~,~,,,~,~,,,Section ,,~,~,Report Number ,,~,~,~,Government Body ,Congress Number ,Congress Session ,~,~,~,~,, +Grant ,,,Title of Grant ,~,~,,~,~,Translator ,,Abbreviation ,Activity Location ,Sponsoring Agency ,Amount Requested ,Amount Received ,Status ,~,,Duration of Grant ,Requirements ,Deadline ,Funding Type ,~,,Original Grant Number ,Review Date ,,Contact Name ,Contact Address ,Contact Phone ,Contact Fax ,Funding Number ,CFDA Number ,~,, +Hearing ,115,,,Committee ,Legislative Body ,,~,~,~,,~,City ,,~,,Document Number ,~,,~,Session ,,~,~,,History ,~,~,~,~,~,~,~,~,~,, +Journal Article ,102,,,Journal ,~,,~,~,~,,Alternate Journal ,~,~,,~,~,,,Start Page ,~,,Type of Article ,ISSN ,,,Reprint Edition ,,~,~,~,~,~,~,~,, +Legal Rule or Regulation ,128,,,~,~,~,~,~,~,Issuing Organization ,Abbreviation ,~,,Rule Number ,Session Number ,Start Page ,~,,Section Number ,,Date of Code Edition ,,Document Number ,,~,~,~,~,~,~,~,~,~,~,, +Magazine Article ,106,,,Magazine ,~,,~,~,~,,Alternate Magazine ,~,~,,Frequency ,Issue Number ,Issue Number ,,~,,,Type of Article ,ISSN ,,,,,~,~,~,~,~,~,~,, +Manuscript ,121,,,Collection Title ,~,,~,~,~,,Abbreviation ,City ,Library/Archive ,Volume/Storage Container ,Manuscript Number ,Folio Number ,~,,~,~,,,~,,~,~,~,~,~,~,~,~,~,~,, +Map ,122,,,Series Title ,~,,Series Editor ,~,~,,,City ,,~,~,~,~,Description ,~,,,Type ,ISBN ,,~,~,~,Scale ,~,~,~,~,~,~,, +Newspaper Article ,105,,,Newspaper ,~,,~,~,~,,~,City ,~,,Frequency ,Start Page ,~,,Section ,,Issue Date ,Type of Article ,ISSN ,,Original Publication ,,Reviewed Item ,~,~,~,~,~,~,~,~, +Online Database ,125,,,~,~,~,~,~,~,,~,~,Publisher ,~,~,~,~,~,~,~,Date Accessed ,~,~,,~,~,~,~,~,~,~,~,~,~,~, +Online Multimedia ,,,,Series Title ,~,~,Series Editor ,~,~,,~,~,Distributor ,~,~,~,~,~,~,~,Date Accessed ,Type of Work ,~,,~,~,~,~,~,~,~,Format/Length ,,~,~, +Patent ,119,,,Published Source ,International Title ,,~,International Author ,~,Issuing Organization ,~,Country ,Assignee ,Patent Version Number ,~,Application Number ,~,,International Patent Number ,International Patent Classification ,,Patent Type ,Patent Number ,,Priority Numbers ,~,~,~,Issue Date ,Designated States ,Attorney/Agent ,References ,Legal Status ,~,~, +Personal Communication ,120,,,~,~,,Recipient ,~,~,,Abbreviation ,City ,,~,Communication Number ,Folio Number ,~,,~,Description ,,Type ,~,,~,~,~,~,~,~,~,~,~,~,, +Report ,109,,,Series Title ,~,,Series Editor ,~,~,,,City ,Institution ,~,~,Document Number ,~,,~,~,,Type ,Report Number ,,Contents ,~,~,~,~,~,~,~,~,~,, +Statute ,118,,Name of Act ,Code ,~,,~,~,~,,Abbreviation ,Country ,~,Code Number ,Statute Number ,Public Law Number ,~,,Sections ,Session ,Date Enacted ,~,~,,History ,~,~,~,~,~,~,~,~,~,, +Thesis ,108,,,Academic Department ,~,,~,Advisor ,~,,~,City ,University ,Degree ,~,~,~,Number of Pages ,~,~,,Thesis Type ,~,,,~,~,,,,,,,,, +Unpublished Work ,124,,Title of Work ,Series Title ,~,,~,~,~,,Abbreviation ,City ,Institution ,~,~,Number ,~,,~,~,,Type of Work ,~,,~,~,~,~,~,~,~,~,~,~,~, +Web Page ,107,,,Series Title ,~,,Series Editor ,~,~,,,City ,Publisher ,Access Year ,~,Access Date ,~,Description ,~,,Last Update Date ,Type of Medium ,ISBN ,,Contents ,~,~,~,~,~,~,~,~,~,~, diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/misc/biblio.highlight.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/misc/biblio.highlight.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,9 @@ +(function ($) { + Drupal.behaviors.BiblioHighlight = { + attach: function (context, settings) { + $('input#biblio-highlight', context).click(function(e) { + $("div.suspect").toggleClass('biblio-highlight'); + }); + } + }; +}(jQuery)); \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/misc/biblio.nodeformbuttonhide.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/misc/biblio.nodeformbuttonhide.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,5 @@ +(function ($, Drupal, window, document, undefined) { + $(document).ready(function() { + $("#edit-biblio-next").addClass("element-invisible"); + }); +})(jQuery, Drupal, this, this.document); \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/misc/minus.png Binary file modules/biblio/misc/minus.png has changed diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/misc/plus-minus.png Binary file modules/biblio/misc/plus-minus.png has changed diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/misc/plus.png Binary file modules/biblio/misc/plus.png has changed diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/CSL.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/CSL.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1744 @@ +init($csl, $lang); + } + } + + function init($csl, $lang) { + $this->mapper = new csl_mapper(); + $this->quash = array(); + + $csl_doc = new DOMDocument(); + + if ($csl_doc->loadXML($csl)) { + + $style_nodes = $csl_doc->getElementsByTagName('style'); + if ($style_nodes) { + foreach ($style_nodes as $style) { + $this->style = new csl_style($style); + } + } + + $info_nodes = $csl_doc->getElementsByTagName('info'); + if ($info_nodes) { + foreach ($info_nodes as $info) { + $this->info = new csl_info($info); + } + } + + $this->locale = new csl_locale($lang); + $this->locale->set_style_locale($csl_doc); + + + $macro_nodes = $csl_doc->getElementsByTagName('macro'); + if ($macro_nodes) { + $this->macros = new csl_macros($macro_nodes, $this); + } + + $citation_nodes = $csl_doc->getElementsByTagName('citation'); + foreach ($citation_nodes as $citation) { + $this->citation = new csl_citation($citation, $this); + } + + $bibliography_nodes = $csl_doc->getElementsByTagName('bibliography'); + foreach ($bibliography_nodes as $bibliography) { + $this->bibliography = new csl_bibliography($bibliography, $this); + } + } + } + function render($data, $mode = NULL) { + $text = ''; + switch ($mode) { + case 'citation': + $text .= (isset($this->citation))? $this->citation->render($data) : ''; + break; + case 'bibliography': + default: + $text .= (isset($this->bibliography))? $this->bibliography->render($data) : ''; + break; + } + return $text; + } + + function render_macro($name, $data, $mode) { + return $this->macros->render_macro($name, $data, $mode); + } + + function get_locale($type, $arg1, $arg2 = NULL, $arg3 = NULL) { + return $this->locale->get_locale($type, $arg1, $arg2, $arg3); + } + + function map_field($field) { + if ($this->mapper) { + return $this->mapper->map_field($field); + } + return ($field); + } + function map_type($field) { + if ($this->mapper) { + return $this->mapper->map_type($field); + } + return ($field); + } +} + +class csl_factory { + public static function create($dom_node, $citeproc = NULL) { + $class_name = 'csl_' . str_replace('-', '_', $dom_node->nodeName); + if (class_exists($class_name)) { + return new $class_name($dom_node, $citeproc); + } + else { + return NULL; + } + } +} + +class csl_collection { + protected $elements = array(); + + function add_element($elem) { + if (isset($elem)) $this->elements[] = $elem; + } + + function render($data, $mode = NULL) {} + + function format($text) {return $text;} + +} + +class csl_element extends csl_collection { + protected $attributes = array(); + protected $citeproc; + + function __construct($dom_node = NULL, $citeproc = NULL) { + + $this->citeproc = &$citeproc; + $this->set_attributes($dom_node); + $this->init($dom_node, $citeproc); + + } + + function init($dom_node, $citeproc) { + if (!$dom_node) return; + + foreach ($dom_node->childNodes as $node) { + if ($node->nodeType == 1) { + $this->add_element(csl_factory::create($node, $citeproc)); + } + } + } + + function __set($name, $value) { + $this->attributes[$name] = $value; + } + + function __isset($name) { + return isset($this->attributes[$name]); + } + + function __unset($name) { + unset($this->attributes[$name]); + } + + function &__get($name = NULL) { + $null = NULL; + if (array_key_exists($name, $this->attributes)) { + return $this->attributes[$name]; + } + if (isset($this->{$name})) { + return $this->{$name}; + } + return $null; + + } + + function set_attributes($dom_node) { + $att = array(); + $element_name = $dom_node->nodeName; + if (isset($dom_node->attributes->length)) { + for ($i=0; $i < $dom_node->attributes->length; $i++) { + $value = $dom_node->attributes->item($i)->value; + $name = str_replace(' ', '_', $dom_node->attributes->item($i)->name); + if ($name == 'type' ) { + $value = $this->citeproc->map_type($value); + } + + if (($name == 'variable' || $name == 'is-numeric') && $element_name != 'label') { + $value = $this->citeproc->map_field($value); + } + $this->{$name} = $value; + } + } + } + + function get_attributes() { + return $this->attributes; + } + + function get_hier_attributes() { + $hier_attr = array(); + $hier_names = array('and', 'delimiter-precedes-last', 'et-al-min', 'et-al-use-first', + 'et-al-subsequent-min', 'et-al-subsequent-use-first', 'initialize-with', + 'name-as-sort-order', 'sort-separator', 'name-form', 'name-delimiter', + 'names-delimiter'); + foreach ($hier_names as $name) { + if (isset($this->attributes[$name])) { + $hier_attr[$name] = $this->attributes[$name]; + } + } + return $hier_attr; + } + + function name($name = NULL) { + if ($name) { + $this->name = $name; + } + else { + return str_replace(' ', '_', $this->name); + } + } + +} + +class csl_rendering_element extends csl_element { + + function render($data, $mode = NULL) { + $text = ''; + $text_parts = array(); + + $delim = $this->delimiter; + foreach ($this->elements as $element) { + $text_parts[] = $element->render($data, $mode); + } + $text = implode($delim, $text_parts); // insert the delimiter if supplied. + + return $this->format($text); + } + +} + +class csl_format extends csl_rendering_element { + protected $no_op; + protected $format; + + function __construct($dom_node = NULL, $citeproc = NULL) { + parent::__construct($dom_node, $citeproc); + $this->init_formatting(); + } + + function init_formatting() { + $this->no_op = TRUE; + $this->format = ''; + if (isset($this->quotes) && strtolower($this->quotes) == "true") { + $this->quotes = array(); + $this->quotes['punctuation-in-quote'] = $this->citeproc->get_locale('style_option', 'punctuation-in-quote'); + $this->quotes['open-quote'] = $this->citeproc->get_locale('term', 'open-quote'); + $this->quotes['close-quote'] = $this->citeproc->get_locale('term', 'close-quote'); + $this->quotes['open-inner-quote'] = $this->citeproc->get_locale('term', 'open-inner-quote'); + $this->quotes['close-inner-quote'] = $this->citeproc->get_locale('term', 'close-inner-quote'); + $this->no_op = FALSE; + } + if (isset($this->{'prefix'})) $this->no_op = FALSE; + if (isset($this->{'suffix'})) $this->no_op = FALSE; + if (isset($this->{'display'})) $this->no_op = FALSE; + + $this->format .= (isset($this->{'font-style'})) ? 'font-style: ' . $this->{'font-style'} . ';' : ''; + $this->format .= (isset($this->{'font-family'})) ? 'font-family: ' . $this->{'font-family'} . ';' : ''; + $this->format .= (isset($this->{'font-weight'})) ? 'font-weight: ' . $this->{'font-weight'} . ';' : ''; + $this->format .= (isset($this->{'font-variant'})) ? 'font-variant: ' . $this->{'font-variant'} . ';' : ''; + $this->format .= (isset($this->{'text-decoration'})) ? 'text-decoration: ' . $this->{'text-decoration'} . ';' : ''; + $this->format .= (isset($this->{'vertical-align'})) ? 'vertical-align: ' . $this->{'vertical-align'} . ';' : ''; + // $this->format .= (isset($this->{'display'}) && $this->{'display'} == 'indent') ? 'padding-left: 25px;' : ''; + + if (isset($this->{'text-case'}) || + !empty($this->format) || + !empty($this->span_class) || + !empty($this->div_class)) { + $this->no_op = FALSE; + } + + } + + function format($text) { + + if (empty($text) || $this->no_op) return $text; + $quotes = $this->quotes; + $quotes = is_array($quotes) ? $quotes : array(); + + if (isset($this->{'text-case'})) { + switch ($this->{'text-case'}) { + case 'uppercase': + $text = drupal_strtoupper($text); + break; + case 'lowercase': + $text = drupal_strtolower($text); + break; + case 'capitalize-all': + case 'title': + $text = mb_convert_case($text, MB_CASE_TITLE); + break; + case 'capitalize-first': + $text = drupal_ucfirst($text); + break; + } + } + + $prefix = $this->prefix; + $prefix .= isset($quotes['open-quote']) ? $quotes['open-quote'] : ''; + $suffix = $this->suffix; + if (isset($quotes['close-quote']) && !empty($suffix) && isset($quotes['punctuation-in-quote'])) { + if (strpos($suffix, '.') !== FALSE || strpos($suffix, ',') !== FALSE) { + $suffix = $suffix . $quotes['close-quote']; + } + } + elseif (isset($quotes['close-quote'])) { + $suffix = $quotes['close-quote'] . $suffix; + } + if (!empty($suffix)) { // gaurd against repeaded suffixes... + $no_tags = strip_tags($text); + if (strlen($no_tags) && ($no_tags[(strlen($no_tags) - 1)] == $suffix[0]) ) { + $suffix = substr($suffix, 1); + } + } + + if (!empty($this->format) || !empty($this->span_class)) { + $style = (!empty($this->format)) ? 'style="' . $this->format . '"' : ''; + $class = (!empty($this->span_class)) ? 'class="' . $this->span_class . '"' : ''; + $text = '' . $text . ''; + } + $div_class = $div_style = ''; + if (!empty($this->div_class)) { + $div_class = (!empty($this->div_class)) ? 'class="' . $this->div_class . '"' : ''; + } + if ($this->display == 'indent') { + $div_style = 'style="text-indent: 0px; padding-left: 45px;"'; + } + if ($div_class || $div_style) { + return '
    ' . $prefix . $text . $suffix . '
    '; + } + + return $prefix . $text . $suffix; + } + +} + +class csl_info { + public $title; + public $id; + public $authors = array(); + public $links = array(); + + function __construct($dom_node) { + $name = array(); + foreach ($dom_node->childNodes as $node) { + if ($node->nodeType == 1) { + switch ($node->nodeName) { + case 'author': + case 'contributor': + foreach ($node->childNodes as $authnode) { + if ($node->nodeType == 1) { + $name[$authnode->nodeName] = $authnode->nodeValue; + } + } + $this->authors[] = $name; + break; + case 'link': + foreach ($node->attributes as $attribute) { + $this->links[] = $attribute->value; + } + break; + default: + $this->{$node->nodeName} = $node->nodeValue; + } + } + } + + } +} + +class csl_terms { + +} + +class csl_name extends csl_format { + private $name_parts = array(); + private $attr_init = FALSE; + + function __construct($dom_node, $citeproc = NULL) { + + $tags = $dom_node->getElementsByTagName('name-part'); + if ($tags) { + foreach ($tags as $tag) { + $name_part = $tag->getAttribute('name'); + $tag->removeAttribute('name'); + for ($i=0; $i < $tag->attributes->length; $i++) { + $value = $tag->attributes->item($i)->value; + $name = str_replace(' ', '_', $tag->attributes->item($i)->name); + $this->name_parts[$name_part][$name] = $value; + } + } + } + + parent::__construct($dom_node, $citeproc); + } + + function init_formatting() { + $this->no_op = array(); + $this->format = array(); + $this->base = $this->get_attributes(); + $this->format['base'] = ''; + $this->format['family'] = ''; + $this->format['given'] = ''; + $this->no_op['base'] = TRUE; + $this->no_op['family'] = TRUE; + $this->no_op['given'] = TRUE; + + if (isset($this->prefix)) { + $this->no_op['base'] = FALSE; + } + if (isset($this->suffix)) { + $this->no_op['base'] = FALSE; + } + $this->init_format($this->base); + + + if (!empty($this->name_parts)) { + foreach ($this->name_parts as $name => $formatting) { + $this->init_format($formatting, $name); + } + } + } + + function init_attrs($mode) { + // $and = $this->get_attributes('and'); + if (isset($this->citeproc)) { + $style_attrs = $this->citeproc->style->get_hier_attributes(); + $mode_attrs = $this->citeproc->{$mode}->get_hier_attributes(); + $this->attributes = array_merge($style_attrs, $mode_attrs, $this->attributes); + } + if (isset($this->and)) { + if ($this->and == 'text') { + $this->and = $this->citeproc->get_locale('term', 'and'); + } + elseif ($this->and == 'symbol') { + $this->and = '&'; + } + } + if (!isset($this->delimiter)) { + $this->delimiter = $this->{'name-delimiter'} ; + } + if (!isset($this->alnum)) { + list($this->alnum, $this->alpha, $this->cntrl, $this->dash, + $this->digit, $this->graph, $this->lower, $this->print, + $this->punct, $this->space, $this->upper, $this->word, + $this->patternModifiers) = $this->get_regex_patterns(); + } + $this->dpl = $this->{'delimiter-precedes-last'}; + $this->sort_separator = isset($this->{'sort-separator'}) ? $this->{'sort-separator'} : ', '; + + $this->delimiter = isset($this->{'name-delimiter'}) ? $this->{'name-delimiter'} : (isset($this->delimiter) ? $this->delimiter : ', '); + + $this->form = isset($this->{'name-form'}) ? $this->{'name-form'} : (isset($this->form) ? $this->form : 'long'); + $this->attr_init = $mode; + } + + function init_format($attribs, $part = 'base') { + if (!isset($this->{$part})) { + $this->{$part} = array(); + } + if (isset($attribs['quotes']) && strtolower($attribs['quotes']) == 'true') { + $this->{$part}['open-quote'] = $this->citeproc->get_locale('term', 'open-quote'); + $this->{$part}['close-quote'] = $this->citeproc->get_locale('term', 'close-quote'); + $this->{$part}['open-inner-quote'] = $this->citeproc->get_locale('term', 'open-inner-quote'); + $this->{$part}['close-inner-quote'] = $this->citeproc->get_locale('term', 'close-inner-quote'); + $this->no_op[$part] = FALSE; + } + + if (isset($attribs['prefix'])) $this->{$part}['prefix'] = $attribs['prefix']; + if (isset($attribs['suffix'])) $this->{$part}['suffix'] = $attribs['suffix']; + + $this->format[$part] .= (isset($attribs['font-style'])) ? 'font-style: ' . $attribs['font-style'] . ';' : ''; + $this->format[$part] .= (isset($attribs['font-family'])) ? 'font-family: ' . $attribs['font-family'] . ';' : ''; + $this->format[$part] .= (isset($attribs['font-weight'])) ? 'font-weight: ' . $attribs['font-weight'] . ';' : ''; + $this->format[$part] .= (isset($attribs['font-variant'])) ? 'font-variant: ' . $attribs['font-variant'] . ';' : ''; + $this->format[$part] .= (isset($attribs['text-decoration'])) ? 'text-decoration: ' . $attribs['text-decoration'] . ';' : ''; + $this->format[$part] .= (isset($attribs['vertical-align'])) ? 'vertical-align: ' . $attribs['vertical-align'] . ';' : ''; + + if (isset($attribs['text-case'])) { + $this->no_op[$part] = FALSE; + $this->{$part}['text-case'] = $attribs['text-case']; + } + if (!empty($this->format[$part])) $this->no_op[$part] = FALSE; + + } + + function format($text, $part = 'base') { + + if (empty($text) || $this->no_op[$part]) return $text; + if (isset($this->{$part}['text-case'])) { + switch ($this->{$part}['text-case']) { + case 'uppercase': + $text = drupal_strtoupper($text); + break; + case 'lowercase': + $text = drupal_strtolower($text); + break; + case 'capitalize-all': + $text = mb_convert_case($text, MB_CASE_TITLE); + break; + case 'capitalize-first': + $text = drupal_ucfirst($text); + break; + } + } + $open_quote = isset($this->{$part}['open-quote']) ? $this->{$part}['open-quote'] : ''; + $close_quote = isset($this->{$part}['close-quote']) ? $this->{$part}['close-quote'] : ''; + $prefix = isset($this->{$part}['prefix']) ? $this->{$part}['prefix'] : ''; + $suffix = isset($this->{$part}['suffix']) ? $this->{$part}['suffix'] : ''; + if ($text[(strlen($text) -1)] == $suffix) unset($suffix); + if (!empty($this->format[$part])) { + $text = '' . $text . ''; + } + return $prefix . $open_quote . $text . $close_quote . $suffix; + } + + function author_link($author) { + $base = variable_get('biblio_base', 'biblio'); + $options = array(); + + if (isset($_GET['sort'])) { + $options['query']['sort'] = $_GET['sort']; + } + if (isset($_GET['order'])) { + $options['query']['order'] = $_GET['order']; + } + + $html = l(trim($author['name']), "$base/author/" . $author['cid'], $options ); + + return $html; + } + + function render($names, $mode = NULL) { + $text = ''; + $authors = array(); + $count = 0; + $auth_count = 0; + $et_al_triggered = FALSE; + + if (!$this->attr_init || $this->attr_init != $mode) $this->init_attrs($mode); + + $initialize_with = $this->{'initialize-with'}; + $options = array('html' => FALSE); + + foreach ($names as $rank => $name) { + if (empty($name['literal'])) { + if (!isset($name['lastname'])) { + module_load_include('inc', 'biblio', '/includes/biblio.contributors'); + $name = biblio_parse_author($name); // this is needed for form preview to fill in all fields + } + $count++; + if (!empty($name['firstname']) && isset($initialize_with)) { + $name['firstname'] = preg_replace("/([$this->upper])[$this->lower]+/$this->patternModifiers", '\\1', $name['firstname']); + $name['firstname'] = preg_replace("/(?<=[-$this->upper]) +(?=[-$this->upper])/$this->patternModifiers", "", $name['firstname']); + $name['initials'] = $name['firstname'] . $name['initials']; + } + if (isset($name['initials'])) { + // within initials, remove any dots: + $name['initials'] = preg_replace("/([$this->upper])\.+/$this->patternModifiers", "\\1", $name['initials']); + // within initials, remove any spaces *between* initials: + $name['initials'] = preg_replace("/(?<=[-$this->upper]) +(?=[-$this->upper])/$this->patternModifiers", "", $name['initials']); + if (isset($this->citeproc->style) && $this->citeproc->style->{'initialize-with-hyphen'} == 'false') { + $name['initials'] = preg_replace("/-/", '', $name['initials']); + } + // within initials, add a space after a hyphen, but only if ... + if (preg_match("/ $/", $initialize_with)) {// ... the delimiter that separates initials ends with a space + $name['initials'] = preg_replace("/-(?=[$this->upper])/$this->patternModifiers", "- ", $name['initials']); + } + // then, separate initials with the specified delimiter: + $name['initials'] = preg_replace("/([$this->upper])(?=[^$this->lower]+|$)/$this->patternModifiers", "\\1$initialize_with", $name['initials']); + // $shortenInitials = (isset($options['numberOfInitialsToKeep'])) ? $options['numberOfInitialsToKeep'] : FALSE; + // if ($shortenInitials) $given = drupal_substr($given, 0, $shortenInitials); + if (isset($initialize_with)) { + $name['firstname'] = $name['initials']; + // if ($shortenInitials) $name['firstname'] = drupal_substr($name['firstname'], 0, $shortenInitials); + } + elseif (!empty($name['firstname'])) { + $name['firstname'] = $name['firstname'] . ' ' . $name['initials']; + } + elseif (empty($name['firstname'])) { + $name['firstname'] = $name['initials']; + } + } + $given = $this->format($name['firstname'], 'given'); + if (isset($name['lastname'])) { + if (!empty($name['prefix'])) { + $name['lastname'] = $name['prefix'] . ' ' . $name['lastname']; + } + if (!empty($name['suffix'])) { + $name['lastname'] = $name['lastname'] . ', ' . $name['suffix']; + } + + $name['lastname'] = $this->format($name['lastname'], 'family'); + if ($this->form == 'short') { + $text = $name['lastname']; + } + else { + switch ($this->{'name-as-sort-order'}) { + case 'first' && $rank == 0: + case 'all': + $text = $name['lastname'] . $this->sort_separator . $given; + break; + default: + $text = $given . ' ' . $name['lastname'] ; + } + } + $text = $this->format($text); + $name['name'] = $text; + if (strstr($text, 'div') || strstr($text, 'span')) { + $options = array('html' => TRUE); + } + else { + $options = array('html' => FALSE); + } + } + } + if (variable_get('biblio_author_links', 1)) { + $text = theme('biblio_author_link', array('author' => $name, 'options' => $options)); + } + + $authors[] = $text; + + if (isset($this->{'et-al-min'}) && $count >= $this->{'et-al-min'}) break; + } + if (isset($this->{'et-al-min'}) && + $count >= $this->{'et-al-min'} && + isset($this->{'et-al-use-first'}) && + $count >= $this->{'et-al-use-first'} && + count($names) > $this->{'et-al-use-first'}) { + if ($this->{'et-al-use-first'} < $this->{'et-al-min'}) { + for ($i = $this->{'et-al-use-first'}; $i < $count; $i++) { + unset($authors[$i]); + } + } + if ($this->etal) { + $etal = $this->etal->render(); + } + else { + $etal = $this->citeproc->get_locale('term', 'et-al'); + } + $et_al_triggered = TRUE; + } + + if (!empty($authors) && !$et_al_triggered) { + $auth_count = count($authors); + if (isset($this->and) && $auth_count > 1) { + $authors[$auth_count-1] = $this->and . ' ' . $authors[$auth_count-1]; //stick an "and" in front of the last author if "and" is defined + } + } + + $text = implode($this->delimiter, $authors); + + if (!empty($authors) && $et_al_triggered) { + switch ($this->{'delimiter-precedes-et-al'}) { + case 'never': + $text = $text . " $etal"; + break; + case 'always': + $text = $text . "$this->delimiter$etal"; + break; + default: + $text = count($authors) == 1 ? $text . " $etal" : $text . "$this->delimiter$etal"; + } + } + + if ($this->form == 'count') { + if (!$et_al_triggered) { + return (int)count($authors); + } + else { + return (int)(count($authors) - 1); + } + } + // strip out the last delimiter if not required + if (isset($this->and) && $auth_count > 1) { + $last_delim = strrpos($text, $this->delimiter . $this->and); + switch ($this->dpl) { //dpl == delimiter proceeds last + case 'always': + return $text; + break; + case 'never': + return substr_replace($text, ' ', $last_delim, strlen($this->delimiter)); + break; + case 'contextual': + default: + if ($auth_count < 3) { + return substr_replace($text, ' ', $last_delim, strlen($this->delimiter)); + } + } + } + return $text ; + } + + function get_regex_patterns() { + // Checks if PCRE is compiled with UTF-8 and Unicode support + if (!@preg_match('/\pL/u', 'a')) { + // probably a broken PCRE library + return $this->get_latin1_regex(); + } + else { + // Unicode safe filter for the value + return $this->get_utf8_regex(); + } + } + + function get_latin1_regex() { + $alnum = "[:alnum:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆäåáàâãçéèêëñöøóòôõüúùûíìîïæÿß"; + // Matches ISO-8859-1 letters: + $alpha = "[:alpha:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆäåáàâãçéèêëñöøóòôõüúùûíìîïæÿß"; + // Matches ISO-8859-1 control characters: + $cntrl = "[:cntrl:]"; + // Matches ISO-8859-1 dashes & hyphens: + $dash = "-–"; + // Matches ISO-8859-1 digits: + $digit = "[\d]"; + // Matches ISO-8859-1 printing characters (excluding space): + $graph = "[:graph:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆäåáàâãçéèêëñöøóòôõüúùûíìîïæÿß"; + // Matches ISO-8859-1 lower case letters: + $lower = "[:lower:]äåáàâãçéèêëñöøóòôõüúùûíìîïæÿß"; + // Matches ISO-8859-1 printing characters (including space): + $print = "[:print:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆäåáàâãçéèêëñöøóòôõüúùûíìîïæÿß"; + // Matches ISO-8859-1 punctuation: + $punct = "[:punct:]"; + // Matches ISO-8859-1 whitespace (separating characters with no visual representation): + $space = "[\s]"; + // Matches ISO-8859-1 upper case letters: + $upper = "[:upper:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆ"; + // Matches ISO-8859-1 "word" characters: + $word = "_[:alnum:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆäåáàâãçéèêëñöøóòôõüúùûíìîïæÿß"; + // Defines the PCRE pattern modifier(s) to be used in conjunction with the above variables: + // More info: + $patternModifiers = ""; + + return array($alnum, $alpha, $cntrl, $dash, $digit, $graph, $lower, + $print, $punct, $space, $upper, $word, $patternModifiers); + + } + function get_utf8_regex() { + // Matches Unicode letters & digits: + $alnum = "\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}"; // Unicode-aware equivalent of "[:alnum:]" + // Matches Unicode letters: + $alpha = "\p{Ll}\p{Lu}\p{Lt}\p{Lo}"; // Unicode-aware equivalent of "[:alpha:]" + // Matches Unicode control codes & characters not in other categories: + $cntrl = "\p{C}"; // Unicode-aware equivalent of "[:cntrl:]" + // Matches Unicode dashes & hyphens: + $dash = "\p{Pd}"; + // Matches Unicode digits: + $digit = "\p{Nd}"; // Unicode-aware equivalent of "[:digit:]" + // Matches Unicode printing characters (excluding space): + $graph = "^\p{C}\t\n\f\r\p{Z}"; // Unicode-aware equivalent of "[:graph:]" + // Matches Unicode lower case letters: + $lower = "\p{Ll}\p{M}"; // Unicode-aware equivalent of "[:lower:]" + // Matches Unicode printing characters (including space): + $print = "\P{C}"; // same as "^\p{C}", Unicode-aware equivalent of "[:print:]" + // Matches Unicode punctuation (printing characters excluding letters & digits): + $punct = "\p{P}"; // Unicode-aware equivalent of "[:punct:]" + // Matches Unicode whitespace (separating characters with no visual representation): + $space = "\t\n\f\r\p{Z}"; // Unicode-aware equivalent of "[:space:]" + // Matches Unicode upper case letters: + $upper = "\p{Lu}\p{Lt}"; // Unicode-aware equivalent of "[:upper:]" + // Matches Unicode "word" characters: + $word = "_\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}"; // Unicode-aware equivalent of "[:word:]" (or "[:alnum:]" plus "_") + // Defines the PCRE pattern modifier(s) to be used in conjunction with the above variables: + // More info: + $patternModifiers = "u"; // the "u" (PCRE_UTF8) pattern modifier causes PHP/PCRE to treat pattern strings as UTF-8 + return array($alnum, $alpha, $cntrl, $dash, $digit, $graph, $lower, + $print, $punct, $space, $upper, $word, $patternModifiers); + } + +} + +class csl_names extends csl_format { + private $substitutes; + + function init_formatting() { + $this->span_class = 'biblio-authors'; + parent::init_formatting(); + + } + + function init($dom_node, $citeproc) { + $etal = ''; + $tag = $dom_node->getElementsByTagName('substitute')->item(0); + if ($tag) { + $this->substitutes = csl_factory::create($tag, $citeproc); + $dom_node->removeChild($tag); + } + + $tag = $dom_node->getElementsByTagName('et-al')->item(0); + if ($tag) { + $etal = csl_factory::create($tag, $citeproc); + $dom_node->removeChild($tag); + } + + $var = $dom_node->getAttribute('variable'); + foreach ($dom_node->childNodes as $node) { + if ($node->nodeType == 1) { + $element = csl_factory::create($node, $citeproc); + if (($element instanceof csl_label)) $element->variable = $var; + if (($element instanceof csl_name) && $etal) { + $element->etal = $etal; + } + $this->add_element($element); + } + } + } + + function render($data, $mode = NULL) { + $matches = array(); + $variable_parts = array(); + + if (!isset($this->delimiter)) { + $style_delimiter = $this->citeproc->style->{'names-delimiter'}; + $mode_delimiter = $this->citeproc->{$mode}->{'names-delimiter'}; + $this->delimiter = (isset($mode_delimiter)) ? $mode_delimiter : (isset($style_delimiter) ? $style_delimiter : ''); + } + + $variables = explode(' ', $this->variable); + + foreach ($variables as $var) { + if (in_array($var, $this->citeproc->quash)) continue; + list($contributor, $category) = explode(':', $var); + if ((isset($data->{$contributor}) && !empty($data->{$contributor})) && $this->_get_category($data->{$contributor}, $category) ) { + $matches[] = $var; + } + } + + if (empty($matches)) { // we don't have any primary suspects, so lets check the substitutes... + if (isset($this->substitutes)) { + foreach ($this->substitutes->elements as $element) { + if (($element instanceof csl_names)) { //test to see if any of the other names variables has content + $sub_variables = explode(' ', $element->variable); + foreach ($sub_variables as $var) { + list($contributor, $category) = explode(':', $var); + if ((isset($data->{$contributor}) && !empty($data->{$contributor})) && $this->_get_category($data->{$contributor}, $category)) { + $matches[] = $var; + $this->citeproc->quash[] = $var; + } + } + } + else { // if it's not a "names" element, just render it + $text = $element->render($data, $mode); + $this->citeproc->quash[] = isset($element->variable) ? $element->variable : $element->var; + if (!empty($text)) $variable_parts[] = $text; + } + if (!empty($matches)) break; + } + } + } + + foreach ($matches as $var) { + if (in_array($var, $this->citeproc->quash) && in_array($var, $variables)) continue; + $text = ''; + list($contributor, $category) = explode(':', $var); + if (!empty($contributor) && $authors = $this->_get_category($data->{$contributor}, $category)) { + foreach ($this->elements as $element) { + if (is_a($element, 'csl_label')) { + $element->variable = $this->_get_csl_name_variable($category); + $text .= $element->render($authors, $mode); + } + elseif (is_a($element, 'csl_name')) { + $text .= $element->render($authors, $mode); + } + } + } + if (!empty($text)) $variable_parts[] = $text; + } + + if (!empty($variable_parts)) { + $text = implode($this->delimiter, $variable_parts); + return $this->format($text); + } + + return ; + } + + private function _get_category($contributors, $category) { + $authors = array(); + foreach ($contributors as $author) { + if ($author['auth_category'] == $category) { + $authors[] = $author; + } + } + return count($authors) ? $authors : FALSE; + } + + private function _get_csl_name_variable($category) { + switch ($category) { + case 1: + return 'author'; + break; + case 2: + return 'editor'; + break; + case 3: + return 'translator'; + break; + default: + } + } +} + +class csl_date extends csl_format { + + function init($dom_node, $citeproc) { + $locale_elements = array(); + + if ($form = $this->form) { + $local_date = $this->citeproc->get_locale('date_options', $form); + $dom_elem = dom_import_simplexml($local_date[0]); + if ($dom_elem) { + foreach ($dom_elem->childNodes as $node) { + if ($node->nodeType == 1) { + $locale_elements[] = csl_factory::create($node, $citeproc); + } + } + } + foreach ($dom_node->childNodes as $node) { + if ($node->nodeType == 1) { + $element = csl_factory::create($node, $citeproc); + + foreach ($locale_elements as $key => $locale_element) { + if ($locale_element->name == $element->name) { + $locale_elements[$key]->attributes = array_merge($locale_element->attributes, $element->attributes); + $locale_elements[$key]->format = $element->format; + break; + } + + else { + $locale_elements[] = $element; + } + } + } + } + if ($date_parts = $this->{'date-parts'}) { + $parts = explode('-', $date_parts); + foreach ($locale_elements as $key => $element) { + if (array_search($element->name, $parts) === FALSE) { + unset($locale_elements[$key]); + } + } + if (count($locale_elements) != count($parts)) { + foreach ($parts as $part) { + $element = new csl_date_part(); + $element->name = $part; + $locale_elements[] = $element; + } + } + // now re-order the elements + foreach ($parts as $part) { + foreach ($locale_elements as $key => $element) + if ($element->name == $part) { + $this->elements[] = $element; + unset($locale_elements[$key]); + } + } + + } + else { + $this->elements = $locale_elements; + } + } + else { + parent::init($dom_node, $citeproc); + } + + + } + + function render($data, $mode = NULL) { + $date_parts = array(); + $text = ''; + + if (($var = $this->variable) && isset($data->{$var})) { + if (is_array($data->{$var})) { + $date = $data->{$var}; + } + else { + $date = array($data->{$var}); + } + foreach ($this->elements as $element) { + $date_parts[] = $element->render($date, $mode); + } + $text = implode($this->delimiter, $date_parts); + } +// else { +// $text = $this->citeproc->get_locale('term', 'no date'); +// } + + return $this->format($text); + } +} + +class csl_date_part extends csl_format { + + function render($date, $mode = NULL) { + $text = ''; + + switch ($this->name) { + case 'year': + $text = (isset($date[0])) ? $date[0] : ''; + if ($text > 0 && $text < 500) { + $text = $text . $this->citeproc->get_locale('term', 'ad'); + } + elseif ($text < 0) { + $text = $text * -1; + $text = $text . $this->citeproc->get_locale('term', 'bc'); + } + //return ((isset($this->prefix))? $this->prefix : '') . $date[0] . ((isset($this->suffix))? $this->suffix : ''); + break; + case 'month': + $text = (isset($date[1])) ? $date[1] : ''; + if (empty($text) || $text < 1 || $text > 12) return; + // $form = $this->form; + switch ($this->form) { + case 'numeric': break; + case 'numeric-leading-zeros': + if ($text < 10) { + $text = '0' . $text; + break; + } + break; + case 'short': + $month = 'month-' . sprintf('%02d', $text); + $text = $this->citeproc->get_locale('term', $month, 'short'); + break; + default: + $month = 'month-' . sprintf('%02d', $text); + $text = $this->citeproc->get_locale('term', $month); + break; + } + break; + case 'day': + $text = (isset($date[2])) ? $date[2] : ''; + break; + } + + return $this->format($text); + } +} + +class csl_number extends csl_format { + + function render($data, $mode = NULL) { + $var = $this->variable; + + if (!$var || empty($data->$var)) return; + + // $form = $this->form; + + switch ($this->form) { + case 'ordinal': + $text = $this->ordinal($data->$var); + break; + case 'long-ordinal': + $text = $this->long_ordinal($data->$var); + break; + case 'roman': + $text = $this->roman($data->$var); + break; + case 'numeric': + default: + $text = $data->$var; + break; + } + return $this->format($text); + } + + function ordinal($num) { + if ( ($num/10)%10 == 1) { + $num .= $this->citeproc->get_locale('term', 'ordinal-04'); + } + elseif ( $num%10 == 1) { + $num .= $this->citeproc->get_locale('term', 'ordinal-01'); + } + elseif ( $num%10 == 2) { + $num .= $this->citeproc->get_locale('term', 'ordinal-02'); + } + elseif ( $num%10 == 3) { + $num .= $this->citeproc->get_locale('term', 'ordinal-03'); + } + else { + $num .= $this->citeproc->get_locale('term', 'ordinal-04'); + } + return $num; + + } + + function long_ordinal($num) { + $num = sprintf("%02d", $num); + $ret = $this->citeproc->get_locale('term', 'long-ordinal-' . $num); + if (!$ret) { + return $this->ordinal($num); + } + return $ret; + } + + function roman($num) { + $ret = ""; + if ($num < 6000) { + $ROMAN_NUMERALS = array( + array( "", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix" ), + array( "", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc" ), + array( "", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm" ), + array( "", "m", "mm", "mmm", "mmmm", "mmmmm") + ); + $numstr = strrev($num); + $len = strlen($numstr); + for ($pos = 0; $pos < $len; $pos++) { + $n = $numstr[$pos]; + $ret = $ROMAN_NUMERALS[$pos][$n] . $ret; + } + } + + return $ret; + } + +} + +class csl_text extends csl_format { + public $source; + protected $var; + + function init($dom_node, $citeproc) { + foreach (array('variable', 'macro', 'term', 'value') as $attr) { + if ($dom_node->hasAttribute($attr)) { + $this->source = $attr; + if ($this->source == 'macro') { + $this->var = str_replace(' ', '_', $dom_node->getAttribute($attr)); + } + else { + $this->var = $dom_node->getAttribute($attr); + } + } + } + } + function init_formatting() { + if ($this->variable == 'title') { + $this->span_class = 'biblio-title'; + } + parent::init_formatting(); + + } + + function render($data = NULL, $mode = NULL) { + $text = ''; + if (in_array($this->var, $this->citeproc->quash)) return; + + switch ($this->source) { + case 'variable': + if (!isset($data->{$this->variable}) || empty($data->{$this->variable}) || trim($data->{$this->variable}) == FALSE) return; + if ($this->variable == 'biblio_url') { + $text = l($data->{$this->variable}, $data->{$this->variable}); + } + else { + $text = $data->{$this->variable}; //$this->data[$this->var]; // include the contents of a variable + } + break; + case 'macro': + $macro = $this->var; + $text = $this->citeproc->render_macro($macro, $data, $mode); //trigger the macro process + break; + case 'term': + $form = (($form = $this->form)) ? $form : ''; + $text = $this->citeproc->get_locale('term', $this->var, $form); + break; + case 'value': + $text = $this->var; //$this->var; // dump the text verbatim + break; + } + + if (empty($text)) return; + $text = $this->format($text); + if ($this->variable == 'title') { + $url = biblio_get_title_url_info($data); + $text = l($text, $url['link'], $url['options']) ; + } + return $text; + } +} + +class csl_et_al extends csl_text { + + function __construct($dom_node = NULL, $citeproc = NULL) { + $this->var = 'et-al'; + $this->source = 'term'; + parent::__construct($dom_node, $citeproc); + + } +} +class csl_label extends csl_format { + private $plural; + + function render($data, $mode = NULL) { + $text = ''; + + $variables = explode(' ', $this->variable); + $form = (($form = $this->form)) ? $form : 'long'; + switch ($this->plural) { + case 'never': + $plural = 'single'; + break; + case 'always': + $plural = 'multiple'; + break; + case 'contextual': + default: + } + foreach ($variables as $variable) { + $field = $this->citeproc->map_field($variable); + if (isset($data->{$field}) && !empty($data->{$field})) { + if (!isset($this->plural) && empty($plural) && is_array($data->{$field})) { + $count = count($data->{$field}); + if ($count == 1) { + $plural = 'single'; + } + elseif ($count > 1) { + $plural = 'multiple'; + } + } + else { + $plural = $this->evaluateStringPluralism($data, $variable); + } + if (($term = $this->citeproc->get_locale('term', $variable, $form, $plural))) { + $text = $term; + break; + } + } + } + + if (empty($text)) return; + if ($this->{'strip-periods'}) $text = str_replace('.', '', $text); + return $this->format($text); + } + + function evaluateStringPluralism($data, $variable) { + $field = $this->citeproc->map_field($variable); + $str = $data->{$field}; + $plural = 'single'; + + if (!empty($str)) { +// $regex = '/(?:[0-9],\s*[0-9]|\s+and\s+|&|([0-9]+)\s*[\-\x2013]\s*([0-9]+))/'; + switch ($variable) { + case 'page': + $page_regex = "/([a-zA-Z]*)([0-9]+)\s*(?:–|-)\s*([a-zA-Z]*)([0-9]+)/"; + $err = preg_match($page_regex, $str, $m); + if ($err !== FALSE && count($m) == 0) { + $plural = 'single'; + } + elseif ($err !== FALSE && count($m)) { + $plural = 'multiple'; + } + break; + default: + } + } + return $plural; + } +} + +class csl_macro extends csl_format{ + +} + +class csl_macros extends csl_collection{ + + function __construct($macro_nodes, $citeproc) { + foreach ($macro_nodes as $macro) { + $macro = csl_factory::create($macro, $citeproc); + $this->elements[$macro->name()] = $macro; + } + } + + function render_macro($name, $data, $mode) { + return $this->elements[$name]->render($data, $mode); + } +} + +class csl_group extends csl_format{ + + function render($data, $mode = NULL) { + $text = ''; + $text_parts = array(); + + $terms = $variables = $have_variables = $element_count = 0; + foreach ($this->elements as $element) { + $element_count++; + if (($element instanceof csl_text) && + ($element->source == 'term' || + $element->source == 'value' )) { + $terms++; + } + if (($element instanceof csl_label)) $terms++; + if ($element->source == 'variable' && + isset($element->variable) && + !empty($data->{$element->variable}) + ) { + $variables++; + } + + $text = $element->render($data, $mode); + + $delimiter = $this->delimiter; + if (!empty($text)) { + if ($delimiter && ($element_count < count($this->elements))) { + //check to see if the delimiter is already the last character of the text string + //if so, remove it so we don't have two of them when we paste together the group + $stext = strip_tags(trim($text)); + if ((strrpos($stext, $delimiter[0])+1) == drupal_strlen($stext) && drupal_strlen($stext) > 1) { + $text = str_replace($stext, '----REPLACE----', $text); + $stext = drupal_substr($stext, 0, -1); + $text = str_replace('----REPLACE----', $stext, $text); + } + } + $text_parts[] = $text; + if ($element->source == 'variable' || isset($element->variable)) $have_variables++; + if ($element->source == 'macro') $have_variables++; + } + } + + if (empty($text_parts)) return; + if ($variables && !$have_variables ) return; // there has to be at least one other none empty value before the term is output + if (count($text_parts) == $terms) return; // there has to be at least one other none empty value before the term is output + + $delimiter = $this->delimiter; + $text = implode($delimiter, $text_parts); // insert the delimiter if supplied. + + + return $this->format($text); + } +} + +class csl_layout extends csl_format { + + function init_formatting() { + // $this->div_class = 'csl-entry'; + parent::init_formatting(); + } + + function render($data, $mode = NULL) { + $text = ''; + $parts = array(); + // $delimiter = $this->delimiter; + + foreach ($this->elements as $element) { + $parts[] = $element->render($data, $mode); + } + + $text = implode($this->delimiter, $parts); + + if ($mode == 'bibliography') { + return $this->format($text); + } + else { + return $text; + } + + } + +} + +class csl_citation extends csl_format{ + private $layout = NULL; + + function init($dom_node, $citeproc) { + $options = $dom_node->getElementsByTagName('option'); + foreach ($options as $option) { + $value = $option->getAttribute('value'); + $name = $option->getAttribute('name'); + $this->attributes[$name] = $value; + } + + $layouts = $dom_node->getElementsByTagName('layout'); + foreach ($layouts as $layout) { + $this->layout = new csl_layout($layout, $citeproc); + } + } + + function render($data, $mode = NULL) { + $this->citeproc->quash = array(); + + $text = $this->layout->render($data, 'citation'); + + return $this->format($text); + } + +} +class csl_bibliography extends csl_format { + private $layout = NULL; + + function init($dom_node, $citeproc) { + $hier_name_attr = $this->get_hier_attributes(); + $options = $dom_node->getElementsByTagName('option'); + foreach ($options as $option) { + $value = $option->getAttribute('value'); + $name = $option->getAttribute('name'); + $this->attributes[$name] = $value; + } + + $layouts = $dom_node->getElementsByTagName('layout'); + foreach ($layouts as $layout) { + $this->layout = new csl_layout($layout, $citeproc); + } + + } + + function init_formatting() { + // $this->div_class = 'csl-bib-body'; + parent::init_formatting(); + } + + function render($data, $mode = NULL) { + $this->citeproc->quash = array(); + $text = $this->layout->render($data, 'bibliography'); + if ($this->{'hanging-indent'} == 'true') { + $text = '
    ' . $text . '
    '; + } + $text = str_replace('?.', '?', str_replace('..', '.', $text)); + return $this->format($text); + } +} + +class csl_option { + private $name; + private $value; + + function get() { + return array($this->name => $this->value); + } +} + +class csl_options extends csl_element{ + +} + +class csl_sort extends csl_element{ + +} +class csl_style extends csl_element{ + + function __construct($dom_node = NULL, $citeproc = NULL) { + if ($dom_node) { + $this->set_attributes($dom_node); + } + } +} + +class csl_choose extends csl_element{ + + function render($data, $mode = NULL) { + foreach ($this->elements as $choice) { + if ($choice->evaluate($data)) { + return $choice->render($data, $mode); + } + } + } +} + +class csl_if extends csl_rendering_element { + + function evaluate($data) { + $match = (($match = $this->match)) ? $match : 'all'; + if (($types = $this->type)) { + $types = explode(' ', $types); + $matches = 0; + foreach ($types as $type) { + if (isset($data->biblio_type)) { + if ($data->biblio_type == $type && $match == 'any') return TRUE; + if ($data->biblio_type != $type && $match == 'all') return FALSE; + if ($data->biblio_type == $type) $matches++; + } + } + if ($match == 'all' && $matches == count($types)) return TRUE; + if ($match == 'none' && $matches == 0) return TRUE; + return FALSE; + } + if (($variables = $this->variable)) { + $variables = explode(' ', $variables); + $matches = 0; + foreach ($variables as $var) { + if (isset($data->$var) && !empty($data->$var) && $match == 'any') return TRUE; + if ((!isset($data->$var) || empty($data->$var)) && $match == 'all') return FALSE; + if (isset($data->$var) && !empty($data->$var)) $matches++; + } + if ($match == 'all' && $matches == count($variables)) return TRUE; + if ($match == 'none' && $matches == 0) return TRUE; + return FALSE; + } + if (($is_numeric = $this->{'is-numeric'})) { + $variables = explode(' ', $is_numeric); + $matches = 0; + foreach ($variables as $var) { + if (isset($data->$var)) { + if (is_numeric($data->$var) && $match == 'any') return TRUE; + if (!is_numeric($data->$var)) { + if (preg_match('/(?:^\d+|\d+$)/', $data->$var)) { + $matches++; + } + elseif ($match == 'all') { + return FALSE; + } + } + if (is_numeric($data->$var)) $matches++; + } + } + if ($match == 'all' && $matches == count($variables)) return TRUE; + if ($match == 'none' && $matches == 0) return TRUE; + return FALSE; + } + if (isset($this->locator)) $test = explode(' ', $this->type); + + return FALSE; + } +} + +class csl_else_if extends csl_if { + +} + +class csl_else extends csl_if { + + function evaluate($data = NULL) { + return TRUE; // the last else always returns TRUE + } +} + +class csl_substitute extends csl_element{ + +} + +class csl_locale { + protected $locale_xmlstring = NULL; + protected $style_locale_xmlstring = NULL; + protected $locale = NULL; + protected $style_locale = NULL; + private $module_path; + + function __construct($lang = 'en') { + $this->module_path = drupal_get_path('module', 'biblio_citeproc'); + $this->locale = new SimpleXMLElement($this->get_locales_file_name($lang)); + if ($this->locale) { + $this->locale->registerXPathNamespace('cs', 'http://purl.org/net/xbiblio/csl'); + } + } + + // SimpleXML objects cannot be serialized, so we must convert to an XML string prior to serialization + function __sleep() { + $this->locale_xmlstring = ($this->locale) ? $this->locale->asXML() : ''; + $this->style_locale_xmlstring = ($this->style_locale) ? $this->style_locale->asXML() : ''; + return array('locale_xmlstring', 'style_locale_xmlstring'); + } + + // SimpleXML objects cannot be serialized, so when un-serializing them, they must rebuild from the serialized XML string. + function __wakeup() { + $this->style_locale = (!empty($this->style_locale_xmlstring)) ? new SimpleXMLElement($this->style_locale_xmlstring) : NULL; + $this->locale = (!empty($this->locale_xmlstring)) ? new SimpleXMLElement($this->locale_xmlstring) : NULL; + if ($this->locale) { + $this->locale->registerXPathNamespace('cs', 'http://purl.org/net/xbiblio/csl'); + } + } + + function get_locales_file_name($lang) { + $lang_bases = array( + "af" => "af-ZA", + "ar" => "ar-AR", + "bg" => "bg-BG", + "ca" => "ca-AD", + "cs" => "cs-CZ", + "da" => "da-DK", + "de" => "de-DE", + "el" => "el-GR", + "en" => "en-US", + "es" => "es-ES", + "et" => "et-EE", + "fa" => "fa-IR", + "fi" => "fi-FI", + "fr" => "fr-FR", + "he" => "he-IL", + "hu" => "hu-HU", + "is" => "is-IS", + "it" => "it-IT", + "ja" => "ja-JP", + "km" => "km-KH", + "ko" => "ko-KR", + "mn" => "mn-MN", + "nb" => "nb-NO", + "nl" => "nl-NL", + "nn" => "nn-NO", + "pl" => "pl-PL", + "pt" => "pt-PT", + "ro" => "ro-RO", + "ru" => "ru-RU", + "sk" => "sk-SK", + "sl" => "sl-SI", + "sr" => "sr-RS", + "sv" => "sv-SE", + "th" => "th-TH", + "tr" => "tr-TR", + "uk" => "uk-UA", + "vi" => "vi-VN", + "zh" => "zh-CN", + ); + return (isset($lang_bases[$lang])) ? file_get_contents($this->module_path . '/locale/locales-' . $lang_bases[$lang] . '.xml') : file_get_contents($this->module_path . '/locale/locales-en-US.xml'); + } + + function get_locale($type, $arg1, $arg2 = NULL, $arg3 = NULL) { + switch ($type) { + case 'term': + $term = ''; + $form = $arg2 ? " and @form='$arg2'" : ''; + $plural = $arg3 ? "/cs:$arg3" : ''; + if ($arg2 == 'verb' || $arg2 == 'verb-short') $plural = ''; + if ($this->style_locale) { + $term = @$this->style_locale->xpath("//locale[@xml:lang='en']/terms/term[@name='$arg1'$form]$plural"); + if (!$term) { + $term = @$this->style_locale->xpath("//locale/terms/term[@name='$arg1'$form]$plural"); + } + } + if (!$term) { + $term = $this->locale->xpath("//cs:term[@name='$arg1'$form]$plural"); + } + if (isset($term[0])) { + if (isset($arg3) && isset($term[0]->{$arg3})) return (string)$term[0]->{$arg3}; + if (!isset($arg3) && isset($term[0]->single)) return (string)$term[0]->single; + return (string)$term[0]; + } + break; + case 'date_option': + $attribs = array(); + if ($this->style_locale) { + $date_part = $this->style_locale->xpath("//date[@form='$arg1']/date-part[@name='$arg2']"); + } + if (!isset($date_part)) { + $date_part = $this->locale->xpath("//cs:date[@form='$arg1']/cs:date-part[@name='$arg2']"); + } + if (isset($date_part)) { + foreach ($$date_part->attributes() as $name => $value) { + $attribs[$name] = (string)$value; + } + } + return $attribs; + break; + case 'date_options': + $options = array(); + if ($this->style_locale) { + $options = $this->style_locale->xpath("//locale[@xml:lang='en']/date[@form='$arg1']"); + if (!$options) { + $options = $this->style_locale->xpath("//locale/date[@form='$arg1']"); + } + } + if (!$options) { + $options = $this->locale->xpath("//cs:date[@form='$arg1']"); + } + if (isset($options[0]))return $options[0]; + break; + case 'style_option': + $attribs = array(); + if ($this->style_locale) { + $option = $this->style_locale->xpath("//locale[@xml:lang='en']/style-options[@$arg1]"); + if (!$option) { + $option = $this->style_locale->xpath("//locale/style-options[@$arg1]"); + } + } + if (isset($option) && !empty($option)) { + $attribs = $option[0]->attributes(); + } + if (empty($attribs)) { + $option = $this->locale->xpath("//cs:style-options[@$arg1]"); + } + foreach ($option[0]->attributes() as $name => $value) { + if ($name == $arg1) return (string)$value; + } + break; + } + } + + public function set_style_locale($csl_doc) { + $xml = ''; + $locale_nodes = $csl_doc->getElementsByTagName('locale'); + if ($locale_nodes) { + $xml_open = ''; + $xml_close = ''; + foreach ($locale_nodes as $key => $locale_node) { + $xml .= $csl_doc->saveXML($locale_node); + } + if (!empty($xml)) { + $this->style_locale = new SimpleXMLElement($xml_open . $xml . $xml_close); + } + } + } + +} + +class csl_mapper { + + function map_field($field) { + if (!isset($this->field_map)) { + $this->field_map = biblio_get_map('field_map', 'csl'); + } + + $vars = explode(' ', $field); + foreach ($vars as $key => $value) { + $vars[$key] = (!empty($this->field_map[$value])) ? $this->field_map[$value] : ''; + } + + return implode(' ', $vars); + } + + function map_type($types) { + if (!isset($this->type_map)) { + $this->type_map = biblio_get_map('type_map', 'csl'); + } + $vars = explode(' ', $types); + foreach ($vars as $key => $value) { + $vars[$key] = (!empty($this->type_map[$value])) ? $this->type_map[$value] : ''; + } + + return implode(' ', $vars); + + } + +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/biblio_citeproc.admin.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/biblio_citeproc.admin.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,710 @@ +expire < time()) { + if (!($style_zip_file = variable_get('biblio_citeproc_styles_zip_file', FALSE))) { + $style_zip_file = _get_zip_from_github(); + } + + if ($style_zip_file) { + $file = drupal_realpath($style_zip_file->uri); + $options = _get_csl_list_from_zip($file); + } + + if (!empty($options)) { + //expire 30 days from now + $expire = time() + 2592000; + cache_set('biblio_citeproc_styles', $options, 'cache', $expire); + } + } + else { + $options = $cache->data; + } + + + $form['available_styles'] = array( + '#type' => 'select', + '#title' => t('Available styles'), + '#size' => 15, + '#multiple' => TRUE, + '#description' => t('Choose the styles you would like to download and install.'), + ); + + $form['install'] = array( + '#type' => 'submit', + '#value' => '<--', + '#description' => t('Install the selected styles from GitHub'), + ); + $form['remove'] = array( + '#type' => 'submit', + '#value' => '-->', + '#description' => t('Un-install the selected styles'), + ); + $form['default'] = array( + '#type' => 'submit', + '#value' => t('Set as site default'), + '#submit' => array('biblio_citeproc_set_site_default'), + ); + $form['update_installed'] = array( + '#type' => 'submit', + '#value' => t('Update installed styles'), + '#submit' => array('biblio_citeproc_update_installed'), + ); + $form['update_available'] = array( + '#type' => 'submit', + '#value' => t('Update available styles'), + '#submit' => array('biblio_citeproc_update_available'), + ); + $form['edit'] = array( + '#type' => 'submit', + '#value' => t('Edit selected'), + '#submit' => array('biblio_citeproc_edit_selected'), + ); +// $form['install_all'] = array( +// '#type' => 'submit', +// '#value' => t('Install all') +// ); + + $form['#attributes']['enctype'] = 'multipart/form-data'; + + $form['import_csl_file'] = array( + '#type' => 'file', + '#title' => t('Import Local CSL file'), + '#default_value' => '', + '#size' => 60 + ); + $form['import'] = array( + '#type' => 'submit', + '#value' => t('Import'), + '#submit' => array('biblio_citeproc_csl_file_import_submit'), + ); + + $result = db_select('biblio_citeproc_styles', 'csl') + ->fields('csl', array('filename', 'title', 'id', 'sha1', 'title', 'summary', 'changed', 'updated')) + ->orderBy('filename', 'ASC') + ->execute(); + + $details = array(); + $titles = array(); + foreach ($result as $style) { + $details[$style->filename] = $style; + $titles[] = $style->title; + } + + // now remove the installed titles from the available titles list + $options = array_diff($options, $titles); + $form['available_styles']['#options'] = $options; + + $form['installed_styles'] = array( + '#type' => 'select', + '#title' => t('Installed styles'), + '#size' => 15, + '#options' => biblio_get_styles(), + '#multiple' => TRUE, + '#description' => t('Currently installed styles.'), + ); + + $form['current_default'] = array( + '#markup' => empty($details) ? '' : $details[variable_get('biblio_citeproc_style', 'ieee.csl')]->title, + ); + + $form['current_summary'] = array( + '#markup' => empty($details) ? '' : $details[variable_get('biblio_citeproc_style', 'ieee.csl')]->summary, + ); + + $timestamp = $details[variable_get('biblio_citeproc_style', 'ieee.csl')]->updated; + $updated = $timestamp ? ' ('. t('Last updated:') . ' ' . format_date($timestamp, 'medium') . ')' : ''; + + $form['current_update'] = array( + '#markup' => $updated, + ); + + return $form; +} + +function theme_biblio_citeproc_style_manager_form($variables) { + $form = $variables['form']; + $rows = array(); + $updated = drupal_render($form['current_update']); + $updated = empty($updated) ? $updated : '
    ' . $updated; + $rows[] = array( + array('data' => t('Current default style:')), + array('data' => '' . drupal_render($form['current_default']) . '' . + '
    ' . drupal_render($form['current_summary']) . '' . $updated + ), + ); + $rows[] = array( + array('data' => t('Example citation:')), + array('data' => biblio_citeproc_example_citation())); + $output = theme('table', array('rows' => $rows)); + $rows = array(); + $rows[] = array( + array('data' => drupal_render($form['installed_styles']) ), + array('data' => drupal_render($form['install']) . '
    ' . drupal_render($form['remove'])), + array('data' => drupal_render($form['available_styles'])), + ); + $rows[] = array( + array('data' => drupal_render($form['default']) . drupal_render($form['edit']) .drupal_render($form['update_installed'])), + array('data' => ''), + array('data' => drupal_render($form['update_available'])), + ); + $rows[] = array(array('data' => drupal_render($form['import_csl_file']) . drupal_render($form['import']), 'colspan' => 3) ); + $output .= theme('table', array('rows' => $rows)); + + $output .= drupal_render_children($form); + return $output; + +} +function biblio_citeproc_style_manager_form_validate($form, &$form_state) { + if ($form_state['clicked_button']['#value'] == '<--' && count( $form_state['values']['available_styles'])) { + if (count($form_state['values']['available_styles']) > 60) { + form_error($form['available_styles'], t('You may not select more than 60 styles for installation at one time')); + } + } + if ($form_state['clicked_button']['#value'] == t('Set as site default') && !count( $form_state['values']['installed_styles'])) { + form_error($form['installed_styles'], t('You must select an installed style to set as the default.')); + } + +} +function biblio_citeproc_style_manager_form_submit($form, &$form_state) { + if ($form_state['clicked_button']['#value'] == '<--' && count( $form_state['values']['available_styles'])) { + if (!($style_zip_file = variable_get('biblio_citeproc_styles_zip_file', FALSE))) { + $style_zip_file = _get_zip_from_github(); + } + + if (!$style_zip_file) { + form_set_error('<--', t('Could not get the style files from GitHub')); + } + + $file = drupal_realpath($style_zip_file->uri); + $selected = $form_state['values']['available_styles']; + _install_selected_from_zip($file, $selected); + } + + if ($form_state['clicked_button']['#value'] == '-->' && count( $form_state['values']['installed_styles'])) { + $selected = $form_state['values']['installed_styles']; + _uninstall_selected($selected); + } +} + +function biblio_citeproc_edit_selected($form, &$form_state) { + if (count( $form_state['values']['installed_styles'])) { + $style = array_shift($form_state['values']['installed_styles']); + $dest = drupal_get_destination(); + drupal_goto('admin/config/content/biblio/citeproc/styles/' . $style . '/edit'); + } +} + +function biblio_citeproc_set_site_default($form, &$form_state) { + if (count( $form_state['values']['installed_styles']) == 1) { + $def = array_shift($form_state['values']['installed_styles']); + variable_set('biblio_citeproc_style', $def); + } + else { + form_set_error('installed_styles', t('You may only select one style when setting the default')); + } +} + +function biblio_citeproc_update_installed($form, &$form_state) { + $batch_op = array( + 'title' => t('Updating all installed styles from the main GitHub repository'), + 'operations' => array( + array('_get_zip_from_github', array()), + array('biblio_citeproc_update_installed_batch', array()), + ), + 'progressive' => TRUE, + 'finished' => 'biblio_citeproc_update_installed_finished', + 'init_message' => t('Downloading file...'), + 'progress_message' => t('Updating styles...'), + 'file' => './' . drupal_get_path('module', 'biblio_citeproc') . '/biblio_citeproc.admin.inc' + ); + batch_set($batch_op); +} + +function biblio_citeproc_update_available($form, &$form_state) { + _get_zip_from_github(); +} + +function biblio_citeproc_csl_file_import_submit($form, &$form_state) { + $validators = array( + 'file_validate_extensions' => array('csl xml'), + 'biblio_citeproc_validate_csl_file' => array() + ); + + if ($import_file = file_save_upload('import_csl_file', $validators)) { + $csl = file_get_contents($import_file->uri); +// if (biblio_citeproc_validate_csl($csl)) { + _install_csl($import_file->filename, $csl); +// } + } + +} +function _get_github_repo_tree($path = '') { + $options = array(); + $tree_url = 'https://api.github.com/repos/citation-style-language/styles/contents'; + if (!empty($path)) { + $tree_url .= '/' . $path; + } + + $result= drupal_http_request($tree_url); + if ($result->code == 200) { + $tree = json_decode($result->data); + } + else { + $message = t('Attempt to get list of styles from GitHub resulted in an HTTP error: !code.', array('!code' => $result->code)); + + $cache = cache_get('github_csl_repo'); + + if ($cache) { + $message .= ' ' . t('I will use cached data instead.'); + $mess_type = 'warning'; + $options = $cache->data; + } + else { + $message .= ' ' . t('I have no cached data, so you will not be able to install new styles at this time.'); + $mess_type = 'error'; + } + drupal_set_message(check_plain($message), $mess_type); + return $options; + } + + foreach ($tree as $file) { + if ($file->type == 'file' && strstr($file->name, '.csl')) { + $options[$file->path] = basename($file->name); + } + elseif ($file->type == 'dir') { + $options = array_merge($options, _get_github_repo_tree($file->name)); + } + } + return $options; +} + +function _install_csl($name = NULL, $csl = NULL, $sha = NULL, $all = FALSE, $update = FALSE) { + static $installed = array(); + + if (empty($installed)) { + $result = db_select('biblio_citeproc_styles', 'csl') + ->fields('csl', array('filename', 'id', 'sha1', 'title')) + ->orderBy('filename', 'ASC') + ->execute(); + + $installed = array(); + foreach ($result as $style) { + $installed[$style->id] = $style; + } + } + + $xml = simplexml_load_string($csl); + + if ($xml) { + $parent = ''; + foreach ($xml->info->link as $link) { + $attrs = $link->attributes(); + if (isset($attrs['rel']) && $attrs['rel'] == 'independent-parent') { + $parent = (string)$attrs['href']; + } + } + if (!$all && !$update && !empty($parent)) { + $csl_file_contents = db_query("SELECT csl FROM {biblio_citeproc_styles} WHERE id = :parent", array(':parent' => $parent))->fetchField(); + if (!$csl_file_contents) { + _install_csl_from_github(basename($parent) . '.csl'); + } + } + + $sha1 = (isset($sha)) ? $sha : sha1($csl); + + $record = array( + 'filename' => $name, + 'parent' => $parent, + 'title' => trim((string)$xml->info->title), + 'summary' => (string)$xml->info->summary, + 'csl' => $csl, + 'sha1' => $sha1, + 'id' => (string)$xml->info->id, + 'updated' => time(), + 'changed' => 0, + ); + + if (!array_key_exists($record['id'], $installed)) { + db_insert('biblio_citeproc_styles')->fields($record)->execute(); + $installed[$record['id']] = TRUE; + return 1; + } + elseif ($record['sha1'] != $installed[$record['id']]->sha1) { + db_update('biblio_citeproc_styles')->condition('id', $record['id'])->fields($record)->execute(); + return 2; + } + elseif (($record['sha1'] == $installed[$record['id']]->sha1 && $update == FALSE)) { + $message = t('The CSL file you supplied: !name, is already installed', array('!name' => $name)); + drupal_set_message(check_plain($message), 'warning'); + } + } + else { + drupal_set_message(t('I could not parse the CSL provided as valid XML', 'error')); + } +} + +function _get_zip_from_github() { + $zip_url = 'https://github.com/citation-style-language/styles/zipball/master'; + $destination = file_build_uri('Biblio-CiteProc-Styles.zip'); + $zip_file = system_retrieve_file($zip_url, $destination, TRUE, FILE_EXISTS_REPLACE); + $usage = file_usage_list($zip_file); + if (empty($usage)) { + file_usage_add($zip_file, 'biblio_citeproc', 'csl', 0); + } + variable_set('biblio_citeproc_styles_zip_file', $zip_file); + cache_clear_all('biblio_citeproc_styles', 'cache'); + return $zip_file; +} + +function _install_csl_from_github($path, $update = FALSE) { + $csl = ''; + $github_url = 'https://api.github.com/repos/citation-style-language/styles/contents/'; + $URL = $github_url . $path; + $result = drupal_http_request($URL); + if ($result->code == 200) { + $file = json_decode($result->data); + switch ($file->encoding) { + case 'base64': + $csl = base64_decode($file->content); + break; + } + _install_csl($file->name, $csl, $file->sha, FALSE, $update); + } + else { + $message = t('Attempt to get style: %name from GitHub resulted in an HTTP error: !code.', array('%name' => $path, '!code' => $result->code)); + $mess_type = 'error'; + drupal_set_message(check_plain($message), $mess_type); + } + return; +} + +function _get_csl_list_from_zip($filename) { + $options = array(); + $za = new ZipArchive(); + + if ($za->open($filename) !== TRUE) { + $message = t('Could not open zip file containing styles: @file', array('@file' => realpath($filename))); + $message = check_plain($message); + drupal_set_message($message, 'error'); + return $options; + } + + $num_files = $za->numFiles; + + for ($i = 0; $i < $num_files; $i++) { + $name = $za->getNameIndex($i); + $name = basename($name); + if (strstr($name, '.csl')) { + $csl = $za->getFromIndex($i); + $xml = simplexml_load_string($csl); + if ($xml) { + $options[$i] = trim((string)$xml->info->title); + } + } + } + + $za->close(); + asort($options); + return $options; +} + +function _install_selected_from_zip($filename = '', $ids = array()) { + $za = new ZipArchive(); + if ($za->open($filename) == TRUE) { + foreach ($ids as $id) { + $name = $za->getNameIndex($id); + $name = basename($name); + if (strstr($name, '.csl')) { + $csl = $za->getFromIndex($id); + _install_csl($name, $csl); + } + } + $za->close(); + } +} + +function _uninstall_selected($ids = array()) { + $result = db_select('biblio_citeproc_styles', 'csl') + ->fields('csl', array('id', 'filename', 'parent')) + ->orderBy('filename', 'ASC') + ->execute(); + + foreach ($result as $csl) { + $fp[$csl->filename] = $csl->parent; + $fi[$csl->filename] = $csl->id; + } + + foreach ($ids as $id) { + db_delete('biblio_citeproc_styles')->condition('filename', $id)->execute(); + //if this is a dependent style, delete the parent style if no others are using it + if (!empty($fp[$id])) { + $parent = array_keys($fp, $fp[$id]); + if ( count($parent) == 1) { + db_delete('biblio_citeproc_styles')->condition('id', $fp[$id])->execute(); + } + } + //delete all the dependents + $children = array_keys($fp, $fi[$id]); + if (!empty($children)) { + db_delete('biblio_citeproc_styles')->condition('filename', $children, 'IN')->execute(); + } + if (variable_get('biblio_citeproc_style', 'ieee.csl') == $id) { + variable_del('biblio_citeproc_style'); + } + } + +} + +function _install_all_from_zip(&$context = NULL) { + + $zipname = $context['results']['zipname']; + + if (!empty($zipname)) { + //variable_del('github_zip'); + $zip = zip_open($zipname); + $za = new ZipArchive(); + + if ($za->open($zipname) !== TRUE) { + $message = t('Could not open zip file containing styles: @file', array('@file' => realpath($zipname))); + $message = check_plain($message); + drupal_set_message($message, 'error'); + return; + } + if (empty($context['sandbox'])) { + $context['sandbox']['progress'] = 0; + $context['results']['install_count'] = 0; + } + + $num_files = $za->numFiles; + $start = $context['sandbox']['progress']; + $end = min(($start+50), $num_files); + + for ($i = $start; $i < $end; $i++) { + $name = $za->getNameIndex($i); + $name = basename($name); + if (strstr($name, '.csl')) { + $csl = $za->getFromIndex($i); + _install_csl($name, $csl, NULL, TRUE); + $context['results']['install_count']++; + } + $context['sandbox']['progress']++; + } + $za->close(); + + if ($context['sandbox']['progress'] != $num_files) { + $context['finished'] = $context['sandbox']['progress'] / $num_files; + } + } +} + +function _csl_import_batch_finished($success, $results, $operations) { + $zipname = variable_get('github_zip', ''); + file_unmanaged_delete($zipname); + variable_del('github_zip'); +} + +function biblio_citeproc_example_citation() { + global $language; + $contributors = array( + 0 => array( + 'lastname' => 'Oneauth', + 'firstname' => 'Joe', + 'initials' => 'A', + 'auth_category' => 1, + 'cid' => -1), + 1 => array( + 'lastname' => 'Twoauth', + 'firstname' => 'John', + 'initials' => 'B', + 'auth_category' => 1, + 'cid' => -2), + ); + $node = new stdClass(); + $node->nid = -1; + $node->title = 'This is a fantastic title.'; + $node->biblio_contributors = $contributors; + $node->biblio_type = 102; + $node->biblio_year = 2010; + $node->biblio_volume = 1; + $node->biblio_issue = 2; + $node->biblio_secondary_title = 'Journal of Fantastic Articles'; + $node->biblio_pages = '424-31'; + $node->biblio_coins = ''; + return theme_biblio_citeproc_style(array('node' => $node)); + +} + +function biblio_citeproc_csl_editor($form, &$form_state, $style) { + + $csl = db_query('SELECT id,parent,csl FROM {biblio_citeproc_styles} WHERE filename = :id', array(':id' => $style))->fetchObject(); + if (!isset($csl->csl)) { + drupal_set_message(t('Biblio-CiteProc could not fetch the style file: @csl_id from the database. Check your CiteProc settings.', array('@csl_id' => $style)), 'error'); + return; + } + if (!empty($csl->parent)) { + $csl = db_query("SELECT id,csl FROM {biblio_citeproc_styles} WHERE id = :id", array(':id' => $csl->parent))->fetchObject(); + + } + if (isset($csl->csl)) { + $csl_file_contents = $csl->csl; + } + + $form['editor'] = array( + '#title' => t('Editing %style', array('%style' => $style)), + '#type' => 'text_format', + '#rows' => 40, + '#format' => 'csl', + '#default_value' => $csl_file_contents, + ); + $form['save'] = array( + '#value' => t('Save'), + '#type' => 'submit', + ); + $form['cancel'] = array( + '#value' => t('Cancel'), + '#type' => 'submit', + ); + $form['style'] = array( + '#value' => $style, + '#type' => 'hidden', + ); + $form['id'] = array( + '#value' => $csl->id, + '#type' => 'hidden', + ); + + return $form; +} +function biblio_citeproc_csl_editor_validate($form, &$form_state) { + if ($form_state['triggering_element']['#value'] == t('Save')) { + $csl = $form_state['values']['editor']['value']; + $valid = biblio_citeproc_validate_csl($csl); + if (!empty($valid)) { + form_set_error('editor', $valid[0]); + } + else { + $form_state['values']['editor']['value'] = $csl; + } + } +} +function biblio_citeproc_csl_editor_submit($form, &$form_state) { + $form_state['redirect'] = 'admin/config/content/biblio/citeproc/styles'; + + if ($form_state['triggering_element']['#value'] == t('Save')) { + $csl = $form_state['values']['editor']['value']; + $id = $form_state['values']['id']; + + $record = array( + 'id' => $id, + 'csl' => $csl, + 'sha1' => sha1($csl), + 'changed' => time(), + 'updated' => time(), + ); + drupal_write_record('biblio_citeproc_styles', $record, 'id'); + } + +} + +function biblio_citeproc_validate_csl_file($file) { + if ($file->source == 'import_csl_file') { + $csl = file_get_contents($file->uri); + return biblio_citeproc_validate_csl($csl); + } +} + +function biblio_citeproc_validate_csl($csl) { + $rng_schema = drupal_get_path('module', 'biblio_citeproc') . '/schema/csl.rng'; + $doc = new DOMDocument(); + $doc->loadXML($csl); + $updated = $doc->getElementsByTagName('updated')->item(0); + $updated->nodeValue = date(DATE_ATOM, time()); + $valid = $doc->relaxNGValidate($rng_schema); + $csl = $doc->saveXML(); + return ($valid) ? array() : array(t('The supplied CSL file did not pass CSL 1.0 validation')); + +} + +function biblio_citeproc_update_installed_batch(&$context = NULL) { + $style_zip_file = variable_get('biblio_citeproc_styles_zip_file', FALSE); + $zipname = $style_zip_file ? drupal_realpath($style_zip_file->uri) : FALSE; + + if (empty($context['sandbox']['installed'])) { + $context['sandbox']['installed'] = array(); + + $result = db_select('biblio_citeproc_styles', 'csl') + ->fields('csl', array('filename', 'id', 'sha1', 'title', 'parent', 'changed', 'updated')) + ->orderBy('filename', 'ASC') + ->execute(); + + foreach ($result as $style) { + $context['sandbox']['installed'][] = $style; + } + + $context['sandbox']['progress'] = 0; + $context['results']['update_count'] = 0; + $context['results']['updated'] = array(); + } + + if (!empty($zipname)) { + //variable_del('github_zip'); + $zip = zip_open($zipname); + $za = new ZipArchive(); + + if ($za->open($zipname) !== TRUE) { + $message = t('Could not open zip file containing styles: @file', array('@file' => realpath($zipname))); + $message = check_plain($message); + drupal_set_message($message, 'error'); + $context['finished'] = 1; + return; + } + + $num_files = count($context['sandbox']['installed']); + $start = $context['sandbox']['progress']; + $end = min(($start+10), $num_files); + + for ($i = $start; $i < $end; $i++) { + $name = $context['sandbox']['installed'][$i]->filename; + $changed = $context['sandbox']['installed'][$i]->changed; + if (($index = $za->locateName($name, ZIPARCHIVE::FL_NOCASE|ZIPARCHIVE::FL_NODIR)) !== FALSE) { + if ($csl = $za->getFromIndex($index) && !$changed) { + $ret = _install_csl($name, $csl, NULL, NULL, TRUE); + if ($ret == 2) { + $context['results']['updated'][] = $name; + $context['message'] = t('Updated') . ': ' . $name; + } + } + } + $context['sandbox']['progress']++; + } + $za->close(); + + if ($context['sandbox']['progress'] != $num_files) { + $context['finished'] = $context['sandbox']['progress'] / $num_files; + } + } +} + +function biblio_citeproc_update_installed_finished($success, $results, $operations) { + if ($success) { + if (count($results['updated'])) { + $message = format_plural(count($results['updated']), 'The following style was updated.', 'The following @count styles were updated.'); + drupal_set_message($message); + foreach ($results['updated'] as $style) { + drupal_set_message($style); + } + } + else { + $message = t('No updates were found, all styles are current.'); + drupal_set_message($message); + } + } + else { + drupal_set_message(t('Finished with an error.')); + } +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/biblio_citeproc.info --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/biblio_citeproc.info Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,13 @@ +name = Biblio - CiteProc +description = Adds Citation Style Language (CSL) citation processing +core = 7.x +package = Biblio +dependencies[] = biblio +files[] = CSL.inc + +; Information added by drupal.org packaging script on 2013-07-20 +version = "7.x-1.0-rc7" +core = "7.x" +project = "biblio" +datestamp = "1374290470" + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/biblio_citeproc.install --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/biblio_citeproc.install Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,343 @@ + $t('PHP Multibyte String'), + 'severity' => $mbs_severity, + 'description' => $mbs_desc, + ); + } + return $requirements; +} + +function biblio_citeproc_uninstall() { + if (db_table_exists('biblio_type_maps')) { + db_delete('biblio_type_maps') + ->condition('format', 'csl') + ->execute(); + } + if ($file = variable_get('biblio_citeproc_styles_zip_file', NULL)) { + file_usage_delete($file, 'biblio_citeproc'); + file_delete($file); + } + cache_clear_all('biblio_citeproc_styles', 'cache'); + variable_del('biblio_citeproc_styles_zip_file'); + variable_del('biblio_citeproc_style'); +} + +function biblio_citeproc_schema() { + $schema['biblio_citeproc_styles'] = array( + 'fields' => array( + 'id' => array( + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '' + ), + 'title' => array( + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '' + ), + 'filename' => array( + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '' + ), + 'parent' => array( + 'type' => 'varchar', + 'length' => 255, + 'not null' => FALSE, + 'default' => '' + ), + 'summary' => array( + 'type' => 'text', + 'not null' => FALSE, + ), + 'csl' => array( + 'type' => 'blob', + 'not null' => TRUE + ), + 'sha1' => array( + 'type' => 'varchar', + 'length' => 40, + 'not null' => TRUE, + 'default' => '' + ), + 'changed' => array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), + 'updated' => array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), + ), + 'primary key' => array('id') + ); + + return $schema; +} + +function biblio_citeproc_install_default_styles() { + $record = array(); + $dir = drupal_get_path('module', 'biblio_citeproc') . '/style'; + $files = file_scan_directory($dir, '/..*.csl$/'); + + foreach ($files as $file) { + $csl = file_get_contents($file->uri); + $name = basename($file->filename); + biblio_citeproc_install_style($name, $csl); + } +} + +function biblio_citeproc_update_default_styles() { + biblio_citeproc_install_default_styles(); +} + +function _get_csl_type_map() { + $map['type_map'] = serialize( + array( + 'article' => '', + 'article-magazine' => 106, + 'article-newspaper' => 105, + 'article-journal' => 102, + 'bill' => 117, + 'book' => 100, + 'broadcast' => 111, + 'chapter' => 101, + 'entry' => '', + 'entry-dictionary' => '', + 'entry-encyclopedia' => '', + 'figure' => '', + 'graphic' => '', + 'interview' => '', + 'legislation' => 118, + 'legal_case' => 128, + 'manuscript' => 121, + 'map' => 122, + 'motion_picture' => 110, + 'musical_score' => '', + 'pamphlet' => '', + 'paper-conference' => 103, + 'patent' => 119, + 'post' => '', + 'post-weblog' => '', + 'personal\_communication' => 120, + 'report' => 109, + 'review' => '', + 'review-book' => '', + 'song' => '', + 'speech' => '', + 'thesis' => 108, + 'treaty' => '', + 'webpage' => 107, + ) + ); + $map['format'] = 'csl'; + return $map; +} +function _get_csl_type_names() { + $map['type_names'] = serialize( + array( + 'article' => '', + 'article-magazine' => "Magazine Article", + 'article-newspaper' => "Newspaper Article", + 'article-journal' => "Journal Article", + 'bill' => 'Bill', + 'book' => "Book", + 'broadcast' => 'Broadcast', + 'chapter' => "Book Section", + 'entry' => '', + 'entry-dictionary' => '', + 'entry-encyclopedia' => '', + 'figure' => '', + 'graphic' => '', + 'interview' => '', + 'legislation' => 'Legislation', + 'legal_case' => 'Legal Ruling', + 'manuscript' => 'Manuscript', + 'map' => 'Map', + 'motion_picture' => "Film or Broadcast", + 'musical_score' => '', + 'pamphlet' => '', + 'paper-conference' => "Conference Paper", + 'patent' => "Patent", + 'post' => '', + 'post-weblog' => '', + 'personal\_communication' => 'Personal Communication', + 'report' => "Report", + 'review' => '', + 'review-book' => '', + 'song' => '', + 'speech' => '', + 'thesis' => "Thesis", + 'treaty' => '', + 'webpage' => "Web Page", + ) + ); + + $map['format'] = 'csl'; + return $map; +} + +function _get_csl_field_map() { + $map['field_map'] = serialize( + array( + 'title' => 'title', + 'container-title' => 'biblio_secondary_title', + 'collection-title' => 'biblio_secondary_title', + 'original-title' => 'biblio_alternate_title', + 'publisher' => 'biblio_publisher', + 'publisher-place' => 'biblio_place_published', + 'original-publisher' => '', + 'original-publisher-place' => '', + 'archive' => '', + 'archive-place' => '', + 'authority' => '', + 'archive_location' => '', + 'event' => 'biblio_secondary_title', + 'event-place' => 'biblio_place_published', + 'page' => 'biblio_pages', + 'page-first' => '', + 'locator' => '', + 'version' => 'biblio_edition', + 'volume' => 'biblio_volume', + 'number-of-volumes' => 'biblio_number_of_volumes', + 'number-of-pages' => '', + 'issue' => 'biblio_issue', + 'chapter-number' => 'biblio_section', + 'medium' => '', + 'status' => '', + 'edition' => 'biblio_edition', + 'section' => 'biblio_section', + 'genre' => '', + 'note' => 'biblio_notes', + 'annote' => '', + 'abstract' => 'biblio_abst_e', + 'keyword' => 'biblio_keywords', + 'number' => 'biblio_number', + 'references' => '', + 'URL' => 'biblio_url', + 'DOI' => 'biblio_doi', + 'ISBN' => 'biblio_isbn', + 'call-number' => 'biblio_call_number', + 'citation-number' => '', + 'citation-label' => 'biblio_citekey', + 'first-reference-note-number' => '', + 'year-suffix' => '', + 'jurisdiction' => '', + + //Date Variables' + + 'issued' => 'biblio_year', + 'event' => 'biblio_date', + 'accessed' => 'biblio_access_date', + 'container' => 'biblio_date', + 'original-date' => 'biblio_date', + + //Name Variables' + + 'author' => 'biblio_contributors:1', + 'editor' => 'biblio_contributors:2', + 'translator' => 'biblio_contributors:3', + 'recipient' => '', + 'interviewer' => 'biblio_contributors:1', + 'publisher' => 'biblio_publisher', + 'composer' => 'biblio_contributors:1', + 'original-publisher' => '', + 'original-author' => '', + 'container-author' => '', + 'collection-editor' => '', + ) + ); + $map['format'] = 'csl'; + return $map; +} + +function _save_csl_maps() { + $typemap = _get_csl_type_map(); + $typenames = _get_csl_type_names(); + $fieldmap = _get_csl_field_map(); + $maps = array_merge($typemap, $typenames, $fieldmap); + biblio_save_map($maps); +} + +function _reset_csl_map($type = NULL) { + $count = db_query("SELECT COUNT(*) FROM {biblio_type_maps} WHERE format='csl'")->fetchField(); + if ($count && $type) { //update + $function = '_get_csl_' . $type; + if (!function_exists($function)) return; + $map = $function(); + db_update('biblio_type_maps') + ->fields($map) + ->condition('format', 'csl') + ->execute(); + } + else { // install + db_delete('biblio_type_maps') + ->condition('format', 'csl') + ->execute(); + _save_csl_maps(); + } +} +/** + * + * Adds CSL field and type maps to biblio_type_maps table + */ +function biblio_citeproc_update_7001() { + _reset_csl_map(); +} +/** + * + * Updates the default CSL styles + */ +function biblio_citeproc_update_7002() { + biblio_citeproc_update_default_styles(); +} +/** + * Adds "changed" and "updated" columns + * + */ +function biblio_citeproc_update_7003() { + $spec = array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ); + db_add_field('biblio_citeproc_styles', 'changed', $spec); + db_add_field('biblio_citeproc_styles', 'updated', $spec); +} +/** + * Corrects an error in the field_map + * + */ +function biblio_citeproc_update_7004() { + $map = biblio_get_map('field_map', 'csl'); + if ($map['accessed'] == 'biblio_accessed') { + $map['accessed'] = 'biblio_access_date'; + biblio_set_map('field_map', 'csl', $map); + } +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/biblio_citeproc.module --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/biblio_citeproc.module Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,191 @@ + 'CiteProc', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_citeproc_style_manager_form'), + 'access arguments' => array('administer biblio'), + 'file' => 'biblio_citeproc.admin.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => 12 + ); + $items['admin/config/content/biblio/citeproc/styles'] = array( + 'title' => 'CiteProc Style Manager', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_citeproc_style_manager_form'), + 'access arguments' => array('administer biblio'), + 'file' => 'biblio_citeproc.admin.inc', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => 12 + ); + $items['admin/config/content/biblio/citeproc/styles/%/edit'] = array( + 'title' => 'CiteProc Style Editor', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_citeproc_csl_editor', 6), + 'access arguments' => array('administer biblio'), + 'file' => 'biblio_citeproc.admin.inc', + 'type' => MENU_CALLBACK, + 'weight' => 12 + ); + $items['admin/config/content/biblio/citeproc/map'] = array( + 'title' => 'CSL Field Mapper', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('biblio_admin_io_mapper_form', 'csl', FALSE), + 'access arguments' => array('administer biblio'), + 'file' => '../../includes/biblio.admin.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => 12 + ); + return $items; +} +function biblio_citeproc_theme() { + return array( + 'biblio_citeproc_style' => array( + 'file' => 'biblio_citeproc.module', + 'variables' => array( + 'node' => '', + 'style_name' => 'cse', + ), + ), + 'biblio_citeproc_style_manager_form' => array( + 'render element' => 'form', + ), + ); +} + +/** + * Implements hook_biblio_map_alter(). + */ +function biblio_citeproc_biblio_map_alter(&$map, $type, $format) { + if ($type == 'field_map' && $format == 'csl') { + $map = array_merge($map, array( + 'author' => 'biblio_contributors:1', + 'editor' => 'biblio_contributors:2', + 'translator' => 'biblio_contributors:3', + 'recipient' => ':', + 'interviewer' => ':', + 'composer' => ':', + )); + } +} + +function biblio_citeproc_theme_registry_alter(&$theme_registry) { + $theme_registry['biblio_style'] = $theme_registry['biblio_citeproc_style']; +} + +function biblio_citeproc_load_csl($csl_id) { + $csl_file_contents = ''; + if (strpos($csl_id, '.csl') === FALSE) {// try to convert old style names to csl... + if (in_array($csl_id, array('ama', 'apa', 'cse', 'ieee', 'mla', 'vancouver'))) { + $csl_id .= '.csl'; + } + elseif ($csl_id == 'chicago') { + $csl_id = 'chicago-fullnote-bibliography.csl'; + } + else { + $csl_id = ''; + $message = t('An invalid style "@style" was selected, please check your "CiteProc" style settings.', array('@style' => $csl_id)); + drupal_set_message($message, 'error'); + } + } + if (!empty($csl_id)) { + $csl = db_query('SELECT parent,csl FROM {biblio_citeproc_styles} WHERE filename = :id', array(':id' => $csl_id))->fetchObject(); + if (!isset($csl->csl)) { + drupal_set_message(t('Biblio-CiteProc could not fetch the style file: @csl_id from the database. Check your CiteProc settings.', array('@csl_id' => $csl_id)), 'error'); + return; + } + if (!empty($csl->parent)) { + $csl_file_contents = db_query("SELECT csl FROM {biblio_citeproc_styles} WHERE id = :id", array(':id' => $csl->parent))->fetchField(); + + } + else { + $csl_file_contents = $csl->csl; + } + } + return $csl_file_contents; +} + +function theme_biblio_citeproc_style($variables) { + static $citeproc; + global $language; + $cached = NULL; + $node = $variables['node']; + $style = isset($variables['style_name']) ? $variables['style_name'] : NULL; + + module_load_include('inc', 'biblio_citeproc', 'CSL'); + + if (!$citeproc) { + $csl_id = ($style) ? $style : biblio_get_style(); + if ($csl_file_contents = biblio_citeproc_load_csl($csl_id)) { + // $cslid = $csl_file_name . '-' . $language->language; + // $cached = cache_get($cslid, 'cache_biblio_csl_object'); + if (!$cached) { + $citeproc = new citeproc($csl_file_contents, $language->language); + // cache_set($cslid, $citeproc, 'cache_biblio_csl_object'); + } + else { + $citeproc = $cached->data; + } + } + } + + $output = ''; + if ($citeproc) { + $styled_node = $citeproc->render($node); + $coins_data = isset($node->biblio_coins) ? filter_xss($node->biblio_coins, array('span')) : ''; + $output = $styled_node . $coins_data; + } + + return $output; +} + +function biblio_citeproc_csl_map_reset($type = NULL) { + module_load_include('install', 'biblio_citeproc', 'biblio_citeproc'); + _reset_csl_map($type); +} + +function biblio_citeproc_install_style($name, $csl) { + + $xml = simplexml_load_string($csl); + + $parent = ''; + foreach ($xml->info->link as $link) { + $attrs = $link->attributes(); + if (isset($attrs['rel']) && $attrs['rel'] == 'independent-parent') { + $parent = (string)$attrs['href']; + } + } + + $old_sha1 = NULL; + + $old_sha1 = db_query('SELECT sha1 FROM {biblio_citeproc_styles} WHERE id = :id', array(':id' => (string)$xml->info->id))->fetchField(); + + $record = array( + 'filename' => $name, + 'parent' => $parent, + 'title' => (string)$xml->info->title, + 'summary' => (string)$xml->info->summary, + 'csl' => $csl, + 'sha1' => sha1($csl), + 'id' => (string)$xml->info->id, + ); + + if ($old_sha1 && $old_sha1 == sha1($csl)) { //style exists and has not changed + return; + } + elseif ($old_sha1 && $old_sha1 != sha1($csl)) { // update an existing style + $query = db_update('biblio_citeproc_styles') + ->fields($record) + ->condition('id', $record['id']); + } + elseif (!$old_sha1) { //install new style + $query = db_insert('biblio_citeproc_styles') + ->fields(array('id', 'title', 'filename', 'summary', 'csl', 'sha1')); + + $query->values($record); + } + $query->execute(); + +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-af-ZA.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-af-ZA.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + toegang verkry + en + and others + anonymous + anon + at + by + circa + c. + cited + + edition + editions + + ed + et al. + voorhande + van + ibid. + in + in press + internet + interview + letter + no date + n.d. + online + presented at the + + reference + references + + + ref. + refs. + + opgehaal + + + AD + BC + + + + + + + + + + st + nd + rd + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + linguistics + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + reël + reëls + + + note + notes + + + opus + opera + + + bladsy + bladsye + + + paragraaf + paragrawe + + + part + parts + + + section + sections + + + sub verbo + sub verbis + + + verse + verses + + + volume + volumes + + + + bk + chap + col + fig + f + no + op + + bl + bll + + para + pt + sec + + s.v. + s.vv. + + + v + vv + + + vol + vols + + + + + + ¶¶ + + + § + §§ + + + + + + + + + redakteur + redakteurs + + + editor + editors + + + vertaler + vertalers + + + editor & translator + editors & translators + + + + + + + + + red + reds + + + ed. + eds. + + + vert + verts + + + ed. & tran. + eds. & trans. + + + + onder redaksie van + edited by + vertaal deur + edited & translated by + to + interview by + + + by + red + ed. + verts + ed. & trans. by + + + Januarie + Februarie + Maart + April + Mei + Junie + Julie + Augustus + September + Oktober + November + Desember + + + Jan + Feb + Mrt + Apr + Mei + Jun + Jul + Aug + Sep + Okt + Nov + Des + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-ar-AR.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-ar-AR.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,306 @@ + + + + + + + + + + + + + + + تاريخ الوصول + و + وآخرون + مجهول + مجهول + عند + عن طريق + حوالي + حو. + وثق + + الطبعة + الطبعات + + ط. + وآخ. + التالي + من + المرجع السابق + في + قيد النشر + انترنت + مقابلة + خطاب + دون تاريخ + د.ت + على الخط المباشر + قُدَّم في + + مرجع + مراجع + + + مرجع + مراجع + + استرجع في + + + ب.م. + ق.م. + + + + + " + " + ' + ' + + + + + + + + + الاول + الثاني + الثالث + الرابع + الخامس + السادس + السابع + الثامن + التاسع + العاشر + + + الاناسة + الفلك + الأحياء + النبات + الكيمياء + الهندسة + العلوم العامة + الجغرافيا + الجيولوجيا + التاريخ + الإنسانيات + اللغويات + الأدب + الرياضيات + الطب + الفلسفة + الفيزياء + علم النفس + علم الإجتماع + العلوم البحتة + العلوم السياسية + العلوم الإجتماعية + الإلهيات + علم الحيوان + + + + كتاب + كتب + + + فصل + فصول + + + عمود + أعمدة + + + رسم توضيحي + رسوم توضيحية + + + ورقة + أوراق + + + عدد + أعداد + + + سطر + أسطر + + + ملاحظة + ملاحظات + + + نوته موسيقية + نوت موسيقية + + + صفحة + صفحات + + + فقرة + فقرات + + + جزء + أجزاء + + + قسم + أقسام + + + تفسير فرعي + تفسيرات فرعية + + + بيت شعر + أبيات شعر + + + مجلد + مجلدات + + + + كتاب + فصل + عمود + رسم توضيحي + مطوية + عدد + نوتة موسيقية + + ص + ص.ص. + + فقرة + ج. + قسم + + تفسير فرعي + تفسيرات فرعية + + + بيت شعر + أبيات شعر + + + مج. + مج. + + + + + + ¶¶ + + + § + §§ + + + + + مؤلف + مؤلفين + + + محرر + محررين + + + رئيس التحرير + رؤساء التحرير + + + مترجم + مترجمين + + + مترجم ومحرر + مترجمين ومحررين + + + + + مؤلف + مؤلفين + + + محرر + محررين + + + مشرف على الطبعة + مشرفين على الطبعة + + + مترجم + مترجمين + + + مترجم ومشرف على الطباعه + مترجمين ومشرفين على الطباعه + + + + تحرير + اعداد + ترجمة + اعداد وترجمة + مرسل الى + مقابلة بواسطة + + + + تحرير + اشرف على الطبعة + ترجمة + ترجمه واشرف على الطباعه + + + يناير + فبراير + مارس + ابريل + مايو + يونيو + يوليو + اغسطس + سبتمبر + اكتوبر + نوفمبر + ديسمبر + + + يناير + فبراير + مارس + ابريل + مايو + يونيو + يوليو + اغسطس + سبتمبر + اكتوبر + نوفمبر + ديسمبر + + + الربيع + الصيف + الخريف + الشتاء + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-bg-BG.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-bg-BG.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + отворен на + и + и други + анонимен + анон + в + by + circa + c. + цитиран + + издание + издания + + изд + и съавт. + предстоящ + от + пак там + в + под печат + интернет + интервю + писмо + no date + без дата + онлайн + представен на + + reference + references + + + ref. + refs. + + изтеглен на + + + AD + BC + + + + + + + + + + st + nd + rd + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + антропология + астрономия + биология + ботаника + химия + инженерство + обща база + география + геология + история + хуманитарни науки + linguistics + литература + математика + медицина + философия + физика + физиология + социология + наука + политически науки + обществени науки + теология + зоология + + + + книга + книги + + + глава + глави + + + колона + колони + + + фигура + фигури + + + фолио + фолия + + + брой + броеве + + + ред + редове + + + бележка + бележки + + + опус + опуси + + + страница + страници + + + параграф + параграфи + + + част + части + + + раздел + раздели + + + sub verbo + sub verbis + + + стих + стихове + + + том + томове + + + + кн + гл + кол + фиг + фол + бр + оп + + с + с-ци + + п + ч + разд + + s.v. + s.vv. + + + ст + ст-ове + + + том + т-ове + + + + + + ¶¶ + + + § + §§ + + + + + автор + автори + + + редактор + редактори + + + editor + editors + + + преводач + преводачи + + + editor & translator + editors & translators + + + + + авт + авт-ри + + + ред + ред-ри + + + ed. + eds. + + + прев + прев-чи + + + ed. & tran. + eds. & trans. + + + + редактиран от + edited by + преведен от + edited & translated by + до + интервюиран от + + + by + ред + ed. + прев + ed. & trans. by + + + Януари + Февруари + Март + Април + Май + Юни + Юли + Август + Септември + Октомври + Ноември + Декември + + + Яну + Фев + Мар + Апр + Май + Юни + Юли + Авг + Сеп + Окт + Ное + Дек + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-ca-AD.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-ca-AD.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + accedit + i + i altres + anònim + anòn. + a + per + circa + c. + citat + + edició + edicions + + ed. + et al. + previst + de + ibíd. + en + en impremta + internet + entrevista + carta + sense data + s.d. + en línia + presentat a + + referència + referències + + + ref. + ref. + + recuperat + + + dC + aC + + + + « + » + + + + + a + a + a + a + + + primera + segona + tercera + quarta + cinquena + sisena + setena + vuitena + novena + desena + + + antropologia + astronomia + biologia + botànica + química + enginyeria + base genèrica + geografia + geologia + història + humanitats + lingüística + literatura + matemàtiques + medicina + filosofia + física + psicologia + sociologia + ciències + ciències polítiques + ciències socials + teologia + zoologia + + + + llibre + llibres + + + capítol + capítols + + + columna + columnes + + + figura + figures + + + foli + folis + + + número + números + + + línia + línies + + + nota + notes + + + opus + opera + + + pàgina + pàgines + + + paràgraf + paràgrafs + + + part + parts + + + secció + seccions + + + sub voce + sub vocibus + + + vers + versos + + + volum + volums + + + + llib. + cap. + col. + fig. + f. + núm. + op. + + p. + p. + + par. + pt. + sec. + + s.v. + s.v. + + + v. + v. + + + vol. + vol. + + + + + § + § + + + § + § + + + + + + + + + editor + editors + + + editor + editors + + + traductor + traductors + + + editor i traductor + editors i traductors + + + + + + + + + ed. + ed. + + + ed. + ed. + + + trad. + trad. + + + ed. i trad. + ed. i trad. + + + + editat per + editat per + traduït per + editat i traduït per + a + entrevistat per + + + per + ed. + ed. + trad. + ed. i trad. per + + + gener + febrer + març + abril + maig + juny + juliol + agost + setembre + octubre + novembre + desembre + + + gen. + febr. + març + abr. + maig + juny + jul. + ag. + set. + oct. + nov. + des. + + + primavera + estiu + tardor + hivern + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-cs-CZ.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-cs-CZ.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + přístup + a + a další + anonymous + anon. + v + by + circa + c. + citován + + vydání + vydání + + vyd. + et al. + nadcházející + z + ibid. + v + v tisku + internet + interview + dopis + bez data + nedatováno + online + prezentován v + + reference + references + + + ref. + refs. + + získáno + + + n. l. + př. n. l. + + + + + + + + + + . + . + . + . + + + první + druhé + třetí + čtvrté + páté + šesté + sedmé + osmé + deváté + desáté + + + antropologie + astronomie + biologie + botanika + chemie + technika + všeobecný základ + geografie + geologie + historie + humanitní + linguistics + literatura + matematika + medicína + filosofie + fyzika + psychologie + sociologie + věda + politologie + sociální věda + teologie + zoologie + + + + kniha + knihy + + + kapitola + kapitoly + + + sloupec + sloupce + + + obrázek + obrázky + + + list + listy + + + číslo + číslo + + + řádek + řádky + + + poznámka + poznámky + + + opus + opera + + + strana + strany + + + odstavec + odstavce + + + část + části + + + sekce + sekce + + + sub verbo + sub verbis + + + verš + verše + + + ročník + ročníky + + + + kn. + kap. + sl. + obr. + l. + čís. + op. + + s. + s. + + odst. + č. + sek. + + s.v. + s.vv. + + + v. + v. + + + roč. + roč. + + + + + + ¶¶ + + + § + §§ + + + + + autor + autoři + + + editor + editoři + + + editor + editors + + + překladatel + překladatelé + + + editor a překladatel + editoři a překladatelé + + + + + + + + + ed. + ed. + + + ed. + ed. + + + překl. + překl. + + + ed. a překl. + ed. a překl. + + + + editoval + editoval + přeložil + editoval a přeložil + pro + rozhovor vedl + + + by + ed. + ed. + překl. + ed. a přel. + + + leden + únor + březen + duben + květen + červen + červenec + srpen + září + říjen + listopad + prosinec + + + led. + úno. + bře. + dub. + kvě. + čer. + čvc. + srp. + zář. + říj. + lis. + pro. + + + jaro + léto + podzim + zima + + \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-da-DK.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-da-DK.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + åbnet + og + med flere + anonym + anon. + + af + cirka + ca. + citeret + + udgave + udgaver + + udg. + et al. + kommende + fra + ibid. + i + i tryk + internet + interview + brev + ingen dato + udateret + online + præsenteret ved + + reference + referencer + + + ref. + refr. + + hentet + + + e.Kr + f.Kr + + + + « + » + + + + + . + . + . + . + + + første + anden + tredje + fjerde + femte + sjette + syvende + ottende + niende + tiende + + + antropologi + astronomi + biologi + botanik + kemi + ingeniørvidenskab + generel + geografi + geologi + historie + humanistiske fag + lingvistik + litteratur + matematik + medicin + filosofi + fysik + fysiologi + sociologi + naturvidenskab + statskundskab + samfundsvidenskab + teologi + zoologi + + + + bog + bøger + + + kapitel + kapitler + + + kolonne + kolonner + + + figur + figurer + + + folio + folier + + + nummer + numre + + + linje + linjer + + + note + noter + + + opus + opuser + + + side + sider + + + afsnit + afsnit + + + del + dele + + + sektion + sektionerne + + + sub verbo + sub verbis + + + vers + vers + + + bind + bind + + + + b. + kap. + kol. + fig. + fol. + nr. + op. + + s. + s. + + afs. + d. + sekt. + + s.v. + s.vv. + + + v. + v. + + + bd. + bd. + + + + + + ¶¶ + + + § + §§ + + + + + + + + + redaktør + redaktører + + + redaktør + redaktører + + + oversætter + oversættere + + + redaktør & oversætter + redaktører & oversættere + + + + + + + + + red. + red. + + + red. + red. + + + overs. + overs. + + + red. & overs. + red. & overs. + + + + redigeret af + redigeret af + oversat af + redigeret & oversat af + modtaget af + interviewet af + + + af + red. + red. + overs. + red. & overs. af + + + Januar + Februar + Marts + April + Maj + Juni + Juli + August + September + Oktober + November + December + + + Jan. + Feb. + Mar. + Apr. + Maj + Jun. + Jul. + Aug. + Sep. + Okt. + Nov. + Dec. + + + Forår + Sommer + Efterår + vinter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-de-AT.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-de-AT.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + zugegriffen + und + und andere + ohne Autor + o. A. + auf + von + circa + ca. + zitiert + + Auflage + Auflagen + + Aufl. + u. a. + i. E. + von + ebd. + in + im Druck + Internet + Interview + Brief + ohne Datum + o. J. + online + gehalten auf der + + Referenz + Referenzen + + + Ref. + Ref. + + abgerufen + + + v. Chr. + n. Chr. + + + + + + + + + . + . + . + . + + + erster + zweiter + dritter + vierter + fünfter + sechster + siebter + achter + neunter + zehnter + + + Anthropologie + Astronomie + Biologie + Botanik + Chemie + Ingenieurswissenschaften + generischer Stil + Geographie + Geologie + Geschichte + Geisteswissenschaften + Linguistik + Literatur + Mathematik + Medizin + Philosophie + Physik + Psychologie + Soziologie + Naturwissenschaften + Politikwissenschaft + Sozialwissenschaften + Theologie + Zoologie + + + + Buch + Bücher + + + Kapitel + Kapitel + + + Spalte + Spalten + + + Abbildung + Abbildungen + + + Blatt + Blätter + + + Nummer + Nummern + + + Zeile + Zeilen + + + Note + Noten + + + Opus + Opera + + + Seite + Seiten + + + Absatz + Absätze + + + Teil + Teile + + + Abschnitt + Abschnitte + + + sub verbo + sub verbis + + + Vers + Verse + + + Band + Bände + + + + B. + Kap. + Sp. + Abb. + Fol. + Nr. + op. + + S. + S. + + Abs. + Teil + Abschn. + + s.v. + s.vv. + + + V. + V. + + + Bd. + Bd. + + + + + + ¶¶ + + + § + §§ + + + + + + + + + Herausgeber + Herausgeber + + + Herausgeber + Herausgeber + + + Übersetzer + Übersetzer + + + Herausgeber & Übersetzer + Herausgeber & Übersetzer + + + + + + + + + Hrsg. + Hrsg. + + + Hrsg. + Hrsg. + + + Übers. + Übers. + + + Hrsg. & Übers. + Hrsg. & Übers + + + + herausgegeben von + herausgegeben von + übersetzt von + herausgegeben und übersetzt von + an + interviewt von + + + von + hg. von + hg. von + übers. von + hg. & übers. von + + + Januar + Februar + März + April + Mai + Juni + Juli + August + September + Oktober + November + Dezember + + + Jan. + Feb. + März + Apr. + Mai + Juni + Juli + Aug. + Sep. + Okt. + Nov. + Dez. + + + Frühjahr + Sommer + Herbst + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-de-CH.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-de-CH.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + zugegriffen + und + und andere + ohne Autor + o. A. + auf + von + circa + ca. + zitiert + + Auflage + Auflagen + + Aufl. + u. a. + i. E. + von + ebd. + in + im Druck + Internet + Interview + Brief + ohne Datum + o. J. + online + gehalten auf der + + Referenz + Referenzen + + + Ref. + Ref. + + abgerufen + + + v. Chr. + n. Chr. + + + + + + + + + . + . + . + . + + + erster + zweiter + dritter + vierter + fünfter + sechster + siebter + achter + neunter + zehnter + + + Anthropologie + Astronomie + Biologie + Botanik + Chemie + Ingenieurswissenschaften + generischer Stil + Geographie + Geologie + Geschichte + Geisteswissenschaften + Linguistik + Literatur + Mathematik + Medizin + Philosophie + Physik + Psychologie + Soziologie + Naturwissenschaften + Politikwissenschaft + Sozialwissenschaften + Theologie + Zoologie + + + + Buch + Bücher + + + Kapitel + Kapitel + + + Spalte + Spalten + + + Abbildung + Abbildungen + + + Blatt + Blätter + + + Nummer + Nummern + + + Zeile + Zeilen + + + Note + Noten + + + Opus + Opera + + + Seite + Seiten + + + Absatz + Absätze + + + Teil + Teile + + + Abschnitt + Abschnitte + + + sub verbo + sub verbis + + + Vers + Verse + + + Band + Bände + + + + B. + Kap. + Sp. + Abb. + Fol. + Nr. + op. + + S. + S. + + Abs. + Teil + Abschn. + + s.v. + s.vv. + + + V. + V. + + + Bd. + Bd. + + + + + + ¶¶ + + + § + §§ + + + + + + + + + Herausgeber + Herausgeber + + + Herausgeber + Herausgeber + + + Übersetzer + Übersetzer + + + Herausgeber & Übersetzer + Herausgeber & Übersetzer + + + + + + + + + Hrsg. + Hrsg. + + + Hrsg. + Hrsg. + + + Übers. + Übers. + + + Hrsg. & Übers. + Hrsg. & Übers + + + + herausgegeben von + herausgegeben von + übersetzt von + herausgegeben und übersetzt von + an + interviewt von + + + von + hg. von + hg. von + übers. von + hg. & übers. von + + + Januar + Februar + März + April + Mai + Juni + Juli + August + September + Oktober + November + Dezember + + + Jan. + Feb. + März + Apr. + Mai + Juni + Juli + Aug. + Sep. + Okt. + Nov. + Dez. + + + Frühjahr + Sommer + Herbst + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-de-DE.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-de-DE.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + zugegriffen + und + und andere + ohne Autor + o. A. + auf + von + circa + ca. + zitiert + + Auflage + Auflagen + + Aufl. + u. a. + i. E. + von + ebd. + in + im Druck + Internet + Interview + Brief + ohne Datum + o. J. + online + gehalten auf der + + Referenz + Referenzen + + + Ref. + Ref. + + abgerufen + + + v. Chr. + n. Chr. + + + + + + + + + . + . + . + . + + + erster + zweiter + dritter + vierter + fünfter + sechster + siebter + achter + neunter + zehnter + + + Anthropologie + Astronomie + Biologie + Botanik + Chemie + Ingenieurswissenschaften + generischer Stil + Geographie + Geologie + Geschichte + Geisteswissenschaften + Linguistik + Literatur + Mathematik + Medizin + Philosophie + Physik + Psychologie + Soziologie + Naturwissenschaften + Politikwissenschaft + Sozialwissenschaften + Theologie + Zoologie + + + + Buch + Bücher + + + Kapitel + Kapitel + + + Spalte + Spalten + + + Abbildung + Abbildungen + + + Blatt + Blätter + + + Nummer + Nummern + + + Zeile + Zeilen + + + Note + Noten + + + Opus + Opera + + + Seite + Seiten + + + Absatz + Absätze + + + Teil + Teile + + + Abschnitt + Abschnitte + + + sub verbo + sub verbis + + + Vers + Verse + + + Band + Bände + + + + B. + Kap. + Sp. + Abb. + Fol. + Nr. + op. + + S. + S. + + Abs. + Teil + Abschn. + + s.v. + s.vv. + + + V. + V. + + + Bd. + Bd. + + + + + + ¶¶ + + + § + §§ + + + + + + + + + Herausgeber + Herausgeber + + + Herausgeber + Herausgeber + + + Übersetzer + Übersetzer + + + Herausgeber & Übersetzer + Herausgeber & Übersetzer + + + + + + + + + Hrsg. + Hrsg. + + + Hrsg. + Hrsg. + + + Übers. + Übers. + + + Hrsg. & Übers. + Hrsg. & Übers + + + + herausgegeben von + herausgegeben von + übersetzt von + herausgegeben und übersetzt von + an + interviewt von + + + von + hg. von + hg. von + übers. von + hg. & übers. von + + + Januar + Februar + März + April + Mai + Juni + Juli + August + September + Oktober + November + Dezember + + + Jan. + Feb. + März + Apr. + Mai + Juni + Juli + Aug. + Sep. + Okt. + Nov. + Dez. + + + Frühjahr + Sommer + Herbst + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-el-GR.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-el-GR.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + ημερομηνία πρόσβασης + και + και άλλοι + ανώνυμο + ανών. + εφ. + από + περίπου + περ. + παρατίθεται + + έκδοση + εκδόσεις + + έκδ. + κ.ά. + προσεχές + από + στο ίδιο + στο + υπό έκδοση + διαδίκτυο + συνέντευξη + επιστολή + χωρίς χρονολογία + χ.χ. + έκδοση σε ψηφιακή μορφή + παρουσιάστηκε στο + + παραπομπή + παραπομπές + + + παρ. + παρ. + + ανακτήθηκε + + + μ.Χ. + π.Χ. + + + + + + ' + ' + + + ος + ος + ος + ος + + + πρώτος + δεύτερος + τρίτος + τέταρτος + πέμπτος + έκτος + έβδομος + όγδοος + ένατος + δέκατος + + + ανθρωπολογία + αστρονομία + βιολογία + βοτανική + χημεία + μηχανική + γενική βιβλιογραφία + γεωγραφία + γεωλογία + ιστορία + ανθρωπιστικές σπουδές + λογοτεχνία + μαθηματικά + ιατρική + φιλοσοφία + φυσική + ψυχολογία + κοινωνιολογία + θετικές επιστήμες + πολιτικές επιστήμες + κοινωνικές επιστήμες + θεολογία + ζωολογία + + + + βιβλίο + βιβλίο + + + κεφάλαιο + κεφάλαια + + + στήλη + στήλες + + + εικόνα + εικόνες + + + φάκελος + φάκελοι + + + τεύχος + τεύχη + + + σειρά + σειρές + + + σημείωση + σημειώσεις + + + έργο + έργα + + + σελίδα + σελίδες + + + παράγραφος + παράγραφοι + + + μέρος + μέρη + + + τμήμα + τμήματα + + + λήμμα + λήμματα + + + στίχος + στίχοι + + + τόμος + τόμοι + + + + βιβ. + κεφ. + στ. + εικ. + φάκ + τχ. + έργ. + + σ + σσ + + παρ. + μέρ. + τμ. + + λήμ. + λήμ. + + + στ. + στ. + + + τ. + τ. + + + + + + ¶¶ + + + § + §§ + + + + + συγγραφέας + συγγραφείς + + + επιμελητής + επιμελητές + + + διευθυντής σειράς + διευθυντές σειράς + + + μεταφραστής + μεταφραστές + + + μεταφραστής και επιμελητής + μεταφραστές και επιμελητές + + + + + συγγρ. + συγγρ. + + + επιμ. + επιμ. + + + δ/ντής σειράς + δ/ντές σειρας + + + μτφ. + μτφ. + + + μτφ. και επιμ. + μτφ. και επιμ. + + + + επιμέλεια + διεύθυνση σειράς + μετάφραση + μετάφραση και επιμέλεια + παραλήπτης + συνέντευξη + + + στον συλλ. τόμο + επιμέλ. + δ/νση σειράς + μετάφρ. + μετάφρ. και επιμέλ. + + + Ιανουάριος + Φεβρουάριος + Μάρτιος + Απρίλιος + Μάιος + Ιούνιος + Ιούλιος + Αύγουστος + Σεπτέμβριος + Οκτώβριος + Νοέμβριος + Δεκέμβριος + + + Ιανουαρίου + Φεβρουαρίου + Μαρτίου + Απριλίου + Μαΐου + Ιουνίου + Ιουλίου + Αυγούστου + Σεπτεμβρίου + Οκτωβρίου + Νοεμβρίου + Δεκεμβρίου + + + Άνοιξη + Καλοκαίρι + Φθινόπωρο + Χειμώνας + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-en-GB.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-en-GB.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + accessed + and + and others + anonymous + anon. + at + by + circa + c. + cited + + edition + editions + + ed. + et al. + forthcoming + from + ibid. + in + in press + internet + interview + letter + no date + n.d. + online + presented at the + + reference + references + + + ref. + refs. + + retrieved + + + AD + BC + + + + + + + + + st + nd + rd + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + linguistics + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + line + lines + + + note + notes + + + opus + opera + + + page + pages + + + paragraph + paragraph + + + part + parts + + + section + sections + + + sub verbo + sub verbis + + + verse + verses + + + volume + volumes + + + + bk. + chap. + col. + fig. + f. + no. + op. + + p. + pp. + + para. + pt. + sec. + + s.v. + s.vv. + + + v. + vv. + + + vol. + vols. + + + + + + ¶¶ + + + § + §§ + + + + + + + + + editor + editors + + + editor + editors + + + translator + translators + + + editor & translator + editors & translators + + + + + + + + + ed. + eds. + + + ed. + eds. + + + tran. + trans. + + + ed. & tran. + eds. & trans. + + + + edited by + edited by + translated by + edited & translated by + to + interview by + + + by + ed. + ed. + trans. + ed. & trans. by + + + January + February + March + April + May + June + July + August + September + October + November + December + + + Jan. + Feb. + Mar. + Apr. + May + Jun. + Jul. + Aug. + Sep. + Oct. + Nov. + Dec. + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-en-US.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-en-US.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + accessed + and + and others + anonymous + anon. + at + by + circa + c. + cited + + edition + editions + + ed. + et al. + forthcoming + from + ibid. + in + in press + internet + interview + letter + no date + n.d. + online + presented at the + + reference + references + + + ref. + refs. + + retrieved + + + AD + BC + + + + + + + + + st + nd + rd + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + linguistics + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + line + lines + + + note + notes + + + opus + opera + + + page + pages + + + paragraph + paragraph + + + part + parts + + + section + sections + + + sub verbo + sub verbis + + + verse + verses + + + volume + volumes + + + + bk. + chap. + col. + fig. + f. + no. + op. + + p. + pp. + + para. + pt. + sec. + + s.v. + s.vv. + + + v. + vv. + + + vol. + vols. + + + + + + ¶¶ + + + § + §§ + + + + + + + + + editor + editors + + + editor + editors + + + translator + translators + + + editor & translator + editors & translators + + + + + + + + + ed. + eds. + + + ed. + eds. + + + tran. + trans. + + + ed. & tran. + eds. & trans. + + + + edited by + edited by + translated by + edited & translated by + to + interview by + + + by + ed. + ed. + trans. + ed. & trans. by + + + January + February + March + April + May + June + July + August + September + October + November + December + + + Jan. + Feb. + Mar. + Apr. + May + Jun. + Jul. + Aug. + Sep. + Oct. + Nov. + Dec. + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-es-ES.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-es-ES.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + accedido + y + y otros + anónimo + anón. + en + de + circa + c. + citado + + edición + ediciones + + ed. + et al. + previsto + a partir de + ibid. + en + en imprenta + internet + entrevista + carta + sin fecha + s. f. + en línea + presentado en + + referencia + referencias + + + ref. + refs. + + recuperado + + + d. C. + a. C. + + + + « + » + + + + + + + + + + + primera + segunda + tercera + cuarta + quinta + sexta + séptima + octava + novena + décima + + + antropología + astronomía + biología + botánica + química + ingeniería + base genérica + geografía + geología + historia + humanidades + lingüística + literatura + matemáticas + medicina + filosofía + física + psicología + sociología + ciencias + ciencias políticas + ciencias sociales + teología + zoología + + + + libro + libros + + + capítulo + capítulos + + + columna + columnas + + + figura + figuras + + + folio + folios + + + número + números + + + línea + líneas + + + nota + notas + + + opus + opera + + + página + páginas + + + párrafo + párrafos + + + parte + partes + + + sección + secciones + + + sub voce + sub vocibus + + + verso + versos + + + volumen + volúmenes + + + + lib. + cap. + col. + fig. + f. + n.º + op. + + p. + pp. + + párr. + pt. + sec. + + s. v. + s. vv. + + + v. + vv. + + + vol. + vols. + + + + + § + § + + + § + § + + + + + + + + + editor + editores + + + editor + editores + + + traductor + traductores + + + editor y traductor + editores y traductores + + + + + + + + + ed. + eds. + + + ed. + eds. + + + trad. + trads. + + + ed. y trad. + eds. y trads. + + + + editado por + editado por + traducido por + editado y traducido por + a + entrevistado por + + + de + ed. + ed. + trad. + ed. y trad. + + + enero + febrero + marzo + abril + mayo + junio + julio + agosto + septiembre + octubre + noviembre + diciembre + + + ene. + feb. + mar. + abr. + may + jun. + jul. + ago. + sep. + oct. + nov. + dic. + + + primavera + verano + otoño + invierno + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-et-EE.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-et-EE.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + vaadatud + ja + ja teised + anonüümne + anon + + + umbes + u + tsiteeritud + + väljaanne + väljaanded + + tr + et al. + ilmumisel + + ibid. + + trükis + internet + intervjuu + kiri + s.a. + s.a. + online + esitatud + + viide + viited + + + viide + viited + + salvestatud + + + pKr + eKr + + + + + + + + + + + + + + + esimene + teine + kolmas + neljas + viies + kuues + seitsmes + kaheksas + üheksas + kümnes + + + antropoloogia + astronoomia + bioloogia + botaanika + keemia + tehnikateadus + määratlemata + geograafia + geoloogia + ajalugu + humanitaarteadus + lingvistika + kirjandusteadus + matemaatika + meditsiin + filosoofia + füüsika + psühholoogia + sotsioloogia + reaalteadus + politoloogia + sotsiaalteadus + teoloogia + zooloogia + + + + raamat + raamatud + + + peatükk + peatükid + + + veerg + veerud + + + joonis + joonised + + + foolio + fooliod + + + number + numbrid + + + rida + read + + + viide + viited + + + opus + opera + + + lehekülg + leheküljed + + + lõik + lõigud + + + osa + osad + + + alajaotis + alajaotised + + + sub verbo + sub verbis + + + värss + värsid + + + köide + köited + + + + rmt + ptk + v + joon + f + nr + op + + lk + lk + + lõik + osa + alajaot. + + s.v. + s.vv. + + + v + vv + + + kd + kd + + + + + + ¶¶ + + + § + §§ + + + + + + + + + toimetaja + toimetajad + + + toimetaja + toimetajad + + + tõlkija + tõlkijad + + + toimetaja & tõlkija + toimetajad & tõlkijad + + + + + + + + + toim + toim + + + toim + toim + + + tõlk + tõlk + + + toim & tõlk + toim & tõlk + + + + toimetanud + toimetanud + tõlkinud + toimetanud & tõlkinud + + intervjueerinud + + + + toim + toim + tõlk + toim & tõlk + + + jaanuar + veebruar + märts + aprill + mai + juuni + juuli + august + september + oktoober + november + detsember + + + jaan + veebr + märts + apr + mai + juuni + juuli + aug + sept + okt + nov + dets + + + kevad + suvi + sügis + talv + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-eu.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-eu.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + eskuratua + eta + eta beste + ezezaguna + ezez. + -(e)n + -(e)k egina + inguru + ing. + aipatua + + argitalpena + argitalpenak + + arg. + et al. + bidean + -(e)tik + ibíd. + in + moldiztegian + internet + elkarrizketa + gutuna + datarik gabe + d. g. + sarean + -(e)n aurkeztua + + aipamena + aipamenak + + + aip. + aip. + + berreskuratua + + + K.a. + K.o. + + + + « + » + + + + + . + . + . + . + + + lehengo + bigarren + hirugarren + laugarren + bosgarren + seigarren + zazpigarren + zortzigarren + bederatzigarren + hamargarren + + + antropologia + astronomia + biologia + botanika + kimika + ingenieritza + oinarri orokorra + geografia + geologia + historia + giza-gaiak + hizkuntzalaritza + literatura + matematika + medikuntza + filosofia + fiska + psicologia + soziologia + zientziak + politika zientziak + gizarte zientziak + teologia + zoologia + + + + liburua + liburuak + + + kapitulua + kapituluak + + + zutabea + zutabeak + + + irudia + irudiak + + + orria + orriak + + + zenbakia + zenbakiak + + + lerroa + lerroak + + + oharra + oharrak + + + obra + obrak + + + orrialdea + orrialdeak + + + paragrafoa + paragrafoak + + + zatia + zatiak + + + atala + atalak + + + sub voce + sub vocem + + + bertsoa + bertsoak + + + luburikia + luburukiak + + + + lib. + kap. + zut. + iru. + or. + zenb. + op. + + or. + or. + + par. + zt. + atal. + + s.v. + s.v. + + + b. + bb. + + + libk. + libk. + + + + + + ¶¶ + + + § + § + + + + + + + + + argitaratzailea + argitaratzaileak + + + argitaratzailea + argitaratzaileak + + + itzultzailea + itzultzaileak + + + argitaratzaile eta itzultzailea + argitaratzaile eta itzultzaileak + + + + + + + + + arg. + arg. + + + arg. + arg. + + + itzul. + itzul. + + + arg. eta itzul. + arg. eta itzul. + + + + -(e)k argitaratua + -(e)k argitaratua + -(e)k itzulia + -(e)k argitaratu eta itzulia + -(r)entzat + -(e)k elkarrizketatua + + + + arg. + arg. + itzul. + -(e)k arg. eta itzul. + + + urtarrilak + otsailak + martxoak + apirilak + maiatzak + ekainak + uztailak + abuztuak + irailak + urriak + azaroak + abenduak + + + urt. + ots. + martx. + apr. + mai. + eka. + uzt. + abz. + ira. + urr. + aza. + abe. + + + udaberria + uda + udazkena + negua + + \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-fa-IR.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-fa-IR.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + دسترسی + و + و دیگران + ناشناس + ناشناس + در + توسط + circa + c. + یادکرد + + ویرایش + ویرایش‌های + + ویرایش + و دیگران + forthcoming + از + همان + در + زیر چاپ + اینترنت + مصاحبه + نامه + بدون تاریخ + بدون تاریخ + برخط + ارائه شده در + + مرجع + مراجع + + + مرجع + مراجع + + retrieved + + + AD + BC + + + + + + + + + st + nd + rd + th + + + اول + دوم + سوم + چهارم + پنجم + ششم + هفتم + هشتم + نهم + دهم + + + مردمشناسی + ستاره‌شناسی + زیستشناسی + گیاه‌شناسی + شیمی + مهندسی + کلیات + جغرافیا + زمینشناسی + تاریخ + علوم انسانی + زبان‌شناسی + ادبیات + ریاضیات + پزشکی + فلسفه + فیزیک + روانشناسی + جامعه‌شناسی + علوم + علوم سیاسی + علوم اجتماعی + الهیات + جانورشناسی + + + + کتاب + کتاب‌های + + + فصل + فصل‌های + + + ستون + ستون‌های + + + تصویر + تصاویر + + + برگ + برگ‌های + + + شماره + شماره‌های + + + خط + خطوط + + + یادداشت + یادداشت‌های + + + قطعه + قطعات + + + صفحه + صفحات + + + پاراگراف + پاراگراف‌های + + + بخش + بخش‌های + + + قسمت + قسمت‌های + + + sub verbo + sub verbis + + + بیت + بیت‌های + + + جلد + جلدهای + + + + کتاب + فصل + ستون + تصویر + برگ + ش + قطعه + + ص + صص + + پاراگراف + بخش + قسمت + + s.v + s.vv + + + بیت + ابیات + + + ج + جج + + + + + + ¶¶ + + + § + §§ + + + + + + + + + ویرایشگر + ویرایشگران + + + ویرایشگر + ویرایشگران + + + مترجم + مترجمین + + + ویرایشگر و مترجم + ویرایشگران و مترجمین + + + + + + + + + ویرایشگر + ویرایشگران + + + ویرایشگر + ویرایشگران + + + مترجم + مترجمین + + + ویرایشگر و مترجم + ویرایشگران و مترجمین + + + + edited by + ویراسته‌ی + ترجمه‌ی + ترجمه و ویراسته‌ی + به + مصاحبه توسط + + + توسط + ویراسته‌ی + ویراسته‌ی + ترجمه‌ی + ترجمه و ویراسته‌ی + + + ژانویه + فوریه + مارس + آوریل + می + ژوئن + جولای + آگوست + سپتامبر + اکتبر + نوامبر + دسامبر + + + ژانویه + فوریه + مارس + آوریل + می + ژوئن + جولای + آگوست + سپتامبر + اکتبر + نوامبر + دسامبر + + + بهار + تابستان + پاییز + زمستان + + \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-fi-FI.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-fi-FI.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + viitattu + ja + ym. + tuntematon + tuntematon + osoitteessa + tekijä + noin + n. + viitattu + + painos + painokset + + p. + ym. + tulossa + alkaen + mt. + teoksessa + painossa + internet + haastattelu + kirje + ei päivämäärää + n.d. + verkossa + esitetty tilaisuudessa + + viittaus + viittaukset + + + viit.. + viit. + + noudettu + + + eaa. + jaa. + + + + + + + + + . + . + . + . + + + ensimmäinen + toinen + kolmas + neljäs + viides + kuudes + seitsemäs + kahdeksas + yhdeksäs + kymmenes + + + antropologia + tähtitiede + biologia + kasvitiede + kemia + tekniikka + yleinen + maantiede + geologia + historia + humanistiset tieteet + kielitiede + kirjallisuus + matematiikka + lääketiede + filosofia + fysiikka + psykologia + sosiologia + luonnontieteet + politiikan tutkimus + yhteiskuntatieteet + teologia + eläintiede + + + + kirja + kirjat + + + luku + luvut + + + palsta + palstat + + + kuvio + kuviot + + + folio + foliot + + + numero + numerot + + + rivi + rivit + + + muistiinpano + muistiinpanot + + + opus + opukset + + + sivu + sivut + + + kappale + kappaleet + + + osa + osat + + + osa + osat + + + sub verbo + sub verbis + + + säkeistö + säkeistöt + + + vuosikerta + vuosikerrat + + + + kirja + luku + palsta + kuv. + fol. + nro + op. + + s. + ss. + + kappale + osa + osa + + s.v. + s.vv. + + + säk. + säk. + + + vol. + vol. + + + + + + ¶¶ + + + § + §§ + + + + + + + + + toimittaja + toimittajat + + + toimittaja + toimittajat + + + suomentaja + suomentajat + + + toimittaja ja suomentaja + toimittajat ja suomentajat + + + + + + + + + toim. + toim. + + + toim. + toim. + + + suom. + suom. + + + toim. ja suom. + toim. ja suom. + + + + toimittanut + toimittanut + suomentanut + toimittanut ja suomentanut + vastaanottaja + haastatellut + + + + toim. + toim. + suom. + toim. ja suom. + + + tammikuu + helmikuu + maaliskuu + huhtikuu + toukokuu + kesäkuu + heinäkuu + elokuu + syyskuu + lokakuu + marraskuu + joulukuu + + + tammi + helmi + maalis + huhti + touko + kesä + heinä + elo + syys + loka + marras + joulu + + + kevät + kesä + syksy + talvi + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-fr-FR.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-fr-FR.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,306 @@ + + + + + + + + + + + + + + + consulté + et + et autres + anonyme + anon. + à + par + vers + v. + cité + + édition + éditions + + éd. + et al. + à paraître + de + ibid. + dans + sous presse + Internet + entretien + lettre + sans date + s. d. + en ligne + présenté à + + référence + références + + + réf. + réf. + + consulté + + + apr. J.-C. + av. J.-C. + + + «  +  » + + + + + ᵉʳ + + + + + + premier + deuxième + troisième + quatrième + cinquième + sixième + septième + huitième + neuvième + dixième + + + anthropologie + astronomie + biologie + botanique + chimie + ingénierie + base générique + géographie + géologie + histoire + lettres et sciences humaines + linguistique + littérature + mathématiques + médecine + philosophie + physique + psychologie + sociologie + sciences de la nature + science politique + sciences sociales + théologie + zoologie + + + + livre + livres + + + chapitre + chapitres + + + colonne + colonnes + + + figure + figures + + + folio + folios + + + numéro + numéros + + + ligne + lignes + + + note + notes + + + opus + opus + + + page + pages + + + paragraphe + paragraphes + + + partie + parties + + + section + sections + + + sub verbo + sub verbis + + + verset + versets + + + volume + volumes + + + + liv. + chap. + col. + fig. + fᵒ + nᵒ + l. + n. + op. + + p. + p. + + paragr. + part. + sect. + + s. v. + s. vv. + + + v. + v. + + + vol. + vol. + + + + + § + § + + + § + § + + + + + + + + + éditeur + éditeurs + + + directeur + directeurs + + + traducteur + traducteurs + + + éditeur et traducteur + éditeurs et traducteurs + + + + + + + + + éd. + éd. + + + dir. + dir. + + + trad. + trad. + + + éd. et trad. + éd. et trad. + + + + édité par + sous la direction de + traduit par + édité et traduit par + à + entretien réalisé par + + + par + éd. par + ss la dir. de + trad. par + éd. et trad. par + + + janvier + février + mars + avril + mai + juin + juillet + août + septembre + octobre + novembre + décembre + + + janv. + févr. + mars + avr. + mai + juin + juill. + août + sept. + oct. + nov. + déc. + + + printemps + été + automne + hiver + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-he-IL.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-he-IL.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + גישה + ו + and others + anonymous + anon + + by + circa + c. + cited + + edition + editions + + ed + ואחרים + forthcoming + מתוך + שם + בתוך + in press + internet + interview + letter + no date + nd + online + presented at the + + reference + references + + + ref. + refs. + + אוחזר + + + AD + BC + + + + + + + + + st + nd + rd + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + linguistics + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + + + ספר + ספרים + + + פרק + פרקים + + + טור + טורים + + + figure + figures + + + folio + folios + + + מספר + מספרים + + + שורה + שורות + + + note + notes + + + אופוס + אופרה + + + עמוד + עמודים + + + paragraph + פיסקה + + + part + parts + + + section + sections + + + sub verbo + sub verbis + + + בית + בתים + + + כרך + כרכים + + + + bk + chap + col + fig + f + no + op + + 'עמ + 'עמ + + para + pt + sec + + s.v. + s.vv. + + + v + vv + + + vol + vols + + + + + + ¶¶ + + + § + §§ + + + + + + + + + עורך + עורכים + + + editor + editors + + + מתרגם + מתרגמים + + + editor & translator + editors & translators + + + + + + + + + ed + eds + + + ed. + eds. + + + tran + trans + + + ed. & tran. + eds. & trans. + + + + נערך ע"י + edited by + תורגם ע"י + edited & translated by + to + interview by + + + by + ed + ed. + trans + ed. & trans. by + + + ינואר + פברואר + מרץ + אפריל + מאי + יוני + יולי + אוגוסט + ספטמבר + אוקטובר + נובמבר + דצמבר + + + Jan + Feb + Mar + Apr + May + Jun + Jul + Aug + Sep + Oct + Nov + Dec + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-hu-HU.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-hu-HU.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + elérés + és + és mások + név nélkül + nn + + by + circa + c. + idézi + + edition + editions + + ed + et al. + megjelenés alatt + forrás + ibid. + in + nyomtatás alatt + internet + interjú + levél + no date + nd + online + előadás + + reference + references + + + ref. + refs. + + elérés + + + AD + BC + + + + + + » + « + + + st + nd + rd + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + antropológia + csillagászat + biológia + botanika + kémia + mérnöki tudományok + általános + földrajz + geológia + történelem + bölcsésztudományok + linguistics + irodalom + matematika + orvostudomány + filozófia + fizika + pszichológia + szociológia + tudomány + politikatudomány + társadalomtudomány + teológia + zoológia + + + + könyv + könyv + + + fejezet + fejezet + + + oszlop + oszlop + + + ábra + ábra + + + fóliáns + fóliáns + + + szám + szám + + + sor + sor + + + jegyzet + jegyzet + + + opus + opera + + + oldal + oldal + + + bekezdés + bekezdés + + + rész + rész + + + szakasz + szakasz + + + sub verbo + sub verbis + + + versszak + versszak + + + kötet + kötet + + + + könyv + fej + oszl + ábr + fol + sz + op + + o + o + + bek + rész + szak + + s.v. + s.vv. + + + vsz + vsz + + + vol + vols + + + + + + ¶¶ + + + § + §§ + + + + + + + + + szerkesztő + szerkesztő + + + editor + editors + + + fordító + fordító + + + editor & translator + editors & translators + + + + + + + + + szerk + szerk + + + ed. + eds. + + + ford + ford + + + ed. & tran. + eds. & trans. + + + + szerkesztette + edited by + fordította + edited & translated by + címzett + interjúkészítő + + + by + szerk + ed. + ford + ed. & trans. by + + + január + február + március + április + május + június + július + augusztus + szeptember + október + november + december + + + jan + febr + márc + ápr + máj + jún + júl + aug + szept + okt + nov + dec + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-is-IS.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-is-IS.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + sótt + og + og fleiri + nafnlaus + nafnl. + af + eftir + sirka + u.þ.b. + tilvitnun + + útgáfa + útgáfur + + útg. + o.fl. + óbirt + af + sama heimild + í + í prentun + rafrænt + viðtal + bréf + engin dagsetning + e.d. + rafrænt + flutt á + + tilvitnun + tilvitnanir + + + tilv. + tilv. + + sótt + + + e.Kr. + f.Kr. + + + + + + + + + . + . + . + . + + + fyrsti + annar + þriðji + fjórði + fimmti + sjötti + sjöundi + áttundi + níundi + tíundi + + + mannfræði + stjörnufræði + líffræði + grasafræði + efnafræði + verkfræði + almennt efni + landafræði + jarðfræði + saga + hugvísindi + málvísindi + bókmenntir + stærðfræði + læknisfræði + heimspeki + eðlisfræði + sálfræði + félagsfræði + vísindi + stjórnmálafræði + félagsvísindi + guðfræði + dýrafræði + + + + bók + bækur + + + kafli + kaflar + + + dálkur + dálkar + + + mynd + myndir + + + handrit + handrit + + + númer + númer + + + lína + línur + + + skilaboð + skilaboð + + + tónverk + tónverk + + + blaðsíða + blaðsíður + + + málsgrein + málsgreinar + + + hluti + hlutar + + + hluti + hlutar + + + sub verbo + sub verbis + + + vers + vers + + + bindi + bindi + + + + b. + k. + d. + mynd. + handr. + nr. + tónv. + + bls. + bls. + + málsgr. + hl. + hl. + + s.v. + s.vv. + + + v. + v. + + + bindi + bindi + + + + + + ¶¶ + + + § + §§ + + + + + höfundur + höfundar + + + ritstjóri + ritstjórar + + + ritstjóri + ritstjórar + + + þýðandi + þýðendur + + + ritstjóri og þýðandi + ritstjórar og þýðendur + + + + + höf. + höf. + + + ritstj. + ritstj. + + + ritstj. + ritstj. + + + þýð. + þýð. + + + ritstj. og þýð. + ritstj. og þýð. + + + + ritstjóri + ritstjóri + þýddi + ritstjóri og þýðandi + til + viðtal tók + + + eftir + ritst. + ritst. + þýð. + ritst. og þýð. + + + janúar + febrúar + mars + apríl + maí + júní + júlí + ágúst + september + október + nóvember + desember + + + jan. + feb. + mar. + apr. + maí + jún. + júl. + ágú. + sep. + okt. + nóv. + des. + + + vor + sumar + haust + vetur + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-it-IT.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-it-IT.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + consultato + e + e altri + anonimo + anon + a + by + circa + c. + citato + + edizione + edizioni + + ed + et al. + futuro + da + ibid. + in + in stampa + internet + intervista + lettera + no date + S.d. + in linea + presentato al + + reference + references + + + ref. + refs. + + recuperato + + + AD + BC + + + + « + » + + + + + st + nd + rd + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + antropologia + astronomia + biologia + botanica + chimica + ingegneria + generica + geografia + geologia + storia + discipline umanistiche + linguistics + letteratura + matematica + medicina + filosofia + fisica + psicologia + sociologia + scienze + scienze politiche + sociologia + teologia + zoologia + + + + libro + libri + + + capitolo + capitoli + + + colonna + colonne + + + figura + figure + + + foglio + fogli + + + numero + numeri + + + riga + righe + + + nota + note + + + opera + opere + + + pagina + pagine + + + capoverso + capoversi + + + parte + parti + + + paragrafo + paragrafi + + + sub verbo + sub verbis + + + verso + versi + + + volume + volumi + + + + lib + cap + col + fig + fgl + + op + + pag + pagg + + cpv + pt + par + + s.v. + s.vv. + + + v + vv + + + vol + vol + + + + + + ¶¶ + + + § + §§ + + + + + + + + + curatore + curatori + + + editor + editors + + + traduttore + traduttori + + + editor & translator + editors & translators + + + + + + + + + cur + cur + + + ed. + eds. + + + trad + trad + + + ed. & tran. + eds. & trans. + + + + a cura di + edited by + tradotto da + edited & translated by + a + intervista di + + + by + cur. da + ed. + trad. da + ed. & trans. by + + + Gennaio + Febbraio + Marzo + Aprile + Maggio + Giugno + Luglio + Agosto + Settembre + Ottobre + Novembre + Dicembre + + + Gen + Feb + Mar + Apr + Mag + Giu + Lug + Ago + Set + Ott + Nov + Dic + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-ja-JP.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-ja-JP.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + アクセス + + and others + anonymous + anon + at + by + circa + c. + cited + + edition + editions + + ed + + 近刊 + から + 前掲 + + in press + internet + interview + letter + no date + 日付なし + online + presented at the + + reference + references + + + ref. + refs. + + 読み込み + + + AD + BC + + + + + + + + + + st + nd + rd + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + linguistics + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + + + + + note + notes + + + opus + opera + + + ページ + ページ + + + 段落 + 段落 + + + part + parts + + + section + sections + + + sub verbo + sub verbis + + + verse + verses + + + volume + volumes + + + + bk + chap + col + fig + f + + op + + p + p + + para + pt + sec + + s.v. + s.vv. + + + v + vv + + + vol + vols + + + + + + ¶¶ + + + § + §§ + + + + + + + + + 編集者 + 編集者 + + + editor + editors + + + 翻訳者 + 翻訳者 + + + editor & translator + editors & translators + + + + + + + + + 編集者 + 編集者 + + + ed. + eds. + + + 翻訳者 + 翻訳者 + + + ed. & tran. + eds. & trans. + + + + 編集者: + edited by + 翻訳者: + edited & translated by + to + interview by + + + by + ed + ed. + trans + ed. & trans. by + + + 1月 + 2月 + 3月 + 4月 + 5月 + 6月 + 7月 + 8月 + 9月 + 10月 + 11月 + 12月 + + + 1月 + 2月 + 3月 + 4月 + 5月 + 6月 + 7月 + 8月 + 9月 + 10月 + 11月 + 12月 + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-km-KH.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-km-KH.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + accessed + and + and others + anonymous + anon. + at + by + circa + c. + cited + + edition + editions + + ed. + et al. + forthcoming + from + ibid + in + in press + internet + interview + letter + no date + n.d. + online + presented at the + + reference + references + + + ref. + refs. + + retrieved + + + AD + BC + + + + + + + + + st + nd + rd + th + + + ទីមួយ + ទីពីរ + ទីបី + ទីបួន + ទីប្រាំ + ទីប្រាំមួយ + ទីប្រាំពីរ + ទីប្រាំបី + ទីប្រាំបួន + ទីដប់មួយ + + + នរវិទ្យា + តារាវិទ្យា + ជីវវិទ្យា + រុក្ខវិទ្យា + គីមីវិទ្យា + វិស្វកម្ម + generic base + ភូមិវិទ្យា + ភូគព្ភវិទ្យា + ប្រវត្តិវិទ្យា + មនុស្សវិទ្យា + ភាសាវិទ្យា + អក្សរសាស្ត្រ + គណិតវិទ្យា + វេជ្ជសាស្ត្រ + ទស្សនវិទ្យា + រូបវិទ្យា + ចិត្តវិទ្យា + សង្គមវិទ្យា + វិទ្យាសាស្ត្រ + វិទ្យាសាស្ត្រនយោបាយ + សង្គមវិទ្យា + ទេវវិទ្យា + សត្តវិទ្យា + + + + សៀវភៅ + សៀវភៅ + + + ជំពូក + ជំពូក + + + កាឡោន + កាឡោន + + + តួលេខ + តួលេខ + + + folio + folios + + + ចំនួន + ចំនួន + + + បន្ទាត់ + បន្ទាត់ + + + កំណត់ចំណាំ + កំណត់ចំណាំ + + + opus + opera + + + ទំព័រ + ទំព័រ + + + កថាខណ្ឌ + កថាខណ្ឌ + + + ជំពូក + ជំពូក + + + ផ្នែក + ផ្នែក + + + sub verbo + sub verbis + + + verse + verses + + + វ៉ុល + វ៉ុល + + + + bk. + chap. + col. + fig. + f. + no. + op. + + p. + pp. + + para. + pt. + sec. + + s.v. + s.vv. + + + v. + vv. + + + vol. + vols. + + + + + + ¶¶ + + + § + §§ + + + + + + + + + editor + editors + + + + editors + + + translator + translator + + + editor & translator + editors & translators + + + + + + + + + ed. + eds. + + + ed. + eds. + + + tran. + trans. + + + ed. & tran. + eds. & trans. + + + + edited by + edited by + translated by + edited & translated by + to + interview by + + + by + ed. + ed. + trans. + ed. & trans. by + + + មករា + កុម្ភៈ + មីនា + មេសា + ឧសភា + មិថុនា + កក្កដា + សីហា + កញ្ញា + តុលា + វិច្ឆិកា + ធ្នូ + + + Jan. + Feb. + Mar. + Apr. + May + Jun. + Jul. + Aug. + Sep. + Oct. + Nov. + Dec. + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-ko-KR.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-ko-KR.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + 접근된 + 와/과 + and others + anonymous + anon + at + by + circa + c. + cited + + edition + editions + + ed + 기타 + 근간 + (으)로부터 + ibid. + in + in press + internet + interview + letter + no date + 일자 없음 + online + presented at the + + reference + references + + + ref. + refs. + + retrieved + + + AD + BC + + + + + + + + + + st + nd + rd + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + linguistics + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + + + + + note + notes + + + opus + opera + + + 페이지 + 페이지 + + + 단락 + 단락 + + + part + parts + + + section + sections + + + sub verbo + sub verbis + + + verse + verses + + + volume + volumes + + + + bk + chap + col + fig + f + + op + + p + pp + + para + pt + sec + + s.v. + s.vv. + + + v + vv + + + vol + vols + + + + + + ¶¶ + + + § + §§ + + + + + + + + + 편집자 + 편집자 + + + editor + editors + + + 번역자 + 번역자 + + + editor & translator + editors & translators + + + + + + + + + 편집자 + 편집자 + + + ed. + eds. + + + 번역자 + 번역자 + + + ed. & tran. + eds. & trans. + + + + 편집자: + edited by + 번역자: + edited & translated by + to + interview by + + + by + ed + ed. + trans + ed. & trans. by + + + 1월 + 2월 + 3월 + 4월 + 5월 + 6월 + 7월 + 8월 + 9월 + 10월 + 11월 + 12월 + + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-mn-MN.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-mn-MN.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,306 @@ + + + + + + + + + + + + + + + accessed + and + and others + anonymous + anon + at + by + circa + c. + cited + + edition + editions + + ed + et al. + forthcoming + from + ibid. + in + in press + internet + interview + letter + no date + n.d. + online + presented at the + + reference + references + + + ref. + refs. + + retrieved + + + AD + BC + + + + + « + » + + + + + st + nd + rd + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + linguistics + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + line + lines + + + note + notes + + + opus + opera + + + page + pages + + + paragraph + paragraph + + + part + parts + + + section + sections + + + sub verbo + sub verbis + + + verse + verses + + + volume + volumes + + + + bk + chap + col + fig + f + no + op + + p + pp + + para + pt + sec + + s.v. + s.vv. + + + v + vv + + + vol + vols + + + + + + ¶¶ + + + § + §§ + + + + + + + + + editor + editors + + + editor + editors + + + translator + translators + + + editor & translator + editors & translators + + + + + + + + + ed + eds + + + ed. + eds. + + + tran + trans + + + ed. & tran. + eds. & trans. + + + + edited by + edited by + translated by + edited & translated by + to + interview by + + + by + ed + ed. + trans + ed. & trans. by + + + January + February + March + April + May + June + July + August + September + October + November + December + + + Jan + Feb + Mar + Apr + May + Jun + Jul + Aug + Sep + Oct + Nov + Dec + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-nb-NO.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-nb-NO.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + åpnet + og + med flere + anonym + anon. + + av + circa + ca. + sitert + + utgave + utgaver + + utg. + mfl. + kommende + fra + ibid. + i + i trykk + Internett + intervju + brev + ingen dato + udatert + online + presentert på + + referanse + referanser + + + ref. + refr. + + hentet + + + f.Kr + e.Kr + + + « + » + + + + + . + . + . + . + + + første + andre + tredje + fjerde + femte + sjette + sjuende + åttende + niende + tiende + + + antropologi + astronomi + biologi + botanikk + kjemi + ingeniørvitenskap + generell + geografi + geologi + historie + humanistiske fag + lingvistikk + litteratur + mattematikk + medisin + filosofi + fysikk + fysiologi + sosiologi + naturvitenskap + statsvitenskap + samfunnsvitenskap + teologi + zoologi + + + + bok + bøker + + + kapittel + kapitler + + + kolonne + kolonner + + + figur + figurer + + + folio + folioer + + + nummer + numre + + + linje + linjer + + + note + noter + + + opus + opus + + + side + sider + + + avsnitt + avsnitt + + + del + deler + + + paragraf + paragrafer + + + sub verbo + sub verbis + + + vers + vers + + + bind + bind + + + + b. + kap. + kol. + fig. + fol. + nr. + op. + + s. + s. + + avsn. + d. + pargr. + + s.v. + s.vv. + + + v. + v. + + + bd. + bd. + + + + + + ¶¶ + + + § + §§ + + + + + + + + + redaktør + redaktører + + + redaktør + redaktører + + + oversetter + oversettere + + + redaktør & oversetter + redaktører & oversettere + + + + + + + + + red. + red. + + + red. + red. + + + overs. + overs. + + + red. & overs. + red. & overs. + + + + redigert av + redigert av + oversatt av + redigert & oversatt av + mottatt av + intervjuet av + + + av + red. + red. + overs. + red. & overs. av + + + januar + februar + mars + april + mai + juni + juli + august + september + oktober + november + desember + + + jan. + feb. + mar. + apr. + mai + jun. + jul. + aug. + sep. + okt. + nov. + des. + + + vår + sommer + høst + vinter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-nl-NL.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-nl-NL.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + bezocht + en + en anderen + anoniem + anon. + bij + door + circa + c. + geciteerd + + editie + edities + + ed. + e.a. + in voorbereiding + van + ibid. + in + in druk + internet + interview + brief + zonder datum + z.d. + online + gepresenteerd bij + + referentie + referenties + + + ref. + refs. + + verkregen + + + AD + BC + + + + + + + + + e + e + e + e + + + eerste + tweede + derde + vierde + vijfde + zesde + zevende + achtste + negende + tiende + + + anthropologie + astronomie + biologie + botanie + scheikunde + techniek + generiek + geografie + geologie + geschiedenis + geesteswetenschappen + taalkunde + literatuur + wiskunde + medicijnen + filosofie + natuurkunde + psychologie + sociologie + wetenschap + politieke wetenschappen + sociale wetenschappen + theologie + zoologie + + + + boek + boeken + + + hoofdstuk + hoofdstukken + + + column + columns + + + figuur + figuren + + + folio + folio's + + + nummer + nummers + + + regel + regels + + + aantekening + aantekeningen + + + opus + opera + + + pagina + pagina's + + + paragraaf + paragrafen + + + deel + delen + + + sectie + secties + + + sub verbo + sub verbis + + + vers + versen + + + volume + volumes + + + + bk. + hfdst. + col. + fig. + f. + nr. + op. + + p. + pp. + + par. + deel + sec. + + s.v. + s.vv. + + + v. + vv. + + + vol. + vols. + + + + + + ¶¶ + + + § + §§ + + + + + + + + + redacteur + redacteuren + + + redacteur + redacteuren + + + vertaler + vertalers + + + redacteur & vertaler + redacteuren & vertalers + + + + + + + + + red. + red. + + + red. + red. + + + vert. + vert. + + + red. & vert. + red. & vert. + + + + bewerkt door + bewerkt door + vertaald door + bewerkt & vertaald door + ontvangen door + geïnterviewd door + + + door + bewerkt door + bewerkt door + vertaald door + bewerkt & vertaald door + + + januari + februari + maart + april + mei + juni + juli + augustus + september + oktober + november + december + + + jan. + feb. + mrt. + apr. + mei + jun. + jul. + aug. + sep. + okt. + nov. + dec. + + + lente + zomer + herst + winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-nn-NO.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-nn-NO.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + vitja + og + med fleire + anonym + anon. + + av + circa + ca. + sitert + + utgåve + utgåver + + utg. + mfl. + kommande + frå + ibid. + i + i trykk + Internett + intervju + brev + ingen dato + udatert + online + presentert på + + referanse + referansar + + + ref. + refr. + + henta + + + f.Kr + e.Kr + + + « + » + + + + + . + . + . + . + + + første + andre + tredje + fjerde + femte + sjette + sjuande + åttande + niande + tiande + + + antropologi + astronomi + biologi + botanikk + kjemi + ingeniørvitskap + generell + geografi + geologi + historie + humanistiske fag + lingvistikk + litteratur + mattematikk + medisin + filosofi + fysikk + fysiologi + sosiologi + naturvitskap + statsvitskap + samfunnsvitskap + teologi + zoologi + + + + bok + bøker + + + kapittel + kapittel + + + kolonne + kolonner + + + figur + figurar + + + folio + folioar + + + nummer + nummer + + + linje + linjer + + + note + notar + + + opus + opus + + + side + sider + + + avsnitt + avsnitt + + + del + deler + + + paragraf + paragrafar + + + sub verbo + sub verbis + + + vers + vers + + + bind + bind + + + + b. + kap. + kol. + fig. + fol. + nr. + op. + + s. + s. + + avsn. + d. + par. + + s.v. + s.vv. + + + v. + v. + + + bd. + bd. + + + + + + ¶¶ + + + § + §§ + + + + + + + + + redaktør + redaktørar + + + redaktør + redaktørar + + + omsetjar + omsetjarar + + + redaktør & omsetjar + redaktørar & omsetjarar + + + + + + + + + red. + red. + + + red. + red. + + + oms. + oms. + + + red. & oms. + red. & oms. + + + + redigert av + redigert av + omsett av + redigert & omsett av + motteke av + intervjua av + + + av + red. + red. + oms. + red. & oms. av + + + januar + februar + mars + april + mai + juni + juli + august + september + oktober + november + desember + + + jan. + feb. + mar. + apr. + mai + jun. + jul. + aug. + sep. + okt. + nov. + des. + + + vår + sommar + haust + vinter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-pl-PL.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-pl-PL.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + udostępniono + i + i inni + anonim + anon. + na + przez + circa + ca + cytowane + + wydanie + wydania + + wyd. + et al. + w przygotowaniu + z + ibid. + w + w druku + internet + wywiad + list + brak daty + b.d. + online + zaprezentowano na + + referencja + referencje + + + ref. + ref. + + pobrano + + + n.e. + p.n.e. + + + + + + « + » + + + . + . + . + . + + + pierwszy + drugi + trzeci + czwarty + piąty + szósty + siódmy + ósmy + dziewiąty + dziesiąty + + + antropologia + astronomia + biologia + botanika + chemia + inżynieria + ogólny + geografia + geologia + historia + humanistyka + lingwistyka + literatura + matematyka + medycyna + filozofia + fizyka + psychologia + socjologia + nauki ścisłe + nauki polityczne + nauki społeczne + teologia + zoologia + + + + książka + książki + + + rozdział + rozdziały + + + kolumna + kolumny + + + rycina + ryciny + + + folio + folio + + + numer + numery + + + wers + wersy + + + notatka + notatki + + + opus + opera + + + strona + strony + + + akapit + akapity + + + część + części + + + sekcja + sekcje + + + sub verbo + sub verbis + + + wers + wersy + + + tom + tomy + + + + książka + rozdz. + kol. + ryc. + fol. + nr + op. + + s. + ss. + + akap. + cz. + sekc. + + s.v. + s.vv. + + + w. + w. + + + t. + t. + + + + + + ¶¶ + + + § + §§ + + + + + + + + + redaktor + redaktorzy + + + edytor + edytorzy + + + tłumacz + tłumacze + + + redaktor & tłumacz + redaktorzy & tłumacze + + + + + + + + + red. + red. + + + red. + red. + + + tłum. + tłum. + + + red. & tłum. + red. & tłum. + + + + zredagowane przez + zredagowane przez + przetłumaczone przez + zredagowane & przetłumaczone przez + dla + przeprowadzony przez + + + przez + red. + red. + tłum. + red. & tłum. + + + styczeń + luty + marzec + kwiecień + maj + czerwiec + lipiec + sierpień + wrzesień + październik + listopad + grudzień + + + sty. + luty + mar. + kwi. + maj + cze. + lip. + sie. + wrz. + paź. + lis. + grudz. + + + wiosna + lato + jesień + zima + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-pt-BR.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-pt-BR.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + acessado + e + e outros + anônimo + anon + em + por + circa + c. + citado + + edição + edições + + ed + et al. + a ser publicado + de + ibidem + in + no prelo + internet + entrevista + carta + sem data + [s.d.] + online + apresentado em + + referência + referências + + + ref. + refs. + + recuperado + + + AD + BC + + + + + + + + + º + º + º + º + + + primeiro + segundo + terceiro + quarto + quinto + sexto + sétimo + oitavo + nono + décimo + + + antropologia + astronomia + biologia + botânica + química + engenharia + base genérica + geografia + geologia + história + humanidades + linguistics + literatura + matemática + medicina + philosofia + física + psicologia + sociologia + ciências + ciências políticas + ciências sociais + teologia + zoologia + + + + livro + livros + + + capítulo + capítulos + + + coluna + colunas + + + figura + figuras + + + folio + folios + + + número + números + + + linha + linhas + + + nota + notas + + + opus + opera + + + página + páginas + + + parágrafo + parágrafos + + + parte + partes + + + seção + seções + + + sub verbo + sub verbis + + + verso + versos + + + volume + volumes + + + + liv. + cap. + col. + fig. + f. + + op. + + p. + p. + + parag. + pt. + seç. + + s.v. + s.vv. + + + v. + vv. + + + vol. + vols. + + + + + + ¶¶ + + + § + §§ + + + + + + + + + organizador + organizadores + + + editor + editors + + + tradutor + tradutores + + + editor e tradutor + editores e tradutores + + + + + + + + + org. + orgs. + + + ed. + eds. + + + trad. + trads. + + + ed. e trad. + eds. e trads. + + + + organizado por + editado por + traduzido por + editado & traduzido por + para + entrevista de + + + por + org. + ed. + trad. + ed. e trad. por + + + janeiro + fevereiro + março + abril + maio + junho + julho + agosto + setembro + outubro + novembro + dezembro + + + jan. + fev. + mar. + abr. + maio + jun. + jul. + ago. + set. + out. + nov. + dez. + + + Primavera + Verão + Outono + Inverno + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-pt-PT.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-pt-PT.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + acedido + e + e outros + anónimo + anón + em + by + circa + c. + citado + + edição + edições + + ed + et al. + a publicar + de + ibid. + em + no prelo + internet + entrevista + carta + no date + sem data + em linha + apresentado na + + reference + references + + + ref. + refs. + + obtido + + + AD + BC + + + + « + » + + + + + st + nd + rd + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + antropologia + astronomia + biologia + botânica + química + engenharia + base genérica + geografia + geologia + história + humanidades + linguistics + literatura + matemática + medicina + filosofia + física + psicologia + sociologia + ciência + ciência política + ciência social + teologia + zoologia + + + + livro + livros + + + capítulo + capítulos + + + coluna + colunas + + + figura + figuras + + + fólio + fólios + + + número + número + + + linha + linhas + + + nota + notas + + + opus + opera + + + página + páginas + + + parágrafo + parágrafos + + + parte + partes + + + secção + secções + + + sub verbo + sub verbis + + + versículo + versículos + + + volume + volumes + + + + liv + cap + col + fig + f + n + op + + p + pp + + par + pt + sec + + s.v. + s.vv. + + + v + vv + + + vol + vols + + + + + + ¶¶ + + + § + §§ + + + + + + + + + editor + editores + + + editor + editors + + + tradutor + tradutores + + + editor & translator + editors & translators + + + + + + + + + ed + eds + + + ed. + eds. + + + trad + trads + + + ed. & tran. + eds. & trans. + + + + editado por + edited by + traduzido por + edited & translated by + para + entrevistado por + + + by + ed + ed. + trad + ed. & trans. by + + + Janeiro + Fevereiro + Março + Abril + Maio + Junho + Julho + Agosto + Setembro + Outubro + Novembro + Dezembro + + + Jan + Fev + Mar + Abr + Mai + Jun + Jul + Ago + Set + Out + Nov + Dez + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-ro-RO.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-ro-RO.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + data accesării: + și + și alții + anonim + anon. + la + de + circa + cca. + citat + + ediția + edițiile + + ed + et al. + în curs de apariție + din + ibidem + în + sub tipar + internet + interviu + scrisoare + fără dată + f.a. + online + prezentat la + + referință + referințe + + + ref. + ref. + + preluat în + + + d.Hr. + î.Hr. + + + + + + « + » + + + + -lea + -lea + -lea + + + primul + al doilea + al treilea + al patrulea + al cincilea + al șaselea + al șaptelea + al optulea + al nouălea + al zecelea + + + antropologie + astronomie + biologie + botanică + chimie + inginerie + general (de bază) + geografie + geologie + istorie + științe umaniste + lingvistică + literatură + matematică + medicină + filosofie + fizică + psihologie + sociologie + știință + științe politice + științe sociale + teologie + zoologie + + + + cartea + cărțile + + + capitolul + capitolele + + + coloana + coloanele + + + figura + figurile + + + folio + folio + + + numărul + numerele + + + linia + liniile + + + nota + notele + + + opusul + opusurile + + + pagina + paginile + + + paragraful + paragrafele + + + partea + părțile + + + secțiunea + secțiunile + + + sub verbo + sub verbis + + + versetul + versetele + + + volumul + volumele + + + + cart. + cap. + col. + fig. + fol. + nr. + op. + + p. + pp. + + par. + part. + sec. + + s.v. + s.vv. + + + v. + vv. + + + vol. + vol. + + + + + + ¶¶ + + + § + §§ + + + + + autor + autori + + + editor + editori + + + editor + editori + + + traducător + traducători + + + editor & traducător + editori & traducători + + + + + aut. + aut. + + + ed. + ed. + + + ed. + ed. + + + trad. + trad. + + + ed. & trad. + ed. & trad. + + + + ediție de + ediție de + traducere de + ediție & traducere de + în + interviu de + + + de + ed. + ed. + trad. + ed. & trad. de + + + ianuarie + februarie + martie + aprilie + mai + iunie + iulie + august + septembrie + octombrie + noiembrie + decembrie + + + ian. + feb. + mar. + apr. + mai + iun. + iul. + aug. + sep. + oct. + nov. + dec. + + + primăvara + vara + toamna + iarna + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-ru-RU.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-ru-RU.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,306 @@ + + + + + + + + + + + + + + + + просмотрено + и + и др. + аноним + анон. + на + + circa + ca. + цитируется по + цит. по + + издание + издания + + изд. + и др. + ожидается + от + там же + в + в печати + Интернет + интервью + письмо + без даты + б. д. + online + представлено на + + reference + references + + + ref. + refs. + + извлечено + + + н. э. + до н. э. + + + « + » + + + + + й + й + й + й + + + первый + второй + третий + четвертый + пятый + шестой + седьмой + восьмой + девятый + десятый + + + антропология + астрономия + биология + ботаника + химия + инженерное дело + общий + география + геология + история + гуманитарные науки + лингвистика + литературоведение + математика + медицина + философия + физика + психология + социология + естественные науки + политические науки + социальные науки + теология + зоология + + + + книга + книги + + + глава + главы + + + столбец + столбцы + + + рисунок + рисунки + + + лист + листы + + + выпуск + выпуски + + + строка + строки + + + примечание + примечания + + + сочинение + сочинения + + + страница + страницы + + + параграф + параграфы + + + часть + части + + + раздел + разделы + + + смотри + смотри + + + стих + стихи + + + том + тома + + + + кн. + гл. + стб. + рис. + л. + + соч. + + с. + с. + + пара. + ч. + разд. + + см. + см. + + + ст. + ст. + + + т. + тт. + + + + + + ¶¶ + + + § + §§ + + + + + + + + + редактор + редакторы + + + ответственный редактор + ответственные редакторы + + + переводчик + переводчики + + + редактор и переводчик + редакторы и переводчики + + + + + + + + + ред. + ред. + + + отв. ред. + отв. ред. + + + перев. + перев. + + + ред. и перев. + ред. и перев. + + + + отредактировано + отредактировано + переведено + отредактировано и переведено + к + интервью + + + + ред. + отв. ред. + перев. + ред. и перев. + + + январь + февраль + март + апрель + май + июнь + июль + август + сентябрь + октябрь + ноябрь + декабрь + + + янв. + фев. + мар. + апр. + май + июн. + июл. + авг. + сен. + окт. + ноя. + дек. + + + весна + лета + осень + зима + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-sk-SK.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-sk-SK.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + cit + a + and ďalší + anonym + anon + v + by + circa + c. + cit + + vydanie + vydania + + vyd + et al + nadchádzajúci + z + ibid. + v + v tlači + internet + osobná komunikácia + list + no date + n.d. + online + prezentované na + + reference + references + + + ref. + refs. + + cit + + + AD + BC + + + + + + + + + st + nd + rd + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + antropológia + astronómia + biológia + botanika + chémia + strojárstvo/technika + všeobecný základ + geografia + geológia + história + humanitné vedy + linguistics + literatúra + matematika + medicína + filozofia + fyzika + psychológia + sociológia + veda + politické vedy + sociálne vedy + teológia + zoológia + + + + kniha + knihy + + + kapitola + kapitoly + + + stĺpec + stĺpce + + + obrázok + obrázky + + + list + listy + + + číslo + čísla + + + riadok + riadky + + + poznámka + poznámky + + + opus + opera + + + strana + strany + + + odstavec + odstavce + + + časť + časti + + + sekcia + sekcie + + + sub verbo + sub verbis + + + verš + verše + + + ročník + ročníky + + + + k + kap + stĺp + obr + l + č + op + + s + s + + par + č + sek + + s.v. + s.vv. + + + v + v + + + roč + roč + + + + + + + + + § + § + + + + + + + + + editor + editori + + + editor + editors + + + prekladateľ + prekladatelia + + + editor & translator + editors & translators + + + + + + + + + ed + ed + + + ed. + eds. + + + prek + prek + + + ed. & tran. + eds. & trans. + + + + editoval + edited by + preložil + edited & translated by + adresát + rozhovor urobil + + + by + ed + ed. + prel + ed. & trans. by + + + január + február + marec + apríl + máj + jún + júl + august + september + október + november + december + + + jan + feb + mar + apr + máj + jún + júl + aug + sep + okt + nov + dec + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-sl-SI.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-sl-SI.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + dostopano + in + in drugi + anonimni + anon + pri + by + circa + c. + citirano + + izdaja + izdaje + + iz + idr. + pred izidom + od + isto + v + v tisku + internet + intervju + pismo + no date + b.d. + na spletu + predstavljeno na + + reference + references + + + ref. + refs. + + pridobljeno + + + AD + BC + + + + + + + + + + st + nd + rd + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + antropologija + astronomija + biologija + botanika + kemija + strojništvo + splošno + geografija + geologija + zgodovina + humanistika + linguistics + literatura + matematika + medicina + filozofija + fizika + psihologija + sociologija + znanost + politologija + družbene vede + teologija + zoologija + + + + knjiga + knjige + + + poglavje + poglavja + + + stolpec + stolpci + + + slika + slike + + + folio + folii + + + številka + številke + + + vrstica + vrstice + + + opomba + opombe + + + opus + opera + + + stran + strani + + + odstavek + odstavki + + + del + deli + + + odsek + odseki + + + sub verbo + sub verbis + + + verz + verzi + + + letnik + letniki + + + + knj + pogl + sto + sl + f + št + op + + str + str + + odst + del + odsk + + s.v. + s.vv. + + + v + v + + + let + let + + + + + + ¶¶ + + + § + §§ + + + + + + + + + urednik + uredniki + + + editor + editors + + + prevajalec + prevajalci + + + editor & translator + editors & translators + + + + + + + + + ur + ur + + + ed. + eds. + + + prev + prev + + + ed. & tran. + eds. & trans. + + + + uredil + edited by + prevedel + edited & translated by + za + intervjuval + + + by + ur + ed. + prev + ed. & trans. by + + + januar + februar + marec + april + maj + junij + julij + avgust + september + oktober + november + december + + + jan + feb + mar + apr + maj + jun + jul + avg + sep + okt + nov + dec + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-sr-RS.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-sr-RS.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + приступљено + и + и остали + анонимна + анон. + на + by + circa + c. + цитирано + + издање + издања + + изд. + и остали + долазећи + од + ibid. + у + у штампи + Интернет + интервју + писмо + no date + без датума + на Интернету + представљено на + + reference + references + + + ref. + refs. + + преузето + + + AD + BC + + + + + + + + + + st + nd + rd + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + антропологија + астрономија + биологија + ботаника + хемија + инжињерство + уопштена основа + географија + геологија + историја + култура и уметност + linguistics + литература + математика + медицина + филозофија + физика + психологија + социологија + наука + политичка наука + друштвена наука + теологија + зоологија + + + + књига + књиге + + + поглавље + поглавља + + + колона + колоне + + + цртеж + цртежи + + + фолио + фолији + + + број + бројеви + + + линија + линије + + + белешка + белешке + + + опус + опера + + + страница + странице + + + параграф + параграфи + + + део + делова + + + одељак + одељака + + + sub verbo + sub verbis + + + строфа + строфе + + + том + томова + + + + књига + Пог. + кол. + црт. + фолио + изд. + оп. + + стр. + стр. + + пар. + део + од. + + s.v. + s.vv. + + + стр. + стр. + + + том + томови + + + + + + ¶¶ + + + § + §§ + + + + + + + + + уредник + урединици + + + editor + editors + + + преводилац + преводиоци + + + editor & translator + editors & translators + + + + + + + + + ур. + ур. + + + ed. + eds. + + + прев. + прев. + + + ed. & tran. + eds. & trans. + + + + уредио + edited by + превео + edited & translated by + прима + интервјуисао + + + by + ур. + ed. + прев. + ed. & trans. by + + + Јануар + Фебруар + Март + Април + Мај + Јуни + Јули + Август + Септембар + Октобар + Новембар + Децембар + + + Јан. + Феб. + Март + Апр. + Мај + Јуни + Јули + Авг. + Сеп. + Окт. + Нов. + Дец. + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-sv-SE.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-sv-SE.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + åtkomstdatum + och + och andra + anonym + anon + vid + by + circa + c. + citerad + + upplaga + upplagor + + uppl + m.fl. + kommande + från + ibid. + i + i tryck + internet + intervju + brev + no date + nd + online + presenterad vid + + reference + references + + + ref. + refs. + + hämtad + + + AD + BC + + + + + + + + + + st + nd + rd + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + antropologi + astronomi + biologi + botanik + kemi + teknik + generic base + geografi + geologi + historia + humaniora + linguistics + litteraturvetenskap + matematik + medicin + filosofi + fysik + psykologi + sociologi + vetenskap + statsvetenskap + samhällsvetenskap + teologi + zoologi + + + + bok + böcker + + + kapitel + kapitel + + + kolumn + kolumner + + + figur + figurer + + + folio + folios + + + nummer + nummer + + + rad + rader + + + not + noter + + + opus + opera + + + sida + sidor + + + stycke + stycken + + + dek + delar + + + avsnitt + avsnitt + + + sub verbo + sub verbis + + + vers + verser + + + volym + volumer + + + + bok + kap + kol + fig + f + num + op + + s + ss + + st + del + avs + + s.v. + s.vv. + + + vers + verser + + + vol + vols + + + + + + ¶¶ + + + § + §§ + + + + + + + + + redaktör + redaktörer + + + editor + editors + + + översättare + översättare + + + editor & translator + editors & translators + + + + + + + + + red + reds + + + ed. + eds. + + + övers + övers + + + ed. & tran. + eds. & trans. + + + + redigerad av + edited by + översatt av + edited & translated by + till + intervju av + + + by + red + ed. + övers + ed. & trans. by + + + Januari + Februari + Mars + April + Maj + Juni + Juli + Augusti + September + Oktober + November + December + + + Jan + Feb + Mar + Apr + Maj + Jun + Jul + Aug + Sep + Okt + Nov + Dec + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-th-TH.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-th-TH.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + สืบค้น + และ + และคณะ + นิรนาม + นิรนาม + ที่ + โดย + โดยประมาณ + ประมาณ + อ้างถึง + + พิมพ์ครั้งที่ + พิมพ์ครั้งที่ + + พิมพ์ครั้งที่ + และคณะ + เต็มใจให้ข้อมูล + จาก + ในที่เดียวกัน + ใน + กำลังรอตีพิมพ์ + อินเทอร์เน็ต + การสัมภาษณ์ + จดหมาย + ไม่ปรากฏปีที่พิมพ์ + ม.ป.ป. + ออนไลน์ + นำเสนอที่ + + เอกสารอ้างอิง + เอกสารอ้างอิง + + + อ้างอิง + อ้างอิง + + สืบค้น + + + ค.ศ. + พ.ศ. + + + + + + + + + หนึ่ง + สอง + สาม + สี่ + + + หนึ่ง + สอง + สาม + สี่ + ห้า + หก + เจ็ด + แปด + เก้า + สิบ + + + มานุษยวิทยา + ดาราศาสตร์ + ชีววิทยา + พฤกษศาสตร์ + เคมี + วิศวกรรมศาสตร์ + พื้นฐานทั่วไป + ภูมิศาสตร์ + ธรณีวิทยา + ประวัติศาสตร์ + มนุษยศาสตร์ + ภาษาศาสตร์ + วรรณคดี + คณิตศาสตร์ + เวชศาสตร์ + ปรัชญา + ฟิสิกส์ + จิตวิทยา + สังคมวิทยา + วิทยาศาสตร์ + รัฐศาสตร์ + สังคมศาสตร์ + เทววิทยา + สัตววิทยา + + + + หนังสือ + หนังสือ + + + บทที่ + บทที่ + + + สดมภ์ + สดมภ์ + + + รูปภาพ + รูปภาพ + + + หน้า + หน้า + + + ฉบับที่ + ฉบับที่ + + + บรรทัดที่ + บรรทัดที่ + + + บันทึก + บันทึก + + + บทประพันธ์ + บทประพันธ์ + + + หน้า + หน้า + + + ย่อหน้า + ย่อหน้า + + + ส่วนย่อย + ส่วนย่อย + + + หมวด + หมวด + + + ใต้คำ + ใต้คำ + + + ร้อยกรอง + ร้อยกรอง + + + ปีที่ + ปีที่ + + + + หนังสือ + บทที่ + สดมภ์ + รูปภาพ + หน้า + ฉบับที่ + บทประพันธ์ + + น. + น. + + ย่อหน้า + ส่วนย่อย + หมวด + + ใต้คำ + ใต้คำ + + + ร้อยกรอง + ร้อยกรอง + + + ปี + ปี + + + + + + ¶¶ + + + § + §§ + + + + + + + + + บรรณาธิการ + บรรณาธิการ + + + ผู้อำนวยการบทบรรณาธิการ + ผู้อำนวยการบทบรรณาธิการ + + + ผู้แปล + ผู้แปล + + + บรรณาธิการและผู้แปล + บรรณาธิการและผู้แปล + + + + + + + + + บ.ก. + บ.ก. + + + ผอ.บทบรรณาธิการ + ผอ.บทบรรณาธิการ + + + ผู้แปล + ผู้แปล + + + บ.ก. + บ.ก. + + + + เรียบเรียงโดย + เรียบเรียงโดย + แปลโดย + แปลและเรียบเรียงโดย + ถึง + สัมภาษณ์โดย + + + โดย + โดย + โดย + แปล + แปลและเรียบเรียงโดย + + + มกราคม + กุมภาพันธ์ + มีนาคม + เมษายน + พฤษภาคม + มิถุนายน + กรกฎาคม + สิงหาคม + กันยายน + ตุลาคาม + พฤศจิกายน + ธันวาคม + + + ม.ค. + ก.พ. + มี.ค. + เม.ย. + พ.ค. + มิ.ย. + ก.ค. + ส.ค. + ก.ย. + ต.ค. + พ.ย. + ธ.ค. + + + ฤดูใบไม้ผลิ + ฤดูร้อน + ฤดูใบไม้ร่วง + ฤดูหนาว + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-tr-TR.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-tr-TR.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + erişildi + ve + ve diğ. + isimsiz + isimsiz + de + by + circa + c. + kaynak + + edition + editions + + ed + ve diğ. + gelecek + den + ibid. + içinde + basımda + internet + interview + letter + no date + tarih yok + çevrimiçi + sunulan + + reference + references + + + ref. + refs. + + erişildi + + + AD + BC + + + + « + » + + + + + st + nd + rd + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + antropoloji + astronomi + biyoloji + botanik + kimya + mühendislik + generic-base + coğrafya + jeoloji + tarih + humanities + linguistics + edebiyat + matematik + tıp + felsefe + fizik + pisikoloji + sosyoloji + bilim + siyaset bilimi + sosyal bilimler + din bilimi + hayvanbilimi + + + + kitap + kitaplar + + + bölüm + bölümler + + + sütun + sütunlar + + + şekil + şekiller + + + folyo + folyo + + + sayı + sayılar + + + satır + satırlar + + + not + notlar + + + opus + opera + + + sayfa + sayfalar + + + paragraf + paragraflar + + + kısım + kısımlar + + + bölüm + bölümler + + + sub verbo + sub verbis + + + dize + dizeler + + + cilt + ciltler + + + + kit + böl + süt + şek + f + sayı + op + + s + ss + + para + kıs + böl + + s.v. + s.vv. + + + v + vv + + + vol + vols + + + + + + ¶¶ + + + § + §§ + + + + + + + + + editör + editörler + + + editor + editors + + + çevirmen + çevirmenler + + + editor & translator + editors & translators + + + + + + + + + ed + ed + + + ed. + eds. + + + çev + çev + + + ed. & tran. + eds. & trans. + + + + editör + edited by + çeviren + edited & translated by + to + Röportaj yapan + + + by + ed + ed. + çev + ed. & trans. by + + + Ocak + Şubat + Mart + Nisan + Mayıs + Haziran + Temmuz + Ağustos + Eylül + Ekim + Kasım + Aralık + + + Oca + Şub + Mar + Nis + May + Haz + Tem + Ağu + Eyl + Eki + Kas + Ara + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-uk-UA.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-uk-UA.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,306 @@ + + + + + + + + + + + + + + + accessed + і + та інші + анонімний + анон. + на + by + circa + c. + cited + + edition + editions + + ed + et al. + forthcoming + із + ibid. + в + у пресі + інтернет + інтервю + лист + no date + n.d. + online + presented at the + + reference + references + + + ref. + refs. + + retrieved + + + AD + BC + + + + + « + » + + + + + st + nd + rd + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + антропологія + астрономія + біологія + ботаніка + хімія + інженерія + generic base + географія + геологія + історія + гуманітарні + linguistics + література + математика + медицина + філософія + фізика + психологія + соціологія + наука + політичні науки + соціальні науки + теологія + зоологія + + + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + line + lines + + + note + notes + + + opus + opera + + + page + pages + + + paragraph + paragraph + + + part + parts + + + section + sections + + + sub verbo + sub verbis + + + verse + verses + + + volume + volumes + + + + bk + chap + col + fig + f + no + op + + p + pp + + para + pt + sec + + s.v. + s.vv. + + + v + vv + + + vol + vols + + + + + + ¶¶ + + + § + §§ + + + + + + + + + editor + editors + + + editor + editors + + + translator + translators + + + editor & translator + editors & translators + + + + + + + + + ed + eds + + + ed. + eds. + + + tran + trans + + + ed. & tran. + eds. & trans. + + + + edited by + edited by + translated by + edited & translated by + to + interview by + + + by + ed + ed. + trans + ed. & trans. by + + + Січень + Лютий + Березень + Квітень + Травень + Червень + Липень + Серпень + Вересень + Жовтень + Листопад + Грудень + + + Січ + Лют + Бер + Квіт + Трав + Чер + Лип + Сер + Вер + Жов + Лис + Груд + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-vi-VN.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-vi-VN.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + truy cập + + and others + anonymous + anon + at + by + circa + c. + cited + + edition + editions + + ed + và c.s. + sắp tới + từ + n.t. + trong + in press + internet + interview + letter + no date + không ngày + online + presented at the + + reference + references + + + ref. + refs. + + truy vấn + + + AD + BC + + + + « + » + + + + + st + nd + rd + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + linguistics + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + dòng + dòng + + + note + notes + + + opus + opera + + + trang + trang + + + đoạn văn + đoạn văn + + + part + parts + + + section + sections + + + sub verbo + sub verbis + + + verse + verses + + + volume + volumes + + + + bk + chap + col + fig + f + số p.h + op + + tr + tr + + para + pt + sec + + s.v. + s.vv. + + + v + vv + + + vol + vols + + + + + + ¶¶ + + + § + §§ + + + + + + + + + biên tập viên + biên tập viên + + + editor + editors + + + biên dịch viên + biên dịch viên + + + editor & translator + editors & translators + + + + + + + + + b.t.v + b.t.v + + + ed. + eds. + + + b.d.v + b.d.v + + + ed. & tran. + eds. & trans. + + + + biên tập bởi + edited by + biên dịch bởi + edited & translated by + to + interview by + + + by + b.t + ed. + b.d + ed. & trans. by + + + Tháng Giêng + Tháng Hai + Tháng Ba + Tháng Tư + Tháng Năm + Tháng Sáu + Tháng Bảy + Tháng Tám + Tháng Chín + Tháng Mười + Tháng Mười-Một + Tháng Chạp + + + tháng 1 + tháng 2 + tháng 3 + tháng 4 + tháng 5 + tháng 6 + tháng 7 + tháng 8 + tháng 9 + tháng 10 + tháng 11 + tháng 12 + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-zh-CN.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-zh-CN.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + accessed + and + and others + anonymous + anon + at + by + circa + c. + cited + + edition + editions + + ed + et al. + forthcoming + from + ibid. + in + in press + internet + interview + letter + no date + nd + online + presented at the + + reference + references + + + ref. + refs. + + retrieved + + + AD + BC + + + + + + + + + st + nd + rd + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + anthropology + astronomy + biology + botany + chemistry + engineering + generic base + geography + geology + history + humanities + linguistics + literature + math + medicine + philosophy + physics + psychology + sociology + science + political science + social science + theology + zoology + + + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + line + line + + + note + notes + + + opus + opera + + + page + pages + + + paragraph + paragraph + + + part + parts + + + section + sections + + + sub verbo + sub verbis + + + verse + verses + + + volume + volumes + + + + bk + chap + col + fig + f + no + op + + p + pp + + para + pt + sec + + s.v. + s.vv. + + + v + vv + + + vol + vols + + + + + + ¶¶ + + + § + §§ + + + + + + + + + editor + editors + + + editor + editors + + + translator + translators + + + editor & translator + editors & translators + + + + + + + + + ed + eds + + + ed. + eds. + + + tran + trans + + + ed. & tran. + eds. & trans. + + + + edited by + edited by + translated by + edited & translated by + to + interview by + + + by + ed + ed. + trans + ed. & trans. by + + + January + February + March + April + May + June + July + August + September + October + November + December + + + Jan + Feb + Mar + Apr + May + Jun + Jul + Aug + Sep + Oct + Nov + Dec + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/locale/locales-zh-TW.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/locale/locales-zh-TW.xml Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + 被取用 + + 及其他 + 不具名的 + 無名 + + by + circa + c. + 被引用 + + 版本 + 版本 + + + 等人 + 將來的 + + 同上出處 + + 印行中 + 網際網路 + 訪問 + 信件 + no date + 無日期 + 在線上 + 簡報於 + + reference + references + + + ref. + refs. + + 被取回 + + + AD + BC + + + + + + + + + + st + nd + rd + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + 人類學 + 天文學 + 生物學 + 植物學 + 化學 + 工程學 + 一般基礎 + 地理學 + 地質學 + 歷史學 + 人文學科 + linguistics + 文學 + 數學 + 醫學 + 哲學 + 物理學 + 心理學 + 社會學 + 自然科學 + 政治科學 + 社會科學 + 神學 + 動物學 + + + + + + + + + + + + + + + + + + + + 對開紙 + 對開紙 + + + 期數 + 期數 + + + + + + + 筆記 + 筆記 + + + 作品 + 作品 + + + + + + + 段落 + 段落 + + + + + + + + + + + sub verbo + sub verbis + + + 詩句 + 詩句 + + + + + + + + + + + + + + + + + + + + + + + s.v. + s.vv. + + + + + + + + + + + + + + ¶¶ + + + § + §§ + + + + + 作者 + 作者 + + + 編輯 + 編輯 + + + editor + editors + + + 翻譯 + 翻譯 + + + editor & translator + editors & translators + + + + + + + + + + + + + ed. + eds. + + + + + + + ed. & tran. + eds. & trans. + + + + 編者是 + edited by + 譯者是 + edited & translated by + 授與 + 訪問者是 + + + by + + ed. + + ed. & trans. by + + + 一月 + 二月 + 三月 + 四月 + 五月 + 六月 + 七月 + 八月 + 九月 + 十月 + 十一月 + 十二月 + + + 1月 + 2月 + 3月 + 4月 + 5月 + 6月 + 7月 + 8月 + 9月 + 10月 + 11月 + 12月 + + + Spring + Summer + Autumn + Winter + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/schema/csl-categories.rng --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/schema/csl-categories.rng Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,51 @@ + + +
    + + + author-date + numeric + label + note + author + + + + "generic-base" is reserved for truly generic styles (APA, Harvard, etc.). + + anthropology + astronomy + biology + botany + chemistry + communications + engineering + generic-base + geography + geology + history + humanities + law + linguistics + literature + math + medicine + philosophy + physics + political_science + psychology + science + social_science + sociology + theology + zoology + + + + + Categories can be redefined in a customization schema, though please +report obvious gaps for inclusion in the schema. + + +
    +
    diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/schema/csl-terms.rng --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/schema/csl-terms.rng Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,148 @@ + + +
    + Terms + + + accessed + Miscellaneous Terms + ad + and + and others + anonymous + at + bc + by + circa + cited + et-al + forthcoming + from + ibid + in + in press + internet + interview + letter + no date + online + presented at + reference + retrieved + season-01 + Seasons + season-02 + season-03 + season-04 + open-quote + Punctuation + close-quote + open-inner-quote + close-inner-quote + page-range-delimiter + + Terms to which a gender may be assigned + + + Terms for which gender variants may be specified + + + Locators + + + Contributor Roles + + editortranslator + + Categories + + + + + + Terms to which a gender may be assigned + + month-01 + Months + month-02 + month-03 + month-04 + month-05 + month-06 + month-07 + month-08 + month-09 + month-10 + month-11 + month-12 + + Non-locator terms accompanying number variables + + + Locator terms with matching number variables + + + + + Terms for which gender variants may be specified + + ordinal-01 + Ordinals + ordinal-02 + ordinal-03 + ordinal-04 + long-ordinal-01 + Long Ordinals + long-ordinal-02 + long-ordinal-03 + long-ordinal-04 + long-ordinal-05 + long-ordinal-06 + long-ordinal-07 + long-ordinal-08 + long-ordinal-09 + long-ordinal-10 + + + + Locators + + book + chapter + column + figure + folio + line + note + opus + page + paragraph + part + section + sub verbo + verse + + Locator terms with matching number variables + + + + + Locator terms with matching number variables + + issue + volume + + + + Non-locator terms accompanying number variables + + chapter-number + collection-number + edition + number + number-of-pages + number-of-volumes + + +
    +
    diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/schema/csl-types.rng --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/schema/csl-types.rng Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,44 @@ + + +
    + CSL Types + + + article + article-journal + article-magazine + article-newspaper + bill + book + broadcast + chapter + entry + entry-dictionary + entry-encyclopedia + figure + graphic + interview + legal_case + legislation + manuscript + map + motion_picture + musical_score + pamphlet + paper-conference + patent + personal_communication + post + post-weblog + report + review + review-book + song + speech + thesis + treaty + webpage + + +
    +
    diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/schema/csl-variables.rng --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/schema/csl-variables.rng Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,102 @@ + + +
    + name variables + + + author + collection-editor + composer + container-author + editor + editorial-director + illustrator + interviewer + original-author + recipient + translator + + +
    +
    + date variables + + + accessed + container + event-date + issued + original-date + submitted + + +
    +
    + number variables + + + chapter-number + collection-number + edition + issue + number + number-of-pages + number-of-volumes + volume + + +
    +
    + standard variables + + + abstract + annote + archive + archive_location + archive-place + authority + call-number + citation-label + citation-number + collection-title + container-title + container-title-short + dimensions + DOI + event + event-place + first-reference-note-number + genre + ISBN + ISSN + jurisdiction + keyword + locator + medium + note + original-publisher + original-publisher-place + original-title + page + page-first + PMID + PMCID + publisher + publisher-place + references + section + source + status + title + title-short + URL + version + year-suffix + + number variables + + + +
    +
    diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/schema/csl.rng --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/schema/csl.rng Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1751 @@ + + + + Citation Style Language + Bruce D'Arcus + Simon Kornblith + Frank Bennett + Rintze Zelle + Bruce D'Arcus and Simon Kornblith, 2007-2011 + Permission to freely use, copy and distribute. + Citation Style Language (CSL) schema for describing bibliographic and citation formatting. + + + + + + + + + Subparts of the CSL schema + + + + + + + + + This macro call has no corresponding macro. + + + This macro call has no corresponding macro. + + +
    + Independent CSL style + + + + + Set a default style locale. + + + + + Select whether citations appear in-text or as notes. + + in-text + note + + + + + + + + + + + + + + + + + + + + + +
    +
    + Dependent CSL style + + + + + + + +
    +
    + + Style and Locale Metadata + + + + Set the CSL version of the style ("1.0" for CSL 1.0-compatible +styles). + 1.0 + + + + Metadata for independent styles. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Metadata for dependent styles. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Metadata for locale files. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Specify the citation format of the style (using the "citation-format" +attribute) or the fields and disciplines for which the style is +relevant (using the "field" attribute). + + + + + + + + + + + + + Specify the URI to establish the identity of the style. The URI +should be stable, unique and dereferenceable URI. + + + + + + Specify the journal's ISSN(s) for journal-specific styles. An ISSN +must consist of four digits, a hyphen, three digits, and a check +digit (a numeral digit or roman X), e.g. "1234-1231". + + \d{4}\-\d{3}(\d|x|X) + + + + + + Specify the journal's eISSN for journal-specific styles. + + \d{4}\-\d{3}(\d|x|X) + + + + + + Specify the journal's ISSN-L for journal-specific styles. + + \d{4}\-\d{3}(\d|x|X) + + + + + + + + + + Specify how the URL relates to the style. + + self + The URI of the CSL style itself. + template + URI of the style from which the current style is derived. + documentation + URI of style documentation. + independent-parent + Obsolete for independent styles. Will be disallowed with +CSL 1.1. + + + + + + + + + + + + Specify how the URL relates to the style. + + self + The URI of the CSL style itself. + independent-parent + URI of the CSL style whose content should be used for +processing. Required for dependent styles. + documentation + URI of style documentation. + template + Obsolete for dependent styles. Will be disallowed with CSL +1.1. + + + + + + + + Specify when the style was initially created or made available. + + + + + + + + + + + + + + + + + + + + + + + + + + Specify an abbreviated style title (e.g., "APA") + + + + + + Specify when the style was last updated (e.g., +"2007-10-26T21:32:52+02:00") + + + + + + + + + + + + + Obsolete for dependent styles. Will be disallowed with CSL 1.1. + + + + in-text + note + + + + + + + + + + +
    +
    + + Localization + + + CSL locale file (locales-xx-XX.xml) + + + Specify the locale of the locale file. + + + + Set the CSL version of the locale file ("1.0" for CSL +1.0-compatible locale files). + 1.0 + + + + + + + + + + + + + + + + Use to (re)define localized terms, dates and options. + + + Specify the affected locale(s). If "xml:lang" is not set, the +"cs:locale" element affects all locales. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + long + + + + + masculine + feminine + + + + + + + + + + long + + + + + masculine + feminine + + + + + + + "verb-short" reverts to "verb" if the "verb-short" form is not available +"symbol" reverts to "short" if the "symbol" form is not available +"verb" and "short" revert to "long" if the specified form is not available + + long + verb + short + verb-short + symbol + + + +
    + Extension structures. You may override these in a customization schema. +If you do, please contact the CSL project team to add the term or form to +the official schema. + + + + + + +
    + + Simple terms are basic strings, used to represent genres, media, etc. + + + + + + + Compound terms are those whose output can be either singular or plural. +Typically used for things like page number or editor labels. + + + + + + + + + Plural version of the term. + + + + + + Singular version of the term. + + + + + + + Select the localized date format ("text" or "numeric") that will +be defined. + + text + Text date form (e.g., "December 15, 2005" for "en-US"). + numeric + Numeric date form (e.g., "12-15-2005" for "en-US"). + + + + + + + + + + + + + + + + + + + + + Localized global options are specified as attributes in the +cs:style-options element. If future versions of CSL include localized +options that are citation or bibliography specific, the elements +cs:citation-options and cs:bibliography-options can be added. + + + + Specify whether punctuation (a period or comma) is placed within +or outside (default) the closing quotation mark. + + + + + +
    +
    + + Macros + + + + Use to create collections of (reusable) formatting instructions. + + + + + + +
    +
    + + Citation and Bibliography + + + + Use to describe the formatting of citations. + + + + + + + + + + + + Use to describe the formatting of the bibliography. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + Contributor Names + + + Options affecting cs:names, for cs:style, cs:citation and cs:bibliography. + + + Inheritable name option, companion for "delimiter" on cs:names. + + + + + + + + + Specify the delimiter for name lists of name variables rendered by +the same cs:names element. + + + + + + + + + + + Options affecting cs:name, for cs:style, cs:citation and cs:bibliography. + + + + Inheritable name option, companion for "form" on cs:name. + + long + short + count + + + + + + Inheritable name option, companion for "delimiter" on cs:name. + + + + + + + Use to separate the second-to-last and last name of a name list by +the "and" term or ampersand. + + text + Use the "and" term (e.g., "Doe, Johnson and Smith"). + symbol + Use the "ampersand" (e.g., "Doe, Johnson & Smith"). + + + + + + Specify when the name delimiter is used between a truncated name list +and the "et-al" (or "and others") term in case of et-al abbreviation +(e.g., "Smith, Doe et al." or "Smith, Doe, et al."). + + contextual + The name delimiter is only used when the truncated name list +consists of two or more names. + always + The name delimiter is always used. + never + The name delimiter is never used. + + + + + + Specify when the name delimiter is used between the second-to-last +and last name of a non-truncated name list. Only has an effect when +the "and" term or ampersand is used (e.g., "Doe and Smith" or "Doe, +and Smith"). + + contextual + The name delimiter is only used when the name list consists of +three or more names. + always + The name delimiter is always used. + never + The name delimiter is never used. + + + + + + Set the minimum number of names needed in a name variable to activate +et-al abbreviation. + + + + + + Set the number of names to render when et-al abbreviation is active. + + + + + + As "et-al-min", but only affecting subsequent citations to an item. + + + + + + As "et-al-use-first", but only affecting subsequent citations to an +item. + + + + + + If set to "true", the "et-al" (or "and others") term is replaced by +an ellipsis followed by the last name of the name variable. + + + + + + If set to "false", names are not initialized and "initialize-with" +only affects initials already present in the input data. + + + + + + Activate initializing of given names. The attribute value is appended +to each initial (e.g., with ". ", "Orson Welles" becomes "O. Welles"). + + + + + Specify whether (and which) names should be rendered in their sort +order (e.g., "Doe, John" instead of "John Doe"). + + first + Render the first name of each name variable in sort order. + all + Render all names in sort order. + + + + + + Sets the delimiter for name-parts that have switched positions as a +result of "name-as-sort-order" (e.g., ", " in "Doe, John"). + + + + + + + + + + + + + + + + + + + + + + + + + + Short version of "names" element, without children, allowed in <substitute/> + + + + + + + + + + + + Select the "long" (first name + last name, for Western names), +"short" (last name only, for Western names), or "count" name form +(returning the number of names in the name variable, which can be +useful for some sorting algorithms). + + long + short + count + + + + + Set the delimiter for names in a name variable (e.g., ", " in +"Doe, Smith") + + + + Use to format individual name parts (e.g., "Jane DOE"). + + + family + given + + + + + + + + + + + Inherits variable from the parent cs:names element. + + + + + + + + + + + + Specify the term used for et-al abbreviation and its formatting. + + + Select the term to use for et-al abbreviation. + + et-al + and others + + + + + + + + + + Specify substitution options when the name variables selected on the +parent cs:names element are empty. + + + + + + + + +
    +
    + + Dates + + + + + + + + + + Use to select a localized date format. + + text + Use the localized text form of the date (e.g., "December +15, 2005" for en-US). + numeric + Use the localized numeric form of the date (e.g., +"12-15-2005" for en-US) + + + + + Limit the date parts rendered. + + year-month-day + Year, month and day + year-month + Year and month + year + Year only + + + + + + Specify overriding formatting for localized dates (affixes +cannot be overridden, as these are considered locale-specific). +Example uses are forcing the use of leading-zeros, or of the +"short" month form. Has no effect on which, and in what order, +date parts are rendered. + + + + + + + + + + + + + + Specify, in the desired order, the date parts that should be +rendered and their formatting. + + + + + + + + + + + + + + + + + + + + + + + Specify a delimiter for date ranges (by default the en-dash). A custom +delimiter is retrieved from the largest date part ("day", "month" or +"year") that differs between the two dates. + + + + + + day + + + + Day forms: "numeric" ("5"), "numeric-leading-zeros" ("05"), "ordinal" +("5th"). + + numeric + numeric-leading-zeros + ordinal + + + + + + + + month + + + + Months forms: "long" (e.g., "January"), "short" ("Jan."), "numeric" +("1"), and "numeric-leading-zeros" ("01"). + + long + short + numeric + numeric-leading-zeros + + + + + + + + + year + + + + Year forms: "long" ("2005"), "short" ("05"). + + short + long + + + + + +
    +
    + + Formatting Text + + + + Use to call macros, render variables, terms, or verbatim text. + + + + + + + + + Select a macro. + + + + + Select a term. + + + + + + + + + + Specify term plurality: singular ("false") or plural ("true"). + + + + + + Specify verbatim text. + + + + Select a variable. + + + + + + short + long + + + + + + + + + + Use to render a number variable. + + + + + + + + + + Number forms: "numeric" ("4"), "ordinal" ("4th"), "long-ordinal" +("fourth"), "roman" ("iv"). + + numeric + ordinal + long-ordinal + roman + + + + + +
    +
    + + Label Text + + + + Use to render a term whose pluralization depends on the content of a +variable. E.g., if "page" variable holds a range, the plural label +"pp." is selected instead of the singular "p.". + + + + + locator + page + + + + + + long + short + symbol + + + + + + + + + + + + + Specify when the plural version of a term is selected. + + always + never + contextual + + + + +
    +
    + + Groups + + + + Use to group rendering elements. Groups are useful for setting a +delimiter for the group children, for organizing the layout of +bibliographic entries (using the "display" attribute), and for +suppressing the rendering of terms and verbatim text when variables +are empty. + + + + + + + + + +
    +
    + + Options + + + + + + + + + + + + + + + + + + + + + + + + + + + + Specify whether the non-dropping particle is demoted in inverted +names (e.g., "Koning, W. de"). + + never + sort-only + display-and-sort + + + + + + + + Specify whether compound given names (e.g., "Jean-Luc") are +initialized with ("J-L") or without a hyphen ("JL"). + + + + + + + + Reformat page ranges in the "page" variable. + + expanded + minimal + chicago + + + + + + + + Activate cite grouping and specify the delimiter for cites within a +cite group. + + + + + + + Activate cite grouping and specify the method of citation collapsing. + + citation-number + Collapse ranges of numeric cites, e.g. from "[1,2,3]" to "[1-3]". + year + Collapse cites by suppressing repeated names, e.g. from "(Doe +2000, Doe 2001)" to "(Doe 2000, 2001)". + year-suffix + Collapse cites as with "year", but also suppresses repeated +years, e.g. from "(Doe 2000a, Doe 2000b)" to "(Doe 2000a, b)". + year-suffix-ranged + Collapses cites as with "year-suffix", but also collapses +ranges of year-suffixes, e.g. from "(Doe 2000a, Doe 2000b, +Doe 2000c)" to "(Doe 2000a-c)". + + + + + + Specify the delimiter between year-suffixes. Defaults to the cite +delimiter. + + + + + Specify the delimiter following a group of collapsed cites. Defaults +to the cite delimiter. + + + + + + + Set to "true" to activate disambiguation by showing names that were +originally hidden as a result of et-al abbreviation. + + + + + + Set to "true" to activate disambiguation by expanding names, showing +initials or full given names. + + + + + + Set to "true" to activate disambiguation by adding year-suffixes +(e.g., "(Doe 2007a, Doe 2007b)") for items from the same author(s) +and year. + + + + + + Specify how name are expanded for disambiguation. + + all-names + Each ambiguous names is progressively transformed until +disambiguated (when disambiguation is not possible, the name +remains in its original form). + all-names-with-initials + As "all-names", but name expansion is limited to showing +initials. + primary-name + As "all-names", but disambiguation is limited to the first name +of each cite. + primary-name-with-initials + As "all-names-with-initials", but disambiguation is limited to +the first name of each cite. + by-cite + As "all-names", but only ambiguous names in ambiguous cites are +expanded. + + + + + + + + Set the number of preceding notes (footnotes or endnotes) within +which the current item needs to have been previously cited in order +for the "near-note" position to be "true". + + + + + + + + Set to "true" to render bibliographic entries with hanging indents. + + + + + + + + Set the spacing between bibliographic entries. + + + + + + Set the spacing between bibliographic lines. + + 0 + + + + + + + + Use to align any subsequent lines of bibliographic entries with the +beginning of the second field. + + flush + Align the first field with the margin. + margin + Put the first field in the margin and align all subsequent +lines of text with the margin. + + + + + + + + Substitute names that repeat in subsequent bibliographic entries by +the attribute value. + + + + + Specify the method of substitution of names repeated in subsequent +bibliographic entries. + + complete-all + Requires a match of all rendered names in the name variable, and +substitutes once for all names. + complete-each + Requires a match of all rendered names in the name variable, +and substitutes for each name. + partial-each + Substitutes for each name, until the first mismatch. + partial-first + Substitutes the first name if it matches. + + + + +
    +
    + + Sorting + + + + + + + + + + + Specify how cites and bibliographic entries should be sorted. By +default, items appear in the order in which they were cited. + + + + + + + + + + + + + + + + + + Select between an ascending and descending sort. + + ascending + descending + + + + + + The minimum number of names needed in a name variable to activate +name list truncation. Overrides the values set on any +"et-al-(subsequent-)min" attributes. + + + + + + The number of names to render when name list truncation is +activated. Overrides the values set on the +"et-al-(subsequent-)use-first" attributes. + + + + + + Use to override the value of the "et-at-use-last" attribute. + + + + + +
    +
    + + Conditional Statements + + + + Use to conditionally render rendering elements. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + If used, the element content is only rendered if it disambiguates two +otherwise identical citations. This attempt at disambiguation is only +made after all other disambiguation methods have failed. + true + + + Tests whether the given variables contain numeric text. + + + + + + + + Tests whether the given date variables contain approximate dates. + + + + + + + + Tests whether the locator matches the given locator types. + + + + + sub-verbo + + + + + + Tests whether the cite position matches the given positions. + + + + first + subsequent + ibid + ibid-with-locator + near-note + + + + + + Tests whether the item matches the given types. + + + + + + + + Tests whether the default ("long") forms of the given variables +contain non-empty values. + + + + + + + + + + + + Set the testing logic. + + all + Element only tests "true" when all conditions test "true" for all +given test values. + any + Element tests "true" when any condition tests "true" for any given +test value. + none + Element only tests "true" when none of the conditions test "true" +for any given test value. + + + + +
    +
    + Formatting attributes. + + + + + + + + + + + + + + + + + By default, bibliographic entries consist of continuous runs of text. +With the "display" attribute, portions of each entry can be +individually positioned. + + block + Places the content in a block stretching from margin to margin. + left-margin + Places the content in a block starting at the left margin. + right-inline + Places the content in a block to the right of a preceding +"left-margin" block. + indent + Places the content in a block indented to the right by a standard +amount. + + + + + + The font-formatting attributes are based on those of CSS and XSL-FO. + + + + italic + normal + oblique + + + + + + + normal + small-caps + + + + + + + normal + bold + light + + + + + + + none + underline + + + + + + + baseline + sup + sub + + + + + + + + When set to "true", quotes are placed around the rendered text. + + + + + + + + When set to "true", periods are removed from the rendered text. + + + + + + + + + lowercase + Renders text in lowercase. + uppercase + Renders text in uppercase. + capitalize-first + Capitalizes the first character (other characters remain in +their original case). + capitalize-all + Capitalizes the first character of every word (other characters +remain in their original case). + title + Renders text in title case. + sentence + Renders text in sentence case. + + + + +
    +
    diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/style/american-medical-association.csl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/style/american-medical-association.csl Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,237 @@ + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/style/apa.csl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/style/apa.csl Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,443 @@ + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/style/apsa.csl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/style/apsa.csl Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,235 @@ + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/style/asa.csl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/style/asa.csl Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,226 @@ + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/style/chicago-author-date.csl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/style/chicago-author-date.csl Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,481 @@ + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/style/chicago-fullnote-bibliography.csl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/style/chicago-fullnote-bibliography.csl Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1045 @@ + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/style/chicago-note-bibliography.csl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/style/chicago-note-bibliography.csl Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1016 @@ + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/style/council-of-science-editors.csl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/style/council-of-science-editors.csl Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,184 @@ + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/style/harvard1.csl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/style/harvard1.csl Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,185 @@ + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/style/ieee.csl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/style/ieee.csl Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,299 @@ + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/style/mhra.csl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/style/mhra.csl Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,416 @@ + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/style/mla.csl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/style/mla.csl Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,396 @@ + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/style/national-library-of-medicine-grant.csl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/style/national-library-of-medicine-grant.csl Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,254 @@ + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/style/nature.csl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/style/nature.csl Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,114 @@ + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/CiteProc/style/vancouver.csl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/CiteProc/style/vancouver.csl Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,267 @@ + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/RIS/biblio_ris.info --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/RIS/biblio_ris.info Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,13 @@ +name = Biblio - RIS +description = Provides RIS file import and export to the Biblio module. +core = 7.x +package = Biblio +dependencies[] = biblio +files[] = views/biblio_handler_field_export_link_ris.inc + +; Information added by drupal.org packaging script on 2013-07-20 +version = "7.x-1.0-rc7" +core = "7.x" +project = "biblio" +datestamp = "1374290470" + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/RIS/biblio_ris.install --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/RIS/biblio_ris.install Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,218 @@ +condition('format', 'ris') + ->execute(); + } +} + +function biblio_ris_enable() { + biblio_ris_set_system_weight(); +} + +function biblio_ris_set_system_weight() { + db_update('system') + ->fields(array('weight' => 27)) + ->condition('name', 'biblio_ris') + ->execute(); +} + +function _save_ris_maps() { + + $typemap = _get_ris_type_map(); + $typenames = _get_ris_type_names(); + $fieldmap = _get_ris_field_map(); + $maps = array_merge($typemap, $typenames, $fieldmap); + biblio_save_map($maps); + +} +function _reset_ris_map($type) { + $count = db_query("SELECT COUNT(*) FROM {biblio_type_maps} WHERE format='ris'")->fetchField(); + if ($count && $type) { //update + $function = '_get_ris_' . $type; + if (!function_exists($function)) return; + $map = $function(); + + db_update('biblio_type_maps') + ->fields($map) + ->condition('format', 'ris') + ->execute(); + } + else { // install + db_delete('biblio_type_maps') + ->condition('format', 'ris') + ->execute(); + _save_ris_maps(); + } +} + function _get_ris_type_map() { + $map['type_map'] = serialize( + array( + 'ABST' => 129, + 'ADVS' => 114, + 'ART' => 112, + 'BILL' => 117, + 'BOOK' => 100, + 'CASE' => 116, + 'CHAP' => 101, + 'COMP' => 113, + 'CONF' => 103, + 'CTLG' => 129, + 'DATA' => 125, + 'ELEC' => 129, + 'GEN' => 129, + 'HEAR' => 115, + 'ICOMM' => 107, + 'INPR' => 129, + 'JFULL' => 129, + 'JOUR' => 102, + 'MAP' => 122, + 'MGZN' => 106, + 'MPCT' => 110, + 'MUSIC' => 129, + 'NEWS' => 105, + 'PAMP' => 129, + 'PAT' => 119, + 'PCOMM' => 120, + 'RPRT' => 109, + 'SER' => 100, + 'SLIDE' => 129, + 'SOUND' => 129, + 'STAT' => 125, + 'THES' => 108, + 'UNBILl' => 129, + 'UNPB' => 124, + 'VIDEO' => 129, + ) + ); + $map['format'] = 'ris'; + return $map; +} + +function _get_ris_type_names() { + $map['type_names'] = serialize( + array( + 'ABST' => 'Abstract', + 'ADVS' => 'Audiovisual material', + 'ART' => 'Art Work', + 'BILL' => 'Bill/Resolution', + 'BOOK' => 'Book, Whole', + 'CASE' => 'Case', + 'CHAP' => 'Book chapter', + 'COMP' => 'Computer program', + 'CONF' => 'Conference proceeding', + 'CTLG' => 'Catalog', + 'DATA' => 'Data file', + 'ELEC' => 'Electronic Citation', + 'GEN' => 'Generic', + 'HEAR' => 'Hearing', + 'ICOMM' => 'Internet Communication', + 'INPR' => 'In Press', + 'JFULL' => 'Journal (full)', + 'JOUR' => 'Journal', + 'MAP' => 'Map', + 'MGZN' => 'Magazine article', + 'MPCT' => 'Motion picture', + 'MUSIC' => 'Music score', + 'NEWS' => 'Newspaper', + 'PAMP' => 'Pamphlet', + 'PAT' => 'Patent', + 'PCOMM' => 'Personal communication', + 'RPRT' => 'Report', + 'SER' => 'Serial (Book, Monograph)', + 'SLIDE' => 'Slide', + 'SOUND' => 'Sound recording', + 'STAT' => 'Statute', + 'THES' => 'Thesis/Dissertation', + 'UNBILl' => 'Unenacted bill/resolution', + 'UNPB' => 'Unpublished work', + 'VIDEO' => 'Video recording', + ) + ); + $map['format'] = 'ris'; + return $map; +} +function _get_ris_field_map() { + $map['field_map'] = serialize( + array( + 'ID' => '', //- Reference ID (not imported to reference software) + 'T1' => 'title', //- Primary title + 'TI' => 'title', //- Book title + 'BT' => 'title', //- Book title + 'CT' => 'title', //- Title of unpublished reference + 'A1' => '', //- Primary author + 'A2' => '', //- Secondary author (each name on separate line) + 'AU' => '', //- Author (syntax. Last name, First name, Suffix) + 'Y1' => 'biblio_year', //- Primary date + 'PY' => '', //- Publication year (YYYY/MM/DD) + 'N1' => 'biblio_notes', //- Notes + 'KW' => '', //- Keywords (each keyword must be on separate line preceded KW -) + 'RP' => '', //- Reprint status (IN FILE, NOT IN FILE, ON REQUEST (MM/DD/YY)) + 'SP' => '', //- Start page number + 'EP' => '', //- Ending page number + 'JF' => 'biblio_secondary_title',//- Periodical full name + 'JO' => 'biblio_short_title', //- Periodical standard abbreviation + 'JA' => 'biblio_secondary_title',//- Periodical in which article was published + 'J1' => 'biblio_short_title', //- Periodical name //- User abbreviation 1 + 'J2' => 'biblio_short_title', //- Periodical name - User abbreviation 2 + 'VL' => 'biblio_volume', //- Volume number + 'IS' => 'biblio_issue', //- Issue number + 'CP' => 'biblio_issue', //- Issue number + 'T2' => 'biblio_secondary_title',//- Title secondary + 'CY' => 'biblio_place_published',//- City of Publication + 'PB' => 'biblio_publisher', //- Publisher + 'U1' => 'biblio_custom1', //- User definable 1 + 'U2' => 'biblio_custom2', //- User definable 2 + 'U3' => 'biblio_custom3', //- User definable 3 + 'U4' => 'biblio_custom4', //- User definable 4 + 'U5' => 'biblio_custom5', //- User definable 5 + 'T3' => 'biblio_tertiary_title', //- Title series + 'AB' => 'biblio_abst_e', //- Abstract + 'N2' => 'biblio_abst_e', //- Abstract + 'SN' => 'biblio_isbn', //- ISSN/ISBN (e.g. ISSN XXXX-XXXX) + 'AV' => '', //- Availability + 'M1' => '', //- Misc. 1 + 'M3' => '', //- Misc. 3 + 'AD' => '', //- Address + 'UR' => 'biblio_url', //- Web/URL + 'L1' => '', //- Link to PDF + 'L2' => '', //- Link to Full-text + 'L3' => '', //- Related records + 'L4' => '', //- Images + 'ER' => '', //- End of Reference (must be the last tag) + ) + ); + + $map['format'] = 'ris'; + return $map; +} +/** + * Implementation of hook_schema(). + * + * Note: Pro Drupal Development models use of t() to translate 'description' + * for field definitions, but Drupal core does not use them. We follow core. + */ +function biblio_ris_schema() { + $schema = array(); + $schema['biblio_ris'] = array( + 'fields' => array( + 'nid' => array('type' => 'int', 'not null' => TRUE), + 'biblio_ris_md5' => array('type' => 'char', 'length' => 32, 'not null' => TRUE), + ), + 'primary key' => array('nid'), + ); + return $schema; +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/RIS/biblio_ris.module --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/RIS/biblio_ris.module Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,490 @@ + 2, + 'path' => drupal_get_path('module', 'biblio_ris') . '/views', + ); +} +/* + * add the ris option to the option list of the biblio_import_form + * the key is the module name use by module_invoke to call hook_biblio_import + * module_invoke('biblio_ris', 'biblio_import',...) + */ +function biblio_ris_biblio_import_options() { + return array('biblio_ris' => t('RIS')); +} +function biblio_ris_biblio_mapper_options() { + return array( + 'ris' => array( + 'title' => t('RIS'), + 'export' => TRUE, + ) + ); +} + +function biblio_ris_biblio_export_options() { + return array('ris' => t('RIS')); +} +function biblio_ris_form_biblio_node_form_alter(&$form, &$form_state) { + global $user; + if (!$form_state['submitted'] && !isset($form_state['values']) && !isset($form['#node']->nid)) { + if (!$form_state['submitted']) { + $form['biblio_ris_paste'] = array( + '#type' => 'fieldset', + '#title' => t('Paste RIS Record'), + '#weight' => -20, + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + $form['biblio_ris_paste']['paste_data_ris'] = array( + '#type' => 'textarea', + '#title' => t('RIS'), + '#required' => FALSE, + '#default_value' => isset($form_state['values']['paste_data_ris']) ? $form_state['values']['paste_data_ris'] : '', + '#description' => t('Paste a RIS entry here'), + '#size' => 60, + '#weight' => -4 + ); + $form['biblio_ris_paste']['paste_submit'] = array( + '#type' => 'submit', + '#value' => t('Populate using RIS'), + '#submit' => array('biblio_ris_form_biblio_node_form_submit') + ); + } + } + $biblio_ris_id = (isset($form_state['values']['biblio_ris_id'])) ? $form_state['values']['biblio_ris_id'] : ''; + $biblio_ris_md5 = (isset($form_state['values']['biblio_ris_md5'])) ? $form_state['values']['biblio_ris_md5'] : ''; + $form['biblio_ris_id'] = array('#type' => 'value', '#value' => $biblio_ris_id); + $form['biblio_ris_md5'] = array('#type' => 'value', '#value' => $biblio_ris_md5); +} + +function biblio_ris_form_biblio_node_form_submit($form, &$form_state) { + global $user; + $node_data = array(); + $dups = array(); + + if (strlen($form_state['values']['paste_data_ris'])) { + $node_data = _biblio_ris_import_string($form_state['values']['paste_data_ris']); + } + if (!empty($node_data) && is_object($node_data)) { + $form_state['values'] = array_merge($form_state['values'], (array)$node_data); + $form_state['input']['biblio_type'] = $form_state['biblio_type'] = $node_data->biblio_type; + } + $form_state['rebuild'] = TRUE; + return; +} + +/** + * Creates a link to export a node (or view) in ris format + * + * @param $base this is the base url (defaults to /biblio) + * @param $nid the node id, if NULL then the current view is exported + * @return a link (ris) + */ +function biblio_ris_biblio_export_link($nid = NULL, $filter = array()) { + $show_link = variable_get('biblio_export_links', array('ris' => TRUE)); + if (!isset($show_link['ris']) || empty($show_link['ris']) || !biblio_access('export') ) { + return array(); + } + $base = variable_get('biblio_base', 'biblio'); + + if (module_exists('popups') && !empty($nid)) { + $link = array( + 'attributes' => array( + 'class' => 'popups', + 'title' => t("Click to get the RIS output"))); + } + else { + $link = array( + 'attributes' => array( + 'title' => t("Click to download the RIS formatted file"))); + } + + $link['attributes'] += array('rel' => 'nofollow'); + + $link['href'] = "$base/export/ris/$nid"; + $link['title'] = t('RIS'); + + if (empty($nid) && !empty($filter)) { // add any filters which may be on the current page + $link['query'] = $filter; + } + + return array('biblio_ris' => $link); +} + +function biblio_ris_node_delete($node) { + if ($node->type != 'biblio') { + return; + } + db_delete('biblio_ris') + ->condition('nid', $node->nid) + ->execute(); +} + +function biblio_ris_node_insert($node) { + if (isset($node->biblio_ris_md5)) { + drupal_write_record('biblio_ris', $node); + } +} + +function biblio_ris_node_view($node, $view_mode) { + if ( $node->type == 'biblio') { + switch ($view_mode) { + case 'full': + case 'teaser': + $links = biblio_ris_biblio_export_link($node->nid); + $node->content['links']['biblio_ris'] = array( + '#links' => $links, + '#attributes' => array('class' => array('links', 'inline')), + ); + } + } +} + +function biblio_ris_biblio_import($file, $terms = array(), $batch = FALSE, $session_id = NULL, $save = TRUE, $string = FALSE) { + $nids = array(); + $dups = array(); + list($nids, $dups) = _biblio_ris_import($file, $terms, $batch, $session_id); + + return array($nids, $dups); +} + +function biblio_ris_biblio_export($nids) { + + if (module_exists('popups') && $nid) { + $popup = TRUE; + } + else { + $popup = FALSE; + drupal_add_http_header('Content-type', 'application/x-endnote-refer'); + drupal_add_http_header('Content-Disposition', 'attachment; filename="Drupal-Biblio.ris"'); + } + + $nodes = node_load_multiple($nids, array(), TRUE); + foreach ($nodes as $node) { + if (variable_get('biblio_hide_bibtex_braces', 0) ) { + $node->title = biblio_remove_brace($node->title); + } + + if (!$popup) { + print _biblio_ris_export($node); + } + else{ + $popup_data .= _biblio_ris_export($node); + } + } + if ($popup && !empty($popup_data)) return '
    ' . $popup_data . '
    '; + +} + +function _biblio_ris_import_string($string) { + $tag = ''; + $node = new stdClass(); + $unmapped = array(); + + $lines = preg_split('/[\r\n]/', $string, -1, PREG_SPLIT_NO_EMPTY); + foreach ($lines as $line) { + $line_len = strlen($line); + if ($line_len > 3) { + $start = strpos($line, ' -'); // There could be some unprintables at the beginning of the line so fine the location of the % + if ($start !== FALSE) { + $tag = drupal_substr($line, $start -2, 2); + $data = trim(drupal_substr($line, $start +3)); + } + else { + $data = $line; + } + } + if ($line_len > 3 && !empty($tag)) { // if this is not a blank line + if ($tag == 'ER') { + if (!empty($node)) { + $node->biblio_ris_md5 = md5(serialize($node)); + if (empty ($node->title )) $node->title = t("Untitled"); + if (! ($dup = biblio_ris_check_md5($node->biblio_ris_md5))) { + return $node; + } + else { + $message = t('The RIS node that you are trying to paste into the form already exists in the database, see !url', array('!url' => l('node/' . $dup, 'node/' . $dup))); + form_set_error('paste_data_ris', $message); + return; + } + } + } + else { + _biblio_ris_parse_line($tag, $data, $node, $unmapped); + } + } + } // end while + if (!empty($unmapped)) { + $ignored_tags = array_unique($unmapped); + $message = t("The following elements were ignored because they do not map to any biblio fields:") . ' '; + $message .= implode(', ', $ignored_tags); + if (user_access('administer biblio')) { + $message .= '. ' . t('Click !url if you wish to check the field mapping', array('!url' => l(t('here'), 'admin/config/content/biblio/iomap/edit/ris'))); + } + drupal_set_message($message, 'warning'); + } +} + +function _biblio_ris_import($file, $terms = array(), $batch = FALSE, $session_id = NULL) { + ini_set('auto_detect_line_endings', TRUE); + if (!($fp = fopen($file->uri, "r"))) { + drupal_set_message(t("Could not open RIS input file for reading."), 'error'); + return; + } + + $tag = ''; + $nids = array(); + $dups = array(); + $unmapped = array(); + $node = new stdClass(); + + while (!feof($fp)) { + $line = fgets($fp); + // Remove any character other than: carriage return, line feed, tab, or ANSI/ASCII character codes 32-255 + $line = preg_replace('/[^\r\n\t\x20-\xFF]/', '', $line); + $line_len = strlen($line); + if ($line_len > 3) { + $start = strpos($line, ' -'); // There could be some unprintables at the beginning of the line so fine the location of the % + if ($start !== FALSE) { + $tag = drupal_substr($line, $start -2, 2); + $data = trim(drupal_substr($line, $start +3)); + } + else { + $data = $line; + } + } + if ($line_len > 3 && !empty($tag)) { // if this is not a blank line + if ($tag == 'ER') { + if (!empty($node)) { + $node->biblio_ris_md5 = md5(serialize($node)); + if (empty ($node->title )) $node->title = t("Untitled"); + if (! ($dup = biblio_ris_check_md5($node->biblio_ris_md5))) { + biblio_save_node($node, $terms, $batch, $session_id); + if (!empty($node->nid)) $nids[] = $node->nid; + } + else { + $dups[] = $dup; + } + } + + $node = new stdClass(); + $node->biblio_contributors = array(); + } + else { + _biblio_ris_parse_line($tag, $data, $node, $unmapped); + } + + } + } // end while + + fclose($fp); + + if (!empty($unmapped)) { + $ignored_tags = array_unique($unmapped); + $message = t('The following elements were ignored because they do not map to any biblio fields:') . ' '; + $message .= implode(', ', $ignored_tags); + if (user_access('administer biblio')) { + $message .= '. ' . t('Click !url if you wish to check the field mapping', array('!url' => l(t('here'), 'admin/config/content/biblio/iomap/edit/ris'))); + } + drupal_set_message($message, 'warning'); + } + + return array($nids, $dups); +} + +function _biblio_ris_parse_line($tag, $data, $node, &$unmapped) { + switch ($tag) { + case 'TY' : + $node->biblio_type = _biblio_ris_type_map($data); + break; + case 'A1' : + case 'AU' : + $node->biblio_contributors[] = array( + 'name' => $data, + 'auth_category' => 1, + 'auth_type' => _biblio_get_auth_type(1, $node->biblio_type)); + break; + case 'DA' : + if (!isset($node->biblio_year) || empty($node->biblio_year)) { + $node->biblio_year = ($end = strpos($data, "/")) ? substr($data, 0, $end) : $data; + } + $node->biblio_date = $data; + break; + case 'Y1' : + case 'PY' : + if (!isset($node->biblio_year) || empty($node->biblio_year)) { + $node->biblio_year = ($end = strpos($data, "/")) ? substr($data, 0, $end) : $data; + } + if (!isset($node->biblio_date) || empty($node->biblio_date)) { + $node->biblio_date = $data; + } + break; + case 'A2' : + case 'ED' : + $node->biblio_contributors[] = array( + 'name' => $data, + 'auth_category' => 2, + 'auth_type' => _biblio_get_auth_type(2, $node->biblio_type)); + break; + case 'KW' : + $node->biblio_keywords[] = $data; + break; + case 'SP' : + case 'EP' : + $node->biblio_pages .= ($tag == "SP") ? $data : " - " . $data; + break; + case 'A3' : + $node->biblio_contributors[] = array( + 'name' => $data, + 'auth_category' => 5, + 'auth_type' => _biblio_get_auth_type(5, $node->biblio_type)); + break; + case 'BT' : + if ($node->biblio_type == 100) { + $node->title = $data; + } + else { + $node->biblio_secondary_title = $data; + } + break; + default : + if ($field = _biblio_ris_field_map($tag)) { + $node->$field .= $data; + } + else { + if (!in_array($tag, $unmapped)) { + $unmapped[] = $tag; + } + } + } +} + +function _biblio_ris_export($node) { + $reverse = TRUE; + $ris = ""; + $ris .= "TY - " . _biblio_ris_type_map($node->biblio_type, $reverse) . "\r\n"; + if (!empty($node->title)) $ris .= "T1 - " . trim($node->title) . "\r\n"; + switch ($node->biblio_type) { + case 100 : + case 101 : + case 103 : + case 104 : + case 105 : + case 108 : + case 119 : + if (!empty($node->biblio_secondary_title)) + $ris .= "T2 - " . trim($node->biblio_secondary_title) . "\r\n"; + break; + case 102 : + if (!empty($node->biblio_secondary_title)) + $ris .= "JF - " . trim($node->biblio_secondary_title) . "\r\n"; + unset($node->biblio_secondary_title); + break; // journal + } + if (isset($node->biblio_year) && $node->biblio_year < 9998) { + $ris .= "Y1 - " . trim($node->biblio_year) . "\r\n"; + } + + foreach (biblio_get_contributor_category($node->biblio_contributors, 1) as $auth) { + $ris .= "A1 - " . trim($auth['name']) . "\r\n"; + } + foreach (biblio_get_contributor_category($node->biblio_contributors, 2) as $auth) { + $ris .= "ED - " . trim($auth['name']) . "\r\n"; + } + + $kw_array = array(); + if (!empty($node->terms)) { + foreach ($node->terms as $term) { + $kw_array[] = $term->name; + } + } + if (!empty($node->biblio_keywords)) { + foreach ($node->biblio_keywords as $term) { + $kw_array[] = $term; + } + } + if (!empty($kw_array)) { + $kw_array = array_unique($kw_array); + foreach ($kw_array as $term) { + $ris .= "KW - " . trim($term) . "\r\n"; + } + } + $abst = ""; + if (!empty($node->biblio_abst_e)) $abst .= trim($node->biblio_abst_e); + if ($abst) { + $search = array("/\r/", "/\n/"); + $replace = " "; + $abst = preg_replace($search, $replace, $abst); + $ris .= "AB - " . $abst . "\r\n"; + } + $skip_fields = array('biblio_year', 'biblio_abst_e', 'biblio_abst_f', 'biblio_type' ); + $fields = drupal_schema_fields_sql('biblio'); + $fields = array_diff($fields, $skip_fields); + foreach ($fields as $field) { + if (!empty($node->$field)) { + $ris .= _biblio_ris_format_entry($field, $node->$field); + } + } + $ris .= "ER - \r\n\r\n"; + return $ris; +} + +function _biblio_ris_format_entry($key, $value) { + $reverse = TRUE; + $tag = _biblio_ris_field_map($key, $reverse); + if (!empty($tag)) { + return "$tag - " . trim($value) . "\r\n"; + } + +} + +function _biblio_ris_type_map($type, $reverse = FALSE) { + static $map = array(); + if (empty($map)) { + $map = biblio_get_map('type_map', 'ris'); + } + + if ($reverse) { + return ($tag = array_search($type, $map)) ? $tag : 'Generic'; //return the biblio type or 129 (Misc) if type not found + } + return (isset($map[$type]))?$map[$type]:129; //return the biblio type or 129 (Misc) if type not found +} + +function _biblio_ris_field_map($field, $reverse = FALSE) { + static $fmap = array(); + if (empty($fmap)) { + $fmap = biblio_get_map('field_map', 'ris'); + } + if ($reverse) { + return ($tag = array_search($field, $fmap)) ? $tag : ''; + + } + return (!empty($fmap[$field])) ? $fmap[$field] : ''; + +} +function biblio_ris_ris_map_reset($type = NULL) { + module_load_include('install', 'biblio_ris', 'biblio_ris'); + _reset_ris_map($type); +} + +function biblio_ris_check_md5($md5) { + static $ris_md5s = array(); + if (empty($ris_md5s)) { + $result = db_query("SELECT * FROM {biblio_ris} "); + foreach ($result as $row) { + $ris_md5s[$row->biblio_ris_md5] = $row->nid; + } + } + if (isset($ris_md5s[$md5])) { + return $ris_md5s[$md5]; + } + else { + $ris_md5s[$md5] = TRUE; // gaurd against duplicates in the same import + return; + } +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/bibtexParse/CHANGELOG --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/bibtexParse/CHANGELOG Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,83 @@ +CHANGELOG + +Released through http://bibliophile.sourceforge.net under the GPL licence. +Do whatever you like with this -- some credit to the author(s) would be appreciated. + +A collection of PHP classes to manipulate bibtex files. + +If you make improvements, please consider contacting the administrators at bibliophile.sourceforge.net so that your improvements can be added to the release package. + +Mark Grimshaw 2004/2005/2006 +http://bibliophile.sourceforge.net + +################################################ +v2.2 +24/April/2006 - Esteban Zimanyi and Mark Grimshaw +1/ A 4th array, $this->undefinedStrings, is now returned that holds field values that are judged to be undefined strings. i.e. they are a non-numeric value that is not defined in a @string{...} entry and not enclosed by braces or double-quotes. This array will be empty unless the following condition is met: +($this->removeDelimit || $this->expandMacro && $this->fieldExtract) +2/ When an undefined string is found in function removeDelimiters return the empty string. Return $this->undefinedStrings in the last position to allow compatibility with previous versions. +3/ Fix management of preamble in function returnArrays. + +v2.1 +7/February/2006 - Esteban Zimanyi and Mark Grimshaw +Minor debugging to catch more unusually formatted entries. + + +v2.0 +3/February/2006 - Esteban Zimanyi and Mark Grimshaw +Substantial work on PARSEENTRES.php (mainly by Esteban) to: +1/ handle @strings concatenated from other @strings. +2/ handle all different types of comments possible. +3/ clean-up the code. +4/ handles more unusual formatting of white space between and inside entries. + +v1.5.4 +17/June/2005 - Mark Grimshaw +month fields that have multiple dates (e.g. dec # " 5--9," or nov # " 29" # "--" # dec # " 2") are correctly parsed. (list($startMonth, $startDay, $endMonth, $endDay) = $parseMonth->init($monthField);) + +v1.5.3 +10/June/2005 - Mark Grimshaw +Fixed excessive expansion of @strings in bibtex imports. + +v1.5.2 +5/May/2005 - Mark Grimshaw and Guillaume Gardey. +1/ Corrections to PARSEENTRIES when handling concatenations using '#' +2/ Corrections to the example commandline code for PARSECREATORS. + +v1.5.1 +30th April 2005 - Mark Grimshaw +1/ Ensure entries such as journal = {{Journal of } # JRNL23} are properly parsed and expanded with a hanging '}' removed. + +v1.5 +28th April 2005 - Mark Grimshaw +1/ Fixed a bug when parsing @preamble in PARSEENTRIES.php +2/ Made efficiency and accuracy improvements in PARSECREATORS.php +3/ Added class PARSEMONTH to split a bibtex month field into day and month components. + list($month, $day) = $parseMonth->init($monthField); +4/ Added class PARSEPAGE to split a bibtex pages field into page start and page end components. + list($start, $end) = $parsePage->init($pagesField); + +v1.4 +25th August 2004 +1/ Expand macros added by Guillaume Gardey. +2/ Discard comments on same line as @string. +3/ A few bug fixes. +4/ PARSEENTRIES can parse PHP strings. (loadBibTeXString) +5/ Supports user defined BibTeX macro. (loadStringMacro) + +v1.3 +20th August 2004 +1/ @string{...} now correctly parsed. +2/ Any final "," left on the end of the last field in an entry is now removed. + +v1.2 +15th August 2004 +Corrected bug in extraction of values from @string. +v1.1 +15th August 2004 +1/ Added another flag to PARSEENTRIES to decide whether to remove enclosing "..." or {...} from string and entry fields. +2/ Some debugging and simplification. Both flags now have a default value of TRUE. + +v1.0 +14th August 2004 +Initial release: PARSEENTRIES.php, PARSECREATORS.php diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/bibtexParse/LICENSE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/bibtexParse/LICENSE Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,251 @@ +The GNU General Public License (GPL) + +Version 2, June 1991 + + + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. + +59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library 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. + + + +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) + + + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library General Public License instead of this License. \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/bibtexParse/PARSECREATORS.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/bibtexParse/PARSECREATORS.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,319 @@ +buildTypeMap(); + if (is_array($init)) + { + $this->setCreators($init); + }elseif (is_numeric($init)) + { + $this->loadCreators($init); + } + + } + + function buildTypeMap() + { + $result = db_query("SELECT * FROM {biblio_contributor_type} ;"); + while ($type = db_fetch_object($result)) + { + $this->typeMap[$type->type] = $type->ctid; + } + } + function getCreatorByName($name) + { + $result = db_query('SELECT * + FROM {biblio_contributor_data} + WHERE lastname RLIKE "[[:<:]]%s[[:>:]]" ', $name); + } + + function getCreatorCount() + { + return count($this->authors); + } + + function getCreatorString() + { + foreach ($this->authors as $key => $author) + { + $author_array[$author['rank']] = $author['firstname'] .' '. $author['initials'].' '.$author['lastname']; + } + ksort($author_array); + + return implode(', ' , $author_array); + } + + + private + function loadMD5() + { + $result = db_query('SELECT md5,cid FROM {biblio_contributor_data} '); + while ($row = db_fetch_array($result)) + { + $this->md5[$row['cid']] = $row['md5']; + } + } + + public + function loadCreators($vid) + { + $query = 'SELECT bcd.lastname, bcd.firstname, bcd.initials, + bcd.affiliation, bct.type, bc.rank + FROM {biblio_contributor} bc, + {biblio_contributor_data} bcd, + {biblio_contributor_type} bct + WHERE bc.vid = %d + AND bc.cid = bcd.cid + AND bc.ctid = bct.ctid + ORDER BY bc.ctid ASC, bc.rank ASC;'; + + $result = db_query($query, array($vid)); + while($creator = db_fetch_array($result)) + { + $this->authors[] = $creator; + } + + } + + public + function saveCreators($nid, $vid) + { + if (!empty($this->authors)) + { + $this->loadMD5(); + db_query('DELETE FROM {biblio_contributor} WHERE nid = %d AND vid = %d', $nid, $vid); + foreach ($this->authors as $rank => $author) + { + if (empty($author['cid']) && !empty($this->md5)) $author['cid'] = array_search($author['md5'], $this->md5); + if (empty($author['cid']) ) + { + drupal_write_record('biblio_contributor_data', $author); + $cid = db_last_insert_id('biblio_contributor_data', 'cid'); + }else + { + $cid = $author['cid']; + } + + $link_array = array('nid' => $nid, 'vid' => $vid, + 'cid' => $cid, 'rank' => $rank, + 'ctid' => $author['type']); + + drupal_write_record('biblio_contributor', $link_array ); + + } + } + } + + + function getAuthorArray() + { + return $this->authors; + } + + function getAuthor($rank) + { + return $this->authors[$rank]; + } + +/** + * update object with an array of authors + * + * @param $authors + * an array containing two keys "name" and "type" + * the name is the full name of the contributor which will be parsed into + * component pieces, and type contains a string indicating the author type + */ + function setCreators($authors) + { + foreach ($authors as $author) { + if (strlen(trim($author['name']))) + { + $this->authors[] = $this->parseAuthor($author['name'], $author['type']); + } + } + } + + function setCreator($author, $type = 'author') + { + $this->authors[] = $this->parseAuthor($author, $type); + } + + + +} + +/* +Released through http://bibliophile.sourceforge.net under the GPL licence. +Do whatever you like with this -- some credit to the author(s) would be appreciated. + +A collection of PHP classes to manipulate bibtex files. + +If you make improvements, please consider contacting the administrators at bibliophile.sourceforge.net so that your improvements can be added to the release package. + +Mark Grimshaw 2004/2005 +http://bibliophile.sourceforge.net + +28/04/2005 - Mark Grimshaw. + Efficiency improvements. + +11/02/2006 - Daniel Reidsma. + Changes to preg_matching to account for Latex characters in names such as {\"{o}} +*/ +// For a quick command-line test (php -f PARSECREATORS.php) after installation, uncomment these lines: + +/*********************** + $authors = "Mark \~N. Grimshaw and Bush III, G.W. & M. C. H{\\'a}mmer Jr. and von Frankenstein, Ferdinand Cecil, P.H. & Charles Louis Xavier Joseph de la Vallee P{\\\"{o}}ussin"; + $creator = new PARSECREATORS(); + $creatorArray = $creator->parse($authors); + print_r($creatorArray); +***********************/ + +class PARSECREATORS +{ + function PARSECREATORS() + { + } + + function parse($input, $type = 'author') + { + $input = trim($input); + // split on ' and ' + $authorArray = preg_split("/\s(and|&)\s/i", $input); + return $this->parseArray($authorArray, $type); + } + + function parseArray($authorArray, $type = 'author') + { + foreach ($authorArray as $author) + { + $this->authors[] = $this->parseAuthor($author, $type); + } + } +/* Create writer arrays from bibtex input. +'author field can be (delimiters between authors are 'and' or '&'): +1. +2. , +3. , , +*/ + function parseAuthor($value, $type = 'author') + { + $appellation = $prefix = $surname = $firstname = $initials = ''; + $this->prefix = array(); + $author = explode(",", preg_replace("/\s{2,}/", ' ', trim($value))); + $size = sizeof($author); +// No commas therefore something like Mark Grimshaw, Mark Nicholas Grimshaw, M N Grimshaw, Mark N. Grimshaw + if ($size == 1) + { +// Is complete surname enclosed in {...}, unless the string starts with a backslash (\) because then it is +// probably a special latex-sign.. +// 2006.02.11 DR: in the last case, any NESTED curly braces should also be taken into account! so second +// clause rules out things such as author="a{\"{o}}" +// + if (preg_match("/(.*) {([^\\\].*)}/", $value, $matches) && + !(preg_match("/(.*) {\\\.{.*}.*}/", $value, $matches2))) + { + $author = split(" ", $matches[1]); + $surname = $matches[2]; + } + else + { + $author = split(" ", $value); +// last of array is surname (no prefix if entered correctly) + $surname = array_pop($author); + } + } +// Something like Grimshaw, Mark or Grimshaw, Mark Nicholas or Grimshaw, M N or Grimshaw, Mark N. + else if ($size == 2) + { +// first of array is surname (perhaps with prefix) + list($surname, $prefix) = $this->grabSurname(array_shift($author)); + } +// If $size is 3, we're looking at something like Bush, Jr. III, George W + else + { +// middle of array is 'Jr.', 'IV' etc. + $appellation = join(' ', array_splice($author, 1, 1)); +// first of array is surname (perhaps with prefix) + list($surname, $prefix) = $this->grabSurname(array_shift($author)); + } + $remainder = join(" ", $author); + list($firstname, $initials) = $this->grabFirstnameInitials($remainder); + if (!empty($this->prefix)) + $prefix = join(' ', $this->prefix); + $surname = $surname . ' ' . $appellation; + $creator = array('firstname' => utf8_encode(trim($firstname)), 'initials' => utf8_encode(trim($initials)), 'lastname' => utf8_encode(trim($surname)), 'prefix' => trim($prefix)); + if (isset($creator)) + { + $creator['type'] = $this->typeMap[$type]; + $creator['md5'] = $this->md5sum($creator); + return $creator; + } + return FALSE; + } + + function md5sum($creator) + { + $string = $creator['firstname'].$creator['initials'].$creator['lastname']; + $string = str_replace(' ', '', drupal_strtolower($string)); + + return md5($string); + } +// grab firstname and initials which may be of form "A.B.C." or "A. B. C. " or " A B C " etc. + function grabFirstnameInitials($remainder) + { + $firstname = $initials = ''; + $array = split(" ", $remainder); + foreach ($array as $value) + { + $firstChar = substr($value, 0, 1); + if ((ord($firstChar) >= 97) && (ord($firstChar) <= 122)) + $this->prefix[] = $value; + else if (preg_match("/[a-zA-Z]{2,}/", trim($value))) + $firstnameArray[] = trim($value); + else + $initialsArray[] = str_replace(".", " ", trim($value)); + } + if (isset($initialsArray)) + { + foreach ($initialsArray as $initial) + $initials .= ' ' . trim($initial); + } + if (isset($firstnameArray)) + $firstname = join(" ", $firstnameArray); + return array($firstname, $initials); + } +// surname may have title such as 'den', 'von', 'de la' etc. - characterised by first character lowercased. Any +// uppercased part means lowercased parts following are part of the surname (e.g. Van den Bussche) + function grabSurname($input) + { + $surnameArray = split(" ", $input); + $noPrefix = $surname = FALSE; + foreach ($surnameArray as $value) + { + $firstChar = substr($value, 0, 1); + if (!$noPrefix && (ord($firstChar) >= 97) && (ord($firstChar) <= 122)) + $prefix[] = $value; + else + { + $surname[] = $value; + $noPrefix = TRUE; + } + } + if ($surname) + $surname = join(" ", $surname); + if (isset($prefix)) + { + $prefix = join(" ", $prefix); + return array($surname, $prefix); + } + return array($surname, FALSE); + } +} + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/bibtexParse/PARSEENTRIES.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/bibtexParse/PARSEENTRIES.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,561 @@ +undefinedStrings, is now returned that holds field values that are judged to be undefined strings. + i.e. they are a non-numeric value that is not defined in a @string{...} entry and not enclosed by braces or double-quotes. + This array will be empty unless the following condition is met: + ($this->removeDelimit || $this->expandMacro && $this->fieldExtract) + + 24/04/2006 Esteban Zimanyi + - When an undefined string is found in function removeDelimiters return the empty string + - Return $this->undefinedStrings in the last position to allow compatibility with previous versions + - Fix management of preamble in function returnArrays + */ + +// For a quick command-line test (php -f PARSEENTRIES.php) after installation, uncomment these lines: +require_once(drupal_get_path('module', 'biblio') . '/includes/biblio.contributors.inc'); + +/************************* + // Parse a file + $parse = NEW PARSEENTRIES(); + $parse->expandMacro = TRUE; + // $array = array("RMP" =>"Rev., Mod. Phys."); + // $parse->loadStringMacro($array); + // $parse->removeDelimit = FALSE; + // $parse->fieldExtract = FALSE; + $parse->openBib("bib.bib"); + $parse->extractEntries(); + $parse->closeBib(); + list($preamble, $strings, $entries, $undefinedStrings) = $parse->returnArrays(); + print_r($preamble); + print "\n"; + print_r($strings); + print "\n"; + print_r($entries); + print "\n\n"; + *************************/ + +/************************ + // Parse a bibtex PHP string + $bibtex_data = <<< END + + @STRING{three = "THREE"} + @STRING{two = "TWO"} + @string{JRNL23 = {NatLA 23 } # " " # two # " " # three} + + @article{klitzing.1, + author = "v. Klitzing and Dorda and Pepper", + title = "New method for high mark@sirfragalot.com accuracy determination of fine structure constant based on quantized hall resistance", + volume = "45", + journal = {Journal of } # JRNL23, + pages = "494", + citeulike-article-id = {12222 + } + , + ignoreMe = {blah}, } + + @article + { + klitzing.2, + author = "Klaus von Klitzing", + title = "The Quantized Hall Effect", + volume = "58", + journal = two, + pages = "519", + } + + END; + + $parse = NEW PARSEENTRIES(); + $parse->expandMacro = TRUE; + // $parse->removeDelimit = FALSE; + // $parse->fieldExtract = FALSE; + $array = array("RMP" =>"Rev., Mod. Phys."); + $parse->loadStringMacro($array); + $parse->loadBibtexString($bibtex_data); + $parse->extractEntries(); + list($preamble, $strings, $entries, $undefinedStrings) = $parse->returnArrays(); + print_r($preamble); + print "\n"; + print_r($strings); + print "\n"; + print_r($entries); + print "\n\n"; + + **********************/ + +class PARSEENTRIES +{ + /** + * @return unknown_type + */ + function PARSEENTRIES() + { + require_once(drupal_get_path('module', 'biblio_bibtex') . '/transtab_latex_unicode.inc.php'); + $this->transtab_latex_unicode = get_transtab_latex_unicode(); + $this->preamble = $this->strings = $this->undefinedStrings = $this->entries = array(); + $this->count = 0; + $this->fieldExtract = TRUE; + $this->removeDelimit = TRUE; + $this->expandMacro = FALSE; + $this->parseFile = TRUE; + $this->outsideEntry = TRUE; + $this->translate_latex = TRUE; + } + // Open bib file + /** + * @param $file + * @return none + */ + function openBib($file) + { + if (!is_file($file)) + die; + ini_set('auto_detect_line_endings', true); + $this->fid = fopen ($file,'r'); + $this->parseFile = TRUE; + } + // Load a bibtex string to parse it + function loadBibtexString($bibtex_string) + { + if (is_string($bibtex_string)) { + //$bibtex_string = $this->searchReplaceText($this->transtab_latex_unicode, $bibtex_string, FALSE); + $this->bibtexString = explode("\n",$bibtex_string); + } else { + $this->bibtexString = $bibtex_string; + } + $this->parseFile = FALSE; + $this->currentLine = 0; + } + function searchReplaceText($searchReplaceActionsArray, $sourceString, $includesSearchPatternDelimiters=FALSE) + { + $searchStrings = array_keys($searchReplaceActionsArray); + if (!$includesSearchPatternDelimiters) { + foreach ($searchStrings as $key => $value) { + $searchStrings[$key] = "/" . $value . "/"; // add search pattern delimiters + } + } + + $replaceStrings= array_values($searchReplaceActionsArray); + + // apply the search & replace actions defined in '$searchReplaceActionsArray' to the text passed in '$sourceString': + return preg_replace($searchStrings, $replaceStrings, $sourceString); + } + + // Set strings macro + function loadStringMacro($macro_array) + { + $this->userStrings = $macro_array; + } + // Close bib file + function closeBib() + { + fclose($this->fid); + } + // Get a non-empty line from the bib file or from the bibtexString + function getLine() + { + if ($this->parseFile) { + if (!feof($this->fid)) { + do { + $line = trim(fgets($this->fid)); + } + while(!feof($this->fid) && !$line); + return $line; + } + return FALSE; + } + else { + do { + $line = array_shift($this->bibtexString); + $line = trim($line); + $this->currentLine++; + } + while($this->bibtexString && !$line); + return $line; + } + } // Extract value part of @string field enclosed by double-quotes or braces. + // The string may be expanded with previously-defined strings + function extractStringValue($string) + { + // $string contains a end delimiter, remove it + $string = trim(substr($string,0,strlen($string)-1)); + // remove delimiters and expand + $string = $this->removeDelimitersAndExpand($string); + return $string; + } + // Extract a field + function fieldSplit($seg) + { + // echo "**** ";print_r($seg);echo "
    "; + // handle fields like another-field = {} + $array = preg_split("/,\s*([-_.:,a-zA-Z0-9]+)\s*={1}\s*/U", $seg, PREG_SPLIT_DELIM_CAPTURE); + // echo "**** ";print_r($array);echo "
    "; + //$array = preg_split("/,\s*(\w+)\s*={1}\s*/U", $seg, PREG_SPLIT_DELIM_CAPTURE); + if (!array_key_exists(1, $array)) + return array($array[0], FALSE); + return array($array[0], $array[1]); + } + // Extract and format fields + function reduceFields($oldString) + { + // 03/05/2005 G. Gardey. Do not remove all occurences, juste one + // * correctly parse an entry ended by: somefield = {aValue}} + $lg = strlen($oldString); + if ($oldString[$lg-1] == "}" || $oldString[$lg-1] == ")" || $oldString[$lg-1] == ",") + $oldString = substr($oldString,0,$lg-1); + // $oldString = rtrim($oldString, "}),"); + $split = preg_split("/=/", $oldString, 2); + $string = $split[1]; + while($string) + { + list($entry, $string) = $this->fieldSplit($string); + $values[] = $entry; + } + foreach ($values as $value) + { + $pos = strpos($oldString, $value); + $oldString = substr_replace($oldString, '', $pos, strlen($value)); + } + $rev = strrev(trim($oldString)); + if ($rev{0} != ',') + $oldString .= ','; + $keys = preg_split("/=,/", $oldString); + // 22/08/2004 - Mark Grimshaw + // I have absolutely no idea why this array_pop is required but it is. Seems to always be + // an empty key at the end after the split which causes problems if not removed. + array_pop($keys); + foreach ($keys as $key) + { + $value = trim(array_shift($values)); + $rev = strrev($value); + // remove any dangling ',' left on final field of entry + if ($rev{0} == ',') + $value = rtrim($value, ","); + if (!$value) + continue; + // 21/08/2004 G.Gardey -> expand macro + // Don't remove delimiters now needs to know if the value is a string macro + // $this->entries[$this->count][strtolower(trim($key))] = trim($this->removeDelimiters(trim($value))); + $key = strtolower(trim($key)); + $value = trim($value); + $this->entries[$this->count][$key] = $value; + } + // echo "**** ";print_r($this->entries[$this->count]);echo "
    "; + } + // Start splitting a bibtex entry into component fields. + // Store the entry type and citation. + function fullSplit($entry) + { + $matches = preg_split("/@(.*)[{(](.*),/U", $entry, 2, PREG_SPLIT_DELIM_CAPTURE); + $this->entries[$this->count]['bibtexEntryType'] = strtolower(trim($matches[1])); + // sometimes a bibtex entry will have no citation key + if (preg_match("/=/", $matches[2])) // this is a field + $matches = preg_split("/@(.*)\s*[{(](.*)/U", $entry, 2, PREG_SPLIT_DELIM_CAPTURE); + // print_r($matches); print "

    "; + $this->entries[$this->count]['bibtexCitation'] = $matches[2]; + $this->reduceFields($matches[3]); + } + + // Grab a complete bibtex entry + function parseEntry($entry) + { + set_time_limit(30); // reset the script timer to avoid timeouts + $entry = $this->translate_latex ? $this->searchReplaceText($this->transtab_latex_unicode, $entry, FALSE) : $entry; + $count = 0; + $lastLine = FALSE; + if (preg_match("/@(.*)([{(])/U", preg_quote($entry), $matches)) + { + if (!array_key_exists(1, $matches)) + return $lastLine; + if (preg_match("/string/i", trim($matches[1]))) + $this->strings[] = $entry; + else if (preg_match("/preamble/i", trim($matches[1]))) + $this->preamble[] = $entry; + else if (preg_match("/comment/i", $matches[1])); // MG (31/Jan/2006) -- ignore @comment + else + { + if ($this->fieldExtract) + $this->fullSplit($entry); + else + $this->entries[$this->count] = $entry; + $this->count++; + } + return $lastLine; + } + } + + // Remove delimiters from a string + function removeDelimiters($string) + { + if ($string && ($string{0} == "\"")) + { + $string = substr($string, 1); + $string = substr($string, 0, -1); + } + else if ($string && ($string{0} == "{")) + { + if (strlen($string) > 0 && $string[strlen($string)-1] == "}") + { + $string = substr($string, 1); + $string = substr($string, 0, -1); + } + } + else if (!is_numeric($string) && !array_key_exists($string, $this->strings) + && (array_search($string, $this->undefinedStrings) === FALSE)) + { + $this->undefinedStrings[] = $string; // Undefined string that is not a year etc. + return ''; + } + return $string; + } + + // This function works like explode('#',$val) but has to take into account whether + // the character # is part of a string (i.e., is enclosed into "..." or {...} ) + // or defines a string concatenation as in @string{ "x # x" # ss # {xx{x}x} } + function explodeString($val) + { + $openquote = $bracelevel = $i = $j = 0; + while ($i < strlen($val)) + { + if ($val[$i] == '"') + $openquote = !$openquote; + elseif ($val[$i] == '{') + $bracelevel++; + elseif ($val[$i] == '}') + $bracelevel--; + elseif ( $val[$i] == '#' && !$openquote && !$bracelevel ) + { + $strings[] = substr($val,$j,$i-$j); + $j=$i+1; + } + $i++; + } + $strings[] = substr($val,$j); + return $strings; + } + + // This function receives a string and a closing delimiter '}' or ')' + // and looks for the position of the closing delimiter taking into + // account the following Bibtex rules: + // * Inside the braces, there can arbitrarily nested pairs of braces, + // but braces must also be balanced inside quotes! + // * Inside quotes, to place the " character it is not sufficient + // to simply escape with \": Quotes must be placed inside braces. + function closingDelimiter($val,$delimitEnd) + { + // echo "####>$delimitEnd $val
    "; + $openquote = $bracelevel = $i = $j = 0; + while ($i < strlen($val)) + { + // a '"' found at brace level 0 defines a value such as "ss{\"o}ss" + if ($val[$i] == '"' && !$bracelevel) + $openquote = !$openquote; + elseif ($val[$i] == '{') + $bracelevel++; + elseif ($val[$i] == '}') + $bracelevel--; + if ( $val[$i] == $delimitEnd && !$openquote && !$bracelevel ) + return $i; + $i++; + } + // echo "--> $bracelevel, $openquote"; + return 0; + } + + // Remove enclosures around entry field values. Additionally, expand macros if flag set. + function removeDelimitersAndExpand($string, $inpreamble = FALSE) + { + // only expand the macro if flag set, if strings defined and not in preamble + if (!$this->expandMacro || empty($this->strings) || $inpreamble) + $string = $this->removeDelimiters($string); + else + { + $stringlist = $this->explodeString($string); + $string = ""; + foreach ($stringlist as $str) + { + // trim the string since usually # is enclosed by spaces + $str = trim($str); + // replace the string if macro is already defined + // strtolower is used since macros are case insensitive + if (isset($this->strings[strtolower($str)])) + $string .= $this->strings[strtolower($str)]; + else + $string .= $this->removeDelimiters(trim($str)); + } + } + return $string; + } + + // This function extract entries taking into account how comments are defined in BibTeX. + // BibTeX splits the file in two areas: inside an entry and outside an entry, the delimitation + // being indicated by the presence of a @ sign. When this character is met, BibTex expects to + // find an entry. Before that sign, and after an entry, everything is considered a comment! + function extractEntries() + { + $inside = $possibleEntryStart = FALSE; + $entry=""; + while($line=$this->getLine()) + { + if ($possibleEntryStart) + $line = $possibleEntryStart . $line; + if (!$inside && strchr($line,"@")) + { + // throw all characters before the '@' + $line=strstr($line,'@'); + if (!strchr($line, "{") && !strchr($line, "(")) + $possibleEntryStart = $line; + elseif (preg_match("/@.*([{(])/U", preg_quote($line), $matches)) + { + $inside = TRUE; + if ($matches[1] == '{') + $delimitEnd = '}'; + else + $delimitEnd = ')'; + $possibleEntryStart = FALSE; + } + } + if ($inside) + { + $entry .= " ".$line; + if ($j=$this->closingDelimiter($entry,$delimitEnd)) + { + // all characters after the delimiter are thrown but the remaining + // characters must be kept since they may start the next entry !!! + $lastLine = substr($entry,$j+1); + $entry = substr($entry,0,$j+1); + // Strip excess whitespaces from the entry + $entry = preg_replace('/\s\s+/', ' ', $entry); + $this->parseEntry($entry); + $entry = strchr($lastLine,"@"); + if ($entry) + $inside = TRUE; + else + $inside = FALSE; + } + } + } + } + + // Return arrays of entries etc. to the calling process. + function returnArrays() + { + // global $transtab_latex_unicode; // defined in 'transtab_latex_unicode.inc.php' + foreach ($this->preamble as $value) + { + preg_match("/.*?[{(](.*)/", $value, $matches); + $preamble = substr($matches[1], 0, -1); + $preambles['bibtexPreamble'] = trim($this->removeDelimitersAndExpand(trim($preamble), TRUE)); + } + if (isset($preambles)) + $this->preamble = $preambles; + if ($this->fieldExtract) + { + // Next lines must take into account strings defined by previously-defined strings + $strings = $this->strings; + // $this->strings is initialized with strings provided by user if they exists + // it is supposed that there are no substitutions to be made in the user strings, i.e., no # + $this->strings = isset($this->userStrings) ? $this->userStrings : array() ; + foreach ($strings as $value) + { + // changed 21/08/2004 G. Gardey + // 23/08/2004 Mark G. account for comments on same line as @string - count delimiters in string value + $value = trim($value); + $matches = preg_split("/@\s*string\s*([{(])/i", $value, 2, PREG_SPLIT_DELIM_CAPTURE); + $delimit = $matches[1]; + $matches = preg_split("/=/", $matches[2], 2, PREG_SPLIT_DELIM_CAPTURE); + // macros are case insensitive + $this->strings[strtolower(trim($matches[0]))] = $this->extractStringValue($matches[1]); + } + } + // changed 21/08/2004 G. Gardey + // 22/08/2004 Mark Grimshaw - stopped useless looping. + // removeDelimit and expandMacro have NO effect if !$this->fieldExtract + if ($this->removeDelimit || $this->expandMacro && $this->fieldExtract) + { + for($i = 0; $i < count($this->entries); $i++) + { + foreach ($this->entries[$i] as $key => $value) + // 02/05/2005 G. Gardey don't expand macro for bibtexCitation + // and bibtexEntryType + if ($key != 'bibtexCitation' && $key != 'bibtexEntryType') + $this->entries[$i][$key] = trim($this->removeDelimitersAndExpand($this->entries[$i][$key])); + } + } + // EZ: Remove this to be able to use the same instance for parsing several files, + // e.g., parsing a entry file with its associated abbreviation file + // if (empty($this->preamble)) + // $this->preamble = FALSE; + // if (empty($this->strings)) + // $this->strings = FALSE; + // if (empty($this->entries)) + // $this->entries = FALSE; + return array($this->preamble, $this->strings, $this->entries, $this->undefinedStrings); + } + + function &getEntries() { + if ($this->removeDelimit || $this->expandMacro && $this->fieldExtract) + { + for($i = 0; $i < count($this->entries); $i++) + { + foreach ($this->entries[$i] as $key => $value) + // 02/05/2005 G. Gardey don't expand macro for bibtexCitation + // and bibtexEntryType + if ($key != 'bibtexCitation' && $key != 'bibtexEntryType') + $this->entries[$i][$key] = trim($this->removeDelimitersAndExpand($this->entries[$i][$key])); + } + } + return $this->entries; + } + +} + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/bibtexParse/PARSEMONTH.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/bibtexParse/PARSEMONTH.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,117 @@ +startDay = $endMonth = $this->endDay = FALSE; + $date = split("#", $monthField); + foreach ($date as $field) + { + $field = ucfirst(strtolower(trim($field))); + if ($month = array_search($field, $this->monthToLongName())) + { + if (!$startMonth) + $startMonth = $month; + else + $endMonth = $month; + continue; + } + else if ($month = array_search($field, $this->monthToShortName())) + { + if (!$startMonth) + $startMonth = $month; + else + $endMonth = $month; + continue; + } + $this->parseDay($field); + } + if ($this->endDay && !$endMonth) + $endMonth = $startMonth; + return array($startMonth, $this->startDay, $endMonth, $this->endDay); + } +// extract day of month from field + function parseDay($dayField) + { + preg_match("/([0-9]+).*([0-9]+)|([0-9]+)/", $dayField, $array); + if (array_key_exists(3, $array)) + { + if (!$this->startDay) + $this->startDay = $array[3]; + else if (!$this->endDay) + $this->endDay = $array[3]; + } + else + { + if (array_key_exists(1, $array)) + $this->startDay = $array[1]; + if (array_key_exists(2, $array)) + $this->endDay = $array[2]; + } + } +// Convert month to long name + function monthToLongName() + { + return array( + 1 => 'January', + 2 => 'February', + 3 => 'March', + 4 => 'April', + 5 => 'May', + 6 => 'June', + 7 => 'July', + 8 => 'August', + 9 => 'September', + 10 => 'October', + 11 => 'November', + 12 => 'December', + ); + } +// Convert month to short name + function monthToShortName() + { + return array( + 1 => 'Jan', + 2 => 'Feb', + 3 => 'Mar', + 4 => 'Apr', + 5 => 'May', + 6 => 'Jun', + 7 => 'Jul', + 8 => 'Aug', + 9 => 'Sep', + 10 => 'Oct', + 11 => 'Nov', + 12 => 'Dec', + ); + } +} +?> diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/bibtexParse/PARSEPAGE.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/bibtexParse/PARSEPAGE.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,66 @@ +type1($item)) + return $this->return; +// else, return first number we can find + if (preg_match("/(\d+|[ivx]+)/i", $item, $array)) + return array($array[1], FALSE); +// No valid page numbers found + return array(FALSE, FALSE);; + } +// "77--99" or '-'type? + function type1($item) + { + $start = $end = FALSE; + $array = preg_split("/--|-/", $item); + if (sizeof($array) > 1) + { + if (is_numeric(trim($array[0]))) + $start = trim($array[0]); + else + $start = strtolower(trim($array[0])); + if (is_numeric(trim($array[1]))) + $end = trim($array[1]); + else + $end = strtolower(trim($array[1])); + if ($end && !$start) + $this->return = array($end, $start); + else + $this->return = array($start, $end); + return TRUE; + } + return FALSE; + } +} +?> diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/bibtexParse/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/bibtexParse/README Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,96 @@ +Released through http://bibliophile.sourceforge.net under the GPL licence. +Do whatever you like with this -- some credit to the author(s) would be appreciated. + +A collection of PHP classes to manipulate bibtex files. + +If you make improvements, please consider contacting the administrators at bibliophile.sourceforge.net so that your improvements can be added to the release package. + +Mark Grimshaw & Guillaume Gardey 2004 - 2006 +http://bibliophile.sourceforge.net + +################################################ +PARSEENTRIES +############ +This reads the contents of a BibTeX .bib file or a PHP string and returns arrays of information representing @preamble, @string and valid BibTeX entries. + +Entries may be enclosed by {...} or (...). Fields values may be enclosed by "...", {...} or without enclosure. + +FLAGS can be set: +$parse->fieldExtract; +$parse->removeDelimit; +$parse->expandMacro = FALSE/TRUE to expand macros within BibTeX entries ('#' and @string values). + +If $parse->fieldExtract == TRUE (default), the $entries array using the supplied example bib.bib file will be: +Array +( + [0] => Array + ( + [bibtexEntryType] => article + [bibtexCitation] => klitzing:qhe + [author] => K. v. Klitzing and G. Dorda = "and M. Pepper + [title] => New method for h{\i}gh mark@sirfragalot.com accuracy determination of fine structure constant based on quantized hall resistance + [journal] => PRL + [volume] => 45 + [pages] => 494 + [blah] => bl"ah + [year] => 1980 + ) + + [1] => Array + ( + [bibtexEntryType] => article + [bibtexCitation] => klitzing:nobel + [author] => Klaus von Klitzing + [title] => The Quantized Hall Effect + [journal] => RMP + [volume] => 58 + [pages] => 519 + [year] => 1986 + ) +) + +In other words, an array of separate BibTeX entries each one an array comprising the fields, entry type and given citation. @strings will be similarly formatted. + +If $parse->fieldExtract == FALSE, the $entries array using the supplied example bib.bib file will be: +Array +( + [0] => @ARTICLE{klitzing:qhe, AUTHOR="K. v. Klitzing and G. Dorda = "and M. Pepper", TITLE="New method for h{\i}gh mark@sirfragalot.com accuracy determination of fine structure constant based on quantized hall resistance", JOURNAL=PRL, VOLUME= 45, PAGES=494, blah=" bl"ah ", YEAR=1980 }, + [1] => @ARTICLE(klitzing:nobel, AUTHOR={Klaus von Klitzing}, TITLE="The Quantized Hall Effect",JOURNAL=RMP, VOLUME=58, PAGES=519, YEAR=1986 ) +) + +In other words, an array of separate BibTeX entries with no further processing. @strings will be similarly formatted. +NB - IF fieldExtract == FALSE, SETTINGS FOR expandMacro AND removeDelimit WILL HAVE NO EFFECT. + +If $parse->removeDelimit == TRUE (default), all double-quotes or braces that enclose field values of BibTeX entries/strings will be removed. Otherwise, they will be left in place. Setting this to TRUE only has an effect if $parse->fieldExtract is TRUE. + +In all cases, @preamble (from the given example bib.bib file) will be returned as: +Array +( + [bibtexPreamble] => Blah blah blah some preamble or other r +) + +Additional BibTeX macro can be supplied to the parser: +$more_macro = array("RMP" => "Rev., Mod. Phys.", "LNCS" => "Lecture Notes in Computer Science"); +$parse->loadStringMacro($more_macro); + +$parse->returnArrays() will then return $entries with all BibTeX macros (BibTeX file + $more_macro) expanded. + + +################################################ +PARSECREATORS +############# +This takes a BibTeX author or editor field and splits it into the component writers returning a multidimensional array consisting of writer arrays comprised of array(firstname(s), initials, surname). It attempts to recognise 'et. al' or 'et. al.' and returns either FALSE or TRUE if that exists. If the input is 'Anon', 'anon', 'Anonymous' or 'anonymous' FALSE is returned. +################################################ + + +################################################ +PARSEMONTH +############# +Split a bibtex month field into day and month components including date ranges. + list($startMonth, $startDay, $endMonth, $endDay) = $parseMonth->init($monthField); + +################################################ +PARSEPAGE +############# +Split a bibtex pages field into page start and page end components. + list($start, $end) = $parsePage->init($pagesField); \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/bibtexParse/bib.bib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/bibtexParse/bib.bib Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,44 @@ + + + +@STrinG{PRL="Phys. Rev. +Lett."} + +@preAmbLE {"Blah blah blah some preamble or other +r"} + +%%some comments + + + @ARTICLE{klitzing:qhe, + AUTHOR="K. v. Klitzing and G. Dorda = "and M. +Pepper", + + + TITLE="New method for h{\i}gh mark@sirfragalot.com accuracy determination of fine structure +constant based on quantized hall resistance", +JOURNAL=PRL, +%%some comments + + VOLUME= + +45, + +PAGES=494, +blah=" bl"ah ", +YEAR=1980 # Aug +} + +%% @stRING( +%%RMP="Rev., Mod. +%%Phys.") + @ARTICLE +(klitzing:nobel, +AUTHOR={Klaus von Klitzing}, +TITLE="The Quantized Hall Effect",JOURNAL=RMP, +VOLUME=58, +PAGES=519, +YEAR=1986 +) + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/bibtexParse/biblio_bibtex.info --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/bibtexParse/biblio_bibtex.info Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,14 @@ +name = Biblio - BibTex +description = Provides BibTex import and export to the Biblio module. +core = 7.x +package = Biblio +dependencies[] = biblio +files[] = PARSEENTRIES.php +files[] = views/biblio_handler_field_export_link_bibtex.inc + +; Information added by drupal.org packaging script on 2013-07-20 +version = "7.x-1.0-rc7" +core = "7.x" +project = "biblio" +datestamp = "1374290470" + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/bibtexParse/biblio_bibtex.install --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/bibtexParse/biblio_bibtex.install Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,165 @@ +condition('format', 'bibtex') + ->execute(); + } +} + +function biblio_bibtex_enable() { + biblio_bibtex_set_system_weight(); +} + +function biblio_bibtex_set_system_weight() { + db_update('system') + ->fields(array('weight' => 22)) + ->condition('name', 'biblio_bibtex') + ->execute(); +} + + +function _get_bibtex_type_map() { + $map['type_map'] = serialize( + array( + 'article' => 102, + 'book' => 100, + 'booklet' => 129, + 'conference' => 103, + 'inbook' => 101, + 'incollection' => 101, + 'inproceedings' => 103, + 'manual' => 129, + 'mastersthesis' => 108, + 'misc' => 129, + 'phdthesis' => 108, + 'proceedings' => 104, + 'techreport' => 129, + 'unpublished' => 124, + ) + ); + $map['format'] = 'bibtex'; + return $map; + +} + +function _get_bibtex_type_names() { + $map['type_names'] = serialize( + array( + 'article' => 'An article from a journal', + 'book' => 'A book with an explicit publisher', + 'booklet' => 'A work that is printed and bound, but without a named publisher or sponsoring institution', + 'conference' => 'An article in a conference proceedings', + 'inbook' => 'A part of a book, usually untitled. May be a chapter (or section or whatever) and/or a range of pages', + 'incollection' => 'A part of a book having its own title', + 'inproceedings' => 'An article in a conference proceedings', + 'manual' => 'Technical documentation', + 'mastersthesis' => 'A Master\'s thesis', + 'misc' => 'For use when nothing else fits', + 'phdthesis' => 'A Ph.D. thesis', + 'proceedings' => 'The proceedings of a conference', + 'techreport' => 'A report published by a school or other institution, usually numbered within a series', + 'unpublished' => 'A document having an author and title, but not formally published', + ) + ); + $map['format'] = 'bibtex'; + return $map; + +} +function _get_bibtex_field_map() { + + $map['field_map'] = serialize( + array( + 'journal' => 'biblio_secondary_title', + 'booktitle' => 'biblio_secondary_title', + 'series' => 'biblio_secondary_title', + 'volume' => 'biblio_volume', + 'number' => 'biblio_number', + 'year' => 'biblio_year', + 'note' => 'biblio_notes', + 'month' => 'biblio_date', + 'pages' => 'biblio_pages', + 'publisher' => 'biblio_publisher', + 'school' => 'biblio_publisher', + 'organization' => 'biblio_publisher', + 'institution' => 'biblio_publisher', + 'type' => 'biblio_type_of_work', + 'edition' => 'biblio_edition', + 'chapter' => 'biblio_section', + 'address' => 'biblio_place_published', + 'abstract' => 'biblio_abst_e', + 'keywords' => 'biblio_keywords', + 'isbn' => 'biblio_isbn', + 'issn' => 'biblio_issn', + 'doi' => 'biblio_doi', + 'url' => 'biblio_url', + + ) + ); + + $map['format'] = 'bibtex'; + return $map; + +} + +function _save_bibtex_maps() { + $typemap = _get_bibtex_type_map(); + $typenames = _get_bibtex_type_names(); + $fieldmap = _get_bibtex_field_map(); + $maps = array_merge($typemap, $typenames, $fieldmap); + biblio_save_map($maps); +} + +function _reset_bibtex_map($type) { + $count = db_query("SELECT COUNT(*) FROM {biblio_type_maps} WHERE format='bibtex'")->fetchField(); + if ($count && $type) { //update + $function = '_get_bibtex_' . $type; + if (!function_exists($function)) return; + $map = $function(); + db_update('biblio_type_maps') + ->fields($map) + ->condition('format', 'bibtex') + ->execute(); + } + else { // install + db_delete('biblio_type_maps') + ->condition('format', 'bibtex') + ->execute(); + _save_bibtex_maps(); + } +} + +function biblio_bibtex_schema() { + $schema = array(); + $schema['biblio_bibtex'] = array( + 'fields' => array( + 'nid' => array('type' => 'int', 'not null' => TRUE), + 'biblio_bibtex_md5' => array('type' => 'char', 'length' => 32, 'not null' => TRUE), + 'biblio_bibtex_id' => array('type' => 'varchar', 'length' => 255, 'not null' => FALSE), + ), + 'primary key' => array('nid'), + ); + return $schema; +} + +function biblio_bibtex_update_7001() { + if (!db_field_exists('biblio_bibtex', 'biblio_bibtex_id')) { + $spec = array('type' => 'varchar', 'length' => 255, 'not null' => FALSE); + db_add_field('biblio_bibtex', 'biblio_bibtex_id', $spec); + } +} + + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/bibtexParse/biblio_bibtex.module --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/bibtexParse/biblio_bibtex.module Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,455 @@ + 2, + 'path' => drupal_get_path('module', 'biblio_bibtex') . '/views', + ); +} +/* + * add the BibTex option to the option list of the biblio_import_form + * the key is the module name use by module_invoke to call hook_biblio_import + * module_invoke('biblio_bibtex', 'biblio_import',...) + */ +function biblio_bibtex_biblio_import_options() { + return array('biblio_bibtex' => t('BibTex')); +} +function biblio_bibtex_biblio_mapper_options() { + return array( + 'bibtex' => array( + 'title' => t('BibTex'), + 'export' => TRUE, + ) + ); +} + +function biblio_bibtex_form_biblio_node_form_alter(&$form, &$form_state) { + global $user; + if (!$form_state['submitted'] && !isset($form_state['values']) && !isset($form['#node']->nid)) { + if (!$form_state['submitted']) { + $form['biblio_cut_paste'] = array( + '#type' => 'fieldset', + '#title' => t('Paste BibTex Record'), + '#weight' => -20, + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + $form['biblio_cut_paste']['paste_data_bibtex'] = array( + '#type' => 'textarea', + '#title' => t('BibTex'), + '#required' => FALSE, + '#default_value' => isset($form_state['values']['paste_data_bibtex']) ? $form_state['values']['paste_data_bibtex'] : '', + '#description' => t('Paste a BibTex entry here'), + '#size' => 60, + '#weight' => -4 + ); + $form['biblio_cut_paste']['paste_submit'] = array( + '#type' => 'submit', + '#value' => t('Populate using BibTex'), + '#submit' => array('biblio_bibtex_form_biblio_node_form_submit') + ); + } + } + $biblio_bibtex_id = (isset($form_state['values']['biblio_bibtex_id'])) ? $form_state['values']['biblio_bibtex_id'] : ''; + $biblio_bibtex_md5 = (isset($form_state['values']['biblio_bibtex_md5'])) ? $form_state['values']['biblio_bibtex_md5'] : ''; + $form['biblio_bibtex_id'] = array('#type' => 'value', '#value' => $biblio_bibtex_id); + $form['biblio_bibtex_md5'] = array('#type' => 'value', '#value' => $biblio_bibtex_md5); +} + +function biblio_bibtex_form_biblio_node_form_submit($form, &$form_state) { + global $user; + $node_data = array(); + $dups = array(); + + if (strlen($form_state['values']['paste_data_bibtex'])) { + list($node_data, $dups) = biblio_bibtex_biblio_import($form_state['values']['paste_data_bibtex'], array(), FALSE, NULL, FALSE, TRUE); + } + if (!empty($node_data) && is_object($node_data[0])) { + $form_state['values'] = array_merge($form_state['values'], (array)$node_data[0]); + $form_state['input']['biblio_type'] = $form_state['biblio_type'] = $node_data[0]->biblio_type; + +// $form_state['storage']['biblio_type'] = $node_data[0]->biblio_type; + } + elseif (!empty($dups)) { + $message = t('The bibtex node that you are trying to paste into the form already exists in the database, see !url', array('!url' => l('node/' . $dups[0], 'node/' . $dups[0]))); + form_set_error('paste_data_bibtex', $message); + } + $form_state['rebuild'] = TRUE; + + return; +} + +function biblio_bibtex_biblio_export_options() { + return array('bibtex' => t('BibTex')); +} + +function biblio_bibtex_node_view($node, $view_mode) { + if ($node->type == 'biblio') { + switch ($view_mode) { + case 'full': + case 'teaser': + $links = biblio_bibtex_biblio_export_link($node->nid); + $node->content['links']['biblio_bibtex'] = array( + '#links' => $links, + '#attributes' => array('class' => array('links', 'inline')), + ); + } + } +} + +/** + * Creates a link to export a node (or view) in BibTEX format + * + * @param $base this is the base url (defaults to /biblio) + * @param $nid the node id, if NULL then the current view is exported + * @return a link (BibTEX) + */ +function biblio_bibtex_biblio_export_link($nid = NULL, $filter = array()) { + $show_link = variable_get('biblio_export_links', array('bibtex' => TRUE)); + if (!isset($show_link['bibtex']) || !biblio_access('export')) return array(); + $base = variable_get('biblio_base', 'biblio'); + + if (module_exists('popups') && !empty($nid)) { + $link = array( + 'attributes' => array( + 'class' => 'popups', + 'title' => t("Click to get the BibTEX output"))); + } + else { + $link = array( + 'attributes' => array( + 'title' => t("Click to download the BibTEX formatted file"))); + } + $link['attributes'] += array('rel' => 'nofollow'); + + $link['href'] = "$base/export/bibtex" ; + if (!empty($nid)) { + $link['href'] .= '/' . $nid; + } + $link['title'] = t('BibTex'); + + if (empty($nid) && !empty($filter)) { // add any filters which may be on the current page + $link['query'] = $filter; + } + + return array('biblio_bibtex' => $link); +} + +function biblio_bibtex_node_delete($node) { + if ($node->type != 'biblio') { + return; + } + db_delete('biblio_bibtex') + ->condition('nid', $node->nid) + ->execute(); +} + +function biblio_bibtex_node_insert($node) { + if ($node->type != 'biblio') { + return; + } + if (!isset($node->biblio_bibtex_md5)) { + return; + } + drupal_write_record('biblio_bibtex', $node); +} + +function biblio_bibtex_biblio_import($file, $terms = array(), $batch = FALSE, $session_id = NULL, $save = TRUE, $string = FALSE) { + $nids = array(); + $dups = array(); + + module_load_include('php', 'biblio_bibtex', 'PARSEENTRIES'); + $bibtex = new PARSEENTRIES(); + + if ($string) { + $bibtex->loadBibtexString($file); + } + else { + $bibtex->openBib($file->uri); + } + + $bibtex->extractEntries(); + + if ($bibtex->count) { + $entries =& $bibtex->getEntries(); + list($nids, $dups) = _biblio_bibtex_import($entries, $terms, $batch, $session_id, $save); + } + return array($nids, $dups); +} +function biblio_bibtex_biblio_export($nids) { + if (module_exists('popups') && $nid) { + $popup = TRUE; + } + else { + $popup = FALSE; + drupal_add_http_header('Content-type', 'application/text; charset=utf-8'); + drupal_add_http_header('Content-Disposition', 'attachment; filename="Biblio-Bibtex.bib"'); + } + + $nodes = node_load_multiple($nids, array(), TRUE); + foreach ($nodes as $node) { + if (!$popup) { + print _biblio_bibtex_export($node); + } + else{ + $popup_data .= _biblio_bibtex_export($node); + } + } + if ($popup && !empty($popup_data)) return '

    ' . $popup_data . '
    '; +} + +function _biblio_bibtex_import($entries, $terms = array(), $batch = FALSE, $session_id = NULL, $save = TRUE) { + $nids = array(); + $dups = array(); + + foreach ($entries as $entry) { + $node = new stdClass(); + $node->biblio_contributors = array(); + $node->biblio_type = _biblio_bibtex_type_map($entry['bibtexEntryType'], 'import'); + switch ($entry['bibtexEntryType']) { + case 'mastersthesis': + $node->biblio_type_of_work = 'masters'; + break; + case 'phdthesis': + $node->biblio_type_of_work = 'phd'; + break; + } + if (!empty($entry['author'])) { + // split on ' and ' + $author_array = preg_split("/\s(and|&)\s/i", trim($entry['author'])); + foreach ($author_array as $key => $author) { + // discard braces as biblio uses its own heuristic to split up human names, + // and the braces get in the way + $author = str_replace(array('{', '}'), array('', ''), $author); + $node->biblio_contributors[]= array('name' => $author, 'auth_category' => 1, 'auth_type' => _biblio_get_auth_type(1, $node->biblio_type)); + } + } + + $node->biblio_citekey = (!empty($entry['bibtexCitation'])) ? $entry['bibtexCitation'] : NULL; + if (!empty($entry['editor'])) { + $author_array = preg_split("/\s(and|&)\s/i", trim($entry['editor'])); + foreach ($author_array as $key => $author) { + // discard braces as biblio uses its own heuristic to split up human names, + // and the braces get in the way + $author = str_replace(array('{', '}'), array('', ''), $author); + $node->biblio_contributors[]= array('name' => $author, 'auth_category' => 2, 'auth_type' => _biblio_get_auth_type(2, $node->biblio_type)); + } + } + + $node->biblio_secondary_title = (!empty($entry['journal'])) ? $entry['journal'] : NULL; + if (!empty($entry['booktitle'])) $node->biblio_secondary_title = $entry['booktitle']; + if (!empty($entry['series'])) { + if (!empty($entry['booktitle'])) { + $node->biblio_tertiary_title = $entry['series']; + } + else { + $node->biblio_secondary_title = $entry['series']; + } + } + $node->biblio_volume = (!empty($entry['volume'])) ? $entry['volume'] : NULL; + $node->biblio_number = (!empty($entry['number'])) ? $entry['number'] : NULL; + $node->biblio_year = (!empty($entry['year'])) ? $entry['year'] : NULL; + $node->biblio_notes = (!empty($entry['note'])) ? $entry['note'] : NULL; + $node->biblio_date = (!empty($entry['month'])) ? $entry['month'] : NULL; + $node->biblio_pages = (!empty($entry['pages'])) ? $entry['pages'] : NULL; + $node->biblio_publisher = (!empty($entry['publisher'])) ? $entry['publisher'] : NULL; + if (!empty($entry['organization'])) $node->biblio_publisher = $entry['organization']; + if (!empty($entry['school'])) $node->biblio_publisher = $entry['school']; + if (!empty($entry['institution'])) $node->biblio_publisher = $entry['institution']; + $node->title = (!empty($entry['title'])) ? $entry['title'] : NULL; + $node->biblio_type_of_work .= (!empty($entry['type'])) ? $entry['type'] : NULL; + $node->biblio_edition = (!empty($entry['edition'])) ? $entry['edition'] : NULL; + $node->biblio_section = (!empty($entry['chapter'])) ? $entry['chapter'] : NULL; + $node->biblio_place_published = (!empty($entry['address'])) ? $entry['address'] : NULL; + $node->biblio_abst_e = (!empty($entry['abstract'])) ? $entry['abstract'] : NULL; + if (!empty($entry['keywords'])) { + if (strpos($entry['keywords'], ';')) { + $entry['keywords'] = str_replace(';', ',', $entry['keywords']); + } + $node->biblio_keywords = explode(',', $entry['keywords']); + } + $node->biblio_isbn = (!empty($entry['isbn'])) ? $entry['isbn'] : NULL; + $node->biblio_issn = (!empty($entry['issn'])) ? $entry['issn'] : NULL; + $node->biblio_url = (!empty($entry['url'])) ? $entry['url'] : NULL; + $node->biblio_doi = (!empty($entry['doi'])) ? $entry['doi'] : NULL; + if (module_exists('biblio_pm')) { + $node->biblio_pubmed_id = (!empty($entry['pmid'])) ? $entry['pmid'] : NULL; + $node->biblio_pubmed_md5 = ''; + } + + $node->biblio_bibtex_md5 = md5(serialize($node)); + $node->biblio_import_type = 'bibtex'; + + if (!($dup = biblio_bibtex_check_md5($node->biblio_bibtex_md5))) { + if ($save) { + biblio_save_node($node, $terms, $batch, $session_id, $save); + $nids[] = (!empty($node->nid))? $node->nid : NULL; + } + else { // return the whole node if we are not saveing to the DB (used for the paste function on the input form) + $nids[] = $node; + } + } + else { + $dups[] = $dup; + } + } + return array($nids, $dups); +} +/** + * Export data in bibtex format. + * + * @param $result + * a database result set pointer + * @return + * none + */ +function _biblio_bibtex_export($node) { + static $converter = NULL; + + $bibtex = ''; + $type = "article"; + $journal = $series = $booktitle = $school = $organization = $institution = NULL; + $type = _biblio_bibtex_type_map($node->biblio_type); + switch ($node->biblio_type) { + case 100 : + $series = $node->biblio_secondary_title; + $organization = $node->biblio_publisher; + break; + case 101 : + case 103 : + $booktitle = $node->biblio_secondary_title; + $organization = $node->biblio_publisher; + $series = $node->biblio_tertiary_title; + break; + case 108 : + $school = $node->biblio_publisher; + $node->biblio_publisher = NULL; + if (stripos($node->biblio_type_of_work, 'masters')) { + $type = "mastersthesis"; + } + break; + case 109 : + $institution = $node->biblio_publisher; + $node->biblio_publisher = NULL; + break; + case 102 : + default: + $journal = $node->biblio_secondary_title; + break; + } + + $bibtex .= '@' . $type . ' {'; + $bibtex .= ($node->biblio_citekey) ? $node->biblio_citekey : ""; + $bibtex .= _biblio_bibtex_format_entry('title', $node->title); + $bibtex .= _biblio_bibtex_format_entry('journal', $journal); + $bibtex .= _biblio_bibtex_format_entry('booktitle', $booktitle); + $bibtex .= _biblio_bibtex_format_entry('series', $series); + $bibtex .= _biblio_bibtex_format_entry('volume', $node->biblio_volume); + $bibtex .= _biblio_bibtex_format_entry('number', $node->biblio_number); + $bibtex .= _biblio_bibtex_format_entry('year', $node->biblio_year); + $bibtex .= _biblio_bibtex_format_entry('note', $node->biblio_notes); + $bibtex .= _biblio_bibtex_format_entry('month', $node->biblio_date); + $bibtex .= _biblio_bibtex_format_entry('pages', $node->biblio_pages); + $bibtex .= _biblio_bibtex_format_entry('publisher', $node->biblio_publisher); + $bibtex .= _biblio_bibtex_format_entry('school', $school); + $bibtex .= _biblio_bibtex_format_entry('organization', $organization); + $bibtex .= _biblio_bibtex_format_entry('institution', $institution); + $bibtex .= _biblio_bibtex_format_entry('type', $node->biblio_type_of_work); + $bibtex .= _biblio_bibtex_format_entry('edition', $node->biblio_edition); + $bibtex .= _biblio_bibtex_format_entry('chapter', $node->biblio_section); + $bibtex .= _biblio_bibtex_format_entry('address', $node->biblio_place_published); + $bibtex .= _biblio_bibtex_format_entry('abstract', $node->biblio_abst_e); + + $kw_array = array(); + if (!empty($node->terms)) { + foreach ($node->terms as $term) { + $kw_array[] = $term->name; + } + } + if (!empty($node->biblio_keywords)) { + foreach ($node->biblio_keywords as $term) { + $kw_array[] = $term; + } + } + if (!empty($kw_array)) { + $kw_array = array_unique($kw_array); + $bibtex .= _biblio_bibtex_format_entry('keywords', implode(', ', $kw_array)); + } + + $bibtex .= _biblio_bibtex_format_entry('isbn', $node->biblio_isbn); + $bibtex .= _biblio_bibtex_format_entry('issn', $node->biblio_issn); + $bibtex .= _biblio_bibtex_format_entry('doi', $node->biblio_doi); + $bibtex .= _biblio_bibtex_format_entry('url', $node->biblio_url); + + if (!empty ($node->upload) && count($node->upload['und']) && user_access('view uploaded files')) { + foreach ($node->upload['und'] as $file) { + $attachments[] = file_create_url($file['uri']); + } + $bibtex .= _biblio_bibtex_format_entry('attachments', implode(' , ', $attachments)); + } + + $a = $e = $authors = array(); + if ($authors = biblio_get_contributor_category($node->biblio_contributors, 1)) { + foreach ($authors as $auth) $a[] = trim($auth['name']); + } + if ($authors = biblio_get_contributor_category($node->biblio_contributors, 2)) { + foreach ($authors as $auth) $e[] = trim($auth['name']); + } + $a = implode(' and ', $a); + $e = implode(' and ', $e); + if (!empty ($a)) $bibtex .= _biblio_bibtex_format_entry('author', $a); + if (!empty ($e)) $bibtex .= _biblio_bibtex_format_entry('editor', $e); + $bibtex .= "\n}\n"; + + + //now convert any special characters to the latex equivelents... + if (!isset($converter)) { + module_load_include('php', 'biblio_bibtex', 'PARSEENTRIES'); + include_once(drupal_get_path('module', 'biblio_bibtex') . '/transtab_unicode_bibtex.inc.php'); + $converter = new PARSEENTRIES(); + } + $bibtex = $converter->searchReplaceText(_biblio_bibtex_get_transtab(), $bibtex, FALSE); + + return $bibtex; +} + +function _biblio_bibtex_format_entry($key, $value) { + return !empty($value) ? ",\n\t$key = {" . $value . "}" : ''; +} + +function _biblio_bibtex_type_map($type, $direction = 'export') { + static $map = array(); + if (empty($map)) { + $map = biblio_get_map('type_map', 'bibtex'); + } + if ($direction == 'export') { + return ($type = array_search($type, $map)) ? $type : 'article'; + } + else { + return (isset($map[$type])) ? $map[$type] : 129; //return the biblio type or 129 (Misc) if type not found + } +} +function biblio_bibtex_bibtex_map_reset($type = NULL) { + module_load_include('install', 'biblio_bibtex', 'biblio_bibtex'); + _reset_bibtex_map($type); +} + +function biblio_bibtex_check_md5($md5) { + static $bibtex_md5s = array(); + if (empty($bibtex_md5s)) { + $result = db_query("SELECT * FROM {biblio_bibtex} "); + foreach ($result as $row ) { + $bibtex_md5s[$row->biblio_bibtex_md5] = $row->nid; + } + } + if (isset($bibtex_md5s[$md5])) { + return $bibtex_md5s[$md5]; + } + else { + $bibtex_md5s[$md5] = TRUE; // gaurd against duplicates in the same import + return; + } +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/bibtexParse/transtab_latex_unicode.inc.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/bibtexParse/transtab_latex_unicode.inc.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,256 @@ + for more info about Unicode and transtab. +function get_transtab_latex_unicode() { +return array( + '\\$\\\\#\\$' => "#", + "\\\\%" => "%", + "\\\\&" => "&", + "(? " ", + "\\{\\\\textexclamdown\\}" => "¡", + "\\{\\\\textcent\\}" => "¢", + "\\{\\\\textsterling\\}" => "£", + "\\{\\\\textyen\\}" => "¥", + "\\{\\\\textbrokenbar\\}" => "¦", + "\\{\\\\textsection\\}" => "§", + "\\{\\\\textasciidieresis\\}" => "¨", + "\\{\\\\textcopyright\\}" => "©", + "\\{\\\\textordfeminine\\}" => "ª", + "\\{\\\\guillemotleft\\}" => "«", + "\\{\\\\textlnot\\}" => "¬", + "\\{\\\\textregistered\\}" => "®", + "\\{\\\\textasciimacron\\}" => "¯", + "\\{\\\\textdegree\\}" => "°", + "\\{\\\\textpm\\}" => "±", + "\\{\\\\texttwosuperior\\}" => "²", + "\\{\\\\textthreesuperior\\}" => "³", + "\\{\\\\textasciiacute\\}" => "´", + "\\{\\\\textmu\\}" => "µ", + "\\{\\\\textparagraph\\}" => "¶", + "\\{\\\\textperiodcentered\\}" => "·", + "\\{\\\\c\\\\ \\}" => "¸", + "\\{\\\\textonesuperior\\}" => "¹", + "\\{\\\\textordmasculine\\}" => "º", + "\\{\\\\guillemotright\\}" => "»", + "\\{\\\\textonequarter\\}" => "¼", + "\\{\\\\textonehalf\\}" => "½", + "\\{\\\\textthreequarters\\}" => "¾", + "\\{\\\\textquestiondown\\}" => "¿", + "\\{?\\\\`\\{?A\\}?\\}?" => "À", + "\\{?\\\\'\\{?A\\}?\\}?" => "Á", + "\\{?\\\\\\^\\{?A\\}?\\}?" => "Â", + "\\{?\\\\~\\{?A\\}?\\}?" => "Ã", + "\\{?\\\\\"\\{?A\\}?\\}?" => "Ä", + "\\\\AA\\ +" => "Å", + "\\{?\\\\r\s\\{?A\\}?\\}?" => "Å", + "\\{?\\\\AE\\}?" => "Æ", + "\\{?\\\\c\sC\\}?" => "Ç", + "\\{?\\\\`\\{?E\\}?\\}?" => "È", + "\\{?\\\\'\\{?E\\}?\\}?" => "É", + "\\{?\\\\\\^\\{?E\\}?\\}?" => "Ê", + "\\{?\\\\\"\\{?E\\}?\\}?" => "Ë", + "\\{?\\\\`\\{?I\\}?\\}?" => "Ì", + "\\{?\\\\'\\{?I\\}?\\}?" => "Í", + "\\{?\\\\\\^\\{?I\\}?\\}?" => "Î", + "\\{?\\\\\"\\{?I\\}?\\}?" => "Ï", + "\\{?\\\\DH\\}?" => "Ð", + "\\{?\\\\~\\{?N\\}?\\}?" => "Ñ", + "\\{?\\\\`\\{?O\\}?\\}?" => "Ò", + "\\{?\\\\'\\{?O\\}?\\}?" => "Ó", + "\\{?\\\\\\^\\{?O\\}?\\}?" => "Ô", + "\\{?\\\\~\\{?O\\}?\\}?" => "Õ", + "\\{?\\\\\"\\{?O\\}?\\}?" => "Ö", + "\\{?\\\\texttimes\\}?" => "×", + "\\\\O\\ +" => "Ø", + "\\{?\\\\O\\}?" => "Ø", + "\\{?\\\\`\\{?U\\}?\\}?" => "Ù", + "\\{?\\\\'\\{?U\\}?\\}?" => "Ú", + "\\{?\\\\\\^\\{?U\\}?\\}?" => "Û", + "\\{?\\\\\"\\{?U\\}?\\}?" => "Ü", + "\\{?\\\\'\\{?Y\\}?\\}?" => "Ý", + "\\{?\\\\TH\\}?" => "Þ", + "\\{?\\\\ss\\{?\\}?\\}?" => "ß", + "\\{?\\\\`\\{?a\\}?\\}?" => "à", + "\\{?\\\\'\\{?a\\}?\\}?" => "á", + "\\{?\\\\\\^\\{?a\\}?\\}?" => "â", + "\\{?\\\\~\\{?a\\}?\\}?" => "ã", + "\\{?\\\\\"\\{?a\\}?\\}?" => "ä", + "\\\\aa\\ +" => "å", + "\\{?\\\\r\s\\{?a\\}?\\}?" => "å", + "\\{?\\\\ae\\}?" => "æ", + "\\{?\\\\c\\{?c\\}?\\}?" => "ç", + "\\{?\\\\`\\{?e\\}?\\}?" => "è", + "\\{?\\\\'\\{?e\\}?\\}?" => "é", + "\\{?\\\\\\^\\{?e\\}?\\}?" => "ê", + "\\{?\\\\\"\s?\\{?e\\}?\\}?" => "ë", + "\\{?\\\\`\\{?i\\}?\\}?" => "ì", + "\\{?\\\\'\\{?i\\}?\\}?" => "í", + "\\{?\\\\\\^\\{?i\\}?\\}?" => "î", + "\\{?\\\\\"\\{?i\\}?\\}?" => "ï", + "\\{?\\\\dh\\}?" => "ð", + "\\{?\\\\~\\{?n\\}?\\}?" => "ñ", + "\\{?\\\\`\\{?o\\}?\\}?" => "ò", + "\\{?\\\\'\\{?o\\}?\\}?" => "ó", + "\\{?\\\\\\^\\{?o\\}?\\}?" => "ô", + "\\{?\\\\~\\{?o\\}?\\}?" => "õ", + "\\{?\\\\\"\\{?o\\}?\\}?" => "ö", + "\\{?\\\\textdiv\\}?" => "÷", + "\\\\o\\ +" => "ø", + "\\{?\\\\o\\}?" => "ø", + "\\{?\\\\`\\{?u\\}?\\}?" => "ù", + "\\{?\\\\'\\{?u\\}?\\}?" => "ú", + "\\{?\\\\\\^\\{?u\\}?\\}?" => "û", + "\\{?\\\\\"\\{?u\\}?\\}?" => "ü", + "\\{?\\\\'\\{?y\\}?\\}?" => "ý", + "\\{?\\\\th\\}?" => "þ", + "\\{?\\\\\"\\{?y\\}?\\}?" => "ÿ", + "\\{?\\\\u\\{?A\\}?\\}?" => "Ă", + "\\{?\\\\u\\{?a\\}?\\}?" => "ă", +// "\\{?\\\\k\\{?A\\}?||}?" => "Ą", + "\\{?\\\\k\\{?a\\}?\\}?" => "ą", + "\\{?\\\\'\\{?C\\}?\\}?" => "Ć", + "\\{?\\\\'\\{?c\\}?\\}?" => "ć", + "\\{?\\\\v\\{?C\\}?\\}?" => "Č", + "\\{?\\\\v\\{?c\\}?\\}?" => "č", + "\\{?\\\\v\\{?c\\}?\\}?" => "č", + "\\{?\\\\v\\{?D\\}?\\}?" => "Ď", + "\\{?\\\\v\\{?d\\}?\\}?" => "ď", + "\\{?\\\\DJ\\}?" => "Đ", + "\\{?\\\\dj\\}?" => "đ", + "\\{?\\\\k\\{?E\\}?\\}?" => "Ę", + "\\{?\\\\k\\{?e\\}?\\}?" => "ę", + "\\{?\\\\v\\{?E\\}?\\}?" => "Ě", + "\\{?\\\\v\\{?e\\}?\\}?" => "ě", + "\\{?\\\\u\s?\\{?e\\}?\\}?" => "ĕ", + "\\{?\\\\u\\{?G\\}?\\}?" => "Ğ", + "\\{?\\\\u\\{?g\\}?\\}?" => "ğ", + "\\{?\\\\.\\{?g\\}?\\}?" => "ġ", + "\\{?\\\\.\\{?I\\}?\\}?" => "İ", + "\\\\'\\{?\\\\i\\}?" => "í", + "\\{?\\\\i\\}?" => "ı", + "\\{?\\\\'\\{?L\\}?\\}?" => "Ĺ", +// "\\{?\\\\'\\{?l\\}?||}?" => "ĺ", + "\\{?\\\\v\\{?L\\}?\\}?" => "Ľ", + "\\{?\\\\v\\{?l\\}?\\}?" => "ľ", + "\\{?\\\\L\\}?" => "Ł", + "\\{?\\\\l\\}?" => "ł", + "\\{?\\\\'\\{?N\\}?\\}?" => "Ń", + "\\{?\\\\'\\{?n\\}?\\}?" => "ń", + "\\{?\\\\v\\{?N\\}?\\}?" => "Ň", + "\\{?\\\\v\\{?n\\}?\\}?" => "ň", + "\\{?\\\\NG\\}?" => "Ŋ", + "\\{?\\\\ng\\}?" => "ŋ", + "\\{?\\\\H\\{?O\\}?\\}?" => "Ő", + "\\{?\\\\H\\{?o\\}?\\}?" => "ő", + "\\{?\\\\OE\\}?" => "Œ", + "\\{?\\\\oe\\}?" => "œ", + "\\{?\\\\'\\{?R\\}?\\}?" => "Ŕ", + "\\{?\\\\'\\{?r\\}?\\}?" => "ŕ", + "\\{?\\\\v\\{?R\\}?\\}?" => "Ř", + "\\{?\\\\v\\{?r\\}?\\}?" => "ř", + "\\{?\\\\'\\{?S\\}?\\}?" => "Ś", + "\\{?\\\\'\\{?s\\}?\\}?" => "ś", + "\\{?\\\\c\\{?S\\}?\\}?" => "Ş", + "\\{?\\\\c\\{?s\\}?\\}?" => "ş", + "\\{?\\\\v\\{?S\\}?\\}?" => "Š", + "\\{?\\\\v\\{?s\\}?\\}?" => "š", + "\\{?\\\\c\\{?T\\}?\\}?" => "Ţ", + "\\{?\\\\c\\{?t\\}?\\}?" => "ţ", + "\\{?\\\\v\\{?T\\}?\\}?" => "Ť", + "\\{?\\\\v\\{?t\\}?\\}?" => "ť", + "\\{?\\\\r\\{?U\\}?\\}?" => "Ů", + "\\{?\\\\r\\{?u\\}?\\}?" => "ů", + "\\{?\\\\H\\{?U\\}?\\}?" => "Ű", + "\\{?\\\\H\\{?u\\}?\\}?" => "ű", + "\\{?\\\\\"\\{?Y\\}?\\}?" => "Ÿ", + "\\{?\\\\'\\{?Z\\}?\\}?" => "Ź", + "\\{?\\\\'\\{?z\\}?\\}?" => "ź", + "\\{?\\\\.\\{?Z\\}?\\}?" => "Ż", + "\\{?\\\\.\\{?z\\}?\\}?" => "ż", + "\\{?\\\\v\\{?Z\\}?\\}?" => "Ž", + "\\{?\\\\v\\{?z\\}?\\}?" => "ž", + "\\{?\\\\textflorin\\}?" => "ƒ", + "\\{?\\\\textasciicircum\\}?" => "ˆ", + "\\{?\\\\textacutedbl\\}?" => "˝", + "\\{?\\\\textendash\\}?|--" => "–", + "\\{?\\\\textemdash\\}?|---" => "—", + "\\{?\\\\textbardbl\\}?" => "‖", + "\\{?\\\\textunderscore\\}?" => "‗", + "\\{?\\\\textquoteleft\\}?" => "‘", + "\\{?\\\\textquoteright\\}?" => "’", + "\\{?\\\\quotesinglbase\\}?" => "‚", + "\\{?\\\\textquotedblleft\\}?" => "“", + "\\{?\\\\textquotedblright\\}?" => "”", + "\\{?\\\\quotedblbase\\}?" => "„", + "\\{?\\\\textdagger\\}?" => "†", + "\\{?\\\\textdaggerdbl\\}?" => "‡", + "\\{?\\\\textbullet\\}?" => "•", + "\\{?\\\\textellipsis\\}?" => "…", + "\\{?\\\\textperthousand\\}?" => "‰", + "\\{?\\\\guilsinglleft\\}?" => "‹", + "\\{?\\\\guilsinglright\\}?" => "›", + "\\{?\\\\textfractionsolidus\\}?" => "⁄", + '\\$\\^\\{0\\}\\$' => "⁰", + '\\$\\^\\{4\\}\\$' => "⁴", + '\\$\\^\\{5\\}\\$' => "⁵", + '\\$\\^\\{6\\}\\$' => "⁶", + '\\$\\^\\{7\\}\\$' => "⁷", + '\\$\\^\\{8\\}\\$' => "⁸", + '\\$\\^\\{9\\}\\$' => "⁹", + '\\$\\^\\{+\\}\\$' => "⁺", + '\\$\\^\\{-\\}\\$' => "⁻", + '\\$\\^\\{=\\}\\$' => "⁼", + '\\$\\^\\{n\\}\\$' => "ⁿ", + '\\$_\\{0\\}\\$' => "₀", + '\\$_\\{1\\}\\$' => "₁", + '\\$_\\{2\\}\\$' => "₂", + '\\$_\\{3\\}\\$' => "₃", + '\\$_\\{4\\}\\$' => "₄", + '\\$_\\{5\\}\\$' => "₅", + '\\$_\\{6\\}\\$' => "₆", + '\\$_\\{7\\}\\$' => "₇", + '\\$_\\{8\\}\\$' => "₈", + '\\$_\\{9\\}\\$' => "₉", + '\\$_\\{+\\}\\$' => "₊", + '\\$_\\{-\\}\\$' => "₋", + '\\$_\\{=\\}\\$' => "₌", + "\\{?\\\\texteuro\\}?" => "€", + "\\{?\\\\textcelsius\\}?" => "℃", + "\\{?\\\\textnumero\\}?" => "№", + "\\{?\\\\textcircledP\\}?" => "℗", + "\\{?\\\\textservicemark\\}?" => "℠", + "\\{?\\\\texttrademark\\}?" => "™", + "\\{?\\\\textohm\\}?" => "Ω", + "\\{?\\\\textestimated\\}?" => "℮", + "\\{?\\\\textleftarrow\\}?" => "←", + "\\{?\\\\textuparrow\\}?" => "↑", + "\\{?\\\\textrightarrow\\}?" => "→", + "\\{?\\\\textdownarrow\\}?" => "↓", + '\\$\\\\infty\\$' => "∞", + "\\{?\\\\textlangle\\}?" => "〈", + "\\{?\\\\textrangle\\}?" => "〉", + "\\{?\\\\textvisiblespace\\}?" => "␣", + "\\{?\\\\textopenbullet\\}?" => "◦", + "\\{?\\\\Delta\\}?" => "Δ", + "\\{?\\\\iota\\}?" => "ι", + "\\{?\\\\omicron\\}?" =>"ο", + "\\{?\\\\mu\\}?" => "μ", + "\\{?\\\\eta\\}?" => "η", + "\\{?\\\\delta\\}?" => "δ", + "\\{?\\\\varsigma\\}?" => "ς", + "\\{?\\\\Sigma\\}?" => "Σ", + "\\{?\\\\pi\\}?" => "π", + "\\{?\\\\nu\\}?" => "ν", + "\\{?\\\\epsilon\\}?" => "ε", + "\\{?\\\\lambda\\}?" => "λ", + "\\{?\\\\=\\{?o\\}?\\}?" => "ō", +); +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/bibtexParse/transtab_unicode_bibtex.inc.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/bibtexParse/transtab_unicode_bibtex.inc.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,849 @@ + for more info about Unicode and transtab. + +function _biblio_bibtex_get_transtab() { + + return array( + "(? '$\\#$', + "(? "\\%", + "(? "\\&", + "(? "{\\textquoteright}", + "(? "{\\textquoteleft}", + " " => "~", + "¡" => "{\\textexclamdown}", + "¢" => "{\\textcent}", + "£" => "{\\textsterling}", + "¥" => "{\\textyen}", + "¦" => "{\\textbrokenbar}", + "§" => "{\\textsection}", + "¨" => "{\\textasciidieresis}", + "©" => "{\\textcopyright}", + "ª" => "{\\textordfeminine}", + "«" => "{\\guillemotleft}", + "¬" => "{\\textlnot}", + "­" => "-", + "®" => "{\\textregistered}", + "¯" => "{\\textasciimacron}", + "°" => "{\\textdegree}", + "±" => "{\\textpm}", + "²" => "{\\texttwosuperior}", + "³" => "{\\textthreesuperior}", + "´" => "{\\textasciiacute}", + "µ" => "{\\textmu}", + "¶" => "{\\textparagraph}", + "·" => "{\\textperiodcentered}", + "¸" => "{\\c\\ }", + "¹" => "{\\textonesuperior}", + "º" => "{\\textordmasculine}", + "»" => "{\\guillemotright}", + "¼" => "{\\textonequarter}", + "½" => "{\\textonehalf}", + "¾" => "{\\textthreequarters}", + "¿" => "{\\textquestiondown}", + "À" => "{\\`A}", + "Á" => "{\\'A}", + "Â" => "{\\^A}", + "Ã" => "{\\~A}", + "Ä" => "{\\\"A}", + "Å" => "{\\r A}", + "Æ" => "{\\AE}", + "Ç" => "{\\c C}", + "È" => "{\\`E}", + "É" => "{\\'E}", + "Ê" => "{\\^E}", + "Ë" => "{\\\"E}", + "Ì" => "{\\`I}", + "Í" => "{\\'I}", + "Î" => "{\\^I}", + "Ï" => "{\\\"I}", + "Ð" => "{\\DH}", + "Ñ" => "{\\~N}", + "Ò" => "{\\`O}", + "Ó" => "{\\'O}", + "Ô" => "{\\^O}", + "Õ" => "{\\~O}", + "Ö" => "{\\\"O}", + "×" => "{\\texttimes}", + "Ø" => "{\\O}", + "Ù" => "{\\`U}", + "Ú" => "{\\'U}", + "Û" => "{\\^U}", + "Ü" => "{\\\"U}", + "Ý" => "{\\'Y}", + "Þ" => "{\\TH}", + "ß" => "{\\ss}", + "à" => "{\\`a}", + "á" => "{\\'a}", + "â" => "{\\^a}", + "ã" => "{\\~a}", + "ä" => "{\\\"a}", + "å" => "{\\r a}", + "æ" => "{\\ae}", + "ç" => "{\\c c}", + "è" => "{\\`e}", + "é" => "{\\'e}", + "ê" => "{\\^e}", + "ë" => "{\\\"e}", + "ì" => "{\\`\\i}", + "í" => "{\\'\\i}", + "î" => "{\\^\\i}", + "ï" => "{\\\"\\i}", + "ð" => "{\\dh}", + "ñ" => "{\\~n}", + "ò" => "{\\`o}", + "ó" => "{\\'o}", + "ô" => "{\\^o}", + "õ" => "{\\~o}", + "ö" => "{\\\"o}", + "÷" => "{\\textdiv}", + "ø" => "{\\o}", + "ù" => "{\\`u}", + "ú" => "{\\'u}", + "û" => "{\\^u}", + "ü" => "{\\\"u}", + "ý" => "{\\'y}", + "þ" => "{\\th}", + "ÿ" => "{\\\"y}", + "Ā" => "A", + "ā" => "{\\={a}}", + "Ă" => "{\\u A}", + "ă" => "{\\u a}", + "Ą" => "{\\k A}", + "ą" => "{\\k a}", + "Ć" => "{\\'C}", + "ć" => "{\\'c}", + "Ĉ" => "Ch", + "ĉ" => "ch", + "Ċ" => "C", + "ċ" => "c", + "Č" => "{\\v C}", + "č" => "{\\v c}", + "Ď" => "{\\v D}", + "ď" => "{\\v d}", + "Đ" => "{\\DJ}", + "đ" => "{\\dj}", + "Ē" => "E", + "ē" => "e", + "Ĕ" => "E", + "ĕ" => "e", + "Ė" => "E", + "ė" => "e", + "Ę" => "{\\k E}", + "ę" => "{\\k e}", + "Ě" => "{\\v E}", + "ě" => "{\\v e}", + "Ĝ" => "Gh", + "ĝ" => "gh", + "Ğ" => "{\\u G}", + "ğ" => "{\\u g}", + "Ġ" => "G", + "ġ" => "g", + "Ģ" => "G", + "ģ" => "g", + "Ĥ" => "Hh", + "ĥ" => "hh", + "Ħ" => "H", + "ħ" => "h", + "Ĩ" => "I", + "ĩ" => "i", + "Ī" => "I", + "ī" => "i", + "Ĭ" => "I", + "ĭ" => "i", + "Į" => "I", + "į" => "i", + "İ" => "{\\.I}", + "ı" => "{\\i}", + "IJ" => "IJ", + "ij" => "ij", + "Ĵ" => "Jh", + "ĵ" => "jh", + "Ķ" => "K", + "ķ" => "k", + "ĸ" => "k", + "Ĺ" => "{\\'L}", + "ĺ" => "{\\'l}", + "Ļ" => "L", + "ļ" => "l", + "Ľ" => "{\\v L}", + "ľ" => "{\\v l}", + "Ŀ" => "L·", + "ŀ" => "l·", + "Ł" => "{\\L}", + "ł" => "{\\l}", + "Ń" => "{\\'N}", + "ń" => "{\\'n}", + "Ņ" => "N", + "ņ" => "n", + "Ň" => "{\\v N}", + "ň" => "{\\v n}", + "ʼn" => "'n", + "Ŋ" => "{\\NG}", + "ŋ" => "{\\ng}", + "Ō" => "O", + "ō" => "o", + "Ŏ" => "O", + "ŏ" => "o", + "Ő" => "{\\H O}", + "ő" => "{\\H o}", + "Œ" => "{\\OE}", + "œ" => "{\\oe}", + "Ŕ" => "{\\'R}", + "ŕ" => "{\\'r}", + "Ŗ" => "R", + "ŗ" => "r", + "Ř" => "{\\v R}", + "ř" => "{\\v r}", + "Ś" => "{\\'S}", + "ś" => "{\\'s}", + "Ŝ" => "Sh", + "ŝ" => "sh", + "Ş" => "{\\c S}", + "ş" => "{\\c s}", + "Š" => "{\\v S}", + "š" => "{\\v s}", + "Ţ" => "{\\c T}", + "ţ" => "{\\c t}", + "Ť" => "{\\v T}", + "ť" => "{\\v t}", + "Ŧ" => "T", + "ŧ" => "t", + "Ũ" => "U", + "ũ" => "u", + "Ū" => "U", + "ū" => "u", + "Ŭ" => "U", + "ŭ" => "u", + "Ů" => "{\\r U}", + "ů" => "{\\r u}", + "Ű" => "{\\H U}", + "ű" => "{\\H u}", + "Ų" => "U", + "ų" => "u", + "Ŵ" => "W", + "ŵ" => "w", + "Ŷ" => "Y", + "ŷ" => "y", + "Ÿ" => "{\\\"Y}", + "Ź" => "{\\'Z}", + "ź" => "{\\'z}", + "Ż" => "{\\.Z}", + "ż" => "{\\.z}", + "Ž" => "{\\v Z}", + "ž" => "{\\v z}", + "ſ" => "s", + "ƒ" => "{\\textflorin}", + "Ș" => "S", + "ș" => "s", + "Ț" => "T", + "ț" => "t", + "ʹ" => "'", + "ʻ" => "'", + "ʼ" => "'", + "ʽ" => "'", + "ˆ" => "{\\textasciicircum}", + "ˈ" => "'", + "ˉ" => "-", + "ˌ" => ",", + "ː" => ":", + "˚" => "o", + "˜" => "\\~{}", + "˝" => "{\\textacutedbl}", + "ʹ" => "'", + "͵" => ",", + ";" => ";", + "Ḃ" => "B", + "ḃ" => "b", + "Ḋ" => "D", + "ḋ" => "d", + "Ḟ" => "F", + "ḟ" => "f", + "Ṁ" => "M", + "ṁ" => "m", + "Ṗ" => "P", + "ṗ" => "p", + "Ṡ" => "S", + "ṡ" => "s", + "Ṫ" => "T", + "ṫ" => "t", + "Ẁ" => "W", + "ẁ" => "w", + "Ẃ" => "W", + "ẃ" => "w", + "Ẅ" => "W", + "ẅ" => "w", + "Ỳ" => "Y", + "ỳ" => "y", + " " => " ", + " " => " ", + " " => " ", + " " => " ", + " " => " ", + " " => " ", + " " => " ", + " " => " ", + " " => " ", + " " => " ", + "‐" => "-", + "‑" => "-", + "‒" => "-", + "–" => "{\\textendash}", + "—" => "{\\textemdash}", + "―" => "--", + "‖" => "{\\textbardbl}", + "‗" => "{\\textunderscore}", + "‘" => "{\\textquoteleft}", + "’" => "{\\textquoteright}", + "‚" => "{\\quotesinglbase}", + "‛" => "'", + "“" => "{\\textquotedblleft}", + "”" => "{\\textquotedblright}", + "„" => "{\\quotedblbase}", + "‟" => "\"", + "†" => "{\\textdagger}", + "‡" => "{\\textdaggerdbl}", + "•" => "{\\textbullet}", + "‣" => ">", + "․" => ".", + "‥" => "..", + "…" => "{\\textellipsis}", + "‧" => "-", + " " => " ", + "‰" => "{\\textperthousand}", + "′" => "'", + "″" => "\"", + "‴" => "'''", + "‵" => "`", + "‶" => "``", + "‷" => "```", + "‹" => "{\\guilsinglleft}", + "›" => "{\\guilsinglright}", + "‼" => "!!", + "‾" => "-", + "⁃" => "-", + "⁄" => "{\\textfractionsolidus}", + "⁈" => "?!", + "⁉" => "!?", + "⁊" => "7", + "⁰" => '$^{0}$', + "⁴" => '$^{4}$', + "⁵" => '$^{5}$', + "⁶" => '$^{6}$', + "⁷" => '$^{7}$', + "⁸" => '$^{8}$', + "⁹" => '$^{9}$', + "⁺" => '$^{+}$', + "⁻" => '$^{-}$', + "⁼" => '$^{=}$', + "⁽" => '$^{(}$', + "⁾" => '$^{)}$', + "ⁿ" => '$^{n}$', + "₀" => '$_{0}$', + "₁" => '$_{1}$', + "₂" => '$_{2}$', + "₃" => '$_{3}$', + "₄" => '$_{4}$', + "₅" => '$_{5}$', + "₆" => '$_{6}$', + "₇" => '$_{7}$', + "₈" => '$_{8}$', + "₉" => '$_{9}$', + "₊" => '$_{+}$', + "₋" => '$_{-}$', + "₌" => '$_{=}$', + "₍" => '$_{(}$', + "₎" => '$_{)}$', + "€" => "{\\texteuro}", + "℀" => "a/c", + "℁" => "a/s", + "℃" => "{\\textcelsius}", + "℅" => "c/o", + "℆" => "c/u", + "℉" => "F", + "ℓ" => "l", + "№" => "{\\textnumero}", + "℗" => "{\\textcircledP}", + "℠" => "{\\textservicemark}", + "℡" => "TEL", + "™" => "{\\texttrademark}", + "Ω" => "{\\textohm}", + "K" => "K", + "Å" => "A", + "℮" => "{\\textestimated}", + "⅓" => " 1/3", + "⅔" => " 2/3", + "⅕" => " 1/5", + "⅖" => " 2/5", + "⅗" => " 3/5", + "⅘" => " 4/5", + "⅙" => " 1/6", + "⅚" => " 5/6", + "⅛" => " 1/8", + "⅜" => " 3/8", + "⅝" => " 5/8", + "⅞" => " 7/8", + "⅟" => " 1/", + "Ⅰ" => "I", + "Ⅱ" => "II", + "Ⅲ" => "III", + "Ⅳ" => "IV", + "Ⅴ" => "V", + "Ⅵ" => "VI", + "Ⅶ" => "VII", + "Ⅷ" => "VIII", + "Ⅸ" => "IX", + "Ⅹ" => "X", + "Ⅺ" => "XI", + "Ⅻ" => "XII", + "Ⅼ" => "L", + "Ⅽ" => "C", + "Ⅾ" => "D", + "Ⅿ" => "M", + "ⅰ" => "i", + "ⅱ" => "ii", + "ⅲ" => "iii", + "ⅳ" => "iv", + "ⅴ" => "v", + "ⅵ" => "vi", + "ⅶ" => "vii", + "ⅷ" => "viii", + "ⅸ" => "ix", + "ⅹ" => "x", + "ⅺ" => "xi", + "ⅻ" => "xii", + "ⅼ" => "l", + "ⅽ" => "c", + "ⅾ" => "d", + "ⅿ" => "m", + "←" => "{\\textleftarrow}", + "↑" => "{\\textuparrow}", + "→" => "{\\textrightarrow}", + "↓" => "{\\textdownarrow}", + "↔" => "<->", + "⇐" => "<=", + "⇒" => "=>", + "⇔" => "<=>", + "−" => "-", + "∕" => "/", + "∖" => "\\", + "∗" => "*", + "∘" => "o", + "∙" => ".", + "∞" => '$\\infty$', + "∣" => "|", + "∥" => "||", + "∶" => ":", + "∼" => "\\~{}", + "≠" => "/=", + "≡" => "=", + "≤" => "<=", + "≥" => ">=", + "≪" => "<<", + "≫" => ">>", + "⊕" => "(+)", + "⊖" => "(-)", + "⊗" => "(x)", + "⊘" => "(/)", + "⊢" => "|-", + "⊣" => "-|", + "⊦" => "|-", + "⊧" => "|=", + "⊨" => "|=", + "⊩" => "||-", + "⋅" => ".", + "⋆" => "*", + "⋕" => '$\\#$', + "⋘" => "<<<", + "⋙" => ">>>", + "⋯" => "...", + "〈" => "{\\textlangle}", + "〉" => "{\\textrangle}", + "␀" => "NUL", + "␁" => "SOH", + "␂" => "STX", + "␃" => "ETX", + "␄" => "EOT", + "␅" => "ENQ", + "␆" => "ACK", + "␇" => "BEL", + "␈" => "BS", + "␉" => "HT", + "␊" => "LF", + "␋" => "VT", + "␌" => "FF", + "␍" => "CR", + "␎" => "SO", + "␏" => "SI", + "␐" => "DLE", + "␑" => "DC1", + "␒" => "DC2", + "␓" => "DC3", + "␔" => "DC4", + "␕" => "NAK", + "␖" => "SYN", + "␗" => "ETB", + "␘" => "CAN", + "␙" => "EM", + "␚" => "SUB", + "␛" => "ESC", + "␜" => "FS", + "␝" => "GS", + "␞" => "RS", + "␟" => "US", + "␠" => "SP", + "␡" => "DEL", + "␣" => "{\\textvisiblespace}", + "␤" => "NL", + "␥" => "///", + "␦" => "?", + "①" => "(1)", + "②" => "(2)", + "③" => "(3)", + "④" => "(4)", + "⑤" => "(5)", + "⑥" => "(6)", + "⑦" => "(7)", + "⑧" => "(8)", + "⑨" => "(9)", + "⑩" => "(10)", + "⑪" => "(11)", + "⑫" => "(12)", + "⑬" => "(13)", + "⑭" => "(14)", + "⑮" => "(15)", + "⑯" => "(16)", + "⑰" => "(17)", + "⑱" => "(18)", + "⑲" => "(19)", + "⑳" => "(20)", + "⑴" => "(1)", + "⑵" => "(2)", + "⑶" => "(3)", + "⑷" => "(4)", + "⑸" => "(5)", + "⑹" => "(6)", + "⑺" => "(7)", + "⑻" => "(8)", + "⑼" => "(9)", + "⑽" => "(10)", + "⑾" => "(11)", + "⑿" => "(12)", + "⒀" => "(13)", + "⒁" => "(14)", + "⒂" => "(15)", + "⒃" => "(16)", + "⒄" => "(17)", + "⒅" => "(18)", + "⒆" => "(19)", + "⒇" => "(20)", + "⒈" => "1.", + "⒉" => "2.", + "⒊" => "3.", + "⒋" => "4.", + "⒌" => "5.", + "⒍" => "6.", + "⒎" => "7.", + "⒏" => "8.", + "⒐" => "9.", + "⒑" => "10.", + "⒒" => "11.", + "⒓" => "12.", + "⒔" => "13.", + "⒕" => "14.", + "⒖" => "15.", + "⒗" => "16.", + "⒘" => "17.", + "⒙" => "18.", + "⒚" => "19.", + "⒛" => "20.", + "⒜" => "(a)", + "⒝" => "(b)", + "⒞" => "(c)", + "⒟" => "(d)", + "⒠" => "(e)", + "⒡" => "(f)", + "⒢" => "(g)", + "⒣" => "(h)", + "⒤" => "(i)", + "⒥" => "(j)", + "⒦" => "(k)", + "⒧" => "(l)", + "⒨" => "(m)", + "⒩" => "(n)", + "⒪" => "(o)", + "⒫" => "(p)", + "⒬" => "(q)", + "⒭" => "(r)", + "⒮" => "(s)", + "⒯" => "(t)", + "⒰" => "(u)", + "⒱" => "(v)", + "⒲" => "(w)", + "⒳" => "(x)", + "⒴" => "(y)", + "⒵" => "(z)", + "Ⓐ" => "(A)", + "Ⓑ" => "(B)", + "Ⓒ" => "(C)", + "Ⓓ" => "(D)", + "Ⓔ" => "(E)", + "Ⓕ" => "(F)", + "Ⓖ" => "(G)", + "Ⓗ" => "(H)", + "Ⓘ" => "(I)", + "Ⓙ" => "(J)", + "Ⓚ" => "(K)", + "Ⓛ" => "(L)", + "Ⓜ" => "(M)", + "Ⓝ" => "(N)", + "Ⓞ" => "(O)", + "Ⓟ" => "(P)", + "Ⓠ" => "(Q)", + "Ⓡ" => "(R)", + "Ⓢ" => "(S)", + "Ⓣ" => "(T)", + "Ⓤ" => "(U)", + "Ⓥ" => "(V)", + "Ⓦ" => "(W)", + "Ⓧ" => "(X)", + "Ⓨ" => "(Y)", + "Ⓩ" => "(Z)", + "ⓐ" => "(a)", + "ⓑ" => "(b)", + "ⓒ" => "(c)", + "ⓓ" => "(d)", + "ⓔ" => "(e)", + "ⓕ" => "(f)", + "ⓖ" => "(g)", + "ⓗ" => "(h)", + "ⓘ" => "(i)", + "ⓙ" => "(j)", + "ⓚ" => "(k)", + "ⓛ" => "(l)", + "ⓜ" => "(m)", + "ⓝ" => "(n)", + "ⓞ" => "(o)", + "ⓟ" => "(p)", + "ⓠ" => "(q)", + "ⓡ" => "(r)", + "ⓢ" => "(s)", + "ⓣ" => "(t)", + "ⓤ" => "(u)", + "ⓥ" => "(v)", + "ⓦ" => "(w)", + "ⓧ" => "(x)", + "ⓨ" => "(y)", + "ⓩ" => "(z)", + "⓪" => "(0)", + "─" => "-", + "━" => "=", + "│" => "|", + "┃" => "|", + "┄" => "-", + "┅" => "=", + "┆" => "|", + "┇" => "|", + "┈" => "-", + "┉" => "=", + "┊" => "|", + "┋" => "|", + "┌" => "+", + "┍" => "+", + "┎" => "+", + "┏" => "+", + "┐" => "+", + "┑" => "+", + "┒" => "+", + "┓" => "+", + "└" => "+", + "┕" => "+", + "┖" => "+", + "┗" => "+", + "┘" => "+", + "┙" => "+", + "┚" => "+", + "┛" => "+", + "├" => "+", + "┝" => "+", + "┞" => "+", + "┟" => "+", + "┠" => "+", + "┡" => "+", + "┢" => "+", + "┣" => "+", + "┤" => "+", + "┥" => "+", + "┦" => "+", + "┧" => "+", + "┨" => "+", + "┩" => "+", + "┪" => "+", + "┫" => "+", + "┬" => "+", + "┭" => "+", + "┮" => "+", + "┯" => "+", + "┰" => "+", + "┱" => "+", + "┲" => "+", + "┳" => "+", + "┴" => "+", + "┵" => "+", + "┶" => "+", + "┷" => "+", + "┸" => "+", + "┹" => "+", + "┺" => "+", + "┻" => "+", + "┼" => "+", + "┽" => "+", + "┾" => "+", + "┿" => "+", + "╀" => "+", + "╁" => "+", + "╂" => "+", + "╃" => "+", + "╄" => "+", + "╅" => "+", + "╆" => "+", + "╇" => "+", + "╈" => "+", + "╉" => "+", + "╊" => "+", + "╋" => "+", + "╌" => "-", + "╍" => "=", + "╎" => "|", + "╏" => "|", + "═" => "=", + "║" => "|", + "╒" => "+", + "╓" => "+", + "╔" => "+", + "╕" => "+", + "╖" => "+", + "╗" => "+", + "╘" => "+", + "╙" => "+", + "╚" => "+", + "╛" => "+", + "╜" => "+", + "╝" => "+", + "╞" => "+", + "╟" => "+", + "╠" => "+", + "╡" => "+", + "╢" => "+", + "╣" => "+", + "╤" => "+", + "╥" => "+", + "╦" => "+", + "╧" => "+", + "╨" => "+", + "╩" => "+", + "╪" => "+", + "╫" => "+", + "╬" => "+", + "╭" => "+", + "╮" => "+", + "╯" => "+", + "╰" => "+", + "╱" => "/", + "╲" => "\\", + "╳" => "X", + "╼" => "-", + "╽" => "|", + "╾" => "-", + "╿" => "|", + "○" => "o", + "◦" => "{\\textopenbullet}", + "★" => "*", + "☆" => "*", + "☒" => "X", + "☓" => "X", + "☹" => ":-(", + "☺" => ":-)", + "☻" => "(-:", + "♭" => "b", + "♯" => '$\\#$', + "✁" => '$\\%<$', + "✂" => '$\\%<$', + "✃" => '$\\%<$', + "✄" => '$\\%<$', + "✌" => "V", + "✓" => "v", + "✔" => "V", + "✕" => "x", + "✖" => "x", + "✗" => "X", + "✘" => "X", + "✙" => "+", + "✚" => "+", + "✛" => "+", + "✜" => "+", + "✝" => "+", + "✞" => "+", + "✟" => "+", + "✠" => "+", + "✡" => "*", + "✢" => "+", + "✣" => "+", + "✤" => "+", + "✥" => "+", + "✦" => "+", + "✧" => "+", + "✩" => "*", + "✪" => "*", + "✫" => "*", + "✬" => "*", + "✭" => "*", + "✮" => "*", + "✯" => "*", + "✰" => "*", + "✱" => "*", + "✲" => "*", + "✳" => "*", + "✴" => "*", + "✵" => "*", + "✶" => "*", + "✷" => "*", + "✸" => "*", + "✹" => "*", + "✺" => "*", + "✻" => "*", + "✼" => "*", + "✽" => "*", + "✾" => "*", + "✿" => "*", + "❀" => "*", + "❁" => "*", + "❂" => "*", + "❃" => "*", + "❄" => "*", + "❅" => "*", + "❆" => "*", + "❇" => "*", + "❈" => "*", + "❉" => "*", + "❊" => "*", + "❋" => "*", + "ff" => "ff", + "fi" => "fi", + "fl" => "fl", + "ffi" => "ffi", + "ffl" => "ffl", + "ſt" => "st", + "st" => "st" + ); + +} \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/crossref/biblio.crossref.client.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/crossref/biblio.crossref.client.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,326 @@ +setDOI($doi); + $this->setUserID($id); + $this->setURL(self::BASE_URL); + $this->field_map = array(); + $this->type_map = array(); + } + + public function setURL($url) { + $this->url = $url; + } + + public function setDOI($doi) { + $this->doi = $doi; + } + + public function getDOI() { + return $this->doi; + } + + public function setUserID($id) { + $this->pid = $id; + } + + public function getUserID() { + return $this->pid; + } + + public function getQuery() { + return $this->query; + } + + public function fetch() { + $this->query = $this->url . '?pid=' . $this->pid . '&noredirect=true&format=unixref&id=doi%3A' . $this->doi; + + $request_options = array('method' => 'POST'); + $result = drupal_http_request($this->query, $request_options); + + if ($result->code != 200) { + drupal_set_message(t('HTTP error: !error when trying to contact crossref.org for XML input', array('!error' => $result->code)),'error'); + return; + } + if (empty($result->data)) { + drupal_set_message(t('Did not get any data from crossref.org'),'error'); + return; + } + $sxml = @simplexml_load_string($result->data); + if (!isset($sxml->doi_record)) { + drupal_set_message(t('Failed to retrieve data for doi ') . $this->doi, 'error'); + return; + } + + if ($error = (string)$sxml->doi_record->crossref->error) { + drupal_set_message($error,'error'); + return; + } + $this->nodes = array(); + $this->parser = drupal_xml_parser_create($result->data); + // use case-folding so we are sure to find the tag in + xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, FALSE); + xml_parser_set_option($this->parser, XML_OPTION_SKIP_WHITE, TRUE); + + xml_set_object($this->parser, $this); + xml_set_element_handler($this->parser, 'unixref_startElement', 'unixref_endElement'); + xml_set_character_data_handler($this->parser, 'unixref_characterData'); + + if(!xml_parse($this->parser, $result->data)){ + drupal_set_message(sprintf("XML error: %s at line %d", + xml_error_string(xml_get_error_code($this->parser)), + xml_get_current_line_number($this->parser)),'error'); + } + + xml_parser_free($this->parser); + + return $this->node; + } + + + function unixref_startElement($parser, $name, $attrs) { + switch ($name) { + case 'doi_record' : + $this->node = array(); + $this->node['biblio_contributors'] = array(); + $this->contributors = array(); + $this->element = $name; + break; + case 'book': + case 'journal': + case 'standard': + case 'conference': + case 'report-paper': + case 'dissertation': + case 'database': + case 'sa_component': + $this->node['biblio_type'] = $this->_unixref_type_map($name); + $this->element = $name; + break; + case 'journal_article': + case 'conference_paper': + case 'content_item': + case 'report-paper_metadata': + case 'standard_metadata': + case 'database_date': + case 'component': + $this->node['year'] = ''; + $this->node['doi'] = ''; + $this->element = $name; + break; + case 'person_name' : + $this->auth_category = $this->_unixref_get_contributor_category($attrs['contributor_role']); + if (!isset($this->contrib_count)) $this->contrib_count = 0; + $this->element = $name; + break; + case 'organization': + if (!isset($this->org_count)) $this->org_count = 0; + $this->element = $name; + break; + case 'issn': + if (isset($attrs['media_type']) ) $this->attribute = $attrs['media_type']; + $this->element = $name; + break; + case 'isbn': + if (isset($attrs['media_type']) ) $this->attribute = $attrs['media_type']; + $this->element = $name; + break; + case 'i': // HTML font style tags + case 'b': + case 'u': + case 'sub': + case 'sup': + $this->unixref_characterData(NULL, ' <' . $name . '>'); + break; + case 'doi_data': + $this->doi_data = TRUE; + break; + default : + $this->element = $name; + } + + } + + function unixref_decode(&$item, $key) { + $item = html_entity_decode($item, NULL, 'UTF-8'); + } + + function unixref_endElement($parser, $name) { + switch ($name) { + case 'doi_record' : + $this->node['biblio_contributors'] += $this->contributors; + array_walk_recursive($this->node, array($this,'unixref_decode') ); + $this->node['biblio_crossref_id'] = $this->getDOI(); + $this->node['biblio_crossref_md5'] = md5(serialize($this->node)); + $this->nodes[] = $this->node; //biblio_save_node($node, $batch, $session_id, $save_node); + break; + case 'person_name' : + $this->contributors[$this->contrib_count]['auth_type'] = _biblio_get_auth_type($this->auth_category, $this->node['biblio_type']); + $this->contributors[$this->contrib_count]['auth_category'] = $this->auth_category; + $this->contributors[$this->contrib_count]['name'] = + $this->contributors[$this->contrib_count]['lastname']; + if (isset($this->contributors[$this->contrib_count]['firstname'])) { + $this->contributors[$this->contrib_count]['name'] .= + ', ' . $this->contributors[$this->contrib_count]['firstname']; + } + + $this->auth_category = ''; + $this->contrib_count++; + break; + case 'organization' : + $this->contributors[$this->contrib_count]['auth_type'] = _biblio_get_auth_type(5, $this->node['biblio_type']); + $this->contributors[$this->contrib_count]['auth_category'] = 5; + $this->contrib_count++; + break; + case 'pages': + if (isset($this->node['biblio_first_page'])) $this->node['biblio_pages'] = $this->node['biblio_first_page']; + if (isset($this->node{'biblio_last_page'})) $this->node['biblio_pages'] .= ' - ' . $this->node['biblio_last_page']; + break; + case 'publication_date': + + break; + case 'journal_issue': + case 'journal_article': + if (!isset($this->node['biblio_date']) || empty($this->node['biblio_date'])) { + $day = !empty($this->node['day']) ? $this->node['day'] : 1; + $month = !empty($this->node['month']) ? $this->node['month'] : 1; + $year = !empty($this->node['year']) ? $this->node['year'] : 0; + if ($year) { + $this->node['biblio_date'] = date("M-d-Y", mktime(0, 0, 0, $day, $month, $year)); + } + } + if ((!isset($this->node['biblio_year']) || empty($this->node['biblio_year'])) && isset($this->node['year'])) { + $this->node['biblio_year'] = $this->node['year']; + } + break; + case 'conference_paper': + case 'content_item': + case 'report-paper_metadata': + case 'standard_metadata': + case 'database_date': + case 'component': + if ((!isset($this->node['biblio_year']) || empty($this->node['biblio_year'])) && isset($this->node['year'])) { + $this->node['biblio_year'] = $this->node['year']; + unset($this->node['year']); + } +// $this->node['biblio_doi'] = $this->node['doi']; + break; + case 'issn': + case 'isbn': + $this->attribute = ''; + break; + case 'i': // HTML font style tags + case 'b': + case 'u': + case 'sub': + case 'sup': + $this->unixref_characterData(NULL, ' '); + break; + case 'doi_data': + $this->doi_data = FALSE; + break; + default : + } + } + + function unixref_characterData($parser, $data) { + $data = htmlspecialchars_decode($data); + if (trim($data)) { + switch ($this->element) { + case 'surname' : + $this->contributors[$this->contrib_count]['lastname'] = $data; + break; + case 'given_name' : + $this->contributors[$this->contrib_count]['firstname'] = $data; + break; + case 'suffix': + $this->contributors[$this->contrib_count]['suffix'] = $data; + break; + case 'affiliation' : + $this->contributors[$this->contrib_count]['affiliation'] = $data; + break; + case 'organization': + $this->contributors[$this->contrib_count]['name'] = $data; + break; + case 'year': + case 'month': + case 'day': + $this->node[$this->element] = $data; + break; + case 'issn': + case 'isbn': + if ($this->attribute == 'print') { + if ($field = $this->_unixref_field_map(trim($this->element))) { + $this->_set_data($field, $data); + } + } + break; + case 'doi': + if ($this->doi_data) { + if ($field = $this->_unixref_field_map(trim($this->element))) { + $this->_set_data($field, $data); + } + } + break; + case 'resource': + if ($this->doi_data) { + $this->_set_data('biblio_url', $data); + } + break; + + default: + if ($field = $this->_unixref_field_map(trim($this->element))) { + $this->_set_data($field, $data); + } + + } + } + } + function _set_data($field, $data) { + $this->node[$field] = (isset($this->node[$field]) ? $this->node[$field] . $data : $data); + } + /* + * map a unixref XML field to a biblio field + */ + function _unixref_field_map($field) { + if (empty($this->field_map)) { + $this->field_map = unserialize(db_query("SELECT field_map FROM {biblio_type_maps} WHERE format='crossref'")->fetchField()); + } + return (isset($this->field_map[$field])) ? $this->field_map[$field]: FALSE; + } + + function _unixref_type_map($type) { + if (empty($this->type_map)) { + $this->type_map = unserialize(db_query("SELECT type_map FROM {biblio_type_maps} WHERE format='crossref'")->fetchField()); + } + return (isset($this->type_map[$type]))?$this->type_map[$type]:129; //return the biblio type or 129 (Misc) if type not found + } + + function _unixref_get_contributor_category($role) { + if ($role == 'author') return 1; + if ($role == 'editor') return 2; + if ($role == 'chair') return 3; + if ($role == 'translator') return 4; + return NULL; + } +} \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/crossref/biblio_crossref.info --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/crossref/biblio_crossref.info Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,13 @@ +name = Biblio - Crossref +description = Provides DOI lookup and import to the Biblio module. +core = 7.x +package = Biblio +dependencies[] = biblio +files[] = biblio.crossref.client.php + +; Information added by drupal.org packaging script on 2013-07-20 +version = "7.x-1.0-rc7" +core = "7.x" +project = "biblio" +datestamp = "1374290470" + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/crossref/biblio_crossref.install --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/crossref/biblio_crossref.install Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,151 @@ +condition('format', 'crossref') + ->execute(); + } +} + +function biblio_crossref_enable() { + biblio_crossref_set_system_weight(); +} + +function biblio_crossref_set_system_weight() { + db_update('system') + ->fields(array('weight' => 20)) + ->condition('name', 'biblio_crossref') + ->execute(); +} +function _save_crossref_maps() { + $typemap = _get_crossref_type_map(); + $typenames = _get_crossref_type_names(); + $fieldmap = _get_crossref_field_map(); + $maps = array_merge($typemap, $typenames, $fieldmap); + biblio_save_map($maps); +} +function _reset_crossref_map($type) { + $count = db_query("SELECT COUNT(*) FROM {biblio_type_maps} WHERE format='crossref'")->fetchField(); + if ($count && $type) { //update + $function = '_get_crossref_' . $type; + if (!function_exists($function)) return; + $map = $function(); + db_update('biblio_type_maps') + ->fields($map) + ->condition('format', 'crossref') + ->execute(); + } + else { // install +// db_query("DELETE FROM {biblio_type_maps} WHERE format='crossref'"); + db_delete('biblio_type_maps') + ->condition('format', 'crossref') + ->execute(); + _save_crossref_maps(); + } +} + +function _get_crossref_type_map() { + $map['type_map'] = serialize( + array( + 'error' => 0, + 'book' => 100, // Book + 'journal' => 102, // Journal Article + 'standard' => 129, // Generic + 'conference' => 103, // conference_paper + 'report-paper' => 109, // Report + 'dissertation' => 108, // Thesis + 'database' => 125, // online database + 'sa_component' => 129 + ) + ); + $map['format'] = 'crossref'; + return $map; +} + +function _get_crossref_type_names() { + $map['type_names'] = serialize( + array( + 'error' => 'Error', + 'book' => 'Book', + 'journal' => 'Journal Article', + 'standard' => 'Generic', + 'conference' => 'Conference Paper', + 'report-paper' => 'Report', + 'dissertation' => 'Thesis', + 'database' => 'Online database', + 'sa_component' => 'SA Component', + ) + ); + $map['format'] = 'crossref'; + return $map; +} + +function _get_crossref_field_map() { + $map['field_map'] = serialize( + array( + 'publisher_place' => 'biblio_place_published', + 'publisher_name' => 'biblio_publisher', + 'volume' => 'biblio_volume', + 'number' => 'biblio_number', + 'issue' => 'biblio_issue', + 'edition_number' => 'biblio_edition', + 'section' => 'biblio_section', + 'doi' => 'biblio_doi', + 'title' => 'title', + 'isbn' => 'biblio_isbn', + 'issn' => 'biblio_issn', + 'first_page' => 'biblio_first_page', + 'last_page' => 'biblio_last_page', + // Journal metadata + 'full_title' => 'biblio_secondary_title', + 'abbrev_title' => 'biblio_short_title', + // Conference metadata + 'conference_location' => 'biblio_place_published', + 'conference_name' => 'biblio_secondary_title', + 'conference_acronym' => 'biblio_short_title', + // Proceedings metadata + 'proceedings_title' => 'biblio_secondary_title', + 'year' => 'year', + 'month' => 'month', + 'day' => 'day', + 'degree' => 'biblio_type_of_work', + 'error' => 'error', + 'language' => 'biblio_lang', + ) + ); + + $map['format'] = 'crossref'; + return $map; + +} + +/** + * Implementation of hook_schema(). + * + * Note: Pro Drupal Development models use of t() to translate 'description' + * for field definitions, but Drupal core does not use them. We follow core. + */ +function biblio_crossref_schema() { + $schema = array(); + $schema['biblio_crossref'] = array( + 'fields' => array( + 'nid' => array('type' => 'int', 'not null' => TRUE), + 'biblio_crossref_md5' => array('type' => 'char', 'length' => 32, 'not null' => TRUE), + 'biblio_crossref_id' => array('type' => 'char', 'length' => 255, 'not null' => TRUE), + ), + 'primary key' => array('nid'), + ); + return $schema; +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/crossref/biblio_crossref.module --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/crossref/biblio_crossref.module Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,168 @@ + 5 && !$form_state['submitted'] && !isset($form['#node']->nid)) { + $form['biblio_doi_lookup'] = array( + '#type' => 'fieldset', + '#title' => t('DOI Lookup'), + '#weight' => -20, + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + $have_pid = variable_get('biblio_crossref_pid', ''); + $user_pid = (isset($user->data['biblio_crossref_pid']) && !empty($user->data['biblio_crossref_pid'])) ? $user->data['biblio_crossref_pid'] : ''; + if (variable_get('biblio_show_crossref_profile_form', '1') && !empty($user_pid)) { + $have_pid = $user_pid; + } + if (empty($have_pid)) { + $form['biblio_doi_lookup']['doi_register'] = array( + '#prefix' => '

    ', + '#suffix' => '

    ', + '#markup' => t('!url1 and then enter your CrossRef UserID in the "CrossRef Login Information" section of your account profile !url2', array('!url1' => l(t('You need to register with CrossRef'), 'http://www.crossref.org/requestaccount/', array('attributes' => array('target' => '_blank'), 'absolue' => TRUE)), '!url2' => l(t('here...'), "user/$user->uid/edit"))), + ); + } + + $form['biblio_doi_lookup']['doi_data'] = array( + '#type' => 'textfield', + '#title' => t('DOI'), + '#required' => FALSE, + '#default_value' => (isset($form_state['values']['doi_data']) ? $form_state['values']['doi_data'] : ''), + '#description' => t('Enter a DOI name in the form: 10.1000/123456'), + '#disabled' => empty($have_pid), + '#size' => 60, + '#maxlength' => 255, + '#weight' => -4 + ); + $form['biblio_doi_lookup']['doi_submit'] = array( + '#type' => 'submit', + '#disabled' => empty($have_pid), + '#value' => t('Populate using DOI'), + '#submit' => array('biblio_crossref_form_biblio_node_form_submit') + ); + } + $biblio_crossref_id = (isset($form_state['values']['biblio_crossref_id'])) ? $form_state['values']['biblio_crossref_id'] : ''; + $biblio_crossref_md5 = (isset($form_state['values']['biblio_crossref_md5'])) ? $form_state['values']['biblio_crossref_md5'] : ''; + $form['biblio_crossref_id'] = array('#type' => 'value', '#value' => $biblio_crossref_id); + $form['biblio_crossref_md5'] = array('#type' => 'value', '#value' => $biblio_crossref_md5); +} + +function biblio_crossref_form_biblio_node_form_submit($form, &$form_state) { + global $user; + $node_data = array(); + if (strlen($doi = $form_state['values']['doi_data'])) { + if (($doi_start = strpos($form_state['values']['doi_data'], '10.')) !== FALSE) { + if (!($dup = biblio_crossref_check_doi($doi))) { + $crossref_pid = variable_get('biblio_crossref_pid', ''); + $user_pid = (isset($user->data['biblio_crossref_pid']) && !empty($user->data['biblio_crossref_pid'])) ? $user->data['biblio_crossref_pid'] : ''; + if (variable_get('biblio_show_crossref_profile_form', '1') && !empty($user_pid)) { + $crossref_pid = $user_pid; + } + + if (empty($crossref_pid)) { + form_set_error('doi_data', l(t('You need to register with CrossRef'), 'http://www.crossref.org/requestaccount/', array('attributes' => array('target' => '_blank'), 'absolue' => TRUE)) . ' ' . t('and then enter your CrossRef UserID in the "CrossRef Login Information" section of your account profile !url', array('!url' => l(t('here...'), "user/$user->uid/edit")))); + return; + } + + module_load_include('php', 'biblio_crossref', 'biblio.crossref.client'); + $client = new BiblioCrossRefClient($doi, $crossref_pid); + $node_data = $client->fetch(); + + if (!empty($node_data)) { + $form_state['values'] = array_merge($form_state['values'], $node_data); + $form_state['input']['biblio_type'] = $form_state['biblio_type'] = $node_data['biblio_type']; + } + else { + form_set_error('doi_data', ''); + } + } + else { + $message = t('The DOI that you are trying to import already exists in the database, see !url', array('!url' => l('node/' . $dup, 'node/' . $dup))); + form_set_error('doi_data', $message); + } + } + else { + form_set_error('doi_data', t('This does not appear to be a valid DOI name, it should start with "10."')); + } + } + $form_state['rebuild'] = TRUE; + return; +} + +function biblio_crossref_check_doi($doi) { + return db_query("SELECT nid FROM {biblio_crossref} WHERE biblio_crossref_id = :doi", array(':doi' => $doi))->fetchField(); +} + +function biblio_crossref_biblio_lookup_link_settings() { + return array('crossref' => t('DOI')); +} +function biblio_crossref_biblio_mapper_options() { + return array( + 'crossref' => array( + 'title' => t('CrossRef XML'), + 'export' => FALSE, + ), + ); +} + +function biblio_crossref_biblio_lookup_link($node) { + $show_link = variable_get('biblio_lookup_links', array('crossref' => TRUE)); + if (empty($show_link['crossref']) || !isset($node) || (!isset($node->biblio_crossref_id) && empty($node->biblio_doi))) { + return; + } + if ($node->type == 'biblio') { + $doi = isset($node->biblio_crossref_id) ? $node->biblio_crossref_id : $node->biblio_doi; + if ( ($doi_start = strpos($doi, '10.')) !== FALSE) { + $doi = substr($doi, $doi_start); + } + $link = 'http://dx.doi.org/' . $doi; + return array('biblio_crossref' => array( + 'title' => t('DOI'), + 'href' => $link, + 'attributes' => array('title' => t("Click to view the CrossRef listing for this node")), + )); + } + return ; + } + + +function biblio_crossref_node_view($node, $view_mode, $langcode) { + if ($node->type == 'biblio' && (isset($node->biblio_crossref_id) || !empty($node->biblio_doi))) { + switch ($view_mode) { + case 'full': + case 'teaser': + $node->content['links']['biblio_crossref'] = array( + '#links' => biblio_crossref_biblio_lookup_link($node), + '#attributes' => array('class' => array('links', 'inline')), + ); + } + } +} + +function biblio_crossref_node_delete($node) { + if ($node->type != 'biblio') return; + db_delete('biblio_crossref') + ->condition('nid', $node->nid) + ->execute(); +} + +function biblio_crossref_node_insert($node) { + if ($node->type != 'biblio') return; + if (empty($node->biblio_crossref_id)) return; + drupal_write_record('biblio_crossref', $node); +} + +function biblio_crossref_node_load($nodes, $types) { + $result = db_query('SELECT nid, biblio_crossref_id FROM {biblio_crossref} WHERE nid IN(:nids)', array(':nids' => array_keys($nodes))); + foreach ($result as $record) { + $nodes[$record->nid]->biblio_crossref_id = $record->biblio_crossref_id; + } +} +function biblio_crossref_crossref_map_reset($type = NULL) { + module_load_include('install', 'biblio_crossref', 'biblio_crossref'); + _reset_crossref_map($type); +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/endnote/biblio_tagged.info --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/endnote/biblio_tagged.info Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,13 @@ +name = Biblio - EndNote Tagged +description = Provides EndNote tagged file import and export to the Biblio module. +core = 7.x +package = Biblio +dependencies[] = biblio +files[] = views/biblio_handler_field_export_link_tagged.inc + +; Information added by drupal.org packaging script on 2013-07-20 +version = "7.x-1.0-rc7" +core = "7.x" +project = "biblio" +datestamp = "1374290470" + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/endnote/biblio_tagged.install --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/endnote/biblio_tagged.install Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,196 @@ +condition('format', 'tagged') + ->execute(); + } +} + +function biblio_tagged_enable() { + biblio_tagged_set_system_weight(); +} + +function biblio_tagged_set_system_weight() { + db_update('system') + ->fields(array('weight' => 22)) + ->condition('name', 'biblio_tagged') + ->execute(); +} + +function _get_tagged_type_map() { + $map['type_map'] = serialize( + array( + "Journal Article" => 102, + "Conference Paper" => 103, + "Conference Proceedings" => 104, + "Report" => 109, + "Book" => 100, + "Edited Book" => 100, + "Book Section" => 101, + "Thesis" => 108, + "Patent" => 119, + "Generic" => 129, + "Newspaper Article" => 105, + "Magazine Article" => 106, + "Web Page" => 107, + "Film or Broadcast" => 110, + "Artwork" => 112, + "Audiovisual Material" => 114, + "Hearing" => 115, + "Case" => 116, + "Bill" => 117, + "Statute" => 118, + "Personal Communication" => 120, + "Manuscript" => 121, + "Map" => 122, + "Chart or Table" => 123, + "Unpublished Work" => 124, + "Online Database" => 125, + "Government Document" => 126, + "Classical Work" => 127, + "Legal Rule or Regulation" => 128, + ) + ); + $map['format'] = 'tagged'; + return $map; +} +function _get_tagged_type_names() { + $map['type_names'] = serialize( + array( + "Journal Article" => "Journal Article", + "Conference Paper" => "Conference Paper", + "Conference Proceedings" => "Conference Proceedings", + "Report" => "Report", + "Book" => "Book", + "Edited Book" => "Edited Book", + "Book Section" => "Book Section", + "Thesis" => "Thesis", + "Patent" => "Patent", + "Generic" => "Generic", + "Newspaper Article" => "Newspaper Article", + "Magazine Article" => "Magazine Article", + "Web Page" => "Web Page", + "Film or Broadcast" => "Film or Broadcast", + "Artwork" => "Artwork", + "Audiovisual Material" => "Audiovisual Material", + "Hearing" => "Hearing", + "Case" => "Case", + "Bill" => "Bill", + "Statute" => "Statute", + "Personal Communication" => "Personal Communication", + "Manuscript" => "Manuscript", + "Map" => "Map", + "Chart or Table" => "Chart or Table", + "Unpublished Work" => "Unpublished Work", + "Online Database" => "Online Database", + "Government Document" => "Government Document", + "Classical Work" => "Classical Work", + "Legal Rule or Regulation" => "Legal Rule or Regulation", + ) + ); + + $map['format'] = 'tagged'; + return $map; +} + +function _get_tagged_field_map() { + $map['field_map'] = serialize( + array( + '%B' => 'biblio_secondary_title', + '%C' => 'biblio_place_published', + '%D' => 'biblio_year', + '%F' => 'biblio_label', + '%G' => 'biblio_lang', + '%I' => 'biblio_publisher', + '%J' => 'biblio_secondary_title', + '%K' => 'biblio_keywords', + '%L' => 'biblio_call_number', + '%M' => 'biblio_accession_number', + '%N' => 'biblio_issue', + '%P' => 'biblio_pages', + '%R' => 'biblio_doi', + '%S' => 'biblio_tertiary_title', + '%U' => 'biblio_url', + '%V' => 'biblio_volume', + '%1' => 'biblio_custom1', + '%2' => 'biblio_custom2', + '%3' => 'biblio_custom3', + '%4' => 'biblio_custom4', + '%#' => 'biblio_custom5', + '%$' => 'biblio_custom6', + '%]' => 'biblio_custom7', + '%6' => 'biblio_number_of_volumes', + '%7' => 'biblio_edition', + '%8' => 'biblio_date', + '%9' => 'biblio_type_of_work', + '%?' => '', + '%@' => 'biblio_isbn', + '%<' => 'biblio_research_notes', + '%!' => 'biblio_short_title', + '%&' => 'biblio_section', + '%(' => 'biblio_original_publication', + '%)' => 'biblio_reprint_edition', + '%*' => '', + '%+' => '', + ) + ); + $map['format'] = 'tagged'; + return $map; +} + +function _save_tagged_maps() { + $typemap = _get_tagged_type_map(); + $typenames = _get_tagged_type_names(); + $fieldmap = _get_tagged_field_map(); + $maps = array_merge($typemap, $typenames, $fieldmap); + biblio_save_map($maps); +} + +function _reset_tagged_map($type) { + $count = db_query("SELECT COUNT(*) FROM {biblio_type_maps} WHERE format='tagged'")->fetchField(); + if ($count && $type) { //update + $function = '_get_tagged_' . $type; + if (!function_exists($function)) return; + $map = $function(); + db_update('biblio_type_maps') + ->fields($map) + ->condition('format', 'tagged') + ->execute(); + } + else { // install + db_delete('biblio_type_maps') + ->condition('format', 'tagged') + ->execute(); + _save_tagged_maps(); + } +} +/** + * Implementation of hook_schema(). + * + * Note: Pro Drupal Development models use of t() to translate 'description' + * for field definitions, but Drupal core does not use them. We follow core. + */ +function biblio_tagged_schema() { + $schema = array(); + $schema['biblio_tagged'] = array( + 'fields' => array( + 'nid' => array('type' => 'int', 'not null' => TRUE), + 'biblio_tagged_md5' => array('type' => 'char', 'length' => 32, 'not null' => TRUE), + ), + 'primary key' => array('nid'), + ); + return $schema; +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/endnote/biblio_tagged.module --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/endnote/biblio_tagged.module Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,407 @@ + 2, + 'path' => drupal_get_path('module', 'biblio_tagged') . '/views', + ); +} +/* + * add the tagged option to the option list of the biblio_import_form + * the key is the module name use by module_invoke to call hook_biblio_import + * module_invoke('biblio_tagged', 'biblio_import',...) + */ +function biblio_tagged_biblio_import_options() { + return array('biblio_tagged' => t('EndNote Tagged')); +} +function biblio_tagged_biblio_mapper_options() { + return array( + 'tagged' => array( + 'title' => t('EndNote Tagged'), + 'export' => TRUE, + ) + ); +} + +function biblio_tagged_biblio_export_options() { + return array('tagged' => t('EndNote Tagged')); +} + +function biblio_tagged_node_view($node, $view_mode) { + if ($node->type == 'biblio') { + switch ($view_mode) { + case 'full': + case 'teaser': + $links = biblio_tagged_biblio_export_link($node->nid); + $node->content['links']['biblio_tagged'] = array( + '#links' => $links, + '#attributes' => array('class' => array('links', 'inline')), + ); + } + } +} + +/** + * Creates a link to export a node (or view) in tagged format + * + * @param $base this is the base url (defaults to /biblio) + * @param $nid the node id, if NULL then the current view is exported + * @return a link (tagged) + */ +function biblio_tagged_biblio_export_link($nid = NULL, $filter = array()) { + $show_link = variable_get('biblio_export_links', array('tagged' => TRUE)); + if (!isset($show_link['tagged']) || empty($show_link['tagged']) || !biblio_access('export')) { + return array(); + } + $base = variable_get('biblio_base', 'biblio'); + + if (module_exists('popups') && !empty($nid)) { + $link = array( + 'attributes' => array( + 'class' => 'popups', + 'title' => t("Click to get the EndNote Tagged output"))); + } + else { + $link = array( + 'attributes' => array( + 'title' => t("Click to download the EndNote Tagged formatted file"))); + } + + $link['attributes'] += array('rel' => 'nofollow'); + + $link['href'] = "$base/export/tagged"; + if (!empty($nid)) { + $link['href'] .= '/' . $nid; + } + $link['title'] = t('Tagged'); + + if (empty($nid) && !empty($filter)) { // add any filters which may be on the current page + $link['query'] = $filter; + } + + return array('biblio_tagged' => $link); +} + + +function biblio_tagged_node_delete($node) { + if ($node->type != 'biblio') { + return; + } + db_delete('biblio_tagged') + ->condition('nid', $node->nid) + ->execute(); +} + +function biblio_tagged_node_insert($node) { + if ($node->type != 'biblio' || !isset($node->biblio_tagged_md5)) { + return; + } + drupal_write_record('biblio_tagged', $node); +} + +function biblio_tagged_biblio_import($file, $terms = array(), $batch = FALSE, $session_id = NULL, $save = TRUE, $string = FALSE) { + $nids = array(); + $dups = array(); + list($nids, $dups) = _biblio_tagged_import($file, $terms, $batch, $session_id); + + return array($nids, $dups); +} + +function biblio_tagged_biblio_export($nids) { + if (module_exists('popups') && count($nids)) { + $popup = TRUE; + } + else { + $popup = FALSE; + drupal_add_http_header('Content-type', 'application/x-endnote-refer'); + drupal_add_http_header('Content-Disposition', 'attachment; filename="Drupal-Biblio.enw"'); + } + + $nodes = node_load_multiple($nids, array(), TRUE); + foreach ($nodes as $node) { + if (variable_get('biblio_hide_bibtex_braces', 0) ) { + $node->title = biblio_remove_brace($node->title); + } + + if (!$popup) { + print _biblio_tagged_export($node); + } + else{ + $popup_data .= _biblio_tagged_export($node); + } + } + if ($popup && !empty($popup_data)) return '
    ' . $popup_data . '
    '; + +} + +/** + * Export data in tagged format. + * + * @param $result + * a database result set pointer + * @return + * none + */ + +function _biblio_tagged_import($file, $terms = array(), $batch = FALSE, $session_id = NULL) { + ini_set('auto_detect_line_endings', TRUE); + if (!($fp = fopen($file->uri, "r"))) { + drupal_set_message(t("Could not open EndNote Tagged input"), 'error'); + return; + } + $nids = array(); + $dups = array(); + $ignored_tags = array(); + $node = NULL; + $incite = FALSE; + $node_id = NULL; + $contributors = NULL; + while (!feof($fp)) { + $line = trim(fgets($fp)); + $line_len = strlen($line); + if ($line_len) { + $start = strpos($line, "%"); // There could be some unprintables at the beginning of the line so fine the location of the % + if ($start !== FALSE) { + $tag = drupal_substr($line, $start, 2); + $value = trim(drupal_substr($line, $start +3)); + } + else { + $value = $line; + } + } + if ($line_len) { // if this is not a blank line + if (!$incite) { + $incite = TRUE; + $node = new stdClass(); + //$node->biblio_contributors = array(); + + } + switch ($tag) { + case '%0' : + $node->biblio_type = _biblio_tagged_type_map($value); + break; + case '%A' : + $node->biblio_contributors[] = array( + 'name' => $value, + 'auth_category' => 1, + 'auth_type' => _biblio_get_auth_type(1, $node->biblio_type)); + break; + case '%E' : + $node->biblio_contributors[] = array( + 'name' => $value, + 'auth_category' => 2, + 'auth_type' => _biblio_get_auth_type(2, $node->biblio_type)); + break; + case '%T' : + $node->title = $value; + break; + case '%Y' : + $node->biblio_contributors[] = array( + 'name' => $value, + 'auth_category' => 3, + 'auth_type' => _biblio_get_auth_type(3, $node->biblio_type)); + break; + case '%?' : + $node->biblio_contributors[] = array( + 'name' => $value, + 'auth_category' => 4, + 'auth_type' => _biblio_get_auth_type(4, $node->biblio_type)); + break; + case '%X' : + $node->biblio_abst_e .= $value; + break; + case '%Z' : + $node->biblio_notes .= $value; + break; + + default : + $field = _biblio_tagged_field_map($tag); + if (!empty($field)) { + $node->$field = $value; + } + else { + if (!in_array($tag, $ignored_tags)) { + $ignored_tags[] = $tag; + } + } + break; + } //end switch + } + else { + $incite = FALSE; + if (!empty($node)) { + _biblio_tagged_save($node, $terms, $batch, $session_id, $nids, $dups); + $node = NULL; + } + + } // end if ($start !== FALSE) + } // end while + + fclose($fp); + + if ($incite && !empty($node)) { // this catches the case where the file ends without a blank line at the end + _biblio_tagged_save($node, $terms, $batch, $session_id, $nids, $dups); + } + + if (!empty($ignored_tags)) { + $ignored_tags = array_unique($ignored_tags); + $message = t("The following elements were ignored because they do not map to any biblio fields:") . ' '; + $message .= implode(', ', $ignored_tags); + if (user_access('administer biblio')) { + $message .= '. ' . t('Click !url if you wish to check the field mapping', array('!url' => l(t('here'), 'admin/config/content/biblio/iomap/edit/tagged'))); + } + drupal_set_message($message, 'warning'); + } + + return array($nids, $dups); +} + +function _biblio_tagged_save($node, $terms, $batch, $session_id, &$nids, &$dups) { + $node->biblio_tagged_md5 = md5(serialize($node)); + if (! ($dup = biblio_tagged_check_md5($node->biblio_tagged_md5))) { + biblio_save_node($node, $terms, $batch, $session_id); + if (!empty($node->nid)) $nids[] = $node->nid; + } + else { + $dups[] = $dup; + } +} + +function _biblio_tagged_export($node) { + $export = TRUE; + $tagged = ""; + $tagged .= "%0 " . _biblio_tagged_type_map($node->biblio_type, $export) . "\r\n"; + switch ($node->biblio_type) { + case 100 : + case 101 : + case 103 : + case 104 : + case 105 : + case 108 : + case 119 : + if (!empty($node->biblio_secondary_title)) + $tagged .= "%B " . trim($node->biblio_secondary_title) . "\r\n"; + break; + case 102 : + if (!empty($node->biblio_secondary_title)) + $tagged .= "%J " . trim($node->biblio_secondary_title) . "\r\n"; + break; // journal + } + if (isset($node->biblio_year) && $node->biblio_year < 9998) $tagged .= "%D " . trim($node->biblio_year) . "\r\n"; + if (!empty($node->title)) $tagged .= "%T " . trim($node->title) . "\r\n"; + + foreach (biblio_get_contributor_category($node->biblio_contributors, 1) as $auth) { + $tagged .= "%A " . trim($auth['name']) . "\r\n"; + } + foreach (biblio_get_contributor_category($node->biblio_contributors, 2) as $auth) { + $tagged .= "%E " . trim($auth['name']) . "\r\n"; + } + foreach (biblio_get_contributor_category($node->biblio_contributors, 3) as $auth) { + $tagged .= "%Y " . trim($auth['name']) . "\r\n"; + } + foreach (biblio_get_contributor_category($node->biblio_contributors, 4) as $auth) { + $tagged .= "%? " . trim($auth['name']) . "\r\n"; + } + + $kw_array = array(); + if (!empty($node->terms)) { + foreach ($node->terms as $term) { + $kw_array[] = $term->name; + } + } + if (!empty($node->biblio_keywords)) { + foreach ($node->biblio_keywords as $term) { + $kw_array[] = $term; + } + } + if (!empty($kw_array)) { + $kw_array = array_unique($kw_array); + foreach ($kw_array as $term) { + $tagged .= "%K " . trim($term) . "\r\n"; + } + } + $abst = ""; + if (!empty($node->biblio_abst_e)) $abst .= trim($node->biblio_abst_e); + if ($abst) { + $search = array("/\r/", "/\n/"); + $replace = " "; + $abst = preg_replace($search, $replace, $abst); + $tagged .= "%X " . $abst . "\r\n"; + } + $skip_fields = array('biblio_year', 'biblio_abst_e', 'biblio_abst_f', 'biblio_type' ); + $fields = drupal_schema_fields_sql('biblio'); + $fields = array_diff($fields, $skip_fields); + foreach ($fields as $field) { + if (!empty($node->$field)) { + $tagged .= _biblio_tagged_format_entry($field, $node->$field); + } + } + if (!empty ($node->upload) && count($node->upload['und']) && user_access('view uploaded files')) { + foreach ($node->upload['und'] as $file) { + $tagged .= "%> " . file_create_url($file['uri']) . "\r\n"; // insert file here. + } + } + $tagged .= "\r\n"; + return $tagged; +} + +function _biblio_tagged_format_entry($key, $value) { + $reverse = TRUE; + $tag = _biblio_tagged_field_map($key, $reverse); + if (!empty($tag)) { + return "$tag " . trim($value) . "\r\n"; + } + +} + +function _biblio_tagged_type_map($type, $reverse = FALSE) { + static $map = array(); + + if (empty($map)) { + $map = biblio_get_map('type_map', 'tagged'); + } + + if ($reverse) { + return ($tag = array_search($type, $map)) ? $tag : 'Generic'; //return the biblio type or 129 (Misc) if type not found + } + return (isset($map[$type]))?$map[$type]:129; //return the biblio type or 129 (Misc) if type not found +} + +function _biblio_tagged_field_map($field, $reverse = FALSE) { + static $fmap = array(); + + if (empty($fmap)) { + $fmap = biblio_get_map('field_map', 'tagged' ); + } + + if ($reverse) { + return ($tag = array_search($field, $fmap)) ? $tag : ''; + } + return (!empty($fmap[$field])) ? $fmap[$field] : ''; + +} + +function biblio_tagged_tagged_map_reset($type = NULL) { + module_load_include('install', 'biblio_tagged', 'biblio_tagged'); + _reset_tagged_map($type); +} + +function biblio_tagged_check_md5($md5) { + static $tagged_md5s = array(); + if (empty($tagged_md5s)) { + $result = db_query("SELECT * FROM {biblio_tagged} "); + foreach ($result as $row ) { + $tagged_md5s[$row->biblio_tagged_md5] = $row->nid; + } + } + if (isset($tagged_md5s[$md5])) { + return $tagged_md5s[$md5]; + } + else { + $tagged_md5s[$md5] = TRUE; // gaurd against duplicates in the same import + return; + } +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/endnote/biblio_xml.info --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/endnote/biblio_xml.info Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,14 @@ +name = Biblio - EndNote XML +description = Provides EndNote XML file import and export to the Biblio module. +core = 7.x +package = Biblio +dependencies[] = biblio +files[] = endnote_xml_parser.inc +files[] = views/biblio_handler_field_export_link_xml.inc + +; Information added by drupal.org packaging script on 2013-07-20 +version = "7.x-1.0-rc7" +core = "7.x" +project = "biblio" +datestamp = "1374290470" + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/endnote/biblio_xml.install --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/endnote/biblio_xml.install Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,390 @@ +condition('format', 'endnote8') + ->execute(); + + db_delete('biblio_type_maps') + ->condition('format', 'endnote7') + ->execute(); + } +} + +function biblio_xml_enable() { + biblio_xml_set_system_weight(); +} + +function biblio_xml_set_system_weight() { + db_update('system') + ->fields(array('weight' => 26)) + ->condition('name', 'biblio_xml') + ->execute(); +} + +function _save_xml_maps() { + _save_endnote7_maps(); + _save_endnote8_maps(); +} +function _save_endnote7_maps() { + $format = 'endnote7'; + $typemap = _get_endnote7_type_map(); + $typenames = _get_endnote7_type_names(); + $fieldmap = _get_endnote7_field_map(); + $maps = array_merge($typemap, $typenames, $fieldmap); + biblio_save_map($maps); +} + +function _save_endnote8_maps() { + $typemap = _get_endnote8_type_map(); + $typenames = _get_endnote8_type_names(); + $fieldmap = _get_endnote8_field_map(); + $maps = array_merge($typemap, $typenames, $fieldmap); + biblio_save_map($maps); +} + +function _reset_endnote_xml_map($version, $type) { + $count = db_query("SELECT COUNT(*) FROM {biblio_type_maps} WHERE format=:format", array(':format' => $version))->fetchField(); + if ($count && $type) { //update + $function = '_get_' . $version . '_' . $type; + if (!function_exists($function)) return; + $map = $function(); + drupal_write_record('biblio_type_maps', $map, 'format'); + db_update('biblio_type_maps') + ->fields($map) + ->condition('format', $version) + ->execute(); + } + else { // install + db_delete('biblio_type_maps') + ->condition('format', $version) + ->execute(); + $save_maps = '_save_' . $version . '_maps'; + $save_maps(); + } +} + +function _get_endnote8_type_map() { + $map['type_map'] = serialize( + array( + 2 => 112, // artwork + 3 => 114, // Audio Visual + 4 => 117, // bill + 5 => 101, // Book Section + 6 => 100, // Book + 7 => 116, // case + 9 => 113, // software + 17 => 102, // Journal Article + 10 => 104, // Conference Proceeding + 12 => 107, // web page + 13 => 129, // Generic + 14 => 115, // hearing + 19 => 106, // magazine_article + 20 => 122, // map + 21 => 110, // film + 21 => 111, // broadcast + 23 => 105, // newspaper_article + 25 => 119, // patent + 26 => 120, // personal communication + 27 => 109, // Report + 28 => 129, // Edited Book + 31 => 118, // statute + 32 => 108, // Thesis + 34 => 124, // unpublished + 36 => 121, // manuscript + 37 => 129, // figure + 38 => 123, // chart + 39 => 129, // equation + 43 => 129, // electronic article + 44 => 129, // electronic book + 45 => 125, // online database + 46 => 126, // government_document + 47 => 103, // conference_paper + 48 => 129, // online multimedia + 49 => 127, // Classical Work + 50 => 128, // legal_ruling + 52 => 129, // Dictionary + 53 => 129, // Encyclopedia + 54 => 129, // Grant + ) + ); + $map['format'] = 'endnote8'; + return $map; +} + +function _get_endnote8_type_names() { + $map['type_names'] = serialize( + array( + 2 => 'Artwork', + 3 => 'Audio Visual', + 4 => 'Bill', + 5 => 'Book Section', + 6 => 'Book', + 7 => 'Case', + 9 => 'Software', + 17 => 'Journal Article', + 10 => 'Conference Proceeding', + 12 => 'Web page', + 13 => 'Generic', + 14 => 'Hearing', + 19 => 'Magazine Article', + 20 => 'Map', + 21 => 'Film', + 21 => 'Broadcast', + 23 => 'Newspaper Article', + 25 => 'Patent', + 26 => 'Personal Communication', + 27 => 'Report', + 28 => 'Edited Book', + 31 => 'Statute', + 32 => 'Thesis', + 34 => 'Unpublished', + 36 => 'Manuscript', + 37 => 'Figure', + 38 => 'Chart', + 39 => 'Equation', + 43 => 'Electronic Article', + 44 => 'Electronic Book', + 45 => 'Online Database', + 46 => 'Government Document', + 47 => 'Conference Paper', + 48 => 'Online Multimedia', + 49 => 'Classical Work', + 50 => 'Legal Ruling', + 52 => 'Dictionary', + 53 => 'Encyclopedia', + 54 => 'Grant', + ) + ); + $map['format'] = 'endnote8'; + return $map; +} + +function _get_endnote8_field_map() { + + $map['field_map'] = serialize( + array( + 'source-app' => '', + 'rec-number' => '', + 'ref-type' => 'biblio_type', + 'auth-address' => 'biblio_auth_address', + 'auth-affiliaton' => '', + 'secondary-title' => 'biblio_secondary_title', + 'tertiary-title' => 'biblio_tertiary_title', + 'alt-title' => 'biblio_alternate_title', + 'short-title' => 'biblio_short_title', + 'translated-title' => 'biblio_translated_title', + 'full-title' => 'biblio_secondary_title', + 'abbr-1' => 'biblio_short_title', + 'abbr-2' => '', + 'abbr-3' => '', + 'pages' => 'biblio_pages', + 'volume' => 'biblio_volume', + 'number' => 'biblio_number', + 'issue' => 'biblio_issue', + 'secondary-volume' => '', + 'secondary-issue' => '', + 'num-vols' => 'biblio_number_of_volumes', + 'edition' => 'biblio_edition', + 'section' => 'biblio_section', + 'reprint-edition' => 'biblio_reprint_edition', + 'reprint-status' => '', + 'year' => 'biblio_year', + 'pub-dates' => 'biblio_date', + 'copyright-dates' => '', + 'pub-location' => 'biblio_place_published', + 'publisher' => 'biblio_publisher', + 'orig-pub' => 'biblio_original_publication', + 'isbn' => 'biblio_isbn', + 'accession-num' => 'biblio_accession_number', + 'call-num' => 'biblio_call_number', + 'report-id' => '', + 'coden' => '', + 'electronic-resource-num' => '', + 'abstract' => 'biblio_abst_e', + 'label' => 'biblio_label', + 'image' => '', + 'caption' => '', + 'notes' => 'biblio_notes', + 'research-notes' => 'biblio_research_notes', + 'work-type' => 'biblio_type_of_work', + 'reviewed-item' => '', + 'availability' => '', + 'remote-source' => '', + 'meeting-place' => '', + 'work-location' => '', + 'work-extent' => '', + 'pack-method' => '', + 'size' => '', + 'repro-ratio' => '', + 'remote-database-name' => 'biblio_remote_db_name', + 'remote-database-provider' => 'biblio_remote_db_provider', + 'language' => 'biblio_lang', + 'web-urls' => '', + 'pdf-urls' => '', + 'text-urls' => '', + 'image-urls' => '', + 'related-urls' => 'biblio_url', + 'access-date' => 'biblio_access_date', + 'modified-date' => '', + 'custom1' => 'biblio_custom1', + 'custom2' => 'biblio_custom2', + 'custom3' => 'biblio_custom3', + 'custom4' => 'biblio_custom4', + 'custom5' => 'biblio_custom5', + 'custom6' => 'biblio_custom6', + 'custom7' => 'biblio_custom7', + 'misc1' => '', + 'misc2' => '', + 'misc3' => '', + ) + ); + + $map['format'] = 'endnote8'; + return $map; +} +function _get_endnote7_type_map() { + + $map['type_map'] = serialize( + array( + 0 => 102, // Journal Article + 1 => 100, // Book + 2 => 108, // Thesis + 3 => 103, // Conference Proceedings + 4 => 120, // Personal Communication + 5 => 105, // NewsPaper Article + 6 => 113, // Computer Program + 7 => 101, // Book Section + 8 => 106, // Magazine Article + 9 => 100, // Edited Book + 10 => 109, // Report + 11 => 122, // Map + 12 => 114, // Audiovisual Material + 13 => 112, // Artwork + 15 => 119, // Patent + 16 => 107, // Electronic Source + 17 => 117, // Bill + 18 => 116, // Case + 19 => 115, // Hearing + 20 => 121, // Manuscript + 21 => 110, // Film or Broadcast + 22 => 118, // Statute + 26 => 123, // Chart or Table + 31 => 129 // Generic + ) + ); + $map['format'] = 'endnote7'; + return $map; +} +function _get_endnote7_type_names() { + + $map['type_names'] = serialize( + array( + 0 => 'Journal Article', + 1 => 'Book', + 2 => 'Thesis', + 3 => 'Conference Proceedings', + 4 => 'Personal Communication', + 5 => 'NewsPaper Article', + 6 => 'Computer Program', + 7 => 'Book Section', + 8 => 'Magazine Article', + 9 => 'Edited Book', + 10 => 'Report', + 11 => 'Map', + 12 => 'Audiovisual Material', + 13 => 'Artwork', + 15 => 'Patent', + 16 => 'Electronic Source', + 17 => 'Bill', + 18 => 'Case', + 19 => 'Hearing', + 20 => 'Manuscript', + 21 => 'Film or Broadcast', + 22 => 'Statute', + 26 => 'Chart or Table', + 31 => 'Generic', + ) + ); + $map['format'] = 'endnote7'; + return $map; +} + +function _get_endnote7_field_map() { + + $map['field_map'] = serialize( + array( + 'REFERENCE_TYPE' => 'biblio_type', + 'REFNUM' => '', + 'YEAR' => 'biblio_year', + 'SECONDARY_TITLE' => 'biblio_secondary_title', + 'PLACE_PUBLISHED' => 'biblio_place_published', + 'PUBLISHER' => 'biblio_publisher', + 'VOLUME' => 'biblio_volume', + 'ISSUE' => 'biblio_issue', + 'NUMBER_OF_VOLUMES' => 'biblio_number_of_volumes', + 'NUMBER' => 'biblio_number', + 'PAGES' => 'biblio_pages', + 'SECTION' => 'biblio_section', + 'TERTIARY_TITLE' => 'biblio_tertiary_title', + 'EDITION' => 'biblio_edition', + 'DATE' => 'biblio_date', + 'TYPE_OF_WORK' => 'biblio_type_of_work', + 'SHORT_TITLE' => 'biblio_short_title', + 'ALTERNATE_TITLE' => 'biblio_alternate_title', + 'ISBN' => 'biblio_isbn', + 'ORIGINAL_PUB' => 'biblio_original_publication', + 'REPRINT_EDITION' => 'biblio_reprint_edition', + 'REVIEWED_ITEM' => '', + 'CUSTOM1' => 'biblio_custom1', + 'CUSTOM2' => 'biblio_custom2', + 'CUSTOM3' => 'biblio_custom3', + 'CUSTOM4' => 'biblio_custom4', + 'CUSTOM5' => 'biblio_custom5', + 'CUSTOM6' => 'biblio_custom6', + 'ACCESSION_NUMBER' => 'biblio_accession_number', + 'CALL_NUMBER' => 'biblio_call_number', + 'LABEL' => 'biblio_label', + 'KEYWORD' => 'biblio_keywords', + 'ABSTRACT' => 'biblio_abst_e', + 'NOTES' => 'biblio_notes', + 'URL' => 'biblio_url', + 'AUTHOR_ADDRESS' => '', + 'IMAGE' => '', + 'CAPTION' => '', + ) + ); + + $map['format'] = 'endnote7'; + return $map; +} +/** + * Implementation of hook_schema(). + * + * Note: Pro Drupal Development models use of t() to translate 'description' + * for field definitions, but Drupal core does not use them. We follow core. + */ +function biblio_xml_schema() { + $schema = array(); + $schema['biblio_xml'] = array( + 'fields' => array( + 'nid' => array('type' => 'int', 'not null' => TRUE), + 'biblio_xml_md5' => array('type' => 'char', 'length' => 32, 'not null' => TRUE), + ), + 'primary key' => array('nid'), + ); + return $schema; +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/endnote/biblio_xml.module --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/endnote/biblio_xml.module Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,139 @@ + 2, + 'path' => drupal_get_path('module', 'biblio_xml') . '/views', + ); +} + + /* + * add the xml option to the option list of the biblio_import_form + * the key is the module name use by module_invoke to call hook_biblio_import + * module_invoke('biblio_xml', 'biblio_import',...) + */ +function biblio_xml_biblio_import_options() { + return array('biblio_xml' => t('EndNote XML')); +} +function biblio_xml_biblio_mapper_options() { + return array( + 'endnote7' => array( + 'title' => t('EndNote 7 XML'), + 'export' => TRUE, + ), + 'endnote8' => array( + 'title' => t('EndNote X3 XML'), + 'export' => TRUE, + ), + ); +} + +function biblio_xml_biblio_export_options() { + return array('xml' => t('EndNote XML')); +} + +function biblio_xml_node_view($node, $view_mode) { + if ($node->type == 'biblio') { + switch ($view_mode) { + case 'full': + case 'teaser': + $links = biblio_xml_biblio_export_link($node->nid); + $node->content['links']['biblio_xml'] = array( + '#links' => $links, + '#attributes' => array('class' => array('links', 'inline')), + ); + } + } +} + +/** + * Creates a link to export a node (or view) in xml format + * + * @param $base this is the base url (defaults to /biblio) + * @param $nid the node id, if NULL then the current view is exported + * @return a link (xml) + */ +function biblio_xml_biblio_export_link($nid = NULL, $filter = array()) { + $show_link = variable_get('biblio_export_links', array('xml' => TRUE)); + if (!isset($show_link['xml']) || empty($show_link['xml']) || !biblio_access('export')) { + return array(); + } + $base = variable_get('biblio_base', 'biblio'); + + $link = array(); + $link['attributes']['title'] = t("Click to download the EndNote XML formatted file"); + $link['attributes'] += array('rel' => 'nofollow'); + + $link['href'] = "$base/export/xml"; + if (!empty($nid)) { + $link['href'] .= '/' . $nid; + } + $link['title'] = t('XML'); + + if (empty($nid) && !empty($filter)) { // add any filters which may be on the current page + $link['query'] = $filter; + } + return array('biblio_xml' => $link); +} + +function biblio_xml_node_delete($node) { + if ($node->type != 'biblio') { + return; + } + db_delete('biblio_xml') + ->condition('nid', $node->nid) + ->execute(); +} + +function biblio_xml_node_insert($node) { + if ($node->type != 'biblio' || !isset($node->biblio_xml_md5)) { + return; + } + drupal_write_record('biblio_xml', $node); +} + +function biblio_xml_biblio_import($file, $terms = array(), $batch = FALSE, $session_id = NULL, $save = TRUE, $string = FALSE) { + module_load_include('inc', 'biblio_xml', 'endnote_xml_parser'); + + $nids = array(); + $dups = array(); + + $parser = new EndNoteXMLParser; + + list($nids, $dups) = $parser->parse($file, $terms, $batch, $session_id); + + return array($nids, $dups); +} + +function biblio_xml_biblio_export($nids) { + module_load_include('inc', 'biblio_xml', 'endnote8_export'); + drupal_add_http_header('Content-type', 'application/xml; charset=utf-8'); + drupal_add_http_header('Content-Disposition', 'attachment; filename="Biblio-EndNote.xml"'); + + print _endnote8_XML_export('', 'begin'); + $nodes = node_load_multiple($nids, array(), TRUE); + foreach ($nodes as $node) { + // $node = node_load($nid, FALSE, TRUE); + if (variable_get('biblio_hide_bibtex_braces', 0) ) { + $node->title = biblio_remove_brace($node->title); + } + print _endnote8_XML_export($node); + } + + print _endnote8_XML_export('', 'end'); +} + +function biblio_xml_endnote8_map_reset($type = NULL) { + module_load_include('install', 'biblio_xml', 'biblio_xml'); + _reset_endnote_xml_map('endnote8', $type); +} + +function biblio_xml_endnote7_map_reset($type = NULL) { + module_load_include('install', 'biblio_xml', 'biblio_xml'); + _reset_endnote_xml_map('endnote7', $type); +} + + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/endnote/endnote8_export.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/endnote/endnote8_export.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,201 @@ +'; + $xml .= ""; + break; + case 'record': + $xml = ""; + $xml .= 'Drupal-Biblio'; + $xml .= "" . _endnote8_type_map($node->biblio_type) . ""; + unset($node->biblio_type); + // + $xml .= en8_add_contributors($node); + $xml .= en8_add_titles($node); + $xml .= en8_add_keywords($node); + $xml .= en8_add_dates($node); + $xml .= en8_add_urls($node); + + foreach ($node as $key => $value) { + $entag = en8_field_map($key); + if (!empty($entag) && !empty($value)) { + $xml .= "<" . $entag . '>"; + } + } + $xml .= ""; + break; + case 'end': + $xml = ''; + break; + } + return $xml; +} + +function en8_encode_font_faces(&$node) { + $search = array('', '', '', '', '', '', '', '', '', ''); + $replace = array( + '" :''; + $xml .= (!empty ($node->biblio_secondary_title)) ? '" :''; + $xml .= (!empty ($node->biblio_tertiary_title)) ? '" :''; + $xml .= (!empty ($node->biblio_alternate_title)) ? '" :''; + $xml .= (!empty ($node->biblio_short_title)) ? '" :''; + $xml .= (!empty ($node->biblio_translated_title)) ? '" :''; + $xml .= ''; + unset($node->title); + unset($node->biblio_secondary_title); + unset($node->biblio_tertiary_title); + unset($node->biblio_alternate_title); + unset($node->biblio_short_title); + unset($node->biblio_translated_title); + + return $xml; +} +function en8_add_urls(&$node) { + global $base_path; + $xml = ''; + // TODO: fix URLS + if (!empty($node->biblio_url)) { + $xml .= ""; + $xml .= '"; + $xml .= ""; + } + unset($node->biblio_url); + if (!empty ($node->upload) && count($node->upload['und']) && user_access('view uploaded files')) { + $xml .= ""; + foreach ($node->upload['und'] as $file) { + $xml .= '"; + } + $xml .= ""; + } + unset($node->upload['und']); + if (!empty($xml)) return "$xml"; + return ; +} + +function en8_add_dates(&$node) { + $xml = ''; + if (!empty($node->biblio_year) || !empty($node->biblio_date) ) { + $xml .= ''; + $xml .= (!empty($node->biblio_year)) ? '":''; + $xml .= (!empty($node->biblio_date)) ? '":''; + $xml .= ""; + } + unset($node->biblio_year); + unset($node->biblio_date); + return $xml; +} + +function en8_add_keywords(&$node) { + $kw_array = array(); + $xml = ''; + if (!empty($node->biblio_keywords)) { + foreach ($node->biblio_keywords as $term) { + $kw_array[] = trim($term); + } + } + if (!empty($kw_array)) { + $kw_array = array_unique($kw_array); + $xml .= ''; + foreach ($kw_array as $word) { + $xml .= '"; + } + $xml .= ""; + } + unset($node->biblio_keywords); + return $xml; +} + +function en8_add_contributors(&$node) { + $xml = ''; + $authors = biblio_get_contributor_category($node->biblio_contributors, 1); + if (!empty($authors)) { + $xml .= ""; + foreach ($authors as $auth) { + $xml .= '"; + } + $xml .= ""; + } + $authors = biblio_get_contributor_category($node->biblio_contributors, 2); + if (!empty($authors)) { + $xml .= ""; + foreach ($authors as $auth) { + $xml .= '"; + } + $xml .= ""; + } + $authors = biblio_get_contributor_category($node->biblio_contributors, 3); + if (!empty($authors)) { + $xml .= ""; + foreach ($authors as $auth) { + $xml .= '"; + } + $xml .= ""; + } + $authors = biblio_get_contributor_category($node->biblio_contributors, 4); + if (!empty($authors)) { + $xml .= ""; + foreach ($authors as $auth) { + $xml .= '"; + } + $xml .= ""; + } + $authors = biblio_get_contributor_category($node->biblio_contributors, 5); + if (!empty($authors)) { + $xml .= ""; + foreach ($authors as $auth) { + $xml .= '"; + } + $xml .= ""; + } + $xml .= ''; + unset($node->biblio_contributors); + return $xml; +} + +function en8_field_map($biblio_field) { + static $fmap = array(); + if (empty($fmap)) { + $fmap = biblio_get_map('field_map', 'endnote8'); + } + return ($en8_field = array_search($biblio_field, $fmap)) ? $en8_field : ''; +} + +function _endnote8_type_map($bibliotype) { + static $map = array(); + if (empty($map)) { + $map = biblio_get_map('type_map', 'endnote8'); + } + return ($en8_type = array_search($bibliotype, $map)) ? $en8_type : 13; //return the biblio type or 129 (Misc) if type not found +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/endnote/endnote_xml_parser.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/endnote/endnote_xml_parser.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,456 @@ +terms = $terms; + $this->batch_proc = $batch; + $this->session_id = $session_id; + $this->nids = array(); + $this->dups = array(); + $this->unmapped = array(); + + if (!($fp = fopen($file->uri, "r"))) { + drupal_set_message(t("could not open XML input"), 'error'); + return; + } + $data = fread($fp, 2048); + if ((strpos($data, 'record') !== FALSE) && (strpos($data, 'ref-type') !== FALSE)) { + $this->format = 'endnote8'; + } + elseif (strpos($data, 'RECORD') !== FALSE && strpos($data, 'REFERENCE_TYPE') !== FALSE) { + $this->format = 'endnote7'; + } + if ($this->format) { + $this->parser = drupal_xml_parser_create($data); + xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, FALSE); + xml_parser_set_option($this->parser, XML_OPTION_SKIP_WHITE, TRUE); + xml_set_object($this->parser, $this); + xml_set_element_handler($this->parser, $this->format . '_startElement', $this->format . '_endElement'); + xml_set_character_data_handler($this->parser, $this->format . '_characterData'); + + xml_parse($this->parser, $data, feof($fp)); + + while ($data = fread($fp, 2048)) { + // $data = fread($fp, 2048); + set_time_limit(300); + if (!xml_parse($this->parser, $data, feof($fp))) { + drupal_set_message(sprintf("XML error: %s at line %d", + xml_error_string(xml_get_error_code($this->parser)), + xml_get_current_line_number($this->parser)), 'error'); + } + } + xml_parser_free($this->parser); + } + + fclose($fp); + + if (!empty($this->unmapped)) { + $ignored_tags = array_unique($this->unmapped); + $message = t("The following elements were ignored because they do not map to any biblio fields:") . ' '; + $message .= implode(', ', $ignored_tags); + if (user_access('administer biblio')) { + $message .= '. ' . t('Click !url if you wish to check the field mapping', array('!url' => l(t('here'), 'admin/config/content/biblio/iomap/edit/' . $this->format))); + } + drupal_set_message($message, 'warning'); + } + return array($this->nids, $this->dups); + + } + + function endnote8_startElement($parser, $name, $attrs) { + switch ($name) { + case 'record' : + $this->node = new stdClass(); + $this->node->biblio_contributors = array(); + break; + case 'style' : + $this->font_attr = explode(' ', $attrs['face']); + foreach ($this->font_attr as $fatt) { + switch ($fatt) { + case 'normal': + break; + case 'bold': + $this->endnote8_characterData(NULL, ''); + break; + case 'italic': + $this->endnote8_characterData(NULL, ''); + break; + case 'underline': + $this->endnote8_characterData(NULL, ''); + break; + case 'superscript': + $this->endnote8_characterData(NULL, ''); + break; + case 'subscript': + $this->endnote8_characterData(NULL, ''); + break; + } + } + break; + case 'keywords' : + $this->keyword_count = 0; + break; + case 'authors' : + case 'secondary-authors' : + case 'tertiary-authors' : + case 'subsidiary-authors' : + case 'translated-authors' : + $this->contributors_type = $name; + $this->contributors = array(); + $this->contrib_count = 0; + break; + case 'author' : + $this->contributors[$this->contrib_count]['name'] = ''; + $this->element = $name; + break; + case 'year' : + case 'pub-dates' : + case 'copyright-dates' : + $this->dates = $name; + break; + case 'web-urls' : + case 'pdf-urls' : + case 'text-urls' : + case 'related-urls' : + case 'image-urls' : + $this->urls = $name; + break; + case 'keyword': + $this->node->biblio_keywords[$this->keyword_count] = ''; + $this->element = $name; + break; + + default : + $this->element = $name; + } + } + + function endnote8_endElement($parser, $name) { + // global $this->node, $nids, $this->element, $terms, $batch_proc, $session_id, $this->contributors_type, $this->contrib_count, $this->dates, $this->urls, $this->keyword_count, $this->font_attr; + switch ($name) { + case 'record' : + $this->element = $this->contributors_type = $this->contrib_count = $this->dates = $this->urls = ''; + $this->node->biblio_xml_md5 = md5(serialize($this->node)); + if ( !($dup = $this->biblio_xml_check_md5($this->node->biblio_xml_md5)) ) { + biblio_save_node($this->node, $this->terms, $this->batch_proc, $this->session_id); + if (!empty($this->node->nid)) $this->nids[] = $this->node->nid; + } + else { + $this->dups[] = $dup; + } + break; + case 'authors' : + case 'secondary-authors' : + case 'tertiary-authors' : + case 'subsidiary-authors' : + case 'translated-authors' : + $this->contributors_type = ''; + foreach ($this->contributors as $contributor) { + $this->node->biblio_contributors[] = $contributor; + } + break; + case 'author' : + switch ($this->contributors_type) { + case 'authors' : + $this->contributors[$this->contrib_count]['auth_category'] = 1; + $this->contributors[$this->contrib_count]['auth_type'] = 1; + break; + case 'secondary-authors' : + $this->contributors[$this->contrib_count]['auth_category'] = 2; + $this->contributors[$this->contrib_count]['auth_type'] = 2; + break; + case 'tertiary-authors' : + $this->contributors[$this->contrib_count]['auth_category'] = 3; + $this->contributors[$this->contrib_count]['auth_type'] = 3; + break; + case 'subsidiary-authors' : + $this->contributors[$this->contrib_count]['auth_category'] = 4; + $this->contributors[$this->contrib_count]['auth_type'] = 4; + break; + case 'translated-authors' : + $this->contributors[$this->contrib_count]['auth_category'] = 5; + $this->contributors[$this->contrib_count]['auth_type'] = 5; + break; + } + $this->contrib_count++; + break; + case 'keyword' : + $this->keyword_count++; + break; + case 'year' : + case 'pub-dates' : + case 'copyright-dates' : + $this->dates = ''; + break; + case 'web-urls' : + case 'pdf-urls' : + case 'text-urls' : + case 'related-urls' : + case 'image-urls' : + $this->urls = ''; + break; + case 'ref-type': + $this->node->biblio_type = $this->type_map($this->node->biblio_type); + $this->element = ''; + break; + case 'style' : + foreach ($this->font_attr as $fatt) { + switch ($fatt) { + case 'normal': + break; + case 'bold': + $this->endnote8_characterData(NULL, ''); + break; + case 'italic': + $this->endnote8_characterData(NULL, ''); + break; + case 'underline': + $this->endnote8_characterData(NULL, ''); + break; + case 'superscript': + $this->endnote8_characterData(NULL, ''); + break; + case 'subscript': + $this->endnote8_characterData(NULL, ''); + break; + } + } + $this->font_attr = array(); + break; + default : + $this->element = ''; + } + + + } + + function endnote8_characterData($parser, $data) { + // first replace any carriage returns with html line breaks + $data = str_ireplace("\r", "
    ", $data); + if (trim(htmlspecialchars_decode($data))) { + switch ($this->element) { + //Author information + case 'author' : + $this->contributors[$this->contrib_count]['name'] .= $data; + break; + case 'keyword' : + $this->node->biblio_keywords[$this->keyword_count] .= $data; + break; + case 'dates' : + switch ($this->dates) { + case 'year' : + $this->node->biblio_year .= $data; + break; + } + break; + case 'date' : + switch ($this->dates) { + case 'pub-dates' : + $this->node->biblio_date .= $data; + break; + case 'copyright-dates' : + break; + } + break; + case 'urls' : + case 'url' : + switch ($this->urls) { + case 'web-urls' : + $this->node->biblio_url .= $data; + break; + case 'pdf-urls' : + case 'text-urls' : + case 'image-urls' : + break; + case 'related-urls' : + } + break; + case 'title': + $this->node->title .= $data; + break; + default: + if ($field = $this->field_map(trim($this->element))) { + $this->node->$field .= $data; + } + else { + if (!in_array($this->element, $this->unmapped)) { + $this->unmapped[] = $this->element; + } + } + } + } + } + + function endnote7_startElement($parser, $name, $attrs) { + switch ($name) { + case 'RECORD' : + $this->node = new stdClass(); + $this->node->biblio_contributors = array(); + $this->node->biblio_type = 102; // we set 102 here because the xml parser won't + // process a value of 0 (ZERO) which is the + // ref-type 102. if there is a non-zero value it will be overwritten + $this->element = ''; + break; + case 'AUTHORS': + case 'SECONDARY_AUTHORS': + case 'TERTIARY_AUTHORS': + case 'SUBSIDIARY_AUTHORS': + $this->contrib_count = 0; + $this->contributors = array(); + break; + case 'AUTHOR': + case 'SECONDARY_AUTHOR': + case 'TERTIARY_AUTHOR': + case 'SUBSIDIARY_AUTHOR': + $this->contributors[$this->contrib_count]['name'] = ''; + $this->element = $name; + break; + case 'KEYWORDS': + $this->keyword_count = 0; + break; + case 'KEYWORD': + $this->node->biblio_keywords[$this->keyword_count] = ''; + $this->element = $name; + break; + default: + $this->element = $name; + } + } + + function endnote7_endElement($parser, $name) { + switch ($name) { + case 'RECORD' : + $this->node->biblio_xml_md5 = md5(serialize($this->node)); + if ( !($dup = $this->biblio_xml_check_md5($this->node->biblio_xml_md5)) ) { + biblio_save_node($this->node, $this->terms, $this->batch_proc, $this->session_id); + if (!empty($this->node->nid)) $this->nids[] = $this->node->nid; + } + else { + $this->dups[] = $dup; + } + break; + case 'AUTHORS': + case 'SECONDARY_AUTHORS': + case 'TERTIARY_AUTHORS': + case 'SUBSIDIARY_AUTHORS': + $this->contributors_type = ''; + foreach ($this->contributors as $contributor) { + $this->node->biblio_contributors[] = $contributor; + } + break; + case 'AUTHOR': + $this->contributors[$this->contrib_count]['auth_category'] = 1; + $this->contributors[$this->contrib_count]['auth_type'] = 1; + $this->contrib_count++; + break; + case 'SECONDARY_AUTHOR': + $this->contributors[$this->contrib_count]['auth_category'] = 2; + $this->contributors[$this->contrib_count]['auth_type'] = 2; + $this->contrib_count++; + break; + case 'TERTIARY_AUTHOR': + $this->contributors[$this->contrib_count]['auth_category'] = 3; + $this->contributors[$this->contrib_count]['auth_type'] = 3; + $this->contrib_count++; + break; + case 'SUBSIDIARY_AUTHOR': + $this->contributors[$this->contrib_count]['auth_category'] = 4; + $this->contributors[$this->contrib_count]['auth_type'] = 4; + $this->contrib_count++; + break; + case 'KEYWORD': + $this->keyword_count++; + break; + default: + + } + $this->element = ''; + } + + function endnote7_characterData($parser, $data) { + if (trim($data)) { + switch ($this->element) { + case 'REFERENCE_TYPE': + $this->node->biblio_type = $this->type_map($data); + break; + case 'AUTHOR': + case 'SECONDARY_AUTHOR': + case 'TERTIARY_AUTHOR': + case 'SUBSIDIARY_AUTHOR': + $this->contributors[$this->contrib_count]['name'] .= $data; + break; + case 'KEYWORD': + $this->node->biblio_keywords[$this->keyword_count] .= $data; + break; + case 'TITLE': + $this->node->title .= $data; + break; + default: + if ($field = $this->field_map(trim($this->element))) { + $this->node->$field .= $data; + } + else { + if (!in_array($this->element, $this->unmapped)) { + $this->unmapped[] = $this->element; + } + } + } + } + } + + function field_map($enfield) { + static $fmap = array(); + if (empty($fmap)) { + $fmap = biblio_get_map('field_map', $this->format); + } + return (!empty($fmap[$enfield])) ? $fmap[$enfield] : ''; + } + + function type_map($entype) { + static $map = array(); + if (empty($map)) { + $map = biblio_get_map('type_map', $this->format); + } + return (isset($map[$entype]))?$map[$entype]:129; //return the biblio type or 129 (Misc) if type not found + } + + function biblio_xml_check_md5($md5) { + static $xml_md5s = array(); + if (empty($xml_md5s)) { + $result = db_query("SELECT * FROM {biblio_xml} "); + foreach ($result as $row) { + $xml_md5s[$row->biblio_xml_md5] = $row->nid; + } + } + if (isset($xml_md5s[$md5])) { + return $xml_md5s[$md5]; + } + else { + $xml_md5s[$md5] = TRUE; // gaurd against duplicates in the same import + return; + } + } + +} \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/marcParse/biblio_marc.info --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/marcParse/biblio_marc.info Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,13 @@ +name = Biblio - MARC +description = Provides MARC file import to the Biblio module. +core = 7.x +package = Biblio +dependencies[] = biblio +files[] = php-marc.php + +; Information added by drupal.org packaging script on 2013-07-20 +version = "7.x-1.0-rc7" +core = "7.x" +project = "biblio" +datestamp = "1374290470" + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/marcParse/biblio_marc.install --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/marcParse/biblio_marc.install Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,96 @@ +condition('format', 'marc') + ->execute(); + } +} + +function biblio_marc_enable() { + biblio_marc_set_system_weight(); +} + +function biblio_marc_set_system_weight() { + db_update('system') + ->fields(array('weight' => 24)) + ->condition('name', 'biblio_marc') + ->execute(); +} + +function _save_marc_maps() { + $maps['type_map'] = serialize( + array( + 'ab' => 102, // Journal Article + 'as' => 102, // Journal Article + 'am' => 100, // Book + 2 => 108, // Thesis + 3 => 103, // Conference Proceedings + 4 => 120, // Personal Communication + 5 => 105, // NewsPaper Article + 6 => 113, // Computer Program + 'aa' => 101, // Book Section + 8 => 106, // Magazine Article + 9 => 100, // Edited Book + 10 => 109, // Report + 'em' => 122, // Map + 12 => 114, // Audiovisual Material + 13 => 112, // Artwork + 15 => 119, // Patent + 16 => 107, // Electronic Source + 17 => 117, // Bill + 18 => 116, // Case + 19 => 115, // Hearing + 20 => 121, // Manuscript + 21 => 110, // Film or Broadcast + 22 => 118, // Statute + 26 => 123, // Chart or Table + 31 => 129 // Generic + + ) + ); + + $maps['type_names'] = serialize( + array( + ) + ); + + $maps['field_map'] = serialize( + array( + ) + ); + + $maps['format'] = 'marc'; + biblio_save_map($maps); + + +} +/** + * Implementation of hook_schema(). + * + * Note: Pro Drupal Development models use of t() to translate 'description' + * for field definitions, but Drupal core does not use them. We follow core. + */ +function biblio_marc_schema() { + $schema = array(); + $schema['biblio_marc'] = array( + 'fields' => array( + 'nid' => array('type' => 'int', 'not null' => TRUE), + 'biblio_marc_md5' => array('type' => 'char', 'length' => 32, 'not null' => TRUE), + ), + 'primary key' => array('nid'), + ); + return $schema; +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/marcParse/biblio_marc.module --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/marcParse/biblio_marc.module Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,376 @@ + t('MARC')); +} + +function biblio_marc_node_delete($node) { + if ($node->type != 'biblio') { + return; + } + db_delete('biblio_marc') + ->condition('nid', $node->nid) + ->execute(); +} + +function biblio_marc_node_insert($node) { + if ($node->type != 'biblio') { + return; + } + if (!isset($node->biblio_marc_md5)) { + return; + } + drupal_write_record('biblio_marc', $node); +} + +function biblio_marc_biblio_import($file, $terms = array(), $batch = FALSE, $session_id = NULL, $save = TRUE, $string = FALSE) { + $nids = array(); + $dups = array(); + module_load_include('php', 'biblio_marc', 'php-marc'); + $marcfile = new File($file->uri); + while ($record = $marcfile->next() ) { + $node = new stdClass(); + $node->biblio_contributors = array(); + $fields = $record->fields(); + $leader = $record->leader(); + $pubtype = $leader[6]; + $pubtype .= $leader[7]; + $node->biblio_type = _biblio_marc_type_map($pubtype); + foreach ($record->fields() as $fields) { + foreach ($fields as $field) { + $tagnum = $field->tagno; + switch ($tagnum) { + case '008': + $data = $field->data(); + $node->biblio_year = substr($data, 7, 4); + $node->biblio_lang = substr($data, 35, 3); + break; + case '020': + $node->biblio_isbn = $field->subfield('a'); + break; + case '022': + $node->biblio_issn = $field->subfield('a'); + break; + case '024': + $node->biblio_other_number = $field->subfield('a'); + break; + case '050': //LIBRARY OF CONGRESS CALL NUMBER + case '055': //CLASSIFICATION NUMBERS ASSIGNED IN CANADA + case '060': //NATIONAL LIBRARY OF MEDICINE CALL NUMBER + $node->biblio_call_number = $field->subfield('a'); + break; + case '130': + $node->title = str_replace(' /', '', $field->subfield('a')); + break; + case '210': + $node->biblio_short_title = str_replace(' /', '', $field->subfield('a')); + break; + case '245': + $node->title = str_replace(' /', '', $field->subfield('a')) . ' ' . $field->subfield('b'); + break; + case '250': + $node->biblio_edition = $field->subfield('a'); + break; + case '260': + $node->biblio_place_published = str_replace(' :', '', $field->subfield('a')); + $node->biblio_publisher = $field->subfield('b'); + $node->biblio_date = $field->subfield('c'); + break; + case '300': + $node->biblio_pages = $field->subfield('a'); + break; + case '490': + $node->biblio_volume = $field->subfield('v'); + break; + case ($tagnum >= 500 && $tagnum <= 599): + $value = $field->subfield('a'); + if (!empty($value)) { + $node->biblio_notes .= $value; + } + break; + case '650': + foreach ($field->subfields() as $subject) { + $node->biblio_keywords[] = $subject[0]; + } + break; + case '100': + case '700': + $value = $field->subfield('a'); + if (!empty($value)) { + $node->biblio_contributors[] = array( + 'name' => $value, + 'auth_category' => 1, + 'auth_type' => 1 + ); + } + break; + case '110': + case '710': + $node->biblio_contributors[] = array( + 'name' => $field->subfield('a'), + 'auth_category' => 5, + 'auth_type' => 5 + ); + break; + case '856': + $value = $field->subfield('u'); + if (!empty($value)) { + $node->biblio_url = $value; + } + break; + } + } + } + if (!empty($node)) { + $node->biblio_marc_md5 = md5(serialize($node)); + + if (! ($dup = biblio_marc_check_md5($node->biblio_marc_md5))) { + biblio_save_node($node, $terms, $batch, $session_id); + if (!empty($node->nid)) $nids[] = $node->nid; + } + else { + $dups[] = $dup; + } + } + + } + return array($nids, $dups); +} + +function biblio_marc_check_md5($md5) { + static $marc_md5s = array(); + if (empty($marc_md5s)) { + $result = db_query("SELECT * FROM {biblio_marc} "); + foreach ($result as $row) { + $marc_md5s[$row->biblio_marc_md5] = $row->nid; + } + } + if (isset($marc_md5s[$md5])) { + return $marc_md5s[$md5]; + } + else { + $marc_md5s[$md5] = TRUE; // gaurd against duplicates in the same import + return; + } +} + + +function _biblio_marc_type_map($type, $reverse = FALSE) { + static $map = array(); + + if (empty($map)) { + $map = biblio_get_map('type_map', 'marc'); + } + + if ($reverse) { + return ($tag = array_search($type, $map)) ? $tag : 'Generic'; //return the biblio type or 129 (Misc) if type not found + } + return (isset($map[$type]))?$map[$type]:129; //return the biblio type or 129 (Misc) if type not found +} + +function biblio_marc_biblio_export_options() { + return array('marc' => t('MARC')); +} + +function biblio_marc_node_view($node, $view_mode) { + if ($node->type == 'biblio') { + switch ($view_mode) { + case 'full': + case 'teaser': + $links = biblio_marc_biblio_export_link($node->nid); + $node->content['links']['biblio_marc'] = array( + '#links' => $links, + '#attributes' => array('class' => array('links', 'inline')), + ); + } + } +} + +/** + * Creates a link to export a node (or view) in MARC format + * + * @param $nid the node id, if NULL then the current view is exported + * @return a link (marc) + */ +function biblio_marc_biblio_export_link($nid = NULL, $filter = array()) { + $show_link = variable_get('biblio_export_links', array('marc' => TRUE)); + if (!isset($show_link['marc']) || empty($show_link['marc']) || !biblio_access('export')) { + return array(); + } + $base = variable_get('biblio_base', 'biblio'); + + if (module_exists('popups') && !empty($nid)) { + $link = array( + 'attributes' => array( + 'class' => 'popups', + 'title' => t("Click to get the MARC formatted output"))); + } + else { + $link = array( + 'attributes' => array( + 'title' => t("Click to download the MARC formatted file"))); + } + + $link['attributes'] += array('rel' => 'nofollow'); + + $link['href'] = "$base/export/marc"; + if (!empty($nid)) { + $link['href'] .= '/' . $nid; + } + $link['title'] = t('MARC'); + + if (empty($nid) && !empty($filter)) { // add any filters which may be on the current page + $link['query'] = $filter; + } + + return array('biblio_marc' => $link); +} + +function biblio_marc_biblio_export($nids) { + if (module_exists('popups') && count($nids)) { + $popup = TRUE; + } + else { + $popup = FALSE; + drupal_add_http_header('Content-type', 'application/text; charset=utf-8'); + drupal_add_http_header('Content-Disposition', 'attachment; filename="Biblio.mrc"'); + } + + $nodes = node_load_multiple($nids, array(), TRUE); + foreach ($nodes as $node) { + if (!$popup) { + print _biblio_marc_export($node); + } + else{ + $popup_data .= _biblio_marc_export($node); + } + } + if ($popup && !empty($popup_data)) return '
    ' . $popup_data . '
    '; +} + +function _biblio_marc_export($node) { + module_load_include('php', 'biblio_marc', 'php-marc'); + $record = new Record(); + // case '008': + // $data = $field->data(); + // $node->biblio_year = substr($data, 7, 4); + // $node->biblio_lang = substr($data, 35, 3); + // break; + $leader = $record->leader(); + if ($node->biblio_type == 100) { + $type = 'nam a'; + } + else { + $type = 'nas a'; + } + $record->leader(substr_replace($leader, $type, 5, 5)); + + $rec_eight = str_repeat(' ', 40); + $rec_eight = substr_replace($rec_eight, $node->biblio_year, 7, 4); + $rec_eight = substr_replace($rec_eight, $node->biblio_lang, 35, 3); + $rec_eight = substr_replace($rec_eight, 'd', 39, 1); + $field = new Field("008", $rec_eight); + $record->append_fields($field); + + if (!empty($node->biblio_isbn)) { + $field = new Field("020", "", "", array("a" => $node->biblio_isbn)); + $record->append_fields($field); + } + if (!empty($node->biblio_issn)) { + $field = new Field("022", "", "", array("a" => $node->biblio_issn)); + $record->append_fields($field); + } + if (!empty($node->biblio_other_number)) { + $field = new Field("024", "", "", array("a" => $node->biblio_other_number)); + $record->append_fields($field); + } + if (!empty($node->biblio_call_number)) { + $field = new Field("050", "", "", array("a" => $node->biblio_call_number)); + $record->append_fields($field); + } + if (!empty($node->title)) { + $field = new Field("245", "0", "0", array("a" => $node->title)); + $record->append_fields($field); + } + if (!empty($node->biblio_sort_title)) { + $field = new Field("210", "0", "#", array("a" => $node->biblio_sort_title)); + $record->append_fields($field); + } + // case '245': + // $node->title = str_replace(' /', '', $field->subfield('a')) . ' ' . $field->subfield('b'); + // break; + if (!empty($node->biblio_edition)) { + $field = new Field("250", "", "", array("a" => $node->biblio_edition)); + $record->append_fields($field); + } + if (!empty($node->biblio_place_published)) { + $subfields['a'] = $node->biblio_place_published; + } + if (!empty($node->biblio_publisher)) { + $subfields['b'] = $node->biblio_publisher; + } + if (!empty($node->biblio_date)) { + $subfields['c'] = $node->biblio_date; + } + if (!empty($subfields)) { + $field = new Field("260", "", "", $subfields); + $record->append_fields($field); + } + if (!empty($node->biblio_pages)) { + $field = new Field("300", "", "", array("a" => $node->biblio_pages)); + $record->append_fields($field); + } + if (!empty($node->biblio_volume)) { + $field = new Field("490", "0", "", array("v" => $node->biblio_volume)); + $record->append_fields($field); + } + if (!empty($node->biblio_abst_e)) { + $field = new Field("520", "3", "#", array("a" => $node->biblio_abst_e)); + $record->append_fields($field); + } + // case ($tagnum >= 500 && $tagnum <= 599): + // $value = $field->subfield('a'); + // if (!empty($value)) { + // $node->biblio_notes .= $value; + // } + if (!empty($node->biblio_keywords)) { + foreach($node->biblio_keywords as $keyword) { + $field = new Field("653", "1", "0", array("a" => $keyword)); + $record->append_fields($field); + } + } + if (!empty($node->biblio_contributors)) { + foreach ($node->biblio_contributors as $i => $author) { + $first = $author['firstname']; + $last = $author['lastname']; + $init = $author['initials']; + $cat = $author['auth_category']; + $name = $last . ($first ? ', ' . $first : '') . ($init ? ', ' . $init : ''); + $tag = ($i == 0 ? ($cat == 5 ? 110 :100) : ($cat == 5 ? 710 :700)); + $field = new Field($tag, "1", "#", array("a" => $name)); + $record->append_fields($field); + } + } + if (!empty($node->biblio_url)) { + $url = $node->biblio_url; + } + else { + $options['absolute'] = TRUE; + $url = url("node/$node->nid", $options); + } + if (!empty($url)) { + $field = new Field("856", "", "", array("u" => $url)); + $record->append_fields($field); + } + return $record->raw(); + +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/marcParse/example.mrc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/marcParse/example.mrc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1 @@ +01850 2200517 45000010011000000030007000110080039000180200026000570350015000830400007000980420012001050840018001170840018001350840021001530840022001741000030001962450062002262500013002882600058003013000033003594400037003925000023004295990010004527400024004627750034004868410048005208410049005688410047006178410048006648410047007128410047007598520038008068520021008448520013008658520016008788520028008948520021009229000056009439000060009999000057010599000056011169000057011729000060012299760026012890050017013150000000044EMILDA980120s1998 fi j 000 0 swe a9515008808cFIM 72:00 99515008808 aNB 9NB9SEE aHcd,u2kssb/6 5NBauHc2kssb 5SEEaHcf2kssb/6 5QaHcd,uf2kssb/61 aJansson, Tove,d1914-200104aDet osynliga barnet och andra berttelser /cTove Jansson a7. uppl. aHelsingfors :bSchildt,c1998 ;e(Falun :fScandbook) a166, [4] s. :bill. ;c21 cm 0aMumin-biblioteket,x99-0698931-9 aOriginaluppl. 1962 aLi: S4 aDet osynliga barnet1 z951-50-0385-7w9515003857907 5Liaxab0201080u 0 4000uu |000000e1 5SEEaxab0201080u 0 4000uu |000000e1 5Laxab0201080u 0 4000uu |000000e1 5NBaxab0201080u 0 4000uu |000000e1 5Qaxab0201080u 0 4000uu |000000e1 5Saxab0201080u 0 4000uu |000000e1 5NBbNBcNB98:12hpliktjR, 980520 5LibLicCNBhh,u 5SEEbSEE 5QbQj98947 5LbLc0100h98/j3043 H 5SbShSv97j72351saYanson, Tobe,d1914-2001uJansson, Tove,d1914-20011saJanssonov, Tove,d1914-2001uJansson, Tove,d1914-20011saJansone, Tuve,d1914-2001uJansson, Tove,d1914-20011saJanson, Tuve,d1914-2001uJansson, Tove,d1914-20011saJansson, Tuve,d1914-2001uJansson, Tove,d1914-20011saJanssonova, Tove,d1914-2001uJansson, Tove,d1914-2001 2aHcd,ubSknlitteratur20050204111518.0 \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/marcParse/example.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/marcParse/example.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,85 @@ + +// +//----------------------------------------------------------------------------- +// +// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +//----------------------------------------------------------------------------- +// +// $Revision$ +// +//----------------------------------------------------------------------------- + +require_once "../php-marc/php-marc.php"; + +// Other way to access file +/*$string = file("example.mrc"); +$file = new USMARC($string[0]);*/ + +// Open file +$file = new File("example.mrc"); + +// Read next record +$record = $file->next(); + +// Create new field +$field = new Field("245", "", "", array("a" => "Mumin")); +// Add subfield +$field->add_subfields(array("b" => "Det Osynliga Barnet")); +// Other ways to update field +$field->update(array("ind2" => "1", "b" => "Vinter i Mumindalen", "c" => "Tove Jansson")); + +// Replace existing field +$existing =& $record->field("245"); +$existing->replace_with($field); + +$clone = $field->make_clone(); +// Change some more +$clone->update(array("a" => "Muminsagor", "b" => "Muminpappans memoarer")); + +// And append to record +$record->append_fields($clone); + +// Some output +print "
    ";
    +print $record->formatted();
    +print "\n\n";
    +print $file->raw[0];
    +print "\n";
    +print $record->raw();
    +print "\n\n";
    +print $record->ffield("245", "Formatted output: Title: %a, Remainder of title: %b, Responsibility: %c\n");
    +print "
    "; + +?> \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/marcParse/php-marc.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/marcParse/php-marc.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1016 @@ + +// +//----------------------------------------------------------------------------- +// +// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +//----------------------------------------------------------------------------- +// +// $Revision$ +// +//----------------------------------------------------------------------------- + +/** + * Hexadecimal value for Subfield indicator + * @global hex SUBFIELD_INDICATOR + */ +define("SUBFIELD_INDICATOR", "\x1F"); +/** + * Hexadecimal value for End of Field + * @global hex END_OF_FIELD + */ +define("END_OF_FIELD", "\x1E"); +/** + * Hexadecimal value for End of Record + * @global hex END_OF_RECORD + */ +define("END_OF_RECORD", "\x1D"); +/** + * Length of the Directory + * @global integer DIRECTORY_ENTRY_LEN + */ +define("DIRECTORY_ENTRY_LEN", 12); +/** + * Length of the Leader + * @global integer LEADER_LEN + */ +define("LEADER_LEN", 24); + +/** + * Class File + * Class to read MARC records from file(s) + */ +Class File { + + /** + * ========== VARIABLE DECLARATIONS ========== + */ + + /** + * Array containing raw records + * @var array + */ + var $raw; + /** + * Array of warnings + * @var array + */ + var $warn; + /** + * Current position in the array of records + * @var integer + */ + var $pointer; + + /** + * ========== ERROR FUNCTIONS ========== + */ + + /** + * Croaking function + * + * Similar to Perl's croak function, which ends parsing and raises an + * user error with a descriptive message. + * @param string The message to display + */ + function _croak($msg) { + trigger_error($msg, E_USER_ERROR); + } + + /** + * Fuction to issue warnings + * + * Warnings will not be displayed unless explicitly accessed, but all + * warnings issued during parse will be stored + * @param string Warning + * @return string Last added warning + */ + function _warn($msg) { + $this->warn[] = $msg; + return $msg; + } + + /** + * Get warning(s) + * + * Get either all warnings or a specific warning ID + * @param integer ID of the warning + * @return array|string Return either Array of all warnings or specific warning + */ + function warnings($id = "") { + if (!$id) { + return $this->warn; + } else { + if (array_key_exists($id, $this->warn)) { + return $this->warn[$id]; + } else { + return "Invalid warning ID: $id"; + } + } + } + + /** + * ========== PROCESSING FUNCTIONS ========== + */ + + /** + * Return the next raw MARC record + * + * Returns th nexts raw MARC record from the read file, unless all + * records already have been read. + * @return string|FALSE Either a raw record or False + */ + function _next() { + /** + * Exit if we are at the end of the file + */ + if ($this->pointer >= count($this->raw)) { + return FALSE; + } + + /** + * Read next line + */ + $usmarc = $this->raw[$this->pointer++]; + + // remove illegal stuff that sometimes occurs between records + // preg_replace does not know what to do with \x00, thus omitted. + $usmarc = preg_replace("/^[\x0a\x0d]+/", "", $usmarc); + + /** + * Record validation + */ + if ( strlen($usmarc) < 5 ) { + $this->_warn( "Couldn't find record length" ); + } + $reclen = substr($usmarc,0,5); + if ( preg_match("/^\d{5}$/", $reclen) || $reclen != strlen($usmarc) ) { + $this->_warn( "Invalid record length \"$reclen\"" ); + } + + return $usmarc; + } + + /** + * Read in MARC record file + * + * This function will read in MARC record files that either + * contain a single MARC record, or numerous records. + * @param string Name of the file + * @return string Returns warning if issued during read + */ + function file($in) { + if (file_exists($in)) { + $input = file($in); + $recs = explode(END_OF_RECORD, join("", $input)); + // Append END_OF_RECORD as we lost it when splitting + // Last is not record, as it is empty because every record ends + // with END_OF_RECORD. + for ($i = 0; $i < (count($recs)-1); $i++) { + $this->raw[] = $recs[$i].END_OF_RECORD; + } + $this->pointer = 0; + } else { + return $this->_warn("Invalid input file: $i"); + } + } + + /** + * Return next Record-object + * + * Decode the next raw MARC record and return + * @return Record A Record object + */ + function next() { + if ($raw = $this->_next()) { + return $this->decode($raw); + } else { + return FALSE; + } + } + + /** + * Decode a given raw MARC record + * + * "Port" of Andy Lesters MARC::File::USMARC->decode() function into PHP. Ideas and + * "rules" have been used from USMARC::decode(). + * + * @param string Raw MARC record + * @return Record Decoded MARC Record object + */ + function decode($text) { + if (!preg_match("/^\d{5}/", $text, $matches)) { + $this->_croak('Record length "'.substr( $text, 0, 5 ).'" is not numeric'); + } + + $marc = new Record; + + // Store record length + $reclen = $matches[0]; + + if ($reclen != strlen($text)) { + $this->_croak( "Invalid record length: Leader says $reclen bytes, but it's actually ".strlen($text)); + } + + if (substr($text, -1, 1) != END_OF_RECORD) + $this->_croak("Invalid record terminator"); + + // Store leader + $marc->leader(substr( $text, 0, LEADER_LEN )); + + // bytes 12 - 16 of leader give offset to the body of the record + $data_start = 0 + substr( $text, 12, 5 ); + + // immediately after the leader comes the directory (no separator) + $dir = substr( $text, LEADER_LEN, $data_start - LEADER_LEN - 1 ); // -1 to allow for \x1e at end of directory + + // character after the directory must be \x1e + if (substr($text, $data_start-1, 1) != END_OF_FIELD) { + $this->_croak("No directory found"); + } + + // All directory entries 12 bytes long, so length % 12 must be 0 + if (strlen($dir) % DIRECTORY_ENTRY_LEN != 0) { + $this->_croak("Invalid directory length"); + } + + // go through all the fields + $nfields = strlen($dir) / DIRECTORY_ENTRY_LEN; + for ($n=0; $n<$nfields; $n++) { + // As pack returns to key 1, leave place 0 in list empty + list(, $tagno) = unpack("A3", substr($dir, $n*DIRECTORY_ENTRY_LEN, DIRECTORY_ENTRY_LEN)); + list(, $len) = unpack("A3/A4", substr($dir, $n*DIRECTORY_ENTRY_LEN, DIRECTORY_ENTRY_LEN)); + list(, $offset) = unpack("A3/A4/A5", substr($dir, $n*DIRECTORY_ENTRY_LEN, DIRECTORY_ENTRY_LEN)); + + // Check directory validity + if (!preg_match("/^[0-9A-Za-z]{3}$/", $tagno)) { + $this->_croak("Invalid tag in directory: \"$tagno\""); + } + if (!preg_match("/^\d{4}$/", $len)) { + $this->_croak("Invalid length in directory, tag $tagno: \"$len\""); + } + if (!preg_match("/^\d{5}$/", $offset)) { + $this->_croak("Invalid offset in directory, tag $tagno: \"$offset\""); + } + if ($offset + $len > $reclen) { + $this->_croak("Directory entry runs off the end of the record tag $tagno"); + } + + $tagdata = substr( $text, $data_start + $offset, $len ); + + if ( substr($tagdata, -1, 1) == END_OF_FIELD ) { + # get rid of the end-of-tag character + $tagdata = substr($tagdata, 0, -1); + --$len; + } else { + $this->_croak("field does not end in end of field character in tag $tagno"); + } + + if ( preg_match("/^\d+$/", $tagno) && ($tagno < 10) ) { + $marc->append_fields(new Field($tagno, $tagdata)); + } else { + $subfields = explode(SUBFIELD_INDICATOR, $tagdata); + $indicators = array_shift($subfields); + + if ( strlen($indicators) > 2 || strlen( $indicators ) == 0 ) { + $this->_warn("Invalid indicators \"$indicators\" forced to blanks for tag $tagno\n"); + list($ind1,$ind2) = array(" ", " "); + } else { + $ind1 = substr( $indicators, 0, 1 ); + $ind2 = substr( $indicators, 1, 1 ); + } + + // Split the subfield data into subfield name and data pairs + $subfield_data = array(); + foreach ($subfields as $subfield) { + if ( strlen($subfield) > 0 ) { + $subfield_data[substr($subfield, 0, 1)][] = substr($subfield, 1); + } else { + $this->_warn( "Entirely empty subfield found in tag $tagno" ); + } + } + + if (!isset($subfield_data)) { + $this->_warn( "No subfield data found $location for tag $tagno" ); + } + + $marc->append_fields(new Field($tagno, $ind1, $ind2, $subfield_data )); + } + } + return $marc; + } + + /** + * Get the number of records available in this Record + * @return int The number of records + */ + function num_records() { + return count($this->raw); + } +} + +/** + * USMARC Class + * Extension class to File class, which allows passing of raw MARC string + * instead of filename + */ +Class USMARC Extends File { + /** + * Read raw MARC string for decoding + * @param string Raw MARC + */ + function usmarc($string) { + $this->raw[] = $string; + $this->pointer = 0; + } +} + +/** + * Record Class + * Create a MARC Record class + */ +Class Record { + + /** + * ========== VARIABLE DECLARATIONS ========== + */ + + /** + * Contain all @link Field objects of the Record + * @var array + */ + var $fields; + /** + * Leader of the Record + * @var string + */ + var $ldr; + /** + * Array of warnings + * @var array + */ + var $warn; + + /** + * ========== ERROR FUNCTIONS ========== + */ + + /** + * Croaking function + * + * Similar to Perl's croak function, which ends parsing and raises an + * user error with a descriptive message. + * @param string The message to display + */ + function _croak($msg) { + trigger_error($msg, E_USER_ERROR); + } + + /** + * Fuction to issue warnings + * + * Warnings will not be displayed unless explicitly accessed, but all + * warnings issued during parse will be stored + * @param string Warning + * @return string Last added warning + */ + function _warn($msg) { + $this->warn[] = $msg; + return $msg; + } + + /** + * Return an array of warnings + */ + function warnings() { + return $this->warn; + } + + /** + * ========== PROCESSING FUNCTIONS ========== + */ + + /** + * Start function + * + * Set all variables to defaults to create new Record object + */ + function record() { + $this->fields = array(); + $this->ldr = str_repeat(' ', 24); + } + + /** + * Get/Set Leader + * + * If argument specified, sets leader, otherwise gets leader. No validation + * on the specified leader is performed + * @param string Leader + * @return string|null Return leader in case requested. + */ + function leader($ldr = "") { + if ($ldr) { + $this->ldr = $ldr; + } else { + return $this->ldr; + } + } + + /** + * Append field to existing + * + * Given Field object will be appended to the existing list of fields. Field will be + * appended last and not in its "correct" location. + * @param Field The field to append + */ + function append_fields($field) { + if (strtolower(get_class($field)) == "field") { + $this->fields[$field->tagno][] = $field; + } else { + $this->_croak(sprintf("Given argument must be Field object, but was '%s'", get_class($field))); + } + } + + /** + * Build Record Directory + * + * Generate the directory of the Record according to existing data. + * @return array Array ( $fields, $directory, $total, $baseaddress ) + */ + function _build_dir() { + // Vars + $fields = array(); + $directory = array(); + + $dataend = 0; + foreach ($this->fields as $field_group ) { + foreach ($field_group as $field) { + // Get data in raw format + $str = $field->raw(); + $fields[] = $str; + + // Create directory entry + $len = strlen($str); + $direntry = sprintf( "%03s%04d%05d", $field->tagno(), $len, $dataend ); + $directory[] = $direntry; + $dataend += $len; + } + } + + /** + * Rules from MARC::Record::USMARC + */ + $baseaddress = + LEADER_LEN + // better be 24 + ( count($directory) * DIRECTORY_ENTRY_LEN ) + + // all the directory entries + 1; // end-of-field marker + + + $total = + $baseaddress + // stuff before first field + $dataend + // Length of the fields + 1; // End-of-record marker + + return array($fields, $directory, $total, $baseaddress); + } + + /** + * Set Leader lengths + * + * Set the Leader lengths of the record according to defaults specified in + * http://www.loc.gov/marc/bibliographic/ecbdldrd.html + */ + function leader_lengths($reclen, $baseaddr) { + $this->ldr = substr_replace($this->ldr, sprintf("%05d", $reclen), 0, 5); + $this->ldr = substr_replace($this->ldr, sprintf("%05d", $baseaddr), 12, 5); + $this->ldr = substr_replace($this->ldr, '22', 10, 2); + $this->ldr = substr_replace($this->ldr, '4500', 20, 4); + } + + /** + * Return all Field objects + * @return array Array of Field objects + */ + function fields() { + return $this->fields; + } + + /** + * Get specific field + * + * Search for field in Record fields based on field name, e.g. 020 + * @param string Field name + * @return Field|FALSE Return Field if found, otherwise FALSE + */ + function field($spec) { + if (array_key_exists($spec, $this->fields)) { + return $this->fields[$spec][0]; + } else { + return FALSE; + } + } + + /** + * Get subfield of Field object + * + * Returns the value of a specific subfield of a given Field object + * @param string Name of field + * @param string Name of subfield + * @return string|FALSE Return value of subfield if Field exists, otherwise FALSE + */ + function subfield($field, $subfield) { + if (!$field = $this->field($field)) { + return FALSE; + } else { + return $field->subfield($subfield); + } + } + + /** + * Delete Field + * + * Delete a given field from within a Record + * @param Field The field to be deleted + */ + function delete_field($obj) { + unset($this->fields[$obj->field]); + } + + /** + * Clone record + * + * Clone a record with all its Fields and subfields + * @return Record Clone record + */ + function make_clone() { + $clone = new Record; + $clone->leader($this->ldr); + + foreach ($this->fields() as $data) { + foreach ($data as $field) { + $clone->append_fields($field); + } + } + + return $clone; + } + + /** + * ========== OUTPUT FUNCTIONS ========== + */ + + /** + * Formatted representation of Field + * + * Format a Field with a sprintf()-like formatting syntax. The formatting + * codes are the names of the subfields of the Field. + * @param string Field name + * @param string Format string + * @return string|FALSE Return formatted string if Field exists, otherwise False + */ + function ffield($tag, $format) { + $result = ""; + if ($field = $this->field($tag)) { + for ($i=0; $isubfield($curr); + } + } + } + return implode("", $result); + } else { + return FALSE; + } + } + + /** + * Return Raw + * + * Return the Record in raw MARC format. + * @return string Raw MARC data + */ + function raw() { + list ($fields, $directory, $reclen, $baseaddress) = $this->_build_dir(); + $this->leader_lengths($reclen, $baseaddress); + + /** + * Glue together all parts + */ + return $this->ldr.implode("", $directory).END_OF_FIELD.implode("", $fields).END_OF_RECORD; + } + + /** + * Return formatted + * + * Return the Record in a formatted fashion. Similar to the output + * of the formatted() function in MARC::Record in Perl + * @return string Formatted representation of MARC record + */ + function formatted() { + $formatted = ""; + foreach ($this->fields as $field_group) { + foreach ($field_group as $field) { + $formatted .= $field->formatted(). "\n"; + } + } + return $formatted; + } +} + +/** + * Field Class + * Create a MARC Field object + */ +Class Field { + + /** + * ========== VARIABLE DECLARATIONS ========== + */ + + /** + * The tag name of the Field + * @var string + */ + var $tagno; + /** + * Value of the first indicator + * @var string + */ + var $ind1; + /** + * Value of the second indicator + * @var string + */ + var $ind2; + /** + * Array of subfields + * @var array + */ + var $subfields = array(); + /** + * Specify if the Field is a Control field + * @var bool + */ + var $is_control; + /** + * Array of warnings + * @var array + */ + var $warn; + /** + * Value of field, if field is a Control field + * @var string + */ + var $data; + + /** + * ========== ERROR FUNCTIONS ========== + */ + + /** + * Croaking function + * + * Similar to Perl's croak function, which ends parsing and raises an + * user error with a descriptive message. + * @param string The message to display + */ + function _croak($msg) { + trigger_error($msg, E_USER_ERROR); + } + + /** + * Fuction to issue warnings + * + * Warnings will not be displayed unless explicitly accessed, but all + * warnings issued during parse will be stored + * @param string Warning + * @return string Last added warning + */ + function _warn($msg) { + $this->warn[] = $msg; + return $msg; + } + + /** + * Return an array of warnings + */ + function warnings() { + return $this->warn; + } + + /** + * ========== PROCESSING FUNCTIONS ========== + */ + + /** + * Field init function + * + * Create a new Field object from passed arguments + * @param array Array ( tagno, ind1, ind2, subfield_data ) + * @return string Returns warnings if any issued during parse + */ + function field() { + $args = func_get_args(); + + $tagno = array_shift($args); + $this->tagno = $tagno; + + // Check if valid tag + if (!preg_match("/^[0-9A-Za-z]{3}$/", $tagno)) { + return $this->_warn("Tag \"$tagno\" is not a valid tag."); + } + + // Check if field is Control field + $this->is_control = (preg_match("/^\d+$/", $tagno) && $tagno < 10); + if ($this->is_control) { + $this->data = array_shift($args); + } else { + foreach (array("ind1", "ind2") as $indcode) { + $indicator = array_shift($args); + if (!preg_match("/^[0-9A-Za-z ]$/", $indicator)) { + if ($indicator != "") { + $this->_warn("Illegal indicator '$indicator' in field '$tagno' forced to blank"); + } + $indicator = " "; + } + $this->$indcode = $indicator; + } + + $subfields = array_shift($args); + + if (count($subfields) < 1) { + return $this->_warn("Field $tagno must have at least one subfield"); + } else { + $this->add_subfields($subfields); + } + } + } + + /** + * Add subfield + * + * Appends subfields to existing fields last, not in "correct" plase + * @param array Subfield data + * @return string Returns warnings if issued during parse. + */ + function add_subfields() { + // Process arguments + $args = func_get_args(); + if (count($args) == 1 && is_array($args[0])) { + $args = $args[0]; + } + // Add subfields, is appropriate + if ($this->is_control) { + return $this->_warn("Subfields allowed only for tags bigger or equal to 10"); + } else { + $this->subfields = array_merge($this->subfields, $args); + } + + return count($args)/2; + } + + /** + * Return Tag number of Field + */ + function tagno() { + return $this->tagno; + } + + /** + * Set/Get Data of Control field + * + * Sets the Data if argument given, otherwise Data returned + * @param string Data to be set + * @return string Data of Control field if argument not given + */ + function data($data = "") { + if (!$this->is_control) { + $this->_croak("data() is only allowed for tags bigger or equal to 10"); + } + if ($data) { + $this->data = $data; + } else { + return $this->data; + } + } + + /** + * Get values of indicators + * + * @param string Indicator number + */ + function indicator($ind) { + if ($ind == 1) { + return $this->ind1; + } elseif ($ind == 2) { + return $this->ind2; + } else { + $this->_warn("Invalid indicator: $ind"); + } + } + + /** + * Check if Field is Control field + * + * @return bool True or False + */ + function is_control() { + return $this->is_control; + } + + /** + * Get the value of a subfield + * + * Return of the value of the given subfield, if exists + * @param string Name of subfield + * @return string|FALSE Value of the subfield if exists, otherwise FALSE + */ + function subfield($code, $repeatable = FALSE) { + if (array_key_exists($code, $this->subfields)) { + return $repeatable ? $this->subfields[$code] : $this->subfields[$code][0]; + } else { + return $repeatable ? array(): FALSE; + } + } + + /** + * Return array of subfields + * + * @return array Array of subfields + */ + function subfields() { + return $this->subfields; + } + + /** + * Update Field + * + * Update Field with given array of arguments. + * @param array Array of key->value pairs of data + */ + function update() { + // Process arguments + $args = func_get_args(); + if (count($args) == 1 && is_array($args[0])) { + $args = $args[0]; + } + if ($this->is_control) { + $this->data = array_shift($args); + } else { + foreach ($args as $subfield => $value) { + if ($subfield == "ind1") { + $this->ind1 = $value; + } elseif ($subfield == "ind2") { + $this->ind2 = $value; + } else { + $this->subfields[$subfield] = $value; + } + } + } + } + + /** + * Replace Field with given Field + * + * @param Field Field to replace with + */ + function replace_with($obj) { + if (strtolower(get_class($obj)) == "field") { + $this->tagno = $obj->tagno; + $this->ind1 = $obj->ind1; + $this->ind2 = $obj->ind2; + $this->subfields = $obj->subfields; + $this->is_control = $obj->is_control; + $this->warn = $obj->warn; + $this->data = $obj->data; + } else { + $this->_croak(sprintf("Argument must be Field-object, but was '%s'", get_class($obj))); + } + } + + /** + * Clone Field + * + * @return Field Cloned Field object + */ + function make_clone() { + if ($this->is_control) { + return new Field($this->tagno, $this->data); + } else { + return new Field($this->tagno, $this->ind1, $this->ind2, $this->subfields); + } + } + + /** + * ========== OUTPUT FUNCTIONS ========== + */ + + /** + * Return Field formatted + * + * Return Field as string, formatted in a similar fashion to the + * MARC::Record formatted() functio in Perl + * @return string Formatted output of Field + */ + function formatted() { + // Variables + $lines = array(); + // Process + if ($this->is_control) { + return sprintf("%3s %s", $this->tagno, $this->data); + } else { + $pre = sprintf("%3s %1s%1s", $this->tagno, $this->ind1, $this->ind2); + } + // Process subfields + foreach ($this->subfields as $subfield => $value) { + $lines[] = sprintf("%6s _%1s%s", $pre, $subfield, $value); + $pre = ""; + } + + return join("\n", $lines); + } + + /** + * Return Field in Raw MARC + * + * Return the Field formatted in Raw MARC for saving into MARC files + * @return string Raw MARC + */ + function raw() { + if ($this->is_control) { + return $this->data.END_OF_FIELD; + } else { + $subfields = array(); + foreach ($this->subfields as $subfield => $value) { + $subfields[] = SUBFIELD_INDICATOR.$subfield.$value; + } + return $this->ind1.$this->ind2.implode("", $subfields).END_OF_FIELD; + } + } + + /** + * Return Field as String + * + * Return Field formatted as String, with either all subfields or special + * subfields as specified. + * @return string Formatted as String + */ + function string($fields = "") { + $matches = array(); + if ($fields) { + for($i=0; $isubfields)) { + $matches[] = $this->subfields[$fields[$i]]; + } + } + } else { + $matches = $this->subfields; + } + return implode(" ", $matches); + } + +} + +?> \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/pubmed/EntrezClient.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/pubmed/EntrezClient.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,505 @@ +webEnvironment = $webEnvironment; + } + + /** + * Returns the web environment from the previous ESearch results. + * + * This value may change with each utility call. If WebEnv is used, History + * search numbers can be included in an ESummary URL, e.g., + * term=cancer+AND+%23X (where %23 replaces # and X is the History search + * number). + * + * @return string + */ + public function getWebEnvironment() + { + return $this->webEnvironment; + } + + /** + * Sets a history search number. + * + * @param int $key + */ + public function setQueryKey($key) + { + $this->queryKey = $key; + } + + /** + * Returns the history search number from the previous ESearch results. + * + * @return int + */ + public function getQueryKey() + { + return $this->queryKey; + } + + /** + * Sets the entrez database to be queried. + * + * Values available from EInfo, PubMed is the default db. + * + * @param string $database + * @see getAvailableDatabases + */ + public function setDatabase($database) + { + $this->database = strtolower($database); + } + + /** + * Returns the database to be queried in the next search. + * + * @return string + */ + public function getDatabase() + { + return $this->database; + } + + /** + * Returns the available entrez databases from EInfo. + * + * @return array + * @throws Exception + */ + public function getAvailableDatabases() + { + $databases = array(); + + $url = self::BASE_URL . 'einfo.fcgi'; + $result = @simplexml_load_file($url); + + if (!$result) { + throw new Exception('Query ' . $url . ' failed.'); + } + + if (isset($result->DbList->DbName)) { + foreach ($result->DbList->DbName as $name) { + $databases[] = (string)$name; + } + } + + return $databases; + } + + /** + * Sets a string identifying the resource. + * + * A string with no internal spaces that identifies the resource which is + * using Entrez links (e.g., tool=flybase). This argument is used to help + * NCBI provide better service to third parties generating Entrez queries + * from programs. As with any query system, it is sometimes possible to ask + * the same question different ways, with different effects on performance. + * NCBI requests that developers sending batch requests include a constant + * 'tool' argument for all requests using the utilities. + * + * @param string $tool + */ + public function setTool($tool) + { + $this->tool = str_replace(array(" ", "\n", "\r"), '', $tool); + } + + /** + * Returns the resource identifier. + * + * @return string + */ + public function getTool() + { + return $this->tool; + } + + /** + * Sets a contact email address for NCBI. + * + * If you choose to provide an email address, we will use it to contact you + * if there are problems with your queries or if we are changing software + * interfaces that might specifically affect your requests. If you choose + * not to include an email address we cannot provide specific help to you, + * but you can still sign up for utilities-announce to receive general + * announcements. + * + * @param string $email + */ + public function setEmail($email) + { + $this->email = $email; + } + + /** + * Returns the NCBI contact email address. + * + * @return string + */ + public function getEmail() + { + return $this->email; + } + + /** + * Sets the search terms for the next query. + * + * The search command uses terms or phrases with or without Boolean + * operators. See the PubMed or Entrez help for information about search + * field descriptions and tags. Search fields and tags are database specific. + * + * @param string $term + */ + public function setTerm($term) + { + $this->term = $term; + $this->webEnvironment = NULL; + $this->count = NULL; + } + + /** + * Returns the current search terms. + * + * @return string + */ + public function getTerm() + { + return $this->term; + } + + /** + * Sets two specific dates bounding the results. + * + * @param $minDate + * @param $maxDate + * @throws Exception + */ + public function setDateRange($minDate, $maxDate=null) + { + if (is_null($maxDate)) { + $maxDate = date('Y/m/d'); + } else { + $maxDate = date('Y/m/d', strtotime($maxDate)); + } + + $minDate = date('Y/m/d', strtotime($minDate)); + + if ($maxDate < $minDate) { + throw new Exception('First argument must be an earlier date.'); + } + + $this->dateRange = array($minDate, $maxDate); + } + + /** + * Returns the specified date range bounding the results. + * + * @return array + * a pair of dates + */ + public function getDateRange() + { + return $this->dateRange; + } + + /** + * Returns the minimum date of the specified date range bounding the results. + * + * @return string + */ + public function getMinDate() + { + return $this->dateRange[0]; + } + + /** + * Returns the maximum date of the specified date range bounding the results. + * + * @return string + */ + public function getMaxDate() + { + return $this->dateRange[1]; + } + + /** + * Sets the maximum number of items retrieved by a search query. + * + * @param int $number + * @see search + */ + public function setReturnMax($number) + { + $this->returnMax = $number; + } + + /** + * Returns the maximum number of items retrieved by a search query. + * + * @return int + */ + public function getReturnMax() + { + return $this->returnMax; + } + + /** + * Returns the URL of the last executed query. + * + * @return string + */ + public function getLastQuery() + { + return $this->query; + } + + /** + * Returns up to the maximum number of items from the result set starting + * at $retstart. + * + * If this is the first search for a given term a web environment and a query + * key is retrieved from the NCBI server in addition to the result set. + * See http://eutils.ncbi.nlm.nih.gov/corehtml/query/static/esearch_help.html + * + * @param int $retStart + * the sequential number of the first record retrieved - default=0 + * which will retrieve the first record + * @return SimpleXMLElement + * an array of PubMed IDs + * @throws Exception + * @see setReturnMax + * @see setRelativeDate + */ + public function search($retStart=0) + { + if (!is_null($this->webEnvironment)) { + $params['WebEnv'] = $this->webEnvironment; + $params['query_key'] = $this->queryKey; + } else { + $params['usehistory'] = $this->useHistory; + $params['tool'] = $this->getTool(); + $params['email'] = $this->getEmail(); + $params['term'] = $this->getTerm(); + } + + if (isset($this->dateRange)) { + $params['mindate'] = $this->getMinDate(); + $params['maxdate'] = $this->getMaxDate(); + } + + $params['retstart'] = $retStart; + $params['retmax'] = $this->getReturnMax(); + $params['db'] = $this->getDatabase(); + + $this->query = self::BASE_URL . 'esearch.fcgi?' . http_build_query($params); + $result = @simplexml_load_file($this->query); + + if (!$result) { + throw new Exception('Query ' . $this->query . ' failed.'); + } + + if (isset($result->WebEnv)) { + $this->webEnvironment = (string)$result->WebEnv; + $this->queryKey = (int)$result->QueryKey; + $this->count = (int)$result->Count; + } + + return $result; + } + + /** + * Returns the number of results for the previously set search terms. + * + * @return int + * @throws Exception + */ + public function count() + { + if (is_null($this->count)) { + $params['tool'] = $this->getTool(); + $params['email'] = $this->getEmail(); + $params['db'] = $this->getDatabase(); + $params['term'] = $this->getTerm(); + $params['rettype'] = 'count'; + + if (isset($this->dateRange)) { + $params['mindate'] = $this->getMinDate(); + $params['maxdate'] = $this->getMaxDate(); + } + + $this->query = self::BASE_URL . 'esearch.fcgi?' . http_build_query($params); + $result = @simplexml_load_file($this->query); + + if (!$result) { + throw new Exception('Query ' . $this->query . ' failed.'); + } + + if (isset($result->Count)) { + $this->count = (int)$result->Count; + } + } + + return $this->count; + } + + /** + * Returns the document identified by the given PubMed ID as a SimpleXMl + * object. The root element is PubmedArticleSet. + * + * @param int $id + * @return SimpleXMLElement + */ + public function fetch($id) + { + $params['db'] = $this->getDatabase(); + $params['retmode'] = 'xml'; + $params['id'] = $id; + + $this->query = self::BASE_URL . 'efetch.fcgi?' . http_build_query($params); + $request_options = array( + 'method' => 'POST'); + $result = drupal_http_request($this->query, $request_options); + if ($result->code != 200) { + throw new Exception('Query ' . $this->query . ' failed.'); + } + $result = @simplexml_load_string($result->data); + + if (!$result) { + throw new Exception('Query ' . $this->query . ' failed.'); + } + + return $result; + } + public function fetchSummaries($retStart=0) { + return $this->fetchRecords($retStart, TRUE); + } + public function fetchResult($retStart=0) { + return $this->fetchRecords($retStart); + } + + /** + * Returns up to the maximum number of results starting at $retstart + * found by the previous search. + * + * In order to return results this method must be called after search. The + * search method retrieves a web environment and query key from the NCBI + * server which is used to fetch the results. After setting a new search term + * the old web environment is deleted and search must be executed again + * before utilizing this method. + * + * The root element of the returned SimpleXML object is PubmedArticleSet. + * + * @param $retStart + * the sequential number of the first record retrieved - default=0 + * which will retrieve the first record + * @return SimpleXMLElement + * @throws Exception + * @see search + * @see setReturnMax + */ + public function fetchRecords($retStart=0, $summaries = FALSE) { + if (is_null($this->webEnvironment)) { + throw new Exception(t('No web environment set.')); + } + + $params['WebEnv'] = $this->webEnvironment; + $params['query_key'] = $this->queryKey; + $params['retstart'] = $retStart; + $params['retmax'] = $this->getReturnMax(); + $params['db'] = $this->getDatabase(); + $params['retmode'] = 'xml'; + + if (isset($this->dateRange)) { + $params['mindate'] = $this->getMinDate(); + $params['maxdate'] = $this->getMaxDate(); + } + if ($summaries) { + $this->query = self::BASE_URL . 'esummary.fcgi?' . http_build_query($params); + } + else { + $this->query = self::BASE_URL . 'efetch.fcgi?' . http_build_query($params); + } + $request_options = array('method' => 'POST'); + $result = drupal_http_request($this->query, $request_options); + + if ($result->code != 200) { + throw new Exception('Query ' . $this->query . ' failed.'); + } + + $result = @simplexml_load_string($result->data); + + + if (isset($result->body->pre->ERROR)) return FALSE; + + return $result; + } + + public function post($uids) { + $params['db'] = $this->getDatabase(); + $params['id'] = implode(',', $uids); + $this->query = self::BASE_URL . 'epost.fcgi?' . http_build_query($params); + $request_options = array('method' => 'POST'); + $result = drupal_http_request($this->query, $request_options); + + if ($result->code != 200) { + throw new Exception('Query ' . $this->query . ' failed.'); + } + + $result = @simplexml_load_string($result->data); + + if (!$result) { + throw new Exception('Query ' . $this->query . ' failed.'); + } + + if (isset($result->WebEnv)) { + $this->webEnvironment = (string)$result->WebEnv; + $this->queryKey = (int)$result->QueryKey; + $this->count = (int)$result->Count; + } + + } + +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/pubmed/EntrezPubmedArticle.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/pubmed/EntrezPubmedArticle.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,241 @@ +setArticle($pubmedArticle); + } + } + + /** + * Returns the PubMed ID of the article. + * + * @return int + */ + public function setArticle(SimpleXMLElement $pubmedArticle) + { + $this->biblio = array(); + $this->article = $pubmedArticle->MedlineCitation; + $this->pubmeddata = $pubmedArticle->PubmedData; + $this->id = (int)$pubmedArticle->MedlineCitation->PMID; + $this->md5 = md5($pubmedArticle->asXML()); + return $this; + } + public function getId() + { + return $this->id; + } + + /** + * Returns the md5 hash of the serialized XML. + * + * @return string + */ + public function getMd5() + { + return $this->md5; + } + + public function getBiblioAsObject() { + return (object)$this->getBiblio(); + } + + /** + * Returns article elements as an associative array suitable for import into + * a biblio node. + * + * @return array + */ + public function getBiblio() + { + if (empty($this->biblio)) { + if (variable_get('biblio_auto_citekey', 1) ) { + $citekey = ''; + } + else { + $citekey = $this->id; + } + + // Attempts to extract the name of the journal from MedlineTA if + // available. + if (!empty($this->article->MedlineJournalInfo->MedlineTA)) { + $journal = (string)$this->article->MedlineJournalInfo->MedlineTA; + } + elseif (!empty($this->article->Article->Journal->ISOAbbreviation)) { + $journal = (string)$this->article->Article->Journal->ISOAbbreviation; + } + else { + $journal = (string)$this->article->Article->Journal->Title; + } + + $this->biblio = array( + 'title' => (string)$this->article->Article->ArticleTitle, + 'biblio_citekey' => $citekey, + 'biblio_pubmed_id' => $this->id, + 'biblio_pubmed_md5' => $this->md5, + 'biblio_contributors' => $this->contributors(), + // MedlineCitations are always articles from journals or books + 'biblio_type' => 102, + 'biblio_date' => $this->date(), + 'biblio_year' => substr($this->date(), 0, 4), + 'biblio_secondary_title' => $journal, + 'biblio_alternate_title' => (string)$this->article->Article->Journal->ISOAbbreviation, + 'biblio_volume' => (string)$this->article->Article->Journal->JournalIssue->Volume, + 'biblio_issue' => (string)$this->article->Article->Journal->JournalIssue->Issue, + 'biblio_issn' => (string)$this->article->Article->Journal->ISSN, + 'biblio_pages' => (string)$this->article->Article->Pagination->MedlinePgn, + 'biblio_abst_e' => $this->abst(), + 'biblio_custom1' => "http://www.ncbi.nlm.nih.gov/pubmed/{$this->id}?dopt=Abstract", + 'biblio_keywords' => $this->keywords(), + 'biblio_lang' => $this->lang(), + ); + + $doi = $this->article->xpath('.//ELocationID[@EIdType="doi"]/text()'); + if (empty($doi)) { + $doi = $this->pubmeddata->xpath('.//ArticleId[@IdType="doi"]/text()'); + } + if (!empty($doi)) { + $this->biblio['biblio_doi'] = (string)$doi[0]; + } + + $pmcid = $this->pubmeddata->xpath('.//ArticleId[@IdType="pmc"]/text()'); + if (!empty($pmcid)) { + $this->biblio['biblio_pmcid'] = (string)$pmcid[0]; + } + + $grants = $this->grants(); + if (!empty($grants)) { + $this->biblio['biblio_pubmed_grants'] = $grants; + } + } + + return $this->biblio; + } + + /** + * Returns the list of contributors for import obtained from the given + * MedlineCitation element. + * + * @return array + * the contributors of the article + */ + private function contributors() + { + $contributors = array(); + + if (isset($this->article->Article->AuthorList->Author)) { + foreach ($this->article->Article->AuthorList->Author as $author) { + $name = ''; + if (isset($author->CollectiveName)) { + $category = 5; // corporate author + $name = (string)$author->CollectiveName; + } else { + $category = 1; //primary (human) author + $lastname = (string)$author->LastName; + if (isset($author->ForeName)) { + $name = $lastname . ', ' . (string)$author->ForeName; + } elseif (isset($author->FirstName)) { + $name = $lastname . ', ' . (string)$author->FirstName; + } elseif (isset($author->Initials)) { + $name = $lastname . ', ' . (string)$author->Initials; + } + } + if (!empty($name)) { + $contributors[] = array('name' => $name, 'auth_category' => $category); + } + } + } + + return $contributors; + } + + private function grants() { + $grants = array(); + if (isset($this->article->Article->GrantList->Grant)) { + foreach ($this->article->Article->GrantList->Grant as $grant) { + $grants[] = array('grantid' => (string)$grant->GrantID, + 'acronym' => (string)$grant->Acronym, + 'agency' => (string)$grant->Agency, + 'country' => (string)$grant->Country + ); + } + } + return $grants; + } + + /** + * Returns the publication date obtained from the given MedlineCitation's + * PubDate element. See the reference documentation for possible values: + * http://www.nlm.nih.gov/bsd/licensee/elements_descriptions.html#pubdate + * According to the above source it always begins with a four digit year. + * + * @return string + * the publication date of the article + */ + private function date() + { + $pubDate = $this->article->Article->Journal->JournalIssue->PubDate; + + if (isset($pubDate->MedlineDate)) { + $date = (string)$pubDate->MedlineDate; + } else { + $date = implode(' ', (array)$pubDate); + } + + return $date; + } + + private function keywords() { + $keywords = array(); + if (isset($this->article->MeshHeadingList->MeshHeading)) { + foreach ($this->article->MeshHeadingList->MeshHeading as $heading) { + $keywords[] = (string)$heading->DescriptorName; + } + } + return $keywords; + } + + private function lang() { + if (isset($this->article->Article->Language)) { + return (string)$this->article->Article->Language; + } + + } + + private function abst() { + if (isset($this->article->Article->Abstract)) { + $abst = ''; + foreach ($this->article->Article->Abstract->AbstractText as $text) { + $abst .= "

    "; + $attrs = $text->attributes(); + if (isset($attrs['Label'])) { + $abst .= '' . $attrs['Label'] . ': '; + } + $abst .= (string)$text . '

    '; + } + return $abst; + } + } +} diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/pubmed/biblio_pm.admin.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/pubmed/biblio_pm.admin.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,101 @@ + 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#group' => 'biblio_settings', + '#title' => t('PubMed'), + '#description' => t('Please select the action to be performed by the PubMed module when it detects changes to an existing entry.'), + '#weight' => 105, + ); + $form['pm_options']['biblio_pm_dup_action'] = array( + '#type' => 'radios', + '#title' => t('Actions'), + '#default_value' => variable_get('biblio_pm_dup_action', 'newrev'), + '#options' => array( + 'newrev' => t('Accept and create a new revision of the existing node.'), + 'replace' => t('Accept and replace the existing node.'), + 'reject' => t('Reject and keep the existing node.'), + ) + ); + $form['pm_options']['biblio_pm_auto_update'] = array( + '#type' => 'checkbox', + '#title' => t('Automatically check for updates via CRON'), + '#return_value' => 1, + '#default_value' => variable_get('biblio_pm_auto_update', 0), + '#description' => t('Entries which were orginally downloaded from PubMed will be periodically checked and updated if the source record has changed.') + ); + $form['pm_options']['pm_cron'] = array( + '#type' => 'fieldset', + '#collapsible' => FALSE, + '#collapsed' => FALSE, +// '#group' => 'pm_options', + '#title' => t('CRON Settings'), + ); + $form['pm_options']['pm_cron']['biblio_pm_update_interval'] = array( + '#type' => 'select', + '#title' => t('PubMed update frequency'), + '#default_value' => variable_get('biblio_pm_update_interval', 3600), + '#options' => array( + 0 => t('Every CRON run'), + 3600 => t('Hourly'), + 86400 => t('Daily'), + 604800 => t('Weeekly'), + ), + '#description' => t('How frequently should we check for updates.'), + '#states' => array( + 'invisible' => array( + 'input[name="biblio_pm_auto_update"]' => array('checked' => FALSE), + ), + ), + ); + $form['pm_options']['pm_cron']['biblio_pm_update_limit'] = array( + '#type' => 'select', + '#title' => t('Number of items to check per CRON run'), + '#default_value' => variable_get('biblio_pm_update_limit', 100), + '#options' => array( + 10 => 10, + 20 => 20, + 50 => 50, + 100 => 100, + 500 => 500, + ), + '#description' => t('The maximum number of items updated in each pass of a cron maintenance task. If necessary, reduce the number of items to prevent timeouts and memory errors while updating.'), + '#states' => array( + 'invisible' => array( + 'input[name="biblio_pm_auto_update"]' => array('checked' => FALSE), + ), + ), + ); + $form['pm_options']['pm_cron']['biblio_pm_age_limit'] = array( + '#type' => 'select', + '#title' => t('Length of time to wait before re-checking for updates'), + '#default_value' => variable_get('biblio_pm_age_limit', 2419200), + '#options' => array( + 86400 => t('1 Day'), + 604800 => t('1 Week'), + 2419200 => t('1 Month'), + 29030400 => t('1 Year'), + ), + '#description' => t('Wait this long before checking for updates on a given node again.'), + '#states' => array( + 'invisible' => array( + 'input[name="biblio_pm_auto_update"]' => array('checked' => FALSE), + ), + ), + ); + + + return ($form); +} \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/pubmed/biblio_pm.info --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/pubmed/biblio_pm.info Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,14 @@ +name = Biblio - PubMed +description = Provides PubMed import and search to the Biblio module. +core = 7.x +package = Biblio +dependencies[] = biblio +files[] = EntrezClient.php +files[] = EntrezPubmedArticle.php + +; Information added by drupal.org packaging script on 2013-07-20 +version = "7.x-1.0-rc7" +core = "7.x" +project = "biblio" +datestamp = "1374290470" + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/pubmed/biblio_pm.install --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/pubmed/biblio_pm.install Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,158 @@ +fields(array('weight' => 19)) + ->condition('name', 'biblio_pm') + ->execute(); +} + +/** + * Implementation of hook_schema(). + * + * Note: Pro Drupal Development models use of t() to translate 'description' + * for field definitions, but Drupal core does not use them. We follow core. + */ +function biblio_pm_schema() { + $schema = array(); + $schema['biblio_pubmed'] = array( + 'fields' => array( + 'biblio_pubmed_id' => array( + 'type' => 'int', + 'not null' => TRUE + ), + 'biblio_pmcid' => array( + 'type' => 'varchar', + 'length' => 20, + ), + 'nid' => array( + 'type' => 'int', + 'not null' => TRUE + ), + 'biblio_pubmed_md5' => array( + 'type' => 'char', + 'length' => 32, + 'not null' => TRUE + ), + 'biblio_pm_changed' => array( + 'description' => 'The Unix timestamp when the pmid was most recently saved.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0 + ), + ), + 'primary key' => array('nid'), + ); + + $schema['biblio_pubmed_grant_info'] = array( + 'fields' => array( + 'id' => array( + 'type' => 'serial', + 'not null' => TRUE, + 'unsigned' => TRUE, + ), + 'nid' => array( + 'type' => 'int', + 'not null' => TRUE + ), + 'biblio_pubmed_id' => array( + 'type' => 'int', + 'not null' => TRUE + ), + 'grantid' => array( + 'type' => 'varchar', + 'length' => 255, + ), + 'acronym' => array( + 'type' => 'varchar', + 'length' => 2, + ), + 'agency' => array( + 'type' => 'varchar', + 'length' => 255, + ), + 'country' => array( + 'type' => 'varchar', + 'length' => 255, + ), + ), + 'primary key' => array('id'), + ); + return $schema; +} + + +/** +* +* UPDATES +* +*/ + + +/** +* +* add two new fields to the biblio_pubmed table +* +*/ + +function biblio_pm_update_7001() { + $spec = array( + 'description' => 'The Unix timestamp when the pmid was most recently saved.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0 + ); + db_add_field('biblio_pubmed', 'biblio_pm_changed', $spec); + $spec = array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ); + db_add_field('biblio_pubmed', 'biblio_pmcid', $spec); +} +/** +* +* change field type for biblio_pmcid field to the biblio_pubmed table +* +*/ + +function biblio_pm_update_7002() { + $spec = array( + 'type' => 'varchar', + 'length' => 20, + 'not null' => FALSE, + ); + db_change_field('biblio_pubmed', 'biblio_pmcid', 'biblio_pmcid', $spec); +} +/** + * Add a new table 'biblio_pubmed_grant_info' + */ +function biblio_pm_update_7004() { + $schema = biblio_pm_schema(); + $spec = $schema['biblio_pubmed_grant_info']; + db_create_table('biblio_pubmed_grant_info', $spec); +} \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/pubmed/biblio_pm.module --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/pubmed/biblio_pm.module Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,525 @@ += variable_get('biblio_pm_update_next_execution', 0)) { + $ids = array(); + $result = db_select('biblio_pubmed', 'bpm') + ->fields('bpm', array('nid', 'biblio_pubmed_id')) + ->condition('biblio_pm_changed', $age_limit, '<') + ->orderBy('nid', 'ASC') + ->range(0, $count_limit) + ->execute(); + foreach ($result as $pm) { + $ids[$pm->nid] = $pm->biblio_pubmed_id; + } + if (count($ids)) { + + list($nids, $dups) = biblio_pm_import_ids($ids); + + if (count($nids)) { + foreach ($nids as $nid) { + $message = ''; + $message = t('!nid was updated due to changes originating at !url', array( + '!nid' => l($nid, 'node/' . $nid), + '!url' => l(t('PubMed'), 'http://www.ncbi.nlm.nih.gov/pubmed/' . $ids[$nid]), + ) + ); + watchdog('biblio_pm', $message, array(), WATCHDOG_WARNING); + } + } + + if (count($dups)) { + $count = count($dups); + $message = format_plural($count, 'One duplicate PubMed entry was checked, but no changes were found.', + '@count PubMed entries were checked, but no changes were found.'); + watchdog('biblio_pm', $message, array('@count' => $count), WATCHDOG_INFO); + + $now = time(); + + db_update('biblio_pubmed') + ->fields(array('biblio_pm_changed' => $now)) + ->condition('nid', $dups, 'IN') + ->execute(); + } + } + else { + $message = t('There were no PubMed entries older than @age to check.', array( + '@age' => format_interval($age)) + ); + } + watchdog('biblio_pm', $message, array(), WATCHDOG_INFO); + variable_set('biblio_pm_update_next_execution', time() + $interval); + } + } +} + +function biblio_pm_form_biblio_admin_settings_alter(&$form, &$form_state) { + module_load_include('inc', 'biblio_pm', 'biblio_pm.admin'); + $form += biblio_pm_settings_form(); +} + +function biblio_pm_form_biblio_node_form_alter(&$form, &$form_state, $form_id) { + + if (($form_id == 'biblio_node_form') && isset($form_state['biblio_fields'])) { + + if (isset($form_state['values']['biblio_pubmed_id'])) { + $default_pubmed_id = $form_state['values']['biblio_pubmed_id']; + } + elseif (isset($form_state['node']->biblio_pubmed_id)) { + $default_pubmed_id = $form_state['node']->biblio_pubmed_id ; + } + else { + $default_pubmed_id = ''; + } + + if (isset($form_state['values']['biblio_pmcid'])) { + $default_pmcid = $form_state['values']['biblio_pmcid']; + } + elseif (isset($form_state['node']->biblio_pmcid)) { + $default_pmcid = $form_state['node']->biblio_pmcid ; + } + else { + $default_pmcid = ''; + } + + $form['biblio_tabs'][4]['biblio_pubmed_id'] = array( + '#type' => 'textfield', + '#title' => t('PMID'), + '#required' => FALSE, + '#description' => t('PubMed ID'), + '#default_value' => $default_pubmed_id, + '#size' => 50, + '#maxlength' => 50, + ); + + + $form['biblio_tabs'][4]['biblio_pmcid'] = array( + '#type' => 'textfield', + '#title' => t('PMCID'), + '#required' => FALSE, + '#description' => t('PubMed Central ID'), + '#default_value' => $default_pmcid, + '#size' => 50, + '#maxlength' => 50, + ); + + } + if ((!isset($form_state['biblio_type']) || empty($form_state['biblio_type'])) && !isset($form_state['node']->nid)) { + $form['biblio_pubmed_lookup'] = array( + '#type' => 'fieldset', + '#title' => t('PubMed Lookup'), + '#weight' => -20, + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + + $form['biblio_pubmed_lookup']['PMID'] = array( + '#type' => 'textfield', + '#title' => t('PubMed ID'), + '#required' => FALSE, + '#default_value' => '', + '#description' => t('Enter a PubMed ID'), + '#size' => 60, + '#maxlength' => 255, + '#weight' => -4 + ); + $form['biblio_pubmed_lookup']['pubmed_submit'] = array( + '#type' => 'submit', + '#value' => t('Populate using PubMed'), + '#submit' => array('biblio_pm_form_biblio_node_form_submit') + ); + // $form['#submit'] = array_merge(array('biblio_pm_form_biblio_node_form_submit'), isset($form['#submit'])?$form['#submit']:array()); // put my validator first + } + if (isset($form_state['values']['biblio_pubmed_id'])) { + $form['biblio_pubmed_id'] = array('#type' => 'value', '#value' => $form_state['values']['biblio_pubmed_id']); + } + if (isset($form_state['values']['biblio_pubmed_md5'])) { + $form['biblio_pubmed_md5'] = array('#type' => 'value', '#value' => $form_state['values']['biblio_pubmed_md5']); + } + if (isset($form_state['values']['biblio_pmcid'])) { + $form['biblio_pmcid'] = array('#type' => 'value', '#value' => $form_state['values']['biblio_pmcid']); + } + if (isset($form_state['values']['biblio_pubmed_grants'])) { + $form['biblio_pubmed_grants'] = array('#type' => 'value', '#value' => $form_state['values']['biblio_pubmed_grants']); + } + +} + +function biblio_pm_form_biblio_node_form_submit($form, &$form_state) { + $node_data = array(); + if (strlen($pmid = $form_state['values']['PMID'])) { + if (!($dup = biblio_pm_check_pmid($pmid))) { + module_load_include('php', 'biblio_pm', 'EntrezClient'); + module_load_include('php', 'biblio_pm', 'EntrezPubmedArticle'); + $Eclient = new BiblioEntrezClient; + try { + $result = $Eclient->fetch($pmid); + } catch (Exception $e) { + form_set_error($e->getMessage()); + } + if (!isset($result->PubmedArticle)) { + unset($form_state['values']['biblio_type']); + unset($form_state['post']['biblio_type']); + form_set_error('PMID', 'No data available for PubMed ID: ' . check_plain($pmid)); + return; + } + $data = new BiblioEntrezPubmedArticle($result->PubmedArticle); + $node_data = $data->getBiblio(); + } + else { + $message = t('The PubMed ID that you are trying to import already exists in the database, see !url', array('!url' => l('node/' . $dup, 'node/' . $dup))); + form_set_error('PMID', $message); + $form_state['rebuild'] = TRUE; + $form_state['submitted'] = FALSE; + unset($form_state['values']['biblio_type']); + } + } + if (!empty($node_data)) { + $form_state['values'] = array_merge($form_state['values'], $node_data); + $form_state['input']['biblio_type'] = $form_state['biblio_type'] = $node_data['biblio_type']; + $form_state['input']['biblio_pmcid'] = $form_state['biblio_pmcid'] = isset($node_data['biblio_pmcid']) ? $node_data['biblio_pmcid'] : ''; + $form_state['input']['biblio_pubmed_id'] = $form_state['biblio_pubmed_id'] = $node_data['biblio_pubmed_id']; + $form_state['input']['biblio_pubmed_grants'] = $form_state['biblio_pubmed_grants'] = isset($node_data['biblio_pmcid']) ? $node_data['biblio_pmcid'] : array(); + $form_state['rebuild'] = TRUE; + } + + return; +} + +function biblio_pm_biblio_import_options() { + return array( + 'biblio_pm' => t('PubMed ID List'), + 'biblio_pm_xml' => t('PubMed XML') + ); +} + +function biblio_pm_biblio_import($file, $terms = array(), $batch = FALSE, $session_id = NULL, $save = TRUE, $string = FALSE) { + $nids = array(); + $dups = array(); + $pmids = file($file->uri, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + if (empty($pmids)) { + drupal_set_message(t("Could not open PubMed ID file"), 'error'); + return; + } + return biblio_pm_import_ids($pmids, $terms, $batch, $session_id); +} + +/** + * Imports article(s) from an XML file (exported) from PubMed Central + * + * @param file object $file + * @param array $terms + * @param bool $batch + * @param string $session_id + * @return array + */ +function biblio_pm_xml_biblio_import($file, $terms = array(), $batch = FALSE, $session_id = NULL) { + libxml_use_internal_errors(true); + $xml = @simplexml_load_file($file->uri); + if (empty($xml) || isset($xml->body->pre->ERROR)) { + drupal_set_message(t("Could not parse file as PubMed XML"), 'error'); + return; + } + return _biblio_pm_create_node_from_xml($xml, $terms, $batch, $session_id); +} + +/** + * Imports multiple PMIDs + * + * @param array $pmids + * @param array $terms + * @param bool $batch + * @param string $session_id + * @return array: + */ +function biblio_pm_import_ids($pmids, $terms = array(), $batch = FALSE, $session_id = NULL) { + module_load_include('php', 'biblio_pm', 'EntrezClient'); + $retmax = 100; + $resmax = count($pmids); + $start = 0; + $Eclient = new BiblioEntrezClient; + $Eclient->post($pmids); + $Eclient->setReturnMax($retmax); + $nids = array(); + $dups = array(); + while ($start < $resmax && ($result = $Eclient->fetchRecords($start))) { + $start += count($result->xpath('//PubmedArticle')); + list($nid, $dup) = _biblio_pm_create_node_from_xml($result, $terms, $batch, $session_id); + $nids = array_merge($nids, $nid); + $dups = array_merge($dups, $dup); + } + + return array($nids, $dups); +} + +/** + * Fetches the article for the given PMID and returns a biblio node object + * + * Returns an empty node object if the PMID is not found. + * + * @param int $pmid + * @return stdClass $node + */ +function biblio_pm_fetch_pmid($pmid) { + $node = new stdClass; + $Eclient = new BiblioEntrezClient; + $paser = new BiblioEntrezPubmedArticle(); + try { + $xml = $Eclient->fetch($pmid); + } + catch (Exception $e) { + return $node; + } + $articles = $xml->xpath('//PubmedArticle'); + if (count($articles)) { + $node = $paser->setArticle($articles[0])->getBiblioAsObject(); + if (!empty($node)) { + $node->type = 'biblio'; + node_object_prepare($node); + } + } + return $node; +} + +function _biblio_pm_create_node_from_xml($xml, $terms, $batch, $session_id) { + module_load_include('php', 'biblio_pm', 'EntrezPubmedArticle'); + $nids = array(); + $dups = array(); + $node = new stdClass(); + $data = new BiblioEntrezPubmedArticle(); + + foreach ($xml->xpath('//PubmedArticle') as $article) { + $node = $data->setArticle($article)->getBiblioAsObject(); + if (isset($node)) { + $dup = biblio_pm_check_md5($node->biblio_pubmed_id, $node->biblio_pubmed_md5); + $action = variable_get('biblio_pm_dup_action', 'newrev'); + if ($dup < 0 && $action == 'newrev') { //entry has be imported before, but may have changed + // Load the node in order to preserve all its data and merge the new + // data from pubmed. + $node = (object) array_merge((array)node_load(-$dup), (array)$node); + $node->nid = -$dup; + $node->revision = 1; + $curr_date = format_date(time()); + $node->log = t('Automatically updated by the Biblio PubMed module on !date due to changes at !url', array( + '!date' => $curr_date, + '!url' => l('PubMed', 'http://www.ncbi.nlm.nih.gov/pubmed/' . $node->biblio_pubmed_id), + )); + $dup = NULL; + } + if ($dup < 0 && $action == 'replace') { //entry has be imported before, but may have changed + $node->nid = -$dup; + $existing_node = db_query("SELECT * FROM {node} WHERE nid=:nid", array(':nid' => $node->nid))->fetchObject(); + $node = (object) array_merge((array)$existing_node, (array)$node); + $dup = NULL; + } + if (!$dup) { + // Allows other modules to alter the node before it is being saved. (Note: $article is a SimpleXML object) + drupal_alter('biblio_pm_node', $node, $article); + biblio_save_node($node, $terms, $batch, $session_id); + if (!empty($node->nid)) $nids[] = $node->nid; + } + else { + $dups[] = $dup; + } + $node = NULL; + } + } + return array($nids, $dups); +} + +function biblio_pm_check_pmid($pmid) { + return db_query("SELECT nid FROM {biblio_pubmed} WHERE biblio_pubmed_id = :pmid", array(':pmid' => $pmid))->fetchField(); +} + +function biblio_pm_biblio_lookup_link_settings() { + return array('pubmed' => t('PubMed')); +} + +function biblio_pm_biblio_lookup_link($node) { + $show_link = variable_get('biblio_lookup_links', array('pubmed' => TRUE)); + if (!isset($show_link['pubmed']) || + !$show_link['pubmed'] || + !isset($node) || + $node->type != 'biblio' || + !isset($node->biblio_pubmed_id)) { + return array(); + } + + $link = 'http://www.ncbi.nlm.nih.gov/pubmed/' . $node->biblio_pubmed_id . '?dopt=Abstract'; + $attrs = array('title' => t("Click to view the PubMed listing for this node")); + if (variable_get('biblio_links_target_new_window', NULL)) { + $attrs = array_merge($attrs, array('target' => '_blank')); + } + return array('biblio_pubmed' => array( + 'title' => t('PubMed'), + 'href' => $link, + 'attributes' => $attrs, + )); +} + +function biblio_pm_node_view($node, $view_mode, $langcode) { + if ($node->type == 'biblio' && isset($node->biblio_pubmed_id)) { + switch ($view_mode) { + case 'full': + case 'teaser': + $node->content['links']['biblio_pubmed'] = array( + '#links' => biblio_pm_biblio_lookup_link($node), + '#attributes' => array('class' => array('links', 'inline')), + ); + } + } +} + +function biblio_pm_node_delete($node) { + if ($node->type != 'biblio') { + return; + } + db_delete('biblio_pubmed') + ->condition('nid', $node->nid) + ->execute(); + db_delete('biblio_pubmed_grant_info') + ->condition('nid', $node->nid) + ->execute(); +} + + +function biblio_pm_node_insert($node) { + if (isset($node->biblio_pubmed_id) && !empty($node->biblio_pubmed_id)) { + $node->biblio_pm_changed = time(); + drupal_write_record('biblio_pubmed', $node); + } + if (isset($node->biblio_pubmed_grants) && is_array($node->biblio_pubmed_grants)) { + foreach ($node->biblio_pubmed_grants as $grant) { + $info = array( + 'nid' => $node->nid, + 'biblio_pubmed_id' => $node->biblio_pubmed_id + ); + $info += $grant; + drupal_write_record('biblio_pubmed_grant_info', $info); + } + } +} + +function biblio_pm_node_update($node) { + if (isset($node->biblio_pubmed_id) && !empty($node->biblio_pubmed_id)) { + $node->biblio_pm_changed = time(); + drupal_write_record('biblio_pubmed', $node, 'nid'); + } + if (isset($node->biblio_pubmed_grants) && is_array($node->biblio_pubmed_grants) && !empty($node->biblio_pubmed_grants)) { + db_delete('biblio_pubmed_grant_info') + ->condition('nid', $node->nid) + ->execute(); + foreach ($node->biblio_pubmed_grants as $grant) { + $info = array( + 'nid' => $node->nid, + 'biblio_pubmed_id' => $node->biblio_pubmed_id + ); + $info += $grant; + drupal_write_record('biblio_pubmed_grant_info', $info); + } + } +} + +function biblio_pm_node_load($nodes, $types) { + $result = db_select('biblio_pubmed', 'bpm') + ->fields('bpm', array('nid', 'biblio_pubmed_id', 'biblio_pmcid', 'biblio_pubmed_md5')) + ->condition('nid', array_keys($nodes)) + ->execute(); + +// $result = db_query('SELECT biblio_pubmed_id FROM {biblio_pubmed} WHERE nid IN(:nids)', array(':nids' => array_keys($nodes))); + foreach ($result as $record) { + $nodes[$record->nid]->biblio_pubmed_id = $record->biblio_pubmed_id; + $nodes[$record->nid]->biblio_pmcid = $record->biblio_pmcid; + $nodes[$record->nid]->biblio_pubmed_md5 = $record->biblio_pubmed_md5; + } + + $result = db_select('biblio_pubmed_grant_info', 'bpmgi') + ->fields('bpmgi') + ->condition('nid', array_keys($nodes)) + ->execute(); + + foreach ($result as $record) { + $nodes[$record->nid]->biblio_pubmed_grants[] = array( + 'grantid' => $record->grantid, + 'acronym' => $record->acronym, + 'agency' => $record->agency, + 'country' => $record->country); + } +} + +function biblio_pm_check_md5($pmid, $md5) { + static $pm_md5s = array(); + static $pm_nids = array(); + if (empty($pm_md5s)) { + $result = db_query("SELECT * FROM {biblio_pubmed} "); + foreach ($result as $row ) { + $pm_md5s[$row->biblio_pubmed_md5] = $row->nid; + $pm_nids[$row->biblio_pubmed_id] = $row->nid; + } + } + if (isset($pm_nids[$pmid]) && isset($pm_md5s[$md5])) { // must be an exact duplicate of an existing node (return the nid) + return $pm_md5s[$md5]; + } + elseif (isset($pm_nids[$pmid]) && !isset($pm_md5s[$md5])) { //pmid has been save previously but content must have changed (return negative nid) + return -$pm_nids[$pmid]; + } + else { + $pm_md5s[$md5] = TRUE; // gaurd against duplicates in the same import + $pm_nids[$pmid] = TRUE; + return; + } +} + +function biblio_pm_views_api() { + return array('api' => 2); +} + +function biblio_pm_biblio_node_table_rows_alter(&$rows, $node) { + if (isset($node->biblio_pubmed_id) && !empty($node->biblio_pubmed_id)) { + $rows[] = array( + array( + 'data' => t('PubMed ID'), + 'class' => array('biblio-row-title') + ), + array( + 'data' => l($node->biblio_pubmed_id, 'http://www.ncbi.nlm.nih.gov/pubmed/' . $node->biblio_pubmed_id . '?dopt=Abstract') + ) + ); + } + if (isset($node->biblio_pmcid) && !empty($node->biblio_pmcid)) { + $rows[] = array( + array( + 'data' => t('PubMed Central ID'), + 'class' => array('biblio-row-title') + ), + array( + 'data' => check_plain($node->biblio_pmcid) + ) + ); + } + if (isset($node->biblio_pubmed_grants) && is_array($node->biblio_pubmed_grants)) { + + foreach ($node->biblio_pubmed_grants as $grant) { + $list[] = check_plain(implode(' / ', $grant)); + } + $rows[] = array( + array( + 'data' => t('Grant List'), + 'class' => array('biblio-row-title') + ), + array( + 'data' => implode('
    ', $list) + ) + ); + } +} \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/pubmed/biblio_pm.views.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/pubmed/biblio_pm.views.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,157 @@ + 'nid', + 'title' => t('PubMed Table'), + 'help' => t('This table contains PubMed Identifiers'), + 'weight' => 10, + ); + + $data['biblio_pubmed']['table']['join'] = array( + 'node' => array( + 'left_field' => 'nid', + 'field' => 'nid', + ), + ); + + $data['biblio_pubmed']['biblio_pubmed_id'] = array( + 'title' => t('PubMed ID'), + 'help' => t('The PubMed ID (http://pubmed.org)'), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_integer', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_integer', + ), + + ); + $data['biblio_pubmed']['biblio_pmcid'] = array( + 'title' => t('PMCID'), + 'help' => t('The PubMed Central ID (http://www.ncbi.nlm.nih.gov/pmc/)'), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_string', + ), + + ); + $data['biblio_pubmed_grant_info']['table']['group'] = t('Biblio'); + $data['biblio_pubmed_grant_info']['table']['base'] = array( + 'field' => 'nid', + 'title' => t('PubMed Grant Table'), + 'help' => t('This table contains Grant information for PubMed entries'), + 'weight' => 10, + ); + + $data['biblio_pubmed_grant_info']['table']['join'] = array( + 'node' => array( + 'left_field' => 'nid', + 'field' => 'nid', + ), + ); + $data['biblio_pubmed_grant_info']['biblio_pubmed_id'] = array( + 'title' => t('PubMed ID'), + 'help' => t('The PubMed ID (http://pubmed.org)'), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_integer', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_integer', + ), + ); + $data['biblio_pubmed_grant_info']['grantid'] = array( + 'title' => t('PubMed Grant ID'), + 'help' => t('The PubMed ID (http://pubmed.org)'), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_string', + ), + ); + $data['biblio_pubmed_grant_info']['acronym'] = array( + 'title' => t('PubMed Grant Acronym'), + 'help' => t('The PubMed ID (http://pubmed.org)'), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_string', + ), + ); + $data['biblio_pubmed_grant_info']['agency'] = array( + 'title' => t('PubMed Grant Agency'), + 'help' => t('The PubMed ID (http://pubmed.org)'), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_string', + ), + ); + $data['biblio_pubmed_grant_info']['country'] = array( + 'title' => t('PubMed Grant Country'), + 'help' => t('The PubMed ID (http://pubmed.org)'), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_string', + ), + ); + + return $data; +} + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/rtf/biblio_rtf.info --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/rtf/biblio_rtf.info Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,14 @@ +name = Biblio - RTF +description = Provides Rich Text Format file export to the Biblio module. +core = 7.x +package = Biblio +dependencies[] = biblio +files[] = rtf_export.inc +files[] = views/biblio_handler_field_export_link_rtf.inc + +; Information added by drupal.org packaging script on 2013-07-20 +version = "7.x-1.0-rc7" +core = "7.x" +project = "biblio" +datestamp = "1374290470" + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/rtf/biblio_rtf.install --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/rtf/biblio_rtf.install Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,26 @@ +fields(array('weight' => 22)) + ->condition('name', 'biblio_rtf') + ->execute(); +} + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/rtf/biblio_rtf.module --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/rtf/biblio_rtf.module Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,95 @@ + 2, + 'path' => drupal_get_path('module', 'biblio_rtf') . '/views', + ); +} + +function biblio_rtf_biblio_export_options() { + return array('rtf' => t('RTF')); +} + +function biblio_rtf_node_view($node, $view_mode) { + if ($node->type == 'biblio') { + switch ($view_mode) { + case 'full': + case 'teaser': + $links = biblio_rtf_biblio_export_link($node->nid); + $node->content['links']['biblio_rtf'] = array( + '#links' => $links, + '#attributes' => array('class' => array('links', 'inline')), + ); + } + } +} +function biblio_rtf_link($type, $node = NULL, $teaser = FALSE) { + if ($type != 'node' && $node->type != 'biblio') return; + + return biblio_rtf_biblio_export_link($node->nid); +} + +/** + * Creates a link to export a node (or view) in rtf format + * + * @param $base this is the base url (defaults to /biblio) + * @param $nid the node id, if NULL then the current view is exported + * @return a link (rtf) + */ +function biblio_rtf_biblio_export_link($nid = NULL, $filter = array()) { + $show_link = variable_get('biblio_export_links', array('rtf' => TRUE)); + if (!isset($show_link['rtf']) || empty($show_link['rtf']) || !biblio_access('export') ) { + return array(); + } + $base = variable_get('biblio_base', 'biblio'); + + $link = array( + 'attributes' => array( + 'title' => t("Click to download the RTF formatted file"), + 'rel' => 'nofollow') + ); + + $link['href'] = (!empty($nid) ? "$base/export/rtf/$nid" : "$base/export/rtf"); + $link['title'] = t('RTF'); + + if (empty($nid) && !empty($filter)) { // add any filters which may be on the current page + $link['query'] = $filter; + } + return array('biblio_rtf' => $link); +} + +function biblio_rtf_biblio_export($nids) { + $count = 0; + $variables = array( + 'style_name' => biblio_get_style(), + ); + + $nodes = node_load_multiple($nids, array(), TRUE); + foreach ($nodes as $node) { + if (variable_get('biblio_hide_bibtex_braces', 0) ) { + $node->title = biblio_remove_brace($node->title); + } + $count++; + $variables['node'] = $node; + + if ($count == 1) { + $rtf = new rtf(); + $rtf->setPaperSize(5); + $rtf->setPaperOrientation(1); + $rtf->setDefaultFontFace(1); + $rtf->setDefaultFontSize(24); + $rtf->setAuthor("Biblio 7.x"); + $rtf->setOperator(""); + $rtf->setTitle("Biblio RTF Export"); + $rtf->addColour("#000000"); + } + + $rtf->addText(filter_xss(theme('biblio_style', $variables) . '

    ', array('i', 'b', 'br', 'u', 'p', 'strong', 'em', 'sub', 'sup', 'ul', 'li'))); + } + if ($count > 0) $rtf->getDocument(); +} + diff -r d72257b2ddc2 -r a75ead649730 modules/biblio/modules/rtf/rtf_export.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/biblio/modules/rtf/rtf_export.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,347 @@ +} {\author } {\operator }} + var $info_table = array(); + var $page_width; + var $page_height; + var $page_size; + var $page_orientation; + var $rtf_version; + var $tab_width; + + var $document; + var $buffer; + var $inch; + var $cm; + var $mm; + + function rtf() { + $this->inch = 1440; + $this->cm = 567; + $this->mm = 56.7; + + $this->fonts_array[] = array( + "name" => "Arial", + "family" => "swiss", + "charset" => 0 + ); + + $this->fonts_array[] = array( + "name" => "Times New Roman", + "family" => "roman", + "charset" => 0 + ); + + $this->fonts_array[] = array( + "name" => "Verdana", + "family" => "swiss", + "charset" => 0 + ); + + $this->fonts_array[] = array( + "name" => "Symbol", + "family" => "roman", + "charset" => 2 + ); + + $this->setDefaultFontFace(0); + $this->setDefaultFontSize(24); + $this->setPaperSize(5); + $this->setPaperOrientation(1); + $this->rtf_version = 1; + $this->tab_width = 360; + } + + function setDefaultFontFace($face) { + $this->font_face = $face; // $font is interger + } + + function setDefaultFontSize($size) { + $this->font_size = $size; + } + + function setTitle($title="") { + $this->info_table["title"] = $title; + } + + function setAuthor($author="") { + $this->info_table["author"] = $author; + } + + function setOperator($operator="") { + $this->info_table["operator"] = $operator; + } + + function setPaperSize($size=0) { + + // 1 => Letter (8.5 x 11 inch) + // 2 => Legal (8.5 x 14 inch) + // 3 => Executive (7.25 x 10.5 inch) + // 4 => A3 (297 x 420 mm) + // 5 => A4 (210 x 297 mm) + // 6 => A5 (148 x 210 mm) + // Orientation considered as Portrait + + switch ($size) { + case 1: + $this->page_width = floor(8.5*$this->inch); + $this->page_height = floor(11*$this->inch); + $this->page_size = 1; + break; + case 2: + $this->page_width = floor(8.5*$this->inch); + $this->page_height = floor(14*$this->inch); + $this->page_size = 5; + break; + case 3: + $this->page_width = floor(7.25*$this->inch); + $this->page_height = floor(10.5*$this->inch); + $this->page_size = 7; + break; + case 4: + $this->page_width = floor(297*$this->mm); + $this->page_height = floor(420*$this->mm); + $this->page_size = 8; + break; + case 5: + default: + $this->page_width = floor(210*$this->mm); + $this->page_height = floor(297*$this->mm); + $this->page_size = 9; + break; + case 6: + $this->page_width = floor(148*$this->mm); + $this->page_height = floor(210*$this->mm); + $this->page_size = 10; + break; + } + } + + function setPaperOrientation($orientation=0) { + // 1 => Portrait + // 2 => Landscape + + switch ($orientation) { + case 1: + default: + $this->page_orientation = 1; + break; + case 2: + $this->page_orientation = 2; + break; + } + } + + function addColour($hexcode) { + // Get the RGB values + $this->hex2rgb($hexcode); + + // Register in the colour table array + $this->colour_table[] = array( + "red" => $this->colour_rgb["red"], + "green" => $this->colour_rgb["green"], + "blue" => $this->colour_rgb["blue"] + ); + } + + // Convert HEX to RGB (#FFFFFF => r255 g255 b255) + function hex2rgb($hexcode) { + $hexcode = str_replace("#", "", $hexcode); + $rgb = array(); + $rgb["red"] = hexdec(substr($hexcode, 0, 2)); + $rgb["green"] = hexdec(substr($hexcode, 2, 2)); + $rgb["blue"] = hexdec(substr($hexcode, 4, 2)); + + $this->colour_rgb = $rgb; + } + + // Convert newlines into \par + function nl2par($text) { + $text = str_replace("\n", "\\par ", $text); + + return $text; + } + + // Add a text string to the document buffer + function addText($text) { + $text = str_replace("\n", "", $text); + $text = str_replace("\t", "", $text); + $text = str_replace("\r", "", $text); + + $this->document .= $text; + } + + // Ouput the RTF file + function getDocument() { + $this->buffer .= "{"; + // Header + $this->buffer .= $this->getHeader(); + // Font table + $this->buffer .= $this->getFontTable(); + // Colour table + $this->buffer .= $this->getColourTable(); + // File Information + $this->buffer .= $this->getInformation(); + // Default font values + $this->buffer .= $this->getDefaultFont(); + // Page display settings + $this->buffer .= $this->getPageSettings(); + // Parse the text into RTF + $this->buffer .= $this->parseDocument(); + $this->buffer .= "}"; + + header("Content-Type: text/enriched\n"); + header("Content-Disposition: attachment; filename=rtf.rtf"); + echo $this->buffer; + } + + // Header + function getHeader() { + $header_buffer = "\\rtf{$this->rtf_version}\\ansi\\deff0\\deftab{$this->tab_width}\n\n"; + + return $header_buffer; + } + + // Font table + function getFontTable() { + + $font_buffer = "{\\fonttbl\n"; + foreach ($this->fonts_array AS $fnum => $farray) { + $font_buffer .= "{\\f{$fnum}\\f{$farray['family']}\\fcharset{$farray['charset']} {$farray['name']}}\n"; + } + $font_buffer .= "}\n\n"; + + return $font_buffer; + } + + // Colour table + function getColourTable() { + $colour_buffer = ""; + if (sizeof($this->colour_table) > 0) { + $colour_buffer = "{\\colortbl;\n"; + foreach ($this->colour_table AS $cnum => $carray) { + $colour_buffer .= "\\red{$carray['red']}\\green{$carray['green']}\\blue{$carray['blue']};\n"; + } + $colour_buffer .= "}\n\n"; + } + + return $colour_buffer; + } + + // Information + function getInformation() { + $info_buffer = ""; + if (sizeof($this->info_table) > 0) { + $info_buffer = "{\\info\n"; + foreach ($this->info_table AS $name => $value) { + $info_buffer .= "{\\{$name} {$value}}"; + } + $info_buffer .= "}\n\n"; + } + + return $info_buffer; + } + + // Default font settings + function getDefaultFont() { + $font_buffer = "\\f{$this->font_face}\\fs{$this->font_size}\n"; + + return $font_buffer; + } + + // Page display settings + function getPageSettings() { + if ($this->page_orientation == 1) + $page_buffer = "\\paperw{$this->page_width}\\paperh{$this->page_height}\n"; + else + $page_buffer = "\\paperw{$this->page_height}\\paperh{$this->page_width}\\landscape\n"; + + $page_buffer .= "\\pgncont\\pgndec\\pgnstarts1\\pgnrestart\n"; + + return $page_buffer; + } + + // Convert special characters to ASCII + function specialCharacters($text) { + $text_buffer = ""; + for ($i = 0; $i < strlen($text); $i++) + $text_buffer .= $this->escapeCharacter($text[$i]); + + return $text_buffer; + } + + // Convert special characters to ASCII + function escapeCharacter($character) { + $escaped = ""; + if (ord($character) >= 0x00 && ord($character) < 0x20) { + $escaped = "\\'" . dechex(ord($character)); + } + + if ((ord($character) >= 0x20 && ord($character) < 0x80) || ord($character) == 0x09 || ord($character) == 0x0A) { + $escaped = $character; + } + + if (ord($character) >= 0x80 and ord($character) < 0xFF) { + $escaped = "\\'" . dechex(ord($character)); + } + + switch (ord($character)) { + case 0x5C: + case 0x7B: + case 0x7D: + $escaped = "\\" . $character; + break; + } + + return $escaped; + } + + // Parse the text input to RTF + function parseDocument() { + //$doc_buffer = $this->specialCharacters(html_entity_decode($this->document)); + $doc_buffer = html_entity_decode($this->document, ENT_QUOTES, "utf-8"); + $doc_buffer = utf8_decode($doc_buffer); + $doc_buffer = $this->specialCharacters($doc_buffer); + if (preg_match("/
    + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/ohm/templates/comment/comment-wrapper.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/ohm/templates/comment/comment-wrapper.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,54 @@ + +> + + > + + + + type != 'forum'): ?> + + > + + + + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/ohm/templates/comment/comment.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/ohm/templates/comment/comment.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,92 @@ +created variable. + * - $changed: Formatted date and time for when the comment was last changed. + * Preprocess functions can reformat it by calling format_date() with the + * desired parameters on the $comment->changed variable. + * - $new: New comment marker. + * - $permalink: Comment permalink. + * - $submitted: Submission information created from $author and $created during + * template_preprocess_comment(). + * - $user_picture: The comment author's picture from user-picture.tpl.php. + * - $signature: Authors signature. + * - $status: Comment status. Possible values are: + * comment-unpublished, comment-published or comment-preview. + * - $title: Linked title. + * - $classes: String of classes that can be used to style contextually through + * CSS. It can be manipulated through the variable $classes_array from + * preprocess functions. The default values can be one or more of the + * following: + * - comment: The current template type, i.e., "theming hook". + * - comment-by-anonymous: Comment by an unregistered user. + * - comment-by-node-author: Comment by the author of the parent node. + * - comment-preview: When previewing a new or edited comment. + * The following applies only to viewers who are registered users: + * - comment-unpublished: An unpublished comment visible only to + * administrators. + * - comment-by-viewer: Comment by the user currently viewing the page. + * - comment-new: New comment since last the visit. + * - $title_prefix (array): An array containing additional output populated by + * modules, intended to be displayed in front of the main title tag that + * appears in the template. + * - $title_suffix (array): An array containing additional output populated by + * modules, intended to be displayed after the main title tag that appears in + * the template. + * + * These two variables are provided for context: + * - $comment: Full comment object. + * - $node: Node object the comments are attached to. + * + * Other variables: + * - $classes_array: Array of html class attribute values. It is flattened + * into a string within the variable $classes. + * + * @see template_preprocess() + * @see template_preprocess_comment() + * @see template_process() + * @see theme_comment() + */ +?> +> +
    + + + +
    + + > + + + + + > + + + + +
    + +
    + + + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/ohm/templates/system/page.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/ohm/templates/system/page.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,122 @@ + +
    + + +
    +
    + + + + + +

    + + + + + + + + + + +
    + + + +
    + +
    + +
    +
    diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/ohm/theme-settings.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/ohm/theme-settings.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,18 @@ +'; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/ohm/theme/comment-block.theme.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/ohm/theme/comment-block.theme.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,21 @@ +subject, 'comment/' . $comment->cid, array('fragment' => 'comment-' . $comment->cid)) . ' ' . t('@time ago', array('@time' => format_interval(REQUEST_TIME - $comment->changed))) . ''; + } + + if ($items) { + return theme('item_list', array('items' => $items, 'attributes' => array('class' => array('border-list')))); + } + else { + return t('No comments available.'); + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/ohm/theme/pager-link.theme.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/ohm/theme/pager-link.theme.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,72 @@ + t('Go to first page'), + t('‹ previous') => t('Go to previous page'), + t('next ›') => t('Go to next page'), + t('last »') => t('Go to last page'), + ); + } + if (isset($titles[$text])) { + $attributes['title'] = $titles[$text]; + } + elseif (is_numeric($text)) { + $attributes['title'] = t('Go to page @number', array('@number' => $text)); + } + } + + // @todo l() cannot be used here, since it adds an 'active' class based on the + // path only (which is always the current path for pager links). Apparently, + // none of the pager links is active at any time - but it should still be + // possible to use l() here. + // @see http://drupal.org/node/1410574 + $attributes['href'] = url($_GET['q'], array('query' => $query)); + return '' . filter_xss($text) . ''; +} + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/ohm/theme/pager.theme.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/ohm/theme/pager.theme.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,128 @@ + $pager_max) { + // Adjust "center" if at end of query. + $i = $i + ($pager_max - $pager_last); + $pager_last = $pager_max; + } + if ($i <= 0) { + // Adjust "center" if at start of query. + $pager_last = $pager_last + (1 - $i); + $i = 1; + } + // End of generation loop preparation. + + $li_first = theme('pager_first', array('text' => (isset($tags[0]) ? $tags[0] : '' . t('first')), 'element' => $element, 'parameters' => $parameters)); + $li_previous = theme('pager_previous', array('text' => (isset($tags[1]) ? $tags[1] : '' . t('previous')), 'element' => $element, 'interval' => 1, 'parameters' => $parameters)); + $li_next = theme('pager_next', array('text' => (isset($tags[3]) ? $tags[3] : t('next')) . '', 'element' => $element, 'interval' => 1, 'parameters' => $parameters)); + $li_last = theme('pager_last', array('text' => (isset($tags[4]) ? $tags[4] : t('last')) . '', 'element' => $element, 'parameters' => $parameters)); + + if ($pager_total[$element] > 1) { + if ($li_first) { + $items[] = array( + 'class' => array('pager__item', 'pager__item--first'), + 'data' => $li_first, + ); + } + if ($li_previous) { + $items[] = array( + 'class' => array('pager__item', 'pager__item--previous'), + 'data' => $li_previous, + ); + } + + // When there is more than one page, create the pager list. + if ($i != $pager_max) { + if ($i > 1) { + $items[] = array( + 'class' => array('pager__item', 'pager__item--ellipsis'), + 'data' => '…', + ); + } + // Now generate the actual pager piece. + for (; $i <= $pager_last && $i <= $pager_max; $i++) { + if ($i < $pager_current) { + $items[] = array( + 'class' => array('pager__item'), + 'data' => theme('pager_previous', array('text' => $i, 'element' => $element, 'interval' => ($pager_current - $i), 'parameters' => $parameters)), + ); + } + if ($i == $pager_current) { + $items[] = array( + 'class' => array('pager__item', 'pager__item--current'), + 'data' => $i, + ); + } + if ($i > $pager_current) { + $items[] = array( + 'class' => array('pager__item'), + 'data' => theme('pager_next', array('text' => $i, 'element' => $element, 'interval' => ($i - $pager_current), 'parameters' => $parameters)), + ); + } + } + if ($i < $pager_max) { + $items[] = array( + 'class' => array('pager__item', 'pager__item--ellipsis'), + 'data' => '…', + ); + } + } + // End generation. + if ($li_next) { + $items[] = array( + 'class' => array('pager__item', 'pager__item--next'), + 'data' => $li_next, + ); + } + if ($li_last) { + $items[] = array( + 'class' => array('pager__item', 'pager__item--last'), + 'data' => $li_last, + ); + } + return '

    ' . t('Pages') . '

    ' . theme('item_list', array( + 'items' => $items, + 'attributes' => array('class' => array('pager')), + )); + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/.bowerrc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/.bowerrc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,3 @@ +{ + "directory" : "libraries" +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/.gitignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/.gitignore Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,5 @@ +# Ignore the node modules folder (created by 'npm install'). +node_modules + +# We absolutely don't want to have the .sass-cache in git. +.sass-cache diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/.gitignore-contributors --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/.gitignore-contributors Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,8 @@ +# This .gitignore file is only relevant for maintainers and contributors. As we +# are not allowed to host any external libraries on d.o we had to integrate +# Bower into our workflow. This means that we pull in the external libraries +# only on demand. This is actually a nice feature, however, in order to not +# disrupt the git workflow of our users (by adding an actual .gitignore entry +# for the 'components' folder) we should instead add a .gitignore entry to our +# global, personal .gitignore files (~/.gitingore) instead. +ohm/components diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/.jshintrc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/.jshintrc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,24 @@ +{ + "browser": true, + "bitwise": true, + "devel": true, + "curly": true, + "eqeqeq": true, + "forin": true, + "immed": true, + "indent": 2, + "jquery": true, + "latedef": true, + "newcap": true, + "noarg": true, + "quotmark": true, + "regexp": true, + "undef": true, + "unused": true, + "trailing": true, + "smarttabs": true, + "predef": [ + "Drupal", + "Modernizr" + ] +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/.ruby-gemset --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/.ruby-gemset Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1 @@ +omega diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/.ruby-version --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/.ruby-version Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1 @@ +1.9.3 diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/Gemfile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/Gemfile Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,26 @@ +source 'https://rubygems.org' + +group :development do + + # Sass, Compass and extensions. + gem 'sass' # Sass. + gem 'sass-globbing' # Import Sass files based on globbing pattern. + gem 'compass' # Framework built on Sass. + gem 'compass-validator' # So you can `compass validate`. + gem 'compass-normalize' # Compass version of normalize.css. + gem 'compass-rgbapng' # Turns rgba() into .png's for backwards compatibility. + gem 'susy' # Susy grid framework. + gem 'singularitygs' # Alternative to the Susy grid framework. + gem 'toolkit' # Compass utility from the fabulous Snugug. + gem 'breakpoint' # Manages CSS media queries. + gem 'oily_png' # Faster Compass sprite generation. + gem 'css_parser' # Helps `compass stats` output statistics. + + # Dependency to prevent polling. Setup for multiple OS environments. + # Optionally remove the lines not specific to your OS. + # https://github.com/guard/guard#efficient-filesystem-handling + gem 'rb-inotify', '~> 0.9', :require => false # Linux + gem 'rb-fsevent', :require => false # Mac OSX + gem 'rb-fchange', :require => false # Windows + +end diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/Gemfile.lock --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/Gemfile.lock Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,72 @@ +GEM + remote: https://rubygems.org/ + specs: + addressable (2.3.5) + breakpoint (2.0.5) + compass (>= 0.12.1) + sass (>= 3.2.0) + chunky_png (1.2.8) + color-schemer (0.2.5) + compass (~> 0.12) + compass-blend-modes (~> 0.0.2) + compass (0.12.2) + chunky_png (~> 1.2) + fssm (>= 0.2.7) + sass (~> 3.1) + compass-blend-modes (0.0.2) + compass + compass-normalize (1.4.3) + compass (>= 0.12.0) + compass-rgbapng (0.2.1) + chunky_png (>= 0.8.0) + compass (>= 0.10.0) + compass-validator (3.0.1) + css_parser (1.3.4) + addressable + ffi (1.9.0) + fssm (0.2.10) + oily_png (1.1.0) + chunky_png (~> 1.2.7) + rb-fchange (0.0.6) + ffi + rb-fsevent (0.9.3) + rb-inotify (0.9.0) + ffi (>= 0.5.0) + sass (3.2.9) + sass-globbing (1.1.0) + sass (>= 3.1) + sassy-strings (0.3.1) + compass (>= 0.12.2) + singularitygs (1.0.8) + breakpoint (>= 2.0.1) + compass (>= 0.12.2) + sass (>= 3.2.1) + susy (1.0.9) + compass (>= 0.12.2) + sass (>= 3.2.0) + toolkit (1.3.3) + breakpoint (>= 2.0.2) + color-schemer (>= 0.2.3) + compass (>= 0.12.2) + sassy-strings (>= 0.1) + singularitygs (>= 1.0.7) + +PLATFORMS + ruby + +DEPENDENCIES + breakpoint + compass + compass-normalize + compass-rgbapng + compass-validator + css_parser + oily_png + rb-fchange + rb-fsevent + rb-inotify (~> 0.9) + sass + sass-globbing + singularitygs + susy + toolkit diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/Gruntfile.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/Gruntfile.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,74 @@ +'use strict'; + +module.exports = function (grunt) { + + grunt.initConfig({ + watch: { + options: { + livereload: true + }, + sass: { + files: ['sass/{,**/}*.{scss,sass}'], + tasks: ['compass'] + }, + images: { + files: ['images/**'] + }, + css: { + files: ['stylesheets/{,**/}*.css'] + }, + js: { + files: ['js/{,**/}*.js', '!js/{,**/}*.js'], + tasks: ['jshint', 'uglify:dev'] + } + }, + + compass: { + all: { + options: { + environment: 'production', + force: true, + config: 'config.rb', + bundleExec: true + } + } + }, + + jshint: { + options: { + jshintrc: '.jshintrc' + }, + all: ['js/{,**/}*.js', '!js/{,**/}*.min.js'] + }, + + uglify: { + options: { + mangle: false, + compress: false + }, + all: { + files: { + 'js/jquery.matchmedia.min.js': ['js/jquery.matchmedia.js'], + 'js/jquery.resizeend.min.js': ['js/jquery.resizeend.js'], + 'js/jquery.scrollable.min.js': ['js/jquery.matchmedia.js'], + 'js/omega.admin.min.js': ['js/omega.admin.js'], + 'js/omega.indicator.min.js': ['js/omega.indicator.js'], + 'js/omega.mediaqueries.min.js': ['js/omega.mediaqueries.js'], + 'js/omega.messages.min.js': ['js/omega.messages.js'] + } + } + } + }); + + grunt.loadNpmTasks('grunt-contrib-watch'); + grunt.loadNpmTasks('grunt-contrib-compass'); + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-contrib-uglify'); + + grunt.registerTask('build', [ + 'uglify', + 'compass', + 'jshint' + ]); + +}; diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/README.md Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,19 @@ +# Omega base theme + +Omega 4.x is a modern, [Sass](http://sass-lang.com/) and [Compass](http://compass-style.org/) enabled Drupal 7 base theme. + +## Installation + +In order to install Omega 4.x, simply place it in your sites theme folder (normally located at sites/all/themes). Omega 4.x is a base theme and as such should **never** be used or modified directly. Instead, you should use the [sub-theming functionality](https://drupal.org/node/225125) provided by Drupal. + +The easiest way to create a new Omega-based sub-theme is by using [Drush](http://drupal.org/project/drush). Omega comes with a very easy-to-use Drush command for generating sub-themes through a command-line wizard. You can start the sub-theme creation wizard by invoking `drush omega-wizard` in the command-line. + +## Documentation + +The [Omega 4.x documentation](https://drupal.org/node/1768686) is hosted on drupal.org as part of the handbook section. Please note that we are still in the process of writing the documentation. If you want to get involved, please contact us. + +## Maintainance + +This version of the Omega theme is maintained by [Sebastian Siemssen](http://drupal.org/user/761344) ([@thefubhy](http://twitter.com/thefubhy)) and [Matt Smith](http://drupal.org/user/1012210) ([@splatio_](http://twitter.com/splatio_)) + +If you wish to get involved, visit us in [#drupal-omega](irc://chat.freenode.net:6667/drupal-omega) on IRC or send us a message through the issue queue or our personal contact forms on [drupal.org](http://drupal.org). diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/apple-touch-icon-precomposed-114x114.png Binary file sites/all/themes/omega/omega/apple-touch-icon-precomposed-114x114.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/apple-touch-icon-precomposed-144x144.png Binary file sites/all/themes/omega/omega/apple-touch-icon-precomposed-144x144.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/apple-touch-icon-precomposed-72x72.png Binary file sites/all/themes/omega/omega/apple-touch-icon-precomposed-72x72.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/apple-touch-icon-precomposed.png Binary file sites/all/themes/omega/omega/apple-touch-icon-precomposed.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/bower.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/bower.json Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,11 @@ +{ + "name": "omega", + "version": "1.0.0", + "dependencies": { + "respond": "fubhy/respond", + "selectivizr": "fubhy/selectivizr", + "html5shiv": "fubhy/html5shiv", + "matchmedia": "fubhy/matchmedia", + "pie": "fubhy/pie" + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/config.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/config.rb Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,48 @@ +## +## This file is only needed for Compass/Sass integration. If you are not using +## Compass, you may safely ignore or delete this file. +## +## If you'd like to learn more about Sass and Compass, see the sass/README.txt +## file for more information. +## + +# Default to development if environment is not set. +saved = environment +if (environment.nil?) + environment = :development +else + environment = saved +end + +# Location of the theme's resources. +css_dir = "css" +sass_dir = "sass" +images_dir = "images" +generated_images_dir = images_dir + "/generated" +javascripts_dir = "js" + +# Require any additional compass plugins installed on your system. +require 'compass-normalize' +require 'rgbapng' +require 'toolkit' +require 'susy' +require 'sass-globbing' + +## +## You probably don't need to edit anything below this. +## + +# You can select your preferred output style here (:expanded, :nested, :compact +# or :compressed). +output_style = (environment == :production) ? :expanded : :nested + +# To enable relative paths to assets via compass helper functions. Since Drupal +# themes can be installed in multiple locations, we don't need to worry about +# the absolute path to the theme from the server omega. +relative_assets = true + +# Conditionally enable line comments when in development mode. +line_comments = (environment == :production) ? false : true + +# Output debugging info in development mode. +sass_options = (environment == :production) ? {} : {:debug_info => true} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/layouts/epiqo/epiqo.layout.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/layouts/epiqo/epiqo.layout.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,4 @@ +/* + Mixins are slightly modified from Benjamin Doherty's first implementations: http://gist.github.com/377912 + rgba-background mixin can now be passed an option $dir variable +*/ diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/layouts/simple/simple.layout.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/layouts/simple/simple.layout.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,142 @@ +/******************************************************************************* + * _layout.scss + * + * Styling of the "simple" layout demonstrating the Compass grid extension Susy + * and building mobile first layouts. + ******************************************************************************/ +.l-header, +.l-main, +.l-footer { + *zoom: 1; + max-width: 1190px; + _width: 1190px; + padding-left: 5px; + padding-right: 5px; + margin-left: auto; + margin-right: auto; + margin-bottom: 20px; +} +.l-header:after, +.l-main:after, +.l-footer:after { + content: ""; + display: table; + clear: both; +} + +.l-region--highlighted, +.l-region--help, +.l-region--sidebar-first, +.l-region--sidebar-second { + margin-bottom: 20px; +} + +@media (min-width: 44em) { + .l-header, + .l-main, + .l-footer { + max-width: 1190px; + } + + .l-branding { + width: 32.20339%; + float: left; + margin-right: 1.69492%; + } + + .l-region--header { + width: 66.10169%; + float: right; + margin-right: 0; + } + + .l-region--navigation { + clear: both; + } + + .sidebar-first .l-content, + .sidebar-second .l-content, + .two-sidebars .l-content { + width: 66.10169%; + float: left; + margin-right: 1.69492%; + } + .sidebar-first .l-region--sidebar-first, + .sidebar-first .l-region--sidebar-second, + .sidebar-second .l-region--sidebar-first, + .sidebar-second .l-region--sidebar-second, + .two-sidebars .l-region--sidebar-first, + .two-sidebars .l-region--sidebar-second { + width: 32.20339%; + float: right; + margin-right: 0; + } + .sidebar-first .l-region--sidebar-second, + .sidebar-second .l-region--sidebar-second, + .two-sidebars .l-region--sidebar-second { + clear: right; + } +} +@media (min-width: 70em) { + .l-header, + .l-main, + .l-footer { + max-width: 1190px; + } + + .l-branding { + width: 36.70886%; + float: left; + margin-right: 1.26582%; + } + + .l-region--header { + width: 62.02532%; + float: right; + margin-right: 0; + } + + .sidebar-first .l-content { + width: 74.68354%; + float: right; + margin-right: 0; + } + .sidebar-first .l-region--sidebar-first { + width: 24.05063%; + float: left; + margin-right: 1.26582%; + } + + .sidebar-second .l-content { + width: 74.68354%; + float: left; + margin-right: 1.26582%; + } + .sidebar-second .l-region--sidebar-second { + width: 24.05063%; + float: right; + margin-right: 0; + clear: none; + } + + .two-sidebars .l-content { + width: 49.36709%; + float: left; + margin-right: 1.26582%; + margin-left: 25.31646%; + } + .two-sidebars .l-region--sidebar-first, + .two-sidebars .l-region--sidebar-second { + width: 24.05063%; + float: left; + margin-right: 1.26582%; + } + .two-sidebars .l-region--sidebar-first { + margin-left: -75.94937%; + } + .two-sidebars .l-region--sidebar-second { + float: right; + margin-right: 0; + clear: none; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/aggregator/aggregator.theme-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/aggregator/aggregator.theme-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,7 @@ +/** + * @file + * Aggregator theme CSS for right to left languages. + */ +.feed-source .feed-icon { + float: left; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/aggregator/aggregator.theme.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/aggregator/aggregator.theme.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,9 @@ +/** + * @file + * Aggregator theme CSS. + */ +.feed-source .feed-icon { + float: right; + /* LTR */ + display: block; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/block/block.admin.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/block/block.admin.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,14 @@ +/** + * @file + * Styles for the block admin page. + */ +.blocks-admin .region-title { + font-weight: bold; +} +.blocks-admin .region-message { + font-weight: normal; + color: #999; +} +.blocks-admin .region-populated { + display: none; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/block/block.demo.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/block/block.demo.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,38 @@ +/** + * @file + * Styles for the block demo page. + */ +.block-region { + margin-top: 4px; + margin-bottom: 4px; + padding: 3px; + background-color: #ff6; +} + +.block-demo-backlink, +.block-demo-backlink:link, +.block-demo-backlink:visited { + /* Position */ + position: fixed; + z-index: 499; + left: 20px; + /* LTR */ + /* Box Model */ + padding: 5px 10px; + /* Font */ + color: #000; + font-family: "Lucida Grande", Verdana, sans-serif; + font-size: small; + line-height: 20px; + /* Other Declarations */ + background-color: #B4D7F0; + -webkit-border-radius: 0 0 10px 10px; + -moz-border-radius: 0 0 10px 10px; + -ms-border-radius: 0 0 10px 10px; + -o-border-radius: 0 0 10px 10px; + border-radius: 0 0 10px 10px; +} + +.block-demo-backlink:hover { + text-decoration: underline; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/book/book.admin.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/book/book.admin.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,29 @@ +/** + * @file + * Administration styles for the Book module. + */ +/** + * Book outline on book edit form. + */ +.js .book-outline-form .form-submit { + display: none; +} + +/** + * Book form for administering a single book's hierarchy. + */ +.book-admin-edit select { + margin-right: 24px; +} + +.book-admin-edit .progress-disabled { + margin-right: 0; +} + +.book-admin-edit .ajax-new-content { + background-color: #ffd; +} + +.book-admin-edit .form-item { + float: left; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/book/book.theme-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/book/book.theme-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,17 @@ +/** + * @file + * Basic default book structural CSS for right to left languages. + */ +.book-navigation__previous { + float: right; + text-align: right; +} + +.book-navigation__up { + float: right; +} + +.book-navigation__next { + float: left; + text-align: left; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/book/book.theme.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/book/book.theme.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,29 @@ +/** + * @file + * Basic theming for the book navigation component. + */ +.book-navigation__previous { + float: left; + /* LTR */ + display: block; + width: 45%; + text-align: left; + /* LTR */ +} + +.book-navigation__up { + float: left; + /* LTR */ + display: block; + width: 10%; + text-align: center; +} + +.book-navigation__next { + float: right; + /* LTR */ + display: block; + width: 45%; + text-align: right; + /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/color/color.admin-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/color/color.admin-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,56 @@ +/** + * @file + * Right-to-left specific stylesheet for the Color module. + */ +#placeholder { + left: 0; + right: auto; +} + +/* Palette */ +.color-form .form-item { + padding-left: 0; + padding-right: 1em; +} + +.color-form label { + float: right; + clear: right; +} + +.color-form .form-text, +.color-form .form-select { + float: right; +} + +.color-form .form-text { + margin-right: 0; + margin-left: 5px; +} + +#palette .hook { + float: right; +} + +#palette .down, +#palette .up, +#palette .both { + background: url('../../../images/modules/color/hook-rtl.png?1378983654') no-repeat 0 0; +} + +#palette .up { + background-position: 0 -27px; +} + +#palette .both { + background-position: 0 -54px; +} + +#palette .lock { + float: right; + right: -10px; +} + +html.js #preview { + float: right; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/color/color.admin.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/color/color.admin.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,108 @@ +/** + * @file + * Stylesheet for the administration pages of the Color module. + */ +/* Farbtastic placement */ +.color-form { + max-width: 50em; + position: relative; +} + +#placeholder { + position: absolute; + top: 0; + right: 0; + /* LTR */ +} + +/* Palette */ +.color-form .form-item { + height: 2em; + line-height: 2em; + padding-left: 1em; + /* LTR */ + margin: 0.5em 0; +} + +.color-form label { + float: left; + /* LTR */ + clear: left; + /* LTR */ + width: 10em; +} + +.color-form .form-text, +.color-form .form-select { + float: left; + /* LTR */ +} + +.color-form .form-text { + text-align: center; + margin-right: 5px; + /* LTR */ + cursor: pointer; +} + +#palette .hook { + float: left; + /* LTR */ + margin-top: 3px; + width: 16px; + height: 16px; +} + +#palette .down, +#palette .up, +#palette .both { + background: url('../../../images/modules/color/hook.png?1378983654') no-repeat 100% 0; + /* LTR */ +} + +#palette .up { + background-position: 100% -27px; + /* LTR */ +} + +#palette .both { + background-position: 100% -54px; + /* LTR */ +} + +#palette .lock { + float: left; + /* LTR */ + position: relative; + top: -1.4em; + left: -10px; + /* LTR */ + width: 20px; + height: 25px; + background: url('../../../images/modules/color/lock.png?1378983654') no-repeat 50% 2px; + cursor: pointer; +} + +#palette .unlocked { + background-position: 50% -22px; +} + +#palette .form-item { + width: 20em; +} + +#palette .item-selected { + background: #eee; +} + +/* Preview */ +#preview { + display: none; +} + +html.js #preview { + display: block; + position: relative; + float: left; + /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/comment/comment.theme-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/comment/comment.theme-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,8 @@ +/** + * @file + * Right-to-left comment module look and feel styling. + */ +.indented { + margin-left: 0; + margin-right: 25px; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/comment/comment.theme.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/comment/comment.theme.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,8 @@ +/** + * @file + * Comment module look and feel styling. + */ +.indented { + margin-left: 25px; + /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/contextual/contextual.base-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/contextual/contextual.base-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,15 @@ +/** + * @file + * Styling for contextual links behaviour and structure. + */ +/** + * Contextual links structure. + */ +.contextual-links-wrapper { + left: 5px; + right: auto; +} + +.contextual-links-trigger { + text-align: left; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/contextual/contextual.base.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/contextual/contextual.base.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,41 @@ +/** + * @file + * Styling for contextual links behaviour and structure. + */ +/** + * Contextual links behaviour. + */ +.contextual-links-wrapper, +.contextual-links-trigger, +.contextual-links { + display: none !important; +} + +html.js .contextual-links-wrapper, +.contextual-links-region:hover .contextual-links-trigger, +.contextual-links-active .contextual-links-trigger, +.contextual-links-active .contextual-links { + display: block !important; +} + +/** + * Contextual links structure. + */ +.contextual-links-region { + outline: none; + position: relative; +} + +.contextual-links-wrapper { + position: absolute; + z-index: 999; + right: 5px; + /* LTR */ + top: 2px; +} + +.contextual-links-trigger { + overflow: hidden; + text-align: right; + /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/contextual/contextual.theme-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/contextual/contextual.theme-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,16 @@ +/** + * @file + * Styling for contextual links look and feel. + */ +/** + * Contextual links. + */ +.contextual-links { + left: 0; + right: auto; + -webkit-border-radius: 0 4px 4px 4px; + -moz-border-radius: 0 4px 4px 4px; + -ms-border-radius: 0 4px 4px 4px; + -o-border-radius: 0 4px 4px 4px; + border-radius: 0 4px 4px 4px; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/contextual/contextual.theme.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/contextual/contextual.theme.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,108 @@ +/** + * @file + * Styling for contextual links look and feel. + * + * We are proactivly making use of !important to ensure the contextual links + * styling isn't broken by unspecific selectors such as ".block a". In order to + * change the styling of the contextual links you should overwrite this file in + * your subtheme. + */ +/** + * Contextual link wrappers + */ +.contextual-links-region-active { + outline: #999 dashed 1px; +} + +.contextual-links-wrapper { + font-size: 12px !important; +} +.contextual-links-wrapper a { + text-decoration: none; +} + +/** + * Contextual trigger. +*/ +.contextual-links-trigger { + /* Positioning */ + height: 18px; + /* Box Model */ + margin: 0 !important; + padding: 0 2px !important; + width: 28px; + /* Other Declarations */ + background: transparent url('../../../images/modules/contextual/gear-select.png?1378983654') no-repeat 2px 0 !important; + border: 1px solid transparent !important; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + -ms-border-radius: 4px; + -o-border-radius: 4px; + border-radius: 4px; + outline: none; + text-indent: 9999px; + /* LTR */ +} + +.contextual-links-trigger:hover, +.contextual-links-active .contextual-links-trigger { + background-position: 2px -18px !important; +} + +.contextual-links-active .contextual-links-trigger { + /* Positioning */ + position: relative; + z-index: 1; + /* Other Declarations */ + background-color: #fff !important; + border-color: #ccc !important; + border-bottom: none !important; + -moz-border-radius-bottomleft: 0; + -webkit-border-bottom-left-radius: 0; + border-bottom-left-radius: 0; + -moz-border-radius-bottomright: 0; + -webkit-border-bottom-right-radius: 0; + border-bottom-right-radius: 0; +} + +/** + * Contextual links. + */ +.contextual-links { + /* Position */ + position: absolute; + right: 0; + /* LTR */ + top: 18px; + /* Box Model */ + margin: 0 !important; + padding: 0 !important; + /* Other Declarations */ + background-color: #fff !important; + border: 1px solid #ccc !important; + -webkit-border-radius: 4px 0 4px 4px; + -moz-border-radius: 4px 0 4px 4px; + -ms-border-radius: 4px 0 4px 4px; + -o-border-radius: 4px 0 4px 4px; + border-radius: 4px 0 4px 4px; + /* LTR */ + text-align: left; + white-space: nowrap; +} +.contextual-links li { + margin: 0 !important; + padding: 0 !important; + line-height: 100%; + list-style: none; + list-style-image: none; +} +.contextual-links a { + display: block; + margin: 0 !important; + padding: 5px 10px !important; + color: #333 !important; + font-size: 12px !important; +} +.contextual-links a:hover { + background-color: #bfdcee !important; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/field/field.theme-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/field/field.theme-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,11 @@ +/** + * @file + * Styling for contextual links behaviour and structure. + */ +/** + * Field display. + */ +.field--label-inline .field__label, +.field--label-inline .field__items { + float: right; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/field/field.theme.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/field/field.theme.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,16 @@ +/** + * @file + * Styling for contextual links behaviour and structure. + */ +/** + * Field display. + */ +.field__label { + font-weight: bold; +} + +.field--label-inline .field__label, +.field--label-inline .field__items { + float: left; + /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/field_ui/field_ui.admin-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/field_ui/field_ui.admin-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,14 @@ +/** + * @file + * Right-to-left specific stylesheet for the Field UI module. + */ +/** + *'Manage fields' and 'Manage display' overviews. + */ +.field-ui-overview { + /* Add New Row */ +} +.field-ui-overview .add-new .label-input { + float: right; + /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/field_ui/field_ui.admin.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/field_ui/field_ui.admin.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,44 @@ +/** + * @file + * Stylesheet for the Field UI module. + */ +/** + *'Manage fields' and 'Manage display' overviews. + */ +.field-ui-overview { + /* Add New Row */ + /* Hidden Messages */ +} +.field-ui-overview .add-new td { + vertical-align: top; +} +.field-ui-overview .add-new .label-input { + float: left; + /* LTR */ +} +.field-ui-overview .add-new .tabledrag-changed { + display: none; +} +.field-ui-overview .add-new .form-type-machine-name .description { + white-space: normal; +} +.field-ui-overview .region-add-new-title { + display: none; +} +.field-ui-overview .region-populated { + display: none; +} + +/** + * 'Manage display' overview + */ +.field-display-overview .field-formatter-settings-editing td { + vertical-align: top; +} +.field-display-overview .field-formatter-settings-editing .field-formatter-type { + display: none; +} + +.field-ui-display-overview-form #edit-refresh { + display: none; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/file/file.theme.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/file/file.theme.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,24 @@ +/** + * @file + * Admin stylesheet for file module. + */ +/** + * Managed file element. + */ +.form-managed-file .progress-disabled { + float: none; + display: inline; +} +.form-managed-file .ajax-progress, +.form-managed-file .throbber { + float: none; +} +.form-managed-file .ajax-progress-bar { + display: none; + width: 28em; + margin-top: 4px; + padding: 0; +} +.form-managed-file .ajax-progress-bar .bar { + margin: 0; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/filter/filter.theme.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/filter/filter.theme.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,49 @@ +/** + * @file + * Styling for the filter module. + */ +/** + * Top Level Wrapper + * Contains the form item being filtered, the filter format form item and + * formatting guidelines. + */ +.text-format-wrapper .form-item { + margin-bottom: 0; +} +.text-format-wrapper .description { + margin-top: 0.5em; +} + +/* Filter Format Wrapper. */ +.filter-wrapper { + border-top: 0; + margin: 0; +} +.filter-wrapper .form-item { + float: left; + padding: 0 0 0.5em 1.5em; +} +.filter-wrapper .form-item label { + display: inline; +} + +/* More Information Link. */ +.filter-help { + float: right; + padding: 0 1.5em 0.5em; +} +.filter-help a { + background: transparent url('../../../images/misc/help.png?1378983654') right center no-repeat; + padding: 0 20px; +} + +/* Filter Guidelines */ +.filter-guidelines { + clear: left; + padding: 0 1.5em; +} + +/* Filter formatting tips. */ +.tips { + font-size: 0.9em; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/forum/forum.theme-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/forum/forum.theme-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,9 @@ +/** + * @file + * Right-to-left styling for the Forum module. + */ +.forum-icon { + float: right; + margin-left: 0; + margin-right: 0.4em; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/forum/forum.theme.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/forum/forum.theme.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,34 @@ +/** + * @file + * Styling for the Forum module. + */ +/* Forum Status Icons */ +.forum-icon { + float: left; + width: 24px; + height: 24px; + margin-right: 0.4em; + background-image: url('../../../images/modules/forum/forum-icons.png?1378983654'); + background-repeat: no-repeat; + text-indent: -9999px; +} + +.forum-icon--status-new { + background-position: -24px 0; +} + +.forum-icon--status-hot { + background-position: -48px 0; +} + +.forum-icon--status-hot-new { + background-position: -72px 0; +} + +.forum-icon--status-sticky { + background-position: -96px 0; +} + +.forum-icon--status-closed { + background-position: -120px 0; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/image/image.admin.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/image/image.admin.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,70 @@ +/** + * @file + * Admin styles for the image module. + */ +/** + * Image style configuration pages. + */ +/* Add new effect form. */ +.image-style-new, +.image-style-new div { + display: inline; +} + +/* Image style columns. */ +.image-style-preview__col { + float: left; + top: 50%; + width: 48%; + padding-bottom: 2em; + text-align: center; +} + +/* Image style preview images. */ +.image-style-preview__preview-image { + margin: auto; + position: relative; +} + +.preview-image__width { + position: absolute; + height: 2px; + left: -1px; + bottom: -6px; + border: 1px solid #666; + border-top: none; +} +.preview-image__width .dimension { + position: relative; + top: 4px; +} + +.preview-image__height { + position: absolute; + right: -6px; + top: -1px; + width: 2px; + border: 1px solid #666; + border-left: none; +} +.preview-image__height .dimension { + position: absolute; + height: 2em; + top: 50%; + left: 10px; + margin-top: -1em; +} + +/** + * Image anchor form element. + */ +.image-anchor { + width: auto; +} +.image-anchor .even, +.image-anchor .odd { + background: none; +} +.image-anchor td { + border: 1px solid #CCC; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/image/image.theme-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/image/image.theme-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,15 @@ +/** + * @file + * Right-to-left styling for the Forum module. + */ +/** + * Image upload widget. + */ +.image-preview { + float: right; + padding: 0 0 10px 10px; +} + +.image-widget-data { + float: right; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/image/image.theme.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/image/image.theme.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,21 @@ +/** + * @file + * Styles for the image module. + */ +/** + * Image upload widget. + */ +.image-preview { + float: left; + /* LTR */ + padding: 0 10px 10px 0; + /* LTR */ +} + +.image-widget-data { + float: left; + /* LTR */ +} +.image-widget-data .text-field { + width: auto; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/locale/locale.admin-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/locale/locale.admin-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,15 @@ +/** + * @file + * Right to left admin styles for the locale module. + */ +.locale-translation-filter-form .form-item-language, +.locale-translation-filter-form .form-item-translation, +.locale-translation-filter-form .form-item-group { + float: right; + padding-left: .8em; + padding-right: 0; +} +.locale-translation-filter-form .form-actions { + float: right; + padding: 3ex 1em 0 0; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/locale/locale.admin.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/locale/locale.admin.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,31 @@ +/** + * @file + * Admin styles for the locale module. + */ +/* Untranslated locales. */ +.locale-untranslated { + font-style: normal; + text-decoration: line-through; +} + +/* Translations 'exposed' filter form. */ +.locale-translation-filter-form .form-item-language, +.locale-translation-filter-form .form-item-translation, +.locale-translation-filter-form .form-item-group { + float: left; + /* LTR */ + padding-right: .8em; + /* LTR */ + margin: 0.1em; + width: 15em; + /* Opera 9 Fix. */ +} +.locale-translation-filter-form .form-type-select select { + width: 100%; +} +.locale-translation-filter-form .form-actions { + float: left; + /* LTR */ + padding: 3ex 0 0 1em; + /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/openid/openid.base-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/openid/openid.base-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,8 @@ +/** + * @file + * Right to left base styles for the Open ID module. + */ +html.js .user-login-form .openid-link, +html.js .user-login .openid-link { + margin-right: 0; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/openid/openid.base.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/openid/openid.base.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,15 @@ +/** + * @file + * Base styles for the Open ID module. + */ +html.js .user-login-form .openid-link, +html.js .user-login .openid-link { + display: block; + margin-left: 0; + /* LTR */ +} + +html.js .user-login-form .form-item-openid-identifier, +html.js .user-login .form-item-openid-identifier { + display: none; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/openid/openid.theme-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/openid/openid.theme-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,14 @@ +/** + * @file + * Right to left theme styles for the openid module. + */ +.form-item-openid-identifier input { + padding-left: 0; + padding-right: 20px; + background-position: right 50%; +} + +.openid-links a { + padding: 0 1.5em 0 0; + background-position: right top; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/openid/openid.theme.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/openid/openid.theme.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,30 @@ +/** + * @file + * Theme styles for the openid module. + */ +.form-item-openid-identifier { + display: block; +} +.form-item-openid-identifier input { + padding-left: 20px; + /* LTR */ + background-image: url('../../../images/modules/openid/login-bg.png?1378983654'); + background-position: left 50%; + /* LTR */ + background-repeat: no-repeat; +} + +.openid-links li { + display: none; + margin: 0; + padding: 0; + list-style: none; +} +.openid-links a { + padding: 0 0 0 1.5em; + /* LTR */ + background-image: url('../../../images/modules/openid/login-bg.png?1378983654'); + background-position: left top; + /* LTR */ + background-repeat: no-repeat; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/poll/poll.admin.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/poll/poll.admin.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,13 @@ +/** + * @file + * Admin styles for the poll module. + */ +/* Poll choice form on node form. */ +.poll-choice-table .form-text { + display: inline; + width: auto; +} +.poll-choice-table .choice-flag { + white-space: nowrap; + width: 4em; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/poll/poll.theme-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/poll/poll.theme-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,16 @@ +/** + * @file + * Right to left theme for the poll voting form and results display. + */ +/* Poll Bars */ +.poll-bars__bar .foreground { + float: right; +} + +.poll-bars__text { + text-align: right; +} + +.poll-bars__percent { + text-align: left; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/poll/poll.theme.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/poll/poll.theme.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,43 @@ +/** + * @file + * Theme for the poll voting form and results display. + */ +/** + * Poll Results + */ +/* Poll Bars */ +.poll-bars__bar { + height: 1em; + margin: 1px 0; + background-color: #ddd; +} +.poll-bars__bar .foreground { + height: 1em; + float: left; + /* LTR */ + background-color: #000; +} + +.poll-bars__percent { + text-align: right; + /* LTR */ +} + +/* Poll Total */ +.poll-results__total { + text-align: center; +} + +/** + * Poll Voting Form + */ +.poll-vote-form { + text-align: center; +} + +.poll-vote-form__choices { + display: table; + margin: 0 auto; + text-align: left; + /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/search/search.theme-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/search/search.theme-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,24 @@ +/** + * @file + * Right to left search module theme. + */ +/** + * Search Results + */ +.search-result__snippet { + padding-left: 0; + padding-right: 1em; +} + +/** + * Advanced Search Form + */ +.search-advanced .criterion { + float: right; + margin-right: 0; + margin-left: 2em; +} +.search-advanced .action { + float: right; + clear: right; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/search/search.theme.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/search/search.theme.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,31 @@ +/** + * @file + * Search module theme. + */ +/** + * Search Results + */ +.search-result__snippet { + padding-left: 1em; + /* LTR */ +} + +.search-result__info { + font-size: 0.85em; +} + +/** + * Advanced Search Form + */ +.search-advanced .criterion { + float: left; + /* LTR */ + margin-right: 2em; + /* LTR */ +} +.search-advanced .action { + float: left; + /* LTR */ + clear: left; + /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/system/system.admin-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/system/system.admin-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,92 @@ +/** + * @file + * Right to left system wide administration styles. + */ +/** + * @file + * Right to left administration style for administration blocks. + */ +/* Admin Panels */ +.admin-panel .admin-panel__body { + padding-right: 1em; +} + +/* Admin Panel Page Layout */ +.admin .left { + float: right; +} +.admin .right { + float: left; +} +.admin .expert-link { + margin-left: 0; + margin-right: 1em; + padding-left: 0; + padding-right: 4px; + text-align: left; +} + +/** + * @file + * Right to left administration styles for the appearance page. + */ +/** + * Disabled/Enabled Theme Lists + */ +/* Theme Selector Links */ +.theme-selector__operations li { + float: right; +} + +/* Theme Selector Enabled State */ +.theme-selector--enabled .theme-selector__info { + float: left; +} +.theme-selector--enabled .theme-selector__screenshot { + float: right; +} + +/* Theme Selector Disabled State */ +.theme-selector--disabled { + float: right; + padding: 20px 20px 20px; +} + +/** + * @file + * Right to left administration styles for the modules table. + */ +/* Module Operation Links */ +.module-link { + padding: 1px 20px 1px 0; +} + +.module-link-help { + background: url('../../../images/misc/help.png?1378983654') 0 50% no-repeat; + /* LTR */ +} + +.module-link-permissions { + background: url('../../../images/misc/permissions.png?1378983654') 0 50% no-repeat; + /* LTR */ +} + +.module-link-configure { + background: url('../../../images/misc/configure.png?1378983654') 0 50% no-repeat; + /* LTR */ +} + +/* Module Help */ +.module-help { + float: left; + margin-left: 0; + margin-right: 1em; +} + +/** + * @file + * Right to left administration styles for the system status report. + */ +.merge-up td { + padding: 0 28px 8px 6px; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/system/system.admin.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/system/system.admin.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,273 @@ +/** + * @file + * System wide administration styles. + */ +/** + * @file + * Administration styles for quick inline admin links. + */ +small .admin-link:before { + content: '['; +} + +small .admin-link:after { + content: ']'; +} + +/** + * @file + * Administration styles for the administration panels. + */ +/* Admin Panels */ +.admin-panel .admin-panel__body { + padding-left: 1em; + /* LTR */ +} + +/* Admin Panel Page Layout */ +.admin { + padding-top: 15px; +} +.admin .left { + float: left; + /* LTR */ + width: 47%; +} +.admin .right { + float: right; + /* LTR */ + width: 47%; +} +.admin .expert-link { + margin-right: 1em; + /* LTR */ + padding-right: 4px; + /* LTR */ + text-align: right; + /* LTR */ +} + +/** + * @file + * Administration styles for the appearance page. + */ +/** + * Disabled/Enabled Theme Lists + */ +.system-themes-list { + margin-bottom: 20px; +} +.system-themes-list h2 { + margin: 0; +} + +.system-themes-list--disabled { + padding-top: 20px; + border-top: 1px solid #cdcdcd; +} + +/** + * Theme Selector + */ +.theme-selector { + padding-top: 20px; +} +.theme-selector h3 { + font-weight: normal; +} + +/* Theme Selector Screenshot */ +.theme-selector__screenshot { + padding: 2px; + width: 294px; + height: 219px; + border: 1px solid #e0e0d8; + line-height: 219px; + text-align: center; +} + +/* Theme Selector Incompatible Message */ +.theme-selector__incompatible { + margin-top: 10px; + font-weight: bold; +} + +/* Theme Selector Links */ +.theme-selector__operations { + margin: 10px 0 0 0; + padding: 0; +} +.theme-selector__operations li { + float: left; + /* LTR */ + margin: 0 1em 0 0; + list-style-type: none; +} + +/* Theme Selector Default State */ +.theme-selector--default h3 { + font-weight: bold; +} +.theme-selector--default .theme-selector__screenshot { + border: 1px solid #aaa; +} + +/* Theme Selector Enabled State */ +.theme-selector--enabled { + width: 820px; +} +.theme-selector--enabled .theme-selector__info { + float: right; + /* LTR */ + width: 500px; +} +.theme-selector--enabled h3 { + margin-top: 0; +} +.theme-selector--enabled .theme-selector__screenshot { + float: left; + /* LTR */ +} + +/* Theme Selector Disabled State */ +.theme-selector--disabled { + float: left; + /* LTR */ + width: 300px; + padding: 20px 20px 20px 0; + /* LTR */ +} +.theme-selector--disabled .theme-selector__info { + min-height: 170px; +} +.theme-selector--disabled .theme-selector__screenshot { + width: 194px; + height: 144px; + line-height: 144px; +} + +/** + * Admin Theme Selector Form + */ +.system-themes-admin-form { + clear: left; +} + +/** + * @file + * Administration styles for compact links. + */ +.compact-link { + margin: 0 0 0.5em 0; +} + +/** + * @file + * Administration styles for the modules table and help. + */ +/* Module State Flags */ +.admin-disabled { + color: #800; +} + +.admin-enabled { + color: #080; +} + +.admin-missing { + color: #f00; +} + +/* Incompatible Modules */ +.incompatible { + font-weight: bold; +} + +/* Module Requirements */ +.admin-requirements, +.admin-required { + font-size: 0.9em; + color: #444; +} + +/* Module Operation Links */ +.module-link { + display: block; + padding: 1px 0 1px 20px; + /* LTR */ + white-space: nowrap; +} + +.module-link-help { + background: url('../../../images/misc/help.png?1378983654') 0 50% no-repeat; + /* LTR */ +} + +.module-link-permissions { + background: url('../../../images/misc/permissions.png?1378983654') 0 50% no-repeat; + /* LTR */ +} + +.module-link-configure { + background: url('../../../images/misc/configure.png?1378983654') 0 50% no-repeat; + /* LTR */ +} + +/* Module Help */ +.module-help { + float: right; + /* LTR */ + margin-left: 1em; + /* LTR */ +} + +/** + * @file + * Administration styles for the system status report. + */ +/* Status Icons */ +.system-status-report .status-icon { + height: 16px; + width: 16px; + background-repeat: no-repeat; +} +.system-status-report .error .status-icon { + background-image: url('../../../images/misc/message-16-error.png?1378983654'); +} +.system-status-report .warning .status-icon { + background-image: url('../../../images/misc/message-16-warning.png?1378983654'); +} + +/* Merge Cells */ +.merge-down, +.merge-down td { + border-bottom-width: 0 !important; +} + +.merge-up, +.merge-up td { + border-top-width: 0 !important; +} + +.merge-up td { + padding: 0 6px 8px 28px; + /* LTR */ +} + +/** + * @file + * Administration styles for the theme settings. + */ +.theme-settings-left { + float: left; + width: 49%; +} + +.theme-settings-right { + float: right; + width: 49%; +} + +.theme-settings-bottom { + clear: both; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/system/system.base-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/system/system.base-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,65 @@ +/** + * @file + * Right to left system wide base styles. + */ +/** + * @file + * Right to left base styles for autocomplete functionality. + * + * @see autocomplete.js + */ +/* Animated throbber */ +html.js .form-autocomplete { + background-position: 0% 2px; +} + +html.js .throbbing { + background-position: 0% -18px; +} + +/** + * @file + * Right to left base styling for the tabledrag behavior. + * + * @see tabledrag.js + */ +.draggable .tabledrag-handle { + float: right; + margin-left: 0; +} + +.indentation { + float: right; +} + +.tree-child, +.tree-child-last { + background-position: -65px center; +} + +.tabledrag-toggle-weight-wrapper { + text-align: left; +} + +/** + * @file + * Right to left base styles for the progress behavior. + * + * @see progress.js + */ +/* Bar */ +.progress .percentage { + float: left; +} + +.progress-disabled { + float: right; +} + +.ajax-progress { + float: right; +} + +.ajax-progress .throbber { + float: right; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/system/system.base.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/system/system.base.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,289 @@ +/** + * @file + * System wide base styles. + */ +/** + * @file + * Base styles for autocomplete functionality. + * + * @see autocomplete.js + */ +/* Suggestion list */ +#autocomplete { + position: absolute; + z-index: 100; + overflow: hidden; +} +#autocomplete ul { + margin: 0; + padding: 0; + list-style: none; + list-style-image: none; +} +#autocomplete li { + cursor: default; + white-space: pre; + zoom: 1; + /* IE7 */ +} + +/* Animated throbber */ +html.js .form-autocomplete { + background-image: url('../../../images/misc/throbber.gif?1378983654'); + background-position: 100% 2px; + /* LTR */ + background-repeat: no-repeat; +} + +html.js .throbbing { + background-position: 100% -18px; + /* LTR */ +} + +/** + * @file + * Base styles for collapsible fieldset functionality. + * + * @see collapse.js + */ +html.js fieldset.collapsed { + height: 1em; +} + +html.js fieldset.collapsed .fieldset-wrapper { + display: none; +} + +fieldset.collapsible { + position: relative; +} + +fieldset.collapsible .fieldset-legend { + display: block; +} + +/** + * @file + * Base styles for the resizable textareas functionality. + * + * @see textarea.js + */ +.form-textarea-wrapper textarea { + display: block; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + width: 100%; + margin: 0; +} + +.resizable-textarea .grippie { + height: 9px; + background: #eeeeee url('../../../images/misc/grippie.png?1378983654') no-repeat center 2px; + border: 1px solid #ddd; + border-top-width: 0; + cursor: s-resize; + overflow: hidden; +} + +/** + * @file + * Base styling for the tabledrag behavior. + * + * @see tabledrag.js + */ +body.drag { + cursor: move; +} + +/* Tabledrag Handle */ +.tabledrag-handle { + float: left; + /* LTR */ + overflow: hidden; + text-decoration: none; + cursor: move; +} +.tabledrag-handle .handle { + height: 15px; + width: 15px; + margin: -0.4em 0; + padding: 0.4em; + background: url('../../../images/misc/draggable.png?1378983654') no-repeat 6px 9px; +} +.tabledrag-handle:hover { + text-decoration: none; +} + +.tabledrag-handle-hover .handle { + background-position: 6px -11px; +} + +/* Indentation */ +.indentation { + float: left; + /* LTR */ + width: 20px; +} + +/* Tree Images */ +.tree-child { + background: url('../../../images/misc/tree.png?1378983654') no-repeat 12px center; + /* LTR */ +} + +.tree-child-last { + background: url('../../../images/misc/tree-bottom.png?1378983654') no-repeat 12px center; + /* LTR */ +} + +.tree-child-horizontal { + background: url('../../../images/misc/tree.png?1378983654') no-repeat -12px center; +} + +/* Toggle Weight Link */ +.tabledrag-toggle-weight-wrapper { + text-align: right; + /* LTR */ +} + +/** + * @file + * Base styling for the tableheader behavior. + * + * @see tableheader.js + */ +.sticky-header { + margin-top: 0; + background-color: #fff; +} + +/** + * @file + * Base styles for the progress behavior. + * + * @see progress.js + */ +/* Bar */ +.progress .bar { + background-color: #fff; + border: 1px solid; +} +.progress .filled { + height: 1.5em; + width: 5px; + background-color: #000; +} +.progress .percentage { + float: right; + /* LTR */ +} + +/* Throbber */ +.ajax-progress { + display: inline-block; +} +.ajax-progress .throbber { + float: left; + /* LTR */ + height: 15px; + width: 15px; + margin: 2px; + background: transparent url('../../../images/misc/throbber.gif?1378983654') no-repeat 0px -18px; +} +.ajax-progress .message { + padding-left: 20px; +} + +tr .ajax-progress .throbber { + margin: 0 2px; +} + +.ajax-progress-bar { + width: 16em; +} + +/** + * @file + * System utility classes. + */ +/** + * Inline items. + */ +.container-inline div, +.container-inline label { + display: inline; +} + +/* Fieldset contents always need to be rendered as block. */ +.container-inline .fieldset-wrapper { + display: block; +} + +/** + * Prevent text wrapping. + */ +.nowrap { + white-space: nowrap; +} + +/** + * For anything you want to hide on page load when JS is enabled, so + * that you can use the JS to control visibility and avoid flicker. + */ +html.js .js-hide { + display: none; +} + +/** + * Hide elements from all users. + * + * Used for elements which should not be immediately displayed to any user. An + * example would be a collapsible fieldset that will be expanded with a click + * from a user. The effect of this class can be toggled with the jQuery show() + * and hide() functions. + */ +.element-hidden { + display: none; +} + +/** + * Hide elements visually, but keep them available for screen-readers. + * + * Used for information required for screen-reader users to understand and use + * the site where visual display is undesirable. Information provided in this + * manner should be kept concise, to avoid unnecessary burden on the user. + * "!important" is used to prevent unintentional overrides. + */ +.element-invisible { + position: absolute !important; + clip: rect(1px 1px 1px 1px); + /* IE6, IE7 */ + clip: rect(1px, 1px, 1px, 1px); + overflow: hidden; + height: 1px; +} + +/** + * The .element-focusable class extends the .element-invisible class to allow + * the element to be focusable when navigated to via the keyboard. + */ +.element-invisible.element-focusable:active, +.element-invisible.element-focusable:focus { + position: static !important; + clip: auto; + overflow: visible; + height: auto; +} + +/** + * Use the clearfix from Compass. + */ +.clearfix { + *zoom: 1; +} +.clearfix:after { + content: ""; + display: table; + clear: both; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/system/system.menus.theme-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/system/system.menus.theme-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,25 @@ +/** + * @file + * Right to left menu and navigational styles. + */ +/** + * @file + * Styles for a hierarchical menu as generated by theme_menu_tree(). + */ +.menu { + text-align: right; + /* Menu Item Hierarchy Modifiers */ +} +.menu .collapsed { + list-style-image: url('../../../images/misc/menu-collapsed-rtl.png?1378983654'); +} + +/** + * @file + * Inline links as generated by theme_links(). + */ +ul.inline li { + float: right; + margin-right: 0; + margin-left: 1em; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/system/system.menus.theme.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/system/system.menus.theme.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,94 @@ +/** + * @file + * Menu and navigational styles. + */ +/** + * @file + * Styles for a hierarchical menu as generated by theme_menu_tree(). + */ +.menu { + border: none; + list-style: none; + text-align: left; + /* LTR */ + /* Menu Item Hierarchy Modifiers */ +} +.menu .expanded { + list-style-image: url('../../../images/misc/menu-expanded.png?1378983654'); + list-style-type: circle; +} +.menu .collapsed { + list-style-image: url('../../../images/misc/menu-collapsed.png?1378983654'); + /* LTR */ + list-style-type: disc; +} +.menu .leaf { + list-style-image: url('../../../images/misc/menu-leaf.png?1378983654'); + list-style-type: square; +} + +/* Menu State Modifiers */ +.active { + color: #000; +} + +.menu-disabled { + background: #ccc; +} + +/** + * @file + * Inline links as generated by theme_links(). + */ +.links--inline { + *zoom: 1; + list-style-type: none; + margin: 0; + padding: 0; +} +.links--inline:after { + content: ""; + display: table; + clear: both; +} +.links--inline li { + float: left; + /* LTR */ + margin-right: 1em; + /* LTR */ +} +.links--inline li > a { + display: block; +} + +/** + * @file + * Theme styles for markup generated by theme_menu_local_tasks(). + */ +/* Tabs */ +.tabs a { + background-color: #eee; + text-decoration: none; +} +.tabs a.active { + background-color: #ccc; +} +.tabs a:hover, .tabs a:focus { + background-color: #bbb; +} + +/* Primary Tabs */ +.tabs--primary { + margin-bottom: 1em; + border-bottom: 1px solid #bbb; +} +.tabs--primary a { + padding: 0.3em 0.8em; +} + +/* Secondary Tabs */ +.tabs--secondary a { + padding: 0.2em 0.5em; + margin: 0.4em 0; + font-size: 0.9em; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/system/system.messages.theme-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/system/system.messages.theme-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,12 @@ +/** + * @file + * Right to left theme for for system messages. + */ +/* Message */ +.messages { + padding: 10px 50px 10px 10px; + background-position: 99% 8px; +} +.messages ul { + margin: 0 1em 0 0; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/system/system.messages.theme.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/system/system.messages.theme.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,74 @@ +/** + * @file + * Theme for for system messages. + */ +/* Message */ +.messages { + margin: 6px 0; + padding: 10px 10px 10px 50px; + /* LTR */ + background-position: 8px 8px; + /* LTR */ + background-repeat: no-repeat; + border: 1px solid; +} +.messages ul { + margin: 0 0 0 1em; + /* LTR */ + padding: 0; +} +.messages li { + list-style-image: none; +} + +/* Status Messages */ +.messages--status { + background-image: url('../../../images/misc/message-24-ok.png?1378983654'); + border-color: #be7; +} + +.messages--status, +tr.ok { + background-color: #f8fff0; +} + +.messages--status, +.ok { + color: #234600; +} + +/* Warning Messages */ +.messages--warning { + background-image: url('../../../images/misc/message-24-warning.png?1378983654'); + border-color: #ed5; +} + +.messages--warning, +tr.warning { + background-color: #fffce5; +} + +.messages--warning, +.warning { + color: #333; +} + +/* Error Messages */ +.messages--error { + background-image: url('../../../images/misc/message-24-error.png?1378983654'); + border-color: #ed541d; +} + +.messages--error, +tr.error { + background-color: #fef5f1; +} + +.messages--error, +.error { + color: #333; +} + +.error .error { + color: #8c2e0b; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/system/system.theme-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/system/system.theme-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,39 @@ +/** + * @file + * Right to left system wide theme styles. + */ +/** + * @file + * Basic right to left styling for common HTML elements. + */ +/* Tables */ +th { + padding-left: 1em; + padding-right: 0; + text-align: right; +} + +/** + * @file + * Right to left theme for collapsible fieldsets. + * + * @see collapse.js + */ +html.js fieldset.collapsible .fieldset-legend { + padding-left: 0; + padding-right: 15px; + background-position: 98% 75%; +} + +html.js fieldset.collapsed .fieldset-legend { + background-image: url('../../../images/misc/menu-collapsed-rtl.png?1378983654'); + background-position: 98% 50%; +} + +/** + * @file + * Right to left theme for the more link. + */ +.more-link { + text-align: left; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/system/system.theme.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/system/system.theme.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,239 @@ +/** + * @file + * System wide theme styles. + */ +/** + * @file + * Basic styling for common HTML elements. + */ +/* Fieldsets */ +fieldset { + margin-bottom: 1em; +} + +/* Tables */ +table { + border-collapse: collapse; +} + +th { + padding-right: 1em; + /* LTR */ + background-color: #bbb; + text-align: left; + /* LTR */ +} + +tr.even, +tr.odd { + background-color: #eee; +} + +tr.odd { + background-color: #ddd; +} + +/** + * @file + * Theme for autocomplete. + * + * @see autocomplete.js + */ +#autocomplete { + background: #fff; + border: 1px solid; + color: #000; +} +#autocomplete .selected { + background: #0072b9; + color: #fff; +} + +/** + * @file + * Theme for collapsible fieldsets. + * + * @see collapse.js + */ +html.js fieldset.collapsible .fieldset-legend { + padding-left: 15px; + /* LTR */ + background: url('../../../images/misc/menu-expanded.png?1378983654') 5px 65% no-repeat; + /* LTR */ +} + +html.js fieldset.collapsed { + border-bottom-width: 0; + border-left-width: 0; + border-right-width: 0; +} +html.js fieldset.collapsed .fieldset-legend { + background-image: url('../../../images/misc/menu-collapsed.png?1378983654'); + /* LTR */ + background-position: 5px 50%; + /* LTR */ +} + +.fieldset-legend .summary { + margin-left: 0.5em; + color: #999; + font-size: 0.9em; +} + +/** + * @file + * Theme for the tabledrag behavior. + * + * @see tabledrag.js + */ +.drag { + background-color: #fffff0; +} + +.drag-previous { + background-color: #ffd; +} + +/** + * @file + * Theme for the progress behavior. + * + * @see progress.js + */ +.progress { + font-weight: bold; +} +.progress .bar { + background: #ccc; + border-color: #666; + margin: 0 0.2em; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; +} +.progress .filled { + background: #0072b9 url('../../../images/misc/progress.gif?1378983654'); +} + +/** + * @file + * Theme for the tableselect behavior. + * + * @see tableselect.js +*/ +.selected td { + background: #ffc; +} + +.checkbox, +.checkbox { + text-align: center; +} + +/** + * @form + * Theme for markup generated by Form API. + */ +/* Generic Form Items. */ +.form-item, +.form-actions { + margin-bottom: 1em; +} +.form-item label, +.form-actions label { + display: block; + font-weight: bold; +} +.form-item .description, +.form-actions .description { + font-size: 0.85em; +} + +/* Checkboxes and Radios */ +.form-checkboxes .form-item, +.form-radios .form-item { + margin-bottom: 0.4em; +} +.form-checkboxes .description, +.form-radios .description { + margin-left: 2.4em; +} + +label.option { + display: inline; + font-weight: normal; +} + +.form-checkbox, +.form-radio { + vertical-align: middle; +} + +/* Errors */ +.marker, +.form-required { + color: #f00; +} + +input.error, +textarea.error, +select.error { + border: 2px solid red; +} + +/* Table Form Items */ +tr .form-item { + margin-top: 0; + margin-bottom: 0; + white-space: nowrap; +} + +/* Inline Items */ +.container-inline .form-actions, +.container-inline.form-actions { + margin-top: 0; + margin-bottom: 0; +} + +/** + * @file + * Theme for the markup generated by theme_tablesort_indicator(). + */ +th.active img { + display: inline; +} + +td.active { + background-color: #ddd; +} + +/** + * @file + * Theme for more links. + */ +.more-link { + display: block; + text-align: right; + /* LTR */ +} + +/** + * @file + * Theme for markup generated by theme_pager(). + */ +.pager { + clear: both; + padding: 0; + text-align: center; +} + +.pager__item { + display: inline; + padding: 0.5em; + background-image: none; + list-style-type: none; +} + +.pager__item--current { + font-weight: bold; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/taxonomy/taxonomy.admin.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/taxonomy/taxonomy.admin.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,11 @@ +/** + * @file + * Administrative styling for the taxonomy module. + */ +.taxonomy-term-divider-top { + border-bottom: none; +} + +.taxonomy-term-divider-bottom { + border-top: 1px dotted #CCC; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/user/user.admin-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/user/user.admin-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,23 @@ +/** + * @file + * Right to left administrative styling for the user module. + */ +/** + * User Permissions Page + */ +.user-admin-permissions .permission { + padding-left: 0; + padding-right: 1.5em; +} + +/** + * User Roles Page + * + * Override default textfield float to put the "Add role" button next to + * the input textfield. + */ +.user-admin-roles .form-item-name { + float: right; + margin-left: 1em; + margin-right: 0; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/user/user.admin.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/user/user.admin.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,33 @@ +/** + * @file + * Administrative styling for the user module. + */ +/** + * User Permissions Page + */ +.user-admin-permissions .module { + font-weight: bold; +} +.user-admin-permissions .permission { + padding-left: 1.5em; + /* LTR */ +} +.user-admin-permissions .form-item { + white-space: normal; +} + +/** + * User Roles Page + * + * Override default textfield float to put the "Add role" button next to + * the input textfield. + */ +.user-admin-roles .edit-name { + clear: both; +} +.user-admin-roles .form-item-name { + float: left; + /* LTR */ + margin-right: 1em; + /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/user/user.base-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/user/user.base-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,4 @@ +/** + * @file + * Right to left base styles for the user module. + */ diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/user/user.base.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/user/user.base.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,7 @@ +/** + * @file + * Base styles for the user module. + */ +div.password-confirm { + visibility: hidden; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/user/user.theme-rtl.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/user/user.theme-rtl.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,35 @@ +/** + * @file + * Right to left theme styling for the user module. + */ +/** + * Password Strength Indicator. + */ +.password-strength { + float: left; +} + +.password-strength-title { + float: right; +} + +.password-strength-text { + float: left; +} + +/** + * Password Confirm. + */ +.password-confirm { + float: left; +} + +/* + * User Profile + * + * Generated by user.module but used by profile.module. + */ +.profile .user-picture { + float: left; + margin: 0 0 1em 1em; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/modules/user/user.theme.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/modules/user/user.theme.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,95 @@ +/** + * @file + * Theme styling for the user module. + */ +/** + * Password Strength Indicator. + */ +.password-strength { + float: right; + /* LTR */ + margin-top: 1.2em; + width: 17em; +} + +.password-strength-title { + float: left; + /* LTR */ +} + +.password-strength-text { + float: right; + /* LTR */ + font-weight: bold; +} + +.password-indicator { + clear: both; + height: 0.3em; + width: 100%; + background-color: #C4C4C4; +} +.password-indicator .indicator { + height: 100%; + width: 0%; + background-color: #47C965; +} + +/** + * Password Confirm. + */ +div.password-confirm { + float: right; + /* LTR */ + clear: both; + width: 17em; + margin-top: 1.5em; +} + +/** + * Password Confirm Inputs. + */ +.form-type-password-confirm input { + width: 16em; +} + +/** + * Password Suggestions. + */ +.password-suggestions { + margin: 0.7em 0; + padding: 0.2em 0.5em; + border: 1px solid #B4B4B4; +} + +/* + * User Profile + */ +.user-profile-item__label { + font-weight: bold; +} + +/* Generated by user.module but used by profile.module. */ +.profile { + clear: both; + margin: 1em 0; +} +.profile .user-picture { + float: right; + /* LTR */ + margin: 0 1em 1em 0; + /* LTR */ +} +.profile h3 { + border-bottom: 1px solid #ccc; +} +.profile dl { + margin: 0 0 1.5em 0; +} +.profile dt { + margin: 0 0 0.2em 0; + font-weight: bold; +} +.profile dd { + margin: 0 0 1em 0; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/omega.admin.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/omega.admin.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,57 @@ +.form-item.form-item-omega-conditional-comments-html-options, +.form-item.form-item-omega-viewport-widget-minimal, +.omega-settings-container { + border: 1px solid #ccc; + margin-left: 18px; + margin-bottom: 12px; + padding: 9px 18px; + background-color: #f2f2f2; +} + +.fieldset-description { + margin-bottom: 15px; +} + +div.vertical-tabs .vertical-tabs-panes .vertical-tabs-pane fieldset { + border: 1px solid #CCC; + padding: 2.5em 0 0 0; + margin: 1em 0; +} +div.vertical-tabs .vertical-tabs-panes .vertical-tabs-pane fieldset legend { + display: block; +} + +.omega-assets-missing-files { + color: #8c2e0b; + margin: 1em 0 1em 1.5em; +} +.omega-assets-missing-files h3 { + font-size: .9em; + text-transform: uppercase; + margin-bottom: 0; +} + +.omega-layout-selection-wrapper { + margin-bottom: 20px; + min-height: 75px; + position: relative; +} +.omega-layout-selection-wrapper .form-item label.option, +.omega-layout-selection-wrapper .form-item div.description { + padding-left: 80px; +} +.omega-layout-selection-wrapper img { + height: 75px; + width: 64px; + position: absolute; + top: 8px; + margin-left: 1.5em; +} + +.form-item.form-item-omega-requirements { + border: 1px solid #ed541d; + color: #8c2e0b; + background-color: #fef5f1; + margin: 6px 0 16px; + padding: 10px; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/omega.development.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/omega.development.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,44 @@ +.omega-browser-width { + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + -ms-border-radius: 5px; + -o-border-radius: 5px; + border-radius: 5px; + background: url('../images/rgbapng/000000bf-5.png?1378988979'); + background: rgba(0, 0, 0, 0.75); + z-index: 1000; + position: fixed; + bottom: 0; + right: 0; + font-family: 'Lucida Grande', 'Lucida Sans Unicode', sans-serif; + font-size: 13px; + color: #fff; + max-width: 100%; + margin: 5px; + padding: 5px 10px; +} + +.region--debug { + background: url('../images/rgbapng/0000001a-5.png?1378988979'); + background: rgba(0, 0, 0, 0.1); + position: relative; + min-height: 29px; + outline: 1px dashed #ccc; +} +.region--debug:before { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + -ms-border-radius: 3px; + -o-border-radius: 3px; + border-radius: 3px; + background: url('../images/rgbapng/077dc3bf-5.png?1378988979'); + background: rgba(7, 125, 195, 0.75); + font-family: 'Lucida Grande', 'Lucida Sans Unicode', sans-serif; + font-size: 11px; + z-index: 50; + position: absolute; + right: 5px; + top: 5px; + padding: 3px 6px; + color: #fff; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/css/omega.messages.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/css/omega.messages.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,20 @@ +@charset "UTF-8"; +div.messages { + position: relative; +} + +.close-message { + text-shadow: none; + position: absolute; + right: .4em; + top: -.2em; + text-decoration: none; + color: rgba(0, 0, 0, 0.3); +} +.close-message:before { + font-size: 1.4em; + content: "×"; +} +.close-message:hover, .close-message:focus, .close-message:active { + color: #000; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/favicon.ico Binary file sites/all/themes/omega/omega/favicon.ico has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/layout-icon-placeholder.png Binary file sites/all/themes/omega/omega/images/layout-icon-placeholder.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/arrow-asc.png Binary file sites/all/themes/omega/omega/images/misc/arrow-asc.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/arrow-desc.png Binary file sites/all/themes/omega/omega/images/misc/arrow-desc.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/configure.png Binary file sites/all/themes/omega/omega/images/misc/configure.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/draggable.png Binary file sites/all/themes/omega/omega/images/misc/draggable.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/feed.png Binary file sites/all/themes/omega/omega/images/misc/feed.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/forum-icons.png Binary file sites/all/themes/omega/omega/images/misc/forum-icons.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/grippie.png Binary file sites/all/themes/omega/omega/images/misc/grippie.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/help.png Binary file sites/all/themes/omega/omega/images/misc/help.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/menu-collapsed-rtl.png Binary file sites/all/themes/omega/omega/images/misc/menu-collapsed-rtl.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/menu-collapsed.png Binary file sites/all/themes/omega/omega/images/misc/menu-collapsed.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/menu-expanded.png Binary file sites/all/themes/omega/omega/images/misc/menu-expanded.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/menu-leaf.png Binary file sites/all/themes/omega/omega/images/misc/menu-leaf.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/message-16-error.png Binary file sites/all/themes/omega/omega/images/misc/message-16-error.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/message-16-help.png Binary file sites/all/themes/omega/omega/images/misc/message-16-help.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/message-16-info.png Binary file sites/all/themes/omega/omega/images/misc/message-16-info.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/message-16-ok.png Binary file sites/all/themes/omega/omega/images/misc/message-16-ok.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/message-16-warning.png Binary file sites/all/themes/omega/omega/images/misc/message-16-warning.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/message-24-error.png Binary file sites/all/themes/omega/omega/images/misc/message-24-error.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/message-24-help.png Binary file sites/all/themes/omega/omega/images/misc/message-24-help.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/message-24-info.png Binary file sites/all/themes/omega/omega/images/misc/message-24-info.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/message-24-ok.png Binary file sites/all/themes/omega/omega/images/misc/message-24-ok.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/message-24-warning.png Binary file sites/all/themes/omega/omega/images/misc/message-24-warning.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/permissions.png Binary file sites/all/themes/omega/omega/images/misc/permissions.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/progress.gif Binary file sites/all/themes/omega/omega/images/misc/progress.gif has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/throbber.gif Binary file sites/all/themes/omega/omega/images/misc/throbber.gif has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/tree-bottom.png Binary file sites/all/themes/omega/omega/images/misc/tree-bottom.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/tree.png Binary file sites/all/themes/omega/omega/images/misc/tree.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/watchdog-error.png Binary file sites/all/themes/omega/omega/images/misc/watchdog-error.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/watchdog-ok.png Binary file sites/all/themes/omega/omega/images/misc/watchdog-ok.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/misc/watchdog-warning.png Binary file sites/all/themes/omega/omega/images/misc/watchdog-warning.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/modules/color/hook-rtl.png Binary file sites/all/themes/omega/omega/images/modules/color/hook-rtl.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/modules/color/hook.png Binary file sites/all/themes/omega/omega/images/modules/color/hook.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/modules/color/lock.png Binary file sites/all/themes/omega/omega/images/modules/color/lock.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/modules/contextual/gear-select.png Binary file sites/all/themes/omega/omega/images/modules/contextual/gear-select.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/modules/forum/forum-icons.png Binary file sites/all/themes/omega/omega/images/modules/forum/forum-icons.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/modules/openid/login-bg.png Binary file sites/all/themes/omega/omega/images/modules/openid/login-bg.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/rgbapng/0000001a-5.png Binary file sites/all/themes/omega/omega/images/rgbapng/0000001a-5.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/rgbapng/0000001a.png Binary file sites/all/themes/omega/omega/images/rgbapng/0000001a.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/rgbapng/000000bf-5.png Binary file sites/all/themes/omega/omega/images/rgbapng/000000bf-5.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/rgbapng/000000bf.png Binary file sites/all/themes/omega/omega/images/rgbapng/000000bf.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/rgbapng/077dc3bf-5.png Binary file sites/all/themes/omega/omega/images/rgbapng/077dc3bf-5.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/images/rgbapng/077dc3bf.png Binary file sites/all/themes/omega/omega/images/rgbapng/077dc3bf.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/includes/assets/assets.extension.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/includes/assets/assets.extension.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,3 @@ +name = Assets +description = There should be a description here. +enabled = TRUE diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/includes/assets/assets.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/includes/assets/assets.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,69 @@ + $info) { + if (!empty($settings[$library]['status'])) { + $registry['html']['libraries'][$library] = array( + 'attached' => array(), + 'settings' => $settings[$library], + 'callbacks' => isset($info['callbacks']) ? array_unique($info['callbacks']) : FALSE, + ); + + if (isset($settings[$library]['variant']) && $variant = $settings[$library]['variant']) { + $registry['html']['libraries'][$library]['attached'] = $info['variants'][$variant]['files']; + } + else { + $registry['html']['libraries'][$library]['attached'] = $info['files']; + } + } + } + } + + if (!empty($registry['html']['libraries'])) { + $registry['html']['preprocess functions'][] = 'omega_extension_assets_attach_libraries'; + } +} + +/** + * Extension callback for attaching enabled libraries. + */ +function omega_extension_assets_attach_libraries(&$variables) { + $registry = theme_get_registry(); + + // Check if there are any enabled libraries. + $libraries = module_exists('devel_themer') ? $registry['html']['original']['libraries'] : $registry['html']['libraries']; + foreach ($libraries as $library => $info) { + drupal_process_attached(array('#attached' => $info['attached'])); + + if (!empty($info['callbacks'])) { + foreach ($info['callbacks'] as $callback) { + $callback($library, $info['settings']); + } + } + } +} + +/** + * Library callback for checking if CSS aggregation is enabled. + */ +function omega_extension_library_requirements_css_aggregation($library, $settings) { + if ((!variable_get('preprocess_css', FALSE) && (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update'))) { + if (user_access('administer site configuration') && flood_is_allowed('omega_' . $GLOBALS['theme'] . '_aggregation_required', 3, 3600, $library)) { + $libraries = omega_theme_libraries_info(); + $info = $libraries[$library]; + + // Tell the user that the library does not work without CSS aggregation. + flood_register_event('omega_' . $GLOBALS['theme'] . '_aggregation_required', 3600, $library); + drupal_set_message(t('The %library library requires aggregated CSS files to work properly. You can enable CSS aggregation in the performance settings.', array('!url' => url('admin/config/development/performance'), '%library' => $info['name'])), 'warning'); + } + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/includes/assets/assets.settings.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/includes/assets/assets.settings.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,244 @@ + 'textarea', + '#title' => t('Move JS files to the footer'), + '#description' => t("Enter one file per line. The '*' character is a wildcard. Each path is relative to a module, theme, profile, theme engine or the 'misc' folder."), + // The paths are stored in an array. + '#default_value' => implode("\n", (array) omega_theme_get_setting('omega_js_footer', array())), + ); + + $element['omega_css_exclude'] = array( + '#type' => 'textarea', + '#title' => t('Exclude CSS files'), + '#description' => t("Enter one file per line. The '*' character is a wildcard. Each path is relative to a module, theme, profile, theme engine or the 'misc' folder."), + // The paths are stored in an array. + '#default_value' => implode("\n", (array) omega_theme_get_setting('omega_css_exclude', array())), + ); + + $element['omega_js_exclude'] = array( + '#type' => 'textarea', + '#title' => t('Exclude JS files'), + '#description' => t("Enter one file per line. The '*' character is a wildcard. Each path is relative to a module, theme, profile, theme engine or the 'misc' folder."), + // The paths are stored in an array. + '#default_value' => implode("\n", (array) omega_theme_get_setting('omega_js_exclude', array())), + ); + + $element['omega_libraries'] = array( + '#type' => 'container', + '#tree' => TRUE, + ); + + $libraries = omega_theme_get_setting('omega_libraries', array()); + foreach (omega_theme_libraries_info() as $library => $info) { + $key = strtolower($info['package']); + if (!isset($element['omega_libraries'][$key])) { + $element['omega_libraries'][$key] = array( + '#type' => 'fieldset', + '#title' => t(filter_xss_admin(ucfirst($info['package']))), + ); + } + + $element['omega_libraries'][$key][$library]['status'] = array( + '#type' => 'checkbox', + '#title' => !isset($info['vendor']) ? $info['name'] : (isset($info['vendor url']) ? t('@library by @vendor', array('@library' => $info['name'], '!url' => $info['vendor url'], '@vendor' => $info['vendor'])) : t('@library by @vendor', array('@library' => $info['name'], '@vendor' => $info['vendor']))), + '#description' => $info['description'], + '#default_value' => !empty($libraries[$library]['status']), + '#parents' => array('omega_libraries', $library, 'status'), + ); + + if ($missing = omega_extension_assets_check_library($info)) { + foreach ($missing as &$file) { + $path = drupal_get_path('theme', $form_state['build_info']['args'][0]); + $file = strpos($file, $path) === 0 ? substr($file, strlen($path) + 1) : $file; + } + + $element['omega_libraries'][$key][$library]['missing'] = array( + '#theme' => 'item_list', + '#title' => t('Missing files'), + '#items' => $missing, + '#prefix' => '
    ', + '#suffix' => '
    ', + ); + } + + $options = array(); + // Some libraries might want to provide special options. + if (isset($info['options form']) && function_exists($info['options form'])) { + // If a library options form callback exists and actually returns some + // options for this library append conditionally show them underneath + // the library checkbox with #states. + $info['options form']($options, $form, $form_state, $library, $info); + } + + if (!empty($info['variants'])) { + $options['variant'] = array( + '#type' => 'radios', + '#title' => t('Variant'), + '#options' => array('_default' => t('Default')), + '#default_value' => !empty($libraries[$library]['variant']) ? $libraries[$library]['variant'] : '_default', + '#parents' => array('omega_libraries', $library, 'variant'), + '#weight' => -10, + ); + + $options['variant']['_default'] = array( + '#description' => t('The default variant generally is a minified version of the library and provides the optimal production solution in most cases.'), + ); + + foreach ($info['variants'] as $variant => $variant_info) { + $options['variant']['#options'][$variant] = $variant_info['name']; + + if (!empty($variant_info['description'])) { + $options['variant'][$variant] = array( + '#description' => $variant_info['description'], + ); + } + } + } + + if (!empty($options)) { + $element['omega_libraries'][$key][$library]['options'] = array( + '#type' => 'fieldset', + '#title' => t('Options'), + '#states' => array( + 'visible' => array( + ':input[name="omega_libraries[' . $library . '][status]"]' => array('checked' => TRUE), + ), + ), + '#parents' => array('omega_libraries', $library), + '#tree' => TRUE, + '#attributes' => array('class' => array('omega-settings-container')), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ) + $options; + } + } + + // We need a custom submit handler to store the CSS and JS paths as arrays. + $form['#submit'][] = 'omega_extension_assets_theme_settings_form_submit'; + + return $element; +} + +/** + * Theme settings form submit handler for handling the PIE selectors. + */ +function omega_library_pie_selectors_submit($form, &$form_state) { + $values = &$form_state['values']['omega_libraries']['css3pie']; + + // Generate a CSS file for the provided selectors if the inclusion method is + // set to 'pie.htc' or 'pie.php'. + $selectors = array(); + if (!empty($values['selectors'])) { + // Sanitize the selectors. + $selectors = array_map('trim', explode("\n", $values['selectors'])); + $selectors = array_unique($selectors); + } + + // Save the selectors as an array. + $parents = array('#parents' => array('omega_libraries', 'css3pie', 'selectors')); + form_set_value($parents, $selectors, $form_state); +} + +/** + * CSS3PIE Library options form callback. + */ +function omega_library_pie_options_form(&$element, &$form, $form_state, $library, $info) { + // Give the default variant a proper label. + $element['variant']['#options']['_default'] = t('HTML Component (default)'); + + // Pull the selectors from the theme settings. + $settings = omega_theme_get_setting('omega_libraries', array()); + + // The generated CSS file is stored in the public file system. + $theme = $form_state['build_info']['args'][0]; + $destination = file_create_url('public://omega/' . $theme); + + $element['selectors'] = array( + '#title' => t('Selectors'), + '#type' => 'textarea', + '#description' => t("You can use this textarea to define all the CSS rules that you want to apply the PIE behavior to. Define one CSS selector per line. The selectors submitted with this field get directly cached in a .css file (as well as a .js file) in the public file system. This file is then included on page load and triggers CSS3PIE.", array('!css' => $destination . '/pie-selectors.css', '!js' => $destination . '/pie-selectors.js')), + '#default_value' => !empty($settings['css3pie']['selectors']) ? implode("\n", $settings['css3pie']['selectors']) : '', + ); + + // We need to provide a submit handler to create a CSS file for the + // defined selectors and remove them from the theme settings array. + $form['#submit'][] = 'omega_library_pie_selectors_submit'; +} + +/** + * Form submit handler for the css theme settings extension. + */ +function omega_extension_assets_theme_settings_form_submit($form, &$form_state) { + $values = $form_state['values']; + + // Explode and trim the values for the exclusion rules. + foreach (array('omega_css_exclude', 'omega_js_exclude', 'omega_js_footer') as $item) { + $exclude = array_filter(array_map('trim', explode("\n", $values[$item]))); + form_set_value(array('#parents' => array($item)), $exclude, $form_state); + } + + // Cache the regex for the CSS and JS excludes (if any). + foreach (array('omega_css_exclude', 'omega_js_exclude') as $item) { + if ($value = $form_state['values'][$item]) { + $exclude = omega_generate_path_regex($value); + form_set_value(array('#parents' => array($item . '_regex')), $exclude, $form_state); + } + } + + if (!empty($form_state['values']['omega_libraries'])) { + $values = &$form_state['values']['omega_libraries']; + + foreach ($values as &$settings) { + if (isset($settings['variant']) && $settings['variant'] == '_default') { + // Unset the 'variant' option if it is the default option. + unset($settings['variant']); + } + } + } +} + +/** + * Checks a library for missing files. + * + * @param $info + * A library info array. + * + * @return array + * An array of missing files. + */ +function omega_extension_assets_check_library($info) { + $missing = array(); + foreach (array_filter($info['files']) as $files) { + foreach ($files as $file => $data) { + $file = is_array($data) ? $file : $data; + if (!is_file($file)) { + $missing[$file] = $file; + } + } + } + + if (!empty($info['variants'])) { + foreach ($info['variants'] as $variant) { + foreach (array_filter($variant['files']) as $files) { + foreach ($files as $file => $data) { + $file = is_array($data) ? $file : $data; + if (!is_file($file)) { + $missing[$file] = $file; + } + } + } + } + } + + return $missing; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/includes/compatibility/compatibility.extension.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/includes/compatibility/compatibility.extension.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,3 @@ +name = Compatibility +description = There should be a description here. +enabled = TRUE diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/includes/compatibility/compatibility.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/includes/compatibility/compatibility.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,178 @@ + $name) { + $path = drupal_get_path('theme', $theme); + + // Apple touch icons have to be in the root directory of the theme for + // them to be discoverable. + if ($files = file_scan_directory($path, $mask, array('recurse' => FALSE))) { + foreach ($files as $file) { + $matches = array(); + + // Run the filename through the regex once more picking up the + // sub-matches in order to find out the dimensions of the touch icon + // and whether it's preprocessed or not. + preg_match($mask, $file->filename, $matches); + + // Cache the array of apple touch icons. + $registry['html']['apple-touch-icon'][$file->uri] = array( + 'uri' => $file->uri, + 'precomposed' => !empty($matches[1]), + 'sizes' => !empty($matches[3]) ? $matches[3] : FALSE, + ); + } + + // Break out of the loop because we found at least one touch icon. + break; + } + } + } +} + +/** + * Implements hook_extension_EXTENSION_preproces_html(). + */ +function omega_extension_compatibility_preprocess_html(&$variables) { + // Add the 'HandheldFriendly' meta tag. + if (omega_theme_get_setting('omega_handheld_friendly', TRUE)) { + $meta = array( + '#tag' => 'meta', + '#attributes' => array('name' => 'HandheldFriendly', 'content' => 'true'), + ); + + drupal_add_html_head($meta, 'omega-handheld-friendly'); + } + + // Add a the 'MobileOptimized' meta tag. + if (omega_theme_get_setting('omega_mobile_optimized', TRUE)) { + $meta = array( + '#tag' => 'meta', + '#attributes' => array('name' => 'MobileOptimized', 'content' => 'width'), + ); + + drupal_add_html_head($meta, 'omega-mobile-optimized'); + } + + // Add the 'cleartype' meta tag. + if (omega_theme_get_setting('omega_cleartype', TRUE)) { + $meta = array( + '#tag' => 'meta', + '#attributes' => array('http-equiv' => 'cleartype', 'content' => 'on'), + ); + + drupal_add_html_head($meta, 'omega-cleartype'); + } + + // Add the 'viewport' meta tag. + if (omega_theme_get_setting('omega_viewport', TRUE)) { + $content = array('width=device-width'); + + // Add the 'initial-scale' property if configured. + if ($value = omega_theme_get_setting('omega_viewport_initial_scale')) { + $content[] = "initial-scale=$value"; + } + + // The minimum-scale and maximum-scale properties are ignored if + // user-scalable is set to 'no'. + if (omega_theme_get_setting('omega_viewport_user_scaleable', TRUE) === FALSE) { + $content[] = 'user-scalable=no'; + } + else { + // Set the minimum-scale and maximum-scale properties if specified. + foreach (array('minimum', 'maximum') as $type) { + if ($value = omega_theme_get_setting("omega_viewport_{$type}_scale")) { + $content[] = "$type-scale=$value"; + } + } + } + + $meta = array( + '#tag' => 'meta', + '#attributes' => array('name' => 'viewport', 'content' => implode(', ', $content)), + // The 'viewport' metatag should be rendered after the 'HandheldFriendly' + // metatag. + '#weight' => 10, + ); + + drupal_add_html_head($meta, 'omega-viewport'); + } + + // Add Apple touch icons. + if (omega_theme_get_setting('omega_apple_touch', TRUE)) { + $registry = theme_get_registry(FALSE); + + if (!empty($registry['html']['apple-touch-icon'])) { + // Iterate over the array of touch icons and attributes. + foreach($registry['html']['apple-touch-icon'] as $icon) { + $meta = array( + '#tag' => 'link', + '#attributes' => array( + 'rel' => 'apple-touch-icon' . (!empty($icon['precomposed']) ? '-precomposed' : ''), + 'href' => file_create_url($icon['uri']), + ), + ); + + if (!empty($icon['sizes'])) { + $meta['#attributes']['sizes'] = $icon['sizes']; + } + + // Add the touch icon to the head using a unique key. + $key = 'omega-touch-' . (!empty($icon['precomposed']) ? '-precomposed' : '') . (!empty($icon['sizes']) ? '-' . $icon['uri'] : ''); + drupal_add_html_head($meta, $key); + } + } + } + + // Send X-UA-Compatible HTTP header to force IE to use the most recent + // rendering engine or use Chrome's frame rendering engine if available. + if (omega_theme_get_setting('omega_chrome_edge', TRUE)) { + $supported = omega_theme_get_setting('omega_internet_explorer_support', FALSE); + + if (drupal_get_http_header('X-UA-Compatible') === NULL) { + // Only add the header if it hasn't been added before. + drupal_add_http_header('X-UA-Compatible', 'IE=edge,chrome=' . ($supported ? 'IE' . $supported : '1')); + } + + if (omega_theme_get_setting('omega_chrome_popup', FALSE)) { + // Automatically open the Google Chrome Frame installation iframe. + drupal_add_js('//ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js', array( + 'type' => 'external', + 'scope' => 'footer', + 'weight' => 1000, + 'browsers' => array( + 'IE' => !$supported ? TRUE : 'lte IE ' . $supported, + '!IE' => FALSE, + ), + )); + + drupal_add_js('window.attachEvent("onload",function(){CFInstall.check({mode:"overlay"});})', array( + 'type' => 'inline', + 'scope' => 'footer', + 'weight' => 1000, + 'browsers' => array( + 'IE' => !$supported ? TRUE : 'lte IE ' . $supported, + '!IE' => FALSE, + ), + )); + } + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/includes/compatibility/compatibility.settings.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/includes/compatibility/compatibility.settings.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,178 @@ + 'checkbox', + '#title' => t('Add conditional classes for Internet Explorer'), + '#description' => t('Adds conditional classes (for Internet Explorer) to the <html>.'), + '#default_value' => omega_theme_get_setting('omega_conditional_classes_html', TRUE), + ); + + $element['omega_metatags'] = array( + '#type' => 'fieldset', + '#title' => t('Metatags and HTTP headers'), + ); + + $element['omega_metatags']['omega_apple_touch'] = array( + '#type' => 'checkbox', + '#title' => t('Apple touch icons'), + '#description' => t('You can set an Apple Touch Icon for your website just like you can set a favorite icon.'), + '#default_value' => omega_theme_get_setting('omega_apple_touch', TRUE), + ); + + $element['omega_metatags']['omega_cleartype'] = array( + '#type' => 'checkbox', + '#title' => t('Cleartype support for Windows'), + '#description' => t('Mobile Internet Explorer allows us to activate ClearType technology for smoothing fonts for easy reading.'), + '#default_value' => omega_theme_get_setting('omega_cleartype', TRUE), + ); + + $element['omega_metatags']['omega_handheld_friendly'] = array( + '#type' => 'checkbox', + '#title' => t('Handheld friendly'), + '#description' => t('The HandheldFriendly meta-tag was used initially by older Palm and Blackberry models as well as browsers like AvantGo.'), + '#default_value' => omega_theme_get_setting('omega_handheld_friendly', TRUE), + ); + + $element['omega_metatags']['omega_mobile_optimized'] = array( + '#type' => 'checkbox', + '#title' => t('Mobile Optimized'), + '#description' => t('Microsoft introduced the MobileOptimized tag for the PocketPC.'), + '#default_value' => omega_theme_get_setting('omega_mobile_optimized', TRUE), + ); + + $element['omega_metatags']['omega_viewport'] = array( + '#type' => 'checkbox', + '#title' => t('Viewport'), + '#description' => t('This is more widely supported by modern smartphones, including but not limited to: iOS, Android, Palm Pre, Blackberry, Windows Phone 7.'), + '#default_value' => omega_theme_get_setting('omega_viewport', TRUE), + ); + + $element['omega_metatags']['viewport_settings'] = array( + '#type' => 'fieldset', + '#title' => t('Viewport settings'), + '#states' => array( + 'visible' => array( + ':input[name="omega_viewport"]' => array('checked' => TRUE), + ), + ), + ); + + $options = array('_none' => t('Default')); + foreach (range(0.1, 10, 0.1) as $value) { + // Format the value to display with one decimal. + $value = number_format($value, 1); + $options[(string) $value] = $value; + } + + $element['omega_metatags']['viewport_settings']['omega_viewport_initial_scale'] = array( + '#type' => 'select', + '#title' => t('Initial scale'), + '#default_value' => omega_theme_get_setting('omega_viewport_initial_scale', '_none'), + '#options' => $options, + '#description' => t('The initial scaling of the page. Has to be in the range of the minimum- and maximum scale options.'), + ); + + $element['omega_metatags']['viewport_settings']['omega_viewport_user_scaleable'] = array( + '#type' => 'checkbox', + '#title' => t('User scalable'), + '#default_value' => omega_theme_get_setting('omega_viewport_user_scaleable', TRUE), + '#description' => t("Whether users are allowed to zoom in and out. Defaults to 'yes'. This is usually accomplished via multi-touch gestures on iOS and Android devices. You should only disallow zooming (uncheck this checkbox) if your mobile theme is very customized and presented with good typography and graphics for a reduced mobile size."), + ); + + $element['omega_metatags']['viewport_settings']['scaling_settings'] = array( + '#type' => 'fieldset', + '#title' => t('Scaling settings'), + '#states' => array( + 'visible' => array( + ':input[name="omega_viewport_user_scaleable"]' => array('checked' => TRUE), + ), + ), + ); + + $element['omega_metatags']['viewport_settings']['scaling_settings']['omega_viewport_minimum_scale'] = array( + '#type' => 'select', + '#title' => t('Minimum scale'), + '#default_value' => omega_theme_get_setting('omega_viewport_minimum_scale', '_none'), + '#options' => $options, + '#description' => t('The minimum allowed scaling of the site.'), + ); + + $element['omega_metatags']['viewport_settings']['scaling_settings']['omega_viewport_maximum_scale'] = array( + '#type' => 'select', + '#title' => t('Maximum scale'), + '#default_value' => omega_theme_get_setting('omega_viewport_maximum_scale', '_none'), + '#options' => $options, + '#description' => t('The maximum allowed scaling of the site.'), + ); + + $element['omega_metatags']['omega_chrome_edge'] = array( + '#type' => 'checkbox', + '#title' => t('Enable Chrome Frame and Internet Explorer Edge support'), + '#description' => t('Google\'s Chrome Frame is an open source project for Internet Explorer 6, 7, 8, and 9 that allows those version of Internet Explorer to harness the power of Google Chrome\'s engine. Edge mode tells Internet Explorer to display content in the highest mode available. With Internet Explorer 9, this is equivalent to IE9 mode. If a (hypothetical) future release of Internet Explorer supported a higher compatibility mode, pages set to edge mode would appear in the highest mode supported by that version. Those same pages would still appear in IE9 mode when viewed with Internet Explorer 9.', array('!link' => 'https://www.youtube.com/watch?v=sjW0Bchdj-w&feature=player_embedded"')), + '#default_value' => omega_theme_get_setting('omega_chrome_edge', TRUE), + ); + + $element['omega_metatags']['chrome'] = array( + '#type' => 'fieldset', + '#title' => t('Google Chrome Frame settings'), + '#states' => array( + 'visible' => array( + 'input[name="omega_chrome_edge"]' => array('checked' => TRUE), + ), + ), + ); + + $element['omega_metatags']['chrome']['omega_internet_explorer_support'] = array( + '#type' => 'select', + '#title' => t('Minimum supported Internet Explorer version'), + '#description' => t('The minimum version number of Internet Explorer that you actively support. The Chrome Frame prompt will display for any version below this version number.'), + '#default_value' => omega_theme_get_setting('omega_internet_explorer_support'), + '#options' => array( + '_none' => t('No Internet Explorer support'), + '9' => t('Internet Explorer 10'), + '8' => t('Internet Explorer 9'), + '7' => t('Internet Explorer 8'), + '6' => t('Internet Explorer 7'), + ), + ); + + $element['omega_metatags']['chrome']['omega_chrome_popup'] = array( + '#type' => 'checkbox', + '#title' => t('Enable the Google Chrome Frame popup'), + '#description' => t('Opens a popup window upon page load through which users can install Google Chrome Frame.'), + '#default_value' => omega_theme_get_setting('omega_chrome_popup', FALSE), + ); + + $element['omega_metatags']['chrome']['omega_chrome_notice'] = array( + '#type' => 'checkbox', + '#title' => t('Display a warning for users that do not have Google Chrome Frame installed'), + '#description' => t('Renders a themeable message at the top of the page if a user does not have Google Chrome Frame installed.'), + '#default_value' => omega_theme_get_setting('omega_chrome_notice', FALSE), + ); + + $form['#submit'][] = 'omega_extension_compatibility_settings_form_submit'; + + return $element; +} + +/** + * Form submit callback for the compatibility extension. + */ +function omega_extension_compatibility_settings_form_submit($form, &$form_state) { + $values = &$form_state['values']; + + foreach (array('omega_internet_explorer_support', 'omega_viewport_initial_scale', 'omega_viewport_minimum_scale', 'omega_viewport_maximum_scale') as $item) { + if ($values[$item] === '_none') { + unset($values[$item]); + } + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/includes/development/development.extension.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/includes/development/development.extension.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,3 @@ +name = Development +description = There should be a description here. +enabled = TRUE diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/includes/development/development.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/includes/development/development.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,145 @@ += DRUPAL_BOOTSTRAP_DATABASE && $GLOBALS['theme'] === $GLOBALS['theme_key'] && ($GLOBALS['theme'] == 'omega' || (!empty($GLOBALS['base_theme_info']) && $GLOBALS['base_theme_info'][0]->name == 'omega'))) { + if (user_access('administer site configuration')) { + _omega_extension_development_boot(); + } +} + +/** + * Implements hook_extension_EXTENSION_registry_alter(). + */ +function omega_extension_development_theme_registry_alter(&$registry) { + if (omega_theme_get_setting('omega_demo_regions', TRUE) || omega_theme_get_setting('omega_livereload', TRUE) || omega_theme_get_setting('omega_browser_width_indicator', FALSE)) { + $registry['html']['preprocess functions'][] = 'omega_extension_development_preprocess_html'; + + if (omega_theme_get_setting('omega_demo_regions', TRUE)) { + $registry['region']['preprocess functions'][] = 'omega_extension_development_preprocess_region'; + } + } +} + +/** + * Implements hook_extension_EXTENSION_preproces_html(). + */ +function omega_extension_development_preprocess_html(&$variables) { + $path = drupal_get_path('theme', 'omega'); + + if (omega_theme_get_setting('omega_livereload', TRUE)) { + $port = omega_theme_get_setting('omega_livereload_port', '35729'); + $host = omega_theme_get_setting('omega_livereload_host', 'localhost'); + $script = omega_theme_get_setting('omega_livereload_script', "http://$host:$port/livereload.js"); + $parsed = parse_url($script); + + $query = array(); + if (!isset($parsed['port']) || $parsed['port'] != $port) { + // If no port is specified the livereload.js script will use the default + // port (35729). + $query['port'] = $port; + } + + if (!isset($parsed['host']) || $parsed['host'] != $host) { + // If no host is specified livereload.js will use the host that it is + // served from (e.g. if livereload.js is served from example.com it will + // try to connect to a livereload server on example.com. + $query['host'] = $host; + } + + // We need to add livereload.js as external script with an absolute path + // because otherwise Drupal core messes with the query string. + $script = empty($query) ? $script : $script . '?' . http_build_query($query); + drupal_add_js($script, array( + 'preprocess' => FALSE, + 'type' => 'external', + 'browsers' => array( + 'IE' => FALSE, + '!IE' => TRUE, + ), + )); + } + + if (omega_theme_get_setting('omega_browser_width_indicator', FALSE) || omega_theme_get_setting('omega_demo_regions', TRUE)) { + drupal_add_css($path . '/css/omega.development.css', array('group' => CSS_THEME, 'weight' => -10, 'every_page' => TRUE)); + + if (omega_theme_get_setting('omega_browser_width_indicator', FALSE)) { + if (!module_exists('overlay') || (!$mode = overlay_get_mode()) || $mode == 'parent') { + $variables['attributes_array']['class'][] = 'omega-browser-width-indicator'; + drupal_add_js($path . '/js/omega.indicator.min.js', array('group' => JS_THEME, 'weight' => -10, 'every_page' => TRUE)); + } + } + } +} + +/** + * Implements hook_extension_EXTENSION_preproces_region(). + */ +function omega_extension_development_preprocess_region(&$variables) { + if ($variables['debug'] = !empty($variables['elements']['#debug'])) { + $class = drupal_html_class('region--debug--' . $variables['region']); + drupal_add_css(".$class:before { content: \"{$variables['elements']['#name']}\"; }", array( + 'type' => 'inline', + 'group' => CSS_THEME, + 'weight' => 1000, + )); + + $variables['attributes_array']['class'][] = 'region--debug'; + $variables['attributes_array']['class'][] = $class; + } +} + +/** + * Helper function for bootstrap related tasks that need to run on every page. + */ +function _omega_extension_development_boot() { + // Managing debugging (flood) messages and a few development tasks. This also + // lives outside of any function declaration to make sure that the code is + // executed before any theme hooks. + if (variable_get('theme_' . $GLOBALS['theme'] . '_settings') && flood_is_allowed('omega_' . $GLOBALS['theme'] . '_theme_settings_warning', 3)) { + // Alert the user that the theme settings are served from a variable. + flood_register_event('omega_' . $GLOBALS['theme'] . '_theme_settings_warning'); + drupal_set_message(t('The settings for this theme are currently served from a variable. You might want to export them to your .info file.'), 'warning'); + } + + // Rebuild the theme registry / aggregates on every page load if the + // development extension is enabled and configured to do so. + if (omega_theme_get_setting('omega_rebuild_theme_registry', FALSE)) { + // Rebuild the theme data. + system_rebuild_theme_data(); + // Rebuild the theme registry. + drupal_theme_rebuild(); + + if (flood_is_allowed('omega_' . $GLOBALS['theme'] . '_rebuild_registry_warning', 3)) { + // Alert the user that the theme registry is being rebuilt on every + // request. + flood_register_event('omega_' . $GLOBALS['theme'] . '_rebuild_registry_warning'); + drupal_set_message(t('The theme registry is being rebuilt on every request. Remember to turn off this feature on production websites.', array("!url" => url('admin/appearance/settings/' . $GLOBALS['theme']))), 'warning'); + } + } + + if (omega_theme_get_setting('omega_rebuild_aggregates', FALSE) && variable_get('preprocess_css', FALSE) && (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update')) { + foreach (array('css', 'js') as $type) { + variable_del('drupal_' . $type . '_cache_files'); + + foreach (file_scan_directory('public://' . $type . '', '/.*/') as $file) { + // Delete files that are older than 20 seconds. + if (REQUEST_TIME - filemtime($file->uri) > 20) { + file_unmanaged_delete($file->uri); + } + }; + } + + if (flood_is_allowed('omega_' . $GLOBALS['theme'] . '_rebuild_aggregates_warning', 3)) { + // Alert the user that the theme registry is being rebuilt on every + // request. + flood_register_event('omega_' . $GLOBALS['theme'] . '_rebuild_aggregates_warning'); + drupal_set_message(t('The CSS and JS aggregates are being rebuilt on every request. Remember to turn off this feature on production websites.', array("!url" => url('admin/appearance/settings/' . $GLOBALS['theme']))), 'warning'); + } + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/includes/development/development.settings.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/includes/development/development.settings.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,126 @@ + 'checkbox', + '#title' => t('Rebuild the theme registry on every page load'), + '#description' => t('While creating new templates and theme overrides the theme registry needs to be rebuilt. Note: This has a high (negative) performance impact and has to be deactivated once your website goes into production.'), + '#default_value' => omega_theme_get_setting('omega_rebuild_theme_registry', FALSE), + ); + + $element['omega_rebuild_aggregates'] = array( + '#type' => 'checkbox', + '#title' => t('Rebuild CSS and JS aggregates on every page load'), + '#description' => t('This can be useful for debugging your CSS or JS with activated aggregation. Note: This has a high (negative) performance impact and has to be deactivated once your website goes into production.'), + '#default_value' => omega_theme_get_setting('omega_rebuild_aggregates', FALSE), + ); + + $element['omega_browser_width_indicator'] = array( + '#type' => 'checkbox', + '#title' => t('Browser width indicator'), + '#description' => t('Adds a small box at the bottom of the browser window that displays the current width of the browser window. This can be very useful when writing media queries for a responsive website.'), + '#default_value' => omega_theme_get_setting('omega_browser_width_indicator', FALSE), + ); + + $element['omega_livereload'] = array( + '#type' => 'checkbox', + '#title' => t('Enable LiveReload'), + '#description' => t('LiveReload monitors changes in the file system. As soon as you save a file, it is preprocessed as needed, + and the browser is refreshed. Even cooler, when you change a CSS file or an image, the browser is updated instantly without + reloading the page. After enabling this features livereload.js will + be added to your pages which will then communicate with your LiveReload server.'), + '#default_value' => omega_theme_get_setting('omega_livereload', TRUE), + ); + + $element['omega_livereload_settings'] = array( + '#type' => 'fieldset', + '#title' => t('LiveReload settings'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#states' => array( + 'visible' => array( + 'input[name="omega_livereload"]' => array('checked' => TRUE), + ), + ), + ); + + $host = omega_theme_get_setting('omega_livereload_host', 'localhost'); + $port = omega_theme_get_setting('omega_livereload_port', '35729'); + $element['omega_livereload_settings']['omega_livereload_script'] = array( + '#type' => 'textfield', + '#title' => t('Script URL'), + '#description' => t("The URL from which to load the script. When running LiveReload through Guard or Grunt the + script can be retrieved from wherever Guard or Grunt are running."), + '#default_value' => omega_theme_get_setting('omega_livereload_script', "http://$host:$port/livereload.js"), + '#size' => 10, + ); + + $element['omega_livereload_settings']['omega_livereload_host'] = array( + '#type' => 'textfield', + '#title' => t('Host'), + '#description' => t("The host at which the LiveReload server is running. Do not add any protocol prefixes (e.g. 'http://')."), + '#default_value' => $host, + '#size' => 30, + ); + + $element['omega_livereload_settings']['omega_livereload_port'] = array( + '#type' => 'textfield', + '#title' => t('Port'), + '#description' => t('The port through which the LiveReload server can be reached. By default livereload.js tries to connect + to port 35729 which is also the default for LiveReload server. Therefore, please only specify a custom port if the + LiveReload server is running on a different port.'), + '#default_value' => $port, + '#size' => 10, + ); + + $regions = system_region_list($GLOBALS['theme_key'], REGIONS_VISIBLE); + $regions = module_exists('dashboard') ? array_diff_key($regions, array_flip(dashboard_regions())) : $regions; + if ($regions) { + $element['omega_demo_regions'] = array( + '#type' => 'checkbox', + '#title' => t('Region demo mode'), + '#description' => t('Forces all regions to be rendered, regardless of whether they are empty or not places a label with their name on them.'), + '#default_value' => omega_theme_get_setting('omega_demo_regions', TRUE), + ); + + $element['omega_demo_regions_list'] = array( + '#type' => 'fieldset', + '#title' => t('Select demo regions'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#states' => array( + 'visible' => array( + 'input[name="omega_demo_regions"]' => array('checked' => TRUE), + ), + ), + ); + + $element['omega_demo_regions_list']['omega_demo_regions_list'] = array( + '#type' => 'checkboxes', + '#title' => t('Demo regions'), + '#options' => $regions, + '#default_value' => omega_theme_get_setting('omega_demo_regions_list', array_keys($regions)), + ); + } + + $form['#submit'][] = 'omega_extension_development_settings_form_submit'; + + return $element; +} + +/** + * Form submit handler for the theme settings form to clean up stale values. + */ +function omega_extension_development_settings_form_submit($form, &$form_state) { + if (empty($form_state['values']['omega_demo_regions'])) { + unset($form_state['values']['omega_demo_regions_list']); + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/includes/layouts/layouts.extension.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/includes/layouts/layouts.extension.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,3 @@ +name = Layouts +description = There should be a description here. +enabled = FALSE diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/includes/layouts/layouts.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/includes/layouts/layouts.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,23 @@ + 'radios', + '#options' => array(), + '#title' => t('Choose a layout'), + '#default_value' => omega_theme_get_setting('omega_layout', 'simple'), + ); + + foreach ($layouts as $layout => $info) { + $element['omega_layout']['#options'][$layout] = $info['info']['name']; + $element['omega_layout'][$layout]['#description'] = $info['info']['description']; + + if (isset($info['info']['preview'])) { + $icon = file_create_url($info['path'] . '/' . $info['info']['preview']); + $element['omega_layout'][$layout]['#prefix'] = '
    '; + $element['omega_layout'][$layout]['#suffix'] = '
    '; + } + } + } + + return $element; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/includes/omega.drush.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/includes/omega.drush.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,979 @@ + dt('Creates a Omega subtheme.'), + 'arguments' => array( + 'name' => dt('The name of your subtheme.'), + ), + 'options' => array( + 'destination' => dt('The destination of your subtheme. Defaults to "site:all" (sites/all/themes). May be one of "site:foo", "profile:bar" or "theme:baz" ("foo", "bar" and "baz" being the name of your site, profile or parent theme). May also have a third part for sub-pathing. For example, if using site:all:custom/cat, then the theme will be created in sites/all/themes/custom/cat/.'), + 'machine-name' => dt('The machine-readable name of your subtheme. This will be auto-generated from the human-readable name if omitted.'), + 'starterkit' => dt('The starterkit that your subtheme should use. Defaults to "default".'), + 'basetheme' => dt('Specifies a custom base theme. Defaults to "omega".'), + 'enable' => dt('Automatically enable the subtheme after creation.'), + 'set-default' => dt('Automatically enable the subtheme after creation and make it the default theme.'), + 'no-readme' => dt('Skips readme files when generating the subtheme.'), + 'no-libraries' => dt("Prevent execution of the theme's libraries.make file.") + ), + 'examples' => array( + 'drush omega-subtheme "My Theme"' => dt('Creates an Omega subtheme called "My Theme".'), + 'drush omega-subtheme "My Theme" --destination=site:example.com' => dt('Creates an Omega subtheme called "My Theme" in sites/example.com/themes.'), + 'drush omega-subtheme "My Theme" --basetheme=my_custom_basetheme' => dt('Uses the default starterkit from a custom basetheme to create an Omega subtheme called "My Theme" in sites/all/themes.'), + 'drush omega-subtheme "My Theme" --basetheme=my_custom_basetheme --starterkit=my_custom_starterkit' => dt('Uses the my_custom_starterkit from a custom basetheme to create an Omega subtheme called "My Theme" in sites/all/themes.'), + ), + 'aliases' => array('osub'), + ); + + $items['omega-wizard'] = array( + 'description' => dt('Guides you through a wizard for generating a subtheme.'), + 'aliases' => array('owiz'), + ); + + $items['omega-guard'] = array( + 'description' => dt('Runs guard for the given theme including Compass and LiveReload by default.'), + 'arguments' => array( + 'name' => dt('The name of your subtheme.'), + ), + 'options' => array( + 'screen' => dt('Run guard watch in a detached screen.'), + 'force-polling' => dt('Polling is required for making guard watch work with remote file systems e.g. in case of virtual environments where guard runs on the guest but the files are modified on the host.'), + 'latency' => dt("Sometimes it seems to be required to set a latency (e.g. 5) if working with --force-polling because otherwise file changes are detected twice. Hence, not setting a latency might affect your system performance."), + ), + 'aliases' => array('ogrd'), + ); + + $items['omega-export'] = array( + 'description' => dt('Exports the theme settings of a given theme from the database to the .info file.'), + 'arguments' => array( + 'theme' => dt('The machine-readable name of the theme to export the theme settings for.'), + ), + 'options' => array( + 'revert' => dt('Purges the theme settings from the database after exporting them to the .info file.'), + ), + 'examples' => array( + 'drush omega-export foo' => dt('Exports the theme settings of the "foo" theme to the "foo.info" file in that theme.'), + 'drush omega-export foo --revert' => dt('Purges the theme settings of the "foo" theme from the database after exporting them to the .info file.'), + ), + 'aliases' => array('oexp'), + ); + + $items['omega-revert'] = array( + 'description' => dt('Reverts the theme settings of a given theme by deleting them from the database.'), + 'arguments' => array( + 'theme' => dt('The machine-readable name of the theme to revert the theme settings for.'), + ), + 'options' => array( + 'all' => dt('Reverts the theme settings of all Omega sub-themes.'), + ), + 'examples' => array( + 'drush omega-revert foo' => dt('Reverts the theme settings of the "foo" theme.'), + ), + 'aliases' => array('orev'), + ); + + return $items; +} + +/** + * Implements hook_drush_help(). + */ +function omega_drush_help($section) { + switch ($section) { + case 'drush:omega-subtheme': + return dt('Generates a subtheme.'); + case 'drush:omega-wizard': + return dt('Guides you through a wizard for generating a subtheme.'); + case 'drush:omega-guard': + return dt('Runs guard for the given theme including Compass and LiveReload by default.'); + case 'drush:omega-export': + return dt('Exports the theme settings of a given theme.'); + case 'drush:omega-revert': + return dt('Reverts the theme settings of a given theme.'); + } +} + +/** + * Implements drush_hook_COMMAND_validate(). + */ +function drush_omega_subtheme_validate($name = NULL) { + if (!isset($name)) { + return drush_set_error('OMEGA_MISSING_ARGUMENT', dt("You didn't specify a name for the subtheme.")); + } + + // Rebuild the theme data so that we can safely check for the existence of + // themes by using the information provided by list_themes(). + system_rebuild_theme_data(); + + if ($machine_name = drush_get_option('machine-name')) { + // Validate the machine-readable name of the theme. + if (!is_string($machine_name)) { + return drush_set_error('OMEGA_THEME_NAME_INVALID', dt('The --machine-name option expects a string value.')); + } + + if (!preg_match('/^[a-z][a-z0-9_]*$/', $machine_name)) { + return drush_set_error('OMEGA_THEME_NAME_INVALID', dt('The machine name (@name) is invalid. It may only contain lowercase numbers, letters and underscores and must start with a letter.', array( + '@name' => $machine_name, + ))); + } + + $themes = list_themes(); + // Validate that the machine-readable name of the theme is unique. + if (isset($themes[$machine_name])) { + return drush_set_error('OMEGA_THEME_ALREADY_EXISTS', dt('A theme with the name @name already exists. The machine-readable name must be unique.', array( + '@name' => $machine_name, + ))); + } + } + + if ($destination = drush_get_option('destination')) { + // Check if the syntax of the destination is valid. + if (!is_string($destination) || !preg_match('/^(site|theme|profile)(:(.+?)){1,2}$/', $destination)) { + return drush_set_error('OMEGA_DESTINATION_INVALID', dt('The destination syntax (@destination) is invalid. Please use one of the following destination patterns (site, profile or theme): --destination="site:foo", --destination="profile:bar" or --destination="theme:baz".', array( + '@destination' => $destination, + ))); + } + + // Check if the provided destination exists. + if (!drush_omega_resolve_destination($destination)) { + list($type, $destination) = explode(':', $destination); + + return drush_set_error('OMEGA_DESTINATION_DOES_NOT_EXIST', dt('The given destination @destination of type @type does not exist. Did you misspell it?', array( + '@destination' => $destination, + '@type' => $type, + ))); + } + } + + if ($basetheme = drush_get_option('basetheme')) { + if (!is_string($basetheme)) { + return drush_set_error('OMEGA_BASETHEME_INVALID', dt('The --basetheme option expects a string value.')); + } + + // Check if the base theme exists. + if (!array_key_exists($basetheme, list_themes())) { + return drush_set_error('OMEGA_BASETHEME_DOES_NOT_EXIST', dt('The base theme @basetheme does not exist or is invalid.', array( + '@basetheme' => $basetheme, + ))); + } + + // Check if the base theme is an Omega theme. + if (!array_key_exists('omega', omega_theme_trail($basetheme))) { + return drush_set_error('OMEGA_BASETHEME_INVALID', dt('The base theme @basetheme does not exist or is invalid.', array( + '@basetheme' => $basetheme, + ))); + } + } + + if ($starterkit = drush_get_option('starterkit')) { + if (!is_string($starterkit)) { + return drush_set_error('OMEGA_STARTERKIT_INVALID', dt('The --starterkit option expects a string value.')); + } + + $basetheme = drush_get_option('basetheme', 'omega'); + + // Check if the starterkit exists. + if (!array_key_exists($starterkit, omega_discovery('starterkit', $basetheme))) { + $themes = list_themes(); + + return drush_set_error('OMEGA_STARTERKIT_DOES_NOT_EXIST', dt('There is no valid @basetheme theme starterkit with the name @starterkit. Did you forget to specify the correct basetheme?', array( + '@basetheme' => $themes[$basetheme]->info['name'], + '@starterkit' => $starterkit, + ))); + } + } +} + +/** + * Implements drush_hook_COMMAND(). + */ +function drush_omega_subtheme($name) { + // Try to generate a machine-readable name. If that fails, prompt for one. + if (!$machine_name = drush_get_option('machine-name', drush_omega_generate_theme_name($name))) { + drush_print(dt("Sorry, I couldn't generate a machine-readable name for @name. Please use the '--machine-name' option to specify it manually.", array( + '@name' => $name, + ))); + } + + $basetheme = drush_get_option('basetheme', 'omega'); + $starterkits = omega_discovery('starterkit', $basetheme); + $starterkit = drush_get_option('starterkit', 'basic'); + $starterkit = $starterkits[$starterkit]; + + // Check whether the destination path does not exist and bail out if it does + // so we don't delete any important data by accident. + $destination = drush_omega_resolve_destination(drush_get_option('destination', 'site:all')) . '/' . $machine_name; + if (file_exists($destination)) { + return drush_set_error('OMEGA_SUBTHEME_PATH', dt('The path @path already exists.', array('@path' => $destination))); + } + + // Create a temporary directory so we don't leave any stale files if an + // operation fails. + $temporary = drush_tempdir() . '/' . $name; + + // Try to copy the starterkit to the destination path of the new subtheme. + if (!drush_copy_dir($starterkit['path'], $temporary)) { + return drush_set_error('OMEGA_GENERATE_SUBTHEME', dt('Failed to generate subtheme.')); + } + + // Delete the .starterkit.inc file. + drush_delete_dir($temporary . '/' . basename($starterkit['file'])); + + // Put the name and description for the new subtheme in place. + $info = array( + 'name' => $name, + 'description' => 'Please provide a description for your theme.', + 'base theme' => $basetheme, + ) + $starterkit['info']; + + // Write to the new .info file. + $file = $temporary . '/' . $machine_name . '.info'; + if (!file_put_contents($file, drush_omega_compose_info_file($info))) { + return drush_set_error('OMEGA_GENERATE_SUBTHEME', dt('Failed to generate subtheme.')); + } + + // Optionally remove README.txt files. + if (drush_get_option('no-readme')) { + foreach (file_scan_directory($temporary, '/^README/') as $file) { + drush_delete_dir($file->uri); + } + } + + // Recursively rewrite the file names and contents of all the files that are + // now in the subtheme's directory to represent the human- and + // machine-readable names of the subtheme. + $search = array('/{{ THEME }}/', '/{{ THEMENAME }}/'); + $replace = array($machine_name, $name); + if (!drush_omega_rewrite_recursive($temporary, $search, $replace)) { + return drush_set_error('OMEGA_GENERATE_SUBTHEME', dt('Failed to generate subtheme.')); + } + + // Move the new subtheme to its destination. + if (!drush_op('drush_mkdir', dirname($destination)) || !drush_op('drush_move_dir', $temporary, $destination)) { + return drush_set_error('OMEGA_GENERATE_SUBTHEME', dt('Failed to generate subtheme.')); + } + + // Rebuild the theme caches so that we can do some final tasks. + drupal_theme_rebuild(); + system_rebuild_theme_data(); + + if (($default = drush_get_option('set-default')) || !drush_get_option('enable')) { + // Enable the subtheme. + drush_op('theme_enable', array($machine_name)); + + if ($default) { + // Make the newly created subtheme the default theme. + drush_op('variable_set', 'theme_default', $machine_name); + } + } + + // Execute the theme's libraries.make file unless disabled. + if (!drush_get_option('no-libraries') && is_file("$destination/libraries.make")) { + drush_op('chdir', $destination); + drush_invoke_process('@self', 'make', array('libraries.make'), array( + 'no-core' => TRUE, + 'contrib-destination' => '.', + 'yes' => TRUE, + )); + } + + drush_log(dt('You have successfully created the theme @theme (@name) in @path.', array( + '@theme' => $name, + '@name' => $machine_name, + '@path' => dirname($destination), + )), 'success'); +} + +/** + * Implements drush_hook_COMMAND(). + */ +function drush_omega_wizard() { + // Rebuild the theme data so that we can safely check for the existence of + // themes by using the information provided by list_themes(). + system_rebuild_theme_data(); + + // Prompt for a theme name. + $name = drush_prompt(dt('Please enter the name of the new sub-theme'), 'Omega Subtheme'); + + // Try to generate a machine-readable name. If that fails, prompt for one. + if (!$machine_name = drush_omega_generate_theme_name($name)) { + drush_print(dt("Sorry, I couldn't generate a machine-readable name for @name", array( + '@name' => $name, + ))); + } + // Prompt for a theme name using the automatically generated default if any. + drush_set_option('machine-name', drush_omega_require_valid_theme_name(dt('Please enter a machine-readable name for your new theme'), $machine_name)); + + // Prompt for a base theme. + if (!$basetheme = drush_omega_theme_choice(dt('Please choose a base theme for your new theme'))) { + return; + } + drush_set_option('basetheme', $basetheme); + + // Let the user choose a starterkit. + if (!$starterkit = drush_omega_starterkit_choice($basetheme, dt('Please choose a starterkit for your new theme'))) { + return; + } + drush_set_option('starterkit', $starterkit); + + // Let the user choose a destination. + if (!$destination = drush_omega_destination_choice(dt('Please choose a destination. This is where your sub-theme will be placed'))) { + return; + } + drush_set_option('destination', $destination); + + // Optionally skip readme files when generating the subtheme. + drush_set_option('no-readme', !drush_confirm(dt("Do you want to keep the starterkit's readme files?"))); + + // Finally, let the user choose to directly enable the subtheme. + if ($enable = drush_confirm(dt('Do you want to enable your new theme?'))) { + drush_set_option('set-default', drush_confirm(dt('Do you want to make your new theme the default theme?'))); + } + drush_set_option('enable', $enable); + + drush_invoke('omega-subtheme', $name); +} + +/** + * Implements drush_hook_COMMAND_validate(). + */ +function drush_omega_export_validate($theme = NULL) { + return drush_omega_validate_theme($theme); +} + +/** + * Implements drush_hook_COMMAND(). + * + * Exports the theme settings for the given theme from the database and writes + * them into the .info file of that theme. + * + * @param $theme + * (optional) The machine-readable name of a theme. + * @return bool + * TRUE on success, FALSE on failure. + */ +function drush_omega_export($theme = NULL) { + if (!isset($theme) && !$theme = drush_omega_theme_choice(dt('Which theme do you want to export the theme settings for?'))) { + return; + } + + $themes = list_themes(); + + // Insert the theme settings from the database. + if (!$settings = variable_get('theme_' . $theme . '_settings')) { + if (!drush_confirm(dt('There are no theme settings for @theme stored in the database. Do you want to purge the theme settings from the .info file too?', array('@theme' => $themes[$theme]->info['name'])))) { + return; + } + } + + // Parse the current content of the .info file so we can append the settings + // from the database. + $path = drupal_get_path('theme', $theme) . '/' . $theme . '.info'; + $data = file_get_contents($path); + + // Remove the old theme settings from the .info file. + $data = trim(preg_replace('/^settings\[.*\].*\n?/mi', '', $data)); + + // Append the exported theme settings to the .info file if there are any. + $data = $settings ? $data . "\n\n" . drush_omega_compose_info_file($settings, 'settings') : $data; + + // Write the data to the .info file of the theme. + if (drush_op('file_put_contents', $path, $data)) { + drush_log(dt('The theme settings for the @theme theme have been exported to the .info file of the theme.', array('@theme' => $themes[$theme]->info['name'])), 'success'); + + if (drush_get_option('revert')) { + // Revert the theme settings if the 'revert' option is set and they have + // been exported successfully. In this case, we invoke the API function + // through the drush command to display the messages. + drush_invoke_process('@self', 'omega-revert', array($theme)); + } + + return TRUE; + } + else { + // There was an error while exporting the theme settings. + return drush_set_error('OMEGA_EXPORT_ERROR', dt('An error occurred while trying to export the theme settings for the @theme theme.', array('@theme' => $themes[$theme]->info['name']))); + } +} + +/** + * Implements drush_hook_COMMAND_validate(). + */ +function drush_omega_revert_validate($theme = NULL) { + return drush_omega_validate_theme($theme); +} + +/** + * Implements drush_hook_COMMAND(). + * + * Delete the theme settings that have been stored in the database and thereby + * reverts them to the default settings from the .info file. + * + * @param $theme + * (optional) The machine-readable name of a theme. + */ +function drush_omega_revert($theme = NULL) { + if (drush_get_option('all')) { + // Get a list of all Omega sub-themes. + $themes = array(); + foreach (list_themes() as $key => $info) { + $trail = omega_theme_trail($key); + if (array_key_exists('omega', $trail)) { + $themes[$key] = $info->info['name']; + } + } + + // Get confirmation from user. + drush_print(dt('The settings for the following themes will be reverted: @themes', array('@themes' => implode(', ', $themes)))); + if (!drush_confirm(dt('Do you really want to continue?'))) { + return; + } + } + elseif (!isset($theme) && !$theme = drush_omega_theme_choice(dt('Which theme do you want to revert the theme settings for?'))) { + return; + } + + $info = list_themes(); + $themes = isset($themes) ? $themes : array($theme => $info[$theme]->info['name']); + foreach ($themes as $theme => $name) { + // Delete the theme settings variable for the given theme. + drush_op('variable_del', 'theme_' . $theme . '_settings'); + + // Clear the theme cache. + cache_clear_all('omega:' . $theme . ':', 'cache', TRUE); + } + + // Rebuild the theme data for good measure. + drupal_theme_rebuild(); + system_rebuild_theme_data(); + + drush_log(dt('You have successfully reverted the theme settings for these themes: @themes.', array('@themes' => implode(', ', $themes))), 'success'); +} + +/** + * Implements drush_hook_COMMAND_validate(). + */ +function drush_omega_guard_validate($theme = NULL) { + return drush_omega_validate_theme($theme); +} + +/** + * Implements drush_hook_COMMAND(). + * + * Starts guard for the given theme for compass, theme registry rebuild and + * livereload. + * + * @param $theme + * (optional) The machine-readable name of a theme. + */ +function drush_omega_guard($theme = NULL) { + if (!isset($theme) && !$theme = drush_omega_theme_choice(dt('Which theme do you want to run Guard for?'))) { + return; + } + + // Check if Ruby is installed. + drush_shell_exec('ruby --version'); + $output = reset(drush_shell_exec_output()); + $matches = array(); + if (!preg_match('/^ruby ([0-9][0-9\.]*)/', $output, $matches)) { + // Ruby was not found on this machine. + return drush_set_error(dt('You have to install Ruby version 1.9 or newer.')); + } + elseif (!version_compare($matches[1], '1.8', '>=')) { + // Ruby is outdated. + return drush_set_error(dt('The installed version of Ruby (@version) is outdated. Please upgrade to version 1.9 or newer.', array( + '@version' => $matches[1], + ))); + } + + // Check if Rubygems is installed. + drush_shell_exec('gem --version'); + $output = reset(drush_shell_exec_output()); + $matches = array(); + if (!preg_match('/^[0-9][0-9\.]*$/', $output, $matches)) { + // Rubygems was not found on this machine. + return drush_set_error(dt('You have to install Rubygems version 1.8 or newer.')); + } + elseif (!version_compare($matches[0], '1.8', '>=')) { + // Rubygems is outdated. + return drush_set_error(dt('The installed version of Rubygems (@version) is outdated. Please upgrade to version 1.8 or newer.', array( + '@version' => $matches[0], + ))); + } + + // Check if Bundler is installed. + drush_shell_exec('bundle --version'); + $output = reset(drush_shell_exec_output()); + $matches = array(); + if (!preg_match('/^Bundler version ([0-9][0-9\.]*)/', $output, $matches)) { + // Bundler was not found on this machine. + return drush_set_error(dt('You have to install Bundler version 1.2 or newer.')); + } + elseif (!version_compare($matches[1], '1.2', '>=')) { + // Bundler is outdated. + return drush_set_error(dt('The installed version of Bundler (@version) is outdated. Please upgrade to version 1.2 or newer.', array( + '@version' => $matches[1], + ))); + } + + // Retrieve the path to the theme. + $path = drupal_get_path('theme', $theme); + + // Output an error message if the gemfiles dependencies are not satisfied. + drush_shell_cd_and_exec(DRUPAL_ROOT . '/' . $path, 'bundle check --no-color'); + $output = drush_shell_exec_output(); + switch (reset($output)) { + case "The Gemfile's dependencies are satisfied": + // All is good, we can proceed. + break; + + case 'Could not locate Gemfile': + return drush_set_error(dt('There was no Gemfile at @path.', array( + '@path' => $path, + ))); + + case "Your Gemfile's dependencies could not be satisfied": + // @todo Add prompt for running 'bundle install'. + + default: + return drush_set_error(dt("There was a problem with your setup:\n!error", array( + '!error' => implode("\n", $output), + ))); + } + + // This is the command for running guard through bundler. + $command = 'bundle exec guard'; + if (drush_get_option('screen')) { + drush_shell_exec('screen --version'); + if (!preg_match('/^Screen version/', reset(drush_shell_exec_output()))) { + // Screen was not found on this machine. + return drush_set_error(dt("You have to install 'screen' before you can run 'omega-guard' in a detached screen.")); + } + + // Check if there is already a screen. Running multiple screens at the same + // time ultimately eats up too much performance. This way we ensure that + // you don't accidently run the same screen session multiple times. + drush_shell_exec('screen -list'); + foreach (drush_shell_exec_output() as $output) { + $output = trim($output); + $matches = array(); + if (preg_match('/^((\d+)\.omega:' . $theme . ':guard)/', $output, $matches)) { + $themes = list_themes(); + + // Make sure that we only got one screen for each theme at a time. + if (drush_confirm(dt("There is already a screen running for @theme. Do you want to restart it?", array('@theme' => $themes[$theme]->name)))) { + drush_shell_exec("screen -S $matches[2] -X quit"); + // We found an existing guard session and killed it. + break; + } + else { + // Fine, if the user does not want us to kill the session he has to do + // it manually. + return drush_set_error(dt("There is already a screen running for the @theme theme (@screen). You have to kill the runing screen with '@command' before you can start a new one.", array( + '@theme' => $themes[$theme]->name, + '@screen' => $matches[1], + '@command' => "screen -S $matches[2] -X quit", + ))); + } + } + }; + + // We want to run the command in a detached (-dmS) screen. + $command = "screen -dmS omega:$theme:guard $command"; + } + + // Polling is required for making guard watch work with remote file systems + // e.g. in case of virtual environments where guard runs on the guest but + // the files are modified on the host. + if (drush_get_option('force-polling')) { + $command .= ' --force-polling'; + } + + // Sometimes it seems to be required to set a latency (e.g. 5) if working with + // polling because otherwise the file changes are detected twice. Hence, + // not setting a latency might affect your system performance. If it doesn't + // simply don't worry about it. + if ($latency = drush_get_option('latency')) { + $command .= ' --latency ' . $latency; + } + + // Change the active directory to the theme folder and run the command there. + drush_op('chdir', DRUPAL_ROOT . '/' . drupal_get_path('theme', $theme)); + drush_shell_exec_interactive($command); +} + +/** + * Resolves the destination path for a subtheme. This can either be a profile + * theme folder, a sites theme folder or a theme. + * + * @param $destination + * A destination string, this can either be a site path ('site:foo'), a + * profile path ('profile:foo') or a theme path ('theme:foo'). + * + * @return string|bool + * The full path to the given destination, FALSE if the destination could not + * be resolved. + */ +function drush_omega_resolve_destination($destination) { + list($type, $destination, $custom) = explode(':', $destination); + + // Add a '/' to the custom path suffix. + $custom = $custom ? '/' . $custom : ''; + + switch($type) { + case 'site': + if (array_key_exists($destination, drush_omega_sites())) { + return 'sites/' . $destination . '/themes' . $custom; + } + break; + + case 'profile': + require_once DRUPAL_ROOT . '/includes/install.core.inc'; + if (array_key_exists($destination, install_find_profiles())) { + return 'profiles/' . $destination . '/themes' . $custom; + } + break; + + case 'theme': + if (array_key_exists($destination, list_themes())) { + return drupal_get_path('theme', $destination) . $custom; + } + break; + } +} + +/** + * Helper function for printing a list of available Omega themes. + * + * @param $message + * The message that should be displayed. + * + * @return bool|string + * The machine-readable name of the chosen theme or FALSE if the operation was + * cancelled. + */ +function drush_omega_theme_choice($message) { + $options = array(); + foreach (list_themes() as $key => $info) { + $trail = omega_theme_trail($key); + if (array_key_exists('omega', $trail)) { + $parent = count($trail) > 1 ? array_slice($trail, -2, 1) : FALSE; + $options[$key] = $info->info['name'] . ($parent ? ' (' . dt('Subtheme of @parent', array('@parent' => reset($parent))) . ')' : '') . ' - ' . strip_tags($info->info['description']); + } + } + return drush_choice($options, $message); +} + +/** + * Helper function for printing a list of available starterkits. + * + * @param $basetheme + * The machine-readable name of a basetheme. + * @param $message + * The message that should be displayed. + * + * @return bool|string + * The machine-readable name of the chosen starterkit or FALSE if the + * operation was cancelled. + */ +function drush_omega_starterkit_choice($basetheme, $message) { + $themes = list_themes(); + $options = array(); + foreach (omega_discovery('starterkit', $basetheme) as $key => $info) { + $options[$key] = dt('@name: !description (Provided by @provider)', array( + '@name' => $info['info']['name'], + '!description' => isset($info['info']['description']) ? $info['info']['description'] : dt('No description'), + '@provider' => $themes[$info['theme']]->info['name'], + )); + } + return drush_choice($options, $message); +} + +/** + * Helper function that asks for the desired destination of a subtheme. + * + * @param $message + * The message that should be displayed. + * + * @return bool|string + * The given destination using the pattern "type:destination" + * (e.g. "site:all") or FALSE if the operation was cancelled. + */ +function drush_omega_destination_choice($message) { + drush_print($message); + + // Let the user choose a destination. + $options = array( + 'site' => dt("Site (e.g. 'all' or 'example.com')"), + 'profile' => dt('Installation profile'), + 'theme' => dt('Parent theme'), + ); + + if (!$type = drush_choice($options, dt('Please choose a destination type.'))) { + return FALSE; + } + + switch ($type) { + case 'site': + if (!$destination = drush_choice(drush_omega_sites(), dt('Please choose a site.'))) { + return FALSE; + } + return 'site:' . $destination; + + case 'profile': + require_once DRUPAL_ROOT . '/includes/install.core.inc'; + + $options = array(); + foreach (install_find_profiles() as $profile) { + $info = drupal_parse_info_file(dirname($profile->uri) . '/' . $profile->name . '.info'); + $options[$profile->name] = $info['name']; + } + + if (!$destination = drush_choice($options, dt('Please choose an installation profile.'))) { + return FALSE; + } + return 'profile:' . $destination; + + case 'theme': + if (!$destination = drush_omega_theme_choice(dt('Please choose a theme.'))) { + return FALSE; + } + return 'theme:' . $destination; + + default: + return 'site:all'; + } +} + +/** + * Helper function that continuously prompts for a valid machine-readable name. + * + * @param $message + * The message that should be displayed. + * + * @return string + * A valid, unique machine-readable name. + */ +function drush_omega_require_valid_theme_name($message, $default = NULL) { + while (TRUE) { + // Keep prompting for a machine-name until we get an acceptable value. + $prompt = drush_prompt($message, $default); + + if (!preg_match('/^[a-z][a-z0-9_]*$/', $prompt)) { + drush_print('The machine-readable name is invalid. It may only contain lowercase numbers, letters and underscores and must start with a letter.'); + } + else { + $themes = list_themes(); + // Validate that the machine-readable name of the theme is unique. + if (isset($themes[$prompt])) { + drush_print(dt('A theme with the name @name already exists. The machine-readable name must be unique.', array( + '@name' => $prompt, + ))); + } + else { + // The given machine-readable name is valid. Let's proceed. + return $prompt; + } + } + } +} + +/** + * Recursively rewrites (and renames) all files in a given path. + * + * @param $path + * The path to rewrite all files in. + * @param $search + * The string(s) to look for when replacing the file names and contents. Can + * be an array or a string. + * @param $replace + * The string(s) to replace $search with. Can be an array or a string. + * + * @return bool + * TRUE if the operation succeeded, FALSE otherwise. + * + * @see omega_drush_replace_contents() + * @see str_replace() + */ +function drush_omega_rewrite_recursive($path, $search, $replace) { + if (!is_dir($path)) { + return drush_set_error('INVALID_PATH', dt('The given path @path is not a directory.', array( + '!path' => $path, + ))); + } + + // If the file actually is a directory, proceed with the recursion. + $directory = new DirectoryIterator($path); + foreach ($directory as $item) { + if ($item->isDot()) { + // Do not process '..' and '.'. + continue; + } + + // Retrieve the path of the current item. + $pathname = $item->getPathname(); + if ($item->isDir() && !drush_omega_rewrite_recursive($pathname, $search, $replace)) { + return FALSE; + } + elseif ($item->isFile()) { + // If it is a file, try to replace its contents. + $contents = file_get_contents($pathname); + if (($changed = preg_replace($search, $replace, $contents)) === NULL) { + return drush_set_error('REWRITE_FAILURE', dt('There was an error while trying to rewrite !path (!search to !replace)', array( + '!path' => $pathname, + '!search' => $search, + '!replace' => $replace, + ))); + } + + if ($contents !== $changed) { + file_put_contents($pathname, $changed); + } + } + + // Try to rename (move) the file if the name was changed. + $original = basename($pathname); + if (($renamed = preg_replace($search, $replace, $original)) === NULL) { + return drush_set_error('REWRITE_FAILURE', dt('There was an error while trying to rewrite !path (!search to !replace)', array( + '!path' => $path, + '!search' => $search, + '!replace' => $replace, + ))); + } + + // Move (rename) if the file or directory name was changed. + if ($original !== $renamed) { + $new = dirname($pathname) . "/$renamed"; + if (!drush_move_dir($pathname, $new, TRUE)) { + return FALSE; + }; + } + } + + return TRUE; +} + +/** + * Recursively builds an .info file structure from an array. + * + * @param $array + * The array to build the .info file from. + * @param $prefix + * (Optional) Used internally to forward the current prefix (level of nesting) + * for the keys. + * + * @return string + * A .info file string. + */ +function drush_omega_compose_info_file($array, $prefix = FALSE) { + $info = ''; + + foreach ($array as $key => $value) { + if (is_array($value)) { + // This is an array, let's proceed with the next level. + $info .= drush_omega_compose_info_file($value, (!$prefix ? $key : "{$prefix}[{$key}]")); + } + else { + // Escape all single quotes. + $value = str_replace("'", "\'", $value); + // Wrap the value in single quotes if it has any trailing or leading + // whitespace or it is an empty string from the start. + $value = $value === '' || trim($value) != $value ? "'" . $value . "'" : $value; + // If the key is numeric remove it entirely (simple brackets are enough in + // this case). + $key = is_numeric($key) ? '' : $key; + + $info .= $prefix ? ("{$prefix}[" . $key .']') : $key; + $info .= ' = ' . $value . "\n"; + } + } + + return $info; +} + +/** + * Retrieve an array of available sites. + * + * @return array + * An array that contains all the available sites in a multisite environment. + */ +function drush_omega_sites() { + $sites = array(); + // Look up the available sites by iterating over the contents of the sites + // directory. + $files = new DirectoryIterator(DRUPAL_ROOT . '/sites'); + foreach ($files as $file) { + // The sites/default folder is not a valid destination. + if ($file->isDir() && !$file->isDot() && $file->getFileName() != 'default') { + $name = $file->getFileName(); + $sites[$name] = $name; + } + } + return $sites; +} + +/** + * Helper function for generating a valid machine-readable name for a theme from + * any string. + * + * @param $string + * The string to generate the machine-readable name from. + * + * @return string + * The generated machine-readable name. + */ +function drush_omega_generate_theme_name($string) { + // Machine-readable names have to start with a lowercase letter. + $string = preg_replace('/^[^a-z]+/', '', strtolower($string)); + // Machine-readable names may only contain alphanumeric characters and + // underscores. + $string = preg_replace('/[^a-z0-9_]+/', '_', $string); + // Trim all trailing and leading underscores. + $string = trim($string, '_'); + + $themes = list_themes(); + if (isset($themes[$string])) { + $plain = $string; + $counter = 0; + + while (isset($themes[$string])) { + // Make sure that the machine-readable name of the theme is unique. + $string = $plain . '_' . $counter++; + } + } + + return $string; +} + +/** + * Helper function for validating a given theme. + */ +function drush_omega_validate_theme($theme = NULL) { + if (!isset($theme)) { + return; + } + + // Rebuild the theme data so that we can safely check for the existence of + // themes by using the information provided by list_themes(). + system_rebuild_theme_data(); + + $themes = list_themes(); + // Check if the given theme exists. + if (!isset($themes[$theme])) { + return drush_set_error('OMEGA_THEME_DOES_NOT_EXIST', dt('There is no theme with the name @theme.', array( + '@theme' => $theme, + ))); + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/includes/omega.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/includes/omega.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,697 @@ +base_themes)) { + $cache[$theme] = $GLOBALS['theme_info']->base_themes; + } + + $themes = list_themes(); + if (empty($cache[$theme]) && isset($themes[$theme]->info['base theme'])) { + $cache[$theme] = system_find_base_themes($themes, $theme); + } + + // Add our current subtheme ($key) to that array. + $cache[$theme][$theme] = $themes[$theme]->info['name']; + + return $cache[$theme]; +} + +/** + * Helper function for generating a regex from a list of paths. + * + * Generates a single regex from a list of file paths that can be used to match + * JS or CSS files using preg_grep() for example in hook_css_alter() or + * hook_js_alter(). The '*' (asterisk) character can be used as a wild-card. + * + * @param $paths + * An array of file paths. + * + * @return string + * The generated regex. + * + * @see hook_js_alter() + * @see hook_css_alter() + */ +function omega_generate_path_regex($paths) { + foreach ($paths as &$item) { + // The first segment (everything before the first slash) is the namespace. + // This rule only applies to local files... So if the namespace can not be + // mapped to a module, profile or theme engine we assume that the we are + // trying to target an external file. + list($namespace) = explode('/', $item); + + // Check if the namespace refers to a file residing in the 'misc' folder or + // if it is a global wildcard. + if ($namespace !== '*' && $namespace !== 'misc') { + // Otherwise, check if it refers to a theme, module, profile or theme + // engine. + foreach (array('theme', 'module', 'profile', 'theme_engine') as $type) { + // We can't use drupal_get_path() directly because that uses dirname() + // internally which returns '.' if no filename was found. + if ($filename = drupal_get_filename($type, $namespace)) { + $prefix = dirname($filename); + $item = substr_replace($item, $prefix, 0, strlen($namespace)); + break; + } + } + } + + // Escape any regex characters and turn asterisk wildcards into actual regex + // wildcards. + $item = preg_quote($item, '/'); + $item = str_replace('\*', '(.*)', $item); + } + + return '/^' . implode('|', $paths) . '$/'; +} + +/** + * Helper function for eliminating elements from an array using a simplified + * regex pattern. + * + * @param $elements + * The array of elements that should have some of its items removed. + * @param $regex + * A regex as generated by omega_generate_path_regex(). + */ +function omega_exclude_assets(&$elements, $regex) { + $mapping = omega_generate_asset_mapping($elements); + + // Finally, implode the array of items to exclude into a proper regex and + // invoke in on the array of files to be excluded. + $elements = array_diff_key($elements, preg_grep($regex, $mapping)); +} + +/** + * Helper function for generating a map of assets based on the data attribute. + * + * We can not rely on the array keys of the JS and CSS file arrays in Drupal + * because in case of inline JS or CSS (which uses numerical array keys) and due + * to potential overrides of the 'data' attribute which holds the actual, + * reliable path of the file. This function returns a single-level array of + * reliable JS/CSS file paths using the original array keys as keys. Elements of + * type 'inline' or 'setting' are ignored. + * + * @param $elements + * An array of JS or CSS files as given in hook_css_alter() or + * hook_js_alter(). + * + * @return array + * A map of file paths generated from $elements. + * + * @see hook_js_alter() + * @see hook_css_alter() + */ +function omega_generate_asset_mapping($elements) { + $mapping = array(); + foreach ($elements as $key => $item) { + if ($item['type'] == 'inline' || $item['type'] == 'setting') { + // Naturally, in-line CSS is not supported. + continue; + } + + // We need to build an array containing just the 'data' attribute because + // that's the actual path of the file. The array key of the elements can + // be something else if someone is sneaky enough to use drupal_add_js() or + // drupal_add_css() with a bogus first argument (normally, that is the + // path to the file) and then specify the actual path through the 'data' + // attribute in the $options array. + $mapping[$key] = $item['data']; + } + + return $mapping; +} + +/** + * Retrieves the array of enabled extensions for a theme. Extensions can be + * registered through the .info file. Each extension can define a theme settings + * form altering function named + * 'THEMENAME_extension_EXTENSION_theme_settings_form_alter()' through a file + * named 'THEME_ROOT/includes/EXTENSION/EXTENSION.settings.inc' to have it + * automatically included whenever the theme settings form is displayed. Each + * extension can also define a + * 'THEMENAME_extension_EXTENSION_theme_registry_alter()' function through a + * file named 'THEME_ROOT/includes/EXTENSION/EXTENSION.inc' to register custom + * hooks with the theme registry. + * + * @param $theme + * (Optional) The key (machine-readable name) of a theme. Defaults to the key + * of the current theme. + * + * @return array + * The theme info array of the passed or current theme. + * + * @see _system_default_theme_features() + * @see omega_extension_development_theme_settings_form_alter() + * @see omega_extension_development_theme_registry_alter() + */ +function omega_extensions($theme = NULL, $reset = FALSE) { + $theme = isset($theme) ? $theme : $GLOBALS['theme_key']; + + if (!$reset) { + if (($extensions = &drupal_static(__FUNCTION__)) && isset($extensions[$theme])) { + return $extensions[$theme]; + } + + if (($cache = cache_get('omega:' . $theme . ':extensions')) !== FALSE) { + return $extensions[$theme] = $cache->data; + } + } + + // Extensions can't be hidden. + $extensions[$theme] = omega_discovery('extension', $theme); + + foreach ($extensions[$theme] as $extension => &$info) { + // Make sure that the theme variable is never altered. + $context = $theme; + drupal_alter('omega_extension_info', $info, $context); + + // Determine if the extension is enabled. + $info['enabled'] = omega_theme_get_setting('omega_toggle_extension_' . $extension, !empty($info['info']['enabled'])); + + // Check if all dependencies are met. + $info['errors'] = FALSE; + if (!empty($info['info']['dependencies'])) { + foreach ($info['info']['dependencies'] as $dependency) { + $dependency = drupal_parse_dependency($dependency); + + if ((!$module = system_get_info('module', $dependency['name'])) || omega_check_incompatibility($dependency, $module['version'])) { + $info['errors'] = TRUE; + } + } + } + } + + // Write to the cache. + cache_set('omega:' . $theme . ':extensions', $extensions[$theme]); + + return $extensions[$theme]; +} + +/** + * Determines if an extension is enabled. + * + * @param $extension + * The machine-readable name of an extension. + * @param $theme + * (Optional) The key (machine-readable name) of a theme. Defaults to the key + * of the current theme. + * + * @return bool + * TRUE if the extension is enabled, FALSE otherwise. + */ +function omega_extension_enabled($extension, $theme = NULL) { + $theme = isset($theme) ? $theme : $GLOBALS['theme_key']; + if (($extensions = omega_extensions($theme)) && isset($extensions[$extension])) { + return empty($extensions[$extension]['errors']) && !empty($extensions[$extension]['enabled']) && variable_get('omega_toggle_extension_' . $extension, TRUE); + } +} + +/** + * Looks up the info array of all themes in the theme trail and retrieves a + * particular info array element. + */ +function omega_theme_trail_info($element, $merge = TRUE, $theme = NULL) { + $output = array(); + + // Loop over all themes in the theme trail and look up $element in the .info + // array. + foreach (omega_theme_trail($theme) as $key => $name) { + $info = omega_theme_info($key); + + // If $merge is TRUE we combine all the results of all themes in the theme + // trail. Otherwise we just return the first occurrence. + if (isset($info[$element]) && is_array($info[$element])) { + $output = array_merge($info[$element], $output); + + if (!$merge) { + return array('theme' => $key, 'info' => $output); + } + } + } + + return $output; +} + +/** + * Retrieves the full info array of a theme. + * + * @param $theme + * (Optional) The key (machine-readable name) of a theme. Defaults to the key + * of the current theme. + * + * @return array + * The theme info array of the passed or current theme. + */ +function omega_theme_info($theme = NULL) { + $theme = isset($theme) ? $theme : $GLOBALS['theme_key']; + + // If this is the current theme, just load the theme info from the globals. + // Note: The global 'theme_key' property is not reliable in this case because + // it gets overridden on theme settings pages. + if ($theme == $GLOBALS['theme']) { + return $GLOBALS['theme_info']->info; + } + + $themes = list_themes(); + return $themes[$theme]->info; +} + +/** + * Invoke a hook in all themes in the theme trail that implement it. + * + * @param $hook + * The name of the hook to invoke. + * @param $theme + * (Optional) The key (machine-readable name) of a theme. Defaults to the key + * of the current theme. + * @param ... + * Arguments to pass to the hook. + * + * @return array + * An array of return values of the hook implementations. If themes return + * arrays from their implementations, those are merged into one array. + * + * @see module_invoke_all() + */ +function omega_invoke_all($hook, $theme = NULL) { + $theme = isset($theme) ? $theme : $GLOBALS['theme_key']; + + $args = func_get_args(); + // Remove $hook from the arguments. + unset($args[0], $args[1]); + + $return = array(); + foreach (omega_theme_trail($theme) as $key => $name) { + $function = $key . '_' . $hook; + + if (function_exists($function)) { + $result = call_user_func_array($function, array_merge(array($theme), array_values($args))); + if (isset($result) && is_array($result)) { + // Append the 'theme' property to each array element. + foreach ($result as &$item) { + $item['theme'] = $key; + } + $return = array_merge_recursive($return, $result); + } + elseif (isset($result)) { + $return[] = $result; + } + } + } + return $return; +} + +/** + * Custom implementation of drupal_array_get_nested_value() that also supports + * objects instead of just arrays. + * + * @param $object + * The array or object from which to get the value. + * @param $parents + * An array of parent keys of the value, starting with the outermost key. + * @param $key_exists + * (optional) If given, an already defined variable that is altered by + * reference. + * + * @return mixed + * The requested nested value. Possibly NULL if the value is NULL or not all + * nested parent keys exist. $key_exists is altered by reference and is a + * Boolean that indicates whether all nested parent keys exist (TRUE) or not + * (FALSE). This allows to distinguish between the two possibilities when NULL + * is returned. + * + * @see drupal_array_get_nested_value() + */ +function omega_get_nested_value(&$object, array $parents, &$key_exists = NULL) { + $ref = &$object; + foreach ($parents as $parent) { + if (is_array($ref) && array_key_exists($parent, $ref)) { + $ref = &$ref[$parent]; + } + elseif (is_object($ref) && property_exists($ref, $parent)) { + $ref = &$ref->$parent; + } + else { + $key_exists = FALSE; + return NULL; + } + } + $key_exists = TRUE; + return $ref; +} + +/** + * Retrieves the info array for all available layouts. + * + * @return array + * An array of available layouts for the given theme. + */ +function omega_layouts_info() { + if (($layouts = &drupal_static(__FUNCTION__)) !== NULL) { + return $layouts; + } + + // Try to retrieve the layouts definitions from cache. + if (($cache = cache_get('omega:layouts')) !== FALSE) { + return $layouts = $cache->data; + } + + // Layouts do not have a specific theme scope. + $layouts = omega_discovery('layout', FALSE); + foreach ($layouts as $layout => &$info) { + $info['attached'] = array(); + $info['template'] = isset($info['info']['template']) ? $info['info']['template'] : $layout; + $root = drupal_get_path('theme', $info['theme']); + + if (isset($info['info']['stylesheets'])) { + foreach ($info['info']['stylesheets'] as $media => $files) { + foreach ($files as $key => $file) { + if (is_file($info['path'] . '/' . $file)) { + // First, check if the file exists in the layout's path. + $path = $info['path'] . '/' . $file; + } + elseif (is_file($root . '/' . $file)) { + // Otherwise, check if the file exists in the theme's path. + $path = $root . '/' . $file; + } + else { + // The specified file does not exist. + continue; + } + + $info['attached']['css']["$media:$key"] = array( + 'data' => $path, + 'media' => $media, + 'group' => CSS_THEME, + 'every_page' => TRUE, + 'weight' => -10, + ); + } + } + } + + // Look up possible CSS and JS file overrides. + if (isset($info['info']['scripts'])) { + foreach ($info['info']['scripts'] as $key => $file) { + if (is_file($info['path'] . '/' . $file)) { + // First, check if the file exists in the layout's path. + $path = $info['path'] . '/' . $file; + } + elseif (is_file($root . '/' . $file)) { + // Otherwise, check if the file exists in the theme's path. + $path = $root . '/' . $file; + } + else { + // The specified file does not exist. + continue; + } + + $info['attached']['js'][$key] = array( + 'data' => $path, + 'group' => JS_THEME, + 'every_page' => TRUE, + 'weight' => -10, + ); + } + } + } + + // Give modules and themes a chance to alter the layout info array. + drupal_alter('omega_layouts_info', $layouts); + + // Cache the layout definitions in the database. + cache_set('omega:layouts', $layouts); + + return $layouts; +} + +/** + * Retrieves the active layout for the current page. + * + * @return array|bool + * The info array for the active layout or FALSE if the current page does not + * use an alternative page layout. + */ +function omega_layout() { + if (($cache = &drupal_static(__FUNCTION__)) !== NULL) { + return $cache; + } + + // Load the default layout from the theme settings. + $layout = omega_theme_get_setting('omega_layout', 'simple'); + drupal_alter('omega_layout', $layout); + + $layouts = omega_layouts_info(); + $cache = isset($layouts[$layout]) ? $layouts[$layout] : FALSE; + + return $cache; +} + +/** + * Allow themes to easily define libraries. + * + * @param $theme + * (Optional) The key (machine-readable name) of a theme. Defaults to the key + * of the current theme. + * + * @return array + * An array of libraries defined by themes in the theme trail of the given + * theme. + */ +function omega_theme_libraries_info($theme = NULL) { + $theme = isset($theme) ? $theme : $GLOBALS['theme_key']; + + // Check if the libraries have already been statically cached. + if (($libraries = &drupal_static(__FUNCTION__)) && isset($libraries[$theme])) { + return $libraries[$theme]; + }; + + // Try to retrieve the library definitions from cache. + if (($cache = cache_get("omega:$theme:libraries")) !== FALSE) { + return $libraries[$theme] = $cache->data; + } + + // Retrieve the libraries by invoking the hook. + $libraries[$theme] = omega_invoke_all('omega_theme_libraries_info'); + + $context = $theme; + // Give modules and themes a chance to alter the libraries info array. + drupal_alter('omega_theme_libraries_info', $libraries[$theme], $context); + + // Cache the layout definitions in the database. + cache_set("omega:$theme:libraries", $libraries[$theme]); + + return $libraries[$theme]; +} + +/** + * Helper function for discovering layouts, extensions or other plugins of any + * sort in the theme trail. + * + * @param $type + * A theme extension type (e.g. layout or extension). + * @param $theme + * (Optional) The key (machine-readable name) of a theme. Defaults to the key + * of the current theme. + * + * @return array + * An array containing the discovered definitions. + */ +function omega_discovery($type, $theme = NULL) { + $theme = isset($theme) ? $theme : $GLOBALS['theme_key']; + + if (($discovery = &drupal_static(__FUNCTION__, array())) && isset($discovery[$theme][$type])) { + return $discovery[$theme][$type]; + } + + $discovery[$theme][$type] = array(); + + // Retrieve all themes from the theme trail of the given theme. + $themes = $theme === FALSE ? list_themes() : omega_theme_trail($theme); + + // Collect paths to all sub-themes grouped by base themes. These will be + // used for filtering. This allows base themes to have sub-themes in its + // folder hierarchy without affecting the base themes template discovery. + $paths = array(); + foreach ($themes as $key => $info) { + if (!empty($info->base_theme)) { + $paths[$info->base_theme][$key] = dirname($info->filename); + } + } + foreach ($paths as $basetheme => $subthemes) { + foreach ($subthemes as $subtheme => $path) { + if (isset($paths[$subtheme])) { + $paths[$basetheme] = array_merge($paths[$basetheme], $paths[$subtheme]); + } + } + } + + $strlen = strlen($type) + 1; + foreach ($themes as $key => $label) { + // Retrieve the array of paths that should be ignored for this theme. + $ignore = isset($paths[$key]) ? $paths[$key] : array(); + $path = drupal_get_path('theme', $key); + + // Support files without '.inc' extension for backwards compatibility. + foreach (file_scan_directory($path, '/\.' . $type . '(\.inc)?$/', array('key' => 'name')) as $name => $file) { + // Ignore sub-theme templates for the current theme. + if (strpos($file->uri, str_replace($ignore, '', $file->uri)) !== 0) { + continue; + } + + if (substr($name, -$strlen) === '.' . $type) { + $name = substr($name, 0, strlen($name) - $strlen); + } + + if ($info = drupal_parse_info_file($file->uri)) { + $discovery[$theme][$type][$name] = array( + 'name' => $name, + 'path' => dirname($file->uri), + 'file' => $file->uri, + 'info' => $info, + 'theme' => $key, + ); + } + } + } + + return $discovery[$theme][$type]; +} + +/** + * Checks whether a version is compatible with a given dependency. + * + * This is a wrapper for drupal_check_incompatibility() which strips the core + * version and any potential development version suffix from the given string. + * + * @param $dependency + * The parsed dependency structure from drupal_parse_dependency(). + * @param $current + * The version to check against (like 4.2). + * + * @return + * NULL if compatible, otherwise the original dependency version string that + * caused the incompatibility. + * + * @see drupal_check_incompatibility() + * @see drupal_parse_dependency() + */ +function omega_check_incompatibility($dependency, $current) { + // Remove the core version from the version string. + $current = preg_replace('/^' . DRUPAL_CORE_COMPATIBILITY . '-/', '', $current); + // Remove any potential development version suffixes from the string. + $current = preg_replace('/-dev$/', '', $current); + + return drupal_check_incompatibility($dependency, $current); +} + +/** + * Finds the first occurrence of a given file in the theme trail. + * + * @param $file + * The relative path to a file. + * @param $theme + * (Optional) The key (machine-readable name) of a theme. Defaults to the key + * of the current theme. + * + * @return string + * The path to the file. If the file does not exist at all, it will simply + * return the path of the file as it would be if it existed in the given theme + * directly. This ensures that the code that uses this function does not break + * if a file does not exist anywhere. + */ +function omega_theme_trail_file($file, $theme = NULL) { + $theme = isset($theme) ? $theme : $GLOBALS['theme_key']; + + // Iterate over all themes in the theme trail (starting with the active theme) + // and return the first match. + $current = NULL; + foreach (array_reverse(omega_theme_trail($theme)) as $name => $info) { + $current = drupal_get_path('theme', $name) . '/' . $file; + if (file_exists($current)) { + return $current; + } + } + + // The default (fallback) path is the path of the active theme, even if it + // does not actually have that file. + return drupal_get_path('theme', $theme) . '/' . $file; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/includes/registry.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/includes/registry.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,195 @@ +theme = $theme; + $this->trail = omega_theme_trail($theme); + $this->registry = &$registry; + } + + /** + * Discovers and registers (pre-)process hooks on behalf of a given theme. + * + * @param string $theme + * The name of the theme for which to register (pre-)process hooks. + */ + public function registerHooks($theme) { + foreach (array('process', 'preprocess') as $type) { + // Iterate over all preprocess/process files in the current theme. + foreach ($this->discoverFiles($theme, $type) as $item) { + $callback = "{$theme}_{$type}_{$item->hook}"; + + // If there is no hook with that name, continue. + if (!array_key_exists($item->hook, $this->registry)) { + continue; + } + + // Append the included (pre-)process hook to the array of functions. + $this->registry[$item->hook]["$type functions"][] = $callback; + + // By adding this file to the 'includes' array we make sure that it is + // available when the hook is executed. + $this->registry[$item->hook]['includes'][] = $item->uri; + } + } + } + + /** + * Discovers and registers theme functions on behalf of a given theme. + * + * @param string $theme + * The name of the theme for which to register (pre-)process hooks. + * @param array $trail + * The theme trail of the given theme. + */ + public function registerThemeFunctions($theme, $trail) { + // Recursively scan the folder for the current step for (pre-)process + // files and write them to the registry. + foreach ($this->discoverFiles($theme, 'theme') as $item) { + // Keep a copy of the hook name to accomodate for theme hook suggestions. + $base = $item->hook; + if (($separator = strpos($item->hook, '__')) !== FALSE) { + $base = substr($item->hook, 0, $separator); + } + + // If there is no hook with that name, continue. This does not apply to + // theme hook suggestions. + if (!array_key_exists($base, $this->registry)) { + continue; + } + + // Skip theme function overrides if they are already declared 'final'. + if (!empty($this->registry[$item->hook]['final'])) { + continue; + } + + // Name of the function (theme hook or theme function). + $callback = "{$theme}_{$item->hook}"; + + // Furthermore, we don't want to re-override sub-theme template file or + // theme function overrides with theme functions from include files + // defined in a lower-level base theme. Without this check this would + // happen because our alter hook runs after the template file and theme + // function discovery logic from Drupal core (theme engine). + if (in_array($this->registry[$item->hook]['type'], array('base_theme_engine', 'theme_engine'))) { + foreach (array_reverse(array_keys($this->trail)) as $key) { + // Do not look any further once we reach the current theme. + if ($key === $theme) { + break; + } + + // We need to check if the declaration of that function or template + // file lives further down the theme trail than the function we are + // currently looking at. + if ($this->registry[$item->hook]['theme path'] == drupal_get_path('theme', $key)) { + continue(2); + } + } + } + + // Check if this is a previously unknown theme hook suggestion. + if (!array_key_exists($item->hook, $this->registry) && $base !== $item->hook) { + $arg = isset($this->registry[$base]['variables']) ? 'variables' : 'render element'; + + $this->registry[$item->hook] = array( + $arg => $this->registry[$base][$arg], + 'base hook' => $base, + 'preprocess functions' => array(), + 'process functions' => array(), + ); + } + + $this->registry[$item->hook]['function'] = $callback; + $this->registry[$item->hook]['theme path'] = drupal_get_path('theme', $theme); + $this->registry[$item->hook]['type'] = $theme == $this->theme ? 'theme_engine' : 'base_theme_engine'; + + // By adding this file to the 'includes' array we make sure that it is + // available when the hook is executed. + $this->registry[$item->hook]['includes'][] = $item->uri; + } + } + + /** + * Overrides (pre-)process functions while maintaining execution order. + * + * Useful in cases where we want to take a completely different approach than + * what the original implementation does. In some cases this is much more + * practical than altering or undoing things that were added or changed in a + * previous hook. + * + * @param string $hook + * The name of the theme hook (e.g. 'html', 'page' or 'block'). + * @param string $original + * The name of the original function. + * @param string $override + * The name of the new function. + * @param string $type + * (Optional) The type of the hook ('process' or 'preprocess'). Defaults to + * 'process'. + */ + public function overrideHook($hook, $original, $override, $type = 'process') { + if (($index = array_search($original, $this->registry[$hook]["$type functions"], TRUE)) !== FALSE) { + array_splice($this->registry[$hook]["$type functions"], $index, 1, $override); + } + } + + /** + * Scans for files of a certain type in the given theme's path. + * + * @param string $theme + * The name of the theme scan. + * @param string $type + * The file type (e.g. 'preprocess', 'process', or 'theme') to scan for. + * + * @return array + * An array of file objects that matched the given type. + */ + protected function discoverFiles($theme, $type) { + $length = -(strlen($type) + 1); + + $path = drupal_get_path('theme', $theme); + // Only look for files that match the 'something.preprocess.inc' pattern. + $mask = '/.' . $type . '.inc$/'; + + // Recursively scan the folder for the current step for (pre-)process + // files and write them to the registry. + $files = file_scan_directory($path . '/' . $type, $mask); + foreach ($files as &$file) { + $file->hook = strtr(substr($file->name, 0, $length), '-', '_'); + }; + + return $files; + } + +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/includes/scripts.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/includes/scripts.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,411 @@ + $item) { + if ($item['scope'] == $scope) { + $items[$key] = $item; + } + } + + // Sort the JavaScript so that it appears in the correct order. + uasort($items, 'drupal_sort_css_js'); + + // In Drupal 8, there's a JS_SETTING group for making setting variables + // appear last after libraries have loaded. In Drupal 7, this is forced + // without that group. We do not use the $key => $item type of iteration, + // because PHP uses an internal array pointer for that, and we're modifying + // the array order inside the loop. + foreach (array_keys($items) as $key) { + if ($items[$key]['type'] == 'setting') { + $item = $items[$key]; + unset($items[$key]); + $items[$key] = $item; + } + } + + // There is no need for the ajax page state if there is no ajax js! + if (array_key_exists('misc/ajax.js', $items)) { + // Provide the page with information about the individual JavaScript files + // used, information not otherwise available when aggregation is enabled. + $setting['ajaxPageState']['js'] = array_fill_keys(array_keys($items), 1); + unset($setting['ajaxPageState']['js']['settings']); + drupal_add_js($setting, 'setting'); + + // If we're outputting the header scope, then this might be the final time + // that drupal_get_js() is running, so add the setting to this output as well + // as to the drupal_add_js() cache. If $items['settings'] doesn't exist, it's + // because drupal_get_js() was intentionally passed a $javascript argument + // stripped of settings, potentially in order to override how settings get + // output, so in this case, do not add the setting to this output. + if ($scope == 'header' && isset($items['settings'])) { + $items['settings']['data'][] = $setting; + } + } + + // Render the HTML needed to load the JavaScript. + $elements = array( + '#type' => 'scripts', + '#items' => $items, + ); + + return drupal_render($elements); +} + +/** + * Callback to add the elements needed for JavaScript tags to be rendered. + * + * This function evaluates the aggregation enabled/disabled condition on a group + * by group basis by testing whether an aggregate file has been made for the + * group rather than by testing the site-wide aggregation setting. This allows + * this function to work correctly even if modules have implemented custom + * logic for grouping and aggregating files. + * + * @param $elements + * A render array containing: + * - #items: The JavaScript items as returned by drupal_add_js() and + * altered by drupal_get_js(). + * - #group_callback: A function to call to group #items. Following + * this function, #aggregate_callback is called to aggregate items within + * the same group into a single file. + * - #aggregate_callback: A function to call to aggregate the items within + * the groups arranged by the #group_callback function. + * + * @return array + * A render array that will render to a string of JavaScript tags. + * + * @see drupal_get_js() + */ +function omega_pre_render_scripts($elements) { + // Group and aggregate the items. + if (isset($elements['#group_callback'])) { + $elements['#groups'] = $elements['#group_callback']($elements['#items']); + } + if (isset($elements['#aggregate_callback'])) { + $elements['#aggregate_callback']($elements['#groups']); + } + + // A dummy query-string is added to filenames, to gain control over + // browser-caching. The string changes on every update or full cache + // flush, forcing browsers to load a new copy of the files, as the + // URL changed. Files that should not be cached (see drupal_add_js()) + // get REQUEST_TIME as query-string instead, to enforce reload on every + // page request. + $default_query_string = variable_get('css_js_query_string', '0'); + + // For inline JavaScript to validate as XHTML, all JavaScript containing + // XHTML needs to be wrapped in CDATA. To make that backwards compatible + // with HTML 4, we need to comment out the CDATA-tag. + $embed_prefix = "\n\n"; + + // Since JavaScript may look for arguments in the URL and act on them, some + // third-party code might require the use of a different query string. + $js_version_string = variable_get('drupal_js_version_query_string', 'v='); + + // Defaults for each SCRIPT element. + $element_defaults = array( + '#type' => 'html_tag', + '#tag' => 'script', + '#value' => '', + '#attributes' => array( + 'type' => 'text/javascript', + ), + ); + + // Loop through each group. + foreach ($elements['#groups'] as $group) { + // If a group of files has been aggregated into a single file, + // $group['data'] contains the URI of the aggregate file. Add a single + // script element for this file. + if ($group['type'] == 'file' && isset($group['data'])) { + $element = $element_defaults; + $element['#attributes']['src'] = file_create_url($group['data']); + $element['#browsers'] = $group['browsers']; + $elements[] = $element; + } + // For non-file types, and non-aggregated files, add a script element per + // item. + else { + foreach ($group['items'] as $item) { + // Element properties that do not depend on item type. + $element = $element_defaults; + if (!empty($item['defer'])) { + $element['#attributes']['defer'] = 'defer'; + } + $element['#browsers'] = $item['browsers']; + + // Element properties that depend on item type. + switch ($item['type']) { + case 'setting': + $element['#value_prefix'] = $embed_prefix; + $element['#value'] = 'jQuery.extend(Drupal.settings, ' . drupal_json_encode(drupal_array_merge_deep_array($item['data'])) . ");"; + $element['#value_suffix'] = $embed_suffix; + break; + + case 'inline': + $element['#value_prefix'] = $embed_prefix; + $element['#value'] = $item['data']; + $element['#value_suffix'] = $embed_suffix; + break; + + case 'file': + $query_string = empty($item['version']) ? $default_query_string : $js_version_string . $item['version']; + $query_string_separator = (strpos($item['data'], '?') !== FALSE) ? '&' : '?'; + $element['#attributes']['src'] = file_create_url($item['data']) . $query_string_separator . ($item['cache'] ? $query_string : REQUEST_TIME); + break; + + case 'external': + $element['#attributes']['src'] = $item['data']; + break; + } + + $elements[] = $element; + } + } + } + + return $elements; +} + +/** + * Default callback to aggregate JavaScript files. + * + * Having the browser load fewer JavaScript files results in much faster page + * loads than when it loads many small files. This function aggregates files + * within the same group into a single file unless the site-wide setting to do + * so is disabled (commonly the case during site development). To optimize + * download, it also compresses the aggregate files by removing comments, + * whitespace, and other unnecessary content. + * + * @param $js_groups + * An array of JavaScript groups as returned by drupal_group_js(). For each + * group that is aggregated, this function sets the value of the group's + * 'data' key to the URI of the aggregate file. + * + * @see drupal_group_js() + * @see drupal_pre_render_scripts() + */ +function omega_aggregate_js(&$js_groups) { + // Only aggregate when the site is configured to do so, and not during an + // update. + if (variable_get('preprocess_js', FALSE) && (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update')) { + foreach ($js_groups as $key => $group) { + if ($group['type'] == 'file' && $group['preprocess']) { + $js_groups[$key]['data'] = omega_build_js_cache($group['items']); + } + } + } +} + +/** + * Aggregates JavaScript files into a cache file in the files directory. + * + * The file name for the JavaScript cache file is generated from the hash of + * the aggregated contents of the files in $files. This forces proxies and + * browsers to download new JavaScript when the JavaScript changes. + * + * The cache file name is retrieved on a page load via a lookup variable that + * contains an associative array. The array key is the hash of the names in + * $files while the value is the cache file name. The cache file is generated + * in two cases. First, if there is no file name value for the key, which will + * happen if a new file name has been added to $files or after the lookup + * variable is emptied to force a rebuild of the cache. Second, the cache file + * is generated if it is missing on disk. Old cache files are not deleted + * immediately when the lookup variable is emptied, but are deleted after a set + * period by drupal_delete_file_if_stale(). This ensures that files referenced + * by a cached page will still be available. + * + * @param $files + * An array of JavaScript files to aggregate and compress into one file. + * + * @return string|bool + * The URI of the cache file, or FALSE if the file could not be saved. + */ +function omega_build_js_cache($files) { + $contents = ''; + $uri = ''; + $map = variable_get('drupal_js_cache_files', array()); + // Create a new array so that only the file names are used to create the hash. + // This prevents new aggregates from being created unnecessarily. + $js_data = array(); + foreach ($files as $file) { + $js_data[] = $file['data']; + } + $key = hash('sha256', serialize($js_data)); + if (isset($map[$key])) { + $uri = $map[$key]; + } + + if (empty($uri) || !file_exists($uri)) { + // Build aggregate JS file. + foreach ($files as $path => $info) { + if ($info['preprocess']) { + // Append a ';' and a newline after each JS file to prevent them from running together. + $contents .= file_get_contents($info['data']) . ";\n"; + } + } + // Prefix filename to prevent blocking by firewalls which reject files + // starting with "ad*". + $filename = 'js_' . drupal_hash_base64($contents) . '.js'; + // Create the js/ within the files folder. + $jspath = 'public://js'; + $uri = $jspath . '/' . $filename; + // Create the JS file. + file_prepare_directory($jspath, FILE_CREATE_DIRECTORY); + if (!file_exists($uri) && !file_unmanaged_save_data($contents, $uri, FILE_EXISTS_REPLACE)) { + return FALSE; + } + // If JS gzip compression is enabled, clean URLs are enabled (which means + // that rewrite rules are working) and the zlib extension is available then + // create a gzipped version of this file. This file is served conditionally + // to browsers that accept gzip using .htaccess rules. + if (variable_get('js_gzip_compression', TRUE) && variable_get('clean_url', 0) && extension_loaded('zlib')) { + if (!file_exists($uri . '.gz') && !file_unmanaged_save_data(gzencode($contents, 9, FORCE_GZIP), $uri . '.gz', FILE_EXISTS_REPLACE)) { + return FALSE; + } + } + $map[$key] = $uri; + variable_set('drupal_js_cache_files', $map); + } + return $uri; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/js/jquery.matchmedia.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/js/jquery.matchmedia.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,54 @@ +(function ($, window) { + + 'use strict'; + + /** + * Check if the given media query currently applies. + * + * @param query + * The media query to check for. + * + * @deprecated + * Use window.matchMedia() instead. + */ + $.matchmedia = function (query) { + return window.matchMedia(query); + }; + + /** + * Special event for listening to media query changes. + * + * @deprecated + * Use window.matchMedia(query).addListener(callback) instead. + */ + var event = $.event.special.mediaquery = { + objects: {}, + + handler: function (handler) { + return function (mql) { + mql.applies = mql.matches; + handler.call(mql, mql); + }; + }, + + add: function (handleObj) { + event.objects[handleObj.guid] = window.matchMedia(handleObj.data); + event.objects[handleObj.guid].addListener(event.handler(handleObj.handler)); + }, + + remove: function (handleObj) { + event.objects[handleObj.guid].removeListener(event.handler(handleObj.handler)); + } + }; + + /** + * Event shortcut. + * + * @deprecated + * Use window.matchMedia(query).addListener(callback) instead. + */ + $.fn.mediaquery = function (query, callback) { + return $(this).bind('mediaquery', query, callback); + }; + +})(jQuery, window); diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/js/jquery.matchmedia.min.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/js/jquery.matchmedia.min.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1 @@ +!function($,window){"use strict";$.matchmedia=function(query){return window.matchMedia(query)};var event=$.event.special.mediaquery={objects:{},handler:function(handler){return function(mql){mql.applies=mql.matches;handler.call(mql,mql)}},add:function(handleObj){event.objects[handleObj.guid]=window.matchMedia(handleObj.data);event.objects[handleObj.guid].addListener(event.handler(handleObj.handler))},remove:function(handleObj){event.objects[handleObj.guid].removeListener(event.handler(handleObj.handler))}};$.fn.mediaquery=function(query,callback){return $(this).bind("mediaquery",query,callback)}}(jQuery,window); \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/js/jquery.resizeend.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/js/jquery.resizeend.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,43 @@ +(function ($) { + + 'use strict'; + + /** + * Container for the resizeend timeout. + */ + var resizeTimeout; + + /** + * Throttled resize event. Fires only once after the resize ended. + */ + var event = $.event.special.resizeend = { + setup: function () { + $(this).bind('resize', event.handler); + }, + + teardown: function () { + $(this).unbind('resize', event.handler); + }, + + handler: function (e) { + var context = this; + if (resizeTimeout) { + clearTimeout(resizeTimeout); + } + + resizeTimeout = setTimeout(function () { + // Set correct event type + e.type = 'resizeend'; + $.event.handle.apply(context); + }, 150); + } + }; + + /** + * Wrapper for the resizeend event. + */ + $.fn.resizeend = function (handler) { + return $(this).bind('resizeend', handler); + }; + +})(jQuery); diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/js/jquery.resizeend.min.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/js/jquery.resizeend.min.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1 @@ +!function($){"use strict";var resizeTimeout;var event=$.event.special.resizeend={setup:function(){$(this).bind("resize",event.handler)},teardown:function(){$(this).unbind("resize",event.handler)},handler:function(e){var context=this;if(resizeTimeout){clearTimeout(resizeTimeout)}resizeTimeout=setTimeout(function(){e.type="resizeend";$.event.handle.apply(context)},150)}};$.fn.resizeend=function(handler){return $(this).bind("resizeend",handler)}}(jQuery); \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/js/jquery.scrollable.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/js/jquery.scrollable.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,22 @@ +(function ($) { + + 'use strict'; + + /** + * Custom expression for filtering for scrollable elements. + */ + $.expr[':'].scrollable = function (elem) { + var scrollable = true; + // Backup the original scroll position. + var original = $(elem).scrollTop(); + + if (original === 0) { + $(elem).scrollTop(1); + scrollable = $(elem).scrollTop() === 1; + $(elem).scrollTop(0); + } + + return scrollable; + }; + +})(jQuery); diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/js/jquery.scrollable.min.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/js/jquery.scrollable.min.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1 @@ +!function($,window){"use strict";$.matchmedia=function(query){return window.matchMedia(query)};var event=$.event.special.mediaquery={objects:{},handler:function(handler){return function(mql){mql.applies=mql.matches;handler.call(mql,mql)}},add:function(handleObj){event.objects[handleObj.guid]=window.matchMedia(handleObj.data);event.objects[handleObj.guid].addListener(event.handler(handleObj.handler))},remove:function(handleObj){event.objects[handleObj.guid].removeListener(event.handler(handleObj.handler))}};$.fn.mediaquery=function(query,callback){return $(this).bind("mediaquery",query,callback)}}(jQuery,window); \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/js/omega.admin.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/js/omega.admin.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,41 @@ +(function ($) { + + 'use strict'; + + /** + * Allows administrators to click on the icon of a layout instead of having to + * target the radio button in order to select it. + */ + Drupal.behaviors.omegaThemeSettingsLayouts = { + attach: function (context) { + $('.form-item-omega-layout .omega-layout-icon', context).click(function () { + $(this).siblings('.form-item').find('input').click().change(); + }); + } + }; + + /** + * Provide a nice little summary for the vertical tab pane of each extension + * which indicates whether or not it is currently enabled. + */ + Drupal.behaviors.omegaExtensionSummary = { + attach: function (context) { + $('fieldset[id^=edit-].omega-extension', context).each(function () { + var extension = $(this).attr('id').substring(5); + var $fieldset = $(this); + var $checkbox = $fieldset.find('input[name="omega_toggle_extension_' + extension + '"]'); + + $fieldset.drupalSetSummary(function () { + if (!$checkbox.is(':checked')) { + return Drupal.t('This extension is currently disabled'); + } + }); + + $checkbox.change(function () { + $fieldset.trigger('summaryUpdated'); + }); + }); + } + }; + +})(jQuery); diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/js/omega.admin.min.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/js/omega.admin.min.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1 @@ +!function($){"use strict";Drupal.behaviors.omegaThemeSettingsLayouts={attach:function(context){$(".form-item-omega-layout .omega-layout-icon",context).click(function(){$(this).siblings(".form-item").find("input").click().change()})}};Drupal.behaviors.omegaExtensionSummary={attach:function(context){$("fieldset[id^=edit-].omega-extension",context).each(function(){var extension=$(this).attr("id").substring(5);var $fieldset=$(this);var $checkbox=$fieldset.find('input[name="omega_toggle_extension_'+extension+'"]');$fieldset.drupalSetSummary(function(){if(!$checkbox.is(":checked")){return Drupal.t("This extension is currently disabled")}});$checkbox.change(function(){$fieldset.trigger("summaryUpdated")})})}}}(jQuery); \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/js/omega.indicator.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/js/omega.indicator.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,21 @@ +(function ($) { + + 'use strict'; + + /** + * Renders a widget for displaying the current width of the browser. + */ + Drupal.behaviors.omegaBrowserWidth = { + attach: function (context) { + $('body', context).once('omega-browser-width', function () { + var $indicator = $('
    ').appendTo(this); + + // Bind to the window.resize event to continuously update the width. + $(window).bind('resize.omega-browser-width', function () { + $indicator.text($(this).width() + 'px'); + }).trigger('resize.omega-browser-width'); + }); + } + }; + +})(jQuery); diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/js/omega.indicator.min.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/js/omega.indicator.min.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1 @@ +!function($){"use strict";Drupal.behaviors.omegaBrowserWidth={attach:function(context){$("body",context).once("omega-browser-width",function(){var $indicator=$('
    ').appendTo(this);$(window).bind("resize.omega-browser-width",function(){$indicator.text($(this).width()+"px")}).trigger("resize.omega-browser-width")})}}}(jQuery); \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/js/omega.mediaqueries.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/js/omega.mediaqueries.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,43 @@ +(function ($, window, Drupal) { + + 'use strict'; + + /** + * Toggles media-query specific body classes. + * + * You can define new media queries to listen to by writing them into the + * Drupal.settings.omegaSettings.mediaQueries array. + */ + Drupal.behaviors.omegaMediaQueryClasses = { + handler: function (name, mql) { + if (mql.matches) { + $('body').removeClass(name + '-inactive').addClass(name + '-active'); + } + else { + $('body').removeClass(name + '-active').addClass(name + '-inactive'); + } + }, + + attach: function (context, settings) { + var behavior = this; + var omegaSettings = settings.omega || {}; + var mediaQueries = omegaSettings.mediaQueries || {}; + + $('body', context).once('omega-mediaqueries', function () { + $.each(mediaQueries, function (index, value) { + var mql = window.matchMedia(value); + + // Initially, check if the media query applies or not and add the + // corresponding class to the body. + behavior.handler(index, mql); + + // React to media query changes and toggle the class names. + mql.addListener(function (mql) { + behavior.handler(index, mql); + }); + }); + }); + } + }; + +})(jQuery, window, Drupal); diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/js/omega.mediaqueries.min.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/js/omega.mediaqueries.min.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1 @@ +!function($,window,Drupal){"use strict";Drupal.behaviors.omegaMediaQueryClasses={handler:function(name,mql){if(mql.matches){$("body").removeClass(name+"-inactive").addClass(name+"-active")}else{$("body").removeClass(name+"-active").addClass(name+"-inactive")}},attach:function(context,settings){var behavior=this;var omegaSettings=settings.omega||{};var mediaQueries=omegaSettings.mediaQueries||{};$("body",context).once("omega-mediaqueries",function(){$.each(mediaQueries,function(index,value){var mql=window.matchMedia(value);behavior.handler(index,mql);mql.addListener(function(mql){behavior.handler(index,mql)})})})}}}(jQuery,window,Drupal); \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/js/omega.messages.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/js/omega.messages.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,22 @@ +(function ($, Drupal) { + + 'use strict'; + + /** + * Adds a 'close' link on messages that allows them to be discarded. + */ + Drupal.behaviors.omegaCloseableMessages = { + attach: function (context) { + $('.messages', context).once('closeable-messages', function () { + $('').click(function () { + $(this).closest('.messages').fadeOut(function () { + $(this).remove(); + }); + + return false; + }).appendTo(this); + }); + } + }; + +})(jQuery, Drupal); diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/js/omega.messages.min.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/js/omega.messages.min.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1 @@ +!function($,Drupal){"use strict";Drupal.behaviors.omegaCloseableMessages={attach:function(context){$(".messages",context).once("closeable-messages",function(){$('').click(function(){$(this).closest(".messages").fadeOut(function(){$(this).remove()});return false}).appendTo(this)})}}}(jQuery,Drupal); \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/layouts/simple/preview.png Binary file sites/all/themes/omega/omega/layouts/simple/preview.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/layouts/simple/simple-layout.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/layouts/simple/simple-layout.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,54 @@ +
    + + +
    +
    + + + + + +

    + + + + + + + + + + +
    + + + +
    + +
    + +
    +
    diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/layouts/simple/simple.layout.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/layouts/simple/simple.layout.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,18 @@ +name = Simple +description = A simple 3 column layout demonstrating mobile first and Susy. +preview = preview.png +template = simple-layout + +; Regions +regions[branding] = Branding +regions[header] = Header +regions[navigation] = Navigation bar +regions[highlighted] = Highlighted +regions[help] = Help +regions[content] = Content +regions[sidebar_first] = First sidebar +regions[sidebar_second] = Second sidebar +regions[footer] = Footer + +; Stylesheets +stylesheets[all][] = css/layouts/simple/simple.layout.css diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/libraries.make --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/libraries.make Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,34 @@ +; ############################################################################## +; +; This is a Drush make file that will automatically download the front-end +; libraries used by Omega. Alternatively, you can use Bower (http://bower.io) to +; accomplish this. +; +; To run this file with 'drush make' you first have to navigate into the Omega +; theme directory. +; +; $ cd sites/all/themes/omega/omega +; +; Now you can invoke 'drush make' using the following command: +; +; $ drush make libraries.make --no-core --contrib-destination=. +; +; ############################################################################## + +core = 7.x +api = 2 + +libraries[selectivizr][download][type] = "file" +libraries[selectivizr][download][url] = "https://github.com/fubhy/selectivizr/archive/master.zip" + +libraries[html5shiv][download][type] = "file" +libraries[html5shiv][download][url] = "https://github.com/fubhy/html5shiv/archive/master.zip" + +libraries[respond][download][type] = "file" +libraries[respond][download][url] = "https://github.com/fubhy/respond/archive/master.zip" + +libraries[matchmedia][download][type] = "file" +libraries[matchmedia][download][url] = "https://github.com/fubhy/matchmedia/archive/master.zip" + +libraries[pie][download][type] = "file" +libraries[pie][download][url] = "https://github.com/fubhy/pie/archive/master.zip" diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/logo.png Binary file sites/all/themes/omega/omega/logo.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/omega.info --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/omega.info Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,28 @@ +name = Omega +description = A powerful HTML5 base theme framework utilizing tools like Sass, Compass, Grunt, Bower, Ruby Version Manager, Bundler and more. +screenshot = screenshot.png +engine = phptemplate +hidden = TRUE +core = 7.x + +; Regions +regions[branding] = Branding +regions[header] = Header +regions[navigation] = Navigation +regions[highlighted] = Highlighted +regions[help] = Help +regions[content] = Content +regions[sidebar_first] = First Sidebar +regions[sidebar_second] = Second Sidebar +regions[footer] = Footer + +; Plugins +plugins[panels][layouts] = panels/layouts +plugins[panels][styles] = panels/styles + +; Information added by drupal.org packaging script on 2013-09-12 +version = "7.x-4.0-rc1" +core = "7.x" +project = "omega" +datestamp = "1378993635" + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/package.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/package.json Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,15 @@ +{ + "name": "omega", + "version": "1.0.0", + "dependencies": {}, + "devDependencies": { + "grunt": "~0.4.0", + "grunt-contrib-watch": "~0.4.3", + "grunt-contrib-compass": "~0.2.0", + "grunt-contrib-jshint": "~0.1.1", + "grunt-contrib-uglify": "~0.2.0" + }, + "engines": { + "node": ">=0.8.0" + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/panels/layouts/omega/omega.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/panels/layouts/omega/omega.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,194 @@ + t('Omega'), + 'category' => t('Omega page layouts'), + 'description' => t('Omega page layouts to be used as Panels Everywhere site templates.'), + 'get child' => 'omega_panels_get_sublayout', + 'get children' => 'omega_panels_get_sublayouts', + 'theme' => 'omega_panels', + 'admin theme' => 'omega_panels_admin', + 'regions' => array(), + ); +} + +/** + * Callback to retrieve a single Omega layout. + */ +function omega_panels_get_sublayout($plugin, $layout, $sublayout) { + $layouts = omega_panels_get_sublayouts($plugin, $layout); + if (isset($layouts["$layout:$sublayout"])) { + return $layouts["$layout:$sublayout"]; + } +} + +/** + * Callback to retrieve all Omega layouts. + */ +function omega_panels_get_sublayouts($plugin, $layout) { + require_once drupal_get_path('theme', 'omega') . '/includes/omega.inc'; + $path = drupal_get_path('theme', 'omega'); + + $layouts = array(); + if ($items = omega_layouts_info('omega')) { + foreach ($items as $name => $info) { + // Compute the relative path to the actual layout. + $relative = _omega_relative_path("$path/panels/layouts/omega", $info['path']); + + $layouts["$layout:$name"] = array( + 'name' => "$layout:$name", + 'title' => $info['info']['name'], + 'layout' => $info, + ) + $plugin; + + // Panels calls the preview image 'icon'. + if (isset($info['info']['preview'])) { + $layouts["$layout:$name"]['icon'] = "$relative{$info['info']['preview']}"; + } + + // Layouts may provide 'admin css' files. + if (isset($info['info']['admin css'])) { + $layouts["$layout:$name"]['admin css'] = "$relative{$info['info']['admin css']}"; + } + + // Various optional elements from the .info file of the layout. + foreach (array('regions', 'category', 'description') as $key) { + if (isset($info['info'][$key])) { + $layouts["$layout:$name"][$key] = $info['info'][$key]; + } + } + } + } + return $layouts; +} + +/** + * Implements hook_preprocess_omega_panels_admin(). + */ +function template_preprocess_omega_panels_admin(&$variables) { + _omega_panels_layout_preprocess($variables); +} + +/** + * Theme function for rendering an Omega layout on the Panels admin UI. + */ +function theme_omega_panels_admin(&$variables) { + return _omega_panels_layout_theme($variables); +} + +/** + * Theme function for rendering an Omega layout. + */ +function theme_omega_panels(&$variables) { + return _omega_panels_layout_theme($variables); +} + +/** + * Implements hook_preprocess_omega_panels(). + */ +function template_preprocess_omega_panels(&$variables) { + _omega_panels_layout_preprocess($variables); + drupal_process_attached(array('#attached' => $variables['layout']['layout']['attached'])); +} + +/** + * Helper function for preprocessing an Omega layout in Panels. + */ +function _omega_panels_layout_preprocess(&$variables) { + // Place a reference to the 'content' array so that the variables are + // accessible through both, the default page.tpl.php accessor and the panels + // layout accessor. + $variables['page'] = &$variables['content']; + + // Provide some harmless default variables that would otherwise be added by + // template_preprocess_page(). + $variables['base_path'] = base_path(); + $variables['front_page'] = url(); + $variables['language'] = $GLOBALS['language']; + $variables['language']->dir = $GLOBALS['language']->direction ? 'rtl' : 'ltr'; + + // In order to not render any of these items we simply set them as an empty + // string. + $variables['feed_icons'] = ''; + $variables['logo'] = ''; + $variables['main_menu'] = ''; + $variables['secondary_menu'] = ''; + $variables['action_links'] = ''; + $variables['site_name'] = ''; + $variables['site_slogan'] = ''; + $variables['tabs'] = ''; + $variables['breadcrumb'] = ''; + $variables['title'] = ''; + $variables['messages'] = ''; +} + +/** + * Helper function for rendering an Omega layout in Panels. + */ +function _omega_panels_layout_theme(&$variables) { + // Clean up the theme hook suggestion so we don't end up in an infinite loop. + unset($variables['theme_hook_suggestion'], $variables['theme_hook_suggestions']); + + $hook = str_replace('-', '_', $variables['layout']['layout']['template']); + return theme($hook, $variables); +} + +/** + * Computes the relative path between two absolute paths. + * + * @param string $from + * An absolute path. + * @param string $to + * An absolute path. + * + * @return string + * The relative path between $from and $to. + */ +function _omega_relative_path($from, $to) { + // some compatibility fixes for Windows paths + $from = is_dir($from) ? rtrim($from, '\/') . '/' : $from; + $to = is_dir($to) ? rtrim($to, '\/') . '/' : $to; + $from = str_replace('\\', '/', $from); + $to = str_replace('\\', '/', $to); + $from = explode('/', $from); + $to = explode('/', $to); + $relative = $to; + + foreach ($from as $depth => $dir) { + // Find first non-matching directory. + if ($dir === $to[$depth]) { + // Ignore this directory. + array_shift($relative); + } + else { + // Get number of remaining dirs to $from. + $remaining = count($from) - $depth; + if ($remaining > 1) { + // Add traversals up to first matching directory. + $padding = (count($relative) + $remaining - 1) * -1; + $relative = array_pad($relative, $padding, '..'); + break; + } + else { + $padding[0] = './' . $relative[0]; + } + } + } + + return implode('/', $relative); +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/panels/styles/omega/omega.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/panels/styles/omega/omega.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,32 @@ + TRUE, + 'hook theme' => 'omega_panels_theme_registry_hack', + ); +} + +/** + * Slight hack to ensure that the Omega layouts are always properly registered. + * + * This is required so that they can be used in backend UIs that are not served + * with Omega based themes. + */ +function omega_panels_theme_registry_hack(&$theme, $data) { + // The theme files might not be loaded yet. + if (!function_exists('_omega_theme_layouts')) { + require_once drupal_get_path('theme', 'omega') . '/template.php'; + } + + // Register each layout. + $theme = array_merge($theme, _omega_theme_layouts()); +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/preprocess/block-admin-display-form.preprocess.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/preprocess/block-admin-display-form.preprocess.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,14 @@ + $title) { + drupal_add_tabledrag('blocks', 'match', 'sibling', 'block-region-select', 'block-region-' . $region, NULL, FALSE); + drupal_add_tabledrag('blocks', 'order', 'sibling', 'block-weight', 'block-weight-' . $region); + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/preprocess/block.preprocess.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/preprocess/block.preprocess.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,116 @@ +module); + $variables['attributes_array']['class'] = preg_replace('/^block-' . $css_module . '$/', 'block--' . $css_module, $variables['attributes_array']['class']); + $variables['attributes_array']['class'] = preg_replace('/^block-menu$/', 'block--menu', $variables['attributes_array']['class']); + + $variables['title_attributes_array']['class'][] = 'block__title'; + + $variables['content_attributes_array']['class'][] = 'block__content'; + + // Add template suggestions to appropriate blocks. + switch ($variables['block']->module) { + case 'system': + switch ($variables['block']->delta) { + case 'help': + case 'powered-by': + break; + + case 'main': + // Use a template with no wrapper for the page's main content. + $variables['theme_hook_suggestions'][] = 'block__minimal'; + break; + + default: + // Any other "system" block is a menu block and should use block--nav.tpl.php + $variables['theme_hook_suggestions'][] = 'block__nav'; + break; + } + break; + + case 'menu': + case 'menu_block': + // Use block--nav.tpl.php template. + $variables['theme_hook_suggestions'][] = 'block__nav'; + break; + } + + // Add Aria Roles via attributes. + switch ($variables['block']->module) { + case 'system': + switch ($variables['block']->delta) { + case 'main': + // Note: the "main" role goes in the page.tpl, not here. + break; + + case 'help': + case 'powered-by': + $variables['attributes_array']['role'] = 'complementary'; + break; + + default: + // Any other "system" block is a menu block. + $variables['attributes_array']['role'] = 'navigation'; + break; + } + break; + + case 'menu': + case 'menu_block': + case 'blog': + case 'book': + case 'comment': + case 'forum': + case 'shortcut': + case 'statistics': + $variables['attributes_array']['role'] = 'navigation'; + break; + + case 'search': + $variables['attributes_array']['role'] = 'search'; + break; + + case 'help': + case 'aggregator': + case 'locale': + case 'poll': + case 'profile': + $variables['attributes_array']['role'] = 'complementary'; + break; + + case 'node': + switch ($variables['block']->delta) { + case 'syndicate': + $variables['attributes_array']['role'] = 'complementary'; + break; + + case 'recent': + $variables['attributes_array']['role'] = 'navigation'; + break; + } + break; + + case 'user': + switch ($variables['block']->delta) { + case 'login': + $variables['attributes_array']['role'] = 'form'; + break; + + case 'new': + case 'online': + $variables['attributes_array']['role'] = 'complementary'; + break; + } + break; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/preprocess/comment-wrapper.preprocess.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/preprocess/comment-wrapper.preprocess.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,14 @@ + $comment)) : ''; + // Add a sub component class for the comment content. + $variables['content_attributes_array']['class'][] = 'comment__content'; + // Add a sub component class to the comment links. + $variables['content']['links']['#attributes']['class'][] = 'comment__links'; + // Change modifier classes to use BEM syntax. + $variables['classes_array'] = preg_replace('/^comment-new$/', 'comment--new', $variables['classes_array']); + $variables['classes_array'] = preg_replace('/^comment-by-viewer$/', 'comment--by-viewer', $variables['classes_array']); + $variables['classes_array'] = preg_replace('/^comment-by-node-author$/', 'comment--by-node-author', $variables['classes_array']); +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/preprocess/field.preprocess.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/preprocess/field.preprocess.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,10 @@ + 'profile', + 'href' => $variables['grddl_profile'], + )); + + // Serialize RDF Namespaces into an RDFa 1.1 prefix attribute. + if ($variables['rdf_namespaces']) { + $prefixes = array(); + foreach (explode("\n ", ltrim($variables['rdf_namespaces'])) as $namespace) { + // Remove xlmns: and ending quote and fix prefix formatting. + $prefixes[] = str_replace('="', ': ', substr($namespace, 6, -1)); + } + $variables['rdf_namespaces'] = ' prefix="' . implode(' ', $prefixes) . '"'; + } + + // Classes for body element. Allows advanced theming based on context + // (home page, node of certain type, etc.). + if (!$variables['is_front']) { + // Add unique class for each page. + $path = drupal_get_path_alias($_GET['q']); + // Add unique class for each section of the website. + list($section, ) = explode('/', $path, 2); + $arg = explode('/', $_GET['q']); + + if ($arg[0] == 'node' && isset($arg[1])) { + if ($arg[1] == 'add') { + $section = 'node-add'; + } + elseif (isset($arg[2]) && is_numeric($arg[1]) && ($arg[2] == 'edit' || $arg[2] == 'delete')) { + $section = 'node-' . $arg[2]; + } + } + + $variables['attributes_array']['class'][] = drupal_html_class('section-' . $section); + } + + // Add some styles in case the Omega theme is the active theme. + if ($GLOBALS['theme'] == 'omega') { + _omega_preprocess_html($variables); + } +} + +/** + * Helper function for loading theme assets in case 'Omega' is the active theme. + * + * @see omega_preprocess_html() + */ +function _omega_preprocess_html(&$variables) { + // @todo +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/preprocess/links.preprocess.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/preprocess/links.preprocess.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,13 @@ + $name) { + if (!isset($variables['page'][$region])) { + $variables['page'][$region] = array(); + } + } + + $original = system_region_list($GLOBALS['theme_key'], REGIONS_VISIBLE); + foreach (array_diff_key($original, $layout['info']['regions']) as $region => $name) { + unset($variables['page'][$region]); + } + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/preprocess/poll-results.preprocess.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/preprocess/poll-results.preprocess.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,14 @@ + 'links', + '#links' => $variables['raw_links'], + '#attributes' => array('class' => array('links', 'poll-results__links')), + ); +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/preprocess/region.preprocess.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/preprocess/region.preprocess.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,25 @@ +style_plugin->options; + $columns = $options['columns']; + foreach ($variables['rows'] as $delta => $row) { + $variables['row_attributes_array'][$delta] = isset($variables['row_attributes_array'][$delta]) ? $variables['row_attributes_array'][$delta] : array(); + + if (!empty($variables['row_classes'][$delta])) { + $variables['row_attributes_array'][$delta]['class'] = explode(' ', $variables['row_classes'][$delta]); + } + + // Views tables have additional classes for each column. + for ($column = 0; $column < $columns; $column++) { + $variables['column_attributes_array'][$delta][$column] = isset($variables['column_attributes_array'][$delta][$column]) ? $variables['column_attributes_array'][$delta][$column] : array(); + + if (!empty($variables['column_classes'][$delta][$column])) { + $variables['column_attributes_array'][$delta][$column]['class'] = explode(' ', $variables['column_classes'][$delta][$column]); + } + } + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/preprocess/views/views-view-list.preprocess.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/preprocess/views/views-view-list.preprocess.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,18 @@ + $row) { + $variables['row_attributes_array'][$delta] = isset($variables['row_attributes_array'][$delta]) ? $variables['row_attributes_array'][$delta] : array(); + + if (!empty($variables['classes_array'][$delta])) { + $variables['row_attributes_array'][$delta]['class'] = explode(' ', $variables['classes_array'][$delta]); + } + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/preprocess/views/views-view-table.preprocess.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/preprocess/views/views-view-table.preprocess.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,36 @@ + $row) { + $variables['row_attributes_array'][$delta] = isset($variables['row_attributes_array'][$delta]) ? $variables['row_attributes_array'][$delta] : array(); + + if (!empty($variables['row_classes'][$delta])) { + $variables['row_attributes_array'][$delta]['class'] = $variables['row_classes'][$delta]; + } + + // Views tables have additional classes for each table column. + foreach ($row as $field => $content) { + $variables['field_attributes_array'][$field][$delta] = isset($variables['field_attributes_array'][$field][$delta]) ? $variables['field_attributes_array'][$field][$delta] : array(); + + if (!empty($variables['field_classes'][$field][$delta])) { + $variables['field_attributes_array'][$field][$delta]['class'] = explode(' ', $variables['field_classes'][$field][$delta]); + } + } + } + + // Views tables have additional classes for each header column. + foreach ($variables['header'] as $field => $label) { + $variables['header_attributes_array'][$field] = isset($variables['header_attributes_array'][$field]) ? $variables['header_attributes_array'][$field] : array(); + + if (!empty($variables['header_classes'][$field])) { + $variables['header_attributes_array'][$field]['class'] = explode(' ', $variables['header_classes'][$field]); + } + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/preprocess/views/views-view-unformatted.preprocess.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/preprocess/views/views-view-unformatted.preprocess.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,18 @@ + $row) { + $variables['row_attributes_array'][$delta] = isset($variables['row_attributes_array'][$delta]) ? $variables['row_attributes_array'][$delta] : array(); + + if (!empty($variables['classes_array'][$delta])) { + $variables['row_attributes_array'][$delta]['class'] = explode(' ', $variables['classes_array'][$delta]); + } + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/process/block.process.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/process/block.process.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,9 @@ +subject. + $variables['title'] = $variables['block']->subject; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/process/comment-wrapper.process.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/process/comment-wrapper.process.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,9 @@ +style_plugin->options; + $columns = $options['columns']; + foreach ($variables['rows'] as $delta => $row) { + // Convert the previously set row attributes arrays into strings. + $variables['row_attributes'][$delta] = !empty($variables['row_attributes_array'][$delta]) ? drupal_attributes($variables['row_attributes_array'][$delta]) : ''; + + for ($column = 0; $column < $columns; $column++) { + // Convert the previously set column attributes arrays into strings. + $variables['column_attributes'][$delta][$column] = !empty($variables['column_attributes_array'][$delta][$column]) ? drupal_attributes($variables['column_attributes_array'][$delta][$column]) : ''; + } + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/process/views/views-view-list.process.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/process/views/views-view-list.process.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,13 @@ + $item) { + // Convert the previously set row attributes arrays into strings. + $variables['row_attributes'][$delta] = !empty($variables['row_attributes_array'][$delta]) ? drupal_attributes($variables['row_attributes_array'][$delta]) : ''; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/process/views/views-view-table.process.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/process/views/views-view-table.process.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,23 @@ + $row) { + // Convert the previously set row attributes arrays into strings. + $variables['row_attributes'][$delta] = !empty($variables['row_attributes_array'][$delta]) ? drupal_attributes($variables['row_attributes_array'][$delta]) : ''; + + foreach ($row as $field => $content) { + // Convert the previously set field attributes arrays into strings. + $variables['field_attributes'][$field][$delta] = !empty($variables['field_attributes_array'][$field][$delta]) ? drupal_attributes($variables['field_attributes_array'][$field][$delta]) : ''; + } + } + + foreach ($variables['header'] as $field => $label) { + // Convert the previously set header attributes arrays into strings. + $variables['header_attributes'][$field] = !empty($variables['header_attributes_array'][$field]) ? drupal_attributes($variables['header_attributes_array'][$field]) : ''; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/process/views/views-view-unformatted.process.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/process/views/views-view-unformatted.process.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,13 @@ + $item) { + // Convert the previously set row attributes arrays into strings. + $variables['row_attributes'][$delta] = !empty($variables['row_attributes_array'][$delta]) ? drupal_attributes($variables['row_attributes_array'][$delta]) : ''; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/layouts/simple/simple.layout.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/layouts/simple/simple.layout.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,127 @@ +/******************************************************************************* + * _layout.scss + * + * Styling of the "simple" layout demonstrating the Compass grid extension Susy + * and building mobile first layouts. + ******************************************************************************/ +@import "susy"; + +// Susy Variables + +// Set consistent vertical and horizontal spacing units. +$vert-spacing-unit: 20px; +$horz-spacing-unit: 1em; + +// Define Susy grid variables mobile first. +$total-columns: 4; +$column-width: 4em; +$gutter-width: $horz-spacing-unit; +$grid-padding: 5px; + +$container-style: magic; +$container-width: 1200px; + +// Susy Media Layouts @see http://susy.oddbird.net/guides/reference/#ref-media-layouts +$tab: 44em 12; // At 44em use 12 columns. +$desk: 70em 16; // At 70em use 16 columns. + +.l-header, +.l-main, +.l-footer { + @include container; // Define these elements as the grid containers. + // @include susy-grid-background; // Show the columns for debugging. + margin-bottom: $vert-spacing-unit; +} + +.l-region--highlighted, +.l-region--help, +.l-region--sidebar-first, +.l-region--sidebar-second { + margin-bottom: $vert-spacing-unit; +} + +@include at-breakpoint($tab) { // At a given Susy Media Layout, use a given amount of columns. + .l-header, + .l-main, + .l-footer { + @include set-container-width; // Reset only the container width (elements have already been declared as containers). + // @include susy-grid-background; // Show the columns for debugging. + } + + .l-branding { + @include span-columns(4, 12); // Span 4 out of 12 columns. + } + .l-region--header{ + @include span-columns(8 omega, 12); // Span the last (omega) 8 columns of 12. + } + .l-region--navigation { + clear: both; + } + + .sidebar-first, + .sidebar-second, + .two-sidebars { + .l-content { + @include span-columns(8, 12); // Span 8 out of 12 columns. + } + .l-region--sidebar-first, + .l-region--sidebar-second { + @include span-columns(4 omega, 12); // Span the last (omega) 4 columns of 12. + } + .l-region--sidebar-second { + clear: right; + } + } +} + +@include at-breakpoint($desk) { + .l-header, + .l-main, + .l-footer { + @include set-container-width; // Reset only the container width (elements have already been declared as containers). + // @include susy-grid-background; // Show the columns for debugging. + } + + .l-branding { + @include span-columns(6, 16); // Span 6 out of 16 columns. + } + .l-region--header{ + @include span-columns(10 omega, 16); // Span the last (omega) 10 columns of 16. + } + + .sidebar-first { + .l-content { + @include span-columns(12 omega, 16); // Span the last (omega) 12 columns of 16. + } + .l-region--sidebar-first { + @include span-columns(4, 16); // Span 4 out of 16 columns. + } + } + .sidebar-second { + .l-content { + @include span-columns(12, 16); // Span 12 out of 16 columns. + } + .l-region--sidebar-second { + @include span-columns(4 omega, 16); // Span the last (omega) 4 columns of 16. + clear: none; + } + } + + .two-sidebars { + .l-content { + @include span-columns(8, 16); // Span 8 out of 16 columns. + @include push(4, 16); // Push element by adding 4 out of 16 columns of left margin. + } + .l-region--sidebar-first, + .l-region--sidebar-second { + @include span-columns(4, 16); // Span 4 out of 16 columns. + } + .l-region--sidebar-first { + @include pull(12, 16); // Pull element by adding 12 out of 16 columns of negative left margin. + } + .l-region--sidebar-second { + @include omega; // This element spans the last (omega) column. + clear: none; + } + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/aggregator/aggregator.theme-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/aggregator/aggregator.theme-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,8 @@ +/** + * @file + * Aggregator theme CSS for right to left languages. + */ + +.feed-source .feed-icon { + float: left; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/aggregator/aggregator.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/aggregator/aggregator.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,9 @@ +/** + * @file + * Aggregator theme CSS. + */ + +.feed-source .feed-icon { + float: right; /* LTR */ + display: block; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/block/block.admin.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/block/block.admin.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,16 @@ +/** + * @file + * Styles for the block admin page. + */ +.blocks-admin { + .region-title { + font-weight: bold; + } + .region-message { + font-weight: normal; + color: #999; + } + .region-populated { + display: none; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/block/block.demo.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/block/block.demo.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,34 @@ +/** + * @file + * Styles for the block demo page. + */ + +@import "compass"; + +.block-region { + margin-top: 4px; + margin-bottom: 4px; + padding: 3px; + background-color: #ff6; +} +.block-demo-backlink, +.block-demo-backlink:link, +.block-demo-backlink:visited { + /* Position */ + position: fixed; + z-index: 499; + left: 20px; /* LTR */ + /* Box Model */ + padding: 5px 10px; + /* Font */ + color: #000; + font-family: "Lucida Grande", Verdana, sans-serif; + font-size: small; + line-height: 20px; + /* Other Declarations */ + background-color: #B4D7F0; + @include border-radius(0 0 10px 10px); +} +.block-demo-backlink:hover { + text-decoration: underline; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/book/book.admin.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/book/book.admin.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,25 @@ +/** + * @file + * Administration styles for the Book module. + */ +/** + * Book outline on book edit form. + */ +.js .book-outline-form .form-submit { + display: none; +} +/** + * Book form for administering a single book's hierarchy. + */ +.book-admin-edit select { + margin-right: 24px; +} +.book-admin-edit .progress-disabled { + margin-right: 0; +} +.book-admin-edit .ajax-new-content { + background-color: #ffd; +} +.book-admin-edit .form-item { + float: left; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/book/book.theme-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/book/book.theme-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,15 @@ +/** + * @file + * Basic default book structural CSS for right to left languages. + */ +.book-navigation__previous { + float: right; + text-align: right; +} +.book-navigation__up { + float: right; +} +.book-navigation__next { + float: left; + text-align: left; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/book/book.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/book/book.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,22 @@ +/** + * @file + * Basic theming for the book navigation component. + */ +.book-navigation__previous { + float: left; /* LTR */ + display: block; + width: 45%; + text-align: left; /* LTR */ +} +.book-navigation__up { + float: left; /* LTR */ + display: block; + width: 10%; + text-align: center; +} +.book-navigation__next { + float: right; /* LTR */ + display: block; + width: 45%; + text-align: right; /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/color/color.admin-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/color/color.admin-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,48 @@ +/** + * @file + * Right-to-left specific stylesheet for the Color module. + */ + +#placeholder { + left: 0; + right: auto; +} + +/* Palette */ +.color-form .form-item { + padding-left: 0; + padding-right: 1em; +} +.color-form label { + float: right; + clear: right; +} +.color-form .form-text, +.color-form .form-select { + float: right; +} +.color-form .form-text { + margin-right: 0; + margin-left: 5px; +} +#palette .hook { + float: right; +} +#palette .down, +#palette .up, +#palette .both { + background: image-url('modules/color/hook-rtl.png') no-repeat 0 0; +} +#palette .up { + background-position: 0 -27px; +} +#palette .both { + background-position: 0 -54px; +} +#palette .lock { + float: right; + right: -10px; +} +html.js #preview { + float: right; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/color/color.admin.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/color/color.admin.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,85 @@ +/** + * @file + * Stylesheet for the administration pages of the Color module. + */ + +/* Farbtastic placement */ +.color-form { + max-width: 50em; + position: relative; +} +#placeholder { + position: absolute; + top: 0; + right: 0; /* LTR */ +} + +/* Palette */ +.color-form .form-item { + height: 2em; + line-height: 2em; + padding-left: 1em; /* LTR */ + margin: 0.5em 0; +} +.color-form label { + float: left; /* LTR */ + clear: left; /* LTR */ + width: 10em; +} +.color-form .form-text, +.color-form .form-select { + float: left; /* LTR */ +} +.color-form .form-text { + text-align: center; + margin-right: 5px; /* LTR */ + cursor: pointer; +} + +#palette .hook { + float: left; /* LTR */ + margin-top: 3px; + width: 16px; + height: 16px; +} +#palette .down, +#palette .up, +#palette .both { + background: image-url('modules/color/hook.png') no-repeat 100% 0; /* LTR */ +} +#palette .up { + background-position: 100% -27px; /* LTR */ +} +#palette .both { + background-position: 100% -54px; /* LTR */ +} + +#palette .lock { + float: left; /* LTR */ + position: relative; + top: -1.4em; + left: -10px; /* LTR */ + width: 20px; + height: 25px; + background: image-url('modules/color/lock.png') no-repeat 50% 2px; + cursor: pointer; +} +#palette .unlocked { + background-position: 50% -22px; +} +#palette .form-item { + width: 20em; +} +#palette .item-selected { + background: #eee; +} + +/* Preview */ +#preview { + display: none; +} +html.js #preview { + display: block; + position: relative; + float: left; /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/comment/comment.theme-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/comment/comment.theme-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,9 @@ +/** + * @file + * Right-to-left comment module look and feel styling. + */ + +.indented { + margin-left: 0; + margin-right: 25px; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/comment/comment.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/comment/comment.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,8 @@ +/** + * @file + * Comment module look and feel styling. + */ + +.indented { + margin-left: 25px; /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/contextual/contextual.base-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/contextual/contextual.base-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,15 @@ +/** + * @file + * Styling for contextual links behaviour and structure. + */ + +/** + * Contextual links structure. + */ +.contextual-links-wrapper { + left: 5px; + right: auto; +} +.contextual-links-trigger { + text-align: left; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/contextual/contextual.base.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/contextual/contextual.base.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,37 @@ +/** + * @file + * Styling for contextual links behaviour and structure. + */ + +/** + * Contextual links behaviour. + */ +.contextual-links-wrapper, +.contextual-links-trigger, +.contextual-links { + display: none !important; +} +html.js .contextual-links-wrapper, +.contextual-links-region:hover .contextual-links-trigger, +.contextual-links-active .contextual-links-trigger, +.contextual-links-active .contextual-links { + display: block !important; +} + +/** + * Contextual links structure. + */ +.contextual-links-region { + outline: none; + position: relative; +} +.contextual-links-wrapper { + position: absolute; + z-index: 999; + right: 5px; /* LTR */ + top: 2px; +} +.contextual-links-trigger { + overflow: hidden; + text-align: right; /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/contextual/contextual.theme-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/contextual/contextual.theme-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,15 @@ +/** + * @file + * Styling for contextual links look and feel. + */ + +@import "compass"; + +/** + * Contextual links. + */ +.contextual-links { + left: 0; + right: auto; + @include border-radius(0 4px 4px 4px); +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/contextual/contextual.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/contextual/contextual.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,96 @@ +/** + * @file + * Styling for contextual links look and feel. + * + * We are proactivly making use of !important to ensure the contextual links + * styling isn't broken by unspecific selectors such as ".block a". In order to + * change the styling of the contextual links you should overwrite this file in + * your subtheme. + */ + +@import "compass"; + +/** + * Contextual link wrappers + */ +.contextual-links-region-active { + outline: #999 dashed 1px; +} +.contextual-links-wrapper { + font-size: 12px !important; + + a { + text-decoration: none; + } +} + +/** + * Contextual trigger. +*/ +.contextual-links-trigger { + /* Positioning */ + height: 18px; + /* Box Model */ + margin: 0 !important; + padding: 0 2px !important; + width: 28px; + /* Other Declarations */ + background: transparent image-url('modules/contextual/gear-select.png') no-repeat 2px 0 !important; + border: 1px solid transparent !important; + @include border-radius(4px); + outline: none; + text-indent: 9999px; /* LTR */ +} +.contextual-links-trigger:hover, +.contextual-links-active .contextual-links-trigger { + background-position: 2px -18px !important; +} +.contextual-links-active .contextual-links-trigger { + /* Positioning */ + position: relative; + z-index: 1; + /* Other Declarations */ + background-color: #fff !important; + border-color: #ccc !important; + border-bottom: none !important; + @include border-bottom-radius(0); +} + +/** + * Contextual links. + */ +.contextual-links { + /* Position */ + position: absolute; + right: 0; /* LTR */ + top: 18px; + /* Box Model */ + margin: 0 !important; + padding: 0 !important; + /* Other Declarations */ + background-color: #fff !important; + border: 1px solid #ccc !important; + @include border-radius(4px 0 4px 4px); /* LTR */ + text-align: left; + white-space: nowrap; + + li { + margin: 0 !important; + padding: 0 !important; + line-height: 100%; + list-style: none; + list-style-image: none; + } + + a { + display: block; + margin: 0 !important; + padding: 5px 10px !important; + color: #333 !important; + font-size: 12px !important; + + &:hover { + background-color: #bfdcee !important; + } + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/field/field.theme-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/field/field.theme-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,14 @@ +/** + * @file + * Styling for contextual links behaviour and structure. + */ + +/** + * Field display. + */ +.field--label-inline { + .field__label, + .field__items { + float: right; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/field/field.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/field/field.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,17 @@ +/** + * @file + * Styling for contextual links behaviour and structure. + */ + +/** + * Field display. + */ +.field__label { + font-weight: bold; +} +.field--label-inline { + .field__label, + .field__items { + float: left; /* LTR */ + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/field_ui/field_ui.admin-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/field_ui/field_ui.admin-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,14 @@ +/** + * @file + * Right-to-left specific stylesheet for the Field UI module. + */ + +/** + *'Manage fields' and 'Manage display' overviews. + */ +.field-ui-overview { + /* Add New Row */ + .add-new .label-input { + float: right; /* LTR */ + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/field_ui/field_ui.admin.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/field_ui/field_ui.admin.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,48 @@ +/** + * @file + * Stylesheet for the Field UI module. + */ + +/** + *'Manage fields' and 'Manage display' overviews. + */ +.field-ui-overview { + /* Add New Row */ + .add-new { + td { + vertical-align: top; + } + .label-input { + float: left; /* LTR */ + } + .tabledrag-changed { + display: none; + } + .form-type-machine-name .description { + white-space: normal; + } + } + + /* Hidden Messages */ + .region-add-new-title { + display: none; + } + .region-populated { + display: none; + } +} + +/** + * 'Manage display' overview + */ +.field-display-overview { + .field-formatter-settings-editing td { + vertical-align: top; + } + .field-formatter-settings-editing .field-formatter-type { + display: none; + } +} +.field-ui-display-overview-form #edit-refresh { + display:none; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/file/file.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/file/file.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,30 @@ +/** + * @file + * Admin stylesheet for file module. + */ + +/** + * Managed file element. + */ +.form-managed-file { + .progress-disabled { + float: none; + display: inline; + } + + .ajax-progress, + .throbber { + float: none; + } + + .ajax-progress-bar { + display: none; + width: 28em; + margin-top: 4px; + padding: 0; + + .bar { + margin: 0; + } + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/filter/filter.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/filter/filter.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,55 @@ +/** + * @file + * Styling for the filter module. + */ + +/** + * Top Level Wrapper + * Contains the form item being filtered, the filter format form item and + * formatting guidelines. + */ +.text-format-wrapper { + .form-item { + margin-bottom: 0; + } + .description { + margin-top: 0.5em; + } +} + +/* Filter Format Wrapper. */ +.filter-wrapper { + border-top: 0; + margin: 0; + + .form-item { + float: left; + padding: 0 0 0.5em 1.5em; + + label { + display: inline; + } + } +} + +/* More Information Link. */ +.filter-help { + float: right; + padding: 0 1.5em 0.5em; + + a { + background: transparent image-url('misc/help.png') right center no-repeat; + padding: 0 20px; + } +} + +/* Filter Guidelines */ +.filter-guidelines { + clear: left; + padding: 0 1.5em; +} + +/* Filter formatting tips. */ +.tips { + font-size: 0.9em; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/forum/forum.theme-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/forum/forum.theme-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,10 @@ +/** + * @file + * Right-to-left styling for the Forum module. + */ + +.forum-icon { + float: right; + margin-left: 0; + margin-right: 0.4em; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/forum/forum.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/forum/forum.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,30 @@ +/** + * @file + * Styling for the Forum module. + */ + +/* Forum Status Icons */ +.forum-icon { + float: left; + width: 24px; + height: 24px; + margin-right: 0.4em; + background-image: image-url('modules/forum/forum-icons.png'); + background-repeat: no-repeat; + text-indent: -9999px; +} +.forum-icon--status-new { + background-position: -24px 0; +} +.forum-icon--status-hot { + background-position: -48px 0; +} +.forum-icon--status-hot-new { + background-position: -72px 0; +} +.forum-icon--status-sticky { + background-position: -96px 0; +} +.forum-icon--status-closed { + background-position: -120px 0; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/image/image.admin.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/image/image.admin.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,74 @@ +/** + * @file + * Admin styles for the image module. + */ + +/** + * Image style configuration pages. + */ + +/* Add new effect form. */ +.image-style-new, +.image-style-new div { + display: inline; +} + +/* Image style columns. */ +.image-style-preview__col { + float: left; + top: 50%; + width: 48%; + padding-bottom: 2em; + text-align: center; +} + +/* Image style preview images. */ +.image-style-preview__preview-image { + margin: auto; + position: relative; +} +.preview-image__width { + position: absolute; + height: 2px; + left: -1px; + bottom: -6px; + border: 1px solid #666; + border-top: none; + + .dimension { + position: relative; + top: 4px; + } +} +.preview-image__height { + position: absolute; + right: -6px; + top: -1px; + width: 2px; + border: 1px solid #666; + border-left: none; + + .dimension { + position: absolute; + height: 2em; + top: 50%; + left: 10px; + margin-top: -1em; + } +} + +/** + * Image anchor form element. + */ +.image-anchor { + width: auto; + + .even, + .odd { + background: none; + } + + td { + border: 1px solid #CCC; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/image/image.theme-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/image/image.theme-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,15 @@ +/** + * @file + * Right-to-left styling for the Forum module. + */ + +/** + * Image upload widget. + */ +.image-preview { + float: right; + padding: 0 0 10px 10px; +} +.image-widget-data { + float: right; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/image/image.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/image/image.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,19 @@ +/** + * @file + * Styles for the image module. + */ + +/** + * Image upload widget. + */ +.image-preview { + float: left; /* LTR */ + padding: 0 10px 10px 0; /* LTR */ +} +.image-widget-data { + float: left; /* LTR */ + + .text-field { + width: auto; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/locale/locale.admin-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/locale/locale.admin-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,18 @@ +/** + * @file + * Right to left admin styles for the locale module. + */ + +.locale-translation-filter-form { + .form-item-language, + .form-item-translation, + .form-item-group { + float: right; + padding-left: .8em; + padding-right: 0; + } + .form-actions { + float: right; + padding: 3ex 1em 0 0; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/locale/locale.admin.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/locale/locale.admin.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,29 @@ +/** + * @file + * Admin styles for the locale module. + */ + +/* Untranslated locales. */ +.locale-untranslated { + font-style: normal; + text-decoration: line-through; +} + +/* Translations 'exposed' filter form. */ +.locale-translation-filter-form { + .form-item-language, + .form-item-translation, + .form-item-group { + float: left; /* LTR */ + padding-right: .8em; /* LTR */ + margin: 0.1em; + width: 15em; /* Opera 9 Fix. */ + } + .form-type-select select { + width: 100%; + } + .form-actions { + float: left; /* LTR */ + padding: 3ex 0 0 1em; /* LTR */ + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/openid/openid.base-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/openid/openid.base-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,9 @@ +/** + * @file + * Right to left base styles for the Open ID module. + */ + +html.js .user-login-form .openid-link, +html.js .user-login .openid-link { + margin-right: 0; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/openid/openid.base.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/openid/openid.base.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,14 @@ +/** + * @file + * Base styles for the Open ID module. + */ + +html.js .user-login-form .openid-link, +html.js .user-login .openid-link { + display: block; + margin-left: 0; /* LTR */ +} +html.js .user-login-form .form-item-openid-identifier, +html.js .user-login .form-item-openid-identifier { + display: none; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/openid/openid.theme-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/openid/openid.theme-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,15 @@ +/** + * @file + * Right to left theme styles for the openid module. + */ + +.form-item-openid-identifier input { + padding-left: 0; + padding-right: 20px; + background-position: right 50%; +} + +.openid-links a { + padding: 0 1.5em 0 0; + background-position: right top; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/openid/openid.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/openid/openid.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,30 @@ +/** + * @file + * Theme styles for the openid module. + */ + +.form-item-openid-identifier { + display: block; + + input { + padding-left: 20px; /* LTR */ + background-image: image-url('modules/openid/login-bg.png'); + background-position: left 50%; /* LTR */ + background-repeat: no-repeat; + } +} + +.openid-links { + li { + display: none; + margin: 0; + padding: 0; + list-style: none; + } + a { + padding: 0 0 0 1.5em; /* LTR */ + background-image: image-url('modules/openid/login-bg.png'); + background-position: left top; /* LTR */ + background-repeat: no-repeat; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/poll/poll.admin.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/poll/poll.admin.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,16 @@ +/** + * @file + * Admin styles for the poll module. + */ + +/* Poll choice form on node form. */ +.poll-choice-table { + .form-text { + display: inline; + width: auto; + } + .choice-flag { + white-space: nowrap; + width: 4em; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/poll/poll.theme-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/poll/poll.theme-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,15 @@ +/** + * @file + * Right to left theme for the poll voting form and results display. + */ + +/* Poll Bars */ +.poll-bars__bar .foreground { + float: right; +} +.poll-bars__text { + text-align: right; +} +.poll-bars__percent { + text-align: left; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/poll/poll.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/poll/poll.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,41 @@ +/** + * @file + * Theme for the poll voting form and results display. + */ + +/** + * Poll Results + */ + +/* Poll Bars */ +.poll-bars__bar { + height: 1em; + margin: 1px 0; + background-color: #ddd; + + .foreground { + height: 1em; + float: left; /* LTR */ + background-color: #000; + } +} +.poll-bars__percent { + text-align: right; /* LTR */ +} + +/* Poll Total */ +.poll-results__total { + text-align: center; +} + +/** + * Poll Voting Form + */ +.poll-vote-form { + text-align: center; +} +.poll-vote-form__choices { + display: table; + margin: 0 auto; + text-align: left; /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/search/search.theme-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/search/search.theme-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,27 @@ +/** + * @file + * Right to left search module theme. + */ + +/** + * Search Results + */ +.search-result__snippet { + padding-left: 0; + padding-right: 1em; +} + +/** + * Advanced Search Form + */ +.search-advanced { + .criterion { + float: right; + margin-right: 0; + margin-left: 2em; + } + .action { + float: right; + clear: right; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/search/search.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/search/search.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,28 @@ +/** + * @file + * Search module theme. + */ + +/** + * Search Results + */ +.search-result__snippet { + padding-left: 1em; /* LTR */ +} +.search-result__info { + font-size: 0.85em; +} + +/** + * Advanced Search Form + */ +.search-advanced { + .criterion { + float: left; /* LTR */ + margin-right: 2em; /* LTR */ + } + .action { + float: left; /* LTR */ + clear: left; /* LTR */ + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/admin/adminlink/_adminlink.admin.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/admin/adminlink/_adminlink.admin.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,11 @@ +/** + * @file + * Administration styles for quick inline admin links. + */ + +small .admin-link:before { + content: '['; +} +small .admin-link:after { + content: ']'; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/admin/adminpanel/_adminpanel.admin-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/admin/adminpanel/_adminpanel.admin-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,28 @@ +/** + * @file + * Right to left administration style for administration blocks. + */ + +/* Admin Panels */ +.admin-panel { + .admin-panel__body { + padding-right: 1em; + } +} + +/* Admin Panel Page Layout */ +.admin { + .left { + float: right; + } + .right { + float: left; + } + .expert-link { + margin-left: 0; + margin-right: 1em; + padding-left: 0; + padding-right: 4px; + text-align: left; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/admin/adminpanel/_adminpanel.admin.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/admin/adminpanel/_adminpanel.admin.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,30 @@ +/** + * @file + * Administration styles for the administration panels. + */ + +/* Admin Panels */ +.admin-panel { + .admin-panel__body { + padding-left: 1em; /* LTR */ + } +} + +/* Admin Panel Page Layout */ +.admin { + padding-top: 15px; + + .left { + float: left; /* LTR */ + width: 47%; + } + .right { + float: right; /* LTR */ + width: 47%; + } + .expert-link { + margin-right: 1em; /* LTR */ + padding-right: 4px; /* LTR */ + text-align: right; /* LTR */ + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/admin/appearance/_appearance.admin-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/admin/appearance/_appearance.admin-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,30 @@ +/** + * @file + * Right to left administration styles for the appearance page. + */ + +/** + * Disabled/Enabled Theme Lists + */ + +/* Theme Selector Links */ +.theme-selector__operations { + li { + float: right; + } +} + +/* Theme Selector Enabled State */ +.theme-selector--enabled { + .theme-selector__info { + float: left; + } + .theme-selector__screenshot { + float: right; + } +} +/* Theme Selector Disabled State */ +.theme-selector--disabled { + float: right; + padding: 20px 20px 20px; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/admin/appearance/_appearance.admin.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/admin/appearance/_appearance.admin.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,101 @@ +/** + * @file + * Administration styles for the appearance page. + */ + +/** + * Disabled/Enabled Theme Lists + */ +.system-themes-list { + margin-bottom: 20px; + + h2 { + margin: 0; + } +} +.system-themes-list--disabled { + padding-top: 20px; + border-top: 1px solid #cdcdcd; +} + +/** + * Theme Selector + */ +.theme-selector { + padding-top: 20px; + + h3 { + font-weight: normal; + } +} +/* Theme Selector Screenshot */ +.theme-selector__screenshot { + padding: 2px; + width: 294px; + height: 219px; + border: 1px solid #e0e0d8; + line-height: 219px; + text-align: center; +} +/* Theme Selector Incompatible Message */ +.theme-selector__incompatible { + margin-top: 10px; + font-weight: bold; +} +/* Theme Selector Links */ +.theme-selector__operations { + margin: 10px 0 0 0; + padding: 0; + + li { + float: left; /* LTR */ + margin: 0 1em 0 0; + list-style-type: none; + } +} +/* Theme Selector Default State */ +.theme-selector--default { + h3 { + font-weight: bold; + } + .theme-selector__screenshot { + border: 1px solid #aaa; + } +} +/* Theme Selector Enabled State */ +.theme-selector--enabled { + width: 820px; + + .theme-selector__info { + float: right; /* LTR */ + width: 500px; + } + h3 { + margin-top: 0; + } + .theme-selector__screenshot { + float: left; /* LTR */ + } +} +/* Theme Selector Disabled State */ +.theme-selector--disabled { + float: left; /* LTR */ + width: 300px; + padding: 20px 20px 20px 0; /* LTR */ + + .theme-selector__info { + min-height: 170px; + } + .theme-selector__screenshot { + width: 194px; + height: 144px; + line-height: 144px; + } +} + +/** + * Admin Theme Selector Form + */ +.system-themes-admin-form { + clear: left; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/admin/compactlink/_compactlink.admin.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/admin/compactlink/_compactlink.admin.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,8 @@ +/** + * @file + * Administration styles for compact links. + */ + +.compact-link { + margin: 0 0 0.5em 0; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/admin/modules/_modules.admin-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/admin/modules/_modules.admin-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,25 @@ +/** + * @file + * Right to left administration styles for the modules table. + */ + +/* Module Operation Links */ +.module-link { + padding: 1px 20px 1px 0; +} +.module-link-help { + background: image-url('misc/help.png') 0 50% no-repeat; /* LTR */ +} +.module-link-permissions { + background: image-url('misc/permissions.png') 0 50% no-repeat; /* LTR */ +} +.module-link-configure { + background: image-url('misc/configure.png') 0 50% no-repeat; /* LTR */ +} + +/* Module Help */ +.module-help { + float: left; + margin-left: 0; + margin-right: 1em; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/admin/modules/_modules.admin.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/admin/modules/_modules.admin.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,49 @@ +/** + * @file + * Administration styles for the modules table and help. + */ + +/* Module State Flags */ +.admin-disabled { + color: #800; +} +.admin-enabled { + color: #080; +} +.admin-missing { + color: #f00; +} + +/* Incompatible Modules */ +.incompatible { + font-weight: bold; +} + +/* Module Requirements */ +.admin-requirements, +.admin-required { + font-size: 0.9em; + color: #444; +} + +/* Module Operation Links */ +.module-link { + display: block; + padding: 1px 0 1px 20px; /* LTR */ + white-space: nowrap; +} +.module-link-help { + background: image-url('misc/help.png') 0 50% no-repeat; /* LTR */ +} +.module-link-permissions { + background: image-url('misc/permissions.png') 0 50% no-repeat; /* LTR */ +} +.module-link-configure { + background: image-url('misc/configure.png') 0 50% no-repeat; /* LTR */ +} + +/* Module Help */ +.module-help { + float: right; /* LTR */ + margin-left: 1em; /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/admin/statusreport/_statusreport.admin-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/admin/statusreport/_statusreport.admin-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,8 @@ +/** + * @file + * Right to left administration styles for the system status report. + */ + +.merge-up td { + padding: 0 28px 8px 6px; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/admin/statusreport/_statusreport.admin.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/admin/statusreport/_statusreport.admin.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,33 @@ +/** + * @file + * Administration styles for the system status report. + */ + +/* Status Icons */ +.system-status-report { + .status-icon { + height: 16px; + width: 16px; + background-repeat: no-repeat; + } + .error .status-icon { + background-image: image-url('misc/message-16-error.png'); + } + .warning .status-icon { + background-image: image-url('misc/message-16-warning.png'); + } +} + +/* Merge Cells */ +.merge-down, +.merge-down td { + border-bottom-width: 0 !important; +} + +.merge-up, +.merge-up td { + border-top-width: 0 !important; +} +.merge-up td { + padding: 0 6px 8px 28px; /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/admin/themesettings/_themesettings.admin.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/admin/themesettings/_themesettings.admin.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,16 @@ +/** + * @file + * Administration styles for the theme settings. + */ + +.theme-settings-left { + float: left; + width: 49%; +} +.theme-settings-right { + float: right; + width: 49%; +} +.theme-settings-bottom { + clear: both; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/autocomplete/_autocomplete.base-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/autocomplete/_autocomplete.base-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,14 @@ +/** + * @file + * Right to left base styles for autocomplete functionality. + * + * @see autocomplete.js + */ + +/* Animated throbber */ +html.js .form-autocomplete { + background-position: 0% 2px; +} +html.js .throbbing { + background-position: 0% -18px; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/autocomplete/_autocomplete.base.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/autocomplete/_autocomplete.base.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,35 @@ +/** + * @file + * Base styles for autocomplete functionality. + * + * @see autocomplete.js + */ + +/* Suggestion list */ +#autocomplete { + position: absolute; + z-index: 100; + overflow: hidden; + + ul { + margin: 0; + padding: 0; + list-style: none; + list-style-image: none; + } + li { + cursor: default; + white-space: pre; + zoom: 1; /* IE7 */ + } +} + +/* Animated throbber */ +html.js .form-autocomplete { + background-image: image-url('misc/throbber.gif'); + background-position: 100% 2px; /* LTR */ + background-repeat: no-repeat; +} +html.js .throbbing { + background-position: 100% -18px; /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/autocomplete/_autocomplete.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/autocomplete/_autocomplete.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,17 @@ +/** + * @file + * Theme for autocomplete. + * + * @see autocomplete.js + */ + +#autocomplete { + background: #fff; + border: 1px solid; + color: #000; + + .selected { + background: #0072b9; + color: #fff; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/collapsible/_collapsible.base.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/collapsible/_collapsible.base.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,19 @@ +/** + * @file + * Base styles for collapsible fieldset functionality. + * + * @see collapse.js + */ + +html.js fieldset.collapsed { + height: 1em; +} +html.js fieldset.collapsed .fieldset-wrapper { + display: none; +} +fieldset.collapsible { + position: relative; +} +fieldset.collapsible .fieldset-legend { + display: block; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/collapsible/_collapsible.theme-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/collapsible/_collapsible.theme-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,16 @@ +/** + * @file + * Right to left theme for collapsible fieldsets. + * + * @see collapse.js + */ + +html.js fieldset.collapsible .fieldset-legend { + padding-left: 0; + padding-right: 15px; + background-position: 98% 75%; +} +html.js fieldset.collapsed .fieldset-legend { + background-image: image-url('misc/menu-collapsed-rtl.png'); + background-position: 98% 50%; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/collapsible/_collapsible.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/collapsible/_collapsible.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,26 @@ +/** + * @file + * Theme for collapsible fieldsets. + * + * @see collapse.js + */ + +html.js fieldset.collapsible .fieldset-legend { + padding-left: 15px; /* LTR */ + background: image-url('misc/menu-expanded.png') 5px 65% no-repeat; /* LTR */ +} +html.js fieldset.collapsed { + border-bottom-width: 0; + border-left-width: 0; + border-right-width: 0; + + .fieldset-legend { + background-image: image-url('misc/menu-collapsed.png'); /* LTR */ + background-position: 5px 50%; /* LTR */ + } +} +.fieldset-legend .summary { + margin-left: 0.5em; + color: #999; + font-size: 0.9em; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/elements/_elements.theme-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/elements/_elements.theme-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,11 @@ +/** + * @file + * Basic right to left styling for common HTML elements. + */ + +/* Tables */ +th { + padding-left: 1em; + padding-right: 0; + text-align: right; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/elements/_elements.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/elements/_elements.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,26 @@ +/** + * @file + * Basic styling for common HTML elements. + */ + +/* Fieldsets */ +fieldset { + margin-bottom: 1em; +} + +/* Tables */ +table { + border-collapse: collapse; +} +th { + padding-right: 1em; /* LTR */ + background-color: #bbb; + text-align: left; /* LTR */ +} +tr.even, +tr.odd { + background-color: #eee; +} +tr.odd { + background-color: #ddd; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/exposed/_exposed.admin-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/exposed/_exposed.admin-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,17 @@ +/** + * Exposed filters. + */ +.exposed-filters .filters { + float: right; + margin-left: 1em; + margin-right: 0; +} +.exposed-filters .form-item label { + float: right; +} +/* Current filters */ +.exposed-filters .additional-filters { + float: right; + margin-left: 1em; + margin-right: 0; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/exposed/_exposed.admin.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/exposed/_exposed.admin.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,32 @@ +/** + * Exposed filters. + */ +.exposed-filters .filters { + float: left; /* LTR */ + margin-right: 1em; /* LTR */ + width: 25em; /* IE6 */ +} +.exposed-filters .form-item { + margin: 0 0 0.1em 0; + padding: 0; +} +.exposed-filters .form-item label { + float: left; /* LTR */ + width: 10em; + font-weight: normal; +} +.exposed-filters .form-select { + width: 14em; +} +/* Current filters */ +.exposed-filters .current-filters { + margin-bottom: 1em; +} +.exposed-filters .current-filters .placeholder { + font-style: normal; + font-weight: bold; +} +.exposed-filters .additional-filters { + float: left; /* LTR */ + margin-right: 1em; /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/form/_form.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/form/_form.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,62 @@ +/** + * @form + * Theme for markup generated by Form API. + */ + +/* Generic Form Items. */ +.form-item, +.form-actions { + margin-bottom: 1em; + + label { + display: block; + font-weight: bold; + } + .description { + font-size: 0.85em; + } +} + +/* Checkboxes and Radios */ +.form-checkboxes, +.form-radios { + .form-item { + margin-bottom: 0.4em; + } + .description { + margin-left: 2.4em; + } +} +label.option { + display: inline; + font-weight: normal; +} +.form-checkbox, +.form-radio { + vertical-align: middle; +} + +/* Errors */ +.marker, +.form-required { + color: #f00; +} +input.error, +textarea.error, +select.error { + border: 2px solid red; +} + +/* Table Form Items */ +tr .form-item { + margin-top: 0; + margin-bottom: 0; + white-space: nowrap; +} + +/* Inline Items */ +.container-inline .form-actions, +.container-inline.form-actions { + margin-top: 0; + margin-bottom: 0; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/menus/_links.theme-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/menus/_links.theme-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,12 @@ +/** + * @file + * Inline links as generated by theme_links(). + */ + +ul.inline { + li { + float: right; + margin-right: 0; + margin-left: 1em; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/menus/_links.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/menus/_links.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,20 @@ +/** + * @file + * Inline links as generated by theme_links(). + */ + +@import "compass/utilities/general/clearfix"; + +.links--inline { + @include pie-clearfix; + list-style-type: none; + margin: 0; + padding: 0; + + li { + float: left; /* LTR */ + margin-right: 1em; /* LTR */ + + & > a { display: block; } + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/menus/_localtasks.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/menus/_localtasks.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,37 @@ +/** + * @file + * Theme styles for markup generated by theme_menu_local_tasks(). + */ + +/* Tabs */ +.tabs { + a { + background-color: #eee; + text-decoration: none; + + &.active { + background-color: #ccc; + } + &:hover, + &:focus { + background-color: #bbb; + } + } +} + +/* Primary Tabs */ +.tabs--primary { + margin-bottom: 1em; + border-bottom: 1px solid #bbb; + + a { + padding: 0.3em 0.8em; + } +} + +/* Secondary Tabs */ +.tabs--secondary a { + padding: 0.2em 0.5em; + margin: 0.4em 0; + font-size: 0.9em; +} \ No newline at end of file diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/menus/_menutree.theme-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/menus/_menutree.theme-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,13 @@ +/** + * @file + * Styles for a hierarchical menu as generated by theme_menu_tree(). + */ + +.menu { + text-align: right; + + /* Menu Item Hierarchy Modifiers */ + .collapsed { + list-style-image: image-url('misc/menu-collapsed-rtl.png'); + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/menus/_menutree.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/menus/_menutree.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,32 @@ +/** + * @file + * Styles for a hierarchical menu as generated by theme_menu_tree(). + */ + +.menu { + border: none; + list-style: none; + text-align: left; /* LTR */ + + /* Menu Item Hierarchy Modifiers */ + .expanded { + list-style-image: image-url('misc/menu-expanded.png'); + list-style-type: circle; + } + .collapsed { + list-style-image: image-url('misc/menu-collapsed.png'); /* LTR */ + list-style-type: disc; + } + .leaf { + list-style-image: image-url('misc/menu-leaf.png'); + list-style-type: square; + } +} + +/* Menu State Modifiers */ +.active { + color: #000; +} +.menu-disabled { + background: #ccc; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/morelink/_morelink.theme-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/morelink/_morelink.theme-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,8 @@ +/** + * @file + * Right to left theme for the more link. + */ + +.more-link { + text-align: left; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/morelink/_morelink.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/morelink/_morelink.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,9 @@ +/** + * @file + * Theme for more links. + */ + +.more-link { + display: block; + text-align: right; /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/pager/_pager.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/pager/_pager.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,20 @@ +/** + * @file + * Theme for markup generated by theme_pager(). + */ + +.pager { + clear: both; + padding: 0; + text-align: center; +} +.pager__item { + display: inline; + padding: 0.5em; + background-image: none; + list-style-type: none; + +} +.pager__item--current { + font-weight: bold; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/progress/_progress.base-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/progress/_progress.base-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,20 @@ +/** + * @file + * Right to left base styles for the progress behavior. + * + * @see progress.js + */ + +/* Bar */ +.progress .percentage { + float: left; +} +.progress-disabled { + float: right; +} +.ajax-progress { + float: right; +} +.ajax-progress .throbber { + float: right; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/progress/_progress.base.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/progress/_progress.base.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,45 @@ +/** + * @file + * Base styles for the progress behavior. + * + * @see progress.js + */ + +/* Bar */ +.progress { + .bar { + background-color: #fff; + border: 1px solid; + } + .filled { + height: 1.5em; + width: 5px; + background-color: #000; + } + .percentage { + float: right; /* LTR */ + } +} + +/* Throbber */ +.ajax-progress { + display: inline-block; + + .throbber { + float: left; /* LTR */ + height: 15px; + width: 15px; + margin: 2px; + background: transparent image-url('misc/throbber.gif') no-repeat 0px -18px; + } + .message { + padding-left: 20px; + } +} + +tr .ajax-progress .throbber { + margin: 0 2px; +} +.ajax-progress-bar { + width: 16em; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/progress/_progress.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/progress/_progress.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,21 @@ +/** + * @file + * Theme for the progress behavior. + * + * @see progress.js + */ +.progress { + font-weight: bold; + + .bar { + background: #ccc; + border-color: #666; + margin: 0 0.2em; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; + } + .filled { + background: #0072b9 image-url('misc/progress.gif'); + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/resizable/_resizable.base.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/resizable/_resizable.base.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,23 @@ +/** + * @file + * Base styles for the resizable textareas functionality. + * + * @see textarea.js + */ + +@import "compass"; + +.form-textarea-wrapper textarea { + display: block; + @include box-sizing(border-box); + width: 100%; + margin: 0; +} +.resizable-textarea .grippie { + height: 9px; + background: #eee image-url('misc/grippie.png') no-repeat center 2px; + border: 1px solid #ddd; + border-top-width: 0; + cursor: s-resize; + overflow: hidden; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/system.admin-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/system.admin-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,9 @@ +/** + * @file + * Right to left system wide administration styles. + */ + +@import "admin/adminpanel/adminpanel.admin-rtl"; +@import "admin/appearance/appearance.admin-rtl"; +@import "admin/modules/modules.admin-rtl"; +@import "admin/statusreport/statusreport.admin-rtl"; diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/system.admin.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/system.admin.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,12 @@ +/** + * @file + * System wide administration styles. + */ + +@import "admin/adminlink/adminlink.admin"; +@import "admin/adminpanel/adminpanel.admin"; +@import "admin/appearance/appearance.admin"; +@import "admin/compactlink/compactlink.admin"; +@import "admin/modules/modules.admin"; +@import "admin/statusreport/statusreport.admin"; +@import "admin/themesettings/themesettings.admin"; diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/system.base-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/system.base-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,8 @@ +/** + * @file + * Right to left system wide base styles. + */ + +@import "autocomplete/autocomplete.base-rtl"; +@import "tabledrag/tabledrag.base-rtl"; +@import "progress/progress.base-rtl"; diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/system.base.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/system.base.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,12 @@ +/** + * @file + * System wide base styles. + */ + +@import "autocomplete/autocomplete.base"; +@import "collapsible/collapsible.base"; +@import "resizable/resizable.base"; +@import "tabledrag/tabledrag.base"; +@import "tableheader/tableheader.base"; +@import "progress/progress.base"; +@import "utilities/utilities.base"; diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/system.menus.theme-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/system.menus.theme-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,7 @@ +/** + * @file + * Right to left menu and navigational styles. + */ + +@import "menus/menutree.theme-rtl"; +@import "menus/links.theme-rtl"; diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/system.menus.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/system.menus.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,8 @@ +/** + * @file + * Menu and navigational styles. + */ + +@import "menus/menutree.theme"; +@import "menus/links.theme"; +@import "menus/localtasks.theme"; diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/system.messages.theme-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/system.messages.theme-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,14 @@ +/** + * @file + * Right to left theme for for system messages. + */ + +/* Message */ +.messages { + padding: 10px 50px 10px 10px; + background-position: 99% 8px; + + ul { + margin: 0 1em 0 0; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/system.messages.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/system.messages.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,67 @@ +/** + * @file + * Theme for for system messages. + */ + +/* Message */ +.messages { + margin: 6px 0; + padding: 10px 10px 10px 50px; /* LTR */ + background-position: 8px 8px; /* LTR */ + background-repeat: no-repeat; + border: 1px solid; + + ul { + margin: 0 0 0 1em; /* LTR */ + padding: 0; + } + li { + list-style-image: none; + } +} + +/* Status Messages */ +.messages--status { + background-image: image-url('misc/message-24-ok.png'); + border-color: #be7; +} +.messages--status, +tr.ok { + background-color: #f8fff0; +} +.messages--status, +.ok { + color: #234600; +} + +/* Warning Messages */ +.messages--warning { + background-image: image-url('misc/message-24-warning.png'); + border-color: #ed5; +} +.messages--warning, +tr.warning { + background-color: #fffce5; +} +.messages--warning, +.warning { + color: #333; +} + +/* Error Messages */ +.messages--error { + background-image: image-url('misc/message-24-error.png'); + border-color: #ed541d; +} +.messages--error, +tr.error { + background-color: #fef5f1; +} +.messages--error, +.error { + color: #333; +} + +.error /*p*/.error { + color: #8c2e0b; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/system.theme-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/system.theme-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,8 @@ +/** + * @file + * Right to left system wide theme styles. + */ + +@import "elements/elements.theme-rtl"; +@import "collapsible/collapsible.theme-rtl"; +@import "morelink/morelink.theme-rtl"; diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/system.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/system.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,15 @@ +/** + * @file + * System wide theme styles. + */ + +@import "elements/elements.theme"; +@import "autocomplete/autocomplete.theme"; +@import "collapsible/collapsible.theme"; +@import "tabledrag/tabledrag.theme"; +@import "progress/progress.theme"; +@import "tableselect/tableselect.theme"; +@import "form/form.theme"; +@import "tablesort/tablesort.theme"; +@import "morelink/morelink.theme"; +@import "pager/pager.theme"; diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/tabledrag/_tabledrag.base-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/tabledrag/_tabledrag.base-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,21 @@ +/** + * @file + * Right to left base styling for the tabledrag behavior. + * + * @see tabledrag.js + */ + +.draggable .tabledrag-handle { + float: right; + margin-left: 0; +} +.indentation { + float: right; +} +.tree-child, +.tree-child-last { + background-position: -65px center; +} +.tabledrag-toggle-weight-wrapper { + text-align: left; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/tabledrag/_tabledrag.base.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/tabledrag/_tabledrag.base.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,53 @@ +/** + * @file + * Base styling for the tabledrag behavior. + * + * @see tabledrag.js + */ + +body.drag { + cursor: move; +} +/* Tabledrag Handle */ +.tabledrag-handle { + float: left; /* LTR */ + overflow: hidden; + text-decoration: none; + cursor: move; + + .handle { + height: 15px; + width: 15px; + margin: -0.4em 0; + padding: 0.4em; + background: image-url('misc/draggable.png') no-repeat 6px 9px; + } + &:hover { + text-decoration: none; + } +} +.tabledrag-handle-hover .handle { + background-position: 6px -11px; +} + +/* Indentation */ +.indentation { + float: left; /* LTR */ + width: 20px; +} + +/* Tree Images */ +.tree-child { + background: image-url('misc/tree.png') no-repeat 12px center; /* LTR */ +} +.tree-child-last { + background: image-url('misc/tree-bottom.png') no-repeat 12px center; /* LTR */ +} +.tree-child-horizontal { + background: image-url('misc/tree.png') no-repeat -12px center; +} + +/* Toggle Weight Link */ +.tabledrag-toggle-weight-wrapper { + text-align: right; /* LTR */ +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/tabledrag/_tabledrag.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/tabledrag/_tabledrag.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,13 @@ +/** + * @file + * Theme for the tabledrag behavior. + * + * @see tabledrag.js + */ + +.drag { + background-color: #fffff0; +} +.drag-previous { + background-color: #ffd; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/tableheader/_tableheader.base.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/tableheader/_tableheader.base.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,11 @@ +/** + * @file + * Base styling for the tableheader behavior. + * + * @see tableheader.js + */ + +.sticky-header { + margin-top: 0; + background-color: #fff; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/tableselect/_tableselect.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/tableselect/_tableselect.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,14 @@ +/** + * @file + * Theme for the tableselect behavior. + * + * @see tableselect.js +*/ + +.selected td { + background: #ffc; +} +.checkbox, +.checkbox { + text-align: center; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/tablesort/_tablesort.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/tablesort/_tablesort.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,11 @@ +/** + * @file + * Theme for the markup generated by theme_tablesort_indicator(). + */ + +th.active img { + display: inline; +} +td.active { + background-color: #ddd; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/system/utilities/_utilities.base.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/system/utilities/_utilities.base.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,80 @@ +/** + * @file + * System utility classes. + */ + +@import "compass/utilities/general/clearfix"; + +/** + * Inline items. + */ +.container-inline div, +.container-inline label { + display: inline; +} +/* Fieldset contents always need to be rendered as block. */ +.container-inline .fieldset-wrapper { + display: block; +} + +/** + * Prevent text wrapping. + */ +.nowrap { + white-space: nowrap; +} + +/** + * For anything you want to hide on page load when JS is enabled, so + * that you can use the JS to control visibility and avoid flicker. + */ +html.js .js-hide { + display: none; +} + +/** + * Hide elements from all users. + * + * Used for elements which should not be immediately displayed to any user. An + * example would be a collapsible fieldset that will be expanded with a click + * from a user. The effect of this class can be toggled with the jQuery show() + * and hide() functions. + */ +.element-hidden { + display: none; +} + +/** + * Hide elements visually, but keep them available for screen-readers. + * + * Used for information required for screen-reader users to understand and use + * the site where visual display is undesirable. Information provided in this + * manner should be kept concise, to avoid unnecessary burden on the user. + * "!important" is used to prevent unintentional overrides. + */ +.element-invisible { + position: absolute !important; + clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ + clip: rect(1px, 1px, 1px, 1px); + overflow: hidden; + height: 1px; +} + +/** + * The .element-focusable class extends the .element-invisible class to allow + * the element to be focusable when navigated to via the keyboard. + */ +.element-invisible.element-focusable:active, +.element-invisible.element-focusable:focus { + position: static !important; + clip: auto; + overflow: visible; + height: auto; +} + +/** + * Use the clearfix from Compass. + */ +.clearfix { + @include pie-clearfix; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/taxonomy/taxonomy.admin.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/taxonomy/taxonomy.admin.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,11 @@ +/** + * @file + * Administrative styling for the taxonomy module. + */ + +.taxonomy-term-divider-top { + border-bottom: none; +} +.taxonomy-term-divider-bottom { + border-top: 1px dotted #CCC; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/user/user.admin-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/user/user.admin-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,27 @@ +/** + * @file + * Right to left administrative styling for the user module. + */ +/** + * User Permissions Page + */ +.user-admin-permissions { + .permission { + padding-left: 0; + padding-right: 1.5em; + } +} + +/** + * User Roles Page + * + * Override default textfield float to put the "Add role" button next to + * the input textfield. + */ +.user-admin-roles { + .form-item-name { + float: right; + margin-left: 1em; + margin-right: 0; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/user/user.admin.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/user/user.admin.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,34 @@ +/** + * @file + * Administrative styling for the user module. + */ +/** + * User Permissions Page + */ +.user-admin-permissions { + .module { + font-weight: bold; + } + .permission { + padding-left: 1.5em; /* LTR */ + } + .form-item { + white-space: normal; + } +} + +/** + * User Roles Page + * + * Override default textfield float to put the "Add role" button next to + * the input textfield. + */ +.user-admin-roles { + .edit-name { + clear: both; + } + .form-item-name { + float: left; /* LTR */ + margin-right: 1em; /* LTR */ + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/user/user.base.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/user/user.base.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,7 @@ +/** + * @file + * Base styles for the user module. + */ +div.password-confirm { + visibility: hidden; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/user/user.theme-rtl.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/user/user.theme-rtl.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,33 @@ +/** + * @file + * Right to left theme styling for the user module. + */ +/** + * Password Strength Indicator. + */ +.password-strength { + float: left; +} +.password-strength-title { + float: right; +} +.password-strength-text { + float: left; +} + +/** + * Password Confirm. + */ +.password-confirm { + float: left; +} + +/* + * User Profile + * + * Generated by user.module but used by profile.module. + */ +.profile .user-picture { + float: left; + margin: 0 0 1em 1em; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/modules/user/user.theme.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/modules/user/user.theme.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,91 @@ +/** + * @file + * Theme styling for the user module. + */ +/** + * Password Strength Indicator. + */ +.password-strength { + float: right; /* LTR */ + margin-top: 1.2em; + width: 17em; +} +.password-strength-title { + float: left; /* LTR */ +} +.password-strength-text { + float: right; /* LTR */ + font-weight: bold; +} +.password-indicator { + clear: both; + height: 0.3em; + width: 100%; + background-color: #C4C4C4; + + .indicator { + height: 100%; + width: 0%; + background-color: #47C965; + } +} + +/** + * Password Confirm. + */ +div.password-confirm { + float: right; /* LTR */ + clear: both; + width: 17em; + margin-top: 1.5em; +} + +/** + * Password Confirm Inputs. + */ +.form-type-password-confirm input { + width: 16em; +} + +/** + * Password Suggestions. + */ +.password-suggestions { + margin: 0.7em 0; + padding: 0.2em 0.5em; + border: 1px solid #B4B4B4; +} + + +/* + * User Profile + */ +.user-profile-item__label { + font-weight: bold; +} + + + +/* Generated by user.module but used by profile.module. */ +.profile { + clear: both; + margin: 1em 0; + + .user-picture { + float: right; /* LTR */ + margin: 0 1em 1em 0; /* LTR */ + } + h3 { + border-bottom: 1px solid #ccc; + } + dl { + margin: 0 0 1.5em 0; + } + dt { + margin: 0 0 0.2em 0; + font-weight: bold; + } + dd { + margin: 0 0 1em 0; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/omega.admin.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/omega.admin.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,63 @@ +.form-item.form-item-omega-conditional-comments-html-options, +.form-item.form-item-omega-viewport-widget-minimal, +.omega-settings-container { + border: 1px solid #ccc; + margin-left: 18px; + margin-bottom: 12px; + padding: 9px 18px; + background-color: #f2f2f2; +} + +.fieldset-description { + margin-bottom: 15px; +} + +div.vertical-tabs .vertical-tabs-panes .vertical-tabs-pane fieldset { + border: 1px solid #CCC; + padding: 2.5em 0 0 0; + margin: 1em 0; + + legend { + display: block; + } +} + +.omega-assets-missing-files { + color: #8c2e0b; + margin: 1em 0 1em 1.5em; + + h3 { + font-size: .9em; + text-transform: uppercase; + margin-bottom: 0; + } +} + +.omega-layout-selection-wrapper { + margin-bottom: 20px; + min-height: 75px; + position: relative; + + .form-item { + label.option, + div.description { + padding-left: 80px; + } + } + + img { + height: 75px; + width: 64px; + position: absolute; + top: 8px; + margin-left: 1.5em; + } +} + +.form-item.form-item-omega-requirements { + border: 1px solid #ed541d; + color: #8c2e0b; + background-color: #fef5f1; + margin: 6px 0 16px; + padding: 10px; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/omega.development.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/omega.development.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,37 @@ +@import "rgbapng"; +@import "compass"; + +.omega-browser-width { + @include border-radius(5px); + @include rgba-background(rgba(0, 0, 0, 0.75)); + z-index: 1000; + position: fixed; + bottom: 0; + right: 0; + font-family: 'Lucida Grande', 'Lucida Sans Unicode', sans-serif; + font-size: 13px; + color: #fff; + max-width: 100%; + margin: 5px; + padding: 5px 10px; +} + +.region--debug { + @include rgba-background(rgba(0, 0, 0, 0.1)); + position: relative; + min-height: 29px; + outline: 1px dashed #ccc; + + &:before { + @include border-radius(3px); + @include rgba-background(rgba(#077dc3, 0.75)); + font-family: 'Lucida Grande', 'Lucida Sans Unicode', sans-serif; + font-size: 11px; + z-index: 50; + position: absolute; + right: 5px; + top: 5px; + padding: 3px 6px; + color: #fff; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/sass/omega.messages.scss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/sass/omega.messages.scss Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,24 @@ +@import "compass"; + +// Use the default message layout. +div.messages { + position: relative; +} + +.close-message { + @include single-text-shadow(none); + position: absolute; + right: .4em; + top: -.2em; + text-decoration: none; + color: rgba(0, 0, 0, .3); + + &:before { + font-size: 1.4em; + content: "×"; + } + + &:hover, &:focus, &:active { + color: #000; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/screenshot.png Binary file sites/all/themes/omega/omega/screenshot.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/.bowerrc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/.bowerrc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,3 @@ +{ + "directory" : "libraries" +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/.gitignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/.gitignore Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,5 @@ +# Ignore the node modules folder (created by 'npm install'). +node_modules + +# We absolutely don't want to have the .sass-cache in git. +.sass-cache diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/.jshintrc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/.jshintrc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,24 @@ +{ + "browser": true, + "bitwise": true, + "devel": true, + "curly": true, + "eqeqeq": true, + "forin": true, + "immed": true, + "indent": 2, + "jquery": true, + "latedef": true, + "newcap": true, + "noarg": true, + "quotmark": true, + "regexp": true, + "undef": true, + "unused": true, + "trailing": true, + "smarttabs": true, + "predef": [ + "Drupal", + "Modernizr" + ] +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/.ruby-gemset --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/.ruby-gemset Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1 @@ +omega.{{ THEME }} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/.ruby-version --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/.ruby-version Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1 @@ +1.9.3 diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/Gemfile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/Gemfile Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,33 @@ +source 'https://rubygems.org' + +group :development do + + # Sass, Compass and extensions. + gem 'sass' # Sass. + gem 'sass-globbing' # Import Sass files based on globbing pattern. + gem 'compass' # Framework built on Sass. + gem 'compass-validator' # So you can `compass validate`. + gem 'compass-normalize' # Compass version of normalize.css. + gem 'compass-rgbapng' # Turns rgba() into .png's for backwards compatibility. + gem 'susy' # Susy grid framework. + gem 'singularitygs' # Alternative to the Susy grid framework. + gem 'toolkit' # Compass utility from the fabulous Snugug. + gem 'breakpoint' # Manages CSS media queries. + gem 'oily_png' # Faster Compass sprite generation. + gem 'css_parser' # Helps `compass stats` output statistics. + + # Guard + gem 'guard' # Guard event handler. + gem 'guard-compass' # Compile on sass/scss change. + gem 'guard-shell' # Run shell commands. + gem 'guard-livereload' # Browser reload. + gem 'yajl-ruby' # Faster JSON with LiveReload in the browser. + + # Dependency to prevent polling. Setup for multiple OS environments. + # Optionally remove the lines not specific to your OS. + # https://github.com/guard/guard#efficient-filesystem-handling + gem 'rb-inotify', '~> 0.9', :require => false # Linux + gem 'rb-fsevent', :require => false # Mac OSX + gem 'rb-fchange', :require => false # Windows + +end diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/Gruntfile.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/Gruntfile.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,111 @@ +'use strict'; + +module.exports = function (grunt) { + + grunt.initConfig({ + watch: { + options: { + livereload: true + }, + sass: { + files: ['sass/{,**/}*.{scss,sass}'], + tasks: ['compass:dev'], + options: { + livereload: false + } + }, + registry: { + files: ['*.info', '{,**}/*.{php,inc}'], + tasks: ['shell'], + options: { + livereload: false + } + }, + images: { + files: ['images/**'] + }, + css: { + files: ['css/{,**/}*.css'] + }, + js: { + files: ['js/{,**/}*.js', '!js/{,**/}*.min.js'], + tasks: ['jshint', 'uglify:dev'] + } + }, + + shell: { + all: { + command: 'drush cache-clear theme-registry' + } + }, + + compass: { + options: { + config: 'config.rb', + bundleExec: true + }, + dev: { + options: { + environment: 'development', + force: true + } + }, + dist: { + options: { + environment: 'production', + force: true + } + } + }, + + jshint: { + options: { + jshintrc: '.jshintrc' + }, + all: ['js/{,**/}*.js', '!js/{,**/}*.min.js'] + }, + + uglify: { + dev: { + options: { + mangle: false, + compress: false, + beautify: true + }, + files: [{ + expand: true, + cwd: 'js', + src: ['**/*.js', '!**/*.min.js'], + dest: 'js', + ext: '.min.js' + }] + }, + dist: { + options: { + mangle: true, + compress: true + }, + files: [{ + expand: true, + cwd: 'js', + src: ['**/*.js', '!**/*.min.js'], + dest: 'js', + ext: '.min.js' + }] + } + } + }); + + grunt.loadNpmTasks('grunt-contrib-watch'); + grunt.loadNpmTasks('grunt-contrib-compass'); + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-contrib-uglify'); + grunt.loadNpmTasks('grunt-shell'); + + grunt.registerTask('build', [ + 'uglify:dist', + 'compass:dist', + 'jshint' + ]); + +}; diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/Guardfile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/Guardfile Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,33 @@ +notification :off + +group :development do + + # Only run Compass if we have a config.rb file in place. + if File.exists?("config.rb") + # Compile on start. + puts `compass compile --time --quiet` + + # https://github.com/guard/guard-compass + guard :compass do + watch(%r{.+\.s[ac]ss$}) + end + end + + ## Uncomment this if you wish to clear the theme registry every time you + ## change one of the relevant theme files. + #guard :shell do + # puts 'Monitoring theme files.' + # + # watch(%r{.+\.(php|inc|info)$}) { |m| + # puts 'Change detected: ' + m[0] + # `drush cache-clear theme-registry` + # puts 'Cleared theme registry.' + # } + #end + + # https://github.com/guard/guard-livereload. + guard :livereload do + watch(%r{.+\.(css|js)$}) + end + +end diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/README.txt Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1 @@ +Fill me. diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/basic.starterkit.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/basic.starterkit.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,19 @@ +name = Basic +description = Provides a simple Sass setup. +screenshot = screenshot.png +engine = phptemplate +core = 7.x + +; Styles +stylesheets[all][] = css/{{ THEME }}.normalize.css +stylesheets[all][] = css/{{ THEME }}.styles.css + +; Regions +regions[header] = Header +regions[navigation] = Navigation +regions[highlighted] = Highlighted +regions[help] = Help +regions[content] = Content +regions[sidebar_first] = First Sidebar +regions[sidebar_second] = Second Sidebar +regions[footer] = Footer diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/bower.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/bower.json Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,11 @@ +{ + "name": "{{ THEME }}", + "version": "1.0.0", + "dependencies": { + "respond": "fubhy/respond", + "selectivizr": "fubhy/selectivizr", + "html5shiv": "fubhy/html5shiv", + "matchmedia": "fubhy/matchmedia", + "pie": "fubhy/pie" + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/config.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/config.rb Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,48 @@ +## +## This file is only needed for Compass/Sass integration. If you are not using +## Compass, you may safely ignore or delete this file. +## +## If you'd like to learn more about Sass and Compass, see the sass/README.txt +## file for more information. +## + +# Default to development if environment is not set. +saved = environment +if (environment.nil?) + environment = :development +else + environment = saved +end + +# Location of the theme's resources. +css_dir = "css" +sass_dir = "sass" +images_dir = "images" +generated_images_dir = images_dir + "/generated" +javascripts_dir = "js" + +# Require any additional compass plugins installed on your system. +require 'compass-normalize' +require 'rgbapng' +require 'toolkit' +require 'susy' +require 'sass-globbing' + +## +## You probably don't need to edit anything below this. +## + +# You can select your preferred output style here (:expanded, :nested, :compact +# or :compressed). +output_style = (environment == :production) ? :expanded : :nested + +# To enable relative paths to assets via compass helper functions. Since Drupal +# themes can be installed in multiple locations, we don't need to worry about +# the absolute path to the theme from the server omega. +relative_assets = true + +# Conditionally enable line comments when in development mode. +line_comments = (environment == :production) ? false : true + +# Output debugging info in development mode. +sass_options = (environment == :production) ? {} : {:debug_info => true} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/css/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/css/README.txt Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1 @@ +Fill me. diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/css/{{ THEME }}.normalize.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/css/{{ THEME }}.normalize.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,328 @@ +/******************************************************************************* + * _utils.scss + * + * Sass offers come very useful features, these include variables functions and + * mixins. Extensions such as Compass and Susy can also be used to provide extra + * functions and mixins to be used throughout the theme. This file acts as a + * single place for defining these things, which can then be accessed by + * importing _utils.scss where required. The following should be defined in this + * file: + * - Custom Sass mixins for the theme. + * - Custom Sass functions for the theme. + * - Overriding the default variables provided by extensions such as Compass. + * - Defining new variables for: + * - Colors. + * - Font sizes and families. + * - Layout and grid sizing. + ******************************************************************************/ +/*! normalize.css v1.1.0 | MIT License | git.io/normalize */ +/*! normalize.css v1.1.0 | HTML5 Display Definitions | MIT License | git.io/normalize */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section, +summary { + display: block; +} + +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1; +} + +audio:not([controls]) { + display: none; + height: 0; +} + +[hidden] { + display: none; +} + +/*! normalize.css v1.1.0 | Base | MIT License | git.io/normalize */ +html { + font-size: 100%; + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +html, +button, +input, +select, +textarea { + font-family: sans-serif; +} + +body { + margin: 0; +} + +/*! normalize.css v1.1.0 | Links | MIT License | git.io/normalize */ +a:focus { + outline: thin dotted; +} + +a:active, +a:hover { + outline: 0; +} + +/*! normalize.css v1.1.0 | Typography | MIT License | git.io/normalize */ +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +h2 { + font-size: 1.5em; + margin: 0.83em 0; +} + +h3 { + font-size: 1.17em; + margin: 1em 0; +} + +h4 { + font-size: 1em; + margin: 1.33em 0; +} + +h5 { + font-size: 0.83em; + margin: 1.67em 0; +} + +h6 { + font-size: 0.67em; + margin: 2.33em 0; +} + +abbr[title] { + border-bottom: 1px dotted; +} + +b, +strong { + font-weight: bold; +} + +blockquote { + margin: 1em 40px; +} + +dfn { + font-style: italic; +} + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +mark { + background: #ff0; + color: #000; +} + +p, +pre { + margin: 1em 0; +} + +code, +kbd, +pre, +samp { + font-family: monospace, serif; + _font-family: 'courier new', monospace; + font-size: 1em; +} + +pre { + white-space: pre; + white-space: pre-wrap; + word-wrap: break-word; +} + +q { + quotes: "\201C" "\201D" "\2018" "\2019"; +} + +q { + quotes: none; +} + +q:before, +q:after { + content: ''; + content: none; +} + +small { + font-size: 80%; +} + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +dl, +menu, +ol, +ul { + margin: 1em 0; +} + +dd { + margin: 0 0 0 40px; +} + +menu, +ol, +ul { + padding: 0 0 0 40px; +} + +nav ul, +nav ol { + list-style: none; + list-style-image: none; +} + +/*! normalize.css v1.1.0 | Embedded Content | MIT License | git.io/normalize */ +img { + border: 0; + -ms-interpolation-mode: bicubic; +} + +svg:not(:root) { + overflow: hidden; +} + +/*! normalize.css v1.1.0 | Figures | MIT License | git.io/normalize */ +figure { + margin: 0; +} + +/*! normalize.css v1.1.0 | Forms | MIT License | git.io/normalize */ +form { + margin: 0; +} + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +legend { + border: 0; + padding: 0; + white-space: normal; + *margin-left: -7px; +} + +button, +input, +select, +textarea { + font-family: inherit; + font-size: 100%; + margin: 0; + vertical-align: baseline; + *vertical-align: middle; +} + +button, +input { + line-height: normal; +} + +button, +select { + text-transform: none; +} + +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; + *overflow: visible; +} + +button[disabled], +html input[disabled] { + cursor: default; +} + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + padding: 0; + *height: 13px; + *width: 13px; +} + +input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +textarea { + overflow: auto; + vertical-align: top; +} + +/*! normalize.css v1.1.0 | Tables | MIT License | git.io/normalize */ +table { + border-collapse: collapse; + border-spacing: 0; +} + +*, *:after, *:before { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + *behavior: url('../behaviors/box-sizing/boxsizing.php'); +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/css/{{ THEME }}.styles.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/css/{{ THEME }}.styles.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,88 @@ +/******************************************************************************* + * style.scss + * + * This file shouldn't directly contain any SCSS code, instead it only serves to + * combine the SCSS contained in other Sass partials through @import directives. + * + * BASE............Styling for common HTML and Drupal elements. + * LAYOUT..........Styles for the page structure that contain components. + * COMPONENTS......Components, their modifiers and sub-components. + ******************************************************************************/ +/******************************************************************************* + * _utils.scss + * + * Sass offers come very useful features, these include variables functions and + * mixins. Extensions such as Compass and Susy can also be used to provide extra + * functions and mixins to be used throughout the theme. This file acts as a + * single place for defining these things, which can then be accessed by + * importing _utils.scss where required. The following should be defined in this + * file: + * - Custom Sass mixins for the theme. + * - Custom Sass functions for the theme. + * - Overriding the default variables provided by extensions such as Compass. + * - Defining new variables for: + * - Colors. + * - Font sizes and families. + * - Layout and grid sizing. + ******************************************************************************/ +/******************************************************************************* + * _base.scss + + * Base styles define the default look for HTML and common Drupal elements. + * + * These rules will generally be made up of element selectors for HTML elements + * such as headings, paragraphs and lists. Common Drupal elements such as form + * items, collapsible fieldsets and messages should be included in this partial. + * + * The styleguide module (http://drupal.org/project/styleguide) gives you a good + * overview of Drupals common elements for styling. By setting a solid baseline + * before adding any more specific customisations you ensure that as any new + * features are added they will be correctly styled without any extra work. + ******************************************************************************/ +/******************************************************************************* + * _layout.scss + * + * The layout of the major regions (usually, but not necessarily Drupal regions) + * that components will be placed within. Layout styles for the theme's + * components should not be placed here and should instead be kept with the + * relevant SCSS for that component. + ******************************************************************************/ +/******************************************************************************* + * _components.scss + * + * Imports more partials that contain full components (modules in SMACSS), their + * sub-components and modifiers. + * + * Components are discrete parts of your page that should sit within the regions + * of your layouts. You should try to abstract your components as much as + * possible to promote reuse throughout the theme. Components should be flexible + * enough to respond to any width and should never rely on context + * (e.g. .sidebar-first .component) for styling. This allows modules to be + * placed throughout the theme with no risk of them breaking. + * + * If you find you need to change the look of a component depending on it's + * context you should avoid using context based classes at all costs. Instead it + * is better to add another "modifier" class to the component to alter the + * styling. Again, this promotes reuse. + * + * Sub-components are the individual parts that make up a component. As a + * general rule, adding a class to target a sub-component is a much better + * option than using descendant selectors or element selectors. In many cases + * sub-components can be made more reusable by making them components in their + * own right, so they can then be used within other components. + * + * Almost everything that doesn't belong in base should be made a component. + * Here's some common examples throughout Drupal: + * + * - Blocks + * - Content Types - For example, you may have a generic node component that + * contains sub-components for the submitted by line and links. Specific + * components can then be created for each content type to style the + * specifics of each. Finally, by using entity view modes you can easily + * apply modifications based on the .node-[view-mode] classes. + * - Forms - For instance the log in form. + * - Views - Each views output style could be made into a component, the content + * of each row should be provided my a view mode styled by it's component + * CSS. Exposed filter forms, views pagers and other views elements are + * also good candidates for components. + ******************************************************************************/ diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/images/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/images/README.txt Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1 @@ +Fill me. diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/js/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/js/README.txt Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1 @@ +Fill me. diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/js/example.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/js/example.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,60 @@ +(function ($) { + + /** + * The recommended way for producing HTML markup through JavaScript is to write + * theming functions. These are similiar to the theming functions that you might + * know from 'phptemplate' (the default PHP templating engine used by most + * Drupal themes including Omega). JavaScript theme functions accept arguments + * and can be overriden by sub-themes. + * + * In most cases, there is no good reason to NOT wrap your markup producing + * JavaScript in a theme function. + */ + Drupal.theme.prototype.{{ THEME }}ExampleButton = function (path, title) { + // Create an anchor element with jQuery. + return $('' + title + ''); + }; + + /** + * Behaviors are Drupal's way of applying JavaScript to a page. The advantage + * of behaviors over simIn short, the advantage of Behaviors over a simple + * document.ready() lies in how it interacts with content loaded through Ajax. + * Opposed to the 'document.ready()' event which is only fired once when the + * page is initially loaded, behaviors get re-executed whenever something is + * added to the page through Ajax. + * + * You can attach as many behaviors as you wish. In fact, instead of overloading + * a single behavior with multiple, completely unrelated tasks you should create + * a separate behavior for every separate task. + * + * In most cases, there is no good reason to NOT wrap your JavaScript code in a + * behavior. + * + * @param context + * The context for which the behavior is being executed. This is either the + * full page or a piece of HTML that was just added through Ajax. + * @param settings + * An array of settings (added through drupal_add_js()). Instead of accessing + * Drupal.settings directly you should use this because of potential + * modifications made by the Ajax callback that also produced 'context'. + */ + Drupal.behaviors.{{ THEME }}ExampleBehavior = { + attach: function (context, settings) { + // By using the 'context' variable we make sure that our code only runs on + // the relevant HTML. Furthermore, by using jQuery.once() we make sure that + // we don't run the same piece of code for an HTML snippet that we already + // processed previously. By using .once('foo') all processed elements will + // get tagged with a 'foo-processed' class, causing all future invocations + // of this behavior to ignore them. + $('.some-selector', context).once('foo', function () { + // Now, we are invoking the previously declared theme function using two + // settings as arguments. + var $anchor = Drupal.theme('{{ THEME }}ExampleButton', settings.myExampleLinkPath, settings.myExampleLinkTitle); + + // The anchor is then appended to the current element. + $anchor.appendTo(this); + }); + } + }; + +})(jQuery); diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/libraries.make --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/libraries.make Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,39 @@ +; ############################################################################## +; +; This is a Drush make file that will automatically download the front-end +; libraries used by Omega. Alternatively, you can use Bower (http://bower.io) to +; accomplish this. +; +; Running Drush make in your sub-theme will cause the libraries to be downloaded +; into your theme. If you want to download them into Omega directly to make them +; available to all of your sub-themes (if you have multiple) then you should +; instead run omega.make from the Omega theme directory. +; +; To run this file with 'drush make' you first have to navigate into your theme. +; Normally, this would be 'sites/all/themes/{{ THEME }}'. +; +; $ cd sites/all/themes/{{ THEME }} +; +; Now you can invoke 'drush make' using the following command: +; +; $ drush make libraries.make --no-core --contrib-destination=. +; +; ############################################################################## + +core = 7.x +api = 2 + +libraries[selectivizr][download][type] = "file" +libraries[selectivizr][download][url] = "https://github.com/fubhy/selectivizr/archive/master.zip" + +libraries[html5shiv][download][type] = "file" +libraries[html5shiv][download][url] = "https://github.com/fubhy/html5shiv/archive/master.zip" + +libraries[respond][download][type] = "file" +libraries[respond][download][url] = "https://github.com/fubhy/respond/archive/master.zip" + +libraries[matchmedia][download][type] = "file" +libraries[matchmedia][download][url] = "https://github.com/fubhy/matchmedia/archive/master.zip" + +libraries[pie][download][type] = "file" +libraries[pie][download][url] = "https://github.com/fubhy/pie/archive/master.zip" diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/logo.png Binary file sites/all/themes/omega/omega/starterkits/basic/logo.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/package.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/package.json Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,16 @@ +{ + "name": "{{ THEME }}", + "version": "1.0.0", + "dependencies": {}, + "devDependencies": { + "grunt": "~0.4.0", + "grunt-contrib-watch": "~0.4.3", + "grunt-contrib-compass": "~0.2.0", + "grunt-contrib-jshint": "~0.1.1", + "grunt-contrib-uglify": "~0.2.0", + "grunt-shell": "~0.3.1" + }, + "engines": { + "node": ">=0.8.0" + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/preprocess/README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/preprocess/README.md Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,23 @@ +# Defining preprocess hooks +Rather than placing your preprocess hooks directly in the template.php file you can manage them in automatically discovered and lazy-loaded include files. It is even possible to organize them in sub-folders. This feature greatly improves the maintainability of large themes that would otherwise contain hundreds of lines of unrelated code in your template.php file. + +The include files have to follow a certain naming pattern (HOOK.preprocess.inc) for them to be automatically discovered: + +* THEMENAME_preprocess_html() = html.preprocess.inc +* THEMENAME_preprocess_page() = page.preprocess.inc +* THEMENAME_preprocess_node() = node.preprocess.inc +* THEMENAME_preprocess_comment() = comment.preprocess.inc +* THEMENAME_preprocess_region() = region.preprocess.inc + +As with template files, you should replace underscores from the hook names with hyphens: + +* THEMENAME_preprocess_comment_wrapper() = comment-wrapper.preprocess.inc +* THEMENAME_preprocess_html_tag() = html-tag.preprocess.inc + +Inside of each of these files you define the preprocess hook just as you would otherwise do in your template.php file: + +``` +function THEMENAME_preprocess_HOOK(&$variables) { + // Your code here. +} +``` diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/basic/preprocess/page.preprocess.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/basic/preprocess/page.preprocess.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,9 @@ + 0.9', :require => false # Linux + gem 'rb-fsevent', :require => false # Mac OSX + gem 'rb-fchange', :require => false # Windows + +end diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/extended/Gruntfile.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/extended/Gruntfile.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,111 @@ +'use strict'; + +module.exports = function (grunt) { + + grunt.initConfig({ + watch: { + options: { + livereload: true + }, + sass: { + files: ['sass/{,**/}*.{scss,sass}'], + tasks: ['compass:dev'], + options: { + livereload: false + } + }, + registry: { + files: ['*.info', '{,**}/*.{php,inc}'], + tasks: ['shell'], + options: { + livereload: false + } + }, + images: { + files: ['images/**'] + }, + css: { + files: ['css/{,**/}*.css'] + }, + js: { + files: ['js/{,**/}*.js', '!js/{,**/}*.min.js'], + tasks: ['jshint', 'uglify:dev'] + } + }, + + shell: { + all: { + command: 'drush cache-clear theme-registry' + } + }, + + compass: { + options: { + config: 'config.rb', + bundleExec: true + }, + dev: { + options: { + environment: 'development', + force: true + } + }, + dist: { + options: { + environment: 'production', + force: true + } + } + }, + + jshint: { + options: { + jshintrc: '.jshintrc' + }, + all: ['js/{,**/}*.js', '!js/{,**/}*.min.js'] + }, + + uglify: { + dev: { + options: { + mangle: false, + compress: false, + beautify: true + }, + files: [{ + expand: true, + cwd: 'js', + src: ['**/*.js', '!**/*.min.js'], + dest: 'js', + ext: '.min.js' + }] + }, + dist: { + options: { + mangle: true, + compress: true + }, + files: [{ + expand: true, + cwd: 'js', + src: ['**/*.js', '!**/*.min.js'], + dest: 'js', + ext: '.min.js' + }] + } + } + }); + + grunt.loadNpmTasks('grunt-contrib-watch'); + grunt.loadNpmTasks('grunt-contrib-compass'); + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-contrib-uglify'); + grunt.loadNpmTasks('grunt-shell'); + + grunt.registerTask('build', [ + 'uglify:dist', + 'compass:dist', + 'jshint' + ]); + +}; diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/extended/Guardfile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/extended/Guardfile Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,33 @@ +notification :off + +group :development do + + # Only run Compass if we have a config.rb file in place. + if File.exists?("config.rb") + # Compile on start. + puts `compass compile --time --quiet` + + # https://github.com/guard/guard-compass + guard :compass do + watch(%r{.+\.s[ac]ss$}) + end + end + + ## Uncomment this if you wish to clear the theme registry every time you + ## change one of the relevant theme files. + #guard :shell do + # puts 'Monitoring theme files.' + # + # watch(%r{.+\.(php|inc|info)$}) { |m| + # puts 'Change detected: ' + m[0] + # `drush cache-clear theme-registry` + # puts 'Cleared theme registry.' + # } + #end + + # https://github.com/guard/guard-livereload. + guard :livereload do + watch(%r{.+\.(css|js)$}) + end + +end diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/extended/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/extended/README.txt Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1 @@ +Fill me. diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/extended/bower.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/extended/bower.json Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,11 @@ +{ + "name": "{{ THEME }}", + "version": "1.0.0", + "dependencies": { + "respond": "fubhy/respond", + "selectivizr": "fubhy/selectivizr", + "html5shiv": "fubhy/html5shiv", + "matchmedia": "fubhy/matchmedia", + "pie": "fubhy/pie" + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/extended/config.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/extended/config.rb Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,51 @@ +## +## This file is only needed for Compass/Sass integration. If you are not using +## Compass, you may safely ignore or delete this file. +## +## If you'd like to learn more about Sass and Compass, see the sass/README.txt +## file for more information. +## + +# Default to development if environment is not set. +saved = environment +if (environment.nil?) + environment = :development +else + environment = saved +end + +# Location of the theme's resources. +css_dir = "css" +sass_dir = "sass" +images_dir = "images" +generated_images_dir = images_dir + "/generated" +javascripts_dir = "js" + +# Require any additional compass plugins installed on your system. +require 'compass-normalize' +require 'rgbapng' +require 'toolkit' +require 'susy' +require 'sass-globbing' + +## +## You probably don't need to edit anything below this. +## + +# You can select your preferred output style here (:expanded, :nested, :compact +# or :compressed). +output_style = (environment == :production) ? :expanded : :nested + +# To enable relative paths to assets via compass helper functions. Since Drupal +# themes can be installed in multiple locations, we don't need to worry about +# the absolute path to the theme from the server omega. +relative_assets = true + +# Conditionally enable line comments when in development mode. +line_comments = (environment == :production) ? false : true + +# Output debugging info in development mode. +sass_options = (environment == :production) ? {} : {:debug_info => true} + +# Add the 'sass' directory itself as an import path to ease imports. +add_import_path 'sass' diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/extended/css/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/extended/css/README.txt Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1 @@ +Fill me. diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/extended/css/{{ THEME }}.hacks.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/extended/css/{{ THEME }}.hacks.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,10 @@ +@media all and (max-width: 800px) { + #toolbar, #admin-menu { + display: none; + } + + html body.toolbar, html body.admin-menu { + padding-top: 0 !important; + margin-top: 0 !important; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/extended/css/{{ THEME }}.no-query.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/extended/css/{{ THEME }}.no-query.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,5 @@ +img, media { + max-width: 100%; +} + +/* No files to import found in partials/components/**\/* */ diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/extended/css/{{ THEME }}.normalize.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/extended/css/{{ THEME }}.normalize.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,310 @@ +/* normalize.css v1.1.0 | MIT License | git.io/normalize */ +/* normalize.css v1.1.0 | HTML5 Display Definitions | MIT License | git.io/normalize */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section, +summary { + display: block; +} + +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1; +} + +audio:not([controls]) { + display: none; + height: 0; +} + +[hidden] { + display: none; +} + +/* normalize.css v1.1.0 | Base | MIT License | git.io/normalize */ +html { + font-size: 100%; + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +html, +button, +input, +select, +textarea { + font-family: sans-serif; +} + +body { + margin: 0; +} + +/* normalize.css v1.1.0 | Links | MIT License | git.io/normalize */ +a:focus { + outline: thin dotted; +} + +a:active, +a:hover { + outline: 0; +} + +/* normalize.css v1.1.0 | Typography | MIT License | git.io/normalize */ +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +h2 { + font-size: 1.5em; + margin: 0.83em 0; +} + +h3 { + font-size: 1.17em; + margin: 1em 0; +} + +h4 { + font-size: 1em; + margin: 1.33em 0; +} + +h5 { + font-size: 0.83em; + margin: 1.67em 0; +} + +h6 { + font-size: 0.67em; + margin: 2.33em 0; +} + +abbr[title] { + border-bottom: 1px dotted; +} + +b, +strong { + font-weight: bold; +} + +blockquote { + margin: 1em 40px; +} + +dfn { + font-style: italic; +} + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +mark { + background: #ff0; + color: #000; +} + +p, +pre { + margin: 1em 0; +} + +code, +kbd, +pre, +samp { + font-family: monospace, serif; + font-size: 1em; +} + +pre { + white-space: pre; + white-space: pre-wrap; + word-wrap: break-word; +} + +q { + quotes: "\201C" "\201D" "\2018" "\2019"; +} + +q { + quotes: none; +} + +q:before, +q:after { + content: ''; + content: none; +} + +small { + font-size: 80%; +} + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +dl, +menu, +ol, +ul { + margin: 1em 0; +} + +dd { + margin: 0 0 0 40px; +} + +menu, +ol, +ul { + padding: 0 0 0 40px; +} + +nav ul, +nav ol { + list-style: none; + list-style-image: none; +} + +/* normalize.css v1.1.0 | Embedded Content | MIT License | git.io/normalize */ +img { + border: 0; + -ms-interpolation-mode: bicubic; +} + +svg:not(:root) { + overflow: hidden; +} + +/* normalize.css v1.1.0 | Figures | MIT License | git.io/normalize */ +figure { + margin: 0; +} + +/* normalize.css v1.1.0 | Forms | MIT License | git.io/normalize */ +form { + margin: 0; +} + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +legend { + border: 0; + padding: 0; + white-space: normal; + *margin-left: -7px; +} + +button, +input, +select, +textarea { + font-family: inherit; + font-size: 100%; + margin: 0; + vertical-align: baseline; + *vertical-align: middle; +} + +button, +input { + line-height: normal; +} + +button, +select { + text-transform: none; +} + +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; + *overflow: visible; +} + +button[disabled], +html input[disabled] { + cursor: default; +} + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + padding: 0; + *height: 13px; + *width: 13px; +} + +input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +textarea { + overflow: auto; + vertical-align: top; +} + +/* normalize.css v1.1.0 | Tables | MIT License | git.io/normalize */ +table { + border-collapse: collapse; + border-spacing: 0; +} + +*, *:after, *:before { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + *behavior: url('../behaviors/box-sizing/boxsizing.php'); +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/extended/css/{{ THEME }}.styles.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/extended/css/{{ THEME }}.styles.css Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,5 @@ +img, media { + max-width: 100%; +} + +/* No files to import found in partials/components/**\/* */ diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/extended/extended.starterkit.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/extended/extended.starterkit.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,21 @@ +name = Extended +description = Comes with a well organized Sass setup with heavy use of partials. +screenshot = screenshot.png +engine = phptemplate +core = 7.x + +; Styles +stylesheets[all][] = css/{{ THEME }}.normalize.css +stylesheets[all][] = css/{{ THEME }}.hacks.css +stylesheets[all][] = css/{{ THEME }}.styles.css +stylesheets[all][] = css/{{ THEME }}.no-query.css + +; Regions +regions[header] = Header +regions[navigation] = Navigation +regions[highlighted] = Highlighted +regions[help] = Help +regions[content] = Content +regions[sidebar_first] = First Sidebar +regions[sidebar_second] = Second Sidebar +regions[footer] = Footer diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/extended/images/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/extended/images/README.txt Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1 @@ +Fill me. diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/extended/js/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/extended/js/README.txt Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,1 @@ +Fill me. diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/extended/js/example.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/extended/js/example.js Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,60 @@ +(function ($) { + + /** + * The recommended way for producing HTML markup through JavaScript is to write + * theming functions. These are similiar to the theming functions that you might + * know from 'phptemplate' (the default PHP templating engine used by most + * Drupal themes including Omega). JavaScript theme functions accept arguments + * and can be overriden by sub-themes. + * + * In most cases, there is no good reason to NOT wrap your markup producing + * JavaScript in a theme function. + */ + Drupal.theme.prototype.{{ THEME }}ExampleButton = function (path, title) { + // Create an anchor element with jQuery. + return $('' + title + ''); + }; + + /** + * Behaviors are Drupal's way of applying JavaScript to a page. The advantage + * of behaviors over simIn short, the advantage of Behaviors over a simple + * document.ready() lies in how it interacts with content loaded through Ajax. + * Opposed to the 'document.ready()' event which is only fired once when the + * page is initially loaded, behaviors get re-executed whenever something is + * added to the page through Ajax. + * + * You can attach as many behaviors as you wish. In fact, instead of overloading + * a single behavior with multiple, completely unrelated tasks you should create + * a separate behavior for every separate task. + * + * In most cases, there is no good reason to NOT wrap your JavaScript code in a + * behavior. + * + * @param context + * The context for which the behavior is being executed. This is either the + * full page or a piece of HTML that was just added through Ajax. + * @param settings + * An array of settings (added through drupal_add_js()). Instead of accessing + * Drupal.settings directly you should use this because of potential + * modifications made by the Ajax callback that also produced 'context'. + */ + Drupal.behaviors.{{ THEME }}ExampleBehavior = { + attach: function (context, settings) { + // By using the 'context' variable we make sure that our code only runs on + // the relevant HTML. Furthermore, by using jQuery.once() we make sure that + // we don't run the same piece of code for an HTML snippet that we already + // processed previously. By using .once('foo') all processed elements will + // get tagged with a 'foo-processed' class, causing all future invocations + // of this behavior to ignore them. + $('.some-selector', context).once('foo', function () { + // Now, we are invoking the previously declared theme function using two + // settings as arguments. + var $anchor = Drupal.theme('{{ THEME }}ExampleButton', settings.myExampleLinkPath, settings.myExampleLinkTitle); + + // The anchor is then appended to the current element. + $anchor.appendTo(this); + }); + } + }; + +})(jQuery); diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/extended/libraries.make --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/extended/libraries.make Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,39 @@ +; ############################################################################## +; +; This is a Drush make file that will automatically download the front-end +; libraries used by Omega. Alternatively, you can use Bower (http://bower.io) to +; accomplish this. +; +; Running Drush make in your sub-theme will cause the libraries to be downloaded +; into your theme. If you want to download them into Omega directly to make them +; available to all of your sub-themes (if you have multiple) then you should +; instead run omega.make from the Omega theme directory. +; +; To run this file with 'drush make' you first have to navigate into your theme. +; Normally, this would be 'sites/all/themes/{{ THEME }}'. +; +; $ cd sites/all/themes/{{ THEME }} +; +; Now you can invoke 'drush make' using the following command: +; +; $ drush make libraries.make --no-core --contrib-destination=. +; +; ############################################################################## + +core = 7.x +api = 2 + +libraries[selectivizr][download][type] = "file" +libraries[selectivizr][download][url] = "https://github.com/fubhy/selectivizr/archive/master.zip" + +libraries[html5shiv][download][type] = "file" +libraries[html5shiv][download][url] = "https://github.com/fubhy/html5shiv/archive/master.zip" + +libraries[respond][download][type] = "file" +libraries[respond][download][url] = "https://github.com/fubhy/respond/archive/master.zip" + +libraries[matchmedia][download][type] = "file" +libraries[matchmedia][download][url] = "https://github.com/fubhy/matchmedia/archive/master.zip" + +libraries[pie][download][type] = "file" +libraries[pie][download][url] = "https://github.com/fubhy/pie/archive/master.zip" diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/extended/logo.png Binary file sites/all/themes/omega/omega/starterkits/extended/logo.png has changed diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/extended/package.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/extended/package.json Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,16 @@ +{ + "name": "{{ THEME }}", + "version": "1.0.0", + "dependencies": {}, + "devDependencies": { + "grunt": "~0.4.0", + "grunt-contrib-watch": "~0.4.3", + "grunt-contrib-compass": "~0.2.0", + "grunt-contrib-jshint": "~0.1.1", + "grunt-contrib-uglify": "~0.2.0", + "grunt-shell": "~0.3.1" + }, + "engines": { + "node": ">=0.8.0" + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/extended/preprocess/README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/extended/preprocess/README.md Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,23 @@ +# Defining preprocess hooks +Rather than placing your preprocess hooks directly in the template.php file you can manage them in automatically discovered and lazy-loaded include files. It is even possible to organize them in sub-folders. This feature greatly improves the maintainability of large themes that would otherwise contain hundreds of lines of unrelated code in your template.php file. + +The include files have to follow a certain naming pattern (HOOK.preprocess.inc) for them to be automatically discovered: + +* THEMENAME_preprocess_html() = html.preprocess.inc +* THEMENAME_preprocess_page() = page.preprocess.inc +* THEMENAME_preprocess_node() = node.preprocess.inc +* THEMENAME_preprocess_comment() = comment.preprocess.inc +* THEMENAME_preprocess_region() = region.preprocess.inc + +As with template files, you should replace underscores from the hook names with hyphens: + +* THEMENAME_preprocess_comment_wrapper() = comment-wrapper.preprocess.inc +* THEMENAME_preprocess_html_tag() = html-tag.preprocess.inc + +Inside of each of these files you define the preprocess hook just as you would otherwise do in your template.php file: + +``` +function THEMENAME_preprocess_HOOK(&$variables) { + // Your code here. +} +``` diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/starterkits/extended/preprocess/page.preprocess.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/starterkits/extended/preprocess/page.preprocess.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,9 @@ + $info) { + if (omega_extension_enabled($extension) && ($file = $info['path'] . '/' . $extension . '.inc') && is_file($file)) { + require_once $file; + } +} + +/** + * Implements hook_element_info_alter(). + */ +function omega_element_info_alter(&$elements) { + $elements['scripts'] = array( + '#items' => array(), + '#pre_render' => array('omega_pre_render_scripts'), + '#group_callback' => 'omega_group_js', + '#aggregate_callback' => 'omega_aggregate_js', + ); +} + +/** + * Implements hook_css_alter(). + */ +function omega_css_alter(&$css) { + $omega = drupal_get_path('theme', 'omega'); + + // The CSS_SYSTEM aggregation group doesn't make any sense. Therefore, we are + // pre-pending it to the CSS_DEFAULT group. This has the same effect as giving + // it a separate (low-weighted) group but also allows it to be aggregated + // together with the rest of the CSS. + foreach ($css as &$item) { + if ($item['group'] == CSS_SYSTEM) { + $item['group'] = CSS_DEFAULT; + $item['weight'] = $item['weight'] - 100; + } + } + + // Clean up core and contrib module CSS. + $overrides = array( + 'aggregator' => array( + 'aggregator.css' => array( + 'theme' => 'aggregator.theme.css', + ), + 'aggregator-rtl.css' => array( + 'theme' => 'aggregator.theme-rtl.css', + ), + ), + 'block' => array( + 'block.css' => array( + 'admin' => 'block.admin.css', + 'demo' => 'block.demo.css', + ), + ), + 'book' => array( + 'book.css' => array( + 'theme' => 'book.theme.css', + 'admin' => 'book.admin.css', + ), + 'book-rtl.css' => array( + 'theme' => 'book.theme-rtl.css', + ), + ), + 'color' => array( + 'color.css' => array( + 'admin' => 'color.admin.css', + ), + 'color-rtl.css' => array( + 'admin' => 'color.admin-rtl.css', + ), + ), + 'comment' => array( + 'comment.css' => array( + 'theme' => 'comment.theme.css', + ), + 'comment-rtl.css' => array( + 'theme' => 'comment.theme-rtl.css', + ), + ), + 'contextual' => array( + 'contextual.css' => array( + 'base' => 'contextual.base.css', + 'theme' => 'contextual.theme.css', + ), + 'contextual-rtl.css' => array( + 'base' => 'contextual.base-rtl.css', + 'theme' => 'contextual.theme-rtl.css', + ), + ), + 'field' => array( + 'theme/field.css' => array( + 'theme' => 'field.theme.css', + ), + 'theme/field-rtl.css' => array( + 'theme' => 'field.theme-rtl.css', + ), + ), + 'field_ui' => array( + 'field_ui.css' => array( + 'admin' => 'field_ui.admin.css', + ), + 'field_ui-rtl.css' => array( + 'admin' => 'field_ui.admin-rtl.css', + ), + ), + 'file' => array( + 'file.css' => array( + 'theme' => 'file.theme.css', + ), + ), + 'filter' => array( + 'filter.css' => array( + 'theme' => 'filter.theme.css', + ), + ), + 'forum' => array( + 'forum.css' => array( + 'theme' => 'forum.theme.css', + ), + 'forum-rtl.css' => array( + 'theme' => 'forum.theme-rtl.css', + ), + ), + 'image' => array( + 'image.css' => array( + 'theme' => 'image.theme.css', + ), + 'image-rtl.css' => array( + 'theme' => 'image.theme-rtl.css', + ), + 'image.admin.css' => array( + 'admin' => 'image.admin.css', + ), + ), + 'locale' => array( + 'locale.css' => array( + 'admin' => 'locale.admin.css', + ), + 'locale-rtl.css' => array( + 'admin' => 'locale.admin-rtl.css', + ), + ), + 'openid' => array( + 'openid.css' => array( + 'base' => 'openid.base.css', + 'theme' => 'openid.theme.css', + ), + 'openid-rtl.css' => array( + 'base' => 'openid.base-rtl.css', + 'theme' => 'openid.theme-rtl.css', + ), + ), + 'poll' => array( + 'poll.css' => array( + 'admin' => 'poll.admin.css', + 'theme' => 'poll.theme.css', + ), + 'poll-rtl.css' => array( + 'theme' => 'poll.theme-rtl.css', + ), + ), + 'search' => array( + 'search.css' => array( + 'theme' => 'search.theme.css', + ), + 'search-rtl.css' => array( + 'theme' => 'search.theme-rtl.css', + ), + ), + 'system' => array( + 'system.base.css' => array( + 'base' => 'system.base.css', + ), + 'system.base-rtl.css' => array( + 'base' => 'system.base-rtl.css', + ), + 'system.theme.css' => array( + 'theme' => 'system.theme.css', + ), + 'system.theme-rtl.css' => array( + 'theme' => 'system.theme-rtl.css', + ), + 'system.admin.css' => array( + 'admin' => 'system.admin.css', + ), + 'system.admin-rtl.css' => array( + 'admin' => 'system.admin-rtl.css', + ), + 'system.menus.css' => array( + 'theme' => 'system.menus.theme.css', + ), + 'system.menus-rtl.css' => array( + 'theme' => 'system.menus.theme-rtl.css', + ), + 'system.messages.css' => array( + 'theme' => 'system.messages.theme.css', + ), + 'system.messages-rtl.css' => array( + 'theme' => 'system.messages.theme-rtl.css', + ), + ), + 'taxonomy' => array( + 'taxonomy.css' => array( + 'admin' => 'taxonomy.admin.css', + ), + ), + 'user' => array( + 'user.css' => array( + 'base' => 'user.base.css', + 'admin' => 'user.admin.css', + 'theme' => 'user.theme.css', + ), + 'user-rtl.css' => array( + 'admin' => 'user.admin-rtl.css', + 'theme' => 'user.theme-rtl.css', + ), + ), + ); + + // Check if we are on an admin page. Otherwise, we can skip admin CSS. + $path = current_path(); + $types = path_is_admin($path) ? array('base', 'theme', 'admin') : array('base', 'theme'); + // Add a special case for the block demo page. + $types = strpos($path, 'admin/structure/block/demo') === 0 ? array_merge($types, array('demo')) : $types; + + // Override module provided CSS with clean and modern alternatives provided + // by Omega. + foreach ($overrides as $module => $files) { + // We gathered the CSS files with paths relative to the providing module. + $path = drupal_get_path('module', $module); + + foreach ($files as $file => $items) { + if (isset($css[$path . '/' . $file])) { + // Keep a copy of the original file array so we can merge that with our + // overrides in order to keep the 'weight' and 'group' declarations. + $original = $css[$path . '/' . $file]; + unset($css[$path . '/' . $file]); + + // Omega 4.x tries to follow the pattern described in + // http://drupal.org/node/1089868 for declaring CSS files. Therefore, it + // may take more than a single file to override a .css file added by + // core. This gives us better granularity when overriding .css files + // in a sub-theme. + foreach ($types as $type) { + if (isset($items[$type])) { + $css[$omega . '/css/modules/' . $module . '/' . $items[$type]] = array( + 'data' => $omega . '/css/modules/' . $module . '/' . $items[$type], + ) + $original; + } + } + } + } + } + + // Exclude CSS files as declared in the theme settings. + if (omega_extension_enabled('assets') && $regex = omega_theme_get_setting('omega_css_exclude_regex')) { + // Make sure that RTL styles are excluded as well when a file name has been + // specified with it's full .css file extension. + $regex = preg_replace('/\\\.css$/', '(\.css|-rtl\.css)', $regex); + omega_exclude_assets($css, $regex); + } + + // Allow themes to specify no-query fallback CSS files. + $mapping = omega_generate_asset_mapping($css); + foreach (preg_grep('/\.no-query(-rtl)?\.css$/', $mapping) as $key => $fallback) { + // Don't modify browser settings if they have already been modified. + if ($css[$key]['browsers']['IE'] === TRUE && $css[$key]['browsers']['!IE'] === TRUE) { + $css[$key]['browsers'] = array( + '!IE' => FALSE, + 'IE' => 'lte IE 8', + ); + + // Make sure that we don't break any CSS aggregation groups. + $css[$key]['weight'] += 100; + } + } +} + +/** + * Implements hook_js_alter(). + */ +function omega_js_alter(&$js) { + // If the AJAX.js isn't included... we don't need the ajaxPageState settings! + if (!isset($js['misc/ajax.js']) && isset($js['settings']['data'])) { + foreach ($js['settings']['data'] as $delta => $setting) { + if (array_key_exists('ajaxPageState', $setting)) { + if (count($setting) == 1) { + unset($js['settings']['data'][$delta]); + } + else { + unset($js['settings']['data'][$delta]['ajaxPageState']); + } + } + } + } + + if (!omega_extension_enabled('assets')) { + return; + } + + if ($regex = omega_theme_get_setting('omega_js_exclude_regex')) { + omega_exclude_assets($js, $regex); + } + + // Move the specified JavaScript files to the footer. + if (($footer = omega_theme_get_setting('omega_js_footer')) && is_array($footer)) { + $regex = omega_generate_path_regex($footer); + $mapping = omega_generate_asset_mapping($js); + + foreach (preg_grep($regex, $mapping) as $key => $match) { + $js[$key]['scope'] = 'footer'; + } + } +} + +/** + * Implements hook_form_alter(). + */ +function omega_form_alter(&$form, &$form_state, $form_id) { + // Duplicate the form ID as a class so we can reduce specificity in our CSS. + $form['#attributes']['class'][] = drupal_clean_css_identifier($form['#id']); +} + +/** + * Implements hook_form_FORM_ID_alter(). + */ +function omega_form_field_ui_display_overview_form_alter(&$form, &$form_state, $form_id) { + // Add a class to use as a styling hook, instead of the ID attribute. + $form['fields']['#attributes']['class'][] = 'field-display-overview'; +} + +/** + * Implements hook_theme(). + */ +function omega_theme() { + $info['omega_chrome'] = array( + 'render element' => 'element', + ); + + $info['omega_layout'] = array( + 'base hook' => 'page', + ); + + $info = array_merge($info, _omega_theme_layouts()); + + return $info; +} + +/** + * Helper function for registering theme hooks for Omega layouts. + */ +function _omega_theme_layouts() { + $info = array(); + + foreach (omega_layouts_info() as $layout) { + $hook = str_replace('-', '_', $layout['template']); + $info[$hook] = array( + 'template' => $layout['template'], + 'path' => $layout['path'], + ); + } + + return $info; +} + +/** + * Implements hook_theme_registry_alter(). + */ +function omega_theme_registry_alter(&$registry) { + require_once dirname(__FILE__) . '/includes/registry.inc'; + + // Fix for integration with the theme developer module. + if (module_exists('devel_themer')) { + foreach ($registry as $hook => $data) { + if (isset($data['original'])) { + $registry[$hook] = $data['original']; + } + } + } + + // For maintainability reasons, some of this code lives in a class. + $handler = new OmegaThemeRegistryHandler($registry, $GLOBALS['theme']); + + // Allows themers to split preprocess / process / theme code across separate + // files to keep the main template.php file clean. This is really fast because + // it uses the theme registry to cache the paths to the files that it finds. + $trail = omega_theme_trail($GLOBALS['theme']); + foreach ($trail as $theme => $name) { + $handler->registerHooks($theme); + $handler->registerThemeFunctions($theme, $trail); + } + + // Override the default 'template_process_html' hook implementation. + $handler->overrideHook('html', 'template_process_html', 'omega_template_process_html_override'); + + // We prefer the attributes array instead of the plain classes array used by + // many core and contrib modules. In Drupal 8, we are going to convert all + // occurrences of that into an attributes object. For now, we simply + // synchronize our attributes array with the classes array to encourage + // themers to use it. + foreach ($registry as $hook => $item) { + if (empty($item['base hook']) && empty($item['function'])) { + if (($index = array_search('template_preprocess', $registry[$hook]['preprocess functions'], TRUE)) !== FALSE) { + // Make sure that omega_initialize_attributes() is invoked first. + array_unshift($registry[$hook]['process functions'], 'omega_cleanup_attributes'); + // Add omega_cleanup_attributes() right after template_preprocess(). + array_splice($registry[$hook]['preprocess functions'], $index + 1, 0, 'omega_initialize_attributes'); + } + } + } + + // Allow extensions to register hooks in the theme registry. + foreach (omega_extensions() as $extension => $info) { + // Invoke the according hooks for every enabled extension. + if (omega_extension_enabled($extension)) { + // Give every enabled extension a chance to alter the theme registry. + $hook = $info['theme'] . '_extension_' . $extension . '_theme_registry_alter'; + + if (function_exists($hook)) { + $hook($registry); + } + } + } + + // Fix for integration with the theme developer module. + if (module_exists('devel_themer') && function_exists('devel_themer_theme_registry_alter')) { + devel_themer_theme_registry_alter($registry); + } +} + +/** + * Initializes the attributes array from the classes array. + */ +function omega_initialize_attributes(&$variables) { + $variables['attributes_array']['class'] = &$variables['classes_array']; +} + +/** + * Processes the attributes and classes array. + */ +function omega_cleanup_attributes(&$variables, $hook) { + // Break the reference between the classes array and the attributes array. + $classes = !empty($variables['classes_array']) ? $variables['classes_array'] : array(); + unset($variables['attributes_array']['class'], $variables['classes_array']); + + // Clone the attributes array classes into the classes array for backwards + // compatibility reasons. Note that we do not recommend using the classes in + // classes array anyways. + $variables['classes_array'] = $classes; + + if (!empty($classes)) { + // Only write the 'class' attribute if it's not empty. + $variables['attributes_array']['class'] = $classes; + } +} + +/** + * Overrides template_process_html(). + */ +function omega_template_process_html_override(&$variables) { + // Render page_top and page_bottom into top level variables. + $variables['page_top'] = drupal_render($variables['page']['page_top']); + $variables['page_bottom'] = drupal_render($variables['page']['page_bottom']); + // Place the rendered HTML for the page body into a top level variable. + $variables['page'] = $variables['page']['#children']; + $variables['page_bottom'] .= omega_get_js('footer'); + + $variables['head'] = drupal_get_html_head(); + $variables['css'] = drupal_add_css(); + $variables['styles'] = drupal_get_css(); + $variables['scripts'] = omega_get_js(); +} + +/** + * Implements hook_block_list_alter(). + */ +function omega_block_list_alter(&$blocks) { + if (omega_extension_enabled('layouts') && $layout = omega_layout()) { + $callers = debug_backtrace(); + + // Check if drupal_alter() was invoked from _block_load_blocks(). This is + // required as we do not want to interfere with contrib modules like ctools. + if ($callers['2']['function'] === '_block_load_blocks') { + // In case we are currently serving a Omega layout we have to make sure that + // we don't process blocks that will never be shown because the active layout + // does not even have a region for them. + foreach ($blocks as $id => $block) { + if (!array_key_exists($block->region, $layout['info']['regions'])) { + unset($blocks[$id]); + } + } + } + } + + // Hide the main content block on the front page if the theme settings are + // configured that way. + if (!omega_theme_get_setting('omega_toggle_front_page_content', TRUE) && drupal_is_front_page()) { + foreach ($blocks as $key => $block) { + if ($block->module == 'system' && $block->delta == 'main') { + unset($blocks[$key]); + } + } + + drupal_set_page_content(); + } +} + +/** + * Implements hook_page_delivery_callback_alter(). + */ +function omega_page_delivery_callback_alter(&$callback) { + if (module_exists('overlay') && overlay_display_empty_page()) { + $callback = 'omega_override_overlay_deliver_empty_page'; + } +} + +/** + * Delivery callback to display an empty page. + * + * This function is used to print out a bare minimum empty page which still has + * the scripts and styles necessary in order to trigger the overlay to close. + */ +function omega_override_overlay_deliver_empty_page() { + $empty_page = '' . drupal_get_css() . omega_get_js() . ''; + print $empty_page; + drupal_exit(); +} + +/** + * Implements hook_page_alter(). + */ +function omega_page_alter(&$page) { + // Place dummy blocks in each region if the 'demo regions' setting is active + // to force regions to be rendered. + if (omega_extension_enabled('development') && omega_theme_get_setting ('omega_demo_regions', TRUE) && user_access('administer site configuration')) { + $item = menu_get_item(); + + // Don't interfere with the 'Demonstrate block regions' page. + if (strpos('admin/structure/block/demo/', $item['path']) !== 0) { + $regions = system_region_list($GLOBALS['theme_key'], REGIONS_VISIBLE); + $configured = omega_theme_get_setting('omega_demo_regions_list', array_keys($regions)); + + // We don't explicitly load possible layout regions and instead really + // just show demo regions for those regions that we can actually place + // blocks in. Hence, there will only be demo regions for those regions + // that have been declared through the theme's .info file. + foreach (array_intersect_key($regions, array_flip($configured)) as $region => $name) { + if (empty($page[$region])) { + $page[$region]['#theme_wrappers'] = array('region'); + $page[$region]['#region'] = $region; + } + + $page[$region]['#name'] = $name; + $page[$region]['#debug'] = TRUE; + } + } + } + + if (omega_extension_enabled('compatibility') && omega_theme_get_setting('omega_chrome_edge', TRUE) && omega_theme_get_setting('omega_chrome_notice', TRUE)) { + $supported = omega_theme_get_setting('omega_internet_explorer_support', FALSE); + + $page['page_top']['omega_chrome'] = array( + '#theme' => 'omega_chrome', + '#pre_render' => array('drupal_pre_render_conditional_comments'), + '#browsers' => array( + 'IE' => !$supported ? TRUE : 'lte IE ' . $supported, + '!IE' => FALSE, + ), + ); + } +} + +/** + * Implements hook_html_head_alter(). + */ +function omega_html_head_alter(&$head) { + // Simplify the meta tag for character encoding. + $head['system_meta_content_type']['#attributes'] = array('charset' => str_replace('text/html; charset=', '', $head['system_meta_content_type']['#attributes']['content'])); +} + +/** + * Implements hook_omega_theme_libraries_info(). + */ +function omega_omega_theme_libraries_info($theme) { + $libraries['selectivizr'] = array( + 'name' => t('Selectivizr'), + 'description' => t('Selectivizr is a JavaScript utility that emulates CSS3 pseudo-classes and attribute selectors in Internet Explorer 6-8. Simply include the script in your pages and selectivizr will do the rest.'), + 'vendor' => 'Keith Clark', + 'vendor url' => 'http://selectivizr.com/', + 'package' => t('Polyfills'), + 'files' => array( + 'js' => array( + omega_theme_trail_file('libraries/selectivizr/selectivizr.min.js') => array( + 'browsers' => array('IE' => '(gte IE 6)&(lte IE 8)', '!IE' => FALSE), + 'weight' => 110, + 'every_page' => TRUE, + ), + ), + ), + 'variants' => array( + 'source' => array( + 'name' => t('Source'), + 'description' => t('During development it might be useful to include the source files instead of the minified version.'), + 'files' => array( + 'js' => array( + omega_theme_trail_file('libraries/selectivizr/selectivizr.js') => array( + 'browsers' => array('IE' => '(gte IE 6)&(lte IE 8)', '!IE' => FALSE), + 'weight' => 110, + 'every_page' => TRUE, + ), + ), + ), + ), + ), + ); + + $libraries['respond'] = array( + 'name' => t('Respond'), + 'description' => t('Respond is a fast & lightweight polyfill for min/max-width CSS3 Media Queries (for IE 6-8, and more). Note: This library requires CSS aggregation to be enabled for it to work properly.', array('!url' => url('admin/config/development/performance', array('alias' => TRUE)))), + 'vendor' => 'Scott Jehl', + 'vendor url' => 'http://scottjehl.com/', + 'package' => t('Polyfills'), + 'callbacks' => array('omega_extension_library_requirements_css_aggregation'), + 'files' => array( + 'js' => array( + omega_theme_trail_file('libraries/respond/respond.min.js') => array( + 'browsers' => array('IE' => '(gte IE 6)&(lte IE 8)', '!IE' => FALSE), + 'weight' => 120, + 'every_page' => TRUE, + ), + ), + ), + 'variants' => array( + 'source' => array( + 'name' => t('Source'), + 'description' => t('During development it might be useful to include the source files instead of the minified version.'), + 'files' => array( + 'js' => array( + omega_theme_trail_file('libraries/respond/respond.js') => array( + 'browsers' => array('IE' => '(gte IE 6)&(lte IE 8)', '!IE' => FALSE), + 'weight' => 120, + 'every_page' => TRUE, + ), + ), + ), + ), + ), + ); + + $libraries['css3pie'] = array( + 'name' => t('CSS3 PIE'), + 'description' => t('PIE makes Internet Explorer 6-9 capable of rendering several of the most useful CSS3 decoration features.'), + 'vendor' => 'Keith Clark', + 'vendor url' => 'http://css3pie.com/', + 'options form' => 'omega_library_pie_options_form', + 'package' => t('Polyfills'), + 'files' => array(), + 'variants' => array( + 'js' => array( + 'name' => t('JavaScript'), + 'description' => t('While the .htc behavior is still the recommended approach for most users, the JS version has some advantages that may be a better fit for some users.'), + 'files' => array( + 'js' => array( + omega_theme_trail_file('libraries/pie/PIE.js') => array( + 'browsers' => array('IE' => '(gte IE 6)&(lte IE 8)', '!IE' => FALSE), + 'weight' => 100, + 'every_page' => TRUE, + ), + ), + ), + ), + ), + ); + + $settings = omega_theme_get_setting('omega_libraries'); + if (!empty($settings['css3pie']['selectors'])) { + // Add the generated .css file to the corresponding variant. + $destination = file_create_url('public://omega/' . $theme ); + $destination = substr($destination, strlen($GLOBALS['base_url']) + 1); + file_prepare_directory($destination, FILE_CREATE_DIRECTORY); + + // Save the generated CSS in the public file system. + $file = $destination . '/pie-selectors.css'; + $htc = base_path() . omega_theme_trail_file('libraries/pie/PIE.htc'); + $contents = implode(",", $settings['css3pie']['selectors']) . "{behavior:url($htc)}"; + file_unmanaged_save_data($contents, $file, FILE_EXISTS_REPLACE); + + $libraries['css3pie']['files']['css'][$file] = array( + 'browsers' => array('IE' => '(gte IE 6)&(lte IE 8)', '!IE' => FALSE), + 'weight' => 100, + 'every_page' => TRUE, + ); + + // Save the generated JS in the public file system. + $file = $destination . '/pie-selectors.js'; + $contents = '$(function(){Drupal.behaviors.css3pie={attach:function(context,settings){if(window.PIE){$("' . implode(",", $settings['css3pie']['selectors']) . '").each(function(){PIE.attach(this)})}}}})(jQuery);'; + file_unmanaged_save_data($contents, $file, FILE_EXISTS_REPLACE); + + $libraries['css3pie']['variants']['js']['files']['js'][$file] = array( + 'browsers' => array('IE' => '(gte IE 6)&(lte IE 8)', '!IE' => FALSE), + 'weight' => 100, + 'every_page' => TRUE, + ); + } + + $libraries['html5shiv'] = array( + 'name' => t('HTML5 Shiv'), + 'description' => t('This script is the defacto way to enable use of HTML5 sectioning elements in legacy Internet Explorer, as well as default HTML5 styling in Internet Explorer 6 - 9, Safari 4.x (and iPhone 3.x), and Firefox 3.x.'), + 'vendor' => 'Alexander Farkas', + 'package' => t('Polyfills'), + 'files' => array( + 'js' => array( + omega_theme_trail_file('libraries/html5shiv/html5shiv.js') => array( + 'browsers' => array('IE' => '(gte IE 6)&(lte IE 8)', '!IE' => FALSE), + 'weight' => 100, + 'every_page' => TRUE, + ), + omega_theme_trail_file('libraries/html5shiv/html5shiv-printshiv.js') => array( + 'browsers' => array('IE' => '(gte IE 6)&(lte IE 8)', '!IE' => FALSE), + 'weight' => 100, + 'every_page' => TRUE, + ), + ), + ), + 'variants' => array( + 'source' => array( + 'name' => t('Source'), + 'description' => t('During development it might be useful to include the source files instead of the minified version.'), + 'files' => array( + 'js' => array( + omega_theme_trail_file('libraries/html5shiv/html5shiv.min.js') => array( + 'browsers' => array('IE' => '(gte IE 6)&(lte IE 8)', '!IE' => FALSE), + 'weight' => 100, + 'every_page' => TRUE, + ), + omega_theme_trail_file('libraries/html5shiv/html5shiv-printshiv.min.js') => array( + 'browsers' => array('IE' => '(gte IE 6)&(lte IE 8)', '!IE' => FALSE), + 'weight' => 100, + 'every_page' => TRUE, + ), + ), + ), + ), + ), + ); + + $libraries['messages'] = array( + 'name' => t('Discardable messages'), + 'description' => t("Adds a 'close' button to each message."), + 'package' => t('Goodies'), + 'files' => array( + 'js' => array( + omega_theme_trail_file('js/omega.messages.min.js') => array( + 'weight' => -100, + 'every_page' => TRUE, + ), + ), + 'css' => array( + omega_theme_trail_file('css/omega.messages.css') => array( + 'weight' => -100, + 'every_page' => TRUE, + ), + ), + ), + ); + + return $libraries; +} + +/** + * Theme callback for rendering an Omega layout. + */ +function omega_omega_layout($variables) { + drupal_process_attached(array('#attached' => $variables['omega_layout']['attached'])); + + // Clean up the theme hook suggestion so we don't end up in an infinite loop. + unset($variables['theme_hook_suggestion'], $variables['theme_hook_suggestions']); + $hook = str_replace('-', '_', $variables['omega_layout']['template']); + return theme($hook, $variables); +} + +/** + * Shows a notice when Google Chrome Frame is not installed. + */ +function omega_omega_chrome($variables) { + $message = t('You are using an outdated browser! Upgrade your browser today or install Google Chrome Frame to better experience this site.', array( + '!upgrade' => url('http://browsehappy.com'), + '!install' => url('http://www.google.com/chromeframe', array( + 'query' => array('redirect' => 'true') + )), + )); + + return '

    ' . $message . '

    '; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/aggregator/aggregator-feed-source.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/aggregator/aggregator-feed-source.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,36 @@ + +
    + + +
    + +
    +
    + +
    +
    + +
    +
    diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/aggregator/aggregator-item.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/aggregator/aggregator-item.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,47 @@ + +
    +

    + +

    + +
    + + - + + +
    + + +
    + +
    + + + +
    + : +
    + + +
    diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/aggregator/aggregator-wrapper.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/aggregator/aggregator-wrapper.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,18 @@ + +
    + + +
    diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/block/block--minimal.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/block/block--minimal.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,52 @@ +subject: Block title. + * - $content: Block content. + * - $block->module: Module that generated the block. + * - $block->delta: An ID for the block, unique within each module. + * - $block->region: The block region embedding the current block. + * - $classes: String of classes that can be used to style contextually through + * CSS. It can be manipulated through the variable $classes_array from + * preprocess functions. The default values can be one or more of the + * following: + * - block: The current template type, i.e., "theming hook". + * - block-[module]: The module generating the block. For example, the user + * module is responsible for handling the default user navigation block. In + * that case the class would be 'block-user'. + * - $title_prefix (array): An array containing additional output populated by + * modules, intended to be displayed in front of the main title tag that + * appears in the template. + * - $title_suffix (array): An array containing additional output populated by + * modules, intended to be displayed after the main title tag that appears in + * the template. + * + * Helper variables: + * - $classes_array: Array of html class attribute values. It is flattened + * into a string within the variable $classes. + * - $block_zebra: Outputs 'odd' and 'even' dependent on each block region. + * - $zebra: Same output as $block_zebra but independent of any block region. + * - $block_id: Counter dependent on each block region. + * - $id: Same output as $block_id but independent of any block region. + * - $is_front: Flags true when presented in the front page. + * - $logged_in: Flags true when the current user is a logged-in member. + * - $is_admin: Flags true when the current user is an administrator. + * - $block_html_id: A valid HTML ID and guaranteed unique. + * + * @see template_preprocess() + * @see template_preprocess_block() + * @see template_process() + * + * @ingroup themeable + */ +?> + +subject): ?> + >subject; ?> + + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/block/block--nav.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/block/block--nav.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,55 @@ +subject: Block title. + * - $content: Block content. + * - $block->module: Module that generated the block. + * - $block->delta: An ID for the block, unique within each module. + * - $block->region: The block region embedding the current block. + * - $classes: String of classes that can be used to style contextually through + * CSS. It can be manipulated through the variable $classes_array from + * preprocess functions. The default values can be one or more of the + * following: + * - block: The current template type, i.e., "theming hook". + * - block-[module]: The module generating the block. For example, the user + * module is responsible for handling the default user navigation block. In + * that case the class would be 'block-user'. + * - $title_prefix (array): An array containing additional output populated by + * modules, intended to be displayed in front of the main title tag that + * appears in the template. + * - $title_suffix (array): An array containing additional output populated by + * modules, intended to be displayed after the main title tag that appears in + * the template. + * + * Helper variables: + * - $classes_array: Array of html class attribute values. It is flattened + * into a string within the variable $classes. + * - $block_zebra: Outputs 'odd' and 'even' dependent on each block region. + * - $zebra: Same output as $block_zebra but independent of any block region. + * - $block_id: Counter dependent on each block region. + * - $id: Same output as $block_id but independent of any block region. + * - $is_front: Flags true when presented in the front page. + * - $logged_in: Flags true when the current user is a logged-in member. + * - $is_admin: Flags true when the current user is an administrator. + * - $block_html_id: A valid HTML ID and guaranteed unique. + * + * @see template_preprocess() + * @see template_preprocess_block() + * @see template_process() + * + * @ingroup themeable + */ +?> +> + + subject): ?> + >subject; ?> + + + + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/block/block-admin-display-form.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/block/block-admin-display-form.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,60 @@ +region_title: Region title for the listed block. + * - $data->block_title: Block title. + * - $data->region_select: Drop-down menu for assigning a region. + * - $data->weight_select: Drop-down menu for setting weights. + * - $data->configure_link: Block configuration link. + * - $data->delete_link: For deleting user added blocks. + * + * @see template_preprocess_block_admin_display_form() + * @see theme_block_admin_display() + * + * @ingroup themeable + */ +?> + + + + + + + + + + + + $title): ?> + + + + + + + $data): ?> + + + + + + + + + + + +
    block_title; ?>region_select; ?>weight_select; ?>configure_link; ?>delete_link; ?>
    + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/block/block.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/block/block.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,56 @@ +subject: Block title. + * - $content: Block content. + * - $block->module: Module that generated the block. + * - $block->delta: An ID for the block, unique within each module. + * - $block->region: The block region embedding the current block. + * - $classes: String of classes that can be used to style contextually through + * CSS. It can be manipulated through the variable $classes_array from + * preprocess functions. The default values can be one or more of the + * following: + * - block: The current template type, i.e., "theming hook". + * - block-[module]: The module generating the block. For example, the user + * module is responsible for handling the default user navigation block. In + * that case the class would be 'block-user'. + * - $title_prefix (array): An array containing additional output populated by + * modules, intended to be displayed in front of the main title tag that + * appears in the template. + * - $title_suffix (array): An array containing additional output populated by + * modules, intended to be displayed after the main title tag that appears in + * the template. + * + * Helper variables: + * - $classes_array: Array of html class attribute values. It is flattened + * into a string within the variable $classes. + * - $block_zebra: Outputs 'odd' and 'even' dependent on each block region. + * - $zebra: Same output as $block_zebra but independent of any block region. + * - $block_id: Counter dependent on each block region. + * - $id: Same output as $block_id but independent of any block region. + * - $is_front: Flags true when presented in the front page. + * - $logged_in: Flags true when the current user is a logged-in member. + * - $is_admin: Flags true when the current user is an administrator. + * - $block_html_id: A valid HTML ID and guaranteed unique. + * + * @see template_preprocess() + * @see template_preprocess_block() + * @see template_process() + * + * @ingroup themeable + */ +?> +> + + subject): ?> + >subject; ?> + + + > + +
    +
    diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/book/book-navigation.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/book/book-navigation.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,54 @@ + + +
    + + + + + + +
    + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/comment/comment-wrapper.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/comment/comment-wrapper.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,54 @@ + +> + type != 'forum'): ?> + + > + + + + + + + > + + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/comment/comment.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/comment/comment.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,90 @@ +created variable. + * - $changed: Formatted date and time for when the comment was last changed. + * Preprocess functions can reformat it by calling format_date() with the + * desired parameters on the $comment->changed variable. + * - $new: New comment marker. + * - $permalink: Comment permalink. + * - $submitted: Submission information created from $author and $created during + * template_preprocess_comment(). + * - $user_picture: The comment author's picture from user-picture.tpl.php. + * - $signature: Authors signature. + * - $status: Comment status. Possible values are: + * comment-unpublished, comment-published or comment-preview. + * - $title: Linked title. + * - $classes: String of classes that can be used to style contextually through + * CSS. It can be manipulated through the variable $classes_array from + * preprocess functions. The default values can be one or more of the + * following: + * - comment: The current template type, i.e., "theming hook". + * - comment-by-anonymous: Comment by an unregistered user. + * - comment-by-node-author: Comment by the author of the parent node. + * - comment-preview: When previewing a new or edited comment. + * The following applies only to viewers who are registered users: + * - comment-unpublished: An unpublished comment visible only to + * administrators. + * - comment-by-viewer: Comment by the user currently viewing the page. + * - comment-new: New comment since last the visit. + * - $title_prefix (array): An array containing additional output populated by + * modules, intended to be displayed in front of the main title tag that + * appears in the template. + * - $title_suffix (array): An array containing additional output populated by + * modules, intended to be displayed after the main title tag that appears in + * the template. + * + * These two variables are provided for context: + * - $comment: Full comment object. + * - $node: Node object the comments are attached to. + * + * Other variables: + * - $classes_array: Array of html class attribute values. It is flattened + * into a string within the variable $classes. + * + * @see template_preprocess() + * @see template_preprocess_comment() + * @see template_process() + * @see theme_comment() + */ +?> +> + + + + + > + + +
    + + + +
    + + > + + +
    + +
    + + + + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/forum/forum-icon.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/forum/forum-icon.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,21 @@ + +
    + +
    diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/forum/forum-list.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/forum/forum-list.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,78 @@ +is_container: TRUE if the forum can contain other forums. FALSE + * if the forum can contain only topics. + * - $forum->depth: How deep the forum is in the current hierarchy. + * - $forum->zebra: 'even' or 'odd' string used for row class. + * - $forum->icon_class: 'default' or 'new' string used for forum icon class. + * - $forum->icon_title: Text alternative for the forum icon. + * - $forum->name: The name of the forum. + * - $forum->link: The URL to link to this forum. + * - $forum->description: The description of this forum. + * - $forum->new_topics: TRUE if the forum contains unread posts. + * - $forum->new_url: A URL to the forum's unread posts. + * - $forum->new_text: Text for the above URL, which tells how many new posts. + * - $forum->old_topics: A count of posts that have already been read. + * - $forum->num_posts: The total number of posts in the forum. + * - $forum->last_reply: Text representing the last time a forum was posted or + * commented in. + * - $forum_id: Forum ID for the current forum. Parent to all items within the + * $forums array. + * + * @see template_preprocess_forum_list() + * @see theme_forum_list() + * + * @ingroup themeable + */ +?> + + + + + + + + + + + $forum): ?> + + + + is_container): ?> + + + + + + + + + +
    is_container ? 'colspan="4" class="forum-topic__details forum-topic--container"' : 'class="forum-topic__details forum-topic--forum"'; ?>> + ', $forum->depth); ?> + +
    + icon_title; ?> +
    + + + + description): ?> +
    description; ?>
    + +
    + num_topics ?> + new_topics): ?> +
    + new_text; ?> + +
    num_posts ?>last_reply ?>
    diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/forum/forum-topic-list.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/forum/forum-topic-list.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,72 @@ +icon: The icon to display. + * - $topic->moved: A flag to indicate whether the topic has been moved to + * another forum. + * - $topic->title: The title of the topic. Safe to output. + * - $topic->message: If the topic has been moved, this contains an + * explanation and a link. + * - $topic->zebra: 'even' or 'odd' string used for row class. + * - $topic->comment_count: The number of replies on this topic. + * - $topic->new_replies: A flag to indicate whether there are unread + * comments. + * - $topic->new_url: If there are unread replies, this is a link to them. + * - $topic->new_text: Text containing the translated, properly pluralized + * count. + * - $topic->created: A string representing when the topic was posted. Safe + * to output. + * - $topic->last_reply: An outputtable string representing when the topic was + * last replied to. + * - $topic->timestamp: The raw timestamp this topic was posted. + * - $topic_id: Numeric ID for the current forum topic. + * + * @see template_preprocess_forum_topic_list() + * @see theme_forum_topic_list() + * + * @ingroup themeable + */ +?> + + + + + + + + + + moved): ?> + + + + + + + + +
    icon; ?> +
    + title; ?> +
    +
    + created; ?> +
    +
    message; ?> + comment_count; ?> + new_replies): ?> +
    + new_text; ?> + +
    last_reply; ?>
    + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/forum/forums.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/forum/forums.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,24 @@ + + +
    + + +
    + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/node/node.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/node/node.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,110 @@ +body becomes $body. When needing to access + * a field's raw values, developers/themers are strongly encouraged to use these + * variables. Otherwise they will have to explicitly specify the desired field + * language, e.g. $node->body['en'], thus overriding any language negotiation + * rule that was previously applied. + * + * @see template_preprocess() + * @see template_preprocess_node() + * @see template_process() + */ +?> +> + +
    + + + > + + +
    + + + +
    + + +
    + + + > + + + + + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/panelizer/panelizer-view-mode.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/panelizer/panelizer-view-mode.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,14 @@ +> + + + < > + + + + + + > + + + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/poll/poll-bar--block.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/poll/poll-bar--block.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,27 @@ + +
    +
    +
    +
    +
    +
    + % +
    +
    diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/poll/poll-bar.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/poll/poll-bar.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,27 @@ + +
    +
    +
    +
    +
    +
    + % () +
    +
    diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/poll/poll-results--block.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/poll/poll-results--block.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,28 @@ + +
    +

    + +
    + $votes)); ?> +
    +
    + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/poll/poll-results.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/poll/poll-results.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,30 @@ + +
    + +
    + $votes)); ?> +
    + + + +
    diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/poll/poll-vote.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/poll/poll-vote.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,29 @@ + +
    +
    + +

    + + +
    + +
    + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/region/region--minimal.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/region/region--minimal.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,29 @@ + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/region/region--sidebar.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/region/region--sidebar.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,33 @@ + + + > + + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/region/region.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/region/region.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,33 @@ + + + > + + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/search/search-result.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/search/search-result.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,77 @@ + + * + * + * + * + * @endcode + * + * To check for all available data within $info_split, use the code below. + * @code + * '. check_plain(print_r($info_split, 1)) .''; ?> + * @endcode + * + * @see template_preprocess() + * @see template_preprocess_search_result() + * @see template_process() + * + * @ingroup themeable + */ +?> +
    > + +

    >

    + + +

    >

    + + +
    + +
    diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/search/search-results.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/search/search-results.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,35 @@ + + +

    +
    + +
    + + +

    + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/system/html.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/system/html.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,66 @@ +language contains its textual representation. + * $language->dir contains the language direction. It will either be 'ltr' or 'rtl'. + * - $rdf_namespaces: All the RDF namespace prefixes used in the HTML document. + * - $grddl_profile: A GRDDL profile allowing agents to extract the RDF data. + * - $head_title: A modified version of the page title, for use in the TITLE + * tag. + * - $head_title_array: (array) An associative array containing the string parts + * that were used to generate the $head_title variable, already prepared to be + * output as TITLE tag. The key/value pairs may contain one or more of the + * following, depending on conditions: + * - title: The title of the current page, if any. + * - name: The name of the site. + * - slogan: The slogan of the site, if any, and if there is no title. + * - $head: Markup for the HEAD section (including meta tags, keyword tags, and + * so on). + * - $styles: Style tags necessary to import all CSS files for the page. + * - $scripts: Script tags necessary to load the JavaScript files and settings + * for the page. + * - $page_top: Initial markup from any modules that have altered the + * page. This variable should always be output first, before all other dynamic + * content. + * - $page: The rendered page content. + * - $page_bottom: Final closing markup from any modules that have altered the + * page. This variable should always be output last, after all other dynamic + * content. + * - $classes String of classes that can be used to style contextually through + * CSS. + * + * @see template_preprocess() + * @see template_preprocess_html() + * @see template_process() + */ +?> + + + + + + + > + + > + + + <?php print $head_title; ?> + + + + +> + + + + + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/system/maintenance-page.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/system/maintenance-page.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,67 @@ + + + + + + + + + + + + + <?php print $head_title; ?> + + + + +> +
    + + +
    +
    +

    + + +
    +
    + +
    + +
    +
    diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/system/page.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/system/page.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,124 @@ + +
    + + +
    +
    + + + + + +

    + + + + + + + + + + +
    + + + +
    + +
    + +
    +
    diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/taxonomy/taxonomy-term.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/taxonomy/taxonomy-term.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,51 @@ + +> + +

    + + + > + + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/user/user-profile-category.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/user/user-profile-category.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,35 @@ + +> +
    + +

    + +
    + + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/user/user-profile-item.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/user/user-profile-item.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,28 @@ + +> + + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/user/user-profile.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/user/user-profile.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,33 @@ +field_example has a + * variable $field_example defined. When needing to access a field's raw + * values, developers/themers are strongly encouraged to use these + * variables. Otherwise they will have to explicitly specify the desired + * field language, e.g. $account->field_example['en'], thus overriding any + * language negotiation rule that was previously applied. + * + * @see template_preprocess_user_profile() + */ +?> +> + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/views/views-view-grid.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/views/views-view-grid.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,26 @@ + + +

    + +> + + + + + $columns): ?> + > + $item): ?> + > + + + + + + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/views/views-view-list.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/views/views-view-list.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,17 @@ + + + +

    + + + $row): ?> + > + + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/views/views-view-table.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/views/views-view-table.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,34 @@ + +> + + + + + + + $label): ?> + > + + + + + + + + $row): ?> + > + $content): ?> + > + + + + + + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/templates/views/views-view-unformatted.tpl.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/templates/views/views-view-unformatted.tpl.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,15 @@ + + +

    + + $row): ?> + > + + + diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/theme-settings.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/theme-settings.php Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,215 @@ + $name) { + $path = drupal_get_path('theme', $theme); + + $filename = DRUPAL_ROOT . '/' . $path . '/template.php'; + if (file_exists($filename)) { + require_once $filename; + } + + $filename = DRUPAL_ROOT . '/' . $path . '/theme-settings.php'; + if (file_exists($filename)) { + require_once $filename; + } + } + + // Get the admin theme so we can set a class for styling this form. + $admin = drupal_html_class(variable_get('admin_theme', $GLOBALS['theme'])); + $form['#prefix'] = '
    '; + $form['#suffix'] = '
    '; + + // Add some custom styling and functionality to our theme settings form. + $form['#attached']['css'][] = drupal_get_path('theme', 'omega') . '/css/omega.admin.css'; + $form['#attached']['js'][] = drupal_get_path('theme', 'omega') . '/js/omega.admin.min.js'; + + // Collapse all the core theme settings tabs in order to have the form actions + // visible all the time without having to scroll. + foreach (element_children($form) as $key) { + if ($form[$key]['#type'] == 'fieldset') { + $form[$key]['#collapsible'] = TRUE; + $form[$key]['#collapsed'] = TRUE; + } + } + + if ($extensions = omega_extensions(NULL, TRUE)) { + $form['omega'] = array( + '#type' => 'vertical_tabs', + '#weight' => -10, + ); + + // Load the theme settings for all enabled extensions. + foreach ($extensions as $extension => $info) { + $form['omega'][$extension] = array( + '#type' => 'fieldset', + '#title' => $info['info']['name'], + '#attributes' => array( + 'class' => array('omega-extension'), + ), + ); + + $errors = array(); + if (!empty($info['info']['dependencies'])) { + foreach ($info['info']['dependencies'] as $dependency) { + $dependency = drupal_parse_dependency($dependency); + + // Check if the module exists. + if (!$module = system_get_info('module', $dependency['name'])) { + $errors[] = t('This extension requires the @module module.', array( + '@module' => ucwords(str_replace('_', ' ', $dependency['name'])), + )); + } + // Check if the module version is compatible. + elseif (($version = omega_check_incompatibility($dependency, $module['version'])) !== NULL) { + $errors[] = t('This extension requires @module @version. The currently installed version is @installed.', array( + '@module' => $module['name'], + '@version' => $version, + '@installed' => !empty($module['version']) ? $module['version'] : t('undetermined'), + )); + } + } + + if (!empty($errors)) { + $form['omega'][$extension]['errors'] = array( + '#type' => 'item', + '#title' => t('Missing requirements'), + '#markup' => '
    • ' . implode('
    • ', $errors) . '
    ', + '#weight' => -20, + // Abuse the #name attribute to add a class to the form item. + '#name' => 'omega-requirements', + ); + } + } + + // Disable all options if there were any errors. + $form['omega'][$extension]['#disabled'] = !empty($errors) || variable_get('omega_toggle_extension_' . $extension) !== NULL; + + $form['omega'][$extension]['omega_toggle_extension_' . $extension] = array( + '#type' => 'checkbox', + '#title' => t('Enable @extension extension', array('@extension' => $info['info']['name'])) . (variable_get('omega_toggle_extension_' . $extension) !== NULL ? ' (' . t('overridden') . ')' : ''), + '#description' => t('This setting can be overridden with an equally named variable (@name) so you can control it on a per-environment basis by setting it in your settings.php file.', array('@name' => 'omega_toggle_extension_' . $extension)), + '#default_value' => omega_extension_enabled($extension), + '#weight' => -10, + ); + + $element = array(); + + // Load the implementation for this extensions and invoke the according + // hook. + $file = $info['path'] . '/' . $extension . '.settings.inc'; + if (is_file($file)) { + require_once $file; + } + + $function = $info['theme'] . '_extension_' . $extension . '_settings_form'; + if (function_exists($function)) { + // By default, each extension resides in a vertical tab + $element = $function($element, $form, $form_state) + array( + '#type' => 'fieldset', + '#title' => t('@extension extension configuration', array('@extension' => $info['info']['name'])), + '#description' => $info['info']['description'], + '#states' => array( + 'disabled' => array( + 'input[name="omega_toggle_extension_' . $extension . '"]' => array('checked' => FALSE), + ), + ), + ); + } + + drupal_alter('extension_' . $extension . '_settings_form', $element, $form, $form_state); + + if (element_children($element)) { + // Append the extension form to the theme settings form if it has any + // children. + $form['omega'][$extension]['settings'] = $element; + } + } + } + + // Custom option for toggling the main content blog on the front page. + $form['theme_settings']['omega_toggle_front_page_content'] = array( + '#type' => 'checkbox', + '#title' => t('Front page content'), + '#description' => t('Allow the main content block to be rendered on the front page.'), + '#default_value' => omega_theme_get_setting('omega_toggle_front_page_content', TRUE), + ); + + // We need a custom form submit handler for processing some of the values. + $form['#submit'][] = 'omega_theme_settings_form_submit'; + + // Store the extensions in an array so we can loop over them in the submit + // callback. + $form_state['extensions'] = array_keys($extensions); +} + +/** + * Form submit handler for the theme settings form. + */ +function omega_theme_settings_form_submit($form, &$form_state) { + // Clear the theme cache. + $theme = $form_state['build_info']['args'][0]; + cache_clear_all('omega:' . $theme . ':', 'cache', TRUE); + + // We also need to clear the static right away. + drupal_static_reset('omega_extensions'); + + // Rebuild the theme registry. This has quite a performance impact but since + // this only happens once after we (re-)saved the theme settings this is fine. + // Also, this is actually required because we are caching certain things in + // the theme registry. + drupal_theme_rebuild(); + + // We really don't want to reset theme settings for disabled extensions. + foreach ($form_state['extensions'] as $extension) { + if (!$form_state['values']['omega_toggle_extension_' . $extension]) { + _omega_retain_extension_settings($form, $form_state, $extension, $theme); + } + } + + // This is a relict from the vertical tabs and should be removed so it doesn't + // end up in the theme settings array. + unset($form_state['values']['omega__active_tab']); +} + +/** + * Helper function for retaining settings of an extension. + */ +function _omega_retain_extension_settings($form, &$form_state, $extension, $theme, $parents = array()) { + $current = array_merge(array('omega', $extension, 'settings'), $parents); + + if ($items = drupal_array_get_nested_value($form, $current)) { + foreach (element_children($items) as $key) { + if (array_key_exists($key, $form_state['values'])) { + $form_state['values'][$key] = omega_theme_get_setting($key, NULL, $theme); + } + + $next = array_merge($parents, array($key)); + _omega_retain_extension_settings($form, $form_state, $extension, $theme, $next); + } + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/theme/admin-block.theme.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/theme/admin-block.theme.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,39 @@ +'; + if (!empty($block['title'])) { + $output .= '

    ' . $block['title'] . '

    '; + } + if (!empty($block['content'])) { + $output .= '
    ' . $block['content'] . '
    '; + } + else { + $output .= '
    ' . $block['description'] . '
    '; + } + $output .= ''; + + return $output; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/theme/breadcrumb.theme.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/theme/breadcrumb.theme.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,18 @@ +' . t('You are here') . ''; + + // Override Drupal core breadcrumb item imploding (no arrow). + $output .= ''; + return $output; + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/theme/field.theme.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/theme/field.theme.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,56 @@ +' . $variables['label'] . ': '; + } + + // Render the items. + $output .= '
    '; + foreach ($variables['items'] as $delta => $item) { + $classes = 'field__item ' . ($delta % 2 ? 'odd' : 'even'); + $output .= '
    ' . drupal_render($item) . '
    '; + } + $output .= '
    '; + + // Render the top-level DIV. + $output = '
    ' . $output . '
    '; + + return $output; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/theme/image-style-preview.theme.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/theme/image-style-preview.theme.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,78 @@ + $original_image['height']) { + $original_width = min($original_image['width'], $sample_width); + $original_height = round($original_width / $original_image['width'] * $original_image['height']); + } + else { + $original_height = min($original_image['height'], $sample_height); + $original_width = round($original_height / $original_image['height'] * $original_image['width']); + } + $original_attributes = array_intersect_key($original_image, array('width' => '', 'height' => '')); + $original_attributes['style'] = 'width: ' . $original_width . 'px; height: ' . $original_height . 'px;'; + + // Set up preview file information. + $preview_file = image_style_path($style['name'], $original_path); + if (!file_exists($preview_file)) { + image_style_create_derivative($style, $original_path, $preview_file); + } + $preview_image = image_get_info($preview_file); + if ($preview_image['width'] > $preview_image['height']) { + $preview_width = min($preview_image['width'], $sample_width); + $preview_height = round($preview_width / $preview_image['width'] * $preview_image['height']); + } + else { + $preview_height = min($preview_image['height'], $sample_height); + $preview_width = round($preview_height / $preview_image['height'] * $preview_image['width']); + } + $preview_attributes = array_intersect_key($preview_image, array('width' => '', 'height' => '')); + $preview_attributes['style'] = 'width: ' . $preview_width . 'px; height: ' . $preview_height . 'px;'; + + // In the previews, timestamps are added to prevent caching of images. + $output = '
    '; + + // Build the preview of the original image. + $original_url = file_create_url($original_path); + $output .= '
    '; + $output .= t('original') . ' (' . l(t('view actual size'), $original_url) . ')'; + $output .= '
    '; + $output .= '' . theme('image', array('path' => $original_path, 'alt' => t('Sample original image'), 'title' => '', 'attributes' => $original_attributes)) . ''; + $output .= '
    ' . $original_image['height'] . 'px
    '; + $output .= '
    ' . $original_image['width'] . 'px
    '; + $output .= '
    '; // End preview-image. + $output .= '
    '; // End preview-image-wrapper. + + // Build the preview of the image style. + $preview_url = file_create_url($preview_file) . '?cache_bypass=' . REQUEST_TIME; + $output .= '
    '; + $output .= check_plain($style['name']) . ' (' . l(t('view actual size'), file_create_url($preview_file) . '?' . time()) . ')'; + $output .= '
    '; + $output .= '' . theme('image', array('path' => $preview_url, 'alt' => t('Sample modified image'), 'title' => '', 'attributes' => $preview_attributes)) . ''; + $output .= '
    ' . $preview_image['height'] . 'px
    '; + $output .= '
    ' . $preview_image['width'] . 'px
    '; + $output .= '
    '; // End preview-image. + $output .= '
    '; // End preview-image-wrapper. + + $output .= '
    '; // End image-style-preview. + + return $output; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/theme/item-list.theme.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/theme/item-list.theme.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,66 @@ +' . $title . ''; + } + + if (!empty($items)) { + $output .= "<$type" . drupal_attributes($attributes) . '>'; + $num_items = count($items); + $i = 0; + foreach ($items as $item) { + $attributes = array(); + $children = array(); + $data = ''; + $i++; + if (is_array($item)) { + foreach ($item as $key => $value) { + if ($key == 'data') { + $data = $value; + } + elseif ($key == 'children') { + $children = $value; + } + else { + $attributes[$key] = $value; + } + } + } + else { + $data = $item; + } + if (count($children) > 0) { + // Render nested list. + $data .= theme_item_list(array('items' => $children, 'title' => NULL, 'type' => $type, 'attributes' => $attributes)); + } + $output .= '' . $data . "\n"; + } + $output .= ""; + } + return $output; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/theme/mark.theme.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/theme/mark.theme.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,17 @@ +uid) { + if ($type == MARK_NEW) { + return ' ' . t('new') . ''; + } + elseif ($type == MARK_UPDATED) { + return ' ' . t('updated') . ''; + } + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/theme/menu-local-tasks.theme.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/theme/menu-local-tasks.theme.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,30 @@ +' . t('Primary tabs') . ''; + $variables['primary']['#prefix'] .= ''; + $output .= drupal_render($variables['primary']); + } + if (!empty($variables['secondary'])) { + $variables['secondary']['#prefix'] = '

    ' . t('Secondary tabs') . '

    '; + $variables['secondary']['#prefix'] .= ''; + $output .= drupal_render($variables['secondary']); + } + + return $output; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/theme/more-help-link.theme.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/theme/more-help-link.theme.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,12 @@ + array('class' => array('more-link')))); +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/theme/pager.theme.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/theme/pager.theme.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,128 @@ + $pager_max) { + // Adjust "center" if at end of query. + $i = $i + ($pager_max - $pager_last); + $pager_last = $pager_max; + } + if ($i <= 0) { + // Adjust "center" if at start of query. + $pager_last = $pager_last + (1 - $i); + $i = 1; + } + // End of generation loop preparation. + + $li_first = theme('pager_first', array('text' => (isset($tags[0]) ? $tags[0] : t('« first')), 'element' => $element, 'parameters' => $parameters)); + $li_previous = theme('pager_previous', array('text' => (isset($tags[1]) ? $tags[1] : t('‹ previous')), 'element' => $element, 'interval' => 1, 'parameters' => $parameters)); + $li_next = theme('pager_next', array('text' => (isset($tags[3]) ? $tags[3] : t('next ›')), 'element' => $element, 'interval' => 1, 'parameters' => $parameters)); + $li_last = theme('pager_last', array('text' => (isset($tags[4]) ? $tags[4] : t('last »')), 'element' => $element, 'parameters' => $parameters)); + + if ($pager_total[$element] > 1) { + if ($li_first) { + $items[] = array( + 'class' => array('pager__item', 'pager__item--first'), + 'data' => $li_first, + ); + } + if ($li_previous) { + $items[] = array( + 'class' => array('pager__item', 'pager__item--previous'), + 'data' => $li_previous, + ); + } + + // When there is more than one page, create the pager list. + if ($i != $pager_max) { + if ($i > 1) { + $items[] = array( + 'class' => array('pager__item', 'pager__item--ellipsis'), + 'data' => '…', + ); + } + // Now generate the actual pager piece. + for (; $i <= $pager_last && $i <= $pager_max; $i++) { + if ($i < $pager_current) { + $items[] = array( + 'class' => array('pager__item'), + 'data' => theme('pager_previous', array('text' => $i, 'element' => $element, 'interval' => ($pager_current - $i), 'parameters' => $parameters)), + ); + } + if ($i == $pager_current) { + $items[] = array( + 'class' => array('pager__item', 'pager__item--current'), + 'data' => $i, + ); + } + if ($i > $pager_current) { + $items[] = array( + 'class' => array('pager__item'), + 'data' => theme('pager_next', array('text' => $i, 'element' => $element, 'interval' => ($i - $pager_current), 'parameters' => $parameters)), + ); + } + } + if ($i < $pager_max) { + $items[] = array( + 'class' => array('pager__item', 'pager__item--ellipsis'), + 'data' => '…', + ); + } + } + // End generation. + if ($li_next) { + $items[] = array( + 'class' => array('pager__item', 'pager__item--next'), + 'data' => $li_next, + ); + } + if ($li_last) { + $items[] = array( + 'class' => array('pager__item', 'pager__item--last'), + 'data' => $li_last, + ); + } + return '

    ' . t('Pages') . '

    ' . theme('item_list', array( + 'items' => $items, + 'attributes' => array('class' => array('pager')), + )); + } +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/theme/panels-default-style-render-region.theme.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/theme/panels-default-style-render-region.theme.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,8 @@ + array( + array('class' => array('choice-flag')), + drupal_render($form[$key]['chtext']), + ), + 'class' => array('draggable'), + ); + if ($is_admin) { + $row['data'][] = drupal_render($form[$key]['chvotes']); + } + $row['data'][] = drupal_render($form[$key]['weight']); + + // Add any additional classes set on the row. + if (!empty($form[$key]['#attributes']['class'])) { + $row['class'] = array_merge($row['class'], $form[$key]['#attributes']['class']); + } + + $rows[] = $row; + } + + $output = theme('table', array('header' => $headers, 'rows' => $rows, 'attributes' => array('id' => 'poll-choice-table', 'class' => array('poll-choice-table')))); + $output .= drupal_render_children($form); + return $output; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/theme/status-messages.theme.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/theme/status-messages.theme.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,43 @@ + t('Status message'), + 'error' => t('Error message'), + 'warning' => t('Warning message'), + ); + foreach (drupal_get_messages($display) as $type => $messages) { + $output .= '
    '; + if (!empty($status_heading[$type])) { + $output .= '

    ' . $status_heading[$type] . "

    "; + } + if (count($messages) > 1) { + $output .= '
      '; + foreach ($messages as $message) { + $output .= '
    • ' . $message . '
    • '; + } + $output .= '
    '; + } + else { + $output .= $messages[0]; + } + $output .= '
    '; + } + + return $output; +} diff -r d72257b2ddc2 -r a75ead649730 sites/all/themes/omega/omega/theme/system-themes-page.theme.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sites/all/themes/omega/omega/theme/system-themes-page.theme.inc Fri Sep 20 11:18:21 2013 +0100 @@ -0,0 +1,67 @@ +'; + + foreach ($variables['theme_group_titles'] as $state => $title) { + if (!count($theme_groups[$state])) { + // Skip this group of themes if no theme is there. + continue; + } + // Start new theme group. + $output .= '

    '. $title .'

    '; + + foreach ($theme_groups[$state] as $theme) { + // Theme the screenshot. + if($theme->screenshot) { + $theme->screenshot['attributes']['class'] = str_replace('screenshot', 'theme-selector__screenshot', $theme->screenshot['attributes']['class']); + $screenshot = theme('image', $theme->screenshot); + } else { + $screenshot = '
    ' . t('No Screenshot') . '
    '; + } + + // Localize the theme description. + $description = t($theme->info['description']); + + // Style theme info + $notes = count($theme->notes) ? ' (' . join(', ', $theme->notes) . ')' : ''; + $theme->classes[] = 'theme-selector'; + $theme->classes[] = 'theme-selector--' . $state; + if($theme->is_default) { + $theme->classes = str_replace('theme-default', 'theme-selector--default', $theme->classes); + } + $theme->classes[] = 'clearfix'; + $output .= '
    ' . $screenshot . '

    ' . $theme->info['name'] . ' ' . (isset($theme->info['version']) ? $theme->info['version'] : '') . $notes . '

    ' . $description . '
    '; + + // Make sure to provide feedback on compatibility. + if (!empty($theme->incompatible_core)) { + $output .= '
    ' . t('This version is not compatible with Drupal !core_version and should be replaced.', array('!core_version' => DRUPAL_CORE_COMPATIBILITY)) . '
    '; + } + elseif (!empty($theme->incompatible_php)) { + if (substr_count($theme->info['php'], '.') < 2) { + $theme->info['php'] .= '.*'; + } + $output .= '
    ' . t('This theme requires PHP version @php_required and is incompatible with PHP version !php_version.', array('@php_required' => $theme->info['php'], '!php_version' => phpversion())) . '
    '; + } + else { + $output .= theme('links', array('links' => $theme->operations, 'attributes' => array('class' => array('theme-selector__operations', 'clearfix')))); + } + $output .= '
    '; + } + $output .= '
    '; + } + $output .= ''; + + return $output; +}