diff --git a/sites/all/modules/contrib/flag/flag_lists/CHANGELOG.txt b/sites/all/modules/contrib/flag/flag_lists/CHANGELOG.txt new file mode 100644 index 00000000..7b0923d9 --- /dev/null +++ b/sites/all/modules/contrib/flag/flag_lists/CHANGELOG.txt @@ -0,0 +1,78 @@ +// $id: $ + +Flag lists (Jan. 27, 2011 +Fix bug: Incorrectly checking status of non-flag_lists flags. +Fix bug: Incorrectly applying hook_flag_access() on non-flag_lists flags. + +Flag lists (Jan. 14, 2011 +#1002292 Fixed Tokens not replaced in add-to-list and remove-from-list js messages. +#1002292 Token module now a required dependency. + +Flag lists (Jan. 12, 2011) +#1023432 by erikwebb: Fixed No default value for $account in flag_lists_fl_delete(). +#1002294 by architectJpres: Fixed List block incompatible with block caching. + Block caching turned off for now. Still not making db updates so you need to + remove the block from its region and then put it back to turn on caching. + +Flag lists (Nov. 24, 2010) +===== +Fix bug: Use array_filter instead of array_unique on flag_lists_template_submit() + and flag_lists_template_validate(); +Fix bug: Remove GROUP BY in flag_lists_get_user_flags(). Caused postgres bug. +Fix bug: flag_lists_insert() db_last_insert_id() used wrong table. +Fix typos in flag_lists_theme(). +Remove flag_lists link ops from regular flag links. +Add flag-lists-links to item list in theme_flag_lists_list(). + + +Flag lists (Nov. 07, 2010) +===== +Update view flags_lists_user_lists +Add view flag_lists_user_list +Use views when enabled. + +Flag lists (Nov. 07, 2010) +Show which types are in use in template config form. +Move key from type to name in flag_list_types *NOT creating update for this. +Fix template naming. Was not saved correctly to flag_lists_types table. +Change default template messages to anticipate token use. +Add token support including list terminology and title. +Added argument handler for fid. Uses list title for display instead fid. + +Flag lists (Oct. 11, 2010) +===== +flag_lists_get_user_flags() sets $flag->module = flag_lists for lists, and also +merges in flag module flags. +theme_flag_lists_list($node, $create = TRUE, $ops = TRUE, $flags = FALSE) adds +the $flags boolean, which if TRUE will add flag module flags to the list. +Invoke hook_flag() in flag_lists_do_flag(); +Add hook_flag_lists($flag, $user) with update and insert ops. +Add config options to list block. +Don't return anything to the block if there are no available flags or list +templates. +Fix theme_flag_lists_list to use block options. +Fix bug (wrong variable name) in flag_lists_get_user_flags(). +Fix query in flag_lists_get_user_flags(). Was not loading all list type rows. +Add list and listing generate fucntionality if devel_generate exists. +Added $account as argument to a variety of functions where the user may not always +be the current user. + +Flag lists (Sept. 24, 2010) +===== +Fix rebuild menu path + +Flag lists (Sept. 22, 2010) +===== +code cleanup +fix hook_flag_delete +Change template names from name_fl_template to fl_template_name. +Text changes in template form. +Page title change for template form. +flag_lists_form will take list fid or name. +Use fids on list edit links +change menu paths for edit, delete +improve some messages +allow users with "administer flags" permission to bypass flag_lists_is_owner() +checks. +First run at views integration +Better admin table for lists \ No newline at end of file diff --git a/sites/all/modules/contrib/flag/flag_lists/LICENSE.txt b/sites/all/modules/contrib/flag/flag_lists/LICENSE.txt new file mode 100644 index 00000000..d159169d --- /dev/null +++ b/sites/all/modules/contrib/flag/flag_lists/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/flag/flag_lists/css/flag_lists_ops.css b/sites/all/modules/contrib/flag/flag_lists/css/flag_lists_ops.css new file mode 100644 index 00000000..e69de29b diff --git a/sites/all/modules/contrib/flag/flag_lists/flag_lists.admin.inc b/sites/all/modules/contrib/flag/flag_lists/flag_lists.admin.inc new file mode 100644 index 00000000..71d53220 --- /dev/null +++ b/sites/all/modules/contrib/flag/flag_lists/flag_lists.admin.inc @@ -0,0 +1,599 @@ + NULL)); +} + +/** + * Theme the output for the main flag administration page. + */ +function theme_flag_lists_admin_page($variables) { + $flag = $variables['flag']; + + drupal_set_title(t('Flag lists')); + $output = '

' . t('This page shows all the lists that are currently defined on this system.') . '

'; + + // Can we use our default view? + if (module_exists('views')) { + $view = views_get_view('flag_lists', FALSE); + if (!empty($view)) { + $view->set_display('default'); + $output .= $view->render(); + } + } + + // Else build a simplified display. + else { + $header = array( + array('data' => t('List'), 'field' => 'name'), + array('data' => t('List title'), 'field' => 'title'), + array('data' => t('List type')), + array('data' => t('Owner'), 'field' => 'uid'), + array('data' => t('Node types')), + array('data' => t('Operations')), + ); + $flags = flag_lists_get_flags(25, $header); + foreach ($flags as $flag) { + $ops = theme('flag_lists_ops', $flag); + + $name = db_select('users', 'u') + ->fields('u', array('name')) + ->condition('uid', $flag->uid) + ->execute() + ->fetchField(); + $owner = l($name, 'user/' . $flag->uid, array('attributes' => array('title' => t('View user profile.')))); + $rows[] = array( + $flag->name, + $flag->title, + $flag->content_type, + $owner, + $flag->types ? implode(', ', $flag->types) : '-', + $ops, + ); + } + if (!$flags) { + $rows[] = array( + array('data' => t('No flags are currently defined.'), 'colspan' => 6), + ); + } + + $output .= theme('table', array('header' => $header, 'rows' => $rows)); + $output .= theme('pager', NULL, 25, 0); + } + + return $output; +} + +function flag_lists_add($type = NULL) { + if (is_null($type)) { + drupal_access_denied(); + } + + return drupal_get_form('flag_lists_form', NULL, $type); +} + +/** + * Callback for adding new lists through AJAX. + */ +function flag_lists_add_js($type = NULL) { + if (is_null($type)) { + drupal_json_output(array('error' => t('Type not supplied.'))); + exit(); + } + + $name = check_plain($_REQUEST['name']); + if (!isset($name) || empty($name)) { + drupal_json_output(array('error' => t('List name not supplied.'))); + exit(); + } + + if (drupal_strlen($name) > 255) { + drupal_json_output(array('error' => t('List name is too long. Maximum is 255 characters.'))); + exit(); + } + + if (flag_lists_title_exists($name, $type)) { + drupal_json_output(array('error' => t('You already have a @name with this name for this type of content.', array('@name' => variable_get('flag_lists_name', t('list')))))); + exit(); + } + + if (!isset($account)) { + $account = $GLOBALS['user']; + } + + // New flag. Load the template row. + $query = db_select('flag', 'f'); + $query->leftJoin('flag_lists_types', 'fl', 'f.name = fl.name'); + $query->fields('f') + ->fields('fl') + ->condition('fl.type', $type); + + $row = $query->execute() + ->fetchObject(); + + $newflag = flag_flag::factory_by_entity_type('node'); + + $flag = $newflag->factory_by_row($row); + // The template fid becomes the flag_lists parent flag. + $flag->pfid = $row->fid; + // The fid is NULL because this is really a new flag. + $flag->fid = NULL; + // The name is created in the save function. + $flag->name = NULL; + $flag->link_type = 'toggle'; + $flag->title = $name; + $flag->types = array($type); + $flag->uid = $account->uid; + flag_lists_set_messages($flag); + + // Save it. + flag_lists_save($flag, $account); + + drupal_json_output(array('error' => '', 'flag' => $flag)); +} + +/** + * Form to Add or edit a list. + */ +function flag_lists_form($form, $form_state, $name = NULL, $type = NULL) { + // First some sanity checks. $name and $type can't both be NULL. + // There must be a template for this content type. + if (is_null($name) && is_null($type)) { + drupal_access_denied(); + } + if (!flag_lists_template_exists($type) && is_null($name)) { + return; + } + // If name is numeric, then we have the fid, so get the name. + if (is_numeric($name)) { + $name = db_select('flag_lists_flags', 'f') + ->fields('f', array('name')) + ->condition('fid', $name) + ->execute() + ->fetchField(); + } + // Adding a new list. + if (!isset($name)) { + drupal_set_title(t('Add a new list')); + $form['edit'] = array( + '#type' => 'hidden', + '#value' => FALSE, + ); + } + + // Editing an existing list. + else { + $flag = flag_lists_get_flag($name); + + $title_string_name = variable_get('flag_lists_name', 'list'); + $title_string = t('Edit your "@title" @name title', array('@title' => $flag->get_title(), '@name' => $title_string_name)); + drupal_set_title(); + + $form['edit'] = array( + '#type' => 'hidden', + '#value' => TRUE, + ); + $form['name'] = array( + '#type' => 'hidden', + '#value' => $name, + ); + } + + $form['title'] = array( + '#type' => 'textfield', + '#title' => t('Title'), + '#default_value' => empty($flag->title) ? '' : $flag->title, + '#description' => t('A short, descriptive title for this @name list. Limit to 255 characters.', array('@name' => variable_get('flag_lists_name', t('list')))), + '#maxlength' => 255, + '#required' => TRUE, + '#access' => empty($flag->locked['title']), + '#weight' => -2, + ); + $form['type'] = array( + '#type' => 'hidden', + '#value' => $type, + ); + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Save'), + ); + return $form; +} + +/** + * Validate a list. + */ +function flag_lists_form_validate($form, $form_state) { + // Ensure 255 charactor or less name. + if (drupal_strlen($form_state['values']['title']) > 255) { + form_set_error('name', t('The @name title may only be 255 characters long.', array('@name' => variable_get('flag_lists_name', t('list'))))); + } + // Ensure the machine name is unique. + if (!$form_state['values']['edit']) { + if (flag_lists_title_exists($form_state['values']['title'], $form_state['values']['type'])) { + form_set_error('title', t('You already have a @name with this name for this type of content.', array('@name' => variable_get('flag_lists_name', t('list'))))); + } + } +} + +/** + * Save a list. + */ +function flag_lists_form_submit($form, $form_state, $account = NULL) { + if (!isset($account)) { + $account = $GLOBALS['user']; + } + + if (!empty($form_state['values']['edit'])) { + // Editing the title. + $flag = flag_lists_get_flag($form_state['values']['name']); + $flag->title = $form_state['values']['title']; + flag_lists_set_messages($flag); + flag_lists_save($flag); + _flag_lists_clear_cache(); + } + else { + // New flag. Load the template row. + $type = $form_state['values']['type']; + $query = db_select('flag', 'f'); + $query->leftJoin('flag_lists_types', 'fl', 'f.name = fl.name'); + $query->fields('f') + ->fields('fl') + ->condition('fl.type', $type); + + $row = $query->execute() + ->fetchObject(); + + $newflag = flag_flag::factory_by_entity_type('node'); + + $flag = $newflag->factory_by_row($row); + // The template fid becomes the flag_lists parent flag. + $flag->pfid = $row->fid; + // The fid is NULL because this is really a new flag. + $flag->fid = NULL; + // The name is created in the save function. + $flag->name = NULL; + $flag->link_type = 'toggle'; + $flag->title = $form_state['values']['title']; + $flag->types = array($type); + $flag->uid = $account->uid; + flag_lists_set_messages($flag); + // Save it. + flag_lists_save($flag, $account); + } +} + +/** + * Flag lists settings page. + */ +function flag_lists_settings_form($form, $form_state) { + drupal_set_title(t('Flag lists settings')); + $form['text'] = array( + '#title' => t('Using flag lists'), + '#markup' => t('Flag lists allow users to create their own personal flags. + No user can add to another user\'s lists. Lists inherit their + settings from template flags, which exist as flags in the flags\' module.' + ), + ); + + $form['flag_lists_name'] = array( + '#type' => 'textfield', + '#title' => t('Substitute "list" with your own terminology'), + '#default_value' => variable_get('flag_lists_name', t('list')), + '#description' => t('You can choose to use another name for "list", such as "favorites" or "bookmarks". Lowercase and plural names usually work best.'), + '#required' => TRUE, + ); + $form['rebuild'] = array( + '#type' => 'fieldset', + '#title' => t('Global rebuild'), + '#description' => t('Changes to list templates and settings normally apply + to only newly created flags. However, you can globally apply changes here. + First adjust the settings above and the list templates and save them. Then + click the link below. This will change ALL existing flag lists. It cannot + be undone.'), + '#tree' => FALSE, + ); + $form['rebuild']['global_rebuild'] = array( + '#markup' => l(t('Rebuild all flag lists.'), FLAG_ADMIN_PATH . '/flag-lists/rebuild'), + ); + + return system_settings_form($form); +} + +/** + * Confirm global settings rebuild. + */ +function flag_lists_rebuild_confirm($form, $form_state) { + return confirm_form($form, + t('Are you sure you want to rebuild all flag lists?'), + FLAG_ADMIN_PATH . '/lists/settings', + t('This action cannot be undone.'), + t('Rebuild'), t('Cancel') + ); +} + +/** + * Confirm global settings rebuild. + */ +function flag_lists_rebuild_confirm_submit($form, $form_state) { + flag_lists_rebuild(); + drupal_set_message(t('All flag lists have been rebuilt.')); + drupal_goto(FLAG_ADMIN_PATH . '/lists/settings'); +} + +/** + * Delete flag lists page. + */ +function flag_lists_delete_confirm($form, $form_state, $name) { + $flag = flag_lists_get_flag($name); + if (empty($flag)) { + drupal_goto(); + } + + $form['fid'] = array('#type' => 'value', '#value' => $flag->fid); + + return confirm_form($form, + t('Are you sure you want to delete %title?', array('%title' => $flag->get_title())), + isset($_GET['destination']) ? $_GET['destination'] : '/', + t('This action cannot be undone.'), + t('Delete'), t('Cancel') + ); +} + +function flag_lists_delete_confirm_submit($form, &$form_state) { + $flag = flag_lists_get_flag($form_state['values']['fid']); + if ($form_state['values']['confirm']) { + flag_lists_fl_delete($flag); + } +} + +/** + * Form to create a new template. + */ +function flag_lists_create_template_form($form, $form_state) { + drupal_set_title(t('Add a new list template')); + $form['help'] = array( + '#value' => t('This form creates a new, blank list template. After saving, you will be able to configure further options.'), + ); + $form['name'] = array( + '#type' => 'textfield', + '#title' => t('Template name'), + '#description' => t('The machine-name for this template. It may be up to 32 characters long and my only contain lowercase letters, underscores, and numbers.'), + '#maxlength' => 255, + '#required' => TRUE, + ); + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Save'), + ); + return $form; +} + +/** + * New template validation. + */ +function flag_lists_create_template_form_validate($form, &$form_state) { + // Ensure a safe machine name. + if (!preg_match('/^[a-z_][a-z0-9_]*$/', $form_state['values']['name'])) { + form_set_error('name', t('The flag name may only contain lowercase letters, underscores, and numbers.')); + } + // Ensure 32 charactor or less name. + if (drupal_strlen($form_state['values']['name']) > 32) { + form_set_error('name', t('The flag name may only be 32 characters long.')); + } + // Ensure the machine name is unique. + $flag = flag_get_flag('fl_template_' . $form_state['values']['name']); + if ($flag) { + form_set_error('name', t('Flag names must be unique. This flag name is already in use.')); + } +} + +/** + * New template submit. + */ +function flag_lists_create_template_form_submit($form, &$form_state) { + $template = flag_lists_flag_default_flags('fl_template_' . $form_state['values']['name']); + $flag = flag_flag::factory_by_array($template[0]); + $flag->title = t('List template') . ' ' . $form_state['values']['name']; + $flag->save(); + // Enter the new template into flag_lists_types. + db_insert('flag_lists_types') + ->fields(array( + 'name' => $flag->name, + )) + ->execute(); + $form_state['redirect'] = FLAG_ADMIN_PATH . '/edit/' . $flag->name; +} + + + +/** + * Developer tool to generate dummy lists and listings. + */ + +// @todo use batch api. +function flag_lists_generate_lists_form() { + $templates = flag_lists_get_templates(); + $options = array(); + foreach ($templates as $template) { + $options[$template->fid] = $template->name . ' (' . implode(', ', $template->types) . ')'; + } + $form['templates'] = array( + '#type' => 'checkboxes', + '#title' => t('Generate lists and/or listings for the following templates.'), + '#options' => $options, + ); + + $form['lists'] = array( + '#type' => 'textfield', + '#title' => t('How many lists should be generated?'), + '#default_value' => '0', + '#size' => 7, + '#maxlength' => 7, + ); + + $form['listings'] = array( + '#type' => 'textfield', + '#title' => t('How many listings should be generated?'), + '#default_value' => '0', + ); + + $form['kill_lists'] = array( + '#type' => 'checkbox', + '#title' => t('Delete ALL existing lists and listings before generating new ones? Templates will not be deleted.'), + '#default_value' => FALSE, + ); + $form['kill_listings'] = array( + '#type' => 'checkbox', + '#title' => t('Delete ALL existing listings before generating new ones? (Lists are not deleted unless the above is checked.)'), + '#default_value' => FALSE, + ); + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Do it!'), + ); + return $form; +} + +/** + * Validation handler for flag_lists_generate_lists_form. + */ +function flag_lists_generate_lists_form_validate($form, &$form_state) { + if ($form_state['values']['lists'] && !is_numeric($form_state['values']['lists']) || $form_state['values']['lists'] < 0) { + form_set_error('lists', t('Number of lists to generate must be a number, 1 or more.')); + } + if ($form_state['values']['listings'] && !is_numeric($form_state['values']['listings']) || $form_state['values']['listings'] < 0) { + form_set_error('listings', t('Number of listings to generate must be a number, 1 or more.')); + } + if ($form_state['values']['lists'] > 0 && !count(array_filter($form_state['values']['templates']))) { + form_set_error('templates', t('You must select at least 1 template for the lists to be genereated')); + } + if ($form_state['values']['listings'] > 0 && !count(array_filter($form_state['values']['templates']))) { + form_set_error('templates', t('You must select at least 1 template for the listings to be genereated')); + } +} + +/** + * Submit handler for flag_lists_generate_lists_form. + */ +function flag_lists_generate_lists_form_submit($form, &$form_state) { + global $user; + module_load_include('inc', 'devel_generate'); + + // Delete listings. + if ($form_state['values']['kill_listings']) { + $flags = flag_lists_get_flags(); + foreach ($flags as $flag) { + $result = db_select('flag_lists_content', 'f') + ->fields('f', array('fcid', 'content_id')) + ->condition('fid', $flag->fid) + ->execute(); + + foreach ($result as $row) { + db_delete('flag_lists_content')->condition('fid', $flag->fid)->execute(); + db_delete('flag_lists_counts')->condition('fid', $flag->fid)->execute(); + + module_invoke_all('flag', 'unflag', $flag, $row->content_id, $account, $row->fcid); + } + } + drupal_set_message(t('All listings were deleted.')); + } + + // Delete lists and listings. + if ($form_state['values']['kill_lists']) { + // If we loaded all flags above, don't reload them here. + if (!count($flags)) { + $flags = flag_lists_get_flags(); + } + foreach ($flags as $flag) { + flag_lists_fl_delete($flag, $user); + } + drupal_set_message(t('All lists and their listings were deleted.')); + } + + + $templates = array_filter($form_state['values']['templates']); + $uids = array_filter(devel_get_users()); // Don't use the anon user. + + // Generate lists. + if ($form_state['values']['lists'] && count($templates)) { + for ($i = 1; $i <= $form_state['values']['lists']; $i++ ) { + $template = flag_get_flag(NULL, array_rand($templates)); + $account->uid = $uids[array_rand($uids)]; + $edit['values']['title'] = devel_create_greeking(7, TRUE); + $edit['values']['type'] = $template->types[array_rand($template->types)]; + $form = array(); + flag_lists_form_submit($form, $edit, $account); + } + drupal_set_message(t('@lists created.', array('@lists' => format_plural($form_state['values']['lists'], '1 list', '@count lists')))); + } + + // Generate listings. + if ($form_state['values']['listings']) { + + $count = 0; + + for ($i = 1; $i <= $form_state['values']['listings']; $i++ ) { + $account->uid = $uids[array_rand($uids)]; + $lists = flag_lists_get_user_flags(NULL, $account); + + // Remove any lists that don't use the chosen templates. + foreach ($lists as $key => $list) { + if (!isset($templates[$list->pfid])) { + unset($lists[$key]); + } + } + + // Ensure user has lists. + if (!count($lists)) { + continue; + } + + $list = $lists[array_rand($lists)]; + $content_type = $list->types[array_rand($list->types)]; + + // We get the random nid with 2 SELECTS to avoid slow ORDER BY Rand(). + // Get max nid for our content type. + $query = db_select('node') + ->condition('type', $content_type); + $query->addExpression('MAX(nid)', 'max'); + $max_nid = $query->execute()->fetchField(); + + // Ensure a node exists for the type. + if (!$max_nid) { + continue; + } + + $r = rand(1, $max_nid); + $content_id = db_select('node', 'n') + ->fields('n', array('nid')) + ->condition('type', $content_type) + ->condition('nid', $r) + ->range(0, 1) + ->execute() + ->fetchField(); + + // We can't assume that every attempt will result in a listing because + // we may have a node type with no nodes yet or a user with no lists. + // Also, if a listing already exists, we count it, but it can only be in + // the db once. + if (flag_lists_do_flag($list, 'flag', $content_id, $account, TRUE)) { + $count++; + } + } + drupal_set_message(t('@listings listed.', array('@listings' => format_plural($count, '1 node', '@count nodes')))); + if ($count < $form_state['values']['listings']) { + drupal_set_message(t('Listings are generated randomly. Occassionally a listing will not be created if the random user has no lists or if the node type to be listed has no nodes.')); + } + } +} + + diff --git a/sites/all/modules/contrib/flag/flag_lists/flag_lists.info b/sites/all/modules/contrib/flag/flag_lists/flag_lists.info new file mode 100644 index 00000000..07030fb4 --- /dev/null +++ b/sites/all/modules/contrib/flag/flag_lists/flag_lists.info @@ -0,0 +1,27 @@ +name = Flag lists +core = 7.x +package = Flags +dependencies[] = flag +dependencies[] = token + +files[] = flag_lists.admin.inc +files[] = flag_lists.module +files[] = flag_lists.install +files[] = includes/flag_lists.views.inc +files[] = includes/flag_lists.views_default.inc +files[] = includes/flag_lists_handler_argument_fid.inc +files[] = includes/flag_lists_handler_field_list.inc +files[] = includes/flag_lists_handler_field_list_delete.inc +files[] = includes/flag_lists_handler_field_list_edit.inc +files[] = includes/flag_lists_handler_field_ops.inc +files[] = includes/flag_lists_handler_field_template.inc +files[] = includes/flag_lists_handler_field_template_types.inc +files[] = includes/flag_lists_handler_filter_template.inc + +description = Allows users to create personal flag lists. +; Information added by drupal.org packaging script on 2012-05-03 +version = "7.x-1.1" +core = "7.x" +project = "flag_lists" +datestamp = "1336060255" + diff --git a/sites/all/modules/contrib/flag/flag_lists/flag_lists.install b/sites/all/modules/contrib/flag/flag_lists/flag_lists.install new file mode 100644 index 00000000..a84fd496 --- /dev/null +++ b/sites/all/modules/contrib/flag/flag_lists/flag_lists.install @@ -0,0 +1,207 @@ + array( + 'fid' => array( + 'type' => 'serial', + 'size' => 'small', + 'unsigned' => TRUE, + 'not null' => TRUE, + ), + 'pfid' => array( + 'type' => 'int', + 'size' => 'small', + 'unsigned' => TRUE, + 'not null' => TRUE, + ), + 'uid' => array( + 'type' => 'int', + 'size' => 'small', + 'unsigned' => TRUE, + 'not null' => TRUE, + ), + 'entity_type' => array( + 'type' => 'varchar', + 'length' => '32', + 'not null' => TRUE, + 'default' => '', + ), + 'name' => array( + 'type' => 'varchar', + 'length' => '32', + 'not null' => FALSE, + 'default' => '', + ), + 'title' => array( + 'type' => 'varchar', + 'length' => '255', + 'not null' => FALSE, + 'default' => '', + ), + 'options' => array( + 'type' => 'text', + 'not null' => FALSE, + ), + ), + 'primary key' => array('fid'), + 'unique keys' => array( + 'name' => array('name'), + ), + ); + $schema['flag_lists_content'] = array( + 'fields' => array( + 'fcid' => array( + 'type' => 'serial', + 'unsigned' => TRUE, + 'not null' => TRUE, + ), + 'fid' => array( + 'type' => 'int', + 'size' => 'small', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'entity_type' => array( + 'type' => 'varchar', + 'length' => '32', + 'not null' => TRUE, + 'default' => '', + ), + 'entity_id' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'uid' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'sid' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'timestamp' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'disp-size' => 11, + ) + ), + 'primary key' => array('fcid'), + 'unique keys' => array( + 'fid_entity_id_uid_sid' => array('fid', 'entity_id', 'uid', 'sid'), + ), + 'indexes' => array( + 'entity_type_entity_id' => array('entity_type', 'entity_id'), + 'entity_type_uid_sid' => array('entity_type', 'uid', 'sid'), + ), + ); + $schema['flag_lists_counts'] = array( + 'fields' => array( + 'fid' => array( + 'type' => 'int', + 'size' => 'small', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'entity_type' => array( + 'type' => 'varchar', + 'length' => '32', + 'not null' => TRUE, + 'default' => '', + ), + 'entity_id' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'disp-width' => '10', + ), + 'count' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'disp-width' => '10', + ) + ), + 'primary key' => array('fid', 'entity_id'), + 'indexes' => array( + 'fid_entity_type' => array('fid', 'entity_type'), + 'entity_type_entity_id' => array('entity_type', 'entity_id'), + 'count' => array('count'), + ), + ); + $schema['flag_lists_types'] = array( + 'fields' => array( + 'name' => array( + 'type' => 'varchar', + 'length' => '32', + 'not null' => TRUE, + 'default' => '', + ), + 'type' => array( + 'type' => 'varchar', + 'length' => '32', + 'not null' => FALSE, + 'default' => '') + ), + 'primary key' => array('name', 'type'), + 'indexes' => array( + 'name' => array('name'), + ), + ); + return $schema; +} + +/** + * Implements hook_install(). + */ +function flag_lists_install() { + // Set up our default template. + db_insert('flag_lists_types') + ->fields(array( + 'name' => 'fl_template', + )) + ->execute(); +} + +/** + * Implements hook_uninstall(). + */ +function flag_lists_uninstall() { + // Remove our template flags. + $query = db_select('flag_lists_types', 'fl'); + $query->leftJoin('flag', 'f', 'fl.name = f.name'); + $query->addField('fl', 'fid', 'fid'); + $query->distinct(); + $fids = $query->execute(); + + foreach ($fids as $fid) { + db_delete('flag')->condition('fid', $fid->fid); + db_delete('flag_content')->condition('fid', $fid->fid); + db_delete('flag_types')->condition('fid', $fid->fid); + db_delete('flag_counts')->condition('fid', $fid->fid); + } + + db_delete('variable')->condition('name', 'flag_lists%', 'LIKE'); + drupal_set_message(t('Flag lists has been uninstalled.')); +} diff --git a/sites/all/modules/contrib/flag/flag_lists/flag_lists.module b/sites/all/modules/contrib/flag/flag_lists/flag_lists.module new file mode 100644 index 00000000..8b25b241 --- /dev/null +++ b/sites/all/modules/contrib/flag/flag_lists/flag_lists.module @@ -0,0 +1,1737 @@ + 'Lists', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('flag_lists_settings_form'), + 'access callback' => 'user_access', + 'access arguments' => array('administer flags'), + 'description' => 'Configure default settings allowing users to mark content with personal flags.', + 'file' => 'flag_lists.admin.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => 100, + ); + $items[FLAG_ADMIN_PATH . '/lists/settings'] = array( + 'title' => 'Settings', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('flag_lists_settings_form'), + 'access callback' => 'user_access', + 'access arguments' => array('administer flags'), + 'description' => 'Configure default settings allowing users to mark content with personal flags.', + 'file' => 'flag_lists.admin.inc', + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'weight' => 1, + ); + $items[FLAG_ADMIN_PATH . '/lists/list'] = array( + 'title' => 'List', + 'page callback' => 'flag_lists_admin_page', + 'access callback' => 'user_access', + 'access arguments' => array('administer flags'), + 'file' => 'flag_lists.admin.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => 2, + ); + $items[FLAG_ADMIN_PATH . '/lists/template'] = array( + 'title' => 'New template', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('flag_lists_create_template_form'), + 'access callback' => 'user_access', + 'access arguments' => array('administer flags'), + 'file' => 'flag_lists.admin.inc', + 'type' => MENU_LOCAL_TASK, + 'weight' => 3, + ); + if (module_exists('devel_generate')) { + $items['admin/config/development/generate/flag-lists'] = array( + 'title' => 'Generate lists', + 'description' => 'Generate a given number of lists and listings on site content. Optionally delete existing lists and listings.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('flag_lists_generate_lists_form'), + 'access callback' => 'user_access', + 'access arguments' => array('administer flags'), + 'file' => 'flag_lists.admin.inc', + ); + } + $items['flag-lists/add/%'] = array( + 'title' => 'Add a list', + 'page callback' => 'flag_lists_add', + 'page arguments' => array(2), + 'access callback' => 'user_access', + 'access arguments' => array('create flag lists'), + 'file' => 'flag_lists.admin.inc', + 'type' => MENU_NORMAL_ITEM, + ); + // Callback for adding a new list through JS + $items['flag-lists/add/%/js'] = array( + 'title' => 'Add a list', + 'page callback' => 'flag_lists_add_js', + 'page arguments' => array(2), + 'access callback' => 'user_access', + 'access arguments' => array('create flag lists'), + 'file' => 'flag_lists.admin.inc', + 'type' => MENU_CALLBACK, + ); + + $items['flags/lists/edit/%'] = array( + 'title' => 'Edit a list', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('flag_lists_form', 3), + 'access callback' => 'flag_lists_is_owner', + 'access arguments' => array(2, 3), + 'file' => 'flag_lists.admin.inc', + 'type' => MENU_CALLBACK, + ); + $items['flags/lists/delete/%'] = array( + 'title' => 'Delete a list', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('flag_lists_delete_confirm', 3), + 'access callback' => 'flag_lists_is_owner', + 'access arguments' => array(2, 3), + 'file' => 'flag_lists.admin.inc', + 'type' => MENU_CALLBACK, + ); + $items[FLAG_ADMIN_PATH . '/flag-lists/rebuild'] = array( + 'title' => 'Rebuild all flag lists', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('flag_lists_rebuild_confirm'), + 'access callback' => 'user_access', + 'access arguments' => array('administer flag lists'), + 'file' => 'flag_lists.admin.inc', + 'type' => MENU_CALLBACK, + ); + $items['flag-lists'] = array( + 'title' => 'Flag', + 'page callback' => 'flag_lists_page', + 'access callback' => 'user_access', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + + $items['user/%user/flags/lists'] = array( + 'title' => ucfirst(variable_get('flag_lists_name', 'list')), + 'page callback' => 'flag_lists_user_page', + 'page arguments' => array(1), + 'access callback' => 'user_access', + 'access arguments' => array('view flag lists'), + 'type' => MENU_LOCAL_TASK, + ); + $items['user/%user/flags/lists/%'] = array( + 'title' => ucfirst(variable_get('flag_lists_name', 'list')) . ' content', + 'page callback' => 'flag_lists_user_list', + 'page arguments' => array(1, 4), + 'access callback' => 'user_access', + 'access arguments' => array('view flag lists'), + 'type' => MENU_CALLBACK, + ); + return $items; +} + +/** + * User flag page. Display a list of user-created flag lists. + */ +function flag_lists_user_page($user) { + // Can we use our default view? + if (module_exists('views')) { + $view = views_get_view('flag_lists_user_lists', FALSE); + if (!empty($view)) { + $view->set_display('default'); + $view->set_arguments(array($user->uid)); + $output = $view->render(); + drupal_set_title(str_replace(array_keys($view->build_info['substitutions']), $view->build_info['substitutions'], $view->build_info['title'])); + } + return $output; + } + else { + return theme('flag_lists_user_page', array('uid' => $user->uid)); + } +} + +/** + * Theme the output for a user flag administration page. + */ +function theme_flag_lists_user_page($variables) { + $uid = $variables['uid']; + + $account = user_load($uid); + drupal_set_title(t('Lists')); + if ($flags = flag_lists_get_user_flags(NULL, $account)) { + // Build the list of flag lists for this node. + foreach ($flags as $flag) { + $ops = theme('flag_lists_ops', array('flag' => $flag)); + $items[] = l($flag->title, "user/$uid/flags/lists/" . $flag->fid) . $ops; + } + } + drupal_add_css(drupal_get_path('module', 'flag_lists') . '/theme/flag_lists.css'); + return theme('item_list', array('items' => $items)); +} + +/** + * List the contents of a user-defined list + */ +function flag_lists_user_list($user, $fid) { + $uid = $user->uid; + // Can we use our default view? + if (module_exists('views')) { + $view = views_get_view('flag_lists_user_list', FALSE); + if (!empty($view)) { + $view->set_display('default'); + $view->set_arguments(array($fid)); + $output = $view->render(); + drupal_set_title(str_replace(array_keys($view->build_info['substitutions']), $view->build_info['substitutions'], $view->build_info['title'])); + } + return $output; + } + + else { + return theme('flag_lists_user_list', array('uid' => $uid, 'fid' => $fid)); + } +} + +/** + * Theme the output of user-defined list page + */ +function theme_flag_lists_user_list($variables) { + $uid = $variables['uid']; + $fid = $variables['fid']; + + $flag = flag_lists_get_flag($fid); + drupal_set_title($flag->title); + $content = flag_lists_get_flagged_content($fid, $uid); + foreach ($content as $item) { + if ($item->content_type == 'node') { + $node = node_load($item->entity_id); + $items[] = l($node->title, 'node/' . $node->nid); + } + } + + $breadcrumb = menu_get_active_breadcrumb(); + $breadcrumb[] = l(t('@name lists', array('@name' => drupal_ucfirst(variable_get('flag_lists_name', t('lists'))))), 'user/' . arg(1) . '/flags/lists'); + drupal_set_breadcrumb($breadcrumb); + return theme('item_list', array('items' => $items)); +} + +/** + * Implementation of hook_theme(). + */ +function flag_lists_theme() { + $path = drupal_get_path('module', 'flag') . '/theme'; + + return array( + 'flag_lists_list' => array( + 'variables' => array('node' => NULL, 'create' => NULL, 'ops' => NULL, 'use_flags' => NULL), + ), + 'flag_lists_admin_page' => array( + 'variables' => array('flags' => NULL), + ), + 'flag_lists_user_page' => array( + 'variables' => array('uid' => NULL), + ), + 'flag_lists_user_list' => array( + 'variables' => array('flag_name' => NULL), + ), + 'flag_lists_ops' => array( + 'variables' => array('flag' => NULL), + ) + ); +} + +/** + * Implementation of hook_permission(). + */ +function flag_lists_permission() { + return array( + 'create flag lists' => array( + 'title' => t('Create flag lists'), + 'description' => t(''), + ), + 'edit own flag lists' => array( + 'title' => t('Edit own flag lists'), + 'description' => t(''), + ), + 'delete own flag lists' => array( + 'title' => t('Delete own flag lists'), + 'description' => t(''), + ), + 'view flag lists' => array( + 'title' => t('View flag lists'), + 'description' => t(''), + )); +} + +/** + * Implementation of hook_form_alter(). + */ +function flag_lists_form_alter(&$form, &$form_state, $form_id) { + switch ($form_id) { + case 'flag_form': + // A template flag should always have a record in the flag_lists_types table. + $result = db_select('flag_lists_types', 'f')->fields('f')->execute(); + foreach ($result as $type) { + $types[$type->name] = $type->type; + } + + if (isset($types[$form['name']['#default_value']])) { + $form['name']['#type'] = 'value'; + $form['global']['#type'] = 'value'; + $form['title']['#description'] = t('A short, descriptive title for this template. It will be used in administrative interfaces to refer to this template.'); + + // Warn about types that already have a template. + foreach ($form['access']['types']['#options'] as $option => $value) { + if (in_array($option, $types) && $form['access']['types']['#default_value'] != $option) { + $form['access']['types']['#options'][$option] .= '' . t('(Already has a template.)') . ''; + } + } + $form['access']['types']['#description'] .= t('A type may only be selected in one list template.'); + + // Unset anon permissions for now. @todo allow anon listing. + unset($form['access']['roles']['flag']['#options'][1]); + unset($form['access']['roles']['unflag']['#options'][1]); + + foreach (element_children($form['display']) as $display) { + $form['display'][$display]['#type'] = 'value'; + } + $form['display']['link_type']['#default_value'] = 'fl_template'; + $form['display']['#description'] = t('Unlike normal flags, lists are only displayed in a block provided by this module or in views blocks. See the block admin page to place the block.'); + + $form['#validate'][] = 'flag_lists_template_validate'; + $form['#submit'][] = 'flag_lists_template_submit'; + } + break; + + case 'views_exposed_form': + // Force the exposed filters to perform actions on the page itself because + // the views default viwe didn't come with a page display + if ($form['#id'] == 'views-exposed-form-flag-lists-default') { + $form['#action'] = '/' . implode('/', arg()); + } + break; + } + + // Flag lists operations related changes + if (strpos($form_id, 'views_form_') === 0) { + $flo = _flag_lists_ops_get_field($form_state['build_info']['args'][0]); + + // Not a FLO-enabled views form. + if (empty($flo)) { + return; + } + + // Add FLO's custom callbacks. + $form['#validate'][] = 'flag_lists_ops_form_validate'; + $form['#submit'][] = 'flag_lists_ops_form_submit'; + + // Allow FLO to work when embedded using views_embed_view(), or in a block. + if (empty($flo->view->override_path)) { + if (!empty($flo->view->preview) || $flo->view->display_handler instanceof views_plugin_display_block) { + $flo->view->override_path = $_GET['q']; + } + } + + // Quickfix for FLO & exposed filters using ajax. See http://drupal.org/node/1191928. + $query = drupal_get_query_parameters($_GET, array('q')); + $form['#action'] = url($flo->view->get_url(), array('query' => $query)); + + // Add basic FLO functionality. + if ($form_state['step'] == 'views_form_views_form') { + $form = flag_lists_ops_form($form, $form_state, $flo); + } + } +} + +/** + * Add the Flag list select menu widget. + */ +function flag_lists_ops_form($form, &$form_state, $flo) { + $form['#attached']['js'][] = drupal_get_path('module', 'flag_lists') . '/js/flag_lists_ops.js'; + $form['#attached']['css'][] = drupal_get_path('module', 'flag_lists') . '/css/flag_lists_ops.css'; + $form['#prefix'] = '
'; + $form['#suffix'] = '
'; + + $form_state['flo_operation'] = $flo->options['flo']['operation']; + + // Force browser to reload the page if Back is hit. + if (preg_match('/msie/i', $_SERVER['HTTP_USER_AGENT'])) { + drupal_add_http_header('Cache-Control', 'no-cache'); // works for IE6+ + } + else { + drupal_add_http_header('Cache-Control', 'no-store'); // works for Firefox and other browsers + } + + global $user; + global $base_url; + $account = user_load($user->uid); + $items = array(); + if ($flags = flag_lists_get_user_flags(NULL, $account)) { + // Build the list of flag lists for this node. + foreach ($flags as $flag) { + $items[((string)$flag->fid)] = $flag->title; + } + } + + // Group items into a fieldset for easier theming. + $form['flag_lists_' . $form_state['flo_operation']] = array( + '#type' => 'fieldset', + '#title' => t('List operations'), + '#tree' => TRUE, + '#attributes' => array('class' => array('flag-lists-ops-fieldset')), + ); + switch ($flo->options['flo']['operation']) { + case 'unflag': + $null_text = 'Remove from a list'; + $operation = 'unflag'; + $form['flag_lists_' . $form_state['flo_operation']]['list'] = array( + '#type' => 'button', + '#value' => t('Remove from list'), + '#ajax' => array( + 'callback' => 'flag_lists_ops_form_ajax_callback', + 'wrapper' => 'flag-list-ops-container-' . $flo->options['flo']['operation'], + ), + ); + break; + default: + $null_text = 'Add to a list'; + $operation = 'flag'; + drupal_add_library('system', 'ui.dialog'); + $form['flag_lists_' . $form_state['flo_operation']]['list'] = array( + '#type' => 'select', + '#options' => array('0' => t('- ' . $null_text . ' -')) + $items, + '#default_value' => '0', + '#ajax' => array( + 'callback' => 'flag_lists_ops_form_ajax_callback', + 'wrapper' => 'flag-list-ops-container-' . $flo->options['flo']['operation'], + ), + '#attributes' => array( + 'class' => array( + 'flag-lists-ops-dropdown', + ), + ), + ); + + // Add the necessary JS for creating a new list via AJAX + $result = db_select('flag_lists_types') + ->fields('flag_lists_types') + ->execute(); + $list_types = array(); + foreach ($result as $row) { + if (!empty($row->type)) { + $list_types[] = $row->type; + } + } + drupal_add_js(array('flag_lists' => array('types' => $list_types, 'json_path' => $base_url . '/flag-lists/add/%/js')), 'setting'); + break; + } + + // Get the $ops from the originating form. + if (!empty($form_state['values']['flag_lists_' . $form_state['flo_operation']]['list'])) { + $list = $form_state['values']['flag_lists_' . $form_state['flo_operation']]['list']; + } + if (!empty($_REQUEST['flag_lists_ops'])) { + $ops = $_REQUEST['flag_lists_ops']; + } + if (!empty($ops) && !empty($list) && $form_state['values']['flag_lists_' . $form_state['flo_operation']]['operation'] == 'unflag') { + $hidden_deleted_values = ''; + foreach ($ops as $nid) { + $hidden_deleted_values .= ''; + } + } + + $form['flag_lists_' . $form_state['flo_operation']]['operation'] = array( + '#type' => 'hidden', + '#value' => $operation, + ); + $form['flag_lists_' . $form_state['flo_operation']]['go'] = array( + '#type' => 'submit', + '#value' => t('Go'), + '#attributes' => array( + 'class' => array('flag-lists-ops-go'), + ), + ); + unset($form['actions']['submit']); + + // Generate a status message for AJAX submission. + $form['flag_lists_' . $form_state['flo_operation']]['status_message'] = array('#markup' => ''); + $form['flag_lists_' . $form_state['flo_operation']]['#prefix'] = '
'; + $form['flag_lists_' . $form_state['flo_operation']]['#suffix'] = (!empty($hidden_deleted_values)) ? $hidden_deleted_values : '' . '
'; + + return $form; +} + +function flag_lists_ops_form_ajax_callback($form, $form_state) { + // The form has already been submitted and updated. We can return the replaced + // item as it is. + if (!flag_lists_ops_form_validate($form, $form_state)) { + $message = flag_lists_ops_form_submit($form, $form_state); + } + + $form['flag_lists_' . $form_state['flo_operation']]['status_message']['#markup'] = '
' . $message . '
'; + if ($form_state['flo_operation'] == 'flag') $form['flag_lists_' . $form_state['flo_operation']]['list']['#value'] = '0'; + $form['flag_lists_' . $form_state['flo_operation']]['status_message']['#attributes']['class'][] = 'alert-success'; + + return $form['flag_lists_' . $form_state['flo_operation']]; +} + +function flag_lists_ops_form_validate(&$form, &$form_state) { + global $user; + + $error_count = 0; + + // Check to see if an items are selected, if not fail right away. + if (!isset($_REQUEST['flag_lists_ops']) || empty($_REQUEST['flag_lists_ops'])) { + form_set_error('', t('No content selected.')); + $error_count++; + return $error_count; + } + + switch ($form_state['values']['flag_lists_' . $form_state['flo_operation']]['operation']) { + case 'unflag': + $ops = $_REQUEST['flag_lists_ops']; + foreach ($ops as $key => $op) { + $ops[$key] = explode('-', $op); + if (empty($ops[$key][1]) || !($flag = flag_lists_get_flag($ops[$key][1]))) { + form_set_error('flag_lists][remove', t('Invalid options list selected to remove from.')); + $error_count++; + } + else if ($flag->uid != $user->uid) { + form_set_error('flag_lists][remove', t('You are only allowed to remove content from your own lists.')); + $error_count++; + } + } + break; + default: + if (empty($form_state['values']['flag_lists_' . $form_state['flo_operation']]['list'])) { + form_set_error('flag_lists][list', t('No list selected. Please select a list to add to.')); + $error_count++; + } + else if (!($flag = flag_lists_get_flag($form_state['values']['flag_lists_' . $form_state['flo_operation']]['list']))) { + form_set_error('flag_lists][list', t('Invalid list selected. Please select a list to add to.')); + $error_count++; + } + else if ($flag->uid != $user->uid) { + form_set_error('flag_lists][list', t('Invalid list selected. Please select a list to add to.')); + $error_count++; + } + break; + } + + return $error_count; +} + +function flag_lists_ops_form_submit(&$form, &$form_state) { + // Get the $ops from the originating form. + $ops = $_REQUEST['flag_lists_ops']; + $success_count = 0; + + // Get the operation, or set it + switch ($form_state['values']['flag_lists_' . $form_state['flo_operation']]['operation']) { + case 'unflag': + $operation = 'unflag'; + $message = 'removed from'; + + foreach ($ops as $op) { + // Process the ID into 2 parts + list($nid, $fid) = explode('-', $op); + if (empty($nid) || empty($fid)) return; + + if (($flag = flag_lists_get_flag($fid)) && ($node = node_load($nid))) { + if (flag_lists_do_flag($flag, $operation, $nid)) { + $success_count++; + } + } + } + break; + default: + $operation = 'flag'; + $message = 'added to'; + + if ($flag = flag_lists_get_flag($form_state['values']['flag_lists_' . $form_state['flo_operation']]['list'])) { + foreach ($ops as $nid) { + if (flag_lists_do_flag($flag, $operation, $nid)) { + $success_count++; + } + } + } + break; + } + + $message = t('@count item(s) ' . $message . ' !title', array('@count' => $success_count, '!title' => $flag->title)); + if ($_GET['q'] != 'system/ajax') { + drupal_set_message($message); + } + else { + return $message; + } +} + +/** + * Gets the FLO field if it exists on the passed-in view. + * + * @return + * The field object if found. Otherwise, FALSE. + */ +function _flag_lists_ops_get_field($view) { + foreach ($view->field as $field_name => $field) { + if ($field instanceof flag_lists_handler_field_ops) { + // Add in the view object for convenience. + $field->view = $view; + return $field; + } + } + return FALSE; +} + +function flag_lists_template_validate($form, &$form_state) { + $types = array_filter($form_state['values']['types']); + $errors = array(); + foreach ($types as $type) { + $result = db_select('flag_lists_types', 'f') + ->fields('f') + ->condition('type', $type) + ->condition('name', $form_state['values']['name'], '<>') + ->execute(); + foreach ($result as $errors) { + $content_types[] = $errors->type; + $templates[] = $errors->name; + } + } + if (isset($content_types) && count($content_types)) { + $content_types = implode(', ', $content_types); + $templates = implode(', ', array_unique($templates)); + form_set_error('types', t('The flaggable content type(s) "@type" is(are) already assigned to the template(s) "@template." A content type may be assigned to only one template. To reassign a content type you must first remove its other assignment.', array('@type' => $content_types, '@template' => $templates))); + } +} + +function flag_lists_template_submit($form, &$form_state) { + $types = array_filter($form_state['values']['types']); + // Clean out the old types, then add the new. + $num_deleted = db_delete('flag_lists_types') + ->condition('name', $form_state['values']['name']) + ->execute(); + foreach ($types as $type) { + db_insert('flag_lists_types') + ->fields(array( + 'name' => $form_state['values']['name'], + 'type' => $type, + )) + ->execute(); + } +} +/** + * Helper function to build an array of all lists available to or owned by the + * current user and that are available on the current content type. + */ +function flag_lists_get_content_fids() { + global $user; + + // This is a node view. We only care about nodes for now. + if (arg(0) == 'node' && is_numeric(arg(1)) && is_null(arg(2))) { + $type = db_select('node', 'n') + ->fields('n', array('type')) + ->condition('nid', arg(1)) + ->execute() + ->fetchField(); + + // Get current user's flags for this node. + $query = db_select('flag_lists', 'fc') + ->fields('f', 'fid') + ->condition('fc.uid', $user->uid) + ->condition('fn.type', $type); + $query->leftJoin('flag_types', 'fn', 'fn.fid = fc.fid'); + $query->leftJoin('flags', 'f', 'fc.fid = f.fid'); + $fc_result = $query->execute(); + + foreach ($fc_result as $row) { + $fids[] = $row->fid; + } + } + + // This is the flag / unflag callback + elseif (arg(0) == 'flag' && (arg(1) == 'flag' || arg(1) == 'unflag')) { + // Get the flag for this request. + $fids[] = db_select('flags', 'f') + ->fields('f', array('fid')) + ->condition('name', arg(2)) + ->execute() + ->fetchField(); + } + + // Get the regular flags for this node. The flag module will narrow by role, + // etc. when flag_get_flags() is called. These flag ids are always returned. + $query = db_select('flags', 'f') + ->fields('f', array('fid')) + ->condition('fc.fid', NULL); + $query->leftJoin('flag_lists', 'fc', 'fc.fid = f.fid'); + $f_result = $query->execute(); + + foreach ($f_result as $obj) { + $fids[] = $obj->fid; + } + if (is_array($fids)) { + return array_unique($fids); + } + else { + return array(); + } +} + +/** + * Implements hook_block_info(); + */ +function flag_lists_block_info() { + return array( + 'flag_lists' => array( + 'info' => t('Lists'), + 'cache' => DRUPAL_NO_CACHE, + ), + 'flag_lists_list' => array( + 'info' => t('My lists'), + 'cache' => DRUPAL_NO_CACHE, + ), + ); +} + +/** + * Implements hook_block_configure(). + */ +function flag_lists_block_configure($delta = '') { + $form = array(); + + switch ($delta) { + case 'flag_lists': + $form = array( + 'create_lists' => array( + '#type' => 'checkbox', + '#title' => t('Show link to add new list'), + '#default_value' => variable_get('flag_lists_create_lists', 0), + '#description' => t('Checking this adds a link to the create new list form.'), + ), + 'ops' => array( + '#type' => 'checkbox', + '#title' => t('Show edit and delete links'), + '#default_value' => variable_get('flag_lists_ops', 0), + '#description' => t('Checking this appends edit and delete links to each list name for users with access.'), + ), + 'include_flags' => array( + '#type' => 'checkbox', + '#title' => t('Include flag module flags'), + '#default_value' => variable_get('flag_lists_include_flags', 0), + '#description' => t('Checking this will append flag module flags to the list of lists.'), + ), + ); + break; + } + return $form; +} + +/** + * Implements hook_block_save(). + */ +function flag_lists_block_save($delta = '', $edit = array()) { + switch ($delta) { + case 'flag_lists': + variable_set('flag_lists_create_lists', $edit['create_lists']); + variable_set('flag_lists_ops', $edit['ops']); + variable_set('flag_lists_include_flags', $edit['include_flags']); + break; + } +} + +/** + * Implements hook_block_view(). + */ +function flag_lists_block_view($delta = '') { + $block = array(); + + switch ($delta) { + case 'flag_lists': + if (user_access('create flag lists')) { + $block = array( + 'subject' => t('My lists'), + 'content' => theme('flag_lists_list', array('node' => NULL, 'create' => variable_get('flag_lists_create_lists', 0), 'ops' =>variable_get('flag_lists_ops', 0), 'use_flags' => variable_get('flag_lists_include_flags', 0))), + ); + } + break; + case 'flag_lists_list': + if (user_access('create flag lists')) { + global $user; + $account = user_load($user->uid); + + $block = array( + 'subject' => t('My lists'), + 'content' => flag_lists_user_page($account), + ); + } + break; + } + return (!empty($block['content'])) ? $block : array(); +} + +/** + * Implementation of hook_user_delete(). + */ +function flag_lists_user_delete($account) { + // Remove personal flags by this user. + $num_deleted = db_delete('flag_lists_flags') + ->condition('uid', $account->uid) + ->execute(); +} + +/** + * Build a flag's messages. + */ +function flag_lists_set_messages(&$flag) { + // Get the parent flag. These are cached by the flag module. + $pflag = flag_get_flag(NULL, $flag->pfid); + $title = $flag->title; + $lists_name = variable_get('flag_lists_name', t('list')); + $flag->flag_short = $pflag->flag_short; + $flag->flag_long = $pflag->flag_long; + $flag->flag_message = $pflag->flag_message; + $flag->unflag_short = $pflag->unflag_short; + $flag->unflag_long = $pflag->unflag_long; + $flag->unflag_message = $pflag->unflag_message; +} + +/** + * Implementation of hook_flag_access(). + * + * Make sure a user can only see his/her own personal flags. + */ +function flag_lists_flag_access($flag, $entity_id, $action, $account) { + if (!empty($flag->module) && $flag->module == 'flag_lists') { + switch ($action) { + case 'flag': + case 'unflag': + $fid = db_select('flag_lists_flags', 'f') + ->fields('f') + ->condition('f.uid', $account->uid) + ->execute() + ->fetchField(); + if (!empty($fid)) { + return array('flag_lists' => TRUE); + } + else { + return array('flag_lists' => FALSE); + } + } +} +} + +/** + * Implementation of hook_link(). + */ +// There may be a better way to keep flag lists out of the links, but this +// works for now. @todo Find a better way to keep flags lists out of links. +function flag_lists_link_alter(&$links, $node) { + if (!variable_get('flag_lists_use_links', 1)) { + foreach ($links as $name => $link) { + if (stristr($name, 'flag-fl_')) { + unset($links[$name]); + } + } + } +} + +/** + * Implementation of hook_flag_alter(). + */ +function flag_lists_flag_alter(&$flag) { +} + +/** + * Implementation of hook_flag_delete(). + * + * This is not in flag yet. + */ +function flag_lists_flag_delete($flag) { + // Template flag is being deleted. Clean up our tables. + // Collect the sub-flag fids so we can delete counts and content records. + $results = db_select('flag_lists_flags', 'f') + ->fields('f', array('fid', 'name')) + ->condition('pfid', $flag->fid) + ->execute(); + foreach ($results as $fid) { + db_delete('flag_lists_counts') + ->condition('fid', $flag->fid) + ->execute(); + db_delete('flag_lists_content') + ->condition('fid', $flag->fid) + ->execute(); + } + + // flag_lists_types uses the template flag name, not our own fid. + db_delete('flag_lists_types') + ->condition('name', $flag->name) + ->execute(); + + // Now delete the sub-flags. + $num_deleted = db_delete('flag_lists_flags') + ->condition('pfid', $flag->fid) + ->execute(); + if (!empty($num_deleted)) { + drupal_set_message(t('The template flag "@title" and all its sub-flags have been deleted.', array('@title' => $flag->title))); + } +} + +/** + * Implementation of hook_views_api(). + */ +function flag_lists_views_api() { + return array( + 'api' => 2.0, + 'path' => drupal_get_path('module', 'flag_lists') . '/includes', + ); +} + +/** + * Helper function to test if a flag is owned by the current user, or current + * user can administer flags. + */ +function flag_lists_is_owner($action, $name) { + global $user; + if (user_access('administer flags')) { + return TRUE; + } + + // If we don't have an fid, then we have the flag name. + if (is_numeric($name)) { + $query = db_select('flag_lists_flags', 'f')->condition('fid', $name); + $query->addField('f', 'name'); + $name = $query->execute()->fetchField(); + } + + if (!user_access($action . ' own flag lists')) { + return FALSE; + } + if (db_select('flag_lists_flags', 'f')->fields('f')->condition('f.name', $name)->condition('f.uid', $user->uid)->countQuery()->execute()->fetchField()) { + return TRUE; + } + return FALSE; +} + +/** + * Get a single user's lists, and merge in flag module flags + */ +function flag_lists_get_user_flags($content_type = NULL, $account = NULL, $use_flags = FALSE) { + $flags = array(); + $lists = array(); + if (!isset($account)) { + $account = $GLOBALS['user']; + } + // Get flag lists flags + $query = db_select('flag_lists_flags', 'fl') + ->fields('fl') + ->condition('fl.uid', $account->uid); + $query->leftJoin('flag', 'f', 'fl.pfid = f.fid'); + $query->leftJoin('flag_lists_types', 'ft', 'ft.name = f.name'); + $query->addField('ft', 'type'); + if ($content_type) { + $query->condition('ft.type', $content_type); + } + + $result = $query->execute(); + foreach ($result as $row) { + if (!isset($lists[$row->name])) { + $lists[$row->name] = flag_flag::factory_by_row($row); + $lists[$row->name]->module = 'flag_lists'; + } + else { + $lists[$row->name]->types[] = $row->type; + } + } + // Get regular flags. + if ($use_flags) { + $flags = flag_get_flags('node', $content_type, $account); + + // Strip out any list templates + foreach ($flags as $key => $flag) { + if (stristr($flag->name, 'fl_template') !== FALSE) { + unset($flags[$key]); + } + } + } + + $flags = array_merge($lists, $flags); + return $flags; +} + +/** + * Theme function to return edit, delete links. + * + * @param $flag + * The flag whose links are being built. + */ +function theme_flag_lists_ops($variables) { + $flag = $variables['flag']; + + $links = array( + 'flags_edit' => array('title' => t('edit'), 'href' => 'flags/lists/edit/' . $flag->name, 'query' => drupal_get_destination()), + 'flags_delete' => array('title' => t('delete'), 'href' => 'flags/lists/delete/' . $flag->name, 'query' => drupal_get_destination()), + ); + return theme('links', array('links' => $links, 'attributes' => array('class' => 'flag_lists_ops'))); +} + +/** + * Theme a list of lists + * + * @param $node + * The listable node + * @param boolean $create + * Show the create list form. + * @param boolean $ops + * Show the edit / delete links for lists + * @param boolean $use_flags + * Show flags from the flag module + * @return + */ + +// @todo Separate out the code from the theming better. +function theme_flag_lists_list($variables) { + $node = $variables['node']; + $create = $variables['create']; + $ops = $variables['ops']; + $use_flags = $variables['use_flags']; + + $items = array(); + + // Make sure we have a node. + if (is_object($node) && user_access('create flag lists')) { + $content_type = $node->type; + $entity_id = $node->nid; + } + // Or at least confirm we are on a node page and use has access. + elseif (arg(0) == 'node' && is_numeric(arg(1)) && user_access('create flag lists')) { + $entity_id = arg(1); + $query = db_select('node')->condition('nid', $entity_id); + $query->addField('node', 'type'); + $content_type = $query->execute()->fetchField(); + } + else { + return; + } + + // Do we have a list template for this node type, or are we s + if (!flag_lists_template_exists($content_type) && !$use_flags) { + return; + } + + global $user; + if ($flags = flag_lists_get_user_flags($content_type, $user, $use_flags)) { + // Build the list of lists for this node. + foreach ($flags as $flag) { + if ($flag->module == 'flag_lists') { + $action = _flag_lists_is_flagged($flag, $entity_id, $user->uid, 0) ? 'unflag' : 'flag'; + } + else { + $action = $flag->is_flagged($entity_id) ? 'unflag' : 'flag';; + } + + // Do we need the ops? + if ($ops && $flag->module == 'flag_lists') { + $ops_links = theme('flag_lists_ops', array('flag' => $flag)); + $link = $flag->theme($action, $entity_id) . $ops_links; + } + else { + $link = $flag->theme($action, $entity_id); + } + + // If it's a list, fix the link. + if ($flag->module == 'flag_lists') { + flag_lists_fix_link($link, $action); + } + $items[] = $link; + } + } + if ($create && flag_lists_template_exists($content_type)) { + $items[] = l(t('Make a new @name', array('@name' => variable_get('flag_lists_name', t('list')))), 'flag-lists/add/' . $content_type, array('query' => drupal_get_destination())); + } + + // Return if nothing to display. + if (empty($items) || !count($items)) { + return; + } + + drupal_add_css(drupal_get_path('module', 'flag_lists') . '/theme/flag_lists.css'); + return theme('item_list', array('items' => $items, 'type' => 'ul', 'attributes' => array('class' => 'flag-lists-links'))); +} + + +// Do we still need this, and/or do we need our own cache? +/** + * Clear the flag cache. + * + * This is a less severe cache clear than provided by flag. All flag lists + * users must be authorized, so we don't need to flush the page cache. For now, + * flag lists titles won't be in the menu, so no need to clear that. + */ +function _flag_lists_clear_cache() { + // We're not using _flag_clear_cache because we probably don't need the menu + // rebuild and don't need to clear the page cache. + if (module_exists('views')) { + views_invalidate_cache(); + } +} + +/** + * Update ALL flag lists with settings form values. + */ +function flag_lists_rebuild() { + $flags = flag_lists_get_flags(); + foreach ($flags as $flag) { + flag_lists_set_messages($flag); + $flag->link_type = 'toggle'; + flag_lists_save($flag); + } +} + +/** + * Build array of all flag lists. + * + * @return If limit and header arguments are provided, the paged flags, otherwise + * an array of all flags. + */ +function flag_lists_get_flags($limit = NULL, $header = NULL) { + $flags = array(); + if ($limit) { + $query = db_select('flag_lists_flags', 'fl') + ->fields('fl') + ->groupBy('fl.fid') + ->extend('PagerDefault') + ->limit($limit); + $query->leftJoin('flag_types', 'ft', 'ft.fid = fl.pfid'); + $query->addExpression('GROUP_CONCAT(ft.type)', 'types'); + $result = $query->execute(); + } + else { + $query = db_select('flag_lists_flags', 'fl') + ->fields('fl') + ->groupBy('fl.fid'); + $query->leftJoin('flag_types', 'ft', 'ft.fid = fl.pfid'); + $query->addExpression('GROUP_CONCAT(ft.type)', 'types'); + $result = $query->execute(); + } + foreach ($result as $row) { + $flags[$row->name] = flag_flag::factory_by_row($row); + $flags[$row->name]->types = explode(',', $row->types); + $flags[$row->name]->uid = $row->uid; + } + return $flags; +} + +/** + * Get a specific flag. + * + * Using this instead of flag_get_flag() for performance. + */ +function flag_lists_get_flag($fid) { + // If we don't have an fid, then we have the flag name. + if (!is_numeric($fid)) { + $query = db_select('flag_lists_flags') + ->condition('name', $fid); + $query->addField('flag_lists_flags', 'fid'); + $fid = $query->execute()->fetchField(); + } + + $query = db_select('flag_lists_flags', 'fl') + ->fields('fl') + ->condition('fl.fid', $fid); + $query->leftJoin('flag_types', 'ft', 'ft.fid = fl.pfid'); + $query->addField('ft', 'type'); + $result = $query->execute(); + + foreach ($result as $row) { + if (!isset($flag->name)) { + $flag = flag_flag::factory_by_row($row); + } + else { + $flag->types[] = $row->type; + } + } + return $flag; +} + +/** + * Get all flagged content in a flag. + * + * Using this instead of flag_get_flagged_content() because we need to make sure that we use flag_lists_get_flags() + * + * @param + * The flag name for which to retrieve flagged content. + */ +function flag_lists_get_flagged_content($fid, $uid) { + $return = array(); + $flag = flag_lists_get_flag($fid); + + $result = db_select('flag_lists_content', 'f') + ->fields('f') + ->condition('f.fid', $flag->fid) + ->condition('f.uid', $uid) + ->execute(); + + foreach ($result as $row) { + $return[] = $row; + } + return $return; +} + + +/** + * Implementation of hook_flag_link(). + * + * When Flag uses a link type provided by this module, it will call this + * implementation of hook_flag_link(). It returns a single link's attributes, + * using the same structure as hook_link(). Note that "title" is provided by + * the Flag configuration if not specified here. + * + * @param $flag + * The full flag object of for the flag link being generated. + * @param $action + * The action this link will perform. Either 'flag' or 'unflag'. + * @param $entity_id + * The ID of the node, comment, user, or other object being flagged. + * @return + * An array defining properties of the link. + */ +function flag_lists_flag_link($flag, $action, $entity_id) { + return array(); +} + +/** + * Implementation of hook_flag_link_types(). + */ +function flag_lists_flag_link_types() { + return array( + 'fl_template' => array( + 'title' => t('Flag Lists toggle'), + 'description' => t('If you are creating a Flag lists template flag, you must select this link type.'), + ), + ); +} + + +function flag_lists_flag_default_flags($name = 'fl_template') { + // return array( + // array( + // 'api_version' => 2, + // 'name' => $name, + // 'module' => 'flag_lists', + // 'content_type' => 'node', + // 'global' => 0, + // 'show_on_page' => 0, + // 'show_on_teaser' => 0, + // 'show_on_form' => 0, + // // The following UI labels aren't wrapped in t() because they are written + // // to the DB in English. They are passed to t() later, thus allowing for + // // multilingual sites. + // 'title' => 'Flag lists template', + // 'flag_short' => 'Add to your [flag_lists:title] [flag_lists:term]', + // 'flag_long' => 'Add this post to your [flag_lists:title] [flag_lists:term]', + // 'flag_message' => 'This post has been added to your [flag_lists:title] [flag_lists:term]', + // 'unflag_short' => 'Remove this from your [flag_lists:title] [flag_lists:term]', + // 'unflag_long' => 'Remove this post from your [flag_lists:title] [flag_lists:term]', + // 'unflag_message' => 'This post has been removed from your [flag_lists:title] [flag_lists:term]', + // 'types' => array(), + // 'link_type' => 'toggle', + // ), + // ); + +$flags = array(); +// Exported flag: "Flag lists template". +$flags['fl_template'] = array( + 'entity_type' => 'node', + 'title' => 'Flag lists template', + 'global' => 0, + 'types' => array(), + 'flag_short' => 'Add to your [flag_lists:title] [flag_lists:term]', + 'flag_long' => 'Add this post to your [flag_lists:title] [flag_lists:term]', + 'flag_message' => 'This post has been added to your [flag_lists:title] [flag_lists:term]', + 'unflag_short' => 'Remove this from your [flag_lists:title] [flag_lists:term]', + 'unflag_long' => 'Remove this post from your [flag_lists:title] [flag_lists:term]', + 'unflag_message' => 'This post has been removed from your [flag_lists:title] [flag_lists:term]', + 'unflag_denied_text' => '', + 'link_type' => 'toggle', + 'weight' => 0, + 'api_version' => 3, + 'module' => 'flag_lists', + 'show_on_page' => 0, + 'show_on_teaser' => 0, + 'show_on_form' => 0, + 'status' => FALSE, + 'import_roles' => array( + 'flag' => array(), + 'unflag' => array(), + ), +); +return $flags; + + +} + +/** + * Saves a flag to the database. It is a wrapper around update($flag) and insert($flag). + */ +function flag_lists_save(&$flag, $account = NULL) { + if (!isset($account)) { + $account = $GLOBALS['user']; + } + + if (isset($flag->fid)) { + flag_lists_update($flag); + $flag->is_new = FALSE; + module_invoke_all('flag_lists', $flag, $account); + } + else { + flag_lists_insert($flag); + $flag->is_new = TRUE; + module_invoke_all('flag_lists', $flag, $account); + } + // Clear the page cache for anonymous users. +// cache_clear_all('*', 'cache_page', TRUE); +} + +/** + * Saves an existing flag to the database. Better use save($flag). + */ +function flag_lists_update($flag) { + $num_updated = db_update('flag_lists_flags') + ->fields(array( + 'title' => $flag->title, + 'name' => $flag->name, + 'options' => $flag->get_serialized_options($flag), + )) + ->condition('fid', $flag->fid) + ->execute(); +} + +/** + * Saves a new flag to the database. Better use save($flag). + */ +function flag_lists_insert($flag) { + $flag->fid = db_insert('flag_lists_flags') + ->fields(array( + 'pfid' => $flag->pfid, + 'uid' => $flag->uid, + 'entity_type' => $flag->entity_type, + 'name' => $flag->name, + 'title' => $flag->title, + 'options' => $flag->get_serialized_options($flag), + )) + ->execute(); + $flag->name = 'flag_lists_' . $flag->uid . '_' . $flag->fid; + flag_lists_update($flag); +} + +/** + * Delete a flag_lists flag. + * + */ +function flag_lists_fl_delete($flag, $account = NULL) { + if (!isset($account)) { + $account = $GLOBALS['user']; + } + + db_delete('flag_lists_counts')->condition('fid', $flag->fid)->execute(); + db_delete('flag_lists_content')->condition('fid', $flag->fid)->execute(); + db_delete('flag_lists_flags')->condition('fid', $flag->fid)->execute(); + + $flag->is_deleted = TRUE; + module_invoke_all('flag_lists', $flag, $account); + _flag_lists_clear_cache(); + drupal_set_message(t('The @name @title has been deleted.', array('@name' => variable_get('flag_lists_name', t('list')), '@title' => $flag->title))); +} + + +/** + * Menu callback for (un)flagging a node. + * + * Used both for the regular callback as well as the JS version. We use this + * instead of the flag module's because our flags are not in the flags table. + */ +function flag_lists_page($action = NULL, $flag_name = NULL, $entity_id = NULL) { + global $user; + + // Shorten up the variables that affect the behavior of this page. + $js = isset($_REQUEST['js']); + $token = $_REQUEST['token']; + + // Specifically $_GET to avoid getting the $_COOKIE variable by the same key. + $has_js = isset($_GET['has_js']); + + // Check the flag token, then perform the flagging. + if (!flag_check_token($token, $entity_id)) { + $error = t('Bad token. You seem to have followed an invalid link.'); + } + elseif ($user->uid == 0 && !$has_js) { + $error = t('You must have JavaScript and cookies enabled in your browser to flag content.'); + } + else { + if (empty($flag_name) || !($flag = flag_lists_get_flag($flag_name))) { + // Flag does not exist. + $error = t('You are not allowed to flag, or unflag, this content.'); + } + + // Identify it as ours. + $flag->module = 'flag_lists'; + flag_lists_do_flag($flag, $action, $entity_id); + } + + // If an error was received, set a message and exit. + if (isset($error)) { + if ($js) { + drupal_add_http_header('Content-Type', 'text/javascript; charset=utf-8'); + print drupal_to_js(array( + 'status' => FALSE, + 'errorMessage' => $error, + )); + exit; + } + else { + drupal_set_message($error); + drupal_access_denied(); + return; + } + } + + // If successful, return data according to the request type. + if ($js) { + drupal_add_http_header('Content-Type', 'text/javascript; charset=utf-8'); +// $flag = flag_lists_get_flag($flag_name); + // $flag->link_type = 'toggle'; + $sid = flag_get_sid($user->uid); + $new_action = _flag_lists_is_flagged($flag, $entity_id, $user->uid, $sid) ? 'unflag' : 'flag'; + $new_link = $flag->theme($new_action, $entity_id, array("after_flagging" => TRUE)); + flag_lists_fix_link($new_link, $new_action); + drupal_json_output(array( + 'status' => TRUE, + 'newLink' => $new_link, + // Further information for the benefit of custom JavaScript event handlers: + 'contentId' => $entity_id, + 'contentType' => $flag->content_type, + 'flagName' => $flag->name, + 'flagStatus' => $action, + )); + exit; + } + else { + $flag = flag_lists_get_flag($flag->fid); + drupal_set_message($flag->get_label($action . '_message', $entity_id)); + drupal_goto(); + } +} + +function flag_lists_fix_link(&$link, $action) { + // This is a hack to let us use our own flag/unflag callbacks without having + // to override $flag->theme and creating our own flag_link type. + $link = str_replace('/flag/' . $action . '/', '/flag-lists/' . $action . '/', $link); +} + + /** + * Flags, or unflags, an item. + * + * @param $action + * Either 'flag' or 'unflag'. + * @param $entity_id + * The ID of the item to flag or unflag. + * @param $account + * The user on whose behalf to flag. Leave empty for the current user. + * @param $skip_permission_check + * Flag the item even if the $account user doesn't have permission to do so. + * @return + * FALSE if some error occured (e.g., user has no permission, flag isn't + * applicable to the item, etc.), TRUE otherwise. + */ + function flag_lists_do_flag($flag, $action, $entity_id, $account = NULL, $skip_permission_check = FALSE) { + if (!isset($account)) { + $account = $GLOBALS['user']; + } + if (!$account) { + return FALSE; + } + if (!$skip_permission_check) { + if (!$flag->access($entity_id, $action, $account)) { + // User has no permission to flag/unflag this object. + return FALSE; + } + } + else { + // We are skipping permission checks. However, at a minimum we must make + // sure the flag applies to this content type: + if (!$flag->applies_to_content_id($entity_id)) { + return FALSE; + } + } + + // Clear various caches; We don't want code running after us to report + // wrong counts or false flaggings. +// flag_get_counts(NULL, NULL, TRUE); +// flag_get_user_flags(NULL, NULL, NULL, NULL, TRUE); + + // Find out which user id to use. + $uid = $flag->global ? 0 : $account->uid; + + $sid = flag_get_sid($uid); + // Anonymous users must always have a session id. + if ($sid == 0 && $account->uid == 0) { + return FALSE; + } + + // Perform the flagging or unflagging of this flag. We invoke hook_flag here + // because we do our own flagging. + $flagged = _flag_lists_is_flagged($flag, $entity_id, $uid, $sid); + if ($action == 'unflag') { + if ($flagged) { + $fcid = _flag_lists_unflag($flag, $entity_id, $uid, $sid); + module_invoke_all('flag', 'unflag', $flag, $entity_id, $account, $fcid); + } + } + elseif ($action == 'flag') { + if (!$flagged) { + $fcid = _flag_lists_flag($flag, $entity_id, $uid, $sid); + module_invoke_all('flag', 'flag', $flag, $entity_id, $account, $fcid); + } + } + + return TRUE; + } + + + /** + * Returns TRUE if a certain user has flagged this content. + * + * + * This method is similar to is_flagged() except that it does direct SQL and + * doesn't do caching. Use it when you want to not affect the cache, or to + * bypass it. + * + */ + function _flag_lists_is_flagged($flag, $entity_id, $uid, $sid) { + $query = db_select('flag_lists_content') + ->condition('fid', $flag->fid) + ->condition('uid', $uid) + ->condition('sid', $sid) + ->condition('entity_id', $entity_id); + $query->addField('flag_lists_content', 'fid'); + return $query->execute()->fetchField(); + } + + /** + * A low-level method to flag content. + * + * You probably shouldn't call this raw private method: call the + * flag_lists_do_flag() function instead. + * + */ + function _flag_lists_flag($flag, $entity_id, $uid, $sid) { + $fcid = db_insert('flag_lists_content') + ->fields(array( + 'fid' => $flag->fid, + 'entity_type' => $flag->entity_type, + 'entity_id' => $entity_id, + 'uid' => $uid, + 'sid' => $sid, + 'timestamp' => REQUEST_TIME, + )) + ->execute(); + + _flag_lists_update_count($flag, $entity_id); + return $fcid; + } + + /** + * A low-level method to unflag content. + * + * You probably shouldn't call this raw private method: call the + * flag_lists_do_flag() function instead. + * + */ + function _flag_lists_unflag($flag, $entity_id, $uid, $sid) { + $query = db_select('flag_lists_content') + ->condition('fid', $flag->fid) + ->condition('entity_id', $entity_id) + ->condition('uid', $uid) + ->condition('sid', $sid); + $query->addField('flag_lists_content', 'fcid'); + $fcid = $query->execute()->fetchField(); + if ($fcid) { + db_delete('flag_lists_content') + ->condition('fcid', $fcid) + ->execute(); + _flag_lists_update_count($flag, $entity_id); + } + return $fcid; + } + + /** + * Updates the flag count for this content + */ + function _flag_lists_update_count($flag, $entity_id) { + $count = db_select('flag_lists_content', 'f') + ->fields('f') + ->condition('fid', $flag->fid) + ->condition('entity_id', $entity_id) + ->countQuery() + ->execute() + ->fetchField(); + + if (empty($count)) { + $num_deleted = db_delete('flag_lists_counts') + ->condition('fid', $flag->fid) + ->condition('entity_id', $entity_id) + ->execute(); + } + else { + $num_updated = db_update('flag_lists_counts') + ->fields(array( + 'count' => $count, + )) + ->condition('fid', $flag->fid) + ->condition('entity_id', $entity_id) + ->execute(); + if (empty($num_updated)) { + db_insert('flag_lists_counts') + ->fields(array( + 'fid' => $flag->fid, + 'entity_type' => $flag->entity_type, + 'entity_id' => $entity_id, + 'count' => $count, + )) + ->execute(); + } + } + } + +/** + * Checks for a list template for a content type. + */ +function flag_lists_template_exists($type) { + $query = db_select('flag_lists_types') + ->condition('type', $type); + $query->addField('flag_lists_types', 'type'); + $exists = $query->execute()->fetchField(); + if (!empty($exists)) { + return TRUE; + } + return FALSE; +} + +/** + * Checks for a list title by node type. + */ +function flag_lists_title_exists($title, $type) { + return db_query("SELECT COUNT(flf.fid) FROM {flag_lists_flags} flf LEFT JOIN {flag_types} ft ON flf.pfid=ft.fid WHERE flf.title=:title AND ft.type=:type AND flf.uid=:uid", array(':title' => $title, ':type' => $type, ':uid' => $GLOBALS['user']->uid))->fetchField(); +} + +/** + * Get a list of template flag names. + */ +function flag_lists_get_templates() { + $templates = array(); + $result = db_select('flag_lists_types', 'f') + ->fields('f', array( + 'name' + )) + ->distinct() + ->execute(); + foreach ($result as $obj) { + $templates[] = flag_get_flag($obj->name); + } + return $templates; +} + + +/** + * Implements hook_token_info(). + */ +function flag_lists_token_info() { + $type = array( + 'name' => t('Flag lists'), + 'description' => t('Tokens related to flag lists.'), + 'needs-data' => 'flag_lists', + ); + + $flag_lists['term'] = array( + 'name' => t("Term"), + 'description' => t("The terminology used to name the lists, such as list, wishlist, favorites, etc."), + ); + $flag_lists['title'] = array( + 'name' => t("Title"), + 'description' => t("The title of the list."), + ); + + return array( + 'types' => array('flag_lists' => $type), + 'tokens' => array('flag_lists' => $flag_lists), + ); +} + +/** + * Implements hook_tokens(). + */ +function flag_lists_tokens($type, $tokens, array $data = array(), array $options = array()) { + $replacements = array(); + + if ($type == 'flag_lists' && !empty($data['flag_lists'])) { + $flag_list = $data['flag_lists']; + foreach ($tokens as $name => $original) { + switch ($name) { + case 'title': + $replacements[$original] = $flag_list->title; + break; + case 'term': + $replacements[$original] = variable_get('flag_lists_name', t('list')); + break; + } + } + } + return $replacements; +} + +/** + * Preprocess link title and text for the flag.tpl.php + * + * This seems to be the only place to do this + */ +function flag_lists_preprocess_flag(&$variables) { + if (module_exists('token') && !empty($variables['flag']->module) && $variables['flag']->module == 'flag_lists') { + if (!empty($variables['link_text'])) { + $variables['link_text'] = token_replace($variables['link_text'], array('flag_lists' => $variables['flag'])); + } + if (!empty($variables['link_title'])) { + $variables['link_title'] = token_replace($variables['link_title'], array('flag_lists' => $variables['flag'])); + } + if (!empty($variables['message_text'])) { + $variables['message_text'] = token_replace($variables['message_text'], array('flag_lists' => $variables['flag'])); + } + } +} + +/** + * Implements hook_views_form_substitutions(). + */ +function flag_lists_views_form_substitutions() { + // Views check_plains the column label, so Flag lists needs to do the same + // in order for the replace operation to succeed. + $select_all_placeholder = check_plain(''); + $select_all = array( + '#type' => 'checkbox', + '#default_value' => FALSE, + '#attributes' => array('class' => array('flo-table-select-all')), + ); + return array( + $select_all_placeholder => drupal_render($select_all), + ); +} diff --git a/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists.views.inc b/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists.views.inc new file mode 100644 index 00000000..01d68668 --- /dev/null +++ b/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists.views.inc @@ -0,0 +1,332 @@ + array( + 'path' => drupal_get_path('module', 'flag_lists') . '/includes', + ), + 'handlers' => array( + 'flag_lists_handler_field_list' => array( + 'parent' => 'views_handler_field', + 'file' => 'flag_lists_handler_field_list.inc', + ), + 'flag_lists_handler_field_template' => array( + 'parent' => 'views_handler_field', + 'file' => 'flag_lists_handler_field_template.inc', + ), + 'flag_lists_handler_field_list_edit' => array( + 'parent' => 'views_handler_field', + 'file' => 'flag_lists_handler_field_list_edit.inc', + ), + 'flag_lists_handler_field_list_delete' => array( + 'parent' => 'views_handler_field', + 'file' => 'flag_lists_handler_field_list_delete.inc', + ), + 'flag_lists_handler_field_template_types' => array( + 'parent' => 'views_handler_field_prerender_list', + 'file' => 'flag_lists_handler_field_template_types.inc', + ), + 'flag_lists_handler_filter_template' => array( + 'parent' => 'views_handler_filter_in_operator', + 'file' => 'flag_lists_handler_filter_template.inc', + ), + 'flag_lists_handler_argument_fid' => array( + 'parent' => 'views_handler_argument_numeric', + 'file' => 'flag_lists_handler_argument_fid.inc', + ), + ), + ); +} + + +/** + * Implementation of hook_views_data_alter(). + */ +function flag_lists_views_data_alter(&$data) { + + // We want access to users table fields. + $data['users']['table']['join']['flag_lists_flags'] = array( + 'left_field' => 'uid', + 'field' => 'uid', + ); + + // We need fid and name form flags' data, and join. + $data['flags'] = array( + 'table' => array( + 'group' => t('Flag'), + 'join' => array( + 'flag_lists_flags' => array( + 'left_field' => 'pfid', + 'field' => 'fid', + ), + ), + ), + 'fid' => array( + 'title' => t('Flag fid'), + 'help' => t('Flag id'), + 'field' => array( + 'click sortable' => TRUE, + ), + 'filter' => array( + 'handler' => 'views_handler_filter_numeric', + 'allow empty' => TRUE, + ), + 'argument' => array( + 'handler' => 'views_handler_argument_numeric', + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + ), + 'name' => array( + 'title' => t('Template name'), + 'help' => t('The name of the list template flag'), + 'field' => array( + 'handler' => 'flag_lists_handler_field_template', + 'click sortable' => TRUE, + ), + 'filter' => array( + 'handler' => 'flag_lists_handler_filter_template', + 'allow empty' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + ), + ); + + // Add the checkbox for flagging nodes VBO style, minus batch API + foreach (entity_get_info() as $entity_type => $info) { + if (isset($info['base table']) && $info['base table'] == 'node' && isset($data[$info['base table']])) { + $data[$info['base table']]['flag_lists_ops'] = array( + 'title' => t('Flag lists operations'), + 'help' => t('Provide a checkbox to select the row for flag lists operations.'), + 'real field' => $info['entity keys']['id'], + 'field' => array( + 'handler' => 'flag_lists_handler_field_ops', + 'click sortable' => FALSE, + ), + ); + break; + } + } +} + +/** + * Implementation of hook_views_data(). + */ +function flag_lists_views_data() { + $data = array(); + + // flag_lists_flags data + $data['flag_lists_flags'] = array( + 'table' => array( + 'base' => array( + 'field' => 'fid', + 'title' => t('Flag lists'), + 'help' => 'User created flag lists', + 'weight' => 10, + 'database' => 'default', + ), + 'group' => t('Flag lists'), + 'join' => array( + 'node' => array( + 'table' => 'flag_lists_flags', + 'left_table' => 'flag_lists_content', + 'left_field' => 'fid', + 'field' => 'fid', + ), + ), + ), + 'fid' => array( + 'title' => t('fid'), + 'help' => t('Flag list id, required for Flag lists operationis\'s "unflag" action.'), + 'field' => array( + 'handler' => 'flag_lists_handler_field_list', + 'click sortable' => TRUE, + ), + 'filter' => array( + 'handler' => 'views_handler_filter_numeric', + 'allow empty' => TRUE, + ), + 'argument' => array( + 'handler' => 'flag_lists_handler_argument_fid', + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + ), + 'pfid' => array( + 'title' => t('pfid'), + 'help' => t('Template flag id'), + 'field' => array( + 'handler' => 'flag_lists_handler_field_pfid', + 'click sortable' => TRUE, + ), + 'filter' => array( + 'handler' => 'views_handler_filter_numeric', + 'allow empty' => TRUE, + ), + 'argument' => array( + 'handler' => 'views_handler_argument_numeric', + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + ), + + 'uid' => array( + 'title' => t('Uid'), + 'help' => t('The list owner\'s uid'), // The help that appears on the UI, + 'field' => array( + 'handler' => 'views_handler_field_user', + 'click sortable' => TRUE, + ), + 'argument' => array( + 'handler' => 'views_handler_argument_user_uid', + 'name field' => 'name', // display this field in the summary + ), + 'filter' => array( + 'title' => t('Name'), + 'handler' => 'views_handler_filter_user_name', + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + ), + 'name' => array( + 'title' => t('machine name'), + 'help' => t('Machine name of the list'), + 'field' => array( + 'handler' => 'flag_lists_handler_field_list', + 'click sortable' => TRUE, + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + 'allow empty' => TRUE, + ), + 'argument' => array( + 'handler' => 'views_handler_argument_string', + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + ), + 'title' => array( + 'title' => t('List title'), + 'help' => t('Title of the list'), + 'field' => array( + 'click sortable' => TRUE, + 'handler' => 'flag_lists_handler_field_list', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + 'allow empty' => TRUE, + ), + 'argument' => array( + 'handler' => 'views_handler_argument_string', + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + ), + 'edit_list' => array( + 'field' => array( + 'title' => t('Edit link'), + 'help' => t('Link to edit the list title'), + 'handler' => 'flag_lists_handler_field_list_edit', + ), + ), + 'delete_list' => array( + 'field' => array( + 'title' => t('Delete link'), + 'help' => t('Link to delete the list'), + 'handler' => 'flag_lists_handler_field_list_delete', + ), + ), + ); + + // Flag_lists_content data + + $data['flag_lists_content'] = array( + 'table' => array( + 'join' => array( + 'node' => array( + 'left_field' => 'nid', + 'field' => 'content_id', + ), + ), + 'group' => t('Flag lists'), + ), + 'uid' => array( + 'relationship' => array( + 'title' => t('User'), + 'help' => t('The user who listed this node'), + 'base' => 'users', + 'handler' => 'views_handler_relationship', + 'label' => t('List user'), + ), + ), + 'content_id' => array( + 'relationship' => array( + 'title' => t('Node'), + 'help' => t('The node that has been listed'), + 'base' => 'node', + 'handler' => 'views_handler_relationship', + 'label' => t('Listed content'), + ), + ), + 'timestamp' => array( + 'title' => t('Time listed'), + 'help' => t('The time this node was listed'), + 'field' => array( + 'handler' => 'views_handler_field_date', + 'click sortable' => TRUE, + ), + 'filter' => array( + 'handler' => 'views_handler_filter_numeric', + 'allow empty' => TRUE, + ), + 'argument' => array( + 'handler' => 'views_handler_argument_numeric', + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + ), + ); + + // Flag_lists_types data + + $data['flag_lists_types'] = array( + 'table' => array( + 'group' => t('Flag lists'), + 'join' => array( + 'flag_lists_flags' => array( + 'table' => 'flag_lists_types', + 'type' => 'INNER', + 'left_table' => 'flags', + 'left_field' => 'name', + 'field' => 'name', + ), + ), + ), + 'type' => array( + 'title' => t('Template types'), + 'help' => t('Node types that can be listed by lists using this template'), + 'field' => array( + 'click sortable' => FALSE, + 'handler' => 'flag_lists_handler_field_template_types', + ), + ), + ); + return $data; +} diff --git a/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists.views_default.inc b/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists.views_default.inc new file mode 100644 index 00000000..6a2a59f5 --- /dev/null +++ b/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists.views_default.inc @@ -0,0 +1,864 @@ +name = 'flag_lists'; + $view->description = 'Flag lists'; + $view->tag = ''; + $view->view_php = ''; + $view->base_table = 'flag_lists_flags'; + $view->is_cacheable = FALSE; + $view->api_version = 2; + $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ + $handler = $view->new_display('default', 'Defaults', 'default'); + $handler->override_option('fields', array( + 'title' => array( + 'label' => 'List', + 'alter' => array( + 'alter_text' => 0, + 'text' => '', + 'make_link' => 0, + 'path' => '', + 'link_class' => '', + 'alt' => '', + 'prefix' => '', + 'suffix' => '', + 'target' => '', + 'help' => '', + 'trim' => 0, + 'max_length' => '', + 'word_boundary' => 1, + 'ellipsis' => 1, + 'html' => 0, + 'strip_tags' => 0, + ), + 'empty' => '', + 'hide_empty' => 0, + 'empty_zero' => 0, + 'link_to_list' => 1, + 'exclude' => 0, + 'id' => 'title', + 'table' => 'flag_lists_flags', + 'field' => 'title', + 'relationship' => 'none', + ), + 'name' => array( + 'label' => 'Owner', + 'alter' => array( + 'alter_text' => 0, + 'text' => '', + 'make_link' => 0, + 'path' => '', + 'link_class' => '', + 'alt' => '', + 'prefix' => '', + 'suffix' => '', + 'target' => '', + 'help' => '', + 'trim' => 0, + 'max_length' => '', + 'word_boundary' => 1, + 'ellipsis' => 1, + 'html' => 0, + 'strip_tags' => 0, + ), + 'empty' => '', + 'hide_empty' => 0, + 'empty_zero' => 0, + 'link_to_user' => 1, + 'overwrite_anonymous' => 0, + 'anonymous_text' => '', + 'exclude' => 0, + 'id' => 'name', + 'table' => 'users', + 'field' => 'name', + 'relationship' => 'none', + ), + 'edit_list' => array( + 'label' => 'Operations', + 'alter' => array( + 'alter_text' => 0, + 'text' => '', + 'make_link' => 0, + 'path' => '', + 'link_class' => '', + 'alt' => '', + 'prefix' => '', + 'suffix' => '', + 'target' => '', + 'help' => '', + 'trim' => 0, + 'max_length' => '', + 'word_boundary' => 1, + 'ellipsis' => 1, + 'html' => 0, + 'strip_tags' => 0, + ), + 'empty' => '', + 'hide_empty' => 0, + 'empty_zero' => 0, + 'text' => 'edit', + 'exclude' => 0, + 'id' => 'edit_list', + 'table' => 'flag_lists_flags', + 'field' => 'edit_list', + 'relationship' => 'none', + ), + 'delete_list' => array( + 'label' => 'Delete link', + 'alter' => array( + 'alter_text' => 0, + 'text' => '', + 'make_link' => 0, + 'path' => '', + 'link_class' => '', + 'alt' => '', + 'prefix' => '', + 'suffix' => '', + 'target' => '', + 'help' => '', + 'trim' => 0, + 'max_length' => '', + 'word_boundary' => 1, + 'ellipsis' => 1, + 'html' => 0, + 'strip_tags' => 0, + ), + 'empty' => '', + 'hide_empty' => 0, + 'empty_zero' => 0, + 'text' => '', + 'exclude' => 0, + 'id' => 'delete_list', + 'table' => 'flag_lists_flags', + 'field' => 'delete_list', + 'relationship' => 'none', + ), + 'name_2' => array( + 'label' => 'Edit template', + 'alter' => array( + 'alter_text' => 0, + 'text' => '', + 'make_link' => 0, + 'path' => '', + 'link_class' => '', + 'alt' => '', + 'prefix' => '', + 'suffix' => '', + 'target' => '', + 'help' => '', + 'trim' => 0, + 'max_length' => '', + 'word_boundary' => 0, + 'ellipsis' => 0, + 'html' => 0, + 'strip_tags' => 0, + ), + 'empty' => '', + 'hide_empty' => 0, + 'empty_zero' => 0, + 'link_to_template' => 1, + 'exclude' => 0, + 'link_to_list' => FALSE, + 'id' => 'name_2', + 'table' => 'flags', + 'field' => 'name', + 'relationship' => 'none', + ), + 'type' => array( + 'label' => 'Template types', + 'alter' => array( + 'alter_text' => 0, + 'text' => '', + 'make_link' => 0, + 'path' => '', + 'link_class' => '', + 'alt' => '', + 'prefix' => '', + 'suffix' => '', + 'target' => '', + 'help' => '', + 'trim' => 0, + 'max_length' => '', + 'word_boundary' => 1, + 'ellipsis' => 1, + 'html' => 0, + 'strip_tags' => 0, + ), + 'empty' => '', + 'hide_empty' => 0, + 'empty_zero' => 0, + 'type' => 'separator', + 'separator' => ', ', + 'exclude' => 0, + 'id' => 'type', + 'table' => 'flag_lists_types', + 'field' => 'type', + 'relationship' => 'none', + ), + )); + $handler->override_option('filters', array( + 'title' => array( + 'operator' => 'contains', + 'value' => '', + 'group' => '0', + 'exposed' => TRUE, + 'expose' => array( + 'use_operator' => 0, + 'operator' => 'title_op', + 'identifier' => 'title', + 'label' => 'List title', + 'optional' => 1, + 'remember' => 1, + ), + 'case' => 0, + 'id' => 'title', + 'table' => 'flag_lists_flags', + 'field' => 'title', + 'relationship' => 'none', + ), + 'uid' => array( + 'operator' => 'in', + 'value' => '', + 'group' => '0', + 'exposed' => TRUE, + 'expose' => array( + 'use_operator' => 0, + 'operator' => 'uid_op', + 'identifier' => 'uid', + 'label' => 'Owner', + 'optional' => 1, + 'remember' => 1, + 'reduce' => 0, + ), + 'id' => 'uid', + 'table' => 'flag_lists_flags', + 'field' => 'uid', + 'relationship' => 'none', + ), + 'name' => array( + 'operator' => 'in', + 'value' => array(), + 'group' => '0', + 'exposed' => TRUE, + 'expose' => array( + 'use_operator' => 0, + 'operator' => 'name_op', + 'identifier' => 'name', + 'label' => 'Template name', + 'optional' => 1, + 'single' => 1, + 'remember' => 0, + 'reduce' => 0, + ), + 'id' => 'name', + 'table' => 'flags', + 'field' => 'name', + 'relationship' => 'none', + ), + )); + $handler->override_option('access', array( + 'type' => 'perm', + 'perm' => 'administer flags', + )); + $handler->override_option('cache', array( + 'type' => 'none', + )); + $handler->override_option('items_per_page', 25); + $handler->override_option('use_pager', '1'); + $handler->override_option('style_plugin', 'table'); + $handler->override_option('style_options', array( + 'grouping' => '', + 'override' => 1, + 'sticky' => 0, + 'order' => 'asc', + 'columns' => array( + 'title' => 'title', + 'name' => 'name', + 'edit_list' => 'edit_list', + 'delete_list' => 'edit_list', + 'name_2' => 'name_2', + ), + 'info' => array( + 'title' => array( + 'sortable' => 1, + 'separator' => '', + ), + 'name' => array( + 'sortable' => 1, + 'separator' => '', + ), + 'edit_list' => array( + 'separator' => ' ', + ), + 'delete_list' => array( + 'separator' => '', + ), + 'name_2' => array( + 'sortable' => 0, + 'separator' => '', + ), + ), + 'default' => 'title', + )); + $views[$view->name] = $view; + + $view = new view; + $view->name = 'flag_lists_content'; + $view->description = 'Flag lists listed content'; + $view->tag = ''; + $view->view_php = ''; + $view->base_table = 'node'; + $view->is_cacheable = FALSE; + $view->api_version = 2; + $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ + $handler = $view->new_display('default', 'Defaults', 'default'); + $handler->override_option('relationships', array( + 'entity_id' => array( + 'label' => 'Listed content', + 'required' => 1, + 'id' => 'entity_id', + 'table' => 'flag_lists_content', + 'field' => 'entity_id', + 'relationship' => 'none', + ), + )); + $handler->override_option('fields', array( + 'title' => array( + 'label' => 'Node Title', + 'alter' => array( + 'alter_text' => 0, + 'text' => '', + 'make_link' => 0, + 'path' => '', + 'link_class' => '', + 'alt' => '', + 'prefix' => '', + 'suffix' => '', + 'target' => '', + 'help' => '', + 'trim' => 0, + 'max_length' => '', + 'word_boundary' => 1, + 'ellipsis' => 1, + 'html' => 0, + 'strip_tags' => 0, + ), + 'empty' => '', + 'hide_empty' => 0, + 'empty_zero' => 0, + 'link_to_node' => 1, + 'exclude' => 0, + 'id' => 'title', + 'table' => 'node', + 'field' => 'title', + 'relationship' => 'none', + ), + 'title_1' => array( + 'label' => 'List title', + 'alter' => array( + 'alter_text' => 0, + 'text' => '', + 'make_link' => 0, + 'path' => '', + 'link_class' => '', + 'alt' => '', + 'prefix' => '', + 'suffix' => '', + 'target' => '', + 'help' => '', + 'trim' => 0, + 'max_length' => '', + 'word_boundary' => 1, + 'ellipsis' => 1, + 'html' => 0, + 'strip_tags' => 0, + ), + 'empty' => '', + 'hide_empty' => 0, + 'empty_zero' => 0, + 'link_to_list' => 1, + 'exclude' => 0, + 'id' => 'title_1', + 'table' => 'flag_lists_flags', + 'field' => 'title', + 'relationship' => 'none', + ), + 'name' => array( + 'label' => 'Name', + 'alter' => array( + 'alter_text' => 0, + 'text' => '', + 'make_link' => 0, + 'path' => '', + 'link_class' => '', + 'alt' => '', + 'prefix' => '', + 'suffix' => '', + 'target' => '', + 'help' => '', + 'trim' => 0, + 'max_length' => '', + 'word_boundary' => 1, + 'ellipsis' => 1, + 'html' => 0, + 'strip_tags' => 0, + ), + 'empty' => '', + 'hide_empty' => 0, + 'empty_zero' => 0, + 'link_to_user' => 1, + 'overwrite_anonymous' => 0, + 'anonymous_text' => '', + 'exclude' => 0, + 'id' => 'name', + 'table' => 'users', + 'field' => 'name', + 'relationship' => 'uid', + ), + 'timestamp' => array( + 'label' => 'Time listed', + 'alter' => array( + 'alter_text' => 0, + 'text' => '', + 'make_link' => 0, + 'path' => '', + 'link_class' => '', + 'alt' => '', + 'prefix' => '', + 'suffix' => '', + 'target' => '', + 'help' => '', + 'trim' => 0, + 'max_length' => '', + 'word_boundary' => 1, + 'ellipsis' => 1, + 'html' => 0, + 'strip_tags' => 0, + ), + 'empty' => '', + 'hide_empty' => 0, + 'empty_zero' => 0, + 'date_format' => 'small', + 'custom_date_format' => '', + 'exclude' => 0, + 'id' => 'timestamp', + 'table' => 'flag_lists_content', + 'field' => 'timestamp', + 'relationship' => 'none', + ), + )); + $handler->override_option('filters', array( + 'status' => array( + 'operator' => '=', + 'value' => '1', + 'group' => '0', + 'exposed' => FALSE, + 'expose' => array( + 'operator' => FALSE, + 'label' => '', + ), + 'id' => 'status', + 'table' => 'node', + 'field' => 'status', + 'relationship' => 'none', + ), + )); + $handler->override_option('access', array( + 'type' => 'perm', + 'perm' => 'view flag lists', + )); + $handler->override_option('cache', array( + 'type' => 'none', + )); + $handler->override_option('items_per_page', 25); + $handler->override_option('use_pager', '1'); + $handler->override_option('style_plugin', 'table'); + $handler->override_option('style_options', array( + 'grouping' => '', + 'override' => 1, + 'sticky' => 0, + 'order' => 'desc', + 'columns' => array( + 'title' => 'title', + 'title_1' => 'title_1', + 'name' => 'name', + 'timestamp' => 'timestamp', + ), + 'info' => array( + 'title' => array( + 'sortable' => 1, + 'separator' => '', + ), + 'title_1' => array( + 'sortable' => 1, + 'separator' => '', + ), + 'name' => array( + 'sortable' => 1, + 'separator' => '', + ), + 'timestamp' => array( + 'sortable' => 1, + 'separator' => '', + ), + ), + 'default' => 'timestamp', + )); + $views[$view->name] = $view; + + $view = new view; + $view->name = 'flag_lists_user_lists'; + $view->description = 'Flag lists user lists'; + $view->tag = ''; + $view->view_php = ''; + $view->base_table = 'flag_lists_flags'; + $view->is_cacheable = FALSE; + $view->api_version = 2; + $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ + $handler = $view->new_display('default', 'Defaults', 'default'); + $handler->override_option('fields', array( + 'title' => array( + 'label' => 'List', + 'alter' => array( + 'alter_text' => 0, + 'text' => '', + 'make_link' => 0, + 'path' => '', + 'link_class' => '', + 'alt' => '', + 'prefix' => '', + 'suffix' => '', + 'target' => '', + 'help' => '', + 'trim' => 0, + 'max_length' => '', + 'word_boundary' => 1, + 'ellipsis' => 1, + 'html' => 0, + 'strip_tags' => 0, + ), + 'empty' => '', + 'hide_empty' => 0, + 'empty_zero' => 0, + 'link_to_list' => 1, + 'exclude' => 0, + 'id' => 'title', + 'table' => 'flag_lists_flags', + 'field' => 'title', + 'relationship' => 'none', + ), + 'edit_list' => array( + 'label' => 'Edit link', + 'alter' => array( + 'alter_text' => 0, + 'text' => '', + 'make_link' => 0, + 'path' => '', + 'link_class' => '', + 'alt' => '', + 'prefix' => '', + 'suffix' => '', + 'target' => '', + 'help' => '', + 'trim' => 0, + 'max_length' => '', + 'word_boundary' => 1, + 'ellipsis' => 1, + 'html' => 0, + 'strip_tags' => 0, + ), + 'empty' => '', + 'hide_empty' => 0, + 'empty_zero' => 0, + 'text' => 'Edit', + 'exclude' => 0, + 'id' => 'edit_list', + 'table' => 'flag_lists_flags', + 'field' => 'edit_list', + 'relationship' => 'none', + ), + 'delete_list' => array( + 'label' => 'Delete link', + 'alter' => array( + 'alter_text' => 0, + 'text' => '', + 'make_link' => 0, + 'path' => '', + 'link_class' => '', + 'alt' => '', + 'prefix' => '', + 'suffix' => '', + 'target' => '', + 'help' => '', + 'trim' => 0, + 'max_length' => '', + 'word_boundary' => 1, + 'ellipsis' => 1, + 'html' => 0, + 'strip_tags' => 0, + ), + 'empty' => '', + 'hide_empty' => 0, + 'empty_zero' => 0, + 'text' => '', + 'exclude' => 0, + 'id' => 'delete_list', + 'table' => 'flag_lists_flags', + 'field' => 'delete_list', + 'relationship' => 'none', + ), + )); + $handler->override_option('arguments', array( + 'uid' => array( + 'default_action' => 'not found', + 'style_plugin' => 'default_summary', + 'style_options' => array(), + 'wildcard' => 'all', + 'wildcard_substitution' => 'All', + 'title' => '%1\'s lists', + 'breadcrumb' => '', + 'default_argument_type' => 'fixed', + 'default_argument' => '', + 'validate_type' => 'none', + 'validate_fail' => 'not found', + 'break_phrase' => 0, + 'not' => 0, + 'id' => 'uid', + 'table' => 'flag_lists_flags', + 'field' => 'uid', + 'validate_user_argument_type' => 'uid', + 'validate_user_roles' => array( + '2' => 0, + ), + 'relationship' => 'none', + 'default_options_div_prefix' => '', + 'default_argument_fixed' => '', + 'default_argument_user' => 0, + 'default_argument_php' => '', + 'validate_argument_node_type' => array( + 'page' => 0, + 'story' => 0, + ), + 'validate_argument_node_access' => 0, + 'validate_argument_nid_type' => 'nid', + 'validate_argument_vocabulary' => array(), + 'validate_argument_type' => 'tid', + 'validate_argument_transform' => 0, + 'validate_user_restrict_roles' => 0, + 'validate_argument_node_flag_name' => '*relationship*', + 'validate_argument_node_flag_test' => 'flaggable', + 'validate_argument_node_flag_id_type' => 'id', + 'validate_argument_user_flag_name' => '*relationship*', + 'validate_argument_user_flag_test' => 'flaggable', + 'validate_argument_user_flag_id_type' => 'id', + 'validate_argument_php' => '', + ), + )); + $handler->override_option('access', array( + 'type' => 'perm', + 'perm' => 'view flag lists', + )); + $handler->override_option('cache', array( + 'type' => 'none', + )); + $handler->override_option('items_per_page', 25); + $handler->override_option('use_pager', '1'); + $handler->override_option('style_plugin', 'table'); + $handler->override_option('style_options', array( + 'grouping' => '', + 'override' => 1, + 'sticky' => 0, + 'order' => 'asc', + 'columns' => array( + 'title' => 'title', + 'name' => 'name', + ), + 'info' => array( + 'title' => array( + 'sortable' => 1, + 'separator' => '', + ), + 'name' => array( + 'sortable' => 1, + 'separator' => '', + ), + ), + 'default' => 'title', + )); + $views[$view->name] = $view; + + $view = new view; + $view->name = 'flag_lists_user_list'; + $view->description = 'Flag lists - one of a user\'s lists'; + $view->tag = ''; + $view->view_php = ''; + $view->base_table = 'node'; + $view->is_cacheable = FALSE; + $view->api_version = 2; + $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ + $handler = $view->new_display('default', 'Defaults', 'default'); + $handler->override_option('fields', array( + 'title' => array( + 'label' => '', + 'alter' => array( + 'alter_text' => 0, + 'text' => '', + 'make_link' => 0, + 'path' => '', + 'link_class' => '', + 'alt' => '', + 'prefix' => '', + 'suffix' => '', + 'target' => '', + 'help' => '', + 'trim' => 0, + 'max_length' => '', + 'word_boundary' => 1, + 'ellipsis' => 1, + 'html' => 0, + 'strip_tags' => 0, + ), + 'empty' => '', + 'hide_empty' => 0, + 'empty_zero' => 0, + 'link_to_node' => 1, + 'exclude' => 0, + 'id' => 'title', + 'table' => 'node', + 'field' => 'title', + 'relationship' => 'none', + ), + )); + $handler->override_option('sorts', array( + 'timestamp' => array( + 'order' => 'DESC', + 'id' => 'timestamp', + 'table' => 'flag_lists_content', + 'field' => 'timestamp', + 'relationship' => 'none', + ), + )); + $handler->override_option('arguments', array( + 'fid' => array( + 'default_action' => 'not found', + 'style_plugin' => 'default_summary', + 'style_options' => array(), + 'wildcard' => 'all', + 'wildcard_substitution' => 'All', + 'title' => '%1', + 'breadcrumb' => '', + 'default_argument_type' => 'fixed', + 'default_argument' => '', + 'validate_type' => 'none', + 'validate_fail' => 'not found', + 'break_phrase' => 0, + 'not' => 0, + 'id' => 'fid', + 'table' => 'flag_lists_flags', + 'field' => 'fid', + 'validate_user_argument_type' => 'uid', + 'validate_user_roles' => array( + '2' => 0, + '3' => 0, + '4' => 0, + ), + 'relationship' => 'none', + 'default_options_div_prefix' => '', + 'default_argument_fixed' => '', + 'default_argument_user' => 0, + 'default_argument_image_size' => '_original', + 'default_argument_php' => '', + 'validate_argument_node_type' => array( + 'image' => 0, + 'club' => 0, + 'club_topic' => 0, + 'page' => 0, + 'profile' => 0, + 'story' => 0, + 'vehicle' => 0, + ), + 'validate_argument_node_access' => 0, + 'validate_argument_nid_type' => 'nid', + 'validate_argument_vocabulary' => array( + '1' => 0, + '3' => 0, + ), + 'validate_argument_type' => 'tid', + 'validate_argument_transform' => 0, + 'validate_user_restrict_roles' => 0, + 'validate_argument_node_flag_name' => '*relationship*', + 'validate_argument_node_flag_test' => 'flaggable', + 'validate_argument_node_flag_id_type' => 'id', + 'validate_argument_user_flag_name' => '*relationship*', + 'validate_argument_user_flag_test' => 'flaggable', + 'validate_argument_user_flag_id_type' => 'id', + 'image_size' => array( + '_original' => '_original', + 'thumbnail' => 'thumbnail', + 'preview' => 'preview', + 'home' => 'home', + 'expanded' => 'expanded', + 'block_icon' => 'block_icon', + 'club_grid' => 'club_grid', + 'full' => 'full', + ), + 'validate_argument_is_member' => 'OG_VIEWS_DO_NOT_VALIDATE_MEMBERSHIP', + 'validate_argument_group_node_type' => array( + 'club' => 0, + ), + 'validate_argument_php' => '', + 'override' => array( + 'button' => 'Override', + ), + ), + )); + $handler->override_option('filters', array( + 'status' => array( + 'operator' => '=', + 'value' => '1', + 'group' => '0', + 'exposed' => FALSE, + 'expose' => array( + 'operator' => FALSE, + 'label' => '', + ), + 'id' => 'status', + 'table' => 'node', + 'field' => 'status', + 'relationship' => 'none', + ), + )); + $handler->override_option('access', array( + 'type' => 'none', + )); + $handler->override_option('cache', array( + 'type' => 'none', + )); + $handler = $view->new_display('page', 'Page', 'page_1'); + $handler->override_option('path', 'flags/lists/%'); + $handler->override_option('menu', array( + 'type' => 'none', + 'title' => '', + 'description' => '', + 'weight' => 0, + 'name' => 'navigation', + )); + $handler->override_option('tab_options', array( + 'type' => 'none', + 'title' => '', + 'description' => '', + 'weight' => 0, + 'name' => 'navigation', + )); + + $views[$view->name] = $view; + return $views; +} \ No newline at end of file diff --git a/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_argument_fid.inc b/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_argument_fid.inc new file mode 100644 index 00000000..a9a59014 --- /dev/null +++ b/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_argument_fid.inc @@ -0,0 +1,26 @@ +fields('fl', array('title')) + ->condition('fl.fid', $this->value, 'IN') + ->execute(); + foreach ($result as $term) { + $titles[] = check_plain($term->title); + } + return $titles; + } +} + diff --git a/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_field_list.inc b/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_field_list.inc new file mode 100644 index 00000000..e4edb057 --- /dev/null +++ b/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_field_list.inc @@ -0,0 +1,56 @@ +additional_fields['fid'] = array('table' => 'flag_lists_flags', 'field' => 'fid'); + $this->additional_fields['uid'] = array('table' => 'flag_lists_flags', 'field' => 'uid'); + } + + function option_definition() { + $options = parent::option_definition(); + $options['link_to_list'] = array('default' => FALSE); + return $options; + } + + /** + * Provide link to list option + */ + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + $form['link_to_list'] = array( + '#title' => t('Link this field to its list'), + '#description' => t('This will override any other link you have set.'), + '#type' => 'checkbox', + '#default_value' => !empty($this->options['link_to_list']), + ); + } + + /** + * Render whatever the data is as a link to the list. + * + * Data should be made XSS safe prior to calling this function. + */ + function render_link($data, $values) { + if (!empty($this->options['link_to_list']) && $data !== NULL && $data !== '') { + $this->options['alter']['make_link'] = TRUE; + $this->options['alter']['path'] = "user/" . $values->{$this->aliases['uid']} . "/flags/lists/" . $values->{$this->aliases['fid']}; + } + return $data; + } + + function render($values) { + return $this->render_link(check_plain($values->{$this->field_alias}), $values); + } +} diff --git a/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_field_list_delete.inc b/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_field_list_delete.inc new file mode 100644 index 00000000..3b4f7db3 --- /dev/null +++ b/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_field_list_delete.inc @@ -0,0 +1,50 @@ +additional_fields['fid'] = 'fid'; + } + + function option_definition() { + $options = parent::option_definition(); + + $options['text'] = array('default' => '', 'translatable' => TRUE); + + return $options; + } + + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + $form['text'] = array( + '#type' => 'textfield', + '#title' => t('Text to display'), + '#default_value' => $this->options['text'], + ); + } + + function query() { + $this->ensure_my_table(); + $this->add_additional_fields(); + } + + function render($values) { + $fid = $values->{$this->aliases['fid']}; + + // Check delete access. + if (!flag_lists_is_owner('delete', $fid)) { + return; + } + + $text = !empty($this->options['text']) ? $this->options['text'] : t('delete'); + return l($text, "flags/lists/delete/" . $fid, array('query' => drupal_get_destination())); + } +} \ No newline at end of file diff --git a/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_field_list_edit.inc b/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_field_list_edit.inc new file mode 100644 index 00000000..0f52d400 --- /dev/null +++ b/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_field_list_edit.inc @@ -0,0 +1,50 @@ +additional_fields['fid'] = 'fid'; + } + + function option_definition() { + $options = parent::option_definition(); + + $options['text'] = array('default' => '', 'translatable' => TRUE); + + return $options; + } + + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + $form['text'] = array( + '#type' => 'textfield', + '#title' => t('Text to display'), + '#default_value' => $this->options['text'], + ); + } + + function query() { + $this->ensure_my_table(); + $this->add_additional_fields(); + } + + function render($values) { + $fid = $values->{$this->aliases['fid']}; + + // Check edit access. + if (!flag_lists_is_owner('edit', $fid)) { + return; + } + + $text = !empty($this->options['text']) ? $this->options['text'] : t('edit'); + return l($text, "flags/lists/edit/" . $fid, array('query' => drupal_get_destination())); + } +} diff --git a/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_field_ops.inc b/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_field_ops.inc new file mode 100644 index 00000000..56a8c86a --- /dev/null +++ b/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_field_ops.inc @@ -0,0 +1,94 @@ + array( + 'force_single' => array('default' => FALSE), + 'operation' => array('default' => 'flag'), + ), + ); + + return $options; + } + + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + + $form['flo'] = array( + '#type' => 'fieldset', + '#title' => t('Flag lists operations'), + '#collapsible' => FALSE, + '#collapsed' => FALSE, + ); + $form['flo']['force_single'] = array( + '#type' => 'checkbox', + '#title' => t('Force single'), + '#default_value' => $this->options['flo']['force_single'], + '#description' => t('Check this box to restrict selection to a single value.'), + ); + $form['flo']['operation'] = array( + '#type' => 'radios', + '#title' => t('Operation'), + '#default_value' => $this->options['flo']['operation'], + '#description' => t('The flag lists operation for this selection.'), + '#options' => array( + 'flag' => 'Add to list', + 'unflag' => 'Remove from list', + ), + '#required' => TRUE, + ); + } + + /** + * If the view is using a table style, provide a + * placeholder for a "select all" checkbox. + */ + function label() { + if ($this->view->style_plugin instanceof views_plugin_style_table && !$this->options['flo']['force_single']) { + return ''; + } + else { + return parent::label(); + } + } + + function render($values) { + return ''; + } + + function views_form(&$form, &$form_state) { + // The view is empty, abort. + if (empty($this->view->result)) { + return; + } + + $form[$this->options['id']] = array( + '#tree' => TRUE, + ); + + // At this point, the query has already been run, so we can access the results + // in order to get the base key value (for example, nid for nodes). + foreach ($this->view->result as $row_index => $row) { + $entity_id = $this->get_value($row); + + if ($this->options['flo']['force_single']) { + $form[$this->options['id']][$row_index] = array( + '#type' => 'radio', + '#parents' => array($this->options['id']), + '#return_value' => $entity_id, + ); + } + else { + $form[$this->options['id']][$row_index] = array( + '#type' => 'checkbox', + '#return_value' => $entity_id . (isset($row->flag_lists_flags_fid) ? ('-' . $row->flag_lists_flags_fid) : ''), + '#default_value' => FALSE, + '#attributes' => array('class' => array('flo-select')), + ); + } + } + } +} \ No newline at end of file diff --git a/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_field_template.inc b/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_field_template.inc new file mode 100644 index 00000000..6fa2605a --- /dev/null +++ b/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_field_template.inc @@ -0,0 +1,55 @@ +additional_fields['name'] = array('table' => 'flags', 'field' => 'name'); + } + + function option_definition() { + $options = parent::option_definition(); + $options['link_to_template'] = array('default' => FALSE); + return $options; + } + + /** + * Provide link to list option + */ + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + $form['link_to_template'] = array( + '#title' => t('Link this field to its list template'), + '#description' => t('This will override any other link you have set.'), + '#type' => 'checkbox', + '#default_value' => !empty($this->options['link_to_template']), + ); + } + + /** + * Render whatever the data is as a link to the list. + * + * Data should be made XSS safe prior to calling this function. + */ + function render_link($data, $values) { + if (!empty($this->options['link_to_template']) && $data !== NULL && $data !== '') { + $this->options['alter']['make_link'] = TRUE; + $this->options['alter']['path'] = "admin/build/flags/edit/" . $values->{$this->aliases['name']}; + } + return $data; + } + + function render($values) { + return $this->render_link(check_plain($values->{$this->field_alias}), $values); + } +} \ No newline at end of file diff --git a/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_field_template_types.inc b/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_field_template_types.inc new file mode 100644 index 00000000..e48b05d2 --- /dev/null +++ b/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_field_template_types.inc @@ -0,0 +1,65 @@ +additional_fields['name'] = array('table' => 'flags', 'field' => 'name'); + } + function query() { + $this->add_additional_fields(); + $this->field_alias = $this->aliases['name']; + } + + function pre_render($values) { + $names = array(); + $this->items = array(); + + foreach ($values as $result) { + $names[] = $result->{$this->aliases['name']}; + } + + if (count($names)) { + $query = db_select('flag_lists_types', 'flt'); + $query->innerJoin('flags', 'f', 'flt.name = f.name'); + $result = $query->fields('flt', array('type', 'name')) + ->condition('f.name', $names, 'IN') + ->orderBy('flt.type') + ->execute(); + foreach ($result as $type) { + $this->items[$type->name][$type->type] = check_plain($type->type); + } + } + } + + function render($values) { + $field = $values->{$this->field_alias}; + if (!empty($this->items[$field])) { + if ($this->options['type'] == 'separator') { + return implode($this->sanitize_value($this->options['separator']), $this->items[$field]); + } + else { + return theme('item_list', + array( + 'items' => $this->items[$field], + 'title' => NULL, + 'type' => $this->options['type'] + )); + } + } + } + + function get_value($values, $field = NULL, $raw = FALSE) { + if ($raw) { + return parent::get_value($values, $field); + } + $item = $this->get_items($values); + $item = (array) $item; + if (isset($field) && isset($item[$field])) { + return $item[$field]; + } + return $item; + } +} diff --git a/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_filter_template.inc b/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_filter_template.inc new file mode 100644 index 00000000..a39d829d --- /dev/null +++ b/sites/all/modules/contrib/flag/flag_lists/includes/flag_lists_handler_filter_template.inc @@ -0,0 +1,17 @@ +value_options)) { + $this->value_title = t('List templates'); + $templates = flag_lists_get_templates(); + foreach ($templates as $template) { + $options[$template->name] = $template->name; + } + $this->value_options = $options; + } + } +} diff --git a/sites/all/modules/contrib/flag/flag_lists/js/flag_lists_ops.js b/sites/all/modules/contrib/flag/flag_lists/js/flag_lists_ops.js new file mode 100644 index 00000000..f323bdbb --- /dev/null +++ b/sites/all/modules/contrib/flag/flag_lists/js/flag_lists_ops.js @@ -0,0 +1,79 @@ +(function ($) { + Drupal.behaviors.flagListsOps = { + attach: function(context) { + // Hide the go button, as it is not needed for JS enabled browsers. + $('.flag-lists-ops-go', context).hide(); + + // Make select all checkbox work + $('input.flo-table-select-all', context).each(function(i) { + var selectall = $(this); + + if (!selectall.hasClass('processed')) { + selectall.change(function(e) { + $('input.flo-select', $(this).parents('form')).attr('checked', $(this).attr('checked')); + }).addClass('processed'); + } + }); + + // Animate the deletion for AJAX deleting. + $('.flo-deleted-value', context).each(function(i) { + var parent = $(this).parents('.view'); + $('.flo-select[value='+$(this).val()+']', parent).each(function(i) { + $(this).parents('.views-row, tr').fadeOut().delay(300).remove(); + }); + }); + + // Add new options to bottom of list ops dropdown to create new lists on the spot + $('.flag-lists-ops-dropdown', context).each(function(i) { + var select = $(this); + if (!select.hasClass('new-list-processed')) { + select.addClass('new-list-processed'); + + if (Drupal.settings.flag_lists.types.length > 0) { + $(this).after('New list?
'); + var dialog = $('.new-list-form', $(this).parent()).dialog({ + autoOpen: false, + height: 300, + width: 350, + modal: true, + buttons: { + "Create a new list": function() { + var name = $('input.name', $(this)).val(); + var type = $('select.type', $(this)).val(); + + $.getJSON(Drupal.settings.flag_lists.json_path.replace('%', type)+'?name='+name, function(data) { + if (data.error) { + alert(data.error); + } + else { + select.append(''); + $('input.name', $(this)).val(''); + dialog.dialog('close'); + } + }); + }, + Cancel: function() { + dialog.dialog('close'); + } + }, + close: function() { + + } + }); + $('.create-a-new-list', $(this).parent()) + .button() + .click(function(e) { + dialog.dialog('open'); + }); + } + + // Put entries into the optgroup + for (j in Drupal.settings.flag_lists.types) { + var type = Drupal.settings.flag_lists.types[j]; + $('.new-list-form form select.type').append(''); + } + } + }); + } + } +})(jQuery); diff --git a/sites/all/modules/contrib/flag/flag_lists/theme/flag_lists.css b/sites/all/modules/contrib/flag/flag_lists/theme/flag_lists.css new file mode 100644 index 00000000..d049b07b --- /dev/null +++ b/sites/all/modules/contrib/flag/flag_lists/theme/flag_lists.css @@ -0,0 +1,9 @@ +.block-flag_lists .flag-message { + position: relative; + clear: both; + top:0; + left:0; + line-height: normal; + width: auto; + font-size: .8em; +} \ No newline at end of file