diff --git a/sites/all/modules/bean/CHANGELOG.TXT b/sites/all/modules/bean/CHANGELOG.TXT new file mode 100644 index 0000000000000000000000000000000000000000..0093ab0b899b0b997e132a55c9491b29b98a08c3 --- /dev/null +++ b/sites/all/modules/bean/CHANGELOG.TXT @@ -0,0 +1,252 @@ +Current API VERSION: 5. + +bean 7.x-1.x-dev +================ +Issue #1911224 by DamienMcKenna: Added Support for references_dialog(). +Issue #1910566 by Bès: Added Use label of view mode in bean add and edit form. +Issue #1912444 by John Bickar: Fixed Fatal Error: Call to undefined function entity_language(). +Issue #1354824 by DamienMcKenna, willvincent | mrfelton: Fixed Unable to add fields to newly created bean type. +Issue #1918188 by eugene.ilyin: Added Few useful views handlers for work with bean blocks. +Issue #1916938: Fixed Empty block name in entity reference field. +Issue #1924006 by DamienMcKenna: Added Convert bean URL to lowercase. +Issue #1920296 by fubhy | indytechcook: Fixed Can't delete revisions. + +bean 7.x-1.0 +================ +Issue #1850948 by indytechcook: Fixed Bean revision fields are not accessible in EntityFieldQuery. + +bean 7.x-1.0-rc9 +================ +Make sure bean_reset rebuilds the menu correctly. +Fix issue in install of shortcuts. +#1691482: Moved contextual links back to bean_view and check that return of plugin is a render array +#1891532: Remove check_plain from bean entity class +Issue #1897834 Fixed Bean, Features and permissions. +Issue #1900104: Fixed Error when disabling bean. +Issue #1892272 by stijndm: Fixed Unable to edit exported bean types due to form API syntax error. + +bean 7.x-1.0-rc9 +================ +Issue #1885958 by Steven Jones: Added EntityMetadataWrapper sets not working. +Issue #1893950: Fixed Ctools warnings in log. +Move check_plain into the entity class. +Issue #1887778 by Deciphered: Fixed Incorrect operations colspan. +Issue #1891358 by DamienMcKenna: Fixed Data loss if both 'Create new revision" and "Set Revision as default" options unchecked. +Issue #1886002 by DamienMcKenna | paulhhowells: Fixed Administer Bean Settings x2. +Issue #1889892 Fixed bean_reset() calls menu_rebuild(), which already happens during drupal_flush_all_caches(). + +bean 7.x-1.0-rc8 +================ +Remove batches and use correct cache clear function. +Issue #1883232 by Steven Jones: Fixed Bean EntityMetadataWrapper integration broken. +Fix bean unit test. +Issue #1885238 by indytechcook: Fixed xss bean type label not escaped sufficiently. + +bean 7.x-1.0-rc7 +================ +Issue #1828096 by Brandonian: Fixed bean_update_7007 does not work with real-world data. +Issue #1691482 by Brandonian | mrfelton: Fixed contextual links not working. +Issue #1601960 by indytechcook Fixed [bean_all()] Endless recursion in combination with views. +Issue #1611676 by barraponto | hazah: Added Views filter by bean type. +Issue #1799776 by bforchhammer: Fixed entity translation regressions. +Issue #1710256 by jonhattan, indytechcook: Fixed «Delete block type» button misplaced. +Issue #1785950 by jonhattan | indytechcook: Fixed Revert and delete should be separate operations. +Issue #1786036 by jonhattan | indytechcook: Fixed Caches not completely cleared. +Integrate Bean Revisions +Issue #1814068 by jonhattan: Remove leftover patch files in repo. +Issue #1833176 by darrenmothersele: Fixed List Shortcut module as a dependency or remove from bean_install(). +Issue #1836798 by bhauff: Block Label used rather than Title on block/delta and block/delta/view. +Issue #1844538 by mrfelton: Fixed Field data missing when editing language neutral beans. +Issue #1839966 by ultimateboy: Fixed block/add doesn't check for access before generating list. +Issue #1838088 by jamesharv: Fixed Adding bean type and permissions to existing features module can cause drush cache clear to fail. +Issue #1845974 by indytechcook: Fixed Block Admin label is correct. +Issue #1793586 by Mixologic | indytechcook: Fixed Editing Bean Content Does not Trigger Page Cache Clear. +Issue #1870730 by jm.federico: Fixed bean_view() changes the current page title. +Issue #1859450 by jonhattan: Drop dependency on block.module. + +bean 7.x-1.0-rc6 +================ +Issue #1649312: Bean Usage sub-module +Issue #1691458 by mrfelton: Fixed Unable to access bean overview page unless administer bean permissions is granted. +Issue #1698548 by rsaddington: Fixed Block types tables has too many td's. +Issue #1534722 by broeker, skwashd | tanc: Added Make custom bean forms compatible with Display Suite. +Issue #1684250 by rimen|indytechcook: Transliteration module integration. +Issue #1663264 by brantwynn: Fixed Status Message Text is wrong during Bean Create and Update. +Issue #1717540 by jonhattan: Fixed [bean_all()] Fatal error when creating a block instance. +Issue #1751268 by skwashd: Added Support Services API v3002. +Issue #1770190 by bforchhammer: Fixed entity translation integration. +Issue #1535444 by indytechcook: Fixed display of permission description. + + +bean 7.x-1.0-rc5 +================ +Fixed unit testing issues with Bean permissions. febbraro +Fixed the default plugin fall back for a Bean. febbraro +Added default no-op tests on unimplemented unit tests. febbraro +Issue #1541802: Add back bean_all module +Issue #1538852 by alexweber: Added 'Package" for Bean modules in .info file +Issue #1535444 by indytechcook: Added permission for block_view() url. +Issue #1535444 by barraponto: Fixed mis type in bean_permission. +Issue #1541968 by alexweber: Fixed Fatal error when uninstalling Bean Admin UI. +Issue #1510508 by mraichelson: Fixed issue with sorting with workbench integration +Issue #1510508 by jhedstrom: Fixed access permissions to workbench" +Issue #1559944 by recidive, skwashd: Added Services support. + +bean 7.x-1.0-rc4 +================ +Issue #1510508: Added Integrate with Workbench. +Issue #1503270 by Denes.Szabo|indytechcook: + Added Block list displays the filter form when have not defined a bean type yet. +Issue #1519730 by skwashd: Fixed Plugin @plugin of plugin type bean:@type points to nonexistent file bean_admin_ui()/BeanCustom.class.php for class handler. +Issue #1537456 by barraponto|indytechcook: Fixed Better titles for bean/add/%bean-type and bean/edit/%bean-delta. +Issue #1170188 by barraponto, alexweber | mrfelton: Added menu items for Bean Type edit, delete, manage fields, display fields pages. +Issue #1491956 by recidive: Add UUID/Deploy support. + +bean 7.x-1.0-rc3 +================ +Fixed issue with bean type filter at admin/content/blocks +Issue #1452368 by Denes.Szabo: Fixed Empty description not handled. +Issue #1458298 by tim.cosgrove: Fixed Implementation of Contextual Links for Beans + causes block to appear even with content is otherwise empty. +Issue #1376902 by willvincent: Fixed Plugin container of plugin type bean:types points to nonexistent file. +Issue #1354824 by willvincent | mrfelton: Fixed Unable to add fields to newly created bean type. +Fix coding standards and use the correct scope in functions + +bean 7.x-1.0-rc2 +================ +DO NOT USE + +bean 7.x-1.0-rc1 +================ +Added description to beans +Improve block/add and admin/structure/block-types by alphabetizing and making more consistent with node/add +Added Tests +Issue #1389446 by rogical: Added config link in info file. +Issue #1216572 by duellj: Fixed Block cache not flushed after editing a bean. +fixing a couple of errant block_types (underscore) +Issue #1345966 by brantwynn and indytechcook: Change bean page to use EntityFieldQuery + + +bean 7.x-1.0-beta10 +================ +Issue #1288438 by drewish: Fixed Definitive broken admin page, when filter type isn't set. +fixing schema field for delta in bean.info.inc by tim.cosgrove +Issue #1376902 by indytechcook: Fixed Plugin container of plugin type bean:types points to nonexistent file. +Issue #1371280 by duellj: Fixed New %bean_delta() URL breaks translations. +Issue #1371362 by duellj: Added Provide integration with title.module for translatable block titles. +Issue #1351694 by indytechcook: Check if bean type class exists when loading bean. +Issue #1387242 by brantwynn and indytechcook: Bean module not aligned with Drupal's coding standards. +- API Change: Changed the name of class name for Drupal Standards. All plugins will need to be updated + - bean_plugin renamed to BeanPlugin + - bean_default renamed to BeanDefault + - bean_type_plugin_interface renamed to BeanTypePluginInterface + - bean_custom rename to BeanCustom + + +bean 7.x-1.0-beta9 +================ +Issue #1359472 by indytechcook: Error while uninstalling bean. +Issue #1356088 by indytechcook: Changed path of block types. +Issue #1355818 by Draknek: Fixed Typo in permission description. +Issue #1344146 by aheimlich: Fixed bean.tpl.php not being used. +Change how beans types classes are loaded. Use the Code Registry rather then cto0ls includes + - API CHANGE NOTICE This requires you to have the plugin files in the info file. + - You no longer need to specify a "path" in the plugin. + +bean 7.x-1.0-beta8 +================== +Update to use new entity api methods. Code clean up and minor bug fixes in delete and redirects +#1334476: Add form_state to bean form plugin +#1335482 by jasperknops: Fixed No check if delta is unique. +#1340338 by duellj and indytechcook: Fixed Notice if editing bean without access to change view mode. +#1342360: Fixed creating of new bean object. +Update hook_uninstall to add field_attach_delete_bundle +#1332440 by duellj: Fixed Bean default fields in edit form should come first. +#1330868: Reworked loading of entity from DB to avoid issues with loading plugin + +bean 7.x-1.0-beta7 +================== +DO NOT USE THIS RELEASE + +bean 7.x-1.0-beta6 +================== +API CHANGE HAS BEEN INTRODUCED. SEE #1323876: Entity API 7.x-1.0-beta11 requires new Entity::view() signature. Change your version numbers in your custom block types. + +Increment version level +#1323876 by adamdicarlo: Fixed Entity API 7.x-1.0-beta11 requires new Entity::view() signature. +#1319918: contextual links missing + +bean 7.x-1.0-beta5 +================== +view modes should default to "default" not "full" +#1317016: Add the ability to use different view modes in beans +#1316996: Add required fields to the meta data. + +bean 7.x-1.0-beta4 +================== +#1315582: Fix notice error on install +Updated Documentation and added bean.api.php. +#1309126: Add machine names to beans +#1309126 by adamdicarlo and indytechcook: Add machine names to Beans to use as Delta +#1264686: Adding hook_bean_access() to expose the access decision in bean_access() to other modules. Also adding a menu access callback for the Bean add page (block/add). +#1179420: Unable to install Bean Admin UI from an installation profile. +Fixing code formatting. +#1302224 by aroq: Make bean entities translatable by entity_translate module +#1291274 Parse error: syntax error, unexpected ':' with PHP 5.2 +#1288438 Update filter on bean content page + +bean 7.x-1.0-beta3 +================== +Bug fixes include fixing broken access to the bean admin UI + +Issue #1272402: bean_get_all_beans() fails if called more than once: bean_get_all_beans() fails if called more than once +Issue #1272200: Permissions in bean_admin_ui by ultimateboy: Fix permission in bean_admin_ui +Fix bug caused by caching bean results. + +bean 7.x-1.0-beta2 +================== +Fix for compatibility with latest version of EntityAPI. + +bean 7.x-1.0-beta1 +================== +API Change +The interface BeanTypePluginInterface has changed the validate method to include &$form_state as the second argument. Be sure to change any plugins using the validate method. + +#1221210: Filters for admin/content/blocks: Add filters to bean listing +#1239596: Remove the .gitignore file from the repository: Remove .gitignore +#1221008: Add a MENU_NORMAL_ITEM for the block admin page: Define admin page as MENU_LOCAL_TASK | MENU_NORMAL_ITEM +Add form_state to the validate method +Fixing permission string for Manage Block Types page. +Fix some small code style issues +#1207152: Form level submit handlers not called when bean save button is used - ensure that form level submit handlers are called when bean save button is used +Using block_flush_caches() which triggers _block_rehash() for all themes to clear related caches when a bean is saved. +Adding a dependency on the block module. +Adding check to ensure that the BeanTypePluginInterface interface is loaded. +Adding check to verify that the bean plugin class loaded successfully. + +bean 7.x-1.0-alpha4 +================== +Added missing features.inc file for exportable support +Remove rougr dsm statement +Issue #1196774: Add bean plugin interface: Add code interface for a cleaner implementation + +bean 7.x-1.0-alpha3 +================== +#1167506: Unable to view newly created bean ensure that beans load correcty on older version of php +#1184498: Improvements to the bean administration page improvements to the bean admin page +#1194004: Bean add form submit handler not called when another module alters the form - manually attach validate and submit handlers to bean add/edit form +#1192822: Add logging on bean creation and updating - Add logging on bean create/edit +#1160056: Make Bean types exportable by mrfelton, fabsor: Make bean types exportable + +bean 7.x-1.0-alpha2 +================== +#1167368: Bean plugins not returned from the cache properly by mrfelton: Bean plugins not returned from the cache properly. Be sure to clear caches after pulling this code +#1167506: Unable to view newly created bean, #1167552: Undefined index: alumni_header in bean_fetch_plugin_info() bean.module line 200: Cache and static caching resetting issues +#1173634: Add contextual 'Edit' link for beans add contextual links by mrfelton +#1171200: Deleting Bean Leaves Records in Block Table Delete Bean bugs +#1172884: Missing permissions make it impossible for anonymous users to view Beans by mrfelton Fixed incorrect name of hook_permission + +bean 7.x-1.0-alpha1 +================== +Initial Release + diff --git a/sites/all/modules/bean/LICENSE.txt b/sites/all/modules/bean/LICENSE.txt new file mode 100644 index 0000000000000000000000000000000000000000..d159169d1050894d3ea3b98e1c965c4058208fe1 --- /dev/null +++ b/sites/all/modules/bean/LICENSE.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/sites/all/modules/bean/README.txt b/sites/all/modules/bean/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..a5dd0424b7f3e3d287598a44a5c71dc0fbb42f96 --- /dev/null +++ b/sites/all/modules/bean/README.txt @@ -0,0 +1,29 @@ +Bean (Bean Entities Aren't Nodes) +================================== + +The bean module was created to have the flexibility of +Block Nodes without adding to the node space. + +Bean Types +---------- + +A Bean Type (or Block Type) is a bundle of beans (blocks). +Each Bean type is defined by a ctools plugin and are fieldable. +Currently Bean Types are only defined in hook_bean_plugins(). + +If you enable beans_admin_ui you can add/edit bean types at +admin/structure/block-types + +Beans +----- + +Beans can be added at block/add + +Example Bean Type Plugins +------------------------- +https://github.com/opensourcery/os_slideshow +http://drupal.org/project/beanslide +http://treehouseagency.com/blog/neil-hastings/2011/09/21/building-custom... +http://drupal.org/sandbox/brantwynn/1369224 +http://drupal.org/sandbox/brantwynn/1376658 +https://gist.github.com/1460818 diff --git a/sites/all/modules/bean/bean.api.php b/sites/all/modules/bean/bean.api.php new file mode 100644 index 0000000000000000000000000000000000000000..f8d1b93ffda5f74ef75e48eacb8aa1553323a6cf --- /dev/null +++ b/sites/all/modules/bean/bean.api.php @@ -0,0 +1,74 @@ +<?php + +/** + * Implements hook_bean_types_api_info(). + * + * Tell the bean module that you are implemented a plugin and + * which version of the API are you using. + * + * THIS IS REQUIRED + */ +function hook_bean_types_api_info() { + return array( + 'api' => 4, + ); +} + +/** + * Implements hook_bean_types(). + * + * Beans uses ctools plugins to define the block types. + * All plugin files must be registered in the .info file. + */ +function hook_bean_types() { + $plugins = array(); + + $plugins['plugin_key'] = array( + 'label' => t('Title'), + 'description' => t('Description'), + // This is optional. Set it to TRUE if you do not want the plugin to be displayed in the UI + 'abstract' => FALSE, + 'handler' => array( + 'class' => 'ClassName', + 'parent' => 'bean', + ), + ); + + return $plugins; +} + +/** + * Implements hook_bean_access(). + * + * Access callback for beans + * + * @param $bean + * Tthe fully loaded bean object + * @param $bean + * The access type of view, edit, delete, create + * @param $account + * The user account + * + * @return boolean + * True if access is allowed, FALSE if not. + */ +function hook_bean_access($bean, $op, $account) { + return TRUE; +} + +/** + * Implements hook_bean_submit(). + * + * React to the bean form submit. + */ +function hook_bean_form_submit($form, $form_state) { + +} + +/** + * Implements hook_bean_cache_clear(). + */ +function hook_bean_cache_clear() { + +} + diff --git a/sites/all/modules/bean/bean.info b/sites/all/modules/bean/bean.info new file mode 100644 index 0000000000000000000000000000000000000000..e894f7807f65aabe44ef24a1d097baf22d1559f0 --- /dev/null +++ b/sites/all/modules/bean/bean.info @@ -0,0 +1,22 @@ +name = Bean +description = Create Bean (Block Entities) +core = 7.x +files[] = includes/bean.core.inc +files[] = includes/bean.info.inc +files[] = plugins/base.inc +files[] = includes/translation.handler.bean.inc +files[] = views/views_handler_filter_bean_type.inc +files[] = views/views_handler_field_bean_type.inc +files[] = views/views_handler_field_bean_edit_link.inc +files[] = views/views_handler_field_bean_delete_link.inc +files[] = bean.test +dependencies[] = entity +dependencies[] = ctools +package = Bean + +; Information added by drupal.org packaging script on 2013-02-27 +version = "7.x-1.1" +core = "7.x" +project = "bean" +datestamp = "1361977163" + diff --git a/sites/all/modules/bean/bean.install b/sites/all/modules/bean/bean.install new file mode 100644 index 0000000000000000000000000000000000000000..0620a8870de2bb07056afac3af310f16b85dc88e --- /dev/null +++ b/sites/all/modules/bean/bean.install @@ -0,0 +1,425 @@ +<?php + +/** + * @file + * Bean installation routines + */ + +/** + * Implements hook_schema(). + */ +function bean_schema() { + $schema['bean'] = array( + 'description' => 'Stores bean items.', + 'fields' => array( + 'bid' => array( + 'type' => 'serial', + 'not null' => TRUE, + 'description' => 'Primary Key: Unique bean item ID.', + 'unsigned' => TRUE, + ), + 'vid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'description' => 'Revision ID', + 'default' => 0, + 'unsigned' => TRUE, + ), + 'delta' => array( + 'description' => "The bean's {block}.delta.", + 'type' => 'varchar', + 'length' => 32, + 'not null' => TRUE, + ), + 'label' => array( + 'description' => 'The Displays in the Admin page.', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + ), + 'title' => array( + 'description' => 'The human-readable name of this bean.', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + ), + 'type' => array( + 'description' => 'The {bean_type}.type of this bean.', + 'type' => 'varchar', + 'length' => 32, + 'not null' => TRUE, + 'default' => '', + ), + 'view_mode' => array( + 'description' => 'The View mode to use as the bean.', + 'type' => 'varchar', + 'length' => 32, + 'not null' => TRUE, + 'default' => 'default', + ), + 'data' => array( + 'type' => 'text', + 'not null' => FALSE, + 'size' => 'big', + 'serialize' => TRUE, + 'description' => 'A serialized array of additional data related to this bean.', + ), + 'uid' => array( + 'description' => 'The author of the revision.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'created' => array( + 'description' => 'The Unix timestamp when the entity was created.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), + 'changed' => array( + 'description' => 'The Unix timestamp when the entity was most recently saved.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), + ), + 'foreign keys' => array( + 'type' => array( + 'table' => 'bean_type', + 'columns' => array('type' => 'type'), + ), + 'bean_revision' => array( + 'table' => 'bean_revision', + 'columns' => array('vid' => 'vid'), + ) + ), + 'primary key' => array('bid'), + 'unique keys' => array( + 'vid' => array('vid'), + 'delta' => array('delta'), + ), + ); + + $schema['bean_revision'] = array( + 'description' => 'Stores bean items.', + 'fields' => array( + 'bid' => array( + 'description' => 'The {bean} this version belongs to.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'vid' => array( + 'description' => 'The primary identifier for this version.', + 'type' => 'serial', + 'unsigned' => TRUE, + 'not null' => TRUE, + ), + 'uid' => array( + 'description' => 'The author of the revision.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'delta' => array( + 'description' => "The bean's {block}.delta.", + 'type' => 'varchar', + 'length' => 32, + 'not null' => TRUE, + 'default' => 0, + ), + 'label' => array( + 'description' => 'The Displays in the Admin page.', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + ), + 'title' => array( + 'description' => 'The human-readable name of this bean.', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + ), + 'type' => array( + 'description' => 'The {bean_type}.type of this bean.', + 'type' => 'varchar', + 'length' => 32, + 'not null' => TRUE, + 'default' => '', + ), + 'view_mode' => array( + 'description' => 'The View mode to use as the bean.', + 'type' => 'varchar', + 'length' => 32, + 'not null' => TRUE, + 'default' => 'default', + ), + 'data' => array( + 'type' => 'text', + 'not null' => FALSE, + 'size' => 'big', + 'serialize' => TRUE, + 'description' => 'A serialized array of additional data related to this bean.', + ), + 'log' => array( + 'description' => t('A log message associated with the revision.'), + 'type' => 'text', + 'size' => 'big', + ), + 'created' => array( + 'description' => 'The Unix timestamp when the entity was created.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), + 'changed' => array( + 'description' => 'The Unix timestamp when the entity was most recently saved.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), + ), + 'foreign keys' => array( + 'type' => array( + 'table' => 'bean_type', + 'columns' => array('type' => 'type'), + ), + 'version_bean' => array( + 'table' => 'bean', + 'columns' => array('bid' => 'bid'), + ) + ), + 'primary key' => array('vid'), + 'indexes' => array( + 'bid' => array('bid', 'vid'), + ), + ); + + return $schema; +} + +/** + * Implements hook_uninstall(). + */ +function bean_uninstall() { + // Make sure bean.module is include. + require dirname(__FILE__) . DIRECTORY_SEPARATOR . 'bean.module'; + // Bypass entity_load() as we cannot use it here. + foreach (bean_get_types() as $bean_type) { + field_attach_delete_bundle('bean', $bean_type->type); + } +} + +/** + * Implements hook_install(). + */ +function bean_install() { + + if (module_exists('shortcut')) { + $t = get_t(); + + // Load the default shortcut set + $shortcut_set = shortcut_default_set(); + $shortcut_set->links[] = array( + 'link_path' => 'block/add', + 'link_title' => $t('Add block'), + 'weight' => -18, + ); + $shortcut_set->links[] = array( + 'link_path' => 'admin/content/blocks', + 'link_title' => $t('Blocks'), + 'weight' => -18, + ); + + shortcut_set_save($shortcut_set); + } +} +/** + * Implements hook_disable(). + */ +function bean_disable() { + // Remove all of the currently placed blocks + + // Delete any blocks + // @see block_custom_block_delete_submit() + if (module_exists('block')) { + db_delete('block') + ->condition('module', 'bean') + ->execute(); + db_delete('block_role') + ->condition('module', 'bean') + ->execute(); + + // @see node_form_block_custom_block_delete_submit() + db_delete('block_node_type') + ->condition('module', 'bean') + ->execute(); + } +} + + +/** + * Update Registry to implement new Code Interface + */ +function bean_update_7001() { + registry_rebuild(); + return t('Registry has been rebuilt'); +} + +/** + * Add delta field. + */ +function bean_update_7002() { + $spec = array( + 'description' => "The bean's {block}.delta.", + 'type' => 'varchar', + 'initial' => '', + 'length' => 32, + 'not null' => TRUE, + ); + db_add_field('bean', 'delta', $spec); + db_update('bean') + ->expression('delta', 'bid') + ->execute(); + return t('Bean delta field added.'); +} + +/** + * Add view_mode field. + */ +function bean_update_7003() { + $spec = array( + 'description' => "The view mode of the bean.", + 'type' => 'varchar', + 'initial' => 'default', + 'length' => 32, + 'not null' => TRUE, + ); + db_add_field('bean', 'view_mode', $spec); + db_update('bean') + ->fields(array('view_mode' => 'default')) + ->execute(); + return t('Bean view mode field added.'); +} + +/** + * Update Registry to implement new Code Interface + */ +function bean_update_7004() { + registry_rebuild(); + return t('Registry has been rebuilt'); +} + +/** + * Rebuild the menus + */ +function bean_update_7005() { + registry_rebuild(); + menu_rebuild(); + return t('Registry and Menu have been rebuilt'); +} + +/** + * Rebuild the registry to include new translation class + */ +function bean_update_7006() { + registry_rebuild(); + return t('Registry and Menu have been rebuilt'); +} + +/** + * Add a Bean Revision Table + */ +function bean_update_7007(&$return) { + $t = get_t(); + drupal_load('module', 'bean'); + cache_clear_all('schema', 'cache'); // So we actually load the current schema. + $schema = bean_schema(); + $bean = $schema['bean']; + $bean_revision = $schema['bean_revision']; + + /** + * Adding an unsigned attribute to our primary key. Because our primary key is an auto_increment, + * we can't drop it without a MySQL error. Instead, we're doing a MySQL-specific call to perform + * our alter, and leaving the Drupal-recommended way of doing things as default. + * + * Reference (error): http://stackoverflow.com/questions/2111291/remove-primary-key-in-mysql + * Reference: http://api.drupal.org/api/drupal/includes%21database%21database.inc/function/db_change_field/7 + */ + switch(db_driver('mysql')) { + case 'mysql': + db_query('ALTER TABLE {bean} MODIFY bid INT UNSIGNED NOT NULL AUTO_INCREMENT'); + break; + default: + db_drop_primary_key('bean'); + db_change_field('bean', 'bid', 'bid', $bean['fields']['bid'], array('primary key' => array('bid'))); + } + + db_add_field('bean', 'vid', $bean['fields']['vid']); + + db_create_table('bean_revision', $bean_revision); + + $results = db_query('SELECT * FROM {bean}'); + foreach ($results as $row) { + $bean_revision = array( + 'bid' => $row->bid, + 'uid' => variable_get('bean_uid', 1), + 'delta' => $row->delta, + 'label' => $row->label, + 'title' => $row->title, + 'type' => $row->type, + 'view_mode' => $row->view_mode, + 'data' => $row->data, + 'log' => $t('Added via update script'), + 'created' => REQUEST_TIME, + 'changed' => REQUEST_TIME, + ); + + $options = array('return' => Database::RETURN_INSERT_ID); + $vid = db_insert('bean_revision', $options) + ->fields($bean_revision) + ->execute(); + + db_update('bean') + ->fields(array('vid' => $vid)) + ->condition('bid', $row->bid) + ->execute(); + } + // Add unique key back after populating our table. + db_add_unique_key('bean', 'vid', array('vid')); + + return $t('Bean Revision table has been added.'); +} + +/** + * Add uid, changed and created to bean table + */ +function bean_update_7010(&$sand) { + $t = get_t(); + $schema = bean_schema(); + + db_add_field('bean', 'uid', $schema['bean_revision']['fields']['uid']); + db_add_field('bean', 'created', $schema['bean_revision']['fields']['created']); + db_add_field('bean', 'changed', $schema['bean_revision']['fields']['changed']); + + $results = db_query("SELECT bid, uid, created, changed from {bean_revision} GROUP BY bid ORDER BY changed"); + foreach($results as $row) { + db_update('bean') + ->fields(array( + 'uid' => $row->uid, + 'created' => $row->created, + 'changed' => $row->changed, + )) + ->condition('bid', $row->bid) + ->execute(); + } + + return $t('Bean Table updated and data upgraded'); +} diff --git a/sites/all/modules/bean/bean.module b/sites/all/modules/bean/bean.module new file mode 100644 index 0000000000000000000000000000000000000000..625040be41b6e0e066b7c73be6978fb6cefd8f68 --- /dev/null +++ b/sites/all/modules/bean/bean.module @@ -0,0 +1,1027 @@ +<?php + +/** + * @file + * Block Entity + */ + +/** + * Implements hook_entity_info(). + */ +function bean_entity_info() { + $return = array( + 'bean' => array( + 'label' => t('Block'), + 'entity class' => 'Bean', + 'controller class' => 'BeanEntityAPIController', + 'base table' => 'bean', + 'revision table' => 'bean_revision', + 'fieldable' => TRUE, + 'entity keys' => array( + 'id' => 'bid', + 'bundle' => 'type', + 'label' => 'title', + 'name' => 'delta', + 'revision' => 'vid', + 'default revision' => 'default_revision', + ), + 'bundles' => array(), + 'bundle keys' => array( + 'bundle' => 'type', + ), + 'label callback' => 'entity_class_label', + 'uri callback' => 'entity_class_uri', + 'access callback' => 'bean_access', + 'module' => 'bean', + 'metadata controller class' => 'BeanMetadataController', + 'view modes' => array( + 'default' => array( + 'label' => t('Default'), + 'custom settings' => FALSE, + ), + ), + 'field replacement' => array( + 'title' => array( + 'field' => array( + 'type' => 'text', + 'cardinality' => 1, + 'translatable' => TRUE, + ), + 'instance' => array( + 'label' => t('Title'), + 'description' => t('The Title of the block.'), + 'required' => FALSE, + 'settings' => array( + 'text_processing' => 0, + ), + 'widget' => array( + 'weight' => -5, + ), + ), + ), + ), + 'translation' => array( + 'entity_translation' => array( + 'class' => 'EntityTranslationBeanHandler', + 'base path' => 'block/%bean_delta', + 'path wildcard' => '%bean_delta', + ), + ), + ), + ); + + foreach (bean_get_types() as $type) { + if (!empty($type)) { + $return['bean']['bundles'][$type->type] = array( + 'label' => $type->getLabel(), + 'description' => $type->getDescription(), + 'admin' => array( + 'path' => 'admin/structure/block-types/manage/%bean_type', + 'real path' => 'admin/structure/block-types/manage/' . $type->buildURL(), + 'bundle argument' => 4, + 'access arguments' => array('administer bean types'), + ), + ); + } + } + + return $return; +} + +/** + * Implements hook_menu(). + */ +function bean_menu() { + $items = array(); + + $items['block/add'] = array( + 'title' => 'Add Block', + 'page callback' => 'bean_add_page', + 'access arguments' => array('add'), + 'access callback' => 'bean_add_page_access', + 'file' => 'includes/bean.pages.inc', + ); + + foreach (bean_get_types() as $type) { + if (!empty($type)) { + $items['block/add/' . $type->buildURL()] = array( + 'title' => $type->getLabel(), + 'title callback' => 'check_plain', + 'page callback' => 'bean_add', + 'page arguments' => array($type->type), + 'access arguments' => array('create any ' . $type->type . ' bean'), + 'file' => 'includes/bean.pages.inc', + ); + } + } + + $items['block/%bean_delta'] = array( + 'title' => 'Block', + 'page callback' => 'bean_view_page', + 'page arguments' => array(1), + 'access arguments' => array('view bean page'), + 'file' => 'includes/bean.pages.inc', + ); + + $items['block/%bean_delta/view'] = array( + 'title' => 'View', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'context' => MENU_CONTEXT_NONE, + 'weight' => -20, + ); + + + $items['block/%bean_delta/edit'] = array( + 'title' => 'Edit Block', + 'type' => MENU_LOCAL_TASK, + 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE, + 'page callback' => 'bean_edit', + 'page arguments' => array(1), + 'access arguments' => array('edit', 1), + 'access callback' => 'bean_access', + 'file' => 'includes/bean.pages.inc', + ); + + $items['block/%bean_delta/delete'] = array( + 'title' => 'Delete Block', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('bean_delete_confirm', 1), + 'access callback' => 'bean_access', + 'access arguments' => array('delete', 1), + 'weight' => 1, + 'type' => MENU_LOCAL_TASK, + 'context' => MENU_CONTEXT_NONE, + 'file' => 'includes/bean.pages.inc', + ); + + $items['block/%bean_delta/revisions'] = array( + 'title' => 'Revisions', + 'page callback' => 'bean_revisions_page', + 'page arguments' => array(1), + 'access arguments' => array('view bean revisions'), + 'file' => 'includes/bean.pages.inc', + 'type' => MENU_LOCAL_TASK, + ); + + $items['block/%bean_delta/revisions/%'] = array( + 'title callback' => 'bean_revision_title', + 'title arguments' => array(1), + 'page callback' => 'bean_view', + 'page arguments' => array(1), + 'access callback' => 'bean_access', + 'access arguments' => array('view', 1), + 'file' => 'includes/bean.pages.inc', + 'load arguments' => array(3), + ); + + $items['block/%bean_delta/revisions/%/view'] = array( + 'title' => 'View', + 'page callback' => 'bean_view', + 'page arguments' => array(1), + 'access callback' => 'bean_access', + 'access arguments' => array('view', 1), + 'file' => 'includes/bean.pages.inc', + 'load arguments' => array(3), + 'weight' => -10, + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'context' => MENU_CONTEXT_NONE, + ); + + $items['block/%bean_delta/revisions/%/edit'] = array( + 'title' => 'Edit', + 'page callback' => 'bean_edit', + 'page arguments' => array(1), + 'access callback' => 'bean_access', + 'access arguments' => array('edit', 1), + 'file' => 'includes/bean.pages.inc', + 'load arguments' => array(3), + 'type' => MENU_LOCAL_TASK, + 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE, + ); + + $items['block/%bean_delta/revisions/%/set-default'] = array( + 'title' => 'Set Default', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('bean_set_default_confirm', 1), + 'access callback' => 'bean_access', + 'access arguments' => array('edit', 1), + 'file' => 'includes/bean.pages.inc', + 'load arguments' => array(3), + 'type' => MENU_LOCAL_TASK, + 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE, + ); + + $items['block/%bean_delta/revisions/%/delete'] = array( + 'title' => 'Delete', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('bean_delete_revision_confirm', 1), + 'access callback' => 'bean_access', + 'access arguments' => array('delete', 1), + 'file' => 'includes/bean.pages.inc', + 'load arguments' => array(3), + 'weight' => 1, + 'type' => MENU_LOCAL_TASK, + 'context' => MENU_CONTEXT_NONE, + ); + + $items['admin/content/blocks'] = array( + 'title' => 'Blocks', + 'description' => 'Manage blocks used on your site.', + 'page callback' => 'bean_list', + 'access arguments' => array('access bean overview'), + 'file' => 'includes/bean.pages.inc', + 'type' => MENU_LOCAL_TASK | MENU_NORMAL_ITEM, + ); + + if (module_exists('devel')) { + $devel_path = drupal_get_path('module', 'devel'); + $items['block/%bean_delta/devel'] = array( + 'title' => 'Devel', + 'page callback' => 'devel_load_object', + 'page arguments' => array('bean', 1), + 'access arguments' => array('administer beans'), + 'type' => MENU_LOCAL_TASK, + 'file' => 'devel.pages.inc', + 'file path' => $devel_path, + 'weight' => 100, + ); + $items['block/%bean_delta/devel/load'] = array( + 'title' => 'Load', + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + $items['block/%bean_delta/devel/render'] = array( + 'title' => 'Render', + 'page callback' => 'devel_render_object', + 'page arguments' => array('bean', 1), + 'access arguments' => array('administer beans'), + 'file' => 'devel.pages.inc', + 'file path' => $devel_path, + 'type' => MENU_LOCAL_TASK, + 'weight' => 100, + ); + } + + return $items; +} + +/** + * Title callback + */ +function bean_revision_title($bean) { + return $bean->label(); +} + +/** + * Implements hook_admin_paths(). + */ +function bean_admin_paths() { + $paths = array( + 'block/*/edit' => TRUE, + 'block/*/delete' => TRUE, + 'block/*/revisions' => TRUE, + 'block/*/revisions/*/edit' => TRUE, + 'block/*/revisions/*/set-active' => TRUE, + 'block/*/revisions/*/delete' => TRUE, + 'block/add' => TRUE, + 'block/add/*' => TRUE, + ); + return $paths; +} + +/** + * Title of the bean + */ +function bean_page_title($bean) { + return $bean->label; +} + +/** + * Menu Argument Loader + */ +function bean_type_load($type) { + return bean_load_plugin_class(strtr($type, array('-' => '_'))); +} + +/** + * Gets an array of all bean types, keyed by the type name. + * + * @return BeanType + * Depending whether $type isset, an array of bean types or a single one. + */ +function bean_get_types() { + $bean_types = &drupal_static(__FUNCTION__); + + if (empty($bean_types)) { + $bean_types = bean_load_plugin_class_all(); + } + + return $bean_types; +} + +/** + * Fetch the widget plugin info + */ +function bean_fetch_plugin_info($plugin = NULL) { + $plugins = &drupal_static(__FUNCTION__); + ctools_include('plugins'); + + if (empty($plugins)) { + if (($cache = cache_get('bean_plugins')) && !empty($cache->data)) { + $plugins = $cache->data; + } + else { + $plugins = ctools_get_plugins('bean', 'types'); + + // Only use modules with the same version. + $allowed_modules = array_keys(ctools_plugin_api_info('bean', 'types', bean_min_version(), bean_current_version())); + foreach ($plugins as $key => $plugin_value) { + if (!in_array($plugin_value['module'], $allowed_modules) || ($plugin_value['abstract'])) { + unset($plugins[$key]); + } + } + cache_set('bean_plugins', $plugins); + } + } + + if (empty($plugin)) { + return $plugins; + } + else { + // Make sure the plugin is in the cache. + if (!isset($plugins[$plugin])) { + $plugin_info = ctools_get_plugins('bean', 'types', $plugin); + if (empty($allowed_modules)) { + $allowed_modules = array_keys(ctools_plugin_api_info('bean', 'types', bean_current_version(), bean_min_version())); + } + if (in_array($plugin_info['module'], $allowed_modules)) { + $plugins[$plugin] = $plugin_info; + + cache_set('bean_plugins', $plugins); + } + } + + // If we still don't have the plugin then return NULL. + if (empty($plugins[$plugin])) { + return NULL; + } + return $plugins[$plugin]; + } +} + +/** + * Reset the static variables and caches. + */ +function bean_reset($skip_menu_rebuild = FALSE) { + // Clear ctools cache. + ctools_include('plugins'); + ctools_get_plugins_reset(); + cache_clear_all('plugins:bean:types', 'cache'); + cache_clear_all('ctools_plugin_files', 'cache', TRUE); + + // Invoke modules to clear their caches. + foreach (module_implements('bean_cache_clear') as $module) { + module_invoke($module, 'bean_cache_clear'); + } + + // Rebuild ctools plugin types and the menu. + ctools_plugin_get_plugin_type_info(TRUE); + if (!$skip_menu_rebuild) { + menu_rebuild(); + } +} + +/** + * Implements hook_bean_cache_clear(). + */ +function bean_bean_cache_clear() { + // Clear static variables. + drupal_static_reset('bean_access'); + drupal_static_reset('bean_get_types'); + drupal_static_reset('bean_get_all_beans'); + drupal_static_reset('bean_fetch_plugin_info'); + drupal_static_reset('bean_load_plugin_class'); + + // Flush caches. + cache_clear_all('bean_plugins', 'cache'); +} + +/** + * Load a widget class + * + * @param $plugin_key string + * the key fo the plugin + * @return BeanTypePluginInterface | Boolean + * An instance of the bean class or FALSE if not loaded + */ +function bean_load_plugin_class($plugin_key = NULL) { + $cache = &drupal_static(__FUNCTION__); + + if (!isset($cache[$plugin_key])) { + ctools_include('plugins'); + $class = ctools_plugin_load_class('bean', 'types', $plugin_key, 'handler'); + if ($class && bean_check_plugin_class($class)) { + $cache[$plugin_key] = new $class(bean_fetch_plugin_info($plugin_key)); + } + } + + return isset($cache[$plugin_key]) ? $cache[$plugin_key] : FALSE; +} + +/** + * Check the plugin type class + * + * @param $class string + * The name of the bean type class + * @return Boolean + */ +function bean_check_plugin_class($class) { + $ref_class = new ReflectionClass($class); + if (in_array('BeanTypePluginInterface', $ref_class->getInterfaceNames())) { + return TRUE; + } + + return FALSE; +} + +/** + * Load all widget classes + */ +function bean_load_plugin_class_all() { + $return = array(); + + foreach (bean_fetch_plugin_info() as $plugin) { + if (!empty($plugin['name']) && $plugin['name'] !== 'bean' && $plugin_class = bean_load_plugin_class($plugin['name'])) { + $return[$plugin['name']] = $plugin_class; + } + } + + return $return; +} + +/** + * Load all beans + */ +function bean_get_all_beans() { + $beans = &drupal_static(__FUNCTION__); + + if (!isset($beans)) { + $query = new EntityFieldQuery(); + $result = $query + ->entityCondition('entity_type', 'bean') + ->execute(); + if (isset($result['bean'])) { + $beans = bean_load_multiple(array_keys($result['bean'])); + } + else { + $beans = array(); + } + } + + return $beans; +} + +/** + * Fetch a bean object. + * + * @param $bid + * Integer specifying the bean id. + * @param $reset + * A boolean indicating that the internal cache should be reset. + * @return + * A fully-loaded $bean object or FALSE if it cannot be loaded. + * + * @see bean_load_multiple() + */ +function bean_load($bid, $reset = FALSE) { + $beans = bean_load_multiple(array($bid), array(), $reset); + return reset($beans); +} + +/** + * Fetch a bean revision + * + * A new function to not break the bean_load API + */ +function bean_load_revision($bid, $vid, $reset = FALSE) { + $conditions = array('vid' => $vid); + $beans = bean_load_multiple(array($bid), $conditions, $reset); + return reset($beans); +} + +/** + * Fetch a bean object by its delta. + * + * @param $delta + * String specifying the bean delta. + * @param $reset + * A boolean indicating that the internal cache should be reset. + * @return Bean + * A fully-loaded $bean object or FALSE if it cannot be loaded. + */ +function bean_load_delta($delta, $reset = FALSE, $revision = NULL) { + $result = db_select('bean', 'b') + ->fields('b', array('bid')) + ->condition('delta', $delta) + ->execute(); + if ($bid = $result->fetchField()) { + if ($revision) { + return bean_load_revision($bid, $revision, $reset); + } + else { + return bean_load($bid, $reset); + } + } + return FALSE; +} + +/** + * Menu callback to load a bean by the delta + */ +function bean_delta_load($delta, $revision = NULL) { + return bean_load_delta($delta, FALSE, $revision); +} + +/** + * Load multiple beans based on certain conditions. + * + * @param $bids + * An array of bean IDs. + * @param $conditions + * An array of conditions to match against the {bean} table. + * @param $reset + * A boolean indicating that the internal cache should be reset. + * @return + * An array of bean objects, indexed by pid. + * + * @see entity_load() + * @see bean_load() + */ +function bean_load_multiple($bids = array(), $conditions = array(), $reset = FALSE) { + return entity_load('bean', $bids, $conditions, $reset); +} + +/** + * Delete a bean revision + */ +function bean_delete_revision($vid) { + return entity_get_controller('bean')->deleteRevision($vid); +} + +/** + * Implements hook_permissions(). + */ +function bean_permission() { + $perms = array( + 'administer bean types' => array( + 'title' => t('Administer block types'), + 'description' => t('Create and delete fields on beans, and set their permissions.'), + ), + 'administer beans' => array( + 'title' => t('Administer beans'), + 'description' => t('Edit and view all beans.'), + ), + 'access bean overview' => array( + 'title' => t('Access the Bean overview page'), + 'description' => t('Visit !url', array('!url' => "admin/content/blocks")), + ), + 'edit bean view mode' => array( + 'title' => t('Change the View Mode of the Bean'), + 'description' => t('Ability to change the view mode on the bean form'), + ), + 'view bean page' => array( + 'title' => t('View Bean page'), + 'description' => t('Visit !url', array('!url' => 'block/< delta >')), + ), + 'administer bean settings' => array( + 'title' => t('Administer Bean Settings'), + ), + 'view bean revisions' => array( + 'title' => t('View Bean revisions'), + ), + ); + + // Add a Permission for each entity type. + bean_reset(TRUE); + foreach (bean_get_types() as $bean_type) { + $bean_type_name = check_plain($bean_type->type); + $perms += array( + "create any $bean_type_name bean" => array( + 'title' => t('%type_name: Add Bean', array('%type_name' => $bean_type->getLabel())), + ), + "edit any $bean_type_name bean" => array( + 'title' => t('%type_name: Edit Bean', array('%type_name' => $bean_type->getLabel())), + ), + "view any $bean_type_name bean" => array( + 'title' => t('%type_name: View Bean', array('%type_name' => $bean_type->getLabel())), + ), + "delete any $bean_type_name bean" => array( + 'title' => t('%type_name: Delete Bean', array('%type_name' => $bean_type->getLabel())), + ), + ); + } + + return $perms; +} + +/** + * Access callback for the entity API. + */ +function bean_type_access($op, $type = NULL, $account = NULL) { + return user_access('administer bean types', $account); +} + +/** + * Determines whether the given user has access to a bean. + * + * @param $op + * The operation being performed. One of 'view', 'update', 'create', 'delete' + * or just 'edit' (being the same as 'create' or 'update'). + * @param $bean + * Optionally a bean or a bean type to check access for. If nothing is + * given, access for all beans is determined. + * @param $account + * The user to check for. Leave it to NULL to check for the current user. + * @return boolean + * Whether access is allowed or not. + */ +function bean_access($op, $bean = NULL, $account = NULL) { + $rights = &drupal_static(__FUNCTION__, array()); + + // Only real permissions are view, delete, create and edit + switch ($op) { + case 'view': + case 'delete': + case 'create': + $op = $op; + break; + case 'add': + $op = 'create'; + break; + default: + $op = 'edit'; + } + + // If no user object is supplied, the access check is for the current user. + if (empty($account)) { + $account = $GLOBALS['user']; + } + + $cid = is_object($bean) ? $bean->bid : $bean; + + // If we've already checked access for this node, user and op, return from cache. + if (isset($rights[$account->uid][$cid][$op])) { + return $rights[$account->uid][$cid][$op]; + } + + if (user_access('administer beans', $account)) { + return TRUE; + } + + // We grant access to the bean if both of the following conditions are met: + // - No modules say to deny access. + // - At least one module says to grant access. + // If no module specified either allow or deny, we fall back to the default. + $access = module_invoke_all('bean_access', $bean, $op, $account); + if (in_array(FALSE, $access, TRUE)) { + $rights[$account->uid][$cid][$op] = FALSE; + return FALSE; + } + elseif (in_array(TRUE, $access, TRUE)) { + $rights[$account->uid][$cid][$op] = TRUE; + return TRUE; + } + + if (isset($bean) && isset($bean->type)) { + if (user_access("$op any {$bean->type} bean", $account)) { + $rights[$account->uid][$cid][$op] = TRUE; + return TRUE; + } + } + else { + // Here we are looking for access to any of the types. + foreach (bean_get_types() as $bean_type) { + $perm = $op . ' any ' . $bean_type->type . ' bean'; + if (user_access($perm, $account)) { + $rights[$account->uid][$cid][$op] = TRUE; + return TRUE; + } + } + } + + return FALSE; +} + +/** + * Access callback for the general Bean add page (block/add). + */ +function bean_add_page_access() { + if (user_access('administer bean types') || user_access('administer beans')) { + return TRUE; + } + foreach (bean_get_types() as $bean_type) { + if (bean_access('create', $bean_type->type)) { + return TRUE; + } + } + return FALSE; +} + +/** + * Inserts or updates a bean object into the database. + * + * @param $bean + * The bean object to be inserted. + * + * @return + * Failure to write a record will return FALSE. Otherwise SAVED_NEW or + * SAVED_UPDATED is returned depending on the operation performed. + */ +function bean_save(Bean $bean) { + return $bean->save(); +} + +/** + * Deletes an existing bean. + * + * @param $bean + * The message object to be bean. + */ +function bean_delete(Bean $bean) { + return $bean->delete(); +} + +/** + * Helper to easily create a bean. + * + * @param $values array + * Array with the following keys: + * - "arguments" - Array with arguments that should be replaced on run time in + * the message type. + * + * @return Bean + */ +function bean_create($values) { + return entity_create('bean', $values); +} + +/** + * View the Bean + */ +function bean_view(Bean $bean, $view_mode = 'default', $langcode = NULL) { + if (!isset($langcode)) { + $langcode = $GLOBALS['language_content']->language; + } + + return $bean->view($view_mode, $langcode); +} + +/** + * Implements hook_block_info(). + */ +function bean_block_info() { + $blocks = array(); + $beans = bean_get_all_beans(); + foreach ($beans as $bean) { + $blocks[$bean->delta] = array( + 'info' => $bean->adminTitle(), + 'cache' => $bean->getInfo('cache_level'), + ); + } + + return $blocks; +} + +/** + * Implements hook_block_view(). + */ +function bean_block_view($delta = '') { + $return = array(); + $bean = bean_load_delta($delta); + + if (bean_access('view', $bean) && $bean) { + $content = $bean->view($bean->view_mode); + if (!is_array($content)) { + $content = array( + '#markup' => $content, + ); + } + + $return = array( + 'content' => $content, + 'subject' => $bean->label(), + ); + } + + if (!empty($return['content']) && module_exists('contextual')) { + $return['content']['#contextual_links']['bean'] = array( + 'block', array($bean->Identifier()) + ); + } + + return $return; +} + +/** + * Define the name of the api hook + */ +function bean_types_hook_name() { + return 'bean_types_api_info'; +} + +/** + * The current version of the API + */ +function bean_current_version() { + return 5; +} + +/** + * The minimal version + */ +function bean_min_version() { + return 4; +} + +/** + * Implements hook_bean_types_api_info(). + */ +function bean_bean_types_api_info() { + return array( + 'api' => bean_current_version(), + ); +} + +/** + * Implements hook_ctools_plugin_type(). + */ +function bean_ctools_plugin_type() { + return array( + 'types' => array( + 'cache' => TRUE, + 'use hooks' => TRUE, + 'classes' => array('handler'), + 'info file' => TRUE, + 'alterable' => TRUE, + 'defaults' => array( + 'abstract' => FALSE, + 'label' => t('Block'), + 'description' => '', + 'cache_level' => DRUPAL_CACHE_PER_ROLE, + // Editable in the block type UI + // THESE should have 'bean_custom' as the class + 'editable' => FALSE, + 'view_mode' => 'default', + 'handler' => array( + 'class' => 'BeanDefault', + 'parent' => 'bean', + 'file' => 'base.inc', + 'path' => drupal_get_path('module', 'bean') . '/plugins', + ), + ), + ), + ); +} + +/** + * Implements hook_bean_types(). + */ +function bean_bean_types() { + $plugins = array(); + + $plugins['bean'] = array( + 'handler' => array( + 'class' => 'BeanPlugin', + 'file' => 'base.inc', + 'path' => drupal_get_path('module', 'bean') . '/plugins', + ), + ); + + $plugins['bean_default'] = array( + 'abstract' => TRUE, + 'handler' => array( + 'class' => 'BeanDefault', + 'parent' => 'bean', + 'file' => 'base.inc', + 'path' => drupal_get_path('module', 'bean') . '/plugins', + ), + ); + + return $plugins; +} + +/** + * Implements hook_theme(). + */ +function bean_theme() { + return array( + 'bean' => array( + 'render element' => 'entity', + 'template' => 'bean', + ), + 'bean_add_list' => array( + 'variables' => array('content' => NULL), + ), + ); +} + +/** + * Implements hook_menu_local_tasks_alter(). + */ +function bean_menu_local_tasks_alter(&$data, $router_item, $root_path) { + // Add action link to 'block/add' on 'admin/content/blocks' page. + if ($root_path == 'admin/content/blocks' && bean_get_types()) { + $item = menu_get_item('block/add'); + if ($item['access']) { + $data['actions']['output'][] = array( + '#theme' => 'menu_local_action', + '#link' => $item, + ); + } + } +} + +/** + * Implements hook_workbench_create_alter(). + */ +function bean_workbench_create_alter(&$output) { + $items = array(); + $i = 0; + foreach (bean_get_types() as $bean_type) { + if (bean_access('create', $bean_type->type)) { + $items[str_replace(' ', '', $bean_type->getLabel()) . '_' . $i] = array( + 'title' => $bean_type->getLabel(), + 'href' => 'block/add/' . $bean_type->buildURL(), + 'description' => $bean_type->getDescription(), + 'localized_options' => array(), + ); + $i++; + } + } + + if (!empty($items)) { + ksort($items); + + $output['bean_types'] = array( + '#title' => t('Create Blocks'), + '#markup' => theme('node_add_list', array('content' => $items)), + '#theme' => 'workbench_element', + ); + } +} + +/** + * Implements hook_modules_enabled() + */ +function bean_modules_enabled($modules) { + bean_reset(TRUE); +} + +/** + * Implements hook_field_extra_fields(). + */ +function bean_field_extra_fields() { + $extra = array(); + foreach (bean_get_types() as $type) { + $field = array( + 'label' => t('Bean field: !title', array('!title' => 'Title')), + 'weight' => -5, + ); + + $extra['bean'][$type->type]['form']['title'] = $field; + $extra['bean'][$type->type]['display']['title'] = $field; + } + + return $extra; +} + +/** + * Implements hook_views_api() + */ +function bean_views_api() { + return array( + 'api' => 3, + 'path' => drupal_get_path('module', 'bean') . '/views', + ); +} + +/** + * Implements hook_flush_caches(). + */ +function bean_flush_caches() { + bean_reset(TRUE); + return array(); +} + +/** + * Implements hook_references_dialog_entity_admin_paths(). + * + * Enables integration for the References Dialog module. + */ +function bean_references_dialog_entity_admin_paths() { + return array( + 'bean' => array( + 'add' => 'block/add/[bundle-sanitized]', + 'edit' => 'block/[entity_id]/edit', + ), + ); +} diff --git a/sites/all/modules/bean/bean.services.inc b/sites/all/modules/bean/bean.services.inc new file mode 100644 index 0000000000000000000000000000000000000000..1b9b76ac322a200742544a7d03df547ea14359af --- /dev/null +++ b/sites/all/modules/bean/bean.services.inc @@ -0,0 +1,297 @@ +<?php + +/** + * @file + * Contains callbacks for service resource manipulation. + */ + +/** + * Implements hook_services_resources(). + */ +function bean_services_resources() { + return array( + '#api_version' => 3002, + 'bean' => array( + 'operations' => array( + 'retrieve' => array( + 'help' => t('This method returns a bean.'), + 'callback' => 'bean_services_retrieve', + 'access arguments' => array('view bean page'), + 'args' => array( + array( + 'name' => 'bid', + 'type' => 'int', + 'description' => t('The id of the bean to get.'), + 'source' => array('path' => '0'), + 'optional' => FALSE, + ), + ), + ), + 'create' => array( + 'help' => t('This method creates a bean.'), + 'callback' => 'bean_services_create', + 'access callback' => 'bean_services_access', + 'access arguments' => array('add'), + 'access arguments append' => TRUE, + 'args' => array( + array( + 'name' => 'data', + 'type' => 'struct', + 'description' => t('An object representing the bean.'), + 'source' => 'data', + 'optional' => FALSE, + ), + ), + ), + 'update' => array( + 'help' => t('This method updates a bean.'), + 'callback' => 'bean_services_update', + 'access callback' => 'bean_services_access', + 'access arguments' => array('edit'), + 'access arguments append' => TRUE, + 'args' => array( + array( + 'name' => 'bid', + 'type' => 'int', + 'description' => t('The id of the bean to update.'), + 'source' => array('path' => '0'), + 'optional' => FALSE, + ), + array( + 'name' => 'data', + 'type' => 'struct', + 'description' => t('An object representing the bean.'), + 'source' => 'data', + 'optional' => FALSE, + ), + ), + ), + 'delete' => array( + 'help' => t('This method deletes a bean.'), + 'callback' => 'bean_services_delete', + 'access callback' => 'bean_services_access', + 'access arguments' => array('delete'), + 'access arguments append' => TRUE, + 'args' => array( + array( + 'name' => 'bid', + 'type' => 'int', + 'description' => t('The id of the bean to delete.'), + 'source' => array('path' => '0'), + 'optional' => FALSE, + ), + ), + ), + 'index' => array( + 'help' => t('This method returns a listing of beans.'), + 'callback' => 'bean_services_index', + 'access arguments' => array('administer beans'), + 'args' => array( + array( + 'name' => 'page', + 'optional' => TRUE, + 'type' => 'int', + 'description' => t('The zero-based index of the page to get, defaults to 0.'), + 'default value' => 0, + 'source' => array('param' => 'page'), + ), + array( + 'name' => 'fields', + 'optional' => TRUE, + 'type' => 'string', + 'description' => t('The fields to return.'), + 'default value' => '*', + 'source' => array('param' => 'fields'), + ), + array( + 'name' => 'parameters', + 'optional' => TRUE, + 'type' => 'array', + 'description' => t('Fields an values to filter the list by.'), + 'default value' => array(), + 'source' => array('param' => 'parameters'), + ), + array( + 'name' => 'pagesize', + 'optional' => TRUE, + 'type' => 'int', + 'description' => t('Number of records to get per page.'), + 'default value' => 20, + 'source' => array('param' => 'pagesize'), + ), + ), + ), + ), + ), + ); +} + +/** + * Adds a new bean to a node and returns the bid. + * + * @param $bean Bean + * An object as would be returned from bean_load(). + * @return + * Unique identifier for the bean (bid) or errors if there was a problem. + */ +function bean_services_create($bean) { + if (empty($bean['type'])) { + return services_error(t('A type must be provided.')); + } + + // Include the bean_form. + module_load_include('inc', 'bean', 'includes/bean.pages'); + + $bean_new = bean_create($bean); + + // Setup form_state. + $form_state = array(); + $form_state['values'] = $bean; + $form_state['values']['op'] = t('Save'); + $form_state['build_info']['args'] = array(&$bean_new); + + $ret = drupal_form_submit('bean_form', $form_state); + + // Error if needed. + if ($errors = form_get_errors()) { + return services_error(implode(" ", $errors), 406, array('form_errors' => $errors)); + } + + $bean = $form_state['bean']; + + return array( + 'bid' => $bean->bid, + 'uri' => services_resource_uri(array('bean', $bean->bid)), + ); +} + +/** + * Updates a bean and returns the bid. + * + * @param $bid + * Unique identifier for this bean. + * @param $bean Bean + * An object as would be returned from bean_load(). + * @return + * Unique identifier for the bean (bid) or FALSE if there was a problem. + */ +function bean_services_update($bid, $bean) { + // Include the bean_form. + module_load_include('inc', 'bean', 'includes/bean.pages'); + + $bean['bid'] = $bid; + + $old_bean = bean_load($bid); + if (empty($old_bean)) { + return services_error(t('Bean @bid not found.', array('@bid' => $bid)), 404); + } + + // Setup form_state. + $form_state = array(); + $form_state['values'] = $bean; + $form_state['values']['op'] = t('Save'); + $form_state['build_info']['args'] = array(&$old_bean); + + drupal_form_submit('bean_form', $form_state); + + if ($errors = form_get_errors()) { + return services_error(implode(" ", $errors), 406, array('form_errors' => $errors)); + } + + return $bid; +} + +/** + * Returns a specified bean. + * + * @param $bid + * Unique identifier for the specified bean. + * @return + * The bean object. + */ +function bean_services_retrieve($bid) { + return bean_load($bid); +} + +/** + * Delete a bean. + * + * @param $bid + * Unique identifier of the bean to delete. + * @return + * True. + */ +function bean_services_delete($bid) { + $bean = bean_load($bid); + if (empty($bean)) { + return services_error(t('There is no bean found with id @bid.', array('@bid' => $bid)), 404); + } + + // Delete bean. + bean_delete($bean); + + // Clear the bean cache so an anonymous user sees that the bean was deleted. + bean_reset(); + return TRUE; +} + +/** + * Return an array of optionally paged bids based on a set of criteria. + * + * An example request might look like: + * + * http://domain/endpoint/bean?fields=bid,label¶meters[type]=mytype + * + * This would return an array of objects with only bid and label defined, where + * type = 'mytype'. + * + * @param $page + * Page number of results to return (in pages of 20). + * @param $fields + * The fields you want returned. + * @param $parameters + * An array containing fields and values used to build a sql WHERE clause + * indicating items to retrieve. + * @param $page_size + * Integer number of items to be returned. + * @return + * An array of bean objects. + **/ +function bean_services_index($page, $fields, $parameters, $page_size) { + $bean_select = db_select('bean', 't') + ->orderBy('delta', 'ASC'); + + services_resource_build_index_query($bean_select, $page, $fields, $parameters, $page_size, 'bean'); + + $results = services_resource_execute_index_query($bean_select); + + return services_resource_build_index_list($results, 'bean', 'bid'); +} + +/** + * Access callback for the bean resource. + * + * @param $op + * The operation that's going to be performed. + * @param $args + * The arguments that will be passed to the callback. + * @return + * Whether access is given or not. + */ +function bean_services_access($op, $args) { + $bean = NULL; + if (!empty($args[0])) { + if (is_numeric($args[0])) { + $bean = bean_load($args[0]); + } + else if (is_array($args[1])) { + $bean = (object) $args[1]; + } + } + + if (!empty($args[0]) && !is_object($bean)) { + return FALSE; + } + + return bean_access($op, $bean); +} diff --git a/sites/all/modules/bean/bean.test b/sites/all/modules/bean/bean.test new file mode 100644 index 0000000000000000000000000000000000000000..1b693320a836de0b7cb1fcf72e19eb25327e76cd --- /dev/null +++ b/sites/all/modules/bean/bean.test @@ -0,0 +1,311 @@ +<?php + +/** + * @file + * Tests for block.module. + */ + +abstract class BeanSetup extends DrupalWebTestCase { + protected $admin_user; + protected $plugin_name; + + + function setUp() { + parent::setUp('bean', 'ctools', 'entity', 'bean_test', 'block'); + $this->addAdminUser(); + } + + function addAdminUser() { + $permissions = array_keys(bean_permission()); + $permissions += array( + 'administer blocks', + 'access administration pages', + 'access content', + ); + $this->admin_user = $this->drupalCreateUser($permissions); + $this->drupalLogin($this->admin_user); + + // Test plugin name + $this->plugin_name = 'test_bean'; + } +} + +/** + * Test specific parts of the bean type class + */ +class BeanUnitTests extends BeanSetup { + public static function getInfo() { + return array( + 'name' => 'Bean Unit Tests', + 'description' => 'Test that the individual methods of the bean and bean type classes work.', + 'group' => 'Bean', + ); + + } + + /** + * Test the URL of the bean types + */ + function testBeanTypeURL() { + $test_plugin = array( + 'label' => t('Test'), + 'name' => 'test_name', + 'description' => t('This is a test plugin'), + 'handler' => array( + 'class' => 'BeanTestPlugin', + 'parent' => 'bean', + ), + ); + + $bean_type = new BeanDefault($test_plugin); + $bean_type->type = "test_name"; + $this->assertEqual($bean_type->buildURL(), "test-name", t('URL is formatted correctly.')); + } +} + +/** + * Test the API + */ +class BeanTestPlugins extends BeanSetup { + + public static function getInfo() { + return array( + 'name' => 'Bean Plugin', + 'description' => 'Test the bean plugin API.', + 'group' => 'Bean', + ); + } + + /** + * Test loading of the plugin + */ + function testBeanLoadPlugin() { + // Load the class + $plugin_class = bean_load_plugin_class('test_bean'); + $plugin_class_name = get_class($plugin_class); + + // Plugin should be implement the BeanTypePluginInterface interface + if (bean_check_plugin_class($plugin_class_name)) { + $this->pass(t('Bean type should use the BeanTypePluginInterface interface')); + } + else { + $this->fail(t('Bean type should use the BeanTypePluginInterface interface')); + } + + // Verify that a bean plugin with an invalid class does not load + $this->assertFalse(bean_load_plugin_class('test_no_bean'), t('Bean type should not load with an invalid class')); + $this->assertFalse(bean_load_plugin_class('test_wrong_class'), t('Bean type should not load with an invalid class')); + } + + /** + * Verity that the correct links appear + */ + function testBeanTypeLinks() { + $this->drupalGet('block/add'); + // Verify the block add pages exists + $this->assertResponse(200, t('Block Add Page is accessible')); + + // There should 2 plugins links + $this->assertLinkByHref('block/add/test-bean', 0, t('A link to the bean add for each type should exist')); + $this->assertLinkByHref('block/add/test-bean-2', 0, t('A link to the bean add for each type should exist')); + $this->assertNoLinkByHref('block/add/test-no-bean', t('A link to an invalid bean type should not exist')); + $this->assertNoLinkByHref('block/add/test-wrong-class', t('A link to an invalid bean type should not exist')); + } + + + /** + * Test the bean form + */ + function testBeanTypeForm() { + + foreach (bean_get_types() as $type) { + $this->drupalGet("block/add/{$type->buildUrl()}"); + + // Verify the core fields are there + $this->assertFieldById('edit-label', '', t('Label exists on bean add form.')); + $this->assertFieldById('edit-title', '', t('Title exists on bean add form.')); + $this->assertFieldById('edit-view-mode', '', t('View Mode exists on bean add form.')); + } + } +} + +class BeanTests extends BeanSetup { + public static function getInfo() { + return array( + 'name' => 'Bean functionality', + 'description' => 'Test the bean API.', + 'group' => 'Bean', + ); + } + + /** + * Test the bean API + */ + public function testBeanAPI() { + $values = array( + 'delta' => 'test_bean', + 'label' => t('Test Bean'), + 'title' => t('Test Bean'), + 'type' => $this->plugin_name, + 'view_mode' => 'default', + 'data' => array( + 'test_boolean' => FALSE, + 'test_string' => t('New String'), + 'test_array' => array( + 'test_array_1' => 'new_value', + ), + ), + ); + + $bean = bean_create($values); + $this->assertTrue(bean_save($bean), t('Bean was saved')); + + $values['label'] = $values['title'] = t('Test Bean 2'); + $values['delta'] = 'test_bean2'; + $bean = bean_create($values); + $this->assertTrue(bean_save($bean), t('Bean was saved')); + + $beans = array_values(bean_load_multiple(FALSE, array('type' => $this->plugin_name))); + $this->assertEqual($beans[0]->label, t('Test Bean'), 'Created and loaded bean.'); + $this->assertEqual($beans[1]->label, t('Test Bean 2'), 'Created and loaded bean.'); + + // Delete the first bean + $delete_id = $beans[0]->bid; + bean_delete($beans[0]); + + $bean = $beans[1]; + + // Try to load deleted bean + $delete_bean = bean_load($delete_id, TRUE); + $this->assertFalse($delete_bean, t('Bean Deleted')); + + // Load by delta + $delta_bean = bean_load_delta('test_bean2', TRUE); + $this->assertEqual($delta_bean->identifier(), $bean->identifier(), t('Bean loaded by delta')); + + // Test devel pages + if (module_exists('devel')) { + $this->drupalGet("block/{$bean->identifier()}/devel"); + $this->assertResponse(200, t('Devel load page is viewable')); + $this->assertText($bean->label(), t('Devel load page is viewable')); + + $this->drupalGet("block/{$bean->identifier()}/devel/render"); + $this->assertResponse(200, t('Devel render page is viewable')); + $this->assertText($bean->label(), t('Devel render page is viewable')); + } + + // Test a bean with an invalid plugin + $values['type'] = 'fake_plugin'; + $values['delta'] = 'fake_bean_plugin'; + $bean = bean_create($values); + $this->assertTrue(bean_save($bean), t('Bean with invalid type was saved')); + $this->assertTrue(bean_load_delta('fake_bean_plugin'), t('Bean with an invalid plugin is loaded')); + + // Test a bean with a plugin with an invalid class + $values['delta'] = 'missing_class'; + $values['type'] = 'test_no_bean'; + $bean = bean_create($values); + $this->assertTrue(bean_save($bean), t('Bean with a plugin that has an invalid class is saved')); + $this->assertTrue(bean_load_delta('missing_class'), t('Bean with a plugin that has an invalid class is loaded')); + } + + /** + * Tests viewing beans. + */ + function testRendering() { + $values = array( + 'delta' => 'test_bean', + 'label' => t('Test Bean'), + 'title' => t('Test Bean'), + 'type' => $this->plugin_name, + 'view_mode' => 'default', + 'data' => array( + 'test_boolean' => FALSE, + 'test_string' => t('New String'), + 'test_array' => array( + 'test_array_1' => 'new_value', + ), + ), + ); + + $bean = bean_create($values); + bean_save($bean); + + $this->drupalGet($bean->url()); + $this->assertResponse(200, t('Bean Page is viewable')); + $this->assertText($bean->label(), t('Bean Page is viewable')); + + $this->drupalGet("block/{$bean->identifier()}"); + $this->assertResponse(200, t('Legacy Bean Page is viewable')); + $this->assertText($bean->label(), t('Legacy Bean Page is viewable')); + } +} + +/** + * This should test the access to beans + */ +class BeanAccess extends DrupalWebTestCase { + public static function getInfo() { + return array( + 'name' => 'Bean Access', + 'description' => 'Test the access to beans.', + 'group' => 'Bean', + ); + } + + /** + * Test + */ + public function testAccess() { + $this->assertTrue(TRUE, t('Not implemented')); + } +} + +/** + * Integration Tests + */ +class BeanIntegrationTests extends DrupalWebTestCase { + public static function getInfo() { + return array( + 'name' => 'Bean Integration Tests', + 'description' => 'Make sure everything works from the front end.', + 'group' => 'Bean', + ); + } + + protected function setUp() { + parent::setUp(); + } + + /** + * Test that reactions when there are no bean types + */ + + /** + * Test adding a bean + */ + public function testBeanAdd() { + $this->assertTrue(TRUE, t('Not implemented')); + } + + /** + * Test Editing a Bean + */ + public function testBeanEdit() { + $this->assertTrue(TRUE, t('Not implemented')); + } + + /** + * Test Deleting a Bean + */ + public function testBeanDelete() { + $this->assertTrue(TRUE, t('Not implemented')); + } + + /** + * Place a bean block on the page + */ + public function testBeanPlacement() { + $this->assertTrue(TRUE, t('Not implemented')); + } +} diff --git a/sites/all/modules/bean/bean.tpl.php b/sites/all/modules/bean/bean.tpl.php new file mode 100644 index 0000000000000000000000000000000000000000..dcdb9dc9856598d7da711b00c286ebf6f1fa5cd4 --- /dev/null +++ b/sites/all/modules/bean/bean.tpl.php @@ -0,0 +1,37 @@ +<?php +/** + * @file + * Default theme implementation for beans. + * + * Available variables: + * - $content: An array of comment items. Use render($content) to print them all, or + * print a subset such as render($content['field_example']). Use + * hide($content['field_example']) to temporarily suppress the printing of a + * given element. + * - $title: The (sanitized) entity label. + * - $url: Direct url of the current entity if specified. + * - $page: Flag for the full page state. + * - $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. By default the following classes are available, where + * the parts enclosed by {} are replaced by the appropriate values: + * - entity-{ENTITY_TYPE} + * - {ENTITY_TYPE}-{BUNDLE} + * + * 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_entity() + * @see template_process() + */ +?> +<div class="<?php print $classes; ?> clearfix"<?php print $attributes; ?>> + + <div class="content"<?php print $content_attributes; ?>> + <?php + print render($content); + ?> + </div> +</div> diff --git a/sites/all/modules/bean/bean_admin_ui/bean_admin_ui.admin.inc b/sites/all/modules/bean/bean_admin_ui/bean_admin_ui.admin.inc new file mode 100644 index 0000000000000000000000000000000000000000..54680cf0178cd0e238de87e3e16fb6b54835cc84 --- /dev/null +++ b/sites/all/modules/bean/bean_admin_ui/bean_admin_ui.admin.inc @@ -0,0 +1,215 @@ +<?php + +/** + * @file + * Bean Admin Page + */ + +/** + * Main page callback on the bean type + */ +function bean_admin_ui_admin_page() { + $field_ui = module_exists('field_ui'); + $rows = array(); + $i = 0; + + foreach (bean_get_types() as $bean_type) { + $row = array(); + $row[] = array('data' => check_plain($bean_type->getLabel())); + if (method_exists($bean_type, 'getExportStatus')) { + $export_status = $bean_type->getExportStatus(); + } + else { + $export_status = 'Normal'; + } + $row[] = array('data' => $export_status); + // Edit and delete buttons + if ($bean_type->isEditable()) { + $row[] = array('data' => l(t('Edit'), 'admin/structure/block-types/manage/' . $bean_type->buildURL() . '/edit')); + switch ($export_status) { + case 'Normal': + $row[] = array('data' => l(t('Delete'), 'admin/structure/block-types/manage/' . $bean_type->buildURL() . '/delete')); + break; + case 'Overridden': + $row[] = array('data' => l(t('Revert'), 'admin/structure/block-types/manage/' . $bean_type->buildURL() . '/revert')); + break; + case 'Default': + $row[] = array(); + break; + } + } + else { + // For the operations + $row[] = array(); + $row[] = array(); + } + + if ($field_ui) { + // Manage fields. + $row[] = array('data' => l(t('manage fields'), 'admin/structure/block-types/manage/' . $bean_type->buildURL() . '/fields')); + + // Display fields. + $row[] = array('data' => l(t('manage display'), 'admin/structure/block-types/manage/' . $bean_type->buildURL() . '/display')); + } + //creative way to setup sorting rows; add number to prevent dual keys + $rows[str_replace(' ', '', $bean_type->getLabel()) . '_' . $i] = $row; + } + ksort($rows); + + $header = array(t('Name'), t('Status'), array('data' => t('Operations'), 'colspan' => $field_ui ? '4' : '2')); + + $build['bean_table'] = array( + '#theme' => 'table', + '#header' => $header, + '#rows' => $rows, + '#empty' => t('There are no Block Types Available'), + ); + return $build; +} + +/** + * Generates the bean type editing form. + */ +function bean_admin_ui_type_form($form, &$form_state, $bean_type = NULL) { + $form['new'] = array( + '#type' => 'value', + '#value' => TRUE, + ); + // If bean_type is null then load an empty one. + if (is_null($bean_type)) { + $plugin_info = _bean_admin_default_plugin(); + $plugin_info['name'] = ''; + + $bean_type = new BeanCustom($plugin_info); + } + elseif (!method_exists($bean_type, 'getExportStatus') || $bean_type->getExportStatus() == 'Normal') { + $form['new'] = array( + '#type' => 'value', + '#value' => FALSE, + ); + } + + $disabled = !$bean_type->isEditable(); + + if ($disabled) { + drupal_set_message(t('This Block Type can not be edited')); + } + $form['bean_type'] = array( + '#type' => 'value', + '#value' => $bean_type, + ); + + $form['label'] = array( + '#title' => t('Label'), + '#type' => 'textfield', + '#default_value' => $bean_type->getLabel(), + '#description' => t('The human-readable name of this block type.'), + '#required' => TRUE, + '#size' => 30, + '#disabled' => $disabled, + ); + + $form['description'] = array( + '#title' => t('Description'), + '#type' => 'textarea', + '#default_value' => $bean_type->getDescription(), + '#description' => t('The description of this block type.'), + '#disabled' => $disabled, + ); + + // Machine-readable type name. + $form['name'] = array( + '#type' => 'machine_name', + '#default_value' => isset($bean_type->type) ? $bean_type->type : '', + '#maxlength' => 32, + '#machine_name' => array( + 'exists' => 'bean_type_load', + 'source' => array('label'), + ), + '#description' => t('A unique machine-readable name for this block type. It must only contain lowercase letters, numbers, and underscores.'), + '#disabled' => $disabled, + ); + + $form['actions'] = array('#type' => 'actions'); + $form['actions']['submit'] = array( + '#type' => 'submit', + '#value' => t('Save Block type'), + '#weight' => 40, + '#disabled' => $disabled, + ); + + // This is a new bean type. + if (!empty($bean_type->type)) { + $form['actions']['delete'] = array( + '#type' => 'submit', + '#name' => 'delete', + '#value' => t('Delete Block type'), + '#weight' => 45, + '#limit_validation_errors' => array(), + '#disabled' => $disabled, + ); + + if (method_exists($bean_type, 'getExportStatus')) { + if ($bean_type->getExportStatus() == 'Overridden') { + $form['actions']['delete']['#name'] = 'revert'; + $form['actions']['delete']['#value'] = t('Revert to defaults'); + } + else { + unset($form['actions']['delete']); + } + + } + } + return $form; +} + +/** + * Form API submit callback for the type form. + */ +function bean_admin_ui_type_form_submit(&$form, &$form_state) { + $op = $form_state['clicked_button']['#name']; + if (in_array($op, array('revert', 'delete'))) { + $form_state['redirect'] = 'admin/structure/block-types/manage/' . $form['bean_type']['#value']->type . '/' . $op; + } + $bean_type = $form_state['values']['bean_type']; + $bean_type->type = $form_state['values']['name']; + $bean_type->setLabel($form_state['values']['label']); + $bean_type->setDescription($form_state['values']['description']); + $bean_type->save($form_state['values']['new']); + $form_state['redirect'] = 'admin/structure/block-types'; + ctools_include('export'); + + // Clear the site caches so that the new "manage fields" and "display fields" + // pages for the new bean type work. + drupal_flush_all_caches(); +} + +/** + * Menu callback; Form builder to confirm delete/revert of a bean type. + */ +function bean_admin_ui_type_op_confirm($form, &$form_state, $op, $type) { + $form['op'] = array('#type' => 'value', '#value' => $op); + $form['type'] = array('#type' => 'value', '#value' => $type); + $form['name'] = array('#type' => 'value', '#value' => $type->getLabel()); + $caption = ''; + if ($op == 'delete') { + $message = t('Are you sure you want to delete the block type %type?', array('%type' => $type->getLabel())); + $num_beans = db_query("SELECT COUNT(*) FROM {bean} WHERE type = :type", array(':type' => $type->type))->fetchField(); + if ($num_beans) { + $caption .= '<p>' . format_plural($num_beans, '%type is used by 1 block on your site that is going to be removed along with %type.', '%type is used by @count blocks on your site that are going to be removed along %type.', array('%type' => $type->getLabel())) . '</p>'; + } + $action = t('Delete'); + } + else { + $message = t('Are you sure you want to revert the block type %type?', array('%type' => $type->getLabel())); + $action = t('Revert'); + } + $caption .= '<p>' . t('This action cannot be undone.') . '</p>'; + + return confirm_form($form, $message, 'admin/structure/block-types', $caption, $action); +} + +function bean_admin_ui_type_op_confirm_submit($form, &$form_state) { + $form_state['values']['type']->{$form['op']['#value']}(); + $form_state['redirect'] = 'admin/structure/block-types'; +} diff --git a/sites/all/modules/bean/bean_admin_ui/bean_admin_ui.info b/sites/all/modules/bean/bean_admin_ui/bean_admin_ui.info new file mode 100644 index 0000000000000000000000000000000000000000..443d6a89bf7e2e3c95c785ccde551204c73e561b --- /dev/null +++ b/sites/all/modules/bean/bean_admin_ui/bean_admin_ui.info @@ -0,0 +1,15 @@ +name = Bean Admin UI +description = Add the ability to create Block Types in the UI +core = 7.x +files[] = bean_admin_ui.module +dependencies[] = bean +files[] = plugins/custom.inc +configure = admin/structure/block-types +package = Bean + +; Information added by drupal.org packaging script on 2013-02-27 +version = "7.x-1.1" +core = "7.x" +project = "bean" +datestamp = "1361977163" + diff --git a/sites/all/modules/bean/bean_admin_ui/bean_admin_ui.install b/sites/all/modules/bean/bean_admin_ui/bean_admin_ui.install new file mode 100644 index 0000000000000000000000000000000000000000..d2e0ca21394342e7187108d4fce94bdb1a670757 --- /dev/null +++ b/sites/all/modules/bean/bean_admin_ui/bean_admin_ui.install @@ -0,0 +1,127 @@ +<?php + +/** + * @file + * Install files + */ + +/** + * Implements of hook_schema(). + */ +function bean_admin_ui_schema() { + $schema['bean_type'] = array( + 'description' => 'Stores information about all defined bean types.', + 'export' => array( + 'key' => 'name', + 'identifier' => 'bean_type', + 'default hook' => 'bean_admin_ui_types', + 'admin_title' => 'label', + 'api' => array( + 'owner' => 'bean_admin_ui', + 'api' => 'bean', + 'minimum_version' => 4, + 'current_version' => 5, + ), + ), + 'fields' => array( + 'type_id' => array( + 'description' => 'The Type ID of this block. Only used internally by CTools', + 'type' => 'serial', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'no export' => TRUE, + ), + 'name' => array( + 'description' => 'The machine-readable name of this bean type.', + 'type' => 'varchar', + 'length' => 32, + 'not null' => TRUE, + ), + 'label' => array( + 'description' => 'The human-readable name of this bean type.', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + ), + 'options' => array( + 'description' => 'Block content configuration.', + 'type' => 'text', + 'size' => 'big', + ), + 'description' => array( + 'description' => 'The description of this bean type.', + 'type' => 'text', + 'size' => 'big', + ), + ), + 'primary key' => array('type_id'), + 'unique keys' => array( + 'name' => array('name'), + ), + ); + return $schema; +} + +/** + * Add support for CTools exportables. + */ +function bean_admin_ui_update_7001() { + db_drop_primary_key('bean_type'); + + // Add a type_id column for use by CTools. + $spec = array( + 'description' => 'The Type ID of this block. Only used internally by CTools', + 'type' => 'serial', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'no export' => TRUE, + ); + $new_keys = array( + 'primary key' => array('type_id'), + ); + db_add_field('bean_type', 'type_id', $spec, $new_keys); + + // Add the options column. + $spec = array( + 'description' => 'Block content configuration.', + 'type' => 'text', + 'size' => 'big', + ); + db_add_field('bean_type', 'options', $spec); + + // Adjust the type column so tat it doesn't clash with CTools. + $spec = array( + 'description' => 'The machine-readable name of this bean type.', + 'type' => 'varchar', + 'length' => 32, + 'not null' => TRUE, + ); + $new_keys = array( + 'unique keys' => array( + 'name' => array('name'), + ), + ); + db_change_field('bean_type', 'type', 'name', $spec, $new_keys); + + // Force a cache flush to ensure CTools plugins can be found and menus are rebuilt. + cache_clear_all('*', 'cache', TRUE); + + return t('Added new fields required for CTools exportable support.'); +} + +/** + * Add description column to bean + * + */ +function bean_admin_ui_update_7002() { + // Add the description column. + $spec = array( + 'description' => 'Block description.', + 'type' => 'text', + 'size' => 'big', + ); + db_add_field('bean_type', 'description', $spec); + + return t('Added description field to beans.'); +} diff --git a/sites/all/modules/bean/bean_admin_ui/bean_admin_ui.module b/sites/all/modules/bean/bean_admin_ui/bean_admin_ui.module new file mode 100644 index 0000000000000000000000000000000000000000..73ee17b4676d2fecfbb3a8f52dacf87de7f56076 --- /dev/null +++ b/sites/all/modules/bean/bean_admin_ui/bean_admin_ui.module @@ -0,0 +1,175 @@ +<?php + +/** + * @file + * Bean Admin UI + */ + +module_load_include('inc', 'bean_admin_ui', 'includes/features'); + +/** + * Implements hook_menu(). + */ +function bean_admin_ui_menu() { + $items = array(); + + $items['admin/structure/block-types'] = array( + 'title' => 'Block Types', + 'description' => 'Manage Block Types', + 'page callback' => 'bean_admin_ui_admin_page', + 'access arguments' => array('administer bean types'), + 'file' => 'bean_admin_ui.admin.inc', + ); + + $items['admin/structure/block-types/list'] = array( + 'title' => 'List', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => -10, + ); + + $items['admin/structure/block-types/add'] = array( + 'title' => 'Add block type', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('bean_admin_ui_type_form'), + 'access arguments' => array('administer bean types'), + 'type' => MENU_LOCAL_ACTION, + 'file' => 'bean_admin_ui.admin.inc', + ); + + $items['admin/structure/block-types/manage/%bean_type'] = array( + 'title' => 'Edit block type', + 'title arguments' => array(4), + 'title callback' => 'bean_admin_ui_page_title', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('bean_admin_ui_type_form', 4), + 'access arguments' => array('administer bean types'), + 'file' => 'bean_admin_ui.admin.inc', + ); + $items['admin/structure/block-types/manage/%bean_type/edit'] = array( + 'title' => 'Edit', + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + $items['admin/structure/block-types/manage/%bean_type/delete'] = array( + 'title' => 'Delete', + 'page arguments' => array('bean_admin_ui_type_op_confirm', 'delete', 4), + 'access arguments' => array('administer bean types'), + 'file' => 'bean_admin_ui.admin.inc', + ); + $items['admin/structure/block-types/manage/%bean_type/revert'] = array( + 'title' => 'Delete', + 'page arguments' => array('bean_admin_ui_type_op_confirm', 'revert', 4), + 'access arguments' => array('administer bean types'), + 'file' => 'bean_admin_ui.admin.inc', + ); + + return $items; +} + +/** + * Page title for block types + */ +function bean_admin_ui_page_title($block_type) { + $beantype = bean_fetch_plugin_info($block_type->type); + return check_plain($beantype['label']); +} + +/** + * Implements hook_bean_types_api_info(). + */ +function bean_admin_ui_bean_types_api_info() { + return array( + 'api' => bean_current_version(), + ); +} + +/** + * Implements hook_bean_types(). + */ +function bean_admin_ui_bean_types() { + $plugins = array(); + + // Add in the types defined in the UI. + $bean_types = bean_admin_ui_get_types(); + + foreach ($bean_types as $bean_type) { + $plugins[$bean_type->name] = array( + 'label' => $bean_type->label, + 'description' => empty($bean_type->description) ? '' : $bean_type->description, + 'type' => $bean_type->name, + 'export_status' => $bean_type->type, + ); + + $plugins[$bean_type->name] += _bean_admin_default_plugin(); + } + + return $plugins; +} + +/** + * Get all Custom Bean Types + */ +function bean_admin_ui_get_types() { + ctools_include('export'); + return ctools_export_load_object('bean_type'); +} + +/** + * Implements hook_bean_cache_clear(). + */ +function bean_admin_ui_bean_cache_clear() { + // Clear ctools cache. + ctools_include('export'); + ctools_export_load_object_reset('bean_type'); + + // Flush caches. + cache_clear_all('bean_types', 'cache'); +} + +/** + * The Default plugin settings + */ +function _bean_admin_default_plugin() { + return array( + 'label' => '', + 'description' => '', + 'type' => '', + 'editable' => TRUE, + 'handler' => array( + 'info_file' => TRUE, + 'class' => 'BeanCustom', + 'parent' => 'bean', + 'file' => 'custom.inc', + 'path' => drupal_get_path('module', 'bean_admin_ui') . '/plugins', + ), + ); +} + +/** + * Implements hook_features_api(). + */ +function bean_admin_ui_features_api() { + static $api = FALSE; + if (!$api) { + module_load_include('inc', 'features', 'includes/features.ctools'); + $api = ctools_component_features_api('bean_admin_ui'); + $api['bean_type']['name'] = 'Bean types'; + $api['bean_type']['file'] = drupal_get_path('module', 'bean_admin_ui') . '/includes/features.inc'; + } + return $api; +} + +/** + * Implements hook_modules_enabled(). + */ +function bean_admin_ui_modules_enabled($modules) { + $beans_found = FALSE; + foreach ($modules as $module) { + if (function_exists($module .'_bean_types')) { + $beans_found = TRUE; + } + } + // Flush bean caches and statics if any of the enabled modules provide bean types. + if ($beans_found) { + bean_reset(); + } +} diff --git a/sites/all/modules/bean/bean_admin_ui/includes/features.inc b/sites/all/modules/bean/bean_admin_ui/includes/features.inc new file mode 100644 index 0000000000000000000000000000000000000000..3dce3ecbe9f0051b066074b8a5e2117069fc4911 --- /dev/null +++ b/sites/all/modules/bean/bean_admin_ui/includes/features.inc @@ -0,0 +1,28 @@ +<?php + +/** + * @file + * Features module hooks + */ + +/** + * Implements hook_features_pipe_MODULE_alter(). + */ +function bean_admin_ui_features_pipe_bean_type_alter(&$pipe, $data, $export) { + if (isset($export['features']['bean_type'])) { + foreach ($export['features']['bean_type'] as $type_name) { + $fields = field_info_instances('bean', $type_name); + foreach ($fields as $name => $field) { + $pipe['field'][] = "bean-{$field['bundle']}-{$field['field_name']}"; + } + } + } +} + +/** + * Implements {component}_features_revert(). + */ +function bean_type_features_revert($module, $component) { + ctools_component_features_revert($component, $module); + bean_reset(); +} diff --git a/sites/all/modules/bean/bean_admin_ui/plugins/custom.inc b/sites/all/modules/bean/bean_admin_ui/plugins/custom.inc new file mode 100644 index 0000000000000000000000000000000000000000..e64f0b555d71d3432b54214477e04b663d486f9e --- /dev/null +++ b/sites/all/modules/bean/bean_admin_ui/plugins/custom.inc @@ -0,0 +1,76 @@ +<?php + +/** + * @file + * Bean ctools plugin + */ + +/** + * DO NOT USE THIS BEAN. ONLY USED FOR THE UI PLUGINS + */ +class BeanCustom extends BeanPlugin { + /** + * Delete the record from the database. + */ + public function delete() { + db_delete('bean') + ->condition('type', $this->type) + ->execute(); + + ctools_include('export'); + ctools_export_crud_delete('bean_type', $this->type); + field_attach_delete_bundle('bean', $this->type); + + bean_reset(); + } + + /** + * Save the record to the database + */ + public function save($new = FALSE) { + $bean_type = array( + 'name' => check_plain($this->type), + 'label' => check_plain($this->getLabel()), + 'description' => check_plain($this->getDescription()), + ); + + $primary_key = $new == FALSE ? 'name' : array(); + drupal_write_record('bean_type', $bean_type, $primary_key); + + bean_reset(); + } + + /** + * Revert the bean type to code defaults. + */ + public function revert() { + ctools_include('export'); + ctools_export_crud_delete('bean_type', $this->type); + bean_reset(); + } + + /** + * Get the export status + */ + public function getExportStatus() { + return $this->plugin_info['export_status']; + } + + /** + * Set the label. + * + * @param label + */ + public function setLabel($label) { + $this->plugin_info['label'] = $label; + } + + /** + * Set the description. + * + * @param description + */ + public function setDescription($description) { + $this->plugin_info['description'] = $description; + } +} diff --git a/sites/all/modules/bean/bean_all/bean_all.info b/sites/all/modules/bean/bean_all/bean_all.info new file mode 100644 index 0000000000000000000000000000000000000000..1ca3ec6f21c8802e9d4a0c2f7774f35bfe2c2eff --- /dev/null +++ b/sites/all/modules/bean/bean_all/bean_all.info @@ -0,0 +1,13 @@ +name = Bean All +description = Integrate all blocks with beans. +core = 7.x +files[] = plugins/all.inc +dependencies[] = bean +package = Bean + +; Information added by drupal.org packaging script on 2013-02-27 +version = "7.x-1.1" +core = "7.x" +project = "bean" +datestamp = "1361977163" + diff --git a/sites/all/modules/bean/bean_all/bean_all.install b/sites/all/modules/bean/bean_all/bean_all.install new file mode 100644 index 0000000000000000000000000000000000000000..45d9273b43a1be8e682080fd29f57adf559c5960 --- /dev/null +++ b/sites/all/modules/bean/bean_all/bean_all.install @@ -0,0 +1,39 @@ +<?php + +/** + * Implements hook_install() + */ +function bean_all_install() { + drupal_load('module', 'bean_all'); + + $blocks = array( + 'main', + 'powered-by', + 'help', + ); + + $name = bean_all_build_variable_name('system'); + variable_set($name, $blocks); + + $name = bean_all_build_variable_name('bean'); + variable_set($name, TRUE); +} + +/** + * Add black list variables + */ +function bean_all_update_7001(&$sand) { + drupal_load('module', 'bean_all'); + + $blocks = array( + 'main', + 'powered-by', + 'help', + ); + + $name = bean_all_build_variable_name('system'); + variable_set($name, $blocks); + + $name = bean_all_build_variable_name('bean'); + variable_set($name, TRUE); +} diff --git a/sites/all/modules/bean/bean_all/bean_all.module b/sites/all/modules/bean/bean_all/bean_all.module new file mode 100644 index 0000000000000000000000000000000000000000..6f3e5bfa76806baae2690e8a00a327cc9173e552 --- /dev/null +++ b/sites/all/modules/bean/bean_all/bean_all.module @@ -0,0 +1,166 @@ +<?php + +/** + * Implements hook_menu(). + */ +function bean_all_menu() { + $items = array(); + + $items['admin/config/system/bean-all'] = array( + 'title' => 'Bean Settings', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('bean_all_settings_form'), + 'access arguments' => array('administer bean settings'), + 'type' => MENU_NORMAL_ITEM, + ); + + return $items; +} + +/** + * Implements hook_bean_types(). + */ +function bean_all_bean_types() { + $running = &drupal_static(__FUNCTION__ . "_running", FALSE); + + $plugins = array(); + + if (!$running) { + $running = TRUE; + foreach (module_implements('block_info') as $module) { + if ($module !== 'bean') { + _bean_all_bean_types($plugins, $module); + } + } + $running = FALSE; + } + + return $plugins; +} + +function _bean_all_bean_types(&$plugins, $module) { + $default = array( + 'file' => 'all.inc', + 'path' => drupal_get_path('module', 'bean_all') . '/plugins', + 'handler' => array( + 'class' => 'BeanAll', + 'parent' => 'bean', + 'file' => 'all.inc', + 'path' => drupal_get_path('module', 'bean_all') . '/plugins', + ), + ); + + $module_blocks = module_invoke($module, 'block_info'); + + if (!empty($module_blocks)) { + bean_all_filter_blocks($module_blocks, $module); + foreach ($module_blocks as $delta => $block) { + $block = (object) $block; + $block->module = $module; + $block->delta = $delta; + $name = "{$module}_{$delta}"; + $plugins[$name] = array( + 'label' => $block->info, + 'description' => $block->info, + 'name' => "$module-$delta", + 'block' => $block + ) + $default; + } + } +} + +/** + * Implements hook_bean_types_api_info(). + */ +function bean_all_bean_types_api_info() { + return array( + 'api' => 5, + ); +} + +/** + * Get the block blacklist + * + * @param $module + * The module to pull the blacklist of + * + * @return array + * if the array is empty then no blocks are allowed + */ +function bean_all_get_blacklist($module) { + $variable_name = bean_all_build_variable_name($module); + + return variable_get($variable_name); +} + +function bean_all_build_variable_name($module) { + $variable_name = "bean_all_blacklist"; + + if (isset($module)) { + $variable_name .= "_{$module}"; + } + + return $variable_name; +} + + +/** + * Implements hook_block_info_alter(). + * + * Remove the ability to place the blocks in admin/structure/blocks + */ +function bean_all_block_info_alter(&$blocks, $theme, $code_blocks) { + foreach ($blocks as $module => $module_blocks) { + bean_all_filter_blocks($module_blocks, $module); + foreach ($module_blocks as $delta => $block) { + $blocks[$module][$delta]['status'] = FALSE; + $blocks[$module][$delta]['disabled'] = FALSE; + } + } +} + +/** + * Filter a list of blocks for a module + */ +function bean_all_filter_blocks(&$blocks, $module) { + $black_list = bean_all_get_blacklist($module); + + if ($black_list === TRUE) { + $blocks = array(); + } + elseif (is_array($black_list)) { + $black_list = array_combine($black_list, $black_list); + $blocks = array_diff_key($blocks, $black_list); + } +} + +function bean_all_settings_form($form, &$form_state) { + $form = array(); + $module_info = system_rebuild_module_data(); + + drupal_set_title(t('Select Blocks to not appear as Block Types')); + + foreach (module_implements('block_info') as $module) { + if ($module !== 'bean') { + $module_blocks = module_invoke($module, 'block_info'); + $variable_name = bean_all_build_variable_name($module); + $form[$variable_name] = array( + '#title' => $module_info[$module]->info['name'], + '#type' => 'vertical_tabs', + ); + $form[$variable_name][$variable_name] = array( + '#type' => 'checkboxes', + '#default_value' => variable_get($variable_name, array()), + ); + + $options = array(); + foreach ($module_blocks as $delta => $block) { + $options[$delta] = $block['info']; + } + + $form[$variable_name][$variable_name]['#options'] = $options; + } + } + + return system_settings_form($form); +} diff --git a/sites/all/modules/bean/bean_all/plugins/all.inc b/sites/all/modules/bean/bean_all/plugins/all.inc new file mode 100644 index 0000000000000000000000000000000000000000..ef79392048a566377df18c6e1dfdd5ec5063e8ba --- /dev/null +++ b/sites/all/modules/bean/bean_all/plugins/all.inc @@ -0,0 +1,69 @@ +<?php + +class BeanAll extends BeanPlugin { + protected $block_info; + protected $block_config_form; + + public function __construct($plugin_info) { + $this->block_info = $plugin_info['block']; + parent::__construct($plugin_info); + } + + public function values() { + $this->loadBlockConfig(); + $values = array_fill_keys(array_keys($this->block_config_form), array()); + foreach ($values as $key => $nothing) { + $values[$key] = isset($this->block_config_form[$key]['#default_value']) ? + $this->block_config_form[$key]['#default_value'] : ''; + } + + return $values; + } + + public function form($bean, $form, &$form_state) { + return $this->loadBlockConfig()->block_config_form; + } + + public function view($bean, $content, $view_mode = 'default', $langcode = NULL) { + $block_object = $this->getBlockInfo(); + $block_object->title = $block_object->info; + $block_object->enabled = $block_object->page_match = TRUE; + $blocks[$this->getBlockInfo('module') . "_" . $this->getBlockInfo('delta')] = $block_object; + + module_load_include('module', 'block', 'block'); + $block_content = _block_render_blocks($blocks); + $content += _block_get_renderable_array($block_content); + + $build[$this->getBlockInfo('module') . "_" . $this->getBlockInfo('delta')]['#contextual_links']['block'] + = array('block', array($bean->delta)); + + return $content; + } + + public function submit(Bean $bean) { + $bean_values = (array) $bean; + module_invoke($this->getBlockInfo('module'), 'block_save', $this->getBlockInfo('delta'), $bean_values); + return $this; + } + + protected function getBlockInfo($key = NULL) { + if (!empty($key) && isset($this->block_info->$key)) { + return $this->block_info->$key; + } + + return $this->block_info; + } + + protected function loadBlockConfig() { + if (!isset($this->block_config_form)) { + $this-> block_config_form = array(); + if ($settings = module_invoke($this->getBlockInfo('module'), 'block_configure', $this->getBlockInfo('delta'))) { + foreach ($settings as $k => $v) { + $this-> block_config_form[$k] = $v; + } + } + } + + return $this; + } +} diff --git a/sites/all/modules/bean/bean_usage/bean_usage.info b/sites/all/modules/bean/bean_usage/bean_usage.info new file mode 100644 index 0000000000000000000000000000000000000000..afbb317b29d25b906bbd1f2221349f6ac7584823 --- /dev/null +++ b/sites/all/modules/bean/bean_usage/bean_usage.info @@ -0,0 +1,13 @@ +name = Bean Usage +description = View Bean (Block Entities) Usage +core = 7.x +dependencies[] = bean +dependencies[] = blockreference +package = Bean + +; Information added by drupal.org packaging script on 2013-02-27 +version = "7.x-1.1" +core = "7.x" +project = "bean" +datestamp = "1361977163" + diff --git a/sites/all/modules/bean/bean_usage/bean_usage.module b/sites/all/modules/bean/bean_usage/bean_usage.module new file mode 100644 index 0000000000000000000000000000000000000000..932874a1b4a7b8566c5d559569256cb4c4727328 --- /dev/null +++ b/sites/all/modules/bean/bean_usage/bean_usage.module @@ -0,0 +1,518 @@ +<?php + +/* @file + * Show where Beans are used. + * Currently limited to beans displayed with blockreference. + * + */ + +/** + * Implements hook_menu() + * + * @return array + */ +function bean_usage_menu() { + $items = array(); + + // Todo: beans can be placed via context and block admin - we should account for those as well. + // usage tab on bean view + $items['block/%bean_delta/usage'] = array( + 'title' => 'Usage', + 'description' => 'Displays a list of entities where this bean is used.', + 'type' => MENU_LOCAL_TASK, + 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE, + 'page callback' => 'bean_usage_output', + 'page arguments' => array(1), + 'access arguments' => array('view bean usage'), + ); + + // bean usage report + $items['admin/reports/bean/usage'] = array( + 'title' => t('Bean usage'), + 'description' => 'Displays a list of Beans (blockreferences) and where they are used.', + 'page callback' => 'bean_usage_output', + 'page arguments' => array(4), + 'access arguments' => array('view bean usage'), + ); + + $items['admin/reports/bean/usage/list'] = array( + 'title' => t('Usage'), + 'description' => 'Displays a list of Beans (blockreferences) and where they are used.', + 'weight' => 0, + 'page callback' => 'bean_usage_output', + 'page arguments' => array(5), + 'access arguments' => array('view bean usage'), + 'type' => MENU_DEFAULT_LOCAL_TASK + ); + + $items['admin/reports/bean/usage/settings'] = array( + 'title' => t('Settings'), + 'description' => t('Displays a list of Beans (blockreferences) and where they are used.'), + 'weight' => 1, + 'page callback' => 'drupal_get_form', + 'page arguments' => array('bean_usage_settings'), + 'access arguments' => array('administer bean usage'), + 'file' => 'includes/bean_usage.forms.inc', + 'type' => MENU_LOCAL_TASK | MENU_NORMAL_ITEM, + ); + + return $items; +} + +/** + * Implements hook_permission() + * + * @return array + */ +function bean_usage_permission() { + $perms = array( + 'view bean usage' => array( + 'title' => t('View bean usage'), + 'description' => t('View a list of Beans (blockreferences) and where they are used.'), + ), + 'administer bean usage' => array( + 'title' => t('Administer bean usage'), + 'description' => t('Administer settings for the bean usage page.'), + ), + ); + return $perms; +} + +/** + * @file + * Bean Admin Functions and Display + */ + +/** + * Displays a table of Beans and their usage + * + * @return string - the HTML for the table + */ +function bean_usage_output($bean = NULL) { + module_load_include('inc', 'bean_usage', 'includes/bean_usage.forms'); + $output = ''; + $bean_delta = NULL; + $delta_specific = $delta_found = FALSE; + $bean_usage_form = drupal_get_form('bean_usage_filters'); + + if (!empty($bean) && is_object($bean)) { + $delta_specific = TRUE; + } else if (is_numeric($bean)) { + $delta_specific = TRUE; + $bean = bean_load($bean); + } + + if (is_object($bean)) { + drupal_set_title($bean->label . ' Usage'); + $bean_delta = $bean->delta; + } + + // Get all fields that are of type blockreference and not deleted + $fields = bean_usage_blockreference_fields(); + + // If we have something to work with + if (!empty($fields)) { + $filters = empty($_GET['filter']) ? '' : $_GET['filter']; + + if ($delta_specific) { + $delta_found = FALSE; + } + + $entity_types = bean_usage_blockrefence_entity_types(); + $bundles = bean_usage_blockreference_bundles(); + + $query = ''; + foreach($fields as $i => $field) { + if (!$delta_found) { + $field_name = $field->name; + $data_table = 'field_data_' . $field_name; + if ($i == 0) { + $query = _bean_usage_field_data($data_table, $i, $field_name, $entity_types, $bundles, $filters, $delta_specific, $bean); + } + else { + $query->union(_bean_usage_field_data($data_table, $i, $field_name, $entity_types, $bundles, $filters, $delta_specific, $bean)); + } + } + } + + // Get the data + $data = $query->execute()->fetchAll(0); + + if (!empty($data)) { + // Sort the data - default sort is by label + usort($data, 'bean_usage_sort_by_label'); + + if (!empty($_GET['order'])) { + $sort_by = empty($_GET['order']) ? '' : str_replace('bean ', '', (strtolower($_GET['order']))); + switch ($sort_by) { + case 'label': + usort($data, 'bean_usage_sort_by_label'); + break; + case 'title': + usort($data, 'bean_usage_sort_by_title'); + break; + case 'type': + usort($data, 'bean_usage_sort_by_type'); + break; + } + } + + if (!empty($_GET['sort']) && $_GET['sort'] == 'desc') { + $data = array_reverse($data); + } + + $content = array(); + foreach ($data as $bean_data) { + // We want to link to display the entity type title/name + $entity_title = ''; + switch ($bean_data->entity_type) { + // If its a node, get the node title + case 'node': + $entity_title = _bean_usage_entity_display('node', $bean_data->entity_id, 'nid', 'title'); + break; + + // If its a user, get the user name + case 'user': + $entity_title = _bean_usage_entity_display('user', $bean_data->entity_id, 'uid', 'name'); + break; + } + + $content[$bean_data->label][$bean_data->entity_type][$bean_data->delta]['bean_title'] = $bean_data->title; + $content[$bean_data->label][$bean_data->entity_type][$bean_data->delta]['bean_type'] = $bean_data->type; + $content[$bean_data->label][$bean_data->entity_type][$bean_data->delta]['entity_id'] = $bean_data->entity_id; + $content[$bean_data->label][$bean_data->entity_type][$bean_data->delta]['entity_title'] = $entity_title; + + if ($delta_specific) { + $delta_found = TRUE; + } + } + } + + // If we have any usage data create and display the table of data + if (!empty($content)) { + $rows = count($content); + $results_per_page = variable_get('bean_usage_results_per_page', 30); + // set up pager variables + pager_default_initialize($rows, $results_per_page, $element = 0); + + // Set up output table + $bean_table_data = array( + 'attributes' => array( // set table attributes + 'width' => '100%' // width + ), + 'header' => _bean_usage_table_headers($bean_delta), + 'rows' => array(), // table rows + ); + + if ($filters) { + $bean_table_data['caption'] = t('Filters: ') . $filters; + } + + // Get the result subset for the current page + $page = empty($_GET['page']) ? 0 : $_GET['page']; + $range_start = $page * $results_per_page; + $usage = array_slice($content, $range_start, $results_per_page); + // If the user is on a higher page and then filters, the page + if (!empty($filters) && $page != 0 && count($usage) == 0) { + while (count($usage) == 0) { + $page--; + $range_start = $page * $results_per_page; + $usage = array_slice($content, $range_start, $results_per_page); + } + } + + foreach ($usage as $bean_label => $entity_type) { + foreach ($entity_type as $type => $delta) { + $rowspan = count($delta); + $bean_label_cell = ''; + if (empty($bean_delta)) { + $bean_label_cell = array( + 'data' => $bean_label, + 'rowspan' => $rowspan, + 'width' => '30%', + ); + } + + // we create the row with the bean name first and set the rowspan to however many deltas there are + foreach ($delta as $entity) { + $bean_title_cell = array( + 'data' => empty($entity['bean_title']) ? '<em>' . t('No title set') . '</em>' : $entity['bean_title'], + 'rowspan' => $rowspan, + 'width' => '30%', + ); + + $bean_type_cell = array( + 'data' => $entity['bean_type'], + 'rowspan' => $rowspan, + 'width' => '10%', + ); + + // We want to prefix the entity title with the entity id + // We also want the entity title to link back the to the entity page + $link_prefix = ''; + $text_prefix = ''; + switch ($type) { + case 'node': + $text_prefix = '[nid:' . $entity['entity_id'] . '] '; + $link_prefix = 'node/'; + break; + case 'user': + $text_prefix = '[uid:' . $entity['entity_id'] . '] '; + $link_prefix = 'user/'; + break; + } // switch ($entity_type) + + // add the usage data to the table + // We only need to add the Bean label once per delta, Since we set it above we check for its emptiness + if (!empty($bean_label_cell)) { + $bean_table_data['rows'][] = array( + 0 => $bean_label_cell, + 1 => $bean_title_cell, + 2 => $bean_type_cell, + 3 => array( + 'data' => $text_prefix . l($entity['entity_title'], $link_prefix . $entity['entity_id']), + 'width' => '30%', + 'no_striping' => TRUE + ), + ); + } // if (!empty($bean_label_cell)) + else { + $bean_table_data['rows'][] = array( + $text_prefix . l( + t($entity['entity_title']), + $link_prefix . $entity['entity_id'], + array( + 'attributes' => array( + 'title' => $entity['entity_title'], + 'target' => '_blank' + ), + ) + ), + ); + } // else + // empty out the $bean_row so that it doesn't display more than one if there are multiple deltas for the block + $bean_label_cell = ''; + } // foreach ($delta) + } //foreach ($entity_type) + } // foreach ($usage) + // Set the output using theme_table with the header and rows created above + if (!$delta_specific) { + $output .= drupal_render($bean_usage_form); + } + $output .= theme('table', $bean_table_data); + $output .= theme('pager'); + } // if (!empty($usage)) + else { + if ($delta_specific) { + $output = '<p>' . t('This bean is not used anywhere on the site.') . '</p>'; + } + else { + $output .= $bean_usage_form; + $output .= 'There is no bean usage to report for '. $filters; + } + } // else + } // if (!empty($fields)) + + // return the output for page rendering + return $output; +} + +/** + * Get all fields that are of type blockreference and not deleted + * + * @return mixed + */ +function bean_usage_blockreference_fields() { + $fields = &drupal_static(__FUNCTION__); + + if (!isset($fields)) { + $query = db_select('field_config', 'fc'); + $query->addField('fc', 'field_name', 'name'); + $query->leftJoin('field_config_instance', 'fci', 'fc.field_name = fci.field_name'); + $fields = $query->condition('fc.type', 'blockreference') + ->condition('fc.deleted', 0) + ->orderBy('fc.field_name', 'asc') + ->execute() + ->fetchAll(0); + } + + return $fields; +} + +/** + * Get all of the entity types used with beans via blockreference + * + * @return array + */ +function bean_usage_blockrefence_entity_types() { + $entity_types = array(); + + $et_query = db_select('field_config_instance', 'fci')->distinct(); + $et_query->addField('fci', 'entity_type', 'type'); + $et_query->join('field_config', 'fc', 'fc.field_name = fci.field_name'); + $et_res = $et_query->condition('fc.type', 'blockreference') + ->execute() + ->fetchAll(0); + + foreach($et_res as $entity) { + $entity_types[] = $entity->type; + } + + return $entity_types; +} + +/** + * Get all of the bundles used with beans via blockreference + * + * @return array + */ +function bean_usage_blockreference_bundles() { + $bundles = array(); + + $b_query = db_select('field_config_instance', 'fci')->distinct(); + $b_query->join('field_config', 'fc', 'fc.field_name = fci.field_name'); + $b_res = $b_query->fields('fci', array('bundle')) + ->condition('fc.type', 'blockreference') + ->execute() + ->fetchAll(0); + + foreach($b_res as $bundle) { + $bundles[] = $bundle->bundle; + } + + return $bundles; +} + +/** + * Helper function to display an entity on the report + * + * @param $table + * @param $value + * @param $key + * @param $column + * @return mixed + */ +function _bean_usage_entity_display($table, $value, $key, $column) { + $query = db_select($table, 't') + ->fields('t', array($column)) + ->condition($key, $value) + ->execute() + ->fetchAssoc(); + + return $query[$column]; +} + +/** + * Get the data from the field_data tables for bean usage based on bean.bid and bean.delta + * + * @param string $data_table + * @param int $i + * @param string $field_name + * @param array $entity_types + * @param array $bundles + * @param string $filter + * @param boolean $delta_specific + * @param object bean + * + * @return SelectQuery + */ +function _bean_usage_field_data( $data_table, $i, $field_name, $entity_types, $bundles, $filter = NULL, $delta_specific = FALSE, $bean = NULL) { + $filters = explode(',', $filter); + $query = db_select($data_table, 'fd'. $i); + $query->leftJoin('block', 'bl', 'fd'. $i . '.' . $field_name . '_bid = bl.bid'); + $query->join('bean', 'b', 'b.delta = bl.delta'); + $query->fields('b', array('bid', 'label', 'title', 'type')); + $query->fields('fd'. $i, array('entity_id', 'delta', 'entity_type')); + $query->addField('fd'. $i, $field_name . '_bid', 'bid'); + $query_and = db_and(); + $query_and->condition('bl.module', 'bean'); + $query_and->condition('bl.theme', variable_get('theme_default', NULL)); + $query_and->condition('fd'. $i . '.entity_type', $entity_types, 'IN'); + $query_and->condition('fd'. $i . '.bundle', $bundles, 'IN'); + + if (!empty($filter)) { + $query_and->condition('b.type', $filters, 'IN'); + } + + if ($delta_specific && !empty($bean)) { + $query_and->condition('b.bid', intval($bean->bid)); + } + + $query->condition($query_and); + return $query; +} + +/** + * Set the table headers for the table output based on the page that calls for the data. + * + * @param null $bean_delta + * + * @return array + */ +function _bean_usage_table_headers($bean_delta = NULL) { + if (empty($bean_delta)) { + $table_data_headers = array( + 0 => array( + 'data' => t('Bean label'), + 'field' => 'label', + 'sort' => 'asc' + ), + 1 => array( + 'data' => t('Bean title'), + 'field' => 'title', + ), + 2 => array( + 'data' => t('Bean type'), + 'field' => 'type', + ), + 3 => array( + 'data' => t('Used in'), + ), + ); + } + else { + $table_data_headers = array( + 0 => array( + 'data' => t('Used in'), + ), + ); + } + + return $table_data_headers; +} + +/** + * Sort bean usage by bean.label + * + * @param $a + * @param $b + * + * @return int + */ +function bean_usage_sort_by_label($a, $b) { + return strcmp($a->label, $b->label); +} + +/** + * Sort bean usage by bean.title + * + * @param $a + * @param $b + * + * @return int + */ +function bean_usage_sort_by_title($a, $b) { + return strcmp($a->title, $b->title); +} + +/** + * Sort bean usage by bean.type + * + * @param $a + * @param $b + * + * @return int + */ +function bean_usage_sort_by_type($a, $b) { + return strcmp($a->type, $b->type); +} diff --git a/sites/all/modules/bean/bean_usage/includes/bean_usage.forms.inc b/sites/all/modules/bean/bean_usage/includes/bean_usage.forms.inc new file mode 100644 index 0000000000000000000000000000000000000000..524273ea5c6281dddf0bac246cee0fadbf6237f8 --- /dev/null +++ b/sites/all/modules/bean/bean_usage/includes/bean_usage.forms.inc @@ -0,0 +1,117 @@ +<?php +function bean_usage_settings() { + $form = array(); + + $form['bean_usage_results'] = array( + '#type' => 'fieldset', + '#title' => t('Results per page'), + '#weight' => 0, + '#collapsible' => FALSE, + ); + + $form['bean_usage_results']['bean_usage_results_per_page'] = array( + '#title' => t('Results per page'), + '#description' => t('How many results display per page on the bean usage page'), + '#type' => 'select', + '#options' => array( + '5' => 5, + '10' => 10, + '15' => 15, + '20' => 20, + '25' => 25, + '30' => 30, + '35' => 35, + '40' => 40, + '45' => 45, + '50' => 50, + ), + '#default_value' => variable_get('bean_usage_results_per_page', 30), + ); + + return system_settings_form($form); +} + +/** + * Filter form for bean usage view + * + * @return array + */ +function bean_usage_filters() { + $params = drupal_get_query_parameters(); + $filters = empty($params['filter']) ? '' : explode(',', $params['filter']); + + $form = array(); + + $form['bean_usage_filter'] = array( + '#type' => 'fieldset', + '#title' => t('Filter by bean type'), + '#weight' => 0, + '#collapsible' => TRUE, + '#collapsed' => FALSE, + ); + + $bean_types = bean_get_types(); + $options = array(); + foreach ($bean_types as $bean) { + $options[$bean->type] = $bean->type; + } + + asort($options); + $multiple = TRUE; + + $form['bean_usage_filter']['bean_usage_filter_type'] = array( + '#type' => 'select', + '#prefix' => '<div style="margin-right:10px; position:relative; float:left;">', + '#suffix' => '</div>', + '#multiple' => $multiple, + '#size' => $multiple ? min(4, count($options)) : 0, + '#title' => t('Filter type'), + '#description' => t('Choose the bean types to filter the list of results.'), + '#options' => $options, + '#default_value' => $filters, + ); + + $form['bean_usage_filter']['actions'] = array( + '#type' => 'actions', + '#prefix' => '<div style="position:relative; float:left;">', + '#suffix' => '</div>', + ); + + $form['bean_usage_filter']['actions']['apply'] = array( + '#type' => 'submit', + '#value' => t('Apply'), + ); + + $form['bean_usage_filter']['actions']['reset'] = array( + '#type' => 'submit', + '#value' => t('Reset'), + ); + + return $form; +} + +/** + * Submit function for bean_usage_filters() + * + * Applies the filter via a redirect back to the bean usage view page with the added filter query param. + * + * @param $form + * @param $form_state + */ +function bean_usage_filters_submit(&$form, &$form_state) { + // Get the query string parameters minus the drupal url and filter param + $params = drupal_get_query_parameters($_GET, array('q', 'filter')); + + // add the filter to the query string + $filters = $form_state['values']['bean_usage_filter_type']; + if (!empty($filters)) { + switch (strtolower($form_state['values']['op'])) { + case 'apply': + $params['filter'] = join(',', $filters); + break; + } + } + + // Redirect back to bean usage view with added filter query string param + drupal_goto($_GET['q'], array('query' => $params)); +} diff --git a/sites/all/modules/bean/bean_uuid/bean_uuid.info b/sites/all/modules/bean/bean_uuid/bean_uuid.info new file mode 100644 index 0000000000000000000000000000000000000000..bd5e9331064edaf952bf75f12a92cc41adcdca48 --- /dev/null +++ b/sites/all/modules/bean/bean_uuid/bean_uuid.info @@ -0,0 +1,15 @@ +name = Bean UUID +description = Allow deploying bean blocks through Deploy and UUID modules. +core = 7.x + +dependencies[] = bean +dependencies[] = uuid + +package = Bean + +; Information added by drupal.org packaging script on 2013-02-27 +version = "7.x-1.1" +core = "7.x" +project = "bean" +datestamp = "1361977163" + diff --git a/sites/all/modules/bean/bean_uuid/bean_uuid.install b/sites/all/modules/bean/bean_uuid/bean_uuid.install new file mode 100644 index 0000000000000000000000000000000000000000..deab2c519a48e27ffb27aa094b4353d41a205ad0 --- /dev/null +++ b/sites/all/modules/bean/bean_uuid/bean_uuid.install @@ -0,0 +1,38 @@ +<?php + +/** + * @file + * Bean UUID installation and schema hooks. + */ + +/** + * Implements hook_schema_alter(). + */ +function bean_uuid_schema_alter(&$schema = array()) { + $field = uuid_schema_field_definition(); + $schema['bean']['fields']['uuid'] = $field; +} + +/** + * Implements hook_install(). + */ +function bean_uuid_install() { + $field = uuid_schema_field_definition(); + db_add_field('bean', 'uuid', $field); + db_add_index('bean', 'uuid', array('uuid')); +} + +/** + * Implements hook_enable(). + */ +function bean_uuid_enable() { + uuid_sync_all(); +} + +/** + * Implements hook_uninstall(). + */ +function bean_uuid_uninstall() { + db_drop_field('bean', 'uuid'); + db_drop_index('bean', 'uuid'); +} diff --git a/sites/all/modules/bean/bean_uuid/bean_uuid.module b/sites/all/modules/bean/bean_uuid/bean_uuid.module new file mode 100644 index 0000000000000000000000000000000000000000..9dab57bd32d993ad55f759c69cf5d1b5b80e7d58 --- /dev/null +++ b/sites/all/modules/bean/bean_uuid/bean_uuid.module @@ -0,0 +1,33 @@ +<?php + +/** + * @file + * Implement UUID/Entity hooks for integrating with deploy and other modules. + */ + +/** + * Implements hook_entity_info_alter(). + */ +function bean_uuid_entity_info_alter(&$entity_info) { + // Set the properties bellow for bean entity so UUIDs get created on sync. + $entity_info['bean']['uuid'] = TRUE; + $entity_info['bean']['entity keys']['uuid'] = 'uuid'; +} + +/** + * Implements hook_entity_uuid_load(). + */ +function bean_uuid_entity_uuid_load(&$entities, $entity_type) { + if ($entity_type == 'bean') { + entity_property_id_to_uuid($entities, 'bean', 'bid'); + } +} + +/** + * Implements hook_entity_uuid_presave(). + */ +function bean_uuid_entity_uuid_presave(&$entity, $entity_type) { + if ($entity_type == 'bean') { + entity_property_uuid_to_id($entity, 'bean', 'bid'); + } +} diff --git a/sites/all/modules/bean/includes/bean.core.inc b/sites/all/modules/bean/includes/bean.core.inc new file mode 100644 index 0000000000000000000000000000000000000000..162fc02ce342929b909a3b9970a6389298bcc454 --- /dev/null +++ b/sites/all/modules/bean/includes/bean.core.inc @@ -0,0 +1,484 @@ +<?php + +/** + * @file + * Bean classes and plugin interface + */ + +/** + * Interface for Plugin Classes + */ +interface BeanTypePluginInterface { + + /** + * Constructor + * + * Plugin info should be called using bean_fetch_plugin_info(). + * + * @abstract + * + * @param $plugin_info array of information from the ctools plugin. + */ + public function __construct($plugin_info); + + /** + * Get the ctools plugin info. + * + * If you pass in a key, then the key from the plugin info will be returned + * otherwise the entire plugin will be returned + * + * @abstract + * + * @param $key + * @return array of plugin info for value froma key + */ + public function getInfo($key = NULL); + + /** + * Build the URL string for the plugin + * + * @abstract + * + * @return url + */ + public function buildURL(); + + /** + * Get the label name of the plugin + * + * @abstract + * + * @return label of the type + */ + public function getLabel(); + + /** + * Get the description of the plugin + * + * @abstract + * + * @return + * description of the type + */ + public function getDescription(); + + /** + * Set the Bean object for later use + * + * @abstract + * + * @param Bean $bean + */ + public function setBean($bean); + + /** + * Is this type editable? + * + * @abstract + * + * @return boolean + */ + public function isEditable(); + + /** + * Define the form values and their defaults + */ + public function values(); + + /** + * The Plugin Form + * + * The Bean object will be either loaded from the database or filled with the defaults. + * + * @param $bean + * @param $form + * @param $form_state + * @return array + * form array + */ + public function form($bean, $form, &$form_state); + + /** + * Validate function for bean type form + * + * @abstract + * + * @param $values + * @param $form_state + */ + public function validate($values, &$form_state); + + /** + * React to a bean being saved + * + * @abstract + * + * @param Bean $bean + */ + public function submit(Bean $bean); + + /** + * Return the block content. + * + * @abstract + * + * @param $bean + * The bean object being viewed. + * @param $content + * The default content array created by Entity API. This will include any + * fields attached to the entity. + * @param string $view_mode + * The view mode passed into $entity->view(). + * + * @param null $langcode + * + * @return + * Return a renderable content array. + */ + public function view($bean, $content, $view_mode = 'default', $langcode = NULL); +} + +/** + * The Bean entity class + */ +class Bean extends Entity { + public $label; + public $description; + public $title; + public $type; + public $data; + public $delta; + public $view_mode; + public $bid; + public $vid; + public $created; + public $changed; + public $log; + public $uid; + public $default_revision; + public $revisions = array(); + protected $plugin; + + /** + * Get Plugin info + * + * @param $key + * The plugin key to get the info for. + * + * @return array|null + */ + public function getInfo($key = NULL) { + if ($this->plugin instanceof BeanTypePluginInterface) { + return $this->plugin->getInfo($key); + } + + return NULL; + } + + public function __construct(array $values = array()) { + // If this is new then set the type first. + if (isset($values['is_new'])) { + $this->type = isset($values['type']) ? $values['type'] : ''; + } + + parent::__construct($values, 'bean'); + } + + public function adminTitle() { + return check_plain($this->label); + } + + protected function setUp() { + parent::setUp(); + + if (!empty($this->type)) { + $plugin = bean_load_plugin_class($this->type); + $this->loadUp($plugin); + } + return $this; + } + + /** + * This is a work around for version of PDO that call __construct() before + * it loads up the object with values from the DB. + */ + public function loadUp($plugin) { + if (empty($this->plugin)) { + // If the plugin has been disabled, the $plugin will be a boolean. + // just load the base plugin so something will render. + if (!($plugin instanceof BeanTypePluginInterface)) { + $plugin = bean_load_plugin_class('bean_default'); + } + + $this->setPlugin($plugin)->setFields(); + } + return $this; + } + + /** + * Load and set the plugin info. + * This can be called externally via loadUP() + */ + protected function setPlugin($plugin) { + $this->plugin = $plugin; + + return $this; + } + + /** + * Set the fields from the defaults and plugin + * This can be called externally via loadUP() + */ + protected function setFields() { + // NOTE: When setFields is called externally $this->data is already unserialized. + if (!empty($this->plugin) && !empty($this->type)) { + $values = is_array($this->data) ? $this->data : unserialize($this->data); + foreach ($this->plugin->values() as $field => $default) { + $this->$field = isset($values[$field]) ? $values[$field] : $default; + } + } + return $this; + } + + /** + * Override this in order to implement a custom default URI and specify + * 'entity_class_uri' as 'uri callback' hook_entity_info(). + */ + protected function defaultUri() { + return array('path' => 'block/' . strtolower($this->identifier())); + } + + /** + + * Get the default label + + * + + * @return string + + */ + protected function defaultLabel() { + if (empty($this->label)) { + return $this->getTranslation('title'); + } + + return $this->getTranslation('label'); + } + + /** + * Get the plugin form + */ + public function getForm($form, &$form_state) { + return $this->plugin->form($this, $form, $form_state); + } + + /** + * Validate the plugin form + */ + public function validate($values, &$form_state) { + $this->plugin->validate($values, $form_state); + } + + /** + * URL string + */ + public function url() { + $uri = $this->defaultUri(); + return $uri['path']; + } + + /** + * Build the URL string + */ + protected function buildURL($type) { + $url = $this->url(); + return $url . '/' . $type; + } + + /** + * View URL + */ + public function viewURL() { + return $this->buildURL('view'); + } + + /** + * View URL + */ + public function editURL() { + return $this->buildURL('edit'); + } + + /** + * View URL + */ + public function deleteURL() { + return $this->buildURL('delete'); + } + + /** + * Type name + */ + public function typeName() { + return $this->getInfo('label'); + } + + /** + * Set the values from a plugin + */ + public function setValues($values) { + $this->data = array(); + foreach ($this->plugin->values() as $field => $value) { + $this->data[$field] = $values[$field]; + } + + return $this; + } + + /** + * Generate an array for rendering the entity. + * + * @see entity_view() + */ + public function view($view_mode = 'default', $langcode = NULL, $page = NULL) { + $content = parent::view($view_mode, $langcode); + if (empty($this->plugin)) { + return $content; + } + return $this->plugin->view($this, $content, $view_mode, $langcode); + } + + /** + * Override the save to add clearing of caches + */ + public function save() { + $this->setUid()->checkDelta(); + + if (empty($this->created)) { + $this->created = REQUEST_TIME; + } + + $this->changed = REQUEST_TIME; + + $this->plugin->submit($this); + + $return = parent::save(); + bean_reset(); + + return $return; + } + + /** + * Get the user + */ + protected function setUid() { + global $user; + + $this->uid = empty($this->uid) ? $user->uid : $this->uid; + + return $this; + } + + /** + * Set the delta function + */ + protected function checkDelta() { + if (empty($this->delta)) { + $max_length = 32; + + // Base it on the label and make sure it isn't too long for the database. + if (module_exists('transliteration')) { + $delta = drupal_clean_css_identifier(transliteration_get($this->label)); + } + else { + $delta = drupal_clean_css_identifier(strtolower($this->label));; + } + + $this->delta = substr($delta, 0, $max_length); + + // Check if delta is unique. + if (bean_load_delta($this->delta)) { + $i = 0; + $separator = '-'; + $original_delta = $this->delta; + do { + $unique_suffix = $separator . $i++; + $this->delta = substr($original_delta, 0, $max_length - drupal_strlen($unique_suffix)) . $unique_suffix; + } while (bean_load_delta($this->delta)); + } + } + + return $this; + } + + /** + * Load the revisions from the DB + */ + public function loadRevisions() { + $this->revisions = db_select('bean_revision', 'br') + ->condition('delta', $this->identifier()) + ->fields('br') + ->execute(); + + return $this; + } +} + +class BeanEntityAPIController extends EntityAPIControllerExportable { + protected function setPlugin(Bean $bean) { + static $plugins = array(); + + if (empty($plugins[$bean->type])) { + $plugins[$bean->type] = bean_load_plugin_class($bean->type); + $bean->loadUp($plugins[$bean->type]); + } + } + + protected function attachLoad(&$queried_entities, $revision_id = FALSE) { + foreach ($queried_entities as $entity) { + $this->setPlugin($entity); + } + parent::attachLoad($queried_entities, $revision_id); + } + + public function delete($ids, DatabaseTransaction $transaction = NULL) { + $beans = $ids ? $this->load($ids) : array(); + + $deltas = array(); + foreach ($beans as $bean) { + if ($bean->internalIdentifier()) { + field_attach_delete('bean', $bean); + + $deltas[] = $bean->identifier(); + } + } + + if (!empty($deltas)) { + try { + // @see block_custom_block_delete_submit() + if (module_exists('block')) { + db_delete('block') + ->condition('module', 'bean') + ->condition('delta', $deltas) + ->execute(); + db_delete('block_role') + ->condition('module', 'bean') + ->condition('delta', $deltas) + ->execute(); + + // @see node_form_block_custom_block_delete_submit() + db_delete('block_node_type') + ->condition('module', 'bean') + ->condition('delta', $deltas) + ->execute(); + } + } + catch (Exception $e) { + if (isset($transaction)) { + $transaction->rollback(); + } + watchdog_exception('bean', $e); + throw $e; + } + } + parent::delete($ids, $transaction); + } +} + +class BeanException extends Exception {}; diff --git a/sites/all/modules/bean/includes/bean.info.inc b/sites/all/modules/bean/includes/bean.info.inc new file mode 100644 index 0000000000000000000000000000000000000000..aaecd8e60f226f037cd1a58cf190adefe8b99b08 --- /dev/null +++ b/sites/all/modules/bean/includes/bean.info.inc @@ -0,0 +1,60 @@ +<?php + +/** + * @file + * Provides Entity metadata integration. + */ + +/** + * Extend the defaults. + */ +class BeanMetadataController extends EntityDefaultMetadataController { + + public function entityPropertyInfo() { + $info = parent::entityPropertyInfo(); + $properties = &$info[$this->type]['properties']; + + $properties['label'] = array( + 'label' => t('Label'), + 'description' => t('The bean label'), + 'getter callback' => 'entity_property_getter_method', + 'setter callback' => 'entity_property_verbatim_set', + 'schema field' => 'label', + ); + + $properties['title'] = array( + 'label' => t('Title'), + 'description' => t('The bean title'), + 'getter callback' => 'entity_property_verbatim_get', + 'setter callback' => 'entity_property_verbatim_set', + 'schema field' => 'title', + ); + + $properties['view_mode'] = array( + 'label' => t('View Mode'), + 'description' => t('View mode of the bean'), + 'getter callback' => 'entity_property_verbatim_get', + 'schema field' => 'view_mode', + 'required' => TRUE, + ); + + $properties['delta'] = array( + 'getter callback' => 'entity_property_verbatim_get', + 'description' => t('The delta of the block'), + 'label' => t('Block Delta'), + 'required' => TRUE, + 'schema field' => 'delta', + ); + + $properties['type'] = array( + 'type' => 'bean_type', + 'getter callback' => 'entity_property_verbatim_get', + 'setter callback' => 'entity_property_verbatim_set', + 'setter permission' => 'administer beans', + 'required' => TRUE, + 'description' => t('The bean type.'), + ) + $properties['type']; + + return $info; + } +} diff --git a/sites/all/modules/bean/includes/bean.pages.inc b/sites/all/modules/bean/includes/bean.pages.inc new file mode 100644 index 0000000000000000000000000000000000000000..b7ac3f1edc79abbaade311f62068c1850acb21d8 --- /dev/null +++ b/sites/all/modules/bean/includes/bean.pages.inc @@ -0,0 +1,716 @@ +<?php + +/** + * @file + * Bean Functions + */ + +/** + * Bean view page + */ +function bean_view_page(Bean $bean) { + $title = $bean->label() ? $bean->label() : $bean->adminTitle(); + drupal_set_title($title); + return bean_view($bean); +} + +/** + * Edit bean page callback + */ +function bean_edit(Bean $bean) { + $type = bean_fetch_plugin_info($bean->type); + drupal_set_title(t('Edit @type: @title', array('@type' => $type['label'], '@title' => $bean->label))); + return drupal_get_form('bean_form', $bean); +} + +/** + * Add bean page callback + */ +function bean_add($type) { + $bean = bean_create(array('type' => $type)); + $bean_type = bean_type_load($type); + drupal_set_title(t('Create @type block', array('@type' => $bean_type->getLabel()))); + + return drupal_get_form('bean_form', $bean, $type); +} + +/** + * Menu Callback to list available bean types to add + */ +function bean_add_page() { + $bean_types = bean_get_types(); + + $types = array(); + foreach ($bean_types as $key => $bean_type) { + if (bean_access('create', $bean_type->type)) { + $types[$key] = $bean_type; + } + } + + // If there are block types, but the user doesn't have access, return 403. + if (count($types) == 0 && count($bean_types) > 0) { + return drupal_access_denied(); + } + + // Bypass the block/add listing if only one block type is available. + if (count($types) == 1) { + $bean_type = array_shift($types); + drupal_goto('block/add/' . $bean_type->buildURL()); + } + + return theme('bean_add_list', array('content' => $types)); +} + +function bean_list() { + $rows = array(); + + // Build the sortable table header. + $header = array( + 'title' => array( + 'data' => 'Title', + 'type' => 'property', + 'specifier' => 'title', + 'sort' => 'asc' + ), + 'type' => array( + 'data' => 'Type', + 'type' => 'entity', + 'specifier' => 'bundle', + ), + 'operations' => array('data' => t('Operations')), + ); + + $filters = bean_get_filter(); + + + $query = new EntityFieldQuery(); + $query->entityCondition('entity_type', 'bean') + ->tableSort($header) + ->pager($filters['per_page']); + + if (!empty($filters['types'])) { + $query->entityCondition('bundle', $filters['types'], 'IN'); + } + + $result = $query->execute(); + if (!empty($result)) { + $beans = bean_load_multiple(array_keys($result['bean'])); + } + else { + $beans = array(); + } + + foreach ($beans as $bean) { + $rows[$bean->bid] = array( + 'title' => array( + 'data' => array( + '#type' => 'link', + '#title' => $bean->label, + '#href' => 'block/' . $bean->delta, + ), + ), + 'type' => check_plain($bean->type), + ); + + $destination = drupal_get_destination(); + + // Build a list of all the accessible operations for the current bean. + $operations = array(); + $operations['edit'] = array( + 'title' => t('edit'), + 'href' => 'block/' . $bean->delta . '/edit', + 'query' => $destination, + ); + $operations['delete'] = array( + 'title' => t('delete'), + 'href' => 'block/' . $bean->delta . '/delete', + 'query' => $destination, + ); + // Render an unordered list of operations links. + $rows[$bean->bid]['operations'] = array( + 'data' => array( + '#theme' => 'links__bean_operations', + '#links' => $operations, + '#attributes' => array('class' => array('links', 'inline')), + ), + ); + } + + $output = array( + 'bean_filter_form' => drupal_get_form('bean_filter_form'), + 'bean_content' => array( + '#theme' => 'table', + '#header' => $header, + '#rows' => $rows, + '#empty' => t('There are no Block Available'), + ), + 'pager' => array( + '#theme' => 'pager', + ), + ); + + return $output; +} + +/** + * Returns HTML for a list of available bean types for bean creation. + * + * @param $variables + * An associative array containing: + * - content: An array of bean types. + * + * @ingroup themeable + */ +function theme_bean_add_list($variables) { + $content = $variables['content']; + $blocks = array(); + $i = 0; + + if ($content) { + foreach ($content as $item) { + $title = l(t('<span class="icon"></span>@label', array('@label' => $item->getLabel())), 'block/add/' . $item->buildURL(), array('html' => TRUE)); + $description = (!is_array($item->getDescription())) ? '<div class="description">' . $item->getDescription() . '</div>' : ''; + //creative way to setup sorting by label; add number to prevent duplicate keys + $blocks[str_replace(' ', '', $item->getLabel()) . '_' . $i] = '<li>' . $title . $description . '</li>'; + $i++; + } + ksort($blocks); + $output = '<ul class="bean-type-list admin-list">' . implode('', $blocks) . '</ul>'; + } + else { + $output = '<p>' . t('You have not created any block types yet.') . '</p>'; + } + return $output; +} + +/** + * Bean form + */ +function bean_form($form, &$form_state, Bean $bean, $type = NULL) { + + // During initial form build, add the bean entity to the form state for use + // during form building and processing. During a rebuild, use what is in the + // form state. + if (!isset($form_state['bean'])) { + if (!isset($bean->label)) { + $bean->label = NULL; + } + if (isset($type)) { + $bean->type = $type; + } + $form_state['bean'] = $bean; + } + else { + $bean = $form_state['bean']; + } + + $form['label'] = array( + '#type' => 'textfield', + '#title' => t('Label'), + '#required' => TRUE, + '#default_value' => $bean->label, + '#description' => t('Name that displays in the admin interface'), + '#weight' => -10, + ); + + $form['title'] = array( + '#type' => 'textfield', + '#title' => t('Title'), + '#description' => t('The Title of the block.'), + '#default_value' => $bean->title, + '#weight' => -9, + ); + + $form['revision'] = array( + '#weight' => 10, + ); + + if (isset($bean->is_new)) { + $form['revision']['#access'] = FALSE; + } + + ctools_include('dependent'); + ctools_add_js('dependent'); + + $form['revision']['is_new_revision'] = array( + '#type' => 'checkbox', + '#title' => t('Create new revision'), + '#default_value' => 1, + '#id' => 'edit-revision', + ); + + if (isset($bean->is_new)) { + $form['default_revision'] = array( + '#type' => 'value', + '#value' => TRUE, + ); + } + else { + $form['revision']['default_revision'] = array( + '#type' => 'checkbox', + '#title' => t('Set Revision as default'), + '#default_value' => $bean->isDefaultRevision(), + '#states' => array( + // Hide if the option above is disabled, to avoid potential dataloss. + 'invisible' => array( + ':input[name="is_new_revision"]' => array('checked' => FALSE), + ), + ), + ); + } + + $form['revision']['log'] = array( + '#type' => 'textarea', + '#title' => t('Log message'), + '#description' => t('Provide an explanation of the changes you are making. This will help other authors understand your motivations.'), + '#dependency' => array('edit-revision' => array(1)), + '#default_value' => '', + ); + + // The view mode. + if (user_access('edit bean view mode')) { + $bean_info = $bean->entityInfo(); + foreach ($bean_info['view modes'] as $view_mode_name => $data) { + $view_modes[$view_mode_name] = $data['label']; + } + + $form['view_mode'] = array( + '#title' => t('View Mode'), + '#description' => t('Edit the view mode of the Bean'), + '#default_value' => $bean->view_mode, + '#type' => 'select', + '#required' => TRUE, + '#options' => $view_modes, + '#weight' => -8, + ); + } + else { + $form['view_mode'] = array( + '#type' => 'value', + '#value' => $bean->view_mode, + ); + } + + $form['bean'] = array( + '#type' => 'value', + '#value' => $bean, + ); + + // Get the Bean type form. + $form += $bean->getForm($form, $form_state); + + // Add the buttons. + $form['actions'] = array('#type' => 'actions'); + $form['actions']['submit'] = array( + '#type' => 'submit', + '#value' => t('Save'), + '#weight' => 200, + '#submit' => array('bean_form_submit'), + ); + if (!empty($bean->bid) && bean_access('delete', $bean)) { + $form['actions']['delete'] = array( + '#type' => 'submit', + '#value' => t('Delete'), + '#weight' => 201, + '#submit' => array('bean_form_delete_submit'), + ); + } + + $form['#validate'][] = 'bean_form_validate'; + if (!isset($form['#submit']) && function_exists($bean->type . '_bean_form_submit')) { + $form['#submit'][] = $bean->type . '_bean_form_submit'; + } + $form += array('#submit' => array()); + + if(function_exists('entity_language')){ + $langcode = entity_language('bean', $bean); + } + else { + $langcode = NULL; + } + + field_attach_form('bean', $bean, $form, $form_state, $langcode); + return $form; +} + +/** + * Validation for bean form + */ +function bean_form_validate($form, &$form_state) { + $bean = $form_state['values']['bean']; + $bean->label = $form_state['values']['label']; + $bean->title = $form_state['values']['title']; + $bean->view_mode = $form_state['values']['view_mode']; + $bean->is_new_revision = $form_state['values']['is_new_revision']; + // Avoid dataloss. + if (empty($form_state['values']['is_new_revision'])) { + $bean->default_revision = TRUE; + } + else { + $bean->default_revision = $form_state['values']['default_revision']; + } + + if ($bean->is_new_revision) { + $bean->log = $form_state['values']['log']; + } + + if(function_exists('entity_language')){ + $langcode = entity_language('bean', $bean); + } + else { + $langcode = NULL; + } + + field_attach_form_validate('bean', $bean, $form, $form_state, $langcode); + $form_state['values']['bean'] = $bean; + + $bean->validate($form_state['values'], $form_state); +} + +/** + * Submit function for bean form + */ +function bean_form_submit($form, &$form_state) { + $bean = bean_form_submit_build_bean($form, $form_state); + $bean->setValues($form_state['values']); + + // Avoid dataloss. + if (empty($form_state['values']['is_new_revision'])) { + $bean->default_revision = TRUE; + } + + $insert = $bean->internalIdentifier(); + field_attach_submit('bean', $bean, $form, $form_state); + $bean->save(); + + $watchdog_args = array('@type' => $bean->typeName(), '%title' => $bean->label()); + $t_args = array('@type' => $bean->typeName(), '%title' => $bean->label()); + + if (!$insert) { + watchdog('bean', '@type: added %title.', $watchdog_args, WATCHDOG_NOTICE, $bean->viewURL()); + drupal_set_message(t('@type %title has been created.', $t_args)); + } + else { + watchdog('bean', '@type: updated %title.', $watchdog_args, WATCHDOG_NOTICE, $bean->viewURL()); + drupal_set_message(t('@type %title has been updated.', $t_args)); + } + + if ($bean->identifier()) { + $form_state['redirect'] = $bean->viewURL(); + } + else { + // In the unlikely case something went wrong on save, the bean will be + // rebuilt and bean form redisplayed the same way as in preview. + drupal_set_message(t('The block could not be saved.'), 'error'); + $form_state['rebuild'] = TRUE; + } +} + +/** + * Updates the form state's bean entity by processing this submission's values. + * + * This is the default builder function for the bean form. It is called + * during the "Save" and "Preview" submit handlers to retrieve the entity to + * save or preview. This function can also be called by a "Next" button of a + * wizard to update the form state's entity with the current step's values + * before proceeding to the next step. + * + * @return Bean + * + * @see bean_form() + * @see node_form_submit_build_node() + */ +function bean_form_submit_build_bean($form, &$form_state) { + + // @todo Legacy support for modules that extend the bean form with form-level + // submit handlers that adjust $form_state['values'] prior to those values + // being used to update the entity. Module authors are encouraged to instead + // adjust the bean directly within a hook_bean_submit() implementation. For + // Drupal 8, evaluate whether the pattern of triggering form-level submit + // handlers during button-level submit processing is worth supporting + // properly, and if so, add a Form API function for doing so. + unset($form_state['submit_handlers']); + form_execute_handlers('submit', $form, $form_state); + + $bean = $form_state['bean']; + entity_form_submit_build_entity('bean', $bean, $form, $form_state); + + foreach (module_implements('bean_submit') as $module) { + $function = $module . '_bean_submit'; + $function($bean, $form, $form_state); + } + return $bean; +} + +/** + * Button submit function: handle the 'Delete' button on the bean form. + */ +function bean_form_delete_submit($form, &$form_state) { + $destination = array(); + if (isset($_GET['destination'])) { + $destination = drupal_get_destination(); + unset($_GET['destination']); + } + $bean = $form_state['values']['bean']; + $form_state['redirect'] = array($bean->deleteURL(), array('query' => $destination)); +} + +/** + * Menu callback -- ask for confirmation of bean deletion + */ +function bean_delete_confirm($form, &$form_state, $bean) { + $form['#bean'] = $bean; + + return confirm_form($form, + t('Are you sure you want to delete %title?', array('%title' => $bean->label())), + $bean->viewUrl(), + t('This action cannot be undone.'), + t('Delete'), + t('Cancel') + ); +} + +/** + * Execute bean deletion + */ +function bean_delete_confirm_submit($form, &$form_state) { + if ($form_state['values']['confirm']) { + $bean = $form['#bean']; + $bean->delete(); + watchdog('bean', '@type: deleted %title.', array('@type' => $bean->typeName(), '%title' => $bean->label())); + drupal_set_message(t('@type %title has been deleted.', array('@type' => $bean->typeName(), '%title' => $bean->label()))); + } + + $form_state['redirect'] = '<front>'; +} + +/** + * Menu callback -- ask for confirmation of bean deletion + */ +function bean_delete_revision_confirm($form, &$form_state, $bean) { + $form['#bean'] = $bean; + + return confirm_form($form, + t('Are you sure you want to delete revision %vid of %title?', array('%vid' => $bean->vid, '%title' => $bean->label())), + $bean->viewUrl(), + t('This action cannot be undone.'), + t('Delete'), + t('Cancel') + ); +} + +/** + * Delete a bean revisiosn + */ +function bean_delete_revision_confirm_submit($form, &$form_state) { + if ($form_state['values']['confirm']) { + $bean = $form['#bean']; + bean_delete_revision($bean->vid); + watchdog('bean', '@type: deleted %title revision %vid.', array('%vid' => $bean->vid, '@type' => $bean->typeName(), '%title' => $bean->label())); + drupal_set_message(t('@type %title revision %vid has been deleted.', array('%vid' => $bean->vid, '@type' => $bean->typeName(), '%title' => $bean->label()))); + } +} + +/** + * Form for setting a revision active + */ +function bean_set_default_confirm($form, &$form_state, $bean) { + $form['#bean'] = $bean; + + return confirm_form($form, + t('Are you sure you want to set revision %vid of %title active?', array('%vid' => $bean->vid, '%title' => $bean->label())), + $bean->viewUrl(), + t('This action cannot be undone.'), + t('Set Default'), + t('Cancel') + ); +} + +/** + * Submit function + */ +function bean_set_default_confirm_submit($form, &$form_state) { + if ($form_state['values']['confirm']) { + $bean = $form['#bean']; + $bean->setDefault()->save(); + watchdog('bean', '@type: %title revision %vid was set active.', array('%vid' => $bean->vid, '@type' => $bean->typeName(), '%title' => $bean->label())); + drupal_set_message(t('@type %title revision %vid has been set active.', array('%vid' => $bean->vid, '@type' => $bean->typeName(), '%title' => $bean->label()))); + } +} + +function bean_filter_form($form, &$form_state) { + $filters = bean_get_filter(); + + $form['filters'] = array( + '#type' => 'fieldset', + '#title' => t('Filters'), + '#prefix' => '<div class="container-inline">', + '#suffix' => '</div>', + '#tree' => TRUE, + ); + + $type_options = array(); + foreach (bean_get_types() as $type) { + $type_options[$type->type] = $type->getLabel(); + } + asort($type_options); + + $form['filters']['types'] = array( + '#type' => 'select', + '#title' => t('Type'), + '#multiple' => TRUE, + '#options' => $type_options, + '#default_value' => $filters['types'], + ); + + $form['filters']['per_page'] = array( + '#type' => 'select', + '#title' => t('Items Per Page'), + '#multiple' => FALSE, + '#options' => array(20 => '20', 50 => '50', 100 => '100', 200 => '200', 500 => '500'), + '#default_value' => $filters['per_page'], + ); + + $form['filters']['filter'] = array( + '#type' => 'submit', + '#value' => t('Filter'), + '#submit' => array('bean_filter_submit'), + ); + $form['filters']['reset'] = array( + '#type' => 'submit', + '#value' => t('Reset'), + '#submit' => array('bean_reset_filter_submit'), + ); + + return $form; +} + +/** + * Submit function for filter + */ +function bean_filter_submit($form, &$form_state) { + $filters = array( + 'types' => $form_state['values']['filters']['types'], + 'per_page' => $form_state['values']['filters']['per_page'], + ); + + bean_set_filter($filters); + + drupal_goto('admin/content/blocks'); + +} + +function bean_reset_filter_submit($form, &$form_state) { + bean_reset_filter(); + + drupal_goto('admin/content/blocks'); +} + +/** + * Set the filter in the session + */ +function bean_set_filter($filter) { + $_SESSION['bean-filter'] = $filter; +} + +/** + * Get the filter + */ +function bean_get_filter() { + // Pull any saved values from the session. + $filters = isset($_SESSION['bean-filter']) ? $_SESSION['bean-filter'] : array(); + // ...fill in gaps with default values. + return $filters + array('types' => array(), 'per_page' => 50); +} + +/** + * Reset the filter + */ +function bean_reset_filter() { + unset($_SESSION['bean-filter']); +} + +/** + * Revisions page callback + * + * @param $bean Bean + */ +function bean_revisions_page(Bean $bean) { + $bean->loadRevisions(); + + // Build the sortable table header. + $header = array( + 'vid' => array('data' => t('Revision ID')), + 'title' => array('data' => t('Title')), + 'author' => array('data' => t('Author')), + 'changed' => array('data' => t('Date Changed')), + 'operations' => array( + 'data' => t('Operations'), + 'colspan' => 2, + ), + ); + + $rows = array(); + + // Dont' show link for default revision + $can_delete = bean_access('delete', $bean); + $can_edit = bean_access('edit', $bean); + + foreach ($bean->revisions as $rev) { + $active = $rev->vid == $bean->vid ? TRUE : FALSE; + $user = user_load($rev->uid); + $rows[$rev->vid] = array( + 'vid' => $active ? t('@label (Current Revision)', array('@label' => $rev->vid)) : $rev->vid, + 'title' => array( + 'data' => array( + '#type' => 'link', + '#title' => $rev->label, + '#href' => "block/{$rev->delta}/revisions/{$rev->vid}", + ), + ), + 'author' => format_username($user), + 'changed' => format_date($rev->changed), + ); + + $operations = array(); + + if ($can_edit) { + $operations['edit'] = array( + 'title' => t('edit'), + 'href' => "block/{$bean->delta}/revisions/{$rev->vid}/edit", + 'query' => drupal_get_destination(), + ); + } + + if ($can_delete && !$active) { + $operations['delete'] = array( + 'title' => t('delete'), + 'href' => "block/{$bean->delta}/revisions/{$rev->vid}/delete", + 'query' => drupal_get_destination(), + ); + } + + if ($can_edit && !$active) { + $operations['set-active'] = array( + 'title' => t('set active'), + 'href' => "block/{$bean->delta}/revisions/{$rev->vid}/set-active", + 'query' => drupal_get_destination(), + ); + } + + $rows[$rev->vid]['operations'] = array( + 'data' => array( + '#theme' => 'links__bean_operations', + '#links' => $operations, + '#attributes' => array('class' => array('links', 'inline')), + ), + ); + } + + return array( + '#theme' => 'table', + '#header' => $header, + '#rows' => $rows, + '#empty' => t('There are no revisions'), + ); +} diff --git a/sites/all/modules/bean/includes/translation.handler.bean.inc b/sites/all/modules/bean/includes/translation.handler.bean.inc new file mode 100644 index 0000000000000000000000000000000000000000..98a2b27eff6075a965d5c73880a3b814425121af --- /dev/null +++ b/sites/all/modules/bean/includes/translation.handler.bean.inc @@ -0,0 +1,30 @@ +<?php + +/** + * @file + * Bean translation handler for the translation module. + */ + + +/** + * Bean translation handler. + * + * Overrides default behaviours for Bean properties. + */ +class EntityTranslationBeanHandler extends EntityTranslationDefaultHandler { + + public function __construct($entity_type, $entity_info, $entity) { + parent::__construct('bean', $entity_info, $entity); + } + + public function getAccess($op) { + return bean_access($op, $this->entity); + } + + protected function getEntityId() { + if (isset($this->entity->delta)) { + return $this->entity->delta; + } + return parent::getEntityId(); + } +} diff --git a/sites/all/modules/bean/plugins/base.inc b/sites/all/modules/bean/plugins/base.inc new file mode 100644 index 0000000000000000000000000000000000000000..ea1e075d62840c29f128b66a54c7f13732a50186 --- /dev/null +++ b/sites/all/modules/bean/plugins/base.inc @@ -0,0 +1,108 @@ +<?php + +/** + * @file + * Base Plugin Class + */ + +abstract class BeanPlugin implements BeanTypePluginInterface { + protected $plugin_info; + public $type; + + /** + * Get Plugin info + */ + public function getInfo($key = NULL) { + if (!empty($key) && isset($this->plugin_info[$key])) { + return $this->plugin_info[$key]; + } + + return $this->plugin_info; + } + + /** + * Build the URL string + */ + public function buildURL() { + return str_replace('_', '-', $this->type); + } + + /** + * Get the label + */ + public function getLabel() { + return $this->getInfo('label'); + } + + /** + * Get the description + */ + public function getDescription() { + return $this->getInfo('description'); + } + + public function __construct($plugin_info) { + $this->plugin_info = $plugin_info; + $this->type = $plugin_info['name']; + } + + /** + * Define the form values and their defaults + * + * Be sure to call combine the results form the parent::values() with yours + */ + public function values() { + return array( + 'view_mode' => 'default', + ); + } + + public function form($bean, $form, &$form_state) { + return array(); + } + + /** + * Add a Bean to the plugin + */ + public function setBean($bean) { + $this->bean = $bean; + } + + /** + * Is the bean type editable + */ + public function isEditable() { + return $this->getInfo('editable'); + } + + /** + * THe plugin validation function + */ + public function validate($values, &$form_state) {} + + /** + * React to the saving of the bean + */ + public function submit(Bean $bean) { + return $this; + } + + /** + * Return the block content. + * + * @param $bean + * The bean object being viewed. + * @param $content + * The default content array created by Entity API. This will include any + * fields attached to the entity. + * @param $view_mode + * The view mode passed into $entity->view(). + * @return + * Return a renderable content array. + */ + public function view($bean, $content, $view_mode = 'default', $langcode = NULL) { + return $content; + } +} + +class BeanDefault extends BeanPlugin {} diff --git a/sites/all/modules/bean/tests/bean_test.info b/sites/all/modules/bean/tests/bean_test.info new file mode 100644 index 0000000000000000000000000000000000000000..9635289b94f87bf5ee794caa5a60f607d4b8746b --- /dev/null +++ b/sites/all/modules/bean/tests/bean_test.info @@ -0,0 +1,15 @@ +name = Bean Test +description = Creates test plugins for bean +core = 7.x + +dependencies[] = bean +files[] = bean_test.module + +hidden = TRUE + +; Information added by drupal.org packaging script on 2013-02-27 +version = "7.x-1.1" +core = "7.x" +project = "bean" +datestamp = "1361977163" + diff --git a/sites/all/modules/bean/tests/bean_test.module b/sites/all/modules/bean/tests/bean_test.module new file mode 100644 index 0000000000000000000000000000000000000000..76664bfe13ebca45999d31c864ac177656de3dfb --- /dev/null +++ b/sites/all/modules/bean/tests/bean_test.module @@ -0,0 +1,96 @@ +<?php + +/** + * @page + * bean_test.module + */ + +/** + * Implements hook_bean_types_api_info(). + */ +function bean_test_bean_types_api_info() { + return array( + 'api' => 4, + ); +} + +/** + * Implements hook_bean_types(). + */ +function bean_test_bean_types() { + $plugins = array(); + + $plugins['test_bean'] = array( + 'label' => t('Test'), + 'description' => t('This is a test plugin'), + 'handler' => array( + 'class' => 'BeanTestPlugin', + 'parent' => 'bean', + ), + ); + + $plugins['test_bean_2'] = array( + 'label' => t('Test 2'), + 'description' => t('This is a test plugin'), + 'handler' => array( + 'class' => 'BeanTestPlugin', + 'parent' => 'bean', + ), + ); + + + $plugins['test_no_bean'] = array( + 'label' => t('Test No Class'), + 'description' => t('This class does not exist'), + 'handler' => array( + 'class' => 'ClassDoesNotExist', + ), + ); + + $plugins['test_wrong_class'] = array( + 'label' => t('Test Invalid Class'), + 'description' => t('This class does not exist'), + 'handler' => array( + 'class' => 'BeanPluginWrong', + ), + ); + + return $plugins; +} + +class BeanTestPlugin extends BeanPlugin { + public function values() { + return array( + 'test_boolean' => TRUE, + 'test_string' => t('String'), + 'test_array' => array( + 'test_array_1' => 'test_array_1', + ), + ); + } + + public function form($bean, $form, &$form_state) { + $form = array(); + $form['test_boolean'] = array( + '#type' => 'textfield', + '#title' => t('String'), + '#default_value' => $bean->test_string, + ); + + $form['test_boolean'] = array( + '#type' => 'checkbox', + '#title' => t('Boolean'), + '#default_value' => $bean->test_boolean, + ); + + $form['test_array'] = array( + '#type' => 'string', + '#title' => t('Array'), + '#default_value' => $bean->test_array['test_array_1'], + ); + + return $form; + } +} + +class BeanPluginWrong {} \ No newline at end of file diff --git a/sites/all/modules/bean/views/bean.views.inc b/sites/all/modules/bean/views/bean.views.inc new file mode 100644 index 0000000000000000000000000000000000000000..76d8a2b197036f1d46adf4816c67f247f561d235 --- /dev/null +++ b/sites/all/modules/bean/views/bean.views.inc @@ -0,0 +1,33 @@ +<?php + +/** + * Implements hook_views_data_alter(). + */ +function bean_views_data_alter(&$data) { + $data['bean']['type'] = array( + 'title' => t('Type'), + 'help' => t('The block type'), + 'field' => array( + 'handler' => 'views_handler_field_bean_type', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_bean_type', + ), + ); + + $data['bean']['edit_link'] = array( + 'title' => t('Edit link'), + 'help' => t('Edit link for bean block'), + 'field' => array( + 'handler' => 'views_handler_field_bean_edit_link', + ), + ); + + $data['bean']['delete_link'] = array( + 'title' => t('Delete link'), + 'help' => t('Delete link for bean block'), + 'field' => array( + 'handler' => 'views_handler_field_bean_delete_link', + ), + ); +} diff --git a/sites/all/modules/bean/views/views_handler_field_bean_delete_link.inc b/sites/all/modules/bean/views/views_handler_field_bean_delete_link.inc new file mode 100644 index 0000000000000000000000000000000000000000..4f334c72a147d66a2a995c6391ab8ce199964832 --- /dev/null +++ b/sites/all/modules/bean/views/views_handler_field_bean_delete_link.inc @@ -0,0 +1,49 @@ +<?php + +/** + * @file + * Definition of views_handler_field_node_link. + */ + +/** + * Field handler to present a link to the node. + * + * @ingroup views_field_handlers + */ +class views_handler_field_bean_delete_link extends views_handler_field_entity { + + function option_definition() { + $options = parent::option_definition(); + $options['text'] = array('default' => '', 'translatable' => TRUE); + return $options; + } + + function options_form(&$form, &$form_state) { + $form['text'] = array( + '#type' => 'textfield', + '#title' => t('Text to display'), + '#default_value' => $this->options['text'], + ); + parent::options_form($form, $form_state); + + // The path is set by render_link function so don't allow to set it. + $form['alter']['path'] = array('#access' => FALSE); + $form['alter']['external'] = array('#access' => FALSE); + } + + function render($values) { + if ($entity = $this->get_value($values)) { + return $this->render_link($entity); + } + } + + function render_link($bean) { + if (bean_access('delete', $bean)) { + $this->options['alter']['make_link'] = TRUE; + $this->options['alter']['path'] = "block/$bean->delta/delete"; + $this->options['alter']['query'] = drupal_get_destination(); + $text = !empty($this->options['text']) ? $this->options['text'] : t('delete'); + return $text; + } + } +} diff --git a/sites/all/modules/bean/views/views_handler_field_bean_edit_link.inc b/sites/all/modules/bean/views/views_handler_field_bean_edit_link.inc new file mode 100644 index 0000000000000000000000000000000000000000..8519650e889b25fa93b5d0170e2b10666eb77f95 --- /dev/null +++ b/sites/all/modules/bean/views/views_handler_field_bean_edit_link.inc @@ -0,0 +1,49 @@ +<?php + +/** + * @file + * Definition of views_handler_field_node_link. + */ + +/** + * Field handler to present a link to the node. + * + * @ingroup views_field_handlers + */ +class views_handler_field_bean_edit_link extends views_handler_field_entity { + + function option_definition() { + $options = parent::option_definition(); + $options['text'] = array('default' => '', 'translatable' => TRUE); + return $options; + } + + function options_form(&$form, &$form_state) { + $form['text'] = array( + '#type' => 'textfield', + '#title' => t('Text to display'), + '#default_value' => $this->options['text'], + ); + parent::options_form($form, $form_state); + + // The path is set by render_link function so don't allow to set it. + $form['alter']['path'] = array('#access' => FALSE); + $form['alter']['external'] = array('#access' => FALSE); + } + + function render($values) { + if ($entity = $this->get_value($values)) { + return $this->render_link($entity); + } + } + + function render_link($bean) { + if (bean_access('edit', $bean)) { + $this->options['alter']['make_link'] = TRUE; + $this->options['alter']['path'] = "block/$bean->delta/edit"; + $this->options['alter']['query'] = drupal_get_destination(); + $text = !empty($this->options['text']) ? $this->options['text'] : t('edit'); + return $text; + } + } +} diff --git a/sites/all/modules/bean/views/views_handler_field_bean_type.inc b/sites/all/modules/bean/views/views_handler_field_bean_type.inc new file mode 100644 index 0000000000000000000000000000000000000000..6afd06ff9d26fef82ca08cb5149547ce902b55d2 --- /dev/null +++ b/sites/all/modules/bean/views/views_handler_field_bean_type.inc @@ -0,0 +1,23 @@ +<?php + +/** + * @file + * Field handler to present a type of bean. + * + * @ingroup views_field_handlers + */ +class views_handler_field_bean_type extends views_handler_field { + function construct() { + parent::construct(); + } + + function render($values) { + if (!empty($values->bean_type)) { + $types = bean_get_types(); + if (!empty($types[$values->bean_type])) { + return $types[$values->bean_type]->getLabel(); + } + } + return ''; + } +} diff --git a/sites/all/modules/bean/views/views_handler_filter_bean_type.inc b/sites/all/modules/bean/views/views_handler_filter_bean_type.inc new file mode 100644 index 0000000000000000000000000000000000000000..06bd766d0558709434eddd030ecc859ceed98e49 --- /dev/null +++ b/sites/all/modules/bean/views/views_handler_filter_bean_type.inc @@ -0,0 +1,19 @@ +<?php +/** + * Filter by bean type + * + * @ingroup views_filter_handlers + */ +class views_handler_filter_bean_type extends views_handler_filter_in_operator { + function get_value_options() { + if (!isset($this->value_options)) { + $this->value_title = t('Block types'); + $bean_info = entity_get_info('bean'); + foreach ($bean_info['bundles'] as $type => $info) { + $options[$type] = t($info['label']); + } + asort($options); + $this->value_options = $options; + } + } +}