From d565efd4c9636e41285d4e8a57dbb76e4dd65894 Mon Sep 17 00:00:00 2001 From: Andy Stiller Date: Tue, 20 Jan 2015 14:28:58 +0000 Subject: [PATCH] #52 Change to make the owner of the message the recipient and to add the Entity Reference Prepopulate module. --- .../entityreference_prepopulate/LICENSE.txt | 339 ++++++++++++ .../entityreference_prepopulate/README.txt | 42 ++ .../entityreference_prepopulate.api.php | 46 ++ .../entityreference_prepopulate.info | 14 + .../entityreference_prepopulate.module | 501 ++++++++++++++++++ .../entityreference_prepopulate.test | 362 +++++++++++++ ...rencePrepopulateInstanceBehavior.class.php | 171 ++++++ .../plugins/behavior/prepopulate.inc | 8 + .../content_types/node_prepopulate.inc | 100 ++++ .../entityreference_prepopulate_test.info | 13 + .../entityreference_prepopulate_test.module | 18 + .../custom/kendra_msg/kendra_msg.module | 11 +- 12 files changed, 1619 insertions(+), 6 deletions(-) create mode 100644 sites/all/modules/contrib/entityreference_prepopulate/LICENSE.txt create mode 100644 sites/all/modules/contrib/entityreference_prepopulate/README.txt create mode 100644 sites/all/modules/contrib/entityreference_prepopulate/entityreference_prepopulate.api.php create mode 100644 sites/all/modules/contrib/entityreference_prepopulate/entityreference_prepopulate.info create mode 100644 sites/all/modules/contrib/entityreference_prepopulate/entityreference_prepopulate.module create mode 100644 sites/all/modules/contrib/entityreference_prepopulate/entityreference_prepopulate.test create mode 100644 sites/all/modules/contrib/entityreference_prepopulate/plugins/behavior/EntityReferencePrepopulateInstanceBehavior.class.php create mode 100644 sites/all/modules/contrib/entityreference_prepopulate/plugins/behavior/prepopulate.inc create mode 100644 sites/all/modules/contrib/entityreference_prepopulate/plugins/content_types/node_prepopulate.inc create mode 100644 sites/all/modules/contrib/entityreference_prepopulate/tests/entityreference_prepopulate_test.info create mode 100644 sites/all/modules/contrib/entityreference_prepopulate/tests/entityreference_prepopulate_test.module diff --git a/sites/all/modules/contrib/entityreference_prepopulate/LICENSE.txt b/sites/all/modules/contrib/entityreference_prepopulate/LICENSE.txt new file mode 100644 index 00000000..d159169d --- /dev/null +++ b/sites/all/modules/contrib/entityreference_prepopulate/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. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/sites/all/modules/contrib/entityreference_prepopulate/README.txt b/sites/all/modules/contrib/entityreference_prepopulate/README.txt new file mode 100644 index 00000000..03c2f0b4 --- /dev/null +++ b/sites/all/modules/contrib/entityreference_prepopulate/README.txt @@ -0,0 +1,42 @@ +Description +=========== +Allows the contents of an "Entity Reference" field to be pre-populated by +taking a parameter from the URL path. + +Install +======= +1. Download and enable the module. +2. Visit admin/structure/types/manage/[ENTITY-TYPE]/fields/[FIELD-NAME] +3. Enable "Entity reference prepopulate" under the instance settings. + + +Configuration +============= +Enable Entity reference prepopulate: + Check this to enable Entity reference prepopulate on this field. +Action + Using the select box choose the action to take if the entity reference + field is pre-populated. +Fallback behaviour + Select what to do if the URL path does NOT contain a parameter to + pre-populate the field. +Skip access permission + This is a fallback override, the fallback behaviour will not be followed + for users with the specified permission. + +Usage +===== +In order to pre-populate an entity reference field you have to supply the +parameter in the URL. + +The structure is +node/add/article?[field_ref]=[id] + +Where [field_ref] is the name of the entity reference field and [id] is +the id of the entity being referenced. + +Examples: +node/add/article?field_foo=1 +node/add/page?field_bar=1,2,3 + + diff --git a/sites/all/modules/contrib/entityreference_prepopulate/entityreference_prepopulate.api.php b/sites/all/modules/contrib/entityreference_prepopulate/entityreference_prepopulate.api.php new file mode 100644 index 00000000..6d6f984a --- /dev/null +++ b/sites/all/modules/contrib/entityreference_prepopulate/entityreference_prepopulate.api.php @@ -0,0 +1,46 @@ + array( + 'title' => t('URL'), + 'description' => t('Prepopulate from URL'), + 'callback' => 'entityreference_prepopulate_get_values_from_url', + ), + ); +} + +/** + * Alter providers list. + * + * @param $providers + * Array keyed by the provider name, and and array of values. + */ +function entityreference_prepopulate_providers_info_alter(&$providers) { + $providers['url']['disabled'] = TRUE; +} + +/** + * @} End of "addtogroup hooks". + */ diff --git a/sites/all/modules/contrib/entityreference_prepopulate/entityreference_prepopulate.info b/sites/all/modules/contrib/entityreference_prepopulate/entityreference_prepopulate.info new file mode 100644 index 00000000..b0b820ab --- /dev/null +++ b/sites/all/modules/contrib/entityreference_prepopulate/entityreference_prepopulate.info @@ -0,0 +1,14 @@ +name = Entity reference prepopulate +description = Prepopulate entity reference values from URL. +core = 7.x +package = Fields +dependencies[] = entityreference + +files[] = entityreference_prepopulate.test + +; Information added by Drupal.org packaging script on 2014-02-19 +version = "7.x-1.5" +core = "7.x" +project = "entityreference_prepopulate" +datestamp = "1392845305" + diff --git a/sites/all/modules/contrib/entityreference_prepopulate/entityreference_prepopulate.module b/sites/all/modules/contrib/entityreference_prepopulate/entityreference_prepopulate.module new file mode 100644 index 00000000..f6ef78cd --- /dev/null +++ b/sites/all/modules/contrib/entityreference_prepopulate/entityreference_prepopulate.module @@ -0,0 +1,501 @@ + array( + 'render element' => 'form', + ), + ); +} + +/** + * Implements hook_field_create_instance(). + * + * Add "default value function" setting to the field instance. + * We have to do it from this hook, as we don't have another chance of setting + * this option via the hook_field_info(). + */ +function entityreference_prepopulate_field_create_instance($instance) { + if (empty($instance['settings']['behaviors']['prepopulate']['status'])) { + return; + } + + $instance['default_value_function'] = 'entityreference_prepopulate_field_default_value'; + field_update_instance($instance); +} + +/** + * Implements hook_field_update_instance(). + */ +function entityreference_prepopulate_field_update_instance($instance, $prior_instance) { + if (empty($instance['settings']['behaviors']['prepopulate'])) { + return; + } + if (isset($prior_instance['settings']['behaviors']['prepopulate']['status']) && $instance['settings']['behaviors']['prepopulate']['status'] == $prior_instance['settings']['behaviors']['prepopulate']['status']) { + // Nothing changed. + return; + } + + $instance['default_value_function'] = !empty($instance['settings']['behaviors']['prepopulate']['status']) ? 'entityreference_prepopulate_field_default_value' : ''; + field_update_instance($instance); +} + + +/** + * Implements hook_field_attach_form(). + */ +function entityreference_prepopulate_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) { + list($id,,$bundle) = entity_extract_ids($entity_type, $entity); + + if (!empty($form_state['triggering_element']['#ajax'])) { + // We are inside AJAX, so values can't be taken from URL at the + // moment. + return; + } + + // Check if there is a field that needs to be prepopulated attached to the + // given entity. + $found = FALSE; + foreach (field_info_instances($entity_type, $bundle) as $instance) { + if (!empty($instance['settings']['behaviors']['prepopulate']['status'])) { + $found = TRUE; + break; + } + } + + if (!$found) { + return; + } + + foreach (element_children($form_state['field']) as $field_name) { + foreach ($form_state['field'][$field_name] as $lang => $value) { + $instance = $value['instance']; + if (empty($instance['settings']['behaviors']['prepopulate']['status'])) { + continue; + } + $settings = $instance['settings']['behaviors']['prepopulate']; + + if ((!empty($settings['skip_perm']) && user_access($settings['skip_perm'])) || ($id && empty($settings['action_on_edit']))) { + // User has access to skip the action, or the entity is already + // saved, but "Apply action on edit", is disabled. + continue; + } + + $field = $value['field']; + + // Store prepopulated values in the form state to make them persistent, + // in case the form is rebuilt by AJAX requests. + $field_name = $field['field_name']; + + if ($ids = entityreference_prepopulate_get_values($field, $instance)) { + $form_state['entityreference_prepopulate'][$instance['entity_type']][$instance['bundle']][$field_name] = $ids; + } + + if ($ids || ($id && !empty($settings['action_on_edit']))) { + // New entity with prepopulate values, or an existing entity, + // we might need to disable/ hide the group-audience field. + if ($settings['action'] == 'disable') { + $form[$field_name][$lang]['#disabled'] = TRUE; + } + elseif ($settings['action'] == 'hide' && !$id) { + // For new entities we don't hide the field via hook_field_access(), + // as the default value won't be set. We use hook_field_access() only + // on existing ones. + $form[$field_name]['#access'] = FALSE; + } + } + elseif (in_array($settings['fallback'], array('form_error', 'redirect', 'hide'))) { + $message = t('Field @label must be populated via URL.', array('@label' => $instance['label'])); + if ($settings['fallback'] == 'form_error') { + form_error($form, $message); + } + elseif ($settings['fallback'] == 'redirect') { + drupal_set_message($message, 'notice'); + drupal_goto(); + } + elseif ($settings['fallback'] == 'hide') { + $form[$field_name]['#access'] = FALSE; + } + } + } + } +} + +/** + * Implements hook_field_access(). + */ +function entityreference_prepopulate_field_access($op, $field, $entity_type, $entity, $account) { + if ($op != 'edit' || $field['type'] != 'entityreference') { + return; + } + + if (empty($entity)) { + // $entity might be NULL, so return early. + // @see field_access(). + return; + } + + list($id,,$bundle) = entity_extract_ids($entity_type, $entity); + $instance = field_info_instance($entity_type, $field['field_name'], $bundle); + if (empty($instance['settings']['behaviors']['prepopulate']['status'])) { + return; + } + + $settings = $instance['settings']['behaviors']['prepopulate']; + + if (!empty($settings['skip_perm']) && user_access($settings['skip_perm'])) { + return; + } + + if ($id && empty($entity->is_new)) { + // The field need to be hidden when editing the entity. + return $settings['action'] == 'hide' && !empty($settings['action_on_edit']) ? FALSE : NULL; + } + + if ($settings['action'] == 'hide') { + // If entity is already saved and not just inserted, deny access, otherwise + // ignore. + return $id && empty($entity->is_new) ? FALSE : NULL; + } + + $ids = entityreference_prepopulate_get_values($field, $instance); + + if (!$ids && $settings['fallback'] == 'hide') { + return FALSE; + } +} + +/** + * Field default value callback. + * + * Set the default from the URL context. This works even if the widget is + * not shown, e.g. due to restricted field access. + * + * @todo Check field cardinality. + */ +function entityreference_prepopulate_field_default_value($entity_type, $entity, $field, $instance, $langcode) { + $items = array(); + if ($ids = entityreference_prepopulate_get_values($field, $instance)) { + $items = array(); + foreach ($ids as $id) { + $items[] = array('target_id' => $id); + } + } + return $items; +} + +/** + * Wrapper function to get context (e.g. from URL or OG-context). + * + * @param $entity_type + * The entity type the entity. + * @param $entity + * The entity object that is being checked. + * @param $field + * The field info array. + * @param $instance + * The instance info array. + * @param $validate + * Determine if access validation should be performed. Defaults to TRUE. + * + * @return + * Array of IDs a user may view. + */ +function entityreference_prepopulate_get_values($field, $instance, $validate = TRUE) { + if (!$instance['settings']['behaviors']['prepopulate']['status']) { + // Do nothing when prepopulate is disabled for this field. + return; + } + + $field_name = $field['field_name']; + + $cache = &drupal_static(__FUNCTION__, array()); + $identifier = array( + $instance['entity_type'], + $instance['bundle'], + $field_name, + $validate, + ); + + if (module_exists('og') && og_is_group_audience_field($field_name)) { + if (empty($instance['field_mode'])) { + // Group audience field, but no field-mode provided. + // So we iterate over the "default" and possibly "admin" field-modes, + // and return those values together. + $ids = array(); + $field_modes = !user_access('administer group') ? array('default') : array('default', 'admin'); + foreach ($field_modes as $field_mode) { + $instance['field_mode'] = $field_mode; + if ($og_ids = entityreference_prepopulate_get_values($field, $instance)) { + $ids = array_merge($ids, $og_ids); + } + } + + // Return the values. + return $ids; + } + + $identifier[] = $instance['field_mode']; + } + + $identifier = implode(':', $identifier); + + if (isset($cache[$identifier])) { + return $cache[$identifier]; + } + + $cache[$identifier] = $ids = array(); + + // Check if we have cached values. + if (!$ids) { + $ids = entityreference_prepopulate_get_values_from_cache($field, $instance); + } + + // Get the providers. + $enabled_providers = !empty($instance['settings']['behaviors']['prepopulate']['providers']) ? array_filter($instance['settings']['behaviors']['prepopulate']['providers']) : array(); + + if (!$enabled_providers) { + // If the instance isn't updated yet, we assume the URL provider is enabled. + $enabled_providers += array('url' => TRUE); + } + + // For backwards compatibility with version 1.4, we check the "og_context" + // property. + if (!empty($instance['settings']['behaviors']['prepopulate']['og_context'])) { + $enabled_providers += array('og_context' => TRUE); + } + + $providers = entityreference_prepopulate_providers_info(); + foreach (array_keys($enabled_providers) as $name) { + if (empty($providers[$name]) || !empty($providers[$name]['disabled'])) { + // Provider doesn't exist any more or is disabled. + continue; + } + $provider = $providers[$name]; + $function = $provider['callback']; + if ($ids = $function($field, $instance)) { + // We found values, so we can break. + break; + } + } + + if (!$ids || !$validate) { + // No IDs found, or no validation is needed. + $cache[$identifier] = $ids; + return $ids; + } + + $handler = entityreference_get_selection_handler($field, $instance); + if (!$ids = $handler->validateReferencableEntities($ids)) { + $cache[$identifier] = FALSE; + return; + } + + // Check access to the provided entities. + $target_type = $field['settings']['target_type']; + entity_load($target_type, $ids); + foreach ($ids as $delta => $id) { + $entity = entity_load_single($target_type, $id); + if (!$entity || !entity_access('view', $target_type, $entity)) { + unset($ids[$delta]); + } + } + + $cache[$identifier] = $ids; + return $ids; +} + +/** + * Get the values from the cached form. + * + * @param $field + * The field info array. + * @param $instance + * The instance info array. + * + * @see + * entityreference_prepopulate_get_values() + */ +function entityreference_prepopulate_get_values_from_cache($field, $instance) { + // Try to get the form out of cache. + if (!$form_build_id = isset($_GET['form_build_id']) ? $_GET['form_build_id'] : isset($_POST['form_build_id']) ? $_POST['form_build_id'] : NULL) { + return; + } + + $field_name = $field['field_name']; + + $form_state = array(); + form_get_cache($form_build_id, $form_state); + + // If successful, get the value from the form_state. + return isset($form_state['entityreference_prepopulate'][$instance['entity_type']][$instance['bundle']][$field_name]) ? $form_state['entityreference_prepopulate'][$instance['entity_type']][$instance['bundle']][$field_name] : FALSE; +} + +/** + * Get values for prepopulating fields via URL. + * + * @param $field + * The field info array. + * @param $instance + * The instance info array. + * + * @see + * entityreference_prepopulate_get_values() + */ +function entityreference_prepopulate_get_values_from_url($field, $instance) { + $field_name = $field['field_name']; + if (!empty($_GET[$field_name]) && is_string($_GET[$field_name])) { + return explode(',', $_GET[$field_name]); + } +} + + +/** + * Get values for prepopulating fields OG-context. + * + * @param $field + * The field info array. + * @param $instance + * The instance info array. + * + * @see + * entityreference_prepopulate_get_values() + */ +function entityreference_prepopulate_get_values_from_og_context($field, $instance) { + $field_name = $field['field_name']; + + if (!module_exists('og_context') || !$og_context = og_context()) { + return; + } + + if ($og_context['group_type'] != $field['settings']['target_type']) { + // Context is of invalid group-type. + return; + } + + return array($og_context['gid']); +} + + +/** + * Return a form element with crafted links to create nodes for a group. + * + * @param $entity_type + * The entity type of the referenced entity. + * @param $entity_id + * The entity ID of the referenced entity. + * @param $destination + * Optional; The destination after a node is created. Defaults to the + * destination passed in the URL if exists, otherwise back to the current + * page. + * @param $types + * Optional; An array of type names. Restrict the created links to the given + * types. + */ +function entityreference_prepopulate_create_node_links($entity_type, $entity_id, $field_name, $destination = NULL, $types = NULL) { + $wrapper = entity_metadata_wrapper($entity_type, $entity_id); + $field = field_info_field($field_name); + + $entity = entity_load_single($entity_type, $entity_id); + list(,, $bundle) = entity_extract_ids($entity_type, $entity); + + $types = isset($types) ? $types : array_keys(node_type_get_types()); + $names = array(); + foreach ($types as $type_name) { + if ($field['settings']['target_type'] != $entity_type) { + // The entity type isn't referenced by the field. + continue; + } + + if (!empty($field['settings']['handler_settings']['target_bundles']) && !in_array($bundle, $field['settings']['handler_settings']['target_bundles'])) { + // The entity bundle isn't referenced by the field. + continue; + } + + $instance = field_info_instance('node', $field_name, $type_name); + if (empty($instance['settings']['behaviors']['prepopulate']['status'])) { + // The field doesn't exist on the node type, or doesn't have prepopulate + // enabled. + continue; + } + + if (!node_access('create', $type_name)) { + continue; + } + + $names[$type_name] = node_type_get_name($type_name); + } + + if (empty($names)) { + return; + } + + // Sort names. + asort($names); + + // Build links. + $options = array( + 'query' => array($field_name => $entity_id) + drupal_get_destination(), + ); + + $items = array(); + foreach ($names as $type => $name) { + $items[] = array('data' => l($name, 'node/add/' . str_replace('_', '-', $type), $options)); + } + + $element = array(); + $element['entityreference_prepopulate'] = array( + '#theme' => 'item_list', + '#items' => $items, + ); + + return $element; +} + +/** + * Return array of providers. + */ +function entityreference_prepopulate_providers_info() { + $description = t('Determine if values that should be prepopulated should "listen" to the OG-context.'); + if ($disabled = !module_exists('og_context')) { + $description .= '
' . t('Organic groups integration: Enable OG-context module.'); + } + + $providers = array( + 'url' => array( + 'title' => t('URL'), + 'description' => t('Prepopulate from URL'), + 'callback' => 'entityreference_prepopulate_get_values_from_url', + ), + 'og_context' => array( + 'title' => t('OG Context'), + 'description' => $description, + 'disabled' => $disabled, + 'callback' => 'entityreference_prepopulate_get_values_from_og_context', + ), + ); + + $providers = array_merge($providers, module_invoke_all('entityreference_prepopulate_providers_info')); + + // Allow other module to change the providers list. + drupal_alter('entityreference_prepopulate_providers_info', $providers); + + return $providers; +} diff --git a/sites/all/modules/contrib/entityreference_prepopulate/entityreference_prepopulate.test b/sites/all/modules/contrib/entityreference_prepopulate/entityreference_prepopulate.test new file mode 100644 index 00000000..20a7822e --- /dev/null +++ b/sites/all/modules/contrib/entityreference_prepopulate/entityreference_prepopulate.test @@ -0,0 +1,362 @@ + 'OG-context integration', + 'description' => 'Test the OG-context integration, which allows prepopulating by the group context.', + 'group' => 'Entity reference prepopulate', + 'dependencies' => array('og'), + ); + } + + function setUp() { + parent::setUp('og_context', 'entityreference_prepopulate_test'); + + $this->user1 = $this->drupalCreateUser(); + $this->user2 = $this->drupalCreateUser(array('bypass node access', 'administer group')); + + $type = $this->drupalCreateContentType(); + $this->group_type = $type->type; + og_create_field(OG_GROUP_FIELD, 'node', $this->group_type); + + $type = $this->drupalCreateContentType(); + $this->group_content_type = $type->type; + + $og_field = og_fields_info(OG_AUDIENCE_FIELD); + // Enable the prepopulate behavior. + $og_field['instance']['settings']['behaviors']['prepopulate'] = array( + 'status' => TRUE, + 'action' => 'none', + 'fallback' => 'none', + 'skip_perm' => FALSE, + 'providers' => array( + 'url' => TRUE, + 'og_context' => TRUE, + ), + ); + og_create_field(OG_AUDIENCE_FIELD, 'node', $this->group_content_type, $og_field); + } + + /** + * Test the OG-context integration. + */ + function testPrepopulate() { + $settings = array( + 'type' => $this->group_type, + 'uid' => $this->user1->uid, + ); + $settings[OG_GROUP_FIELD][LANGUAGE_NONE][0]['value'] = 1; + $group1 = $this->drupalCreateNode($settings); + + og_group('node', $group1, array('entity_type' => 'user', 'entity' => $this->user2)); + + $this->drupalLogin($this->user2); + $this->drupalGet('node/add/' . str_replace('_', '-', $this->group_content_type)); + $this->assertNoOptionSelected('edit-og-group-ref-und-0-default', 1, 'Group-audience fields is not selected.'); + + // Set the OG-context(); + // See entityreference_prepopulate_test_init(). + $options = array( + 'query' => array( + 'gid' => $group1->nid, + ), + ); + + $this->drupalGet('node/add/' . str_replace('_', '-', $this->group_content_type), $options); + $this->assertOptionSelected('edit-og-group-ref-und-0-default', 1, 'Group-audience fields is selected.'); + } +} + + +class EntityReferenceReferenceRemain extends DrupalWebTestCase { + public $user; + public $node1; + public $node2; + + public static function getInfo() { + return array( + 'name' => 'Prepopulate settings', + 'description' => 'Verify the reference between entity is remaining when saving the node.', + 'group' => 'Entity reference prepopulate', + ); + } + + public function setUp() { + parent::setUp(array('entityreference', 'entityreference_prepopulate')); + + $content_type = $this->drupalCreateContentType(); + $field = array( + 'field_name' => 'node_ref', + 'type' => 'entityreference', + 'cardinality' => 1, + ); + field_create_field($field); + + $instance = array( + 'field_name' => 'node_ref', + 'entity_type' => 'node', + 'label' => 'Node ref', + 'bundle' => $content_type->type, + 'settings' => array( + 'behaviors' => array( + 'prepopulate' => array( + 'status' => TRUE, + 'action' => 'none', + 'fallback' => 'none', + ) + ), + ), + ); + field_create_instance($instance); + + $this->user = $this->drupalCreateUser(array('bypass node access')); + + // Creating two nodes - referencing node and referenced node. + $this->node1 = $this->drupalCreateNode(array( + 'title' => 'Referencing node', + 'type' => $content_type->type, + )); + + $this->node2 = $this->drupalCreateNode(array( + 'title' => 'Referenced node', + 'type' => $content_type->type, + )); + + // Reference the first node to the second node. + $wrapper = entity_metadata_wrapper('node', $this->node1->nid); + $wrapper->node_ref->set($this->node2->nid); + $wrapper->save(); + } + + /** + * Set various settings of the entity reference prepopulate settings. + */ + function testScenarioReference() { + $this->drupalLogin($this->user); + + // Verify the basic prepopulate option. + $options = array('query' => array('node_ref' => $this->node2->nid)); + $edit = array('title' => 'Referencing node'); + + $this->drupalPost('node/add/' . $this->node1->type, $edit, t('Save'), $options); + $this->assertText('Referenced node', 'The reference has been created'); + + // Disable the field. + $this->changeInstanceSettings(array('action' => 'disable')); + + $this->drupalGet('node/add/' . $this->node1->type, $options); + + $xpath = $this->xpath('//input[@id="edit-node-ref-und-0-target-id" and @disabled="disabled" and @value="Referenced node (' . $this->node2->nid . ')"]'); + $this->assertTrue(!empty($xpath), 'The field is disabled and default value is set to the node 2.'); + + $this->drupalPost('node/add/' . $this->node1->type, $edit, t('Save'), $options); + $this->assertText('Referenced node', 'The reference has been created'); + + // Hide the field. + $this->changeInstanceSettings(array('action' => 'hide')); + + $xpath = $this->xpath('//input[@id="edit-node-ref-und-0-target-id"]'); + $this->assertTrue(empty($xpath), 'The field is not visible to the user.'); + + $this->drupalPost('node/add/' . $this->node1->type, $edit, t('Save'), $options); + $this->assertText('Referenced node', 'The reference has been created'); + + // Set an error when the prepopulated value is missing. + $this->changeInstanceSettings(array('fallback' => 'form_error')); + + $this->drupalGet('node/add/' . $this->node1->type); + $this->assertText('Field Node ref must be populated via URL.', 'The error of the missing prepopulated value has been set.'); + + // Redirect when there is the prepopulated field is missing. + $this->changeInstanceSettings(array('fallback' => 'redirect')); + + $this->drupalGet('node/add/' . $this->node1->type); + $this->assertTrue($this->getUrl() == url('', array('absolute' => TRUE)), 'The redirect of due to non prepoulated value.'); + + // Verify the basic edit. + $this->changeInstanceSettings(array( + 'action' => 'hide', + 'action_on_edit' => FALSE, + )); + $this->drupalGet('node/' . $this->node1->nid . '/edit'); + + $xpath = $this->xpath('//input[@id="edit-node-ref-und-0-target-id"]'); + $this->assertTrue(!empty($xpath), "The node reference is visible to the user."); + + $this->drupalPost('node/' . $this->node1->nid . '/edit', array('title' => 'Referencing node'), t('Save')); + $this->verifyReferenceRemain(); + + // Hide the field when editing. + $this->changeInstanceSettings(array( + 'action' => 'hide', + 'action_on_edit' => TRUE, + )); + + $this->drupalGet('node/' . $this->node1->nid . '/edit'); + $xpath = $this->xpath('//input[@id="edit-node-ref-und-0-target-id"]'); + $this->assertTrue(empty($xpath), "The node reference is invisible to the user."); + + $this->drupalPost('node/' . $this->node1->nid . '/edit', array('title' => 'Referencing node'), t('Save'), $options); + $this->verifyReferenceRemain(); + + // Disable the field. + $this->changeInstanceSettings(array('action' => 'disable')); + + $this->drupalGet('node/' . $this->node1->nid . '/edit'); + $xpath = $this->xpath('//input[@id="edit-node-ref-und-0-target-id" and @disabled="disabled" and @value="Referenced node (' . $this->node2->nid . ')"]'); + $this->assertTrue(!empty($xpath), 'The field is disabled and default value is set to the node 2.'); + + $this->drupalPost('node/' . $this->node1->nid . '/edit', array('title' => 'Referencing node'), t('Save')); + $this->verifyReferenceRemain(); + } + + /** + * Change the settings of the instance. + */ + private function changeInstanceSettings($settings) { + $instance = field_info_instance('node', 'node_ref', $this->node1->type); + $old_settings = $instance['settings']['behaviors']['prepopulate']; + $instance['settings']['behaviors']['prepopulate'] = $settings + $old_settings; + field_update_instance($instance); + } + + /** + * Verify the node reference remained. + */ + private function verifyReferenceRemain() { + // Loading a fresh node object from the DB. + $node = node_load($this->node1->nid, NULL, TRUE); + $wrapper = entity_metadata_wrapper('node', $node); + $this->assertTrue($wrapper->node_ref->getIdentifier() == $this->node2->nid, 'The reference from node 1 to node 2 remained.'); + } +} + + +class EntityReferenceProvidersTestCase extends DrupalWebTestCase { + + public static function getInfo() { + return array( + 'name' => 'Providers', + 'description' => 'Test the providers functionality.', + 'group' => 'Entity reference prepopulate', + 'dependencies' => array('og'), + ); + } + + function setUp() { + parent::setUp('og_context', 'entityreference_prepopulate_test'); + + $this->user1 = $this->drupalCreateUser(array('bypass node access', 'administer group')); + $this->drupalLogin($this->user1); + + $type = $this->drupalCreateContentType(); + $this->group_type = $type->type; + og_create_field(OG_GROUP_FIELD, 'node', $this->group_type); + + $type = $this->drupalCreateContentType(); + $this->group_content_type = $type->type; + + $og_field = og_fields_info(OG_AUDIENCE_FIELD); + // Enable the prepopulate behavior. + $og_field['instance']['settings']['behaviors']['prepopulate'] = array( + 'status' => TRUE, + 'action' => 'none', + 'fallback' => 'none', + 'skip_perm' => FALSE, + ); + og_create_field(OG_AUDIENCE_FIELD, 'node', $this->group_content_type, $og_field); + + $settings = array( + 'type' => $this->group_type, + 'uid' => $this->user1->uid, + 'title' => $this->randomName(), + ); + $settings[OG_GROUP_FIELD][LANGUAGE_NONE][0]['value'] = 1; + $this->group1 = $this->drupalCreateNode($settings); + + $settings['title'] = $this->randomName(); + $this->group2 = $this->drupalCreateNode($settings); + } + + /** + * Test the providers functionality. + */ + function testProvidres() { + $nid1 = $this->group1->nid; + $nid2 = $this->group2->nid; + + $path = 'node/add/' . str_replace('_', '-', $this->group_content_type); + $options = array( + 'query' => array( + OG_AUDIENCE_FIELD => $nid1, + // Set the OG context. See entityreference_prepopulate_init(). + 'gid' => $nid2, + ) + ); + + $instance = field_info_instance('node', OG_AUDIENCE_FIELD, $this->group_content_type); + + $scenarios = array( + array( + 'message' => 'No providers set - defaults to URL.', + 'providers' => array(), + 'result' => $nid1, + ), + array( + 'message' => 'URL provider only.', + 'providers' => array( + 'url' => TRUE, + ), + 'result' => $nid1, + ), + array( + 'message' => 'OG Context provider only.', + 'providers' => array( + 'og_context' => TRUE, + ), + 'result' => $nid2, + ), + array( + 'message' => 'URL provider, and then OG Context provider.', + 'providers' => array( + 'url' => TRUE, + 'og_context' => TRUE, + ), + 'result' => $nid1, + ), + array( + 'message' => 'OG Context provider, and then URL provider.', + 'providers' => array( + 'og_context' => TRUE, + 'url' => TRUE, + ), + 'result' => $nid2, + ), + array( + 'message' => 'Invalid provider.', + 'providers' => array( + 'invalid' => TRUE, + ), + 'result' => FALSE, + ), + ); + + foreach ($scenarios as $scenario) { + $instance['settings']['behaviors']['prepopulate']['providers'] = $scenario['providers']; + field_update_instance($instance); + + $this->drupalGet($path, $options); + + if ($scenario['result']) { + $this->assertOptionSelected('edit-og-group-ref-und-0-default', $scenario['result'], $scenario['message']); + } + else { + $this->assertNoOptionSelected('edit-og-group-ref-und-0-default', $nid1, $scenario['message']); + $this->assertNoOptionSelected('edit-og-group-ref-und-0-default', $nid2, $scenario['message']); + } + + } + } +} diff --git a/sites/all/modules/contrib/entityreference_prepopulate/plugins/behavior/EntityReferencePrepopulateInstanceBehavior.class.php b/sites/all/modules/contrib/entityreference_prepopulate/plugins/behavior/EntityReferencePrepopulateInstanceBehavior.class.php new file mode 100644 index 00000000..088db39a --- /dev/null +++ b/sites/all/modules/contrib/entityreference_prepopulate/plugins/behavior/EntityReferencePrepopulateInstanceBehavior.class.php @@ -0,0 +1,171 @@ + 'select', + '#title' => t('Action'), + '#options' => array( + 'none' => t('Do nothing'), + 'hide' => t('Hide field'), + 'disable' => t('Disable field'), + ), + '#description' => t('Action to take when prepopulating field with values via URL.'), + ); + $form['action_on_edit'] = array( + '#type' => 'checkbox', + '#title' => t('Apply action on edit'), + '#description' => t('Apply action when editing an existing entity.'), + '#states' => array( + 'invisible' => array( + ':input[name="instance[settings][behaviors][prepopulate][action]"]' => array('value' => 'none'), + ), + ), + ); + $form['fallback'] = array( + '#type' => 'select', + '#title' => t('Fallback behaviour'), + '#description' => t('Determine what should happen if no values are provided via URL.'), + '#options' => array( + 'none' => t('Do nothing'), + 'hide' => t('Hide field'), + 'form_error' => t('Set form error'), + 'redirect' => t('Redirect'), + ), + ); + + // Get list of permissions. + $perms = array(); + $perms[0] = t('- None -'); + foreach (module_list(FALSE, FALSE, TRUE) as $module) { + // By keeping them keyed by module we can use optgroups with the + // 'select' type. + if ($permissions = module_invoke($module, 'permission')) { + foreach ($permissions as $id => $permission) { + $perms[$module][$id] = strip_tags($permission['title']); + } + } + } + + $form['skip_perm'] = array( + '#type' => 'select', + '#title' => t('Skip access permission'), + '#description' => t('Set a permission that will not be affected by the fallback behavior.'), + '#options' => $perms, + ); + + $form['providers'] = array( + '#type' => 'container', + '#theme' => 'entityreference_prepopulate_providers_table', + '#element_validate' => array('entityreference_prepopulate_providers_validate'), + ); + + $providers = entityreference_prepopulate_providers_info(); + + // Sort providers by weight. + $providers_names = !empty($instance['settings']['behaviors']['prepopulate']['providers']) ? array_keys($instance['settings']['behaviors']['prepopulate']['providers']) : array(); + $providers_names = drupal_array_merge_deep($providers_names, array_keys($providers)); + + $weight = 0; + foreach ($providers_names as $name) { + $provider = $providers[$name]; + + // Set default values. + $provider += array( + 'disabled' => FALSE, + ); + + $form['providers']['title'][$name] = array( + '#type' => 'item', + '#markup' => filter_xss($provider['title']), + '#description' => filter_xss($provider['description']), + ); + + if (!isset($instance['settings']['behaviors']['prepopulate']['providers'][$name])) { + // backwards compatibility with version 1.4. + if ($name == 'url') { + // Enable the URL provider is it is not set in the instance yet. + $default_value = TRUE; + } + elseif ($name == 'og_context') { + $default_value = !empty($instance['settings']['behaviors']['prepopulate']['og_context']); + } + } + else { + $default_value = !empty($instance['settings']['behaviors']['prepopulate']['providers'][$name]); + } + + $form['providers']['enabled'][$name] = array( + '#type' => 'checkbox', + '#disabled' => $provider['disabled'], + '#default_value' => $default_value, + ); + + $form['providers']['weight'][$name] = array( + '#type' => 'weight', + '#default_value' => $weight, + '#attributes' => array('class' => array('provider-weight')), + ); + + ++$weight; + } + + return $form; + } +} + +/** + * Theme the providers table. + * + * @ingroup themeable + */ +function theme_entityreference_prepopulate_providers_table($variables) { + $form = $variables['form']; + + $provider_names = element_children($form['enabled']); + + foreach ($provider_names as $provider_name) { + $row = array( + 'data' => array( + drupal_render($form['title'][$provider_name]), + drupal_render($form['enabled'][$provider_name]), + drupal_render($form['weight'][$provider_name]), + ), + 'class' => array('draggable'), + ); + $rows[] = $row; + } + + $header = array( + array('data' => t('Provider')), + array('data' => t('Enabled')), + array('data' => t('Weight')), + ); + + $table_variables = array( + 'header' => $header, + 'rows' => $rows, + 'attributes' => array('id' => 'table-providers'), + ); + + $output = theme('table', $table_variables); + + drupal_add_tabledrag('table-providers', 'order', 'sibling', 'provider-weight'); + return $output; +} + +/** + * Element validate; Set the value of the providers. + */ +function entityreference_prepopulate_providers_validate($element, &$form_state) { + $value = $form_state['values']['instance']['settings']['behaviors']['prepopulate']['providers']['enabled']; + + // Sort the value by the weight. + uasort($value, 'drupal_sort_weight'); + + form_set_value($element, $value, $form_state); +} diff --git a/sites/all/modules/contrib/entityreference_prepopulate/plugins/behavior/prepopulate.inc b/sites/all/modules/contrib/entityreference_prepopulate/plugins/behavior/prepopulate.inc new file mode 100644 index 00000000..b21490b5 --- /dev/null +++ b/sites/all/modules/contrib/entityreference_prepopulate/plugins/behavior/prepopulate.inc @@ -0,0 +1,8 @@ + t('Entity reference prepopulate'), + 'description' => t('Prepopulate entity reference values from URL.'), + 'class' => 'EntityReferencePrepopulateInstanceBehavior', + 'behavior type' => 'instance', +); diff --git a/sites/all/modules/contrib/entityreference_prepopulate/plugins/content_types/node_prepopulate.inc b/sites/all/modules/contrib/entityreference_prepopulate/plugins/content_types/node_prepopulate.inc new file mode 100644 index 00000000..c62b11a0 --- /dev/null +++ b/sites/all/modules/contrib/entityreference_prepopulate/plugins/content_types/node_prepopulate.inc @@ -0,0 +1,100 @@ + t('Content prepopulate links'), + 'description' => t('Crafted links to create content (nodes) for an entity reference field.'), + 'required context' => new ctools_context_required(t('Node'), 'node'), + 'category' => t('Entity reference'), + 'defaults' => array( + 'types' => array(), + 'field_name' => '', + ), +); + +/** + * Render callback. + */ +function entityreference_prepopulate_node_prepopulate_content_type_render($subtype, $conf, $args, $context) { + if (empty($context->data)) { + return; + } + + $node = $context->data; + $links = entityreference_prepopulate_create_node_links('node', $node->nid, $conf['field_name'], NULL, !empty($conf['types']) ? $conf['types'] : NULL); + if (!$links) { + return; + } + + $module = 'entityreference_prepopulate'; + $block = new stdClass(); + $block->module = $module; + $block->title = t('Content create links'); + $block->content = $links; + return $block; +} + +/** + * Edit form. + */ +function entityreference_prepopulate_node_prepopulate_content_type_edit_form($form, &$form_state) { + $conf = $form_state['conf']; + + $options = array(); + $bundles = array(); + // Use CTools to get the best matching field name. + ctools_include('fields'); + foreach (field_info_instances('node') as $node_type => $instances) { + foreach ($instances as $field_name => $instance) { + if (empty($instance['settings']['behaviors']['prepopulate']['status'])) { + continue; + } + + $field = field_info_field($field_name); + + if ($field['settings']['target_type'] != 'node') { + // Field doesn't reference a node. + continue; + } + + $bundles[] = $instance['bundle']; + if (empty($options[$field_name])) { + $options[$field_name] = ctools_field_label($field_name) . ' (' . $field_name . ')'; + } + } + } + + $form['field_name'] = array( + '#title' => t('Field name'), + '#type' => 'select', + '#options' => $options, + '#default_value' => $conf['field_name'], + '#description' => $options ? t('The entity reference field to prepopulate.') : t('There are no entity reference fields, with prepopulate enabled'), + '#required' => TRUE, + ); + + $options = array(); + foreach (node_type_get_types() as $type) { + if (in_array($type->type, $bundles)) { + $options[$type->type] = check_plain($type->name); + } + } + $form['types'] = array( + '#title' => t('Restrict to content types'), + '#type' => 'checkboxes', + '#options' => $options, + '#default_value' => $conf['types'], + '#description' => t('If left empty, all possible content types are shown.'), + ); + return $form; +} + +/** + * Edit form submit callback. + */ +function entityreference_prepopulate_node_prepopulate_content_type_edit_form_submit($form, &$form_state) { + $form_state['conf']['field_name'] = $form_state['values']['field_name']; + $form_state['conf']['types'] = array_filter($form_state['values']['types']); +} diff --git a/sites/all/modules/contrib/entityreference_prepopulate/tests/entityreference_prepopulate_test.info b/sites/all/modules/contrib/entityreference_prepopulate/tests/entityreference_prepopulate_test.info new file mode 100644 index 00000000..b0336711 --- /dev/null +++ b/sites/all/modules/contrib/entityreference_prepopulate/tests/entityreference_prepopulate_test.info @@ -0,0 +1,13 @@ +name = Entity reference prepopulate test module +description = Functionality to assist Entity reference prepopulate testing. +core = 7.x +dependencies[] = entityreference_prepopulate +dependencies[] = og_context +hidden = TRUE + +; Information added by Drupal.org packaging script on 2014-02-19 +version = "7.x-1.5" +core = "7.x" +project = "entityreference_prepopulate" +datestamp = "1392845305" + diff --git a/sites/all/modules/contrib/entityreference_prepopulate/tests/entityreference_prepopulate_test.module b/sites/all/modules/contrib/entityreference_prepopulate/tests/entityreference_prepopulate_test.module new file mode 100644 index 00000000..eca517dc --- /dev/null +++ b/sites/all/modules/contrib/entityreference_prepopulate/tests/entityreference_prepopulate_test.module @@ -0,0 +1,18 @@ +field_msg_title = check_plain($form_state['values']['title']); $wrapper->field_msg_body = check_plain($form_state['values']['body']); - $wrapper->field_msg_recipient = $uid; + $wrapper->field_msg_sender = $user; //$wrapper->save(); - $recipient_user = user_load($uid); - $destination_email = $recipient_user->mail; $options = array('mail' => $destination_email); message_notify_send_message($message, $options); drupal_set_message('New message to ' . $recipient_user->realname); -} - +} \ No newline at end of file