Index: openacs-4/contrib/obsolete-packages/library/library.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/library.info,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/library.info 2 Jul 2003 12:19:40 -0000 1.1 @@ -0,0 +1,390 @@ + + + + + Library + Libraries + f + f + + + + oracle + postgresql + + Dirk Gomez + Red Hat Knowledge Library for ACS4.0 + Red Hat Knowledge Library for ACS4.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: openacs-4/contrib/obsolete-packages/library/license.txt =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/license.txt,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/license.txt 2 Jul 2003 12:19:40 -0000 1.1 @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. Index: openacs-4/contrib/obsolete-packages/library/readme.txt =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/readme.txt,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/readme.txt 2 Jul 2003 12:19:40 -0000 1.1 @@ -0,0 +1,6 @@ +Knowledge Management Package + +This package is based on the commercial acs version from the year 2000. +You can define different knowledge objects, questions and link the information variable. +It is not tested with the openacs version 4.6.3. + Index: openacs-4/contrib/obsolete-packages/library/sql/oracle/library-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/sql/oracle/library-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/sql/oracle/library-create.sql 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,994 @@ + +-- +-- packages/library/sql/library-create.sql +-- +-- Credit for the ACS 3 version of this module goes to: +-- @author Branimir Dolicki (branimir@arsdigita.com) +-- @author Carsten Clasohm (carsten@arsdigita.com) +-- @author Sarah Arnold (zylonne@web.de) +-- +-- The upgrade of this module to ACS 4 was done by +-- @author Dirk Gomez (dirk@arsdigita.com) +-- in June/July 2001. +-- +-- @creation-date 22-June 2001 +-- @cvs-id $Id: library-create.sql,v 1.1 2003/07/02 12:19:42 peterm Exp $ + +-- Changes, (at least those made by me) in reverse chronological order + +-- (bran 006) 2001-09-18 Moved everything having to do with linking to a -- +-- separate package - sn_links. So basically changes 001, 002, 004 and 005 are +-- there and not here but in packages/sn-links/sql/oracle/sn-links. + +-- (bran 005) 2001-09-12 As we are using the low-tech approach w/o objects we +-- need a sequence to generate link_id's. + +-- (bran 004) 2001-09-10 There ain't gonna be any stinkin' objects here. Links +-- are just rows in a table. Period. Removed acs_object_type.create_type. Same +-- goes for acs_rel_type.create_role and friends + +-- (bran 003) 2001-09-10 Removed question_id from sn_links because it is +-- library-specific. We have a new table in library: +-- sn_question_link_map + +-- (bran 002) 2001-09-10 Removed the sn_link_comments table and put that stuff +-- into sn_links. Finally we admit that it doesn't make sense to have one comment +-- on two links! + +-- (bran 001) 2001-09-10 Removed the link_type_id column from sn_link_types. +-- We are now refering to link types by link_type and not by link_type_id. + +------------------------------------------------------------------------------ +-- The questions table holds all of the data about the kinds of +-- questions that can be asked about a knowledge object. + +create table sn_questions ( + question_id + integer + constraint sn_questions_question_id_fk + references acs_objects (object_id) + constraint sn_questions_question_id_pk + primary key, + pretty_name + varchar(4000), + abstract_data_type + varchar(50) + constraint sn_questions_abstract_data_nn not null, + presentation_type + varchar(100) + constraint sn_questions_presentation_t_nn not null, + -- for all questions which display lists + order_by + varchar(100), + -- default for input forms + default_value + varchar(4000), + entry_explanation + varchar(4000), + tag_width + integer, + tag_height + integer, + help_text + varchar(4000), + -- for object_link: which type to link to + target_object_type_id + integer, + -- that is merged in from a change I (and Carsten ;) already did in + -- 7.1 + defaults_question_id + integer default null + constraint sn_questions_defaults_qu_id_fk + references sn_questions(question_id), + references_question_id + integer + constraint sn_questions_referenc_qu_id_fk + references sn_questions(question_id), + -- for question of data type category + tree_id + integer + constraint sn_questions_tree_ref references generic_trees, + node_id + integer + constraint sn_questions_node_ref references sw_category_dim, + browse_p + varchar(1) default 't' + constraint sn_questions_browse_p_ck + check (browse_p in ('t','f')), + -- This is only used during data migration from ShareNet 7. + category_id + integer, + max_categories + integer default null, + -- this is only for abstract_data_type date to specify what years + -- should be in the select box in respect to the default date. + year_from + integer default -5, + year_to + integer default 5 +); + + +begin + acs_object_type.create_type ( + supertype => 'acs_object', + object_type => 'sn_question', + pretty_name => 'Question', + pretty_plural => 'Questions', + table_name => 'SN_QUESTIONS', + id_column => 'QUESTION_ID' + ); +end; +/ +show errors + +insert into sn_questions (question_id, pretty_name, abstract_data_type, presentation_type) +select object_id, name, 'dummy', 'dummy' from +acs_magic_objects where name = 'km_dummy_object'; + +------------------------------------------------------------------------------ +-- Together with sn_question_object_type_map, table sn_object_types defines +-- the possible types of knowledge objects. + +create table sn_types_map_short_name ( + object_type_id + integer, + short_description + integer + constraint sn_types_map_short_desc_id_fk + references sn_questions (question_id), + position + integer, + constraint sn_types_map_short_name_pk + primary key (object_type_id, short_description) +); + +create table sn_object_types ( + object_type_id + integer + constraint sn_object_types_pk + primary key, + context_id + constraint sn_object_types_context_id_fk + references apm_packages (package_id) + on delete cascade, + short_name + varchar(100), + pretty_name + varchar(100) + constraint sn_object_types_pretty_name_nn not null, + pretty_plural + varchar(100), + -- filename for the graphic icon. This is always + -- $object_type_id.extension + graphic + varchar(200), + graphic_p + char(1) + default 'f' + constraint sn_object_types_graphic_p_nn not null, + constraint sn_object_types_graphic_p_ck + check (graphic_p in ('t', 'f')), + deleted_p + char(1) + default 'f' + constraint sn_object_types_deleted_p_nn not null, + constraint sn_object_types_deleted_p_ck + check (deleted_p in ('t', 'f')), + browse_p + char(1) + default 't' + constraint sn_object_types_browse_p_nn not null, + constraint sn_object_types_browse_p_ck + check (browse_p in ('t', 'f')), + -- If the object type is not public, consult sn_object_type_access + -- to determine if a user may access this type. + public_p + char(1) default 't' + constraint sn_object_types_public_p_nn not null, + constraint sn_object_types_public_p_ck + check (public_p in ('t','f')), + -- to be able to prevent standalone objects of this object type + -- (meaning objects which didnt created as child or nephew) + -- needed this for people sharenet - demand descriptions + create_p + char(1) default 't' + constraint sn_object_types_create_p_nn not null, + constraint sn_object_types_create_p_ck + check (create_p in ('t','f')), + sort_key + integer, + -- The admin can define which question is the name, overview or + -- public_until date for this object type: + short_description + integer + constraint sn_object_typ_short_desc_id_fk + references sn_questions (question_id), + long_description + integer + constraint sn_object_type_long_desc_id_fk + references sn_questions (question_id), + public_until + integer + constraint sn_object_t_public_until_id_fk + references sn_questions (question_id), + -- these two links to date questions have been added for + -- people sharenet (project start/end date): + start_date + integer + constraint sn_object_t_start_date_id_fk + references sn_questions (question_id), + end_date + integer + constraint sn_object_t_end_date_id_fk + references sn_questions (question_id), + -- that is merged in from a change I (and Carsten ;) already did in + -- 7.1 + linked_question_id + integer + constraint sn_object_t_linked_quest_id_fk + references sn_questions(question_id), + default_age_filter + integer default 365, + -- can objects of this type be archived? + archive_p + char(1) + default 'f' + constraint sn_object_types_archive_p_nn not null, + constraint sn_object_types_archive_p_ck + check (archive_p in ('t', 'f')), + -- are you allowed to copy objects of this type? + copy_p + char(1) + default 'f' + constraint sn_object_types_copy_p_nn not null, + constraint sn_object_types_copy_p_ck + check (copy_p in ('t', 'f')), + -- which sweeper should be checking for old objects? + -- outdated: objects haven't been modified for a certain time + -- expired: public_until date has been exceeded + sweeper + varchar(10) + default 'none' + constraint sn_object_types_sweeper_nn not null, + constraint sn_object_types_sweeper_ck + check (sweeper in ('none','outdated','expired')), + -- action to be performed on the objects by the sweeper + sweeper_action + varchar(10) + default 'private' + constraint sn_object_types_sw_action_nn not null, + constraint sn_object_types_sw_action_ck + check (sweeper_action in ('private','archive')), + -- if >0 a warning email will be sent if the object is outdated/expired + -- specifies the amount of days the action should be performed after + -- the warning email + sweeper_warning_time + integer + default 0 + constraint sn_object_types_warning_nn not null, + -- specified the amount of days after which an unchanged objects is + -- regarded as outdated + sweeper_outdated_time + integer + default 30 +); + + +begin + acs_object_type.create_type ( + supertype => 'acs_object', + object_type => 'sn_object_type', + pretty_name => 'Object Type', + pretty_plural => 'Object Types', + table_name => 'SN_OBJECT_TYPES', + id_column => 'OBJECT_TYPE_ID' + ); +end; +/ +show errors + +-- We can only add this foreign key after creating the object_type_table. +alter table sn_questions + add constraint sn_questions_object_type_id_fk + foreign key (target_object_type_id) + references sn_object_types(object_type_id); + +alter table sn_types_map_short_name + add constraint sn_types_map_object_type_id + foreign key (object_type_id) + references sn_object_types(object_type_id); + + +------------------------------------------------------------------------------ +-- This table holds the objects. + +create table sn_objects ( + object_id + integer + constraint sn_objects_id_pk + primary key, + object_type_id + integer + constraint sn_objects_object_type_id_fk + references sn_object_types (object_type_id), + -- objects should be subsite-aware as well + context_id + constraint sn_objects_context_id_fk + references apm_packages (package_id) + on delete cascade, + one_line_description + varchar(4000), + overview + varchar(4000), + overview_html_p + char(1) + constraint sn_objects_overview_html_p_ck + check (overview_html_p in ('t','f')), + creation_date + date, + original_author_id + integer + constraint sn_objects_orig_author_id_fk + references users (user_id), + last_modified + date, + last_modifying_user_id + integer + constraint sn_objects_last_mod_user_id_fk + references users (user_id), + user_checkoff_date date, + -- id of last publisher (user with km_publish permission) (BPM) + publisher_id + integer + constraint sn_objects_publisher_id_fk + references users (user_id), + expiration_date + date default '9999-12-31' + constraint sn_objects_expiration_date_nn not null, + public_until date, + -- these two dates got added for people sharenet: + start_date date, + end_date date, + public_p + char(1) default 'f' + constraint sn_objects_public_p_ck + check (public_p in ('t','f')), + archived_p + char(1) default 'f' + constraint sn_objects_archived_p_ck + check (archived_p in ('t','f')), + -- to mark object (i.e. nephews) that should be reviewd (BPM) + in_review_p + char(1) default 'f' + constraint sn_objects_in_review_p_ck + check (in_review_p in ('t','f')), + access_total integer default 0, + access_month integer default 0, + -- date the object got archived + archiving_date + date + default null, + -- date a warning email got sent that object is outdated + outdated_warning_date + date + default null, + -- date a warning email got sent that object is expired (public_until) + expired_warning_date + date + default null +); + + +begin + acs_object_type.create_type ( + supertype => 'acs_object', + object_type => 'sn_object', + pretty_name => 'Library Object', + pretty_plural => 'Library Objects', + table_name => 'SN_OBJECTS', + id_column => 'OBJECT_ID' + ); end; +/ +show errors + + +-- Create some indexes for performance. + +create index sn_objects_expiration_date_ix on sn_objects (expiration_date); + +create index sn_objects_public_until_ix on sn_objects (public_until); + +create index sn_objects_start_date_ix on sn_objects (start_date); + +create index sn_objects_end_date_ix on sn_objects (end_date); + +create index sn_objects_checkoff_date_ix on sn_objects (user_checkoff_date); + +create index sn_objects_last_modified_ix on sn_objects (last_modified); + +create index sn_objects_new_stuff_ix on sn_objects (last_modified, +user_checkoff_date, expiration_date, object_type_id); + +create index sn_objects_type_id_ix on sn_objects (object_type_id); + +create index sn_objects_browse_ix on sn_objects (object_type_id, context_id, expiration_date, last_modified, public_p, archived_p, object_id); + +create index sn_objects_one_line_desc_ix on sn_objects (substr(upper(one_line_description),1,1)); + +create index sn_objects_archived_p_ix on sn_objects (archived_p); + +create index sn_objects_o_warning_date_ix on sn_objects (outdated_warning_date); + +create index sn_objects_e_warning_date_ix on sn_objects (expired_warning_date); + +create index sn_object_publisher_id_ix on sn_objects (publisher_id); + +------------------------------------------------------------------------------ +-- This defines the set of questions associated with a given object +-- type. Questions can be used in common between object types and grouped +-- together under one parent_question_id for composite questions. +create table sn_question_object_type_map ( + question_id + integer + constraint sn_question_otm_question_id_fk + references sn_questions (question_id), + object_type_id + integer + constraint sn_question_otm_object_t_id_fk + references sn_object_types (object_type_id), + sort_key + integer, + form_number + integer, + mandatory_p + char(1) + constraint sn_question_otm_mandatory_p_ck + check (mandatory_p in ('t','f')), + question_state + varchar(100) + constraint sn_question_otm_question_st_ck + check(question_state in + ('active','deprecated','read-only','invisible')), + -- used for composite and branches + -- -50 is the magic object from acs_magic_objects where name='km_dummy_object'. Don't change it! + parent_question_id + integer + default -50 + constraint sn_question_otm_parent_q_id_nn not null + constraint sn_question_otm_parent_q_id_fk + references sn_questions (question_id), + -- t if this question itself is a branch, NOT if this question LEADS to branches + branch_p + char(1) + constraint sn_question_otm_branch_p_ck + check (branch_p in ('t','f')), + -- applies to the question as the parent node of a branch + branch_operator + varchar(4000), + -- the answers apply to the child nodes + branch_answer + varchar(4000), + -- can reference categories or sn_answer_options + branch_answer_foreign_key + integer, + default_branch + integer + constraint sn_question_otm_default_bra_fk + references sn_questions (question_id), + constraint sn_question_object_type_map_pk + primary key (question_id, object_type_id) +); + +------------------------------------------------------------------------------ +-- ***** Object Data ***** + +-- This table stores the content of the one-to-one questions having abstract +-- data type "text" for any given object. + +-- The questions_id shows which question the content answers. If a single +-- question has more than one answer, then that data belongs in the +-- multiple-choice answers tables (sn_answer_options and sn_object_option_map) +-- having the abstract data type "multiple_choice" or should be constructed as +-- composite question having the abstract data type "composite". + +create table sn_content ( + object_id + integer + constraint sn_content_object_id_fk + references sn_objects(object_id), + question_id + integer + constraint sn_content_question_id_fk + references sn_questions(question_id), + content + clob, + html_p + char(1) + constraint sn_content_html_p_ck + check (html_p in ('t', 'f')), + constraint sn_content_pk + primary key (object_id, question_id) +); + +------------------------------------------------------------------------------ +-- ***** Auditing ***** +-- Whenever the content of an object is changed then we store it here. We +-- don't store changes in the categorization, linking or multiple choice +-- questions. + +create table sn_audit_table ( + object_id + integer + constraint sn_audit_table_object_id_fk + references sn_objects(object_id), + question_id + integer + constraint sn_audit_table_question_id_fk + references sn_questions(question_id), + --this refers to the question being modified + last_modified + date + constraint sn_audit_table_last_modifie_nn not null, + last_modifying_user_id + integer + constraint sn_audit_table_last_mo_u_id_fk + references users (user_id), + content + varchar(4000) +); + +create index audit_table_ix on sn_audit_table(object_id); + +-- The ShareNet admins want to give a reason for object deletion to supervise +-- the incentive system more efficiently. + +create table sn_object_delete_reasons ( + object_id + integer + constraint sn_object_delete_rea_obj_id_fk + references sn_objects(object_id) + constraint sn_object_delete_reasons_pk + primary key, + reason_for_deleting + varchar(4000), + deleted_on + date default sysdate +); + +-- For the archive + +create table sn_object_archive_reasons ( + object_id + integer + constraint sn_object_archive_re_obj_id_fk + references sn_objects(object_id), + reason_for_archiving + varchar(4000), + archived_on + date default sysdate, + constraint sn_object_archive_reasons_pk + primary key (object_id, archived_on) +); + +------------------------------------------------------------------------------ +-- This table holds the answers to multiple choice questions +create table sn_answer_options ( + option_id + integer + constraint sn_answer_options_option_id_pk + primary key, + question_id + integer + constraint sn_answer_options_questi_id_fk + references sn_questions(question_id), + answer_option + varchar(4000), + sort_key + integer +); + +------------------------------------------------------------------------------ +-- This table links multiple-choice answers to objects +create table sn_object_option_map ( + object_id + integer + constraint sn_object_option_map_obj_id_fk + references sn_objects(object_id), + option_id + integer + constraint sn_object_option_map_opt_id_fk + references sn_answer_options(option_id) +); + +------------------------------------------------------------------------------ +-- (bran 003) +-- When linking was library-specific thing we +-- had question_id column in the sn_links table. +-- Now we have a special table which answers the +-- question: "Given a link_id, to which question +-- was the user answering when he created that link?" +create table sn_question_link_map ( + link_id + integer + constraint sn_question_link_ma_link_id_fk + references sn_links (link_id) + on delete cascade + constraint sn_question_link_map_pk + primary key, + question_id + integer + constraint sn_question_lin_question_id_fk + references sn_questions (question_id) + constraint sn_question_lin_question_id_nn + not null +); + +create index sn_question_link_ma_q_id_ix on sn_question_link_map (question_id); + +------------------------------------------------------------------------------ +-- Excursions & Navigation + +create table km_path ( + path_id + integer + constraint km_path_pk + primary key + constraint km_path_path_id_nn not null , + last_path_id + integer, + action + varchar(100), + values_list + varchar(4000), + return_to + varchar(4000), + start_time + date +); + +------------------------------------------------------------------------------ +-- access counting +create table sn_access_counts ( + object_id + integer + constraint sn_access_counts_object_id_fk + references sn_objects(object_id), + access_count + integer, + access_date + date, + constraint sn_access_counts_pk + primary key (object_id,access_date) +); + +create index sn_access_counts_composite_ix on sn_access_counts (object_id,access_date,access_count); + +------------------------------------------------------------------------------ +-- For backwards compatibility. Old-style URLs looked like this: +-- /library/browse-one-type.tcl?object_type=market +-- and they need to be converted to /library/browse-one-type.tcl?object_type_id + +create table sn_table_name_map ( + object_type_id + integer + constraint sn_table_name_map_pk + primary key, + context_id + constraint sn_table_name_map_cont_id_fk + references apm_packages (package_id) + on delete cascade, + object_type_name varchar(100) +); + +------------------------------------------------------------------------------ +-- We're maintaining km_flat_object_hierarchy with triggers that fire +-- on insert or delete from sn_links for link type parent_child. +-- Since it's not allowed to access sn_links from triggers defined on it +-- (table is mutating etc etc), we keep the copy of the relevant data in +-- flat_object_hierarchy itself. Suppose we have following hierarchy: + +-- -------------- +-- 102 +-- 106 +-- 107 +-- 141 +-- 121 +-- -------------- +-- +-- From source sn_links table: + +-- SITE_WIDE_ID_A SITE_WIDE_ID_B +-- ------------------ ----------------- +-- 102 106 +-- 106 107 +-- 141 121 +-- 102 141 + + +-- ... we arrive on flat_object_hierarchy + + +-- PARENT CHILD DISTANCE +-- --------- ---------- -------- +-- 141 121 1 +-- 102 121 2 +-- 102 141 1 +-- 102 106 1 +-- 102 107 2 +-- 106 107 1 + + +create table km_flat_object_hierarchy ( + object_hierarchy_id + integer + constraint km_flat_object_hierarchy_id_pk + primary key, + parent + integer + constraint km_flat_object_hier_parent_nn not null + constraint km_flat_object_hier_parent_fk + references acs_objects (object_id), + child + integer + constraint km_flat_object_hier_child_nn not null + constraint km_flat_object_hier_child_fk + references acs_objects (object_id), + distance + integer, + link_type + varchar2(100), + constraint km_flat_object_hier_unique unique (parent, child) +); + +create index km_flat_object_hier_child_ix on km_flat_object_hierarchy(child); + + +------------------------------------------------------------------------------ +-- This table is pretty damn useful if you want to track long-running +-- transaction. It is being filled by a pl/sql procedure that commits +-- within a autonomous transaction. + +create table km_logger_table ( + log_date + date + default sysdate, + who_is_logging + varchar2(4000), + log_text + varchar2(4000) +); + + +----------------------------------------------------------------------------- +-- This table is for the library sweeper proc that takes care of outdated +-- or expired objects and sets them to private or archive them if +-- the user didn't take action after a warning email + +create table km_sweeper ( + user_id + integer + constraint km_sweeper_user_id_fk + references users, + package_id + integer + constraint km_sweeper_package_id_fk + references apm_packages, + object_type_id + integer + constraint km_sweeper_obj_type_id_fk + references sn_object_types, + object_id + integer + constraint km_sweeper_object_id_fk + references sn_objects, + object_name + varchar2(4000), + content + varchar2(4000), + primary key (user_id, object_id) +); + +-- this table holds the library sweeper emails for publishers +create table km_sweeper_publisher ( + user_id + integer + constraint km_sweeper_publ_user_id_fk + references users, + package_id + integer + constraint km_sweeper_publ_package_id_fk + references apm_packages, + object_type_id + integer + constraint km_sweeper_publ_obj_type_id_fk + references sn_object_types, + object_id + integer + constraint km_sweeper_publ_object_id_fk + references sn_objects, + object_name + varchar2(4000), + content + varchar2(4000), + primary key (user_id, object_id) +); + + +------------------------------------------------------------------------------ +create table km_library_searches ( + km_library_searches_id + integer + constraint km_library_searches_id_pk + primary key, + user_id + integer + constraint km_library_searches_user_id_fk + references users (user_id), + name + varchar(200), + url_params + clob, + creation_date + date + default sysdate +); + +create table km_advanced_search_settings ( + search_id + integer + constraint km_advanced_ss_search_id_fk + references km_library_searches(km_library_searches_id), + parameter_key + varchar(4000), + parameter_value + clob +); + +------------------------------------------------------------------------------ +create table sn_owner_history ( + object_id + integer + constraint sn_own_hist_object_id_fk + references sn_objects(object_id), + change_user_id + integer + constraint sn_own_hist_change_user_id_fk + references users(user_id), + old_user_id + integer + constraint sn_own_hist_old_user_id_fk + references users(user_id), + new_user_id + integer + constraint sn_own_hist_new_user_id_fk + references users(user_id), + change_date + date, + reason + varchar(4000) +); + +------------------------------------------------------------------------------ +-- th 2001-10-22 tables added for people sharenet: application form +------------------ +create table psn_res_applications ( + application_id integer primary key, + object_id constraint psn_res_app_object_id_fk references sn_objects on delete cascade, + resource_req_id constraint psn_res_app_res_req_id_fk references sn_objects on delete cascade, + user_id constraint psn_res_app_user_id_fk references users, + creation_date date default sysdate, + application_date date default null, + sent_p char(1) default 'f' constraint psn_res_app_sent_p_ck check (sent_p in ('t','f')), + recipient varchar2(4000), + subject varchar2(1000), + contact_data varchar2(4000), + nationality varchar2(4000), + manager_email varchar2(4000), + working_area varchar2(4000), + role_other varchar2(1000), + first_language varchar2(1000), + second_language_id integer, + third_language_id integer, + first_language_prof_id integer, + second_language_prof_id integer, + third_language_prof_id integer, + other_language varchar2(4000), + from_date date, + to_date date, + strengths varchar2(4000), + leadership varchar2(4000), + intercultural varchar2(4000), + comments varchar2(4000), + conditions varchar2(4000) +); + +create index psn_res_app_object_idx on psn_res_applications (object_id); + +create index psn_res_app_res_idx on psn_res_applications (resource_req_id); + +create index psn_res_app_user_idx on psn_res_applications (user_id); + +create table psn_res_application_roles ( + application_id integer constraint psn_res_app_roles_app_fk references psn_res_applications on delete cascade, + role_id integer, + primary key (application_id, role_id) +); + +create table psn_category_trees ( + package_id integer primary key, + role_magic_id constraint psn_cat_trees_role_fk references acs_objects (object_id) on delete set null, + language_magic_id constraint psn_cat_trees_lang_fk references acs_objects (object_id) on delete set null, + proficiency_magic_id constraint psn_cat_trees_prof_fk references acs_objects (object_id) on delete set null +); + +create table psn_attachments ( + attachment_id integer primary key, + application_id constraint psn_attach_appl_id_fk references psn_res_applications on delete cascade, + title varchar2(1000), + mime_type varchar2(200) default 'text/plain', + filename varchar2(200), + attachment blob default empty_blob() +); + +create index psn_attach_appl_id_idx on psn_attachments(application_id); + +create sequence psn_attachment_id_seq start with 1; + +begin + acs_object_type.create_type ( + supertype => 'acs_object', + object_type => 'psn_tree_object', + pretty_name => 'Demand Application Form', + pretty_plural => 'Demand Application Forms', + table_name => 'PSN_CATEGORY_TREES' + ); +end; +/ +show errors + +begin + acs_object_type.create_type ( + supertype => 'acs_object', + object_type => 'psn_application', + pretty_name => 'Demand Application', + pretty_plural => 'Demand Applications', + table_name => 'PSN_RES_APPLICATIONS', + id_column => 'APPLICATION_ID' + ); +end; +/ +show errors + + +create table approval_coordinators ( + package_id integer + constraint sn_approval_coord_packag_id_fk + references apm_packages (package_id) + on delete cascade, + coordinator_id + integer + constraint sn_approval_coord_coord_id_fk + references users (user_id), + constraint approval_coordinators_pk + primary key (package_id, coordinator_id) +); + +------------------------------------------------------------------------------ +-- now go on and create the packages + +@@library-temp-tables +@@library-packages +@@library-package-bodies +@@library-triggers +@@library-workflow-create +@@library-workflow-packages + +begin + acs_privilege.create_privilege('km_publish'); + acs_privilege.add_child('km_publish','read'); + acs_privilege.add_child('km_publish','write'); + acs_privilege.add_child('km_publish','delete'); +end; +/ +show errors Index: openacs-4/contrib/obsolete-packages/library/sql/oracle/library-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/sql/oracle/library-drop.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/sql/oracle/library-drop.sql 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,146 @@ +-- +-- packages/library/sql/library-drop.sql +-- +-- Credit for the ACS 3 version of this module goes to: +-- @author Branimir Dolicki (branimir@arsdigita.com) +-- @author Carsten Clasohm (carsten@arsdigita.com) +-- @author Sarah Arnold (no idea) +-- +-- The upgrade of this module to ACS 4 was done by +-- @author Dirk Gomez (dirk@arsdigita.com) +-- @author Jens Kordsmeier (jak@arsdigita.com) +-- in June/July 2000. +-- +-- @creation-date 22-June 2001 +-- @cvs-id $Id + +-- Delete all library question objects and corresponding acs objects + +-- declare +-- cursor c_question_id +-- is +-- select question_id +-- from sn_questions +-- where parent_id not in (select question_id from sn_questions); +-- begin +-- for v_question_id in c_question_id loop +-- question.delete(v_question_id.question_id); +-- end loop; +-- end; +-- / +-- show errors + +-- delete acs_permissions +-- Drop permission metadata +delete from acs_permissions + where privilege in + ('km_instance_admin','km_object_type_read', + 'km_object_type_create','km_object_read', + 'km_object_write','km_publish'); + +delete from acs_privilege_hierarchy + where privilege in + ('km_instance_admin','km_object_type_read', + 'km_object_type_create','km_object_read', + 'km_object_write','km_publish'); + +delete from acs_privilege_hierarchy + where child_privilege in + ('km_instance_admin','km_object_type_read', + 'km_object_type_create','km_object_read', + 'km_object_write','km_publish'); + +delete from acs_privileges + where privilege in + ('km_instance_admin','km_object_type_read', + 'km_object_type_create','km_object_read', + 'km_object_write','km_publish'); + + +declare + cursor c1 is + select package_id from apm_packages where package_key='library'; +begin + for pac_rec in c1 loop + object_type.delete_all_object_types(pac_rec.package_id); + end loop; +end; +/ + +alter table sn_questions + drop constraint sn_questions_object_type_id_fk; +drop table psn_attachments; +drop table psn_category_trees; +drop table psn_res_application_roles; +drop table psn_res_applications; +drop table km_sweeper; +drop table km_sweeper_publisher; +drop table sn_object_archive_reasons; +drop table km_advanced_search_settings; +drop table km_library_searches; +drop table km_logger_table; +drop table km_flat_object_hierarchy; +drop table sn_question_link_map; +drop table sn_table_name_map; +drop table sn_access_counts; +drop table sn_object_option_map; +drop table sn_answer_options; +drop table sn_object_delete_reasons; +drop table km_object_archive_reasons; +drop table sn_audit_table; +drop table sn_content; +drop table sn_question_object_type_map; +drop table sn_objects; +drop table sn_object_types; +drop table sn_questions; +drop table km_path; + +delete from bm_bookmarkable_types where object_type = 'sn_object'; + +delete from subsite_callbacks where object_type = 'sn_object'; + +delete from acs_objects_description where object_id in (select object_id from acs_objects where object_type='sn_object'); + +delete from acs_permissions where object_id in (select object_id from acs_objects where object_type='sn_object'); + +-- Yeah I know it's stupid. But it works. +delete from acs_objects o where object_type='sn_object' and not exists (select 1 from acs_objects i where context_id = o.object_id); +delete from acs_objects o where object_type='sn_object' and not exists (select 1 from acs_objects i where context_id = o.object_id); +delete from acs_objects o where object_type='sn_object' and not exists (select 1 from acs_objects i where context_id = o.object_id); +delete from acs_objects o where object_type='sn_object' and not exists (select 1 from acs_objects i where context_id = o.object_id); +delete from acs_objects o where object_type='sn_object' and not exists (select 1 from acs_objects i where context_id = o.object_id); +delete from acs_objects o where object_type='sn_object' and not exists (select 1 from acs_objects i where context_id = o.object_id); +delete from acs_objects o where object_type='sn_object' and not exists (select 1 from acs_objects i where context_id = o.object_id); +delete from acs_objects o where object_type='sn_object' and not exists (select 1 from acs_objects i where context_id = o.object_id); +delete from acs_objects o where object_type='sn_object' and not exists (select 1 from acs_objects i where context_id = o.object_id); +delete from acs_objects o where object_type='sn_object' and not exists (select 1 from acs_objects i where context_id = o.object_id); + +-- This is even more... +delete from acs_objects where object_type='sn_comment' and context_id in (select object_id from acs_objects where object_type='sn_object'); + +delete from acs_objects where object_type = 'sn_object_type'; +delete from acs_objects where object_type = 'sn_question'; +delete from acs_objects where object_type = 'psn_tree_object'; +delete from acs_objects where object_type = 'psn_application'; + +begin + acs_object_type.drop_type ('sn_object'); + acs_object_type.drop_type ('sn_object_type'); + acs_object_type.drop_type ('sn_question'); + acs_object_type.drop_type ('psn_tree_object'); + acs_object_type.drop_type ('psn_application'); +end; +/ +show errors + +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +-- Those procedures will be deleted one after another once the analog ACS4 +-- stuff is done. + + +drop table sn_links; +drop table sn_link_types; +drop sequence sn_links_seq; +drop sequence psn_attachment_id_seq; Index: openacs-4/contrib/obsolete-packages/library/sql/oracle/library-functions.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/sql/oracle/library-functions.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/sql/oracle/library-functions.sql 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,13 @@ +create or replace function sn_check_type (p_object_id integer, + p_object_type_id integer) +return integer +as + result integer; +begin + select decode(object_type_id, p_object_type_id, 1, 0) into result + from sn_objects + where object_id=p_object_id; + return result; +end; +/ +show errors Index: openacs-4/contrib/obsolete-packages/library/sql/oracle/library-package-bodies.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/sql/oracle/library-package-bodies.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/sql/oracle/library-package-bodies.sql 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,1736 @@ +create or replace package body library +as + procedure copy ( + src_package_id in apm_packages.package_id%TYPE, + dst_package_id in apm_packages.package_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE + ) + is + begin + object_type.copy_all_object_types ( + src_package_id => src_package_id, + dst_package_id => dst_package_id, + creation_user => creation_user, + creation_ip => creation_ip + ); + + psn_res_application.copy ( + src_package_id => src_package_id, + dst_package_id => dst_package_id, + creation_user => creation_user, + creation_ip => creation_ip + ); + + end copy; + +end library; +/ +show errors + +create or replace package body object_type +as + procedure copy_all_object_types ( + src_package_id in acs_objects.context_id%TYPE, + dst_package_id in acs_objects.context_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE + ) + is + cursor c_questions (src_package_id integer) is + select question_id, pretty_name, abstract_data_type, presentation_type, + order_by, entry_explanation, tag_width, tag_height, help_text, + target_object_type_id, references_question_id, tree_id, node_id, + category_id, year_from, year_to, default_value, max_categories, + defaults_question_id + from sn_questions + where question_id in + (select map.question_id + from sn_question_object_type_map map, sn_object_types ot + where map.object_type_id = ot.object_type_id + and ot.context_id = src_package_id); + + cursor c_object_types (src_package_id integer) is + select object_type_id, short_name, pretty_name, pretty_plural, graphic, + graphic_p, deleted_p, browse_p, public_p, create_p, sort_key, + q1.new_id as new_short_description, q2.new_id as new_long_description, + q3.new_id as new_public_until, q4.new_id as new_linked_question_id, + default_age_filter, dst_package_id, archive_p, copy_p, + sweeper, sweeper_action, sweeper_warning_time, sweeper_outdated_time, + start_date, end_date + from sn_object_types ot, km_temp_questions q1, km_temp_questions q2, + km_temp_questions q3, km_temp_questions q4 + where ot.context_id = src_package_id + and q1.old_id(+) = ot.short_description + and q2.old_id(+) = ot.long_description + and q3.old_id(+) = ot.public_until + and q4.old_id(+) = ot.linked_question_id; + + cursor c_answer_options is + select option_id, tq.new_id as new_question_id, answer_option, sort_key + from sn_answer_options ao, km_temp_questions tq + where ao.question_id = tq.old_id; + v_new_question_id sn_questions.question_id%type; + v_new_object_type_id sn_object_types.object_type_id%type; + v_new_answer_option_id sn_answer_options.option_id%type; + v_count integer; + v_new_target_object_type_id integer; + begin + -- Clean up data from previous call in this transaction. + delete from km_temp_questions; + delete from km_temp_object_types; + delete from km_temp_answer_options; + + -- copy the questions + for c1 in c_questions(src_package_id) loop + v_new_question_id := question.insert_question ( + v_pretty_name => c1.pretty_name, + v_abstract_data_type => c1.abstract_data_type, + v_order_by => c1.order_by, + v_default_value => c1.default_value, + v_entry_explanation => c1.entry_explanation, + v_creation_user => creation_user, + v_creation_ip => creation_ip, + v_references_q_id => null); + + update sn_questions + set presentation_type=c1.presentation_type, tag_width=c1.tag_width, + tag_height = c1.tag_height, help_text = c1.help_text, tree_id = + c1.tree_id, node_id = c1.node_id, category_id = c1.category_id, + year_from = c1.year_from, year_to = c1.year_to, + target_object_type_id = c1.target_object_type_id, + max_categories = c1.max_categories, + defaults_question_id = c1.defaults_question_id + where question_id=v_new_question_id; + insert into km_temp_questions + (old_id, new_id) + values + (c1.question_id, v_new_question_id); + end loop; + + -- correct references_question_id + update sn_questions q + set references_question_id = (select new_id + from km_temp_questions + where old_id = q.references_question_id ) + where question_id in + (select old_id from km_temp_questions); + + -- correct defaults_question_id + update sn_questions q + set defaults_question_id = (select new_id + from km_temp_questions + where old_id = q.defaults_question_id ) + where question_id in + (select old_id from km_temp_questions); + + for c2 in c_object_types(src_package_id) loop + -- create the new object type + v_new_object_type_id := acs_object.new ( + object_type => 'sn_object_type', + creation_date => sysdate, + creation_user => creation_user, + creation_ip => creation_ip, + context_id => dst_package_id + ); + + insert into sn_object_types + (object_type_id, short_name, pretty_name, pretty_plural, graphic, + graphic_p, deleted_p, browse_p, public_p, create_p, sort_key, + short_description, long_description, public_until, linked_question_id, + default_age_filter, context_id, archive_p, copy_p, sweeper, + sweeper_action, sweeper_warning_time, sweeper_outdated_time, + start_date, end_date) + values + (v_new_object_type_id, c2.short_name, c2.pretty_name, c2.pretty_plural, c2.graphic, + c2.graphic_p, c2.deleted_p, c2.browse_p, c2.public_p, c2.create_p, c2.sort_key, + c2.new_short_description, c2.new_long_description, + c2.new_public_until, c2.new_linked_question_id, + c2.default_age_filter, c2.dst_package_id, c2.archive_p, + c2.copy_p, c2.sweeper, c2.sweeper_action, c2.sweeper_warning_time, + c2.sweeper_outdated_time, c2.start_date, c2.end_date); + + insert into km_temp_object_types + (old_id, new_id) + values + (c2.object_type_id, v_new_object_type_id); + end loop; + + -- now map the shortname + for c3 in (select tot.new_id as object_type_id, tq.new_id as short_description, map.position + from sn_types_map_short_name map, km_temp_questions tq, + km_temp_object_types tot + where map.short_description = tq.old_id + and map.object_type_id = tot.old_id) + loop + begin + insert into sn_types_map_short_name + (object_type_id, short_description, position) + values + (c3.object_type_id, c3.short_description, c3.position ); + exception + when others then + null; + end; + end loop; + + -- map the answer options + for c4 in c_answer_options loop + select acs_object_id_seq.nextval into v_new_answer_option_id from dual; + insert into sn_answer_options + (option_id, question_id, answer_option, sort_key) + values + (v_new_answer_option_id, c4.new_question_id, c4.answer_option, + c4.sort_key); + insert into km_temp_answer_options + (old_id, new_id) + values + (c4.option_id, v_new_answer_option_id); + end loop; + + -- -50 is the dummy question id + insert into km_temp_questions values (-50,-50); + + -- and now map the frigging questions to the more frigging object type + for c5 in (select tq1.new_id as new_question_id, tot.new_id as new_object_type_id, + sort_key, form_number, mandatory_p, question_state, tq2.new_id as + new_parent_question_id, branch_p, branch_operator, branch_answer, + tao.new_id as new_branch_answer_foreign_key, tq3.new_id as + new_default_branch + from sn_question_object_type_map map, km_temp_questions tq1, + km_temp_questions tq2, km_temp_questions tq3, km_temp_answer_options tao, + km_temp_object_types tot + where map.question_id = tq1.old_id + and map.object_type_id = tot.old_id + and map.parent_question_id = tq2.old_id(+) + and map.default_branch = tq3.old_id(+) + and map.branch_answer_foreign_key = tao.old_id(+)) loop + + begin + insert into sn_question_object_type_map + (question_id, object_type_id, sort_key, form_number, mandatory_p, + question_state, parent_question_id, branch_p, branch_operator, + branch_answer, branch_answer_foreign_key, default_branch) + values + (c5.new_question_id, c5.new_object_type_id, + c5.sort_key, c5.form_number, c5.mandatory_p, c5.question_state, + c5.new_parent_question_id, c5.branch_p, c5.branch_operator, c5.branch_answer, + c5.new_branch_answer_foreign_key, c5.new_default_branch); + exception + when others then + null; + end; + end loop; + -- and correct the target object type ids + for c6 in ( + select q2.target_object_type_id, q1.question_id + from sn_questions q1, sn_questions q2, + km_temp_questions tq + where q1.question_id = tq.new_id + and q2.question_id = tq.old_id + and q2.target_object_type_id is not null + and q1.question_id in + (select new_id from km_temp_questions) + ) loop + select new_id + into v_new_target_object_type_id + from km_temp_object_types tot + where tot.old_id = c6.target_object_type_id; + + update sn_questions q + set target_object_type_id = v_new_target_object_type_id + where question_id = c6.question_id; + end loop; + end copy_all_object_types; + + procedure copy_object_type ( + v_object_type_id in sn_object_types.object_type_id%TYPE, + v_target_context_id in acs_objects.context_id%TYPE, + v_creation_user in acs_objects.creation_user%TYPE, + v_creation_ip in acs_objects.creation_ip%TYPE + ) + is + cursor c_questions (v_object_type_id integer) is + select question_id, pretty_name, abstract_data_type, presentation_type, + order_by, entry_explanation, tag_width, tag_height, help_text, + target_object_type_id, references_question_id, tree_id, node_id, + category_id, year_from, year_to, default_value, max_categories, + defaults_question_id + from sn_questions + where question_id in + (select map.question_id + from sn_question_object_type_map map + where map.object_type_id = v_object_type_id); + cursor c_answer_options is + select option_id, tq.new_id as new_question_id, answer_option, sort_key + from sn_answer_options ao, km_temp_questions tq + where ao.question_id = tq.old_id; + v_new_question_id sn_questions.question_id%TYPE; + v_new_object_type_id sn_object_types.object_type_id%TYPE; + v_new_answer_option_id sn_answer_options.option_id%TYPE; + v_count integer; + begin + -- Clean up data from previous call in this transaction. + delete from km_temp_questions; + delete from km_temp_answer_options; + + -- copy the questions + -- target_object_type_id has to be nullified as it doesn't exist + -- in the target community + for c1 in c_questions(v_object_type_id) loop + v_new_question_id := question.insert_question ( + v_pretty_name => c1.pretty_name, + v_abstract_data_type => c1.abstract_data_type, + v_order_by => c1.order_by, + v_default_value => c1.default_value, + v_entry_explanation => c1.entry_explanation, + v_creation_user => v_creation_user, + v_creation_ip => v_creation_ip, + v_references_q_id => null); + update sn_questions + set presentation_type=c1.presentation_type, tag_width=c1.tag_width, + tag_height = c1.tag_height, help_text = c1.help_text, tree_id = + c1.tree_id, node_id = c1.node_id, category_id = c1.category_id, + year_from = c1.year_from, year_to = c1.year_to, + max_categories = c1.max_categories, + defaults_question_id = c1.defaults_question_id + where question_id=v_new_question_id; + insert into km_temp_questions + (old_id, new_id) + values + (c1.question_id, v_new_question_id); + end loop; + + -- correct references_question_id + update sn_questions q + set references_question_id = (select new_id + from km_temp_questions + where old_id = q.references_question_id ) + where question_id in + (select old_id from km_temp_questions); + + -- correct defaults_question_id + update sn_questions q + set defaults_question_id = (select new_id + from km_temp_questions + where old_id = q.defaults_question_id ) + where question_id in + (select old_id from km_temp_questions); + + -- create the new object type + v_new_object_type_id := acs_object.new ( + object_type => 'sn_object_type', + creation_date => sysdate, + creation_user => v_creation_user, + creation_ip => v_creation_ip, + context_id => v_target_context_id + ); + + insert into sn_object_types + (object_type_id, short_name, pretty_name, pretty_plural, graphic, + graphic_p, deleted_p, browse_p, public_p, create_p, sort_key, + short_description, long_description, public_until, linked_question_id, + default_age_filter, context_id, archive_p, copy_p, sweeper, + sweeper_action, sweeper_warning_time, sweeper_outdated_time, + start_date, end_date) + (select v_new_object_type_id, short_name, pretty_name, pretty_plural, graphic, + graphic_p, deleted_p, browse_p, public_p, create_p, sort_key, + q1.new_id as new_short_description, q2.new_id as new_long_description, + q3.new_id as new_public_until, q4.new_id as new_linked_question_id, + default_age_filter, v_target_context_id, archive_p, copy_p, sweeper, + sweeper_action, sweeper_warning_time, sweeper_outdated_time, + start_date, end_date + from sn_object_types ot, km_temp_questions q1, km_temp_questions q2, + km_temp_questions q3, km_temp_questions q4 + where ot.object_type_id = v_object_type_id + and q1.old_id(+) = ot.short_description + and q2.old_id(+) = ot.long_description + and q3.old_id(+) = ot.public_until + and q4.old_id(+) = ot.linked_question_id); + + -- now map the shortname + insert into sn_types_map_short_name + (object_type_id, short_description, position ) + (select v_new_object_type_id, tq.new_id, map.position + from sn_types_map_short_name map, km_temp_questions tq + where map.short_description = tq.old_id); + + -- map the answer options + for c3 in c_answer_options loop + select acs_object_id_seq.nextval into v_new_answer_option_id from dual; + insert into sn_answer_options + (option_id, question_id, answer_option, sort_key) + values + (v_new_answer_option_id, c3.new_question_id, c3.answer_option, + c3.sort_key); + insert into km_temp_answer_options + (old_id, new_id) + values + (c3.option_id, v_new_answer_option_id); + end loop; + + -- -50 is the dummy question id + insert into km_temp_questions values (-50,-50); + + -- and now map the frigging questions to the more frigging object type + insert into sn_question_object_type_map + (question_id, object_type_id, sort_key, form_number, mandatory_p, + question_state, parent_question_id, branch_p, branch_operator, + branch_answer, branch_answer_foreign_key, default_branch) + (select tq1.new_id as new_question_id, v_new_object_type_id, + sort_key, form_number, mandatory_p, question_state, tq2.new_id as + new_parent_question_id, branch_p, branch_operator, branch_answer, + tao.new_id as new_branch_answer_foreign_key, tq3.new_id as + new_default_branch + from sn_question_object_type_map map, km_temp_questions tq1, + km_temp_questions tq2, km_temp_questions tq3, km_temp_answer_options tao + where map.question_id = tq1.old_id + and map.parent_question_id = tq2.old_id(+) + and map.default_branch = tq3.old_id(+) + and map.branch_answer_foreign_key = tao.old_id(+)); + end copy_object_type; + + procedure delete_all_object_types ( + v_context_id in acs_objects.context_id%TYPE default null + ) + is + cursor c_delete_all_object_types is + select object_type_id + from sn_object_types + where context_id = v_context_id; + begin + for v_delete_all_object_types in c_delete_all_object_types loop + object_type.delete_object_type(v_delete_all_object_types.object_type_id); + end loop; + end delete_all_object_types; + + function insert_object_type ( + v_pretty_name in sn_object_types.pretty_name%TYPE, + v_pretty_plural in sn_object_types.pretty_plural%TYPE, + v_graphic in sn_object_types.graphic%TYPE, + v_deleted_p in sn_object_types.deleted_p%TYPE, + v_browse_p in sn_object_types.browse_p%TYPE, + v_public_p in sn_object_types.public_p%TYPE, + v_sort_key in sn_object_types.sort_key%TYPE, + v_short_description in sn_object_types.short_description%TYPE, + v_long_description in sn_object_types.long_description%TYPE, + v_linked_question_id in sn_object_types.linked_question_id%TYPE, + v_public_until in sn_object_types.public_until%TYPE, + v_default_age_filter in sn_object_types.default_age_filter%TYPE, + v_creation_user in acs_objects.creation_user%TYPE default null, + v_creation_ip in acs_objects.creation_ip%TYPE default null, + v_context_id in acs_objects.context_id%TYPE, + v_short_name in sn_object_types.short_name%TYPE default null, + v_insertion_date in acs_objects.creation_date%TYPE default sysdate + ) return sn_object_types.object_type_id%TYPE + is + v_return_object_type_id acs_objects.object_id%TYPE; + begin + v_return_object_type_id := acs_object.new ( + object_type => 'sn_object_type', + creation_date => v_insertion_date, + creation_user => v_creation_user, + creation_ip => v_creation_ip, + context_id => v_context_id + ); + + insert into sn_object_types + (object_type_id,pretty_name, pretty_plural, graphic, deleted_p, + browse_p, public_p, sort_key, long_description, + public_until, default_age_filter,context_id, short_name ) + values (v_return_object_type_id,v_pretty_name, v_pretty_plural, + v_graphic, v_deleted_p, v_browse_p, v_public_p, v_sort_key, + v_long_description, v_public_until, + v_default_age_filter, v_context_id, v_short_name); + + -- this function is _only_ used by the migration scripts. In the past + -- we didn't have composite short descriptions. Hence the hack here is + -- more than okay. + + if v_short_description is not null then + insert into sn_types_map_short_name + (object_type_id, short_description, position) + values + (v_return_object_type_id, v_short_description, 1); + end if; + return v_return_object_type_id; + end insert_object_type; + + + function insert_object_type ( + v_pretty_name in sn_object_types.pretty_name%TYPE, + v_pretty_plural in sn_object_types.pretty_plural%TYPE, + v_browse_p in sn_object_types.browse_p%TYPE, + v_default_age_filter in sn_object_types.default_age_filter%TYPE, + v_creation_user in acs_objects.creation_user%TYPE default null, + v_creation_ip in acs_objects.creation_ip%TYPE default null, + v_context_id in acs_objects.context_id%TYPE default null, + v_short_name in sn_object_types.short_name%TYPE default null, + v_insertion_date in acs_objects.creation_date%TYPE default sysdate + ) return sn_object_types.object_type_id%TYPE + is + v_return_object_type_id acs_objects.object_id%TYPE; + begin + v_return_object_type_id := acs_object.new ( + object_type => 'sn_object_type', + creation_date => v_insertion_date, + creation_user => v_creation_user, + creation_ip => v_creation_ip, + context_id => v_context_id + ); + + insert into sn_object_types + (object_type_id,pretty_name, pretty_plural, + browse_p, default_age_filter, context_id, short_name ) + values (v_return_object_type_id,v_pretty_name, v_pretty_plural, + v_browse_p, v_default_age_filter, v_context_id, v_short_name); + + return v_return_object_type_id; + end insert_object_type; + + procedure delete_object_type ( + v_object_type_id in sn_object_types.object_type_id%TYPE + ) + is + cursor cur_question_object_type_map is + select question_id + from sn_question_object_type_map + where object_type_id = v_object_type_id; + begin + object.delete_all_objects_of_a_type(v_object_type_id); + + update sn_object_types set + long_description = null, + linked_question_id = null, + public_until = null + where object_type_id = v_object_type_id; + + update sn_questions + set target_object_type_id = null + where target_object_type_id = v_object_type_id; + + for v_question_object_type_map in cur_question_object_type_map loop + question.delete_question(v_question_object_type_map.question_id); + end loop; + + delete from sn_types_map_short_name where object_type_id = v_object_type_id; + delete from sn_table_name_map where object_type_id = v_object_type_id; + delete from acs_permissions where object_id = v_object_type_id; + acs_object.delete(v_object_type_id); + delete from sn_object_types where object_type_id=v_object_type_id; + end delete_object_type; + +end object_type; +/ +show errors + +-- @cvs-id $Id: library-package-bodies.sql,v 1.1 2003/07/02 12:19:42 peterm Exp $ +-- turn off sql plus variables substitution +set define off + +create or replace package body object +as + function name ( + object_id in sn_objects.object_id%TYPE + ) return varchar2 + is + v_result sn_objects.one_line_description%TYPE; + begin + select nvl(one_line_description,'Unnamed ' || ot.pretty_name) into v_result + from sn_objects o, sn_object_types ot + where o.object_type_id = ot.object_type_id + and o.object_id = name.object_id; + + return v_result; + end name; + + + procedure save_content ( + v_object_id in sn_objects.object_id%TYPE, + v_question_id in sn_questions.question_id%TYPE, + v_html_p in sn_content.html_p%TYPE, + v_content_length in integer, + v_modifying_user in acs_objects.creation_user%TYPE, + v_modifying_ip in acs_objects.modifying_ip%TYPE, + v_update_date in acs_objects.last_modified%TYPE default sysdate + ) + is + v_count_exists integer default 0; + begin + update sn_objects + set last_modified = v_update_date, + last_modifying_user_id = v_modifying_user + where object_id = v_object_id; + + update acs_objects_description + set datastore = 'a' + where object_id = v_object_id; + + acs_object.last_modified ( + v_object_id => v_object_id, + v_modifying_user => v_modifying_user, + v_modifying_ip => v_modifying_ip, + v_last_modified => v_update_date); + + select count(*) + into v_count_exists + from sn_content + where object_id=v_object_id + and question_id=v_question_id; + + if v_count_exists = 0 then + insert into sn_content (object_id, question_id, html_p) + values (v_object_id, v_question_id, v_html_p); + else + if v_content_length = 0 then + delete from sn_content + where object_id=v_object_id + and question_id=v_question_id; + else + update sn_content + set html_p = v_html_p + where object_id=v_object_id + and question_id=v_question_id; + end if; + end if; + end save_content; + + function insert_object ( + v_object_type_id in sn_objects.object_type_id%TYPE, + v_creation_user in acs_objects.creation_user%TYPE default null, + v_creation_ip in acs_objects.creation_ip%TYPE default null, + v_context_id in acs_objects.context_id%TYPE default null, + v_insertion_date in acs_objects.creation_date%TYPE default sysdate + ) return sn_objects.object_id%TYPE + is + v_return_object_id acs_objects.object_id%TYPE; + begin + v_return_object_id := acs_object.new ( + object_type => 'sn_object', + creation_date => v_insertion_date, + creation_user => v_creation_user, + creation_ip => v_creation_ip, + context_id => v_context_id + ); + + insert into sn_objects + (object_id, original_author_id, creation_date, last_modifying_user_id, + last_modified, object_type_id,context_id) + values (v_return_object_id, v_creation_user, v_insertion_date, v_creation_user, + v_insertion_date, v_object_type_id,v_context_id); + + return v_return_object_id; + end insert_object; + + + function insert_object ( + v_object_id in acs_objects.object_id%TYPE, + v_object_type_id in sn_objects.object_type_id%TYPE, + v_creation_user in acs_objects.creation_user%TYPE default null, + v_creation_ip in acs_objects.creation_ip%TYPE default null, + v_context_id in acs_objects.context_id%TYPE default null, + v_insertion_date in acs_objects.creation_date%TYPE default sysdate + ) return sn_objects.object_id%TYPE + is + v_return_object_id acs_objects.object_id%TYPE; + begin + v_return_object_id := acs_object.new ( + object_id => v_object_id, + object_type => 'sn_object', + creation_date => v_insertion_date, + creation_user => v_creation_user, + creation_ip => v_creation_ip, + context_id => v_context_id + ); + + insert into sn_objects + (object_id, original_author_id, creation_date, last_modifying_user_id, + last_modified, object_type_id,context_id) + values (v_return_object_id, v_creation_user, v_insertion_date, v_creation_user, + v_insertion_date, v_object_type_id,v_context_id); + + return v_return_object_id; + end insert_object; + + + function copy_object ( + v_object_id in acs_objects.object_id%TYPE, + v_target_id in acs_objects.object_id%TYPE default null, + v_creation_user in acs_objects.creation_user%TYPE default null, + v_creation_ip in acs_objects.creation_ip%TYPE default null, + v_context_id in acs_objects.context_id%TYPE default null + ) return sn_objects.object_id%TYPE + is + v_new_link_id sn_links.link_id%TYPE; + v_return_object_id acs_objects.object_id%TYPE; + begin + v_return_object_id := acs_object.new ( + object_type => 'sn_object', + object_id => v_target_id, + creation_date => sysdate, + creation_user => v_creation_user, + creation_ip => v_creation_ip, + context_id => v_context_id + ); + + acs_object.last_modified ( + v_object_id => v_return_object_id, + v_modifying_user => v_creation_user, + v_modifying_ip => v_creation_ip, + v_last_modified => sysdate + ); + + -- copy sn_object + insert into sn_objects + (object_id, object_type_id, context_id, one_line_description, + overview, overview_html_p, creation_date, original_author_id, + last_modified, last_modifying_user_id, user_checkoff_date, + public_until, public_p, archived_p, access_total, + access_month, archiving_date, outdated_warning_date, + expired_warning_date) + (select v_return_object_id as object_id, object_type_id, context_id, + one_line_description, overview, overview_html_p, + sysdate as creation_date, v_creation_user as original_author_id, + sysdate as last_modified, v_creation_user as last_modifying_user_id, + null as user_checkoff_date, public_until, 'f' as public_p, + 'f' as archived_p, 0 as access_total, 0 as access_month, + null as archiving_date, null as outdated_warning_date, + null as expired_warning_date + from sn_objects o + where o.object_id = v_object_id); + + -- copy categories + insert into sw_object_category_map (category_id, object_id) + (select category_id, v_return_object_id as object_id + from sw_object_category_map ocm + where ocm.object_id = v_object_id); + + -- copy options + insert into sn_object_option_map (object_id, option_id) + (select v_return_object_id as object_id, option_id + from sn_object_option_map oom + where oom.object_id = v_object_id + and oom.option_id in (select ao.option_id + from sn_question_object_type_map qotm, + sn_objects o, sn_answer_options ao + where qotm.object_type_id = o.object_type_id + and qotm.question_state = 'active' + and qotm.question_id = ao.question_id + and o.object_id = v_object_id) ); + + -- copy content + insert into sn_content (object_id, question_id, content, html_p) + (select v_return_object_id as object_id, question_id, content, html_p + from sn_content c + where c.object_id = v_object_id + and c.question_id in (select qotm.question_id + from sn_question_object_type_map qotm, + sn_objects o + where qotm.object_type_id = o.object_type_id + and qotm.question_state = 'active' + and o.object_id = v_object_id) ); + + -- copy links + for link in (select qlm.link_id, qlm.question_id + from sn_question_link_map qlm, sn_objects o, + sn_question_object_type_map qotm, sn_links l + where qotm.object_type_id = o.object_type_id + and qotm.question_state = 'active' + and qlm.question_id = qotm.question_id + and l.link_id = qlm.link_id + and l.link_type = 'bi_directional' + and o.object_id = v_object_id + and l.object_id_a = o.object_id) + loop + select sn_links_seq.nextval into v_new_link_id from dual; + + insert into sn_links + (link_id, link_type, object_id_a, object_id_b, link_comment, + html_p, creation_user, creation_date) + (select v_new_link_id, link_type, + decode(object_id_a,v_object_id,v_return_object_id,object_id_a), + decode(object_id_b,v_object_id,v_return_object_id,object_id_b), + link_comment, html_p, v_creation_user as creation_user, + sysdate as creation_date + from sn_links l + where l.link_id = link.link_id); + + insert into sn_question_link_map (link_id, question_id) + values (v_new_link_id, link.question_id); + end loop; + + return v_return_object_id; + end copy_object; + + procedure audit_object ( + v_object_id in sn_objects.object_id%TYPE, + v_question_id in sn_questions.question_id%TYPE, + v_last_modifying_user_id in acs_objects.modifying_ip%TYPE, + v_modifying_ip in acs_objects.modifying_ip%TYPE, + v_content in sn_audit_table.content%TYPE, + v_last_modified in acs_objects.last_modified%TYPE default sysdate + ) + is + begin + insert into sn_audit_table + (object_id, question_id, last_modified, last_modifying_user_id, content) + values (v_object_id, v_question_id, v_last_modified, v_last_modifying_user_id, v_content); + + update sn_objects + set last_modified = v_last_modified, + last_modifying_user_id = v_last_modifying_user_id, + outdated_warning_date = null + where object_id = v_object_id; + + update acs_objects_description + set datastore = 'a' + where object_id = v_object_id; + + acs_object.last_modified ( + v_object_id => v_object_id, + v_modifying_user => v_last_modifying_user_id, + v_modifying_ip => v_modifying_ip, + v_last_modified => v_last_modified); + end audit_object; + + procedure delete_object ( + v_object_id in sn_objects.object_id%TYPE + ) + is + cursor sn_comments is + select comment_id + from sn_comments + where object_id= v_object_id; + cursor bookmarks is + select bookmark_id + from bm_bookmarks + where object_id= v_object_id; + + begin + delete from recommendations_log + where object_id = v_object_id; + delete from sn_question_link_map where link_id in + (select link_id + from sn_links + where object_id_a = v_object_id or object_id_b=v_object_id); + delete from psn_attachments where application_id in + (select application_id + from psn_res_applications + where object_id=v_object_id); + delete from psn_res_application_roles where application_id in + (select application_id + from psn_res_applications + where object_id=v_object_id); + delete from psn_res_applications where object_id=v_object_id; + delete from sn_links where object_id_a = v_object_id or object_id_b=v_object_id; + delete from user_alert_history where object_id=v_object_id; + delete from alerts where object_id=v_object_id; + delete from user_alerts where object_id=v_object_id; + for cur_val in bookmarks loop + acs_object.delete(cur_val.bookmark_id); + delete from bm_bookmarks where bookmark_id=cur_val.bookmark_id; + end loop; + + delete from bm_shopping_cart where object_id= v_object_id; + -- ratings + for cur_val in sn_comments loop + acs_object.delete(cur_val.comment_id); + end loop; + delete from sn_owner_history where object_id=v_object_id; + delete from sn_content where object_id=v_object_id; + delete from sn_audit_table where object_id=v_object_id; + delete from sn_object_delete_reasons where object_id=v_object_id; + delete from sn_object_option_map where object_id=v_object_id; + delete from sn_access_counts where object_id = v_object_id; + delete from acs_permissions where object_id = v_object_id; + delete from sn_objects where object_id=v_object_id; + acs_object.delete(v_object_id); + end; + + procedure delete_all_objects_of_a_type ( + v_object_type_id in sn_object_types.object_type_id%TYPE + ) + is + cursor cur_objects_of_a_type is + select object_id + from sn_objects + where object_type_id = v_object_type_id; + rows_processed boolean ; + begin + -- delete dependencies + update acs_objects set context_id=null where context_id in (select object_id + from sn_objects + where object_type_id = v_object_type_id); + + delete from user_alert_history where content_type_id=v_object_type_id; + delete from alerts where content_type_id=v_object_type_id; + delete from user_alerts where content_type_id=v_object_type_id; + for v_objects_of_a_type in cur_objects_of_a_type loop + object.delete_object(v_objects_of_a_type.object_id); + end loop; + end; + + procedure delete_all_objects_of_an_inst ( + v_context_id in acs_objects.context_id%TYPE + ) + is + begin + for v_all_objects_of_inst in ( + select object_id from sn_objects + where context_id = v_context_id + ) + loop + object.delete_object(v_all_objects_of_inst.object_id); + end loop; + end; + +end object; +/ +show errors + +create or replace package body question +as + -- Returns true if this question is a root of a branch (at any level) + function root_branch_p ( + v_question_id in sn_questions.question_id%TYPE + ) return char + is + v_result char(1); + begin + select decode(count(*),0,'f','t') + into v_result + from sn_question_object_type_map + where parent_question_id=v_question_id and branch_p='t'; + + return v_result; + end root_branch_p; + + PROCEDURE map_question_on_object ( + v_question_id in sn_questions.question_id%TYPE, + v_object_type_id in sn_objects.object_type_id%TYPE, + v_form_number in sn_question_object_type_map.form_number%TYPE, + v_mandatory_p in sn_question_object_type_map.mandatory_p%TYPE, + v_question_state in sn_question_object_type_map.question_state%TYPE + ) IS + v_max_sort_key sn_question_object_type_map.sort_key%TYPE; + BEGIN + select max(sort_key) + into v_max_sort_key + from sn_question_object_type_map + where object_type_id = v_object_type_id; + + v_max_sort_key := v_max_sort_key + 10; + insert into sn_question_object_type_map + (object_type_id, question_id, form_number, mandatory_p, question_state, branch_p, sort_key) + values (v_object_type_id, v_question_id, v_form_number, v_mandatory_p, v_question_state, 'f', v_max_sort_key); + -- DIRK: update last_modified_date + END map_question_on_object; + + PROCEDURE delete_question ( + v_question_id in sn_questions.question_id%TYPE + ) + is + cursor cur_child_questions is + select question_id + from sn_question_object_type_map + where parent_question_id = v_question_id; + begin + -- nullify all short or long descriptions or linked_question-id or + -- public_until + delete from sn_types_map_short_name + where short_description = v_question_id; + + update sn_object_types set + short_description = null + where short_description = v_question_id; + + update sn_object_types set + long_description = null + where long_description = v_question_id; + + update sn_object_types set + linked_question_id = null + where linked_question_id = v_question_id; + + update sn_object_types set + public_until = null + where public_until = v_question_id; + + update sn_questions set + references_question_id = null + where references_question_id = v_question_id; + + -- delete all child questions + for v_child_questions in cur_child_questions loop + question.delete_question(v_child_questions.question_id); + end loop; + + delete from sn_links where link_id in + (select link_id + from sn_question_link_map + where question_id = v_question_id); + delete from sn_question_link_map + where question_id = v_question_id; + delete from sn_question_object_type_map + where question_id = v_question_id; + delete from sn_content where question_id = v_question_id; + delete from sn_audit_table where question_id = v_question_id; + delete from sn_object_option_map where option_id in (select option_id + from sn_answer_options where question_id = v_question_id); + delete from sn_answer_options where question_id = v_question_id; + + acs_object.delete(v_question_id); + delete from sn_questions where question_id = v_question_id; + end delete_question; + + function insert_question ( + v_question_id in sn_questions.question_id%TYPE default null, + v_pretty_name in sn_questions.pretty_name%TYPE, + v_abstract_data_type in sn_questions.abstract_data_type%TYPE, + v_order_by in sn_questions.order_by%TYPE, + v_default_value in sn_questions.default_value%TYPE, + v_entry_explanation in sn_questions.entry_explanation%TYPE, + v_creation_user in acs_objects.creation_user%TYPE default null, + v_creation_ip in acs_objects.creation_ip%TYPE default null, + v_context_id in acs_objects.context_id%TYPE default null, + v_insertion_date in acs_objects.creation_date%TYPE default sysdate, + v_references_q_id in sn_questions.question_id%TYPE + ) return sn_questions.question_id%TYPE + is + v_return_question_id acs_objects.object_id%TYPE; + v_presentation_type sn_questions.presentation_type%TYPE; + v_max_sort_key sn_question_object_type_map.sort_key%TYPE; + begin + if v_question_id is null then + v_return_question_id := acs_object.new ( + object_type => 'sn_question', + creation_date => v_insertion_date, + creation_user => v_creation_user, + creation_ip => v_creation_ip, + context_id => null + ); + else + v_return_question_id := acs_object.new ( + object_id => v_question_id, + object_type => 'sn_question', + creation_date => v_insertion_date, + creation_user => v_creation_user, + creation_ip => v_creation_ip, + context_id => null + ); + end if; + + if v_abstract_data_type = 'category' then + v_presentation_type := 'select'; + elsif v_abstract_data_type = 'other_category' then + v_presentation_type := 'select'; + elsif v_abstract_data_type = 'option' then + v_presentation_type := 'select'; + elsif v_abstract_data_type = 'integer' then + v_presentation_type := 'shorttext'; + else + v_presentation_type := 'custom'; + end if; + + insert into sn_questions + (question_id, pretty_name, abstract_data_type, presentation_type, + order_by, default_value, entry_explanation, references_question_id) + values + (v_return_question_id, v_pretty_name, v_abstract_data_type, + v_presentation_type, v_order_by, v_default_value, v_entry_explanation, v_references_q_id); + + return v_return_question_id; + end insert_question; + + procedure update_question ( + v_question_id in sn_questions.question_id%TYPE, + v_pretty_name in sn_questions.pretty_name%TYPE, + v_abstract_data_type in sn_questions.abstract_data_type%TYPE, + v_order_by in sn_questions.order_by%TYPE, + v_default_value in sn_questions.default_value%TYPE, + v_entry_explanation in sn_questions.entry_explanation%TYPE, + v_modifying_user in acs_objects.creation_user%TYPE, + v_modifying_ip in acs_objects.modifying_ip%TYPE, + v_update_date in acs_objects.last_modified%TYPE default sysdate, + v_references_q_id in sn_questions.question_id%TYPE, + v_def_question_id in sn_questions.question_id%TYPE default null, + v_max_categories in sn_questions.max_categories%TYPE default null, + v_browse_p in sn_questions.browse_p%TYPE default 't' + ) + is + begin + update sn_questions + set pretty_name = v_pretty_name, + entry_explanation = v_entry_explanation, + abstract_data_type = v_abstract_data_type, + order_by = v_order_by, + default_value = v_default_value, + references_question_id = v_references_q_id, + defaults_question_id = v_def_question_id, + max_categories = v_max_categories, + browse_p = v_browse_p + where question_id = v_question_id; + acs_object.last_modified ( + v_object_id => v_question_id, + v_modifying_user => v_modifying_user, + v_modifying_ip => v_modifying_ip, + v_last_modified => v_update_date); + end update_question; + + procedure delete_all_questions( + v_context_id in acs_objects.context_id%TYPE default null + ) is + cursor c_delete_all_questions is + select q.question_id + from sn_questions q, sn_question_object_type_map map, sn_object_types ot + where ot.context_id = v_context_id + and ot.object_type_id = map.object_type_id + and map.question_id = q.question_id; + begin + for v_delete_all_questions in c_delete_all_questions loop + question.delete_question(v_delete_all_questions.question_id); + end loop; + end delete_all_questions; +end question; +/ +show errors + + +create or replace package body km_utilities +as + function km_ancestor_list ( + v_object_id in integer) + return varchar + is + result varchar(4000); + begin + for c1_rec in ( + select '{' || sno.object_id || ' {' || sno.one_line_description || '}}' as l + from sn_objects sno, km_flat_object_hierarchy fo + where fo.child = v_object_id and fo.parent = sno.object_id + order by distance desc + ) + loop + result := concat(result, c1_rec.l || ' '); + end loop; + return substr(result, 1, length(result) - 1); + end km_ancestor_list; + + function km_category_list ( + v_object_id in integer, + v_parent_node_id in varchar) + return varchar + is + the_list varchar(4000); + begin + for c1_rec in ( + select long_name + from categories c, sw_flat_cat fc, sw_object_category_map cm + where fc.parent = v_parent_node_id + and fc.child_category_id = c.category_id + and cm.category_id = c.category_id + and cm.object_id = v_object_id + ) + loop + the_list := concat(the_list, c1_rec.long_name || ', '); + end loop; + return substr(the_list, 1, length(the_list) - 2); + end km_category_list; + + function km_string2xml (str varchar2) return varchar2 + is + retval varchar2(4000); + begin + retval := replace(str,'&','&'); + retval := replace(retval,'<','<'); + retval := replace(retval,'>','>'); + return retval; + end km_string2xml; + + procedure km_clob2xml (dest in out clob, source in clob) + is + offset integer := 1; + len integer; + text varchar2(4000); + begin + len := dbms_lob.getlength(source); + WHILE len > offset LOOP + text := DBMS_LOB.SUBSTR(source,3000, offset); + text := replace(text,'&','&'); + text := replace(text,'<','<'); + text := replace(text,'>','>'); + dbms_lob.writeappend(dest,length(text),text); + offset := offset + 3000; + END LOOP; + end km_clob2xml; + + procedure km_string2xmlclob (dest in out clob, source varchar2) + is + offset integer := 1; + len integer; + text varchar2(4000); + begin + len := length(source); + WHILE len > offset LOOP + text := substr(source,offset,3000); + text := replace(text,'&','&'); + text := replace(text,'<','<'); + text := replace(text,'>','>'); + dbms_lob.writeappend(dest,length(text),text); + offset := offset + 3000; + END LOOP; + end km_string2xmlclob; + + function km_xml ( id sn_objects.object_id%type) RETURN CLOB + is + v_pretty_name sn_object_types.pretty_name%TYPE; + + -- CONSTANTS + CR CONSTANT VARCHAR2(2) := CHR(13); + sn_objects_rec sn_objects%ROWTYPE; + CURSOR km_cursor (p_object_type_id integer) IS + SELECT b.question_id, b.pretty_name, b.abstract_data_type + FROM sn_question_object_type_map a, sn_questions b + WHERE a.object_type_id = p_object_type_id + AND a.question_id = b.question_id + AND abstract_data_type NOT IN (/*'child_object',*/ 'file', /*'user_link',*/ 'composite') + AND question_state <> 'invisible' + ORDER BY sort_key; + + CURSOR km_category (p_object_id integer) IS + SELECT c.category_id, c.short_name + FROM sw_object_category_map m, categories c + WHERE m.object_id = p_object_id + AND c.category_id = m.category_id; + + CURSOR g_comments (p_object_id integer) IS + SELECT content FROM sn_comments WHERE object_id = p_object_id; + + CURSOR km_links (p_object_id integer, p_question_id integer) IS + SELECT c.object_id linked_id, b.link_type link_type, b.object_id_b + FROM sn_links b, sn_objects c, sn_question_link_map map + WHERE b.object_id_a = p_object_id + AND b.link_id = map.link_id + AND map.question_id = p_question_id + AND b.object_id_b = c.object_id + and c.object_id is not null; + + CURSOR km_content (p_object_id integer, p_question_id integer) IS + SELECT dbms_lob.substr(content,3999,1) answer FROM sn_content WHERE object_id = p_object_id AND question_id = p_question_id and content is not null + UNION + SELECT answer_option answer + FROM sn_object_option_map a, sn_answer_options b + WHERE a.object_id = p_object_id + AND a.option_id = b.option_id + AND b.question_id = p_question_id; + tag_object varchar2(4000); + tag_owner varchar(300); + tag_text varchar(4000); + tag_category varchar(4000); + tag_comments clob; + tag_content clob; + text varchar (4000); + + i integer; + + /* -- VARIABLES -- */ + tlob clob; /* variable for store function output*/ + BEGIN + DBMS_LOB.CREATETEMPORARY(tlob, TRUE, DBMS_LOB.SESSION); + -- prepare temorary lob for store COMMENTS tag + DBMS_LOB.CREATETEMPORARY(tag_comments, TRUE, DBMS_LOB.SESSION); + -- prepare temorary lob for store object_content tag + DBMS_LOB.CREATETEMPORARY(tag_content, TRUE, DBMS_LOB.SESSION); + + -- get various info on table and columns to index + SELECT * INTO sn_objects_rec FROM sn_objects WHERE object_id = id ; + + SELECT pretty_name + into v_pretty_name + FROM sn_object_types a + WHERE a.object_type_id = sn_objects_rec.object_type_id; + + v_pretty_name := km_string2xml(v_pretty_name); + + SELECT ''||CR||''||CR + INTO tag_object + FROM sn_object_types a + WHERE a.object_type_id = sn_objects_rec.object_type_id; + + -- get contents for OWNER tag + IF sn_objects_rec.original_author_id IS NOT NULL THEN + SELECT first_names || ' ' || last_name INTO tag_owner FROM users WHERE user_id = sn_objects_rec.original_author_id; + tag_owner := ' '||km_string2xml(tag_owner)||''||CR; + END IF; + + -- get content for CATEGORY tag + FOR ccat IN km_category(sn_objects_rec.object_id) LOOP + tag_category := tag_category || ' '||km_string2xml(ccat.short_name)||''||CR; + END LOOP; + + -- get content for COMMENTS tag + -- at first look in general_comments table + FOR gcom IN g_comments (sn_objects_rec.object_id) LOOP + if nvl(dbms_lob.getlength(gcom.content),0) > 0 then + DBMS_LOB.WRITEAPPEND(tag_comments, length(' '), ' '); + km_clob2xml(tag_comments, gcom.content); + DBMS_LOB.WRITEAPPEND(tag_comments, length(' '||CR), ' '||CR); + end if; + END LOOP; + + FOR cc IN km_cursor (sn_objects_rec.object_type_id) LOOP + i := 0; + FOR c1 IN km_content(sn_objects_rec.object_id, cc.question_id) LOOP + IF i = 0 THEN + text := ' '||CR; + DBMS_LOB.WRITEAPPEND(tag_content,length(text),text); + i := 1; + END IF; + DBMS_LOB.WRITEAPPEND(tag_content, length(' '), ' '); + + km_string2xmlclob(tag_content, c1.answer); + DBMS_LOB.WRITEAPPEND(tag_content, length(''||CR), ''||CR); + END LOOP; + FOR c2 IN km_links(id, cc.question_id) LOOP + IF i = 0 THEN + text := ' '||CR; + DBMS_LOB.WRITEAPPEND(tag_content,length(text),text); + i := 1; + END IF; + text := ' '||CR; + DBMS_LOB.WRITEAPPEND(tag_content, length(text), text); + END LOOP; + IF i <> 0 THEN + DBMS_LOB.WRITEAPPEND(tag_content,length(' '||CR),' '||CR); + END IF; + END LOOP; + + -- Construct XML DOC + DBMS_LOB.WRITEAPPEND (tlob,length(tag_object),tag_object); + DBMS_LOB.WRITEAPPEND (tlob,length(tag_owner),tag_owner); + IF tag_category is not null THEN + DBMS_LOB.WRITEAPPEND (tlob,length(tag_category),tag_category); + END IF; + DBMS_LOB.APPEND(tlob,tag_comments); + DBMS_LOB.APPEND (tlob,tag_content); + DBMS_LOB.WRITEAPPEND (tlob,9 ,''); + return tlob; + END km_xml; + + procedure km_populate_flat_object_hier + IS + CURSOR child_cursor IS + select object_id_b as object_id from sn_links where link_type in ('parent_child','uncle_nephew'); + BEGIN + delete from km_flat_object_hierarchy; + + FOR child IN child_cursor LOOP + insert into km_flat_object_hierarchy + select acs_object_id_seq.nextval, object_id_a, child.object_id, level, link_type + from sn_links start with object_id_b = child.object_id and link_type in ('parent_child','uncle_nephew') + connect by object_id_b = prior object_id_a and link_type in ('parent_child','uncle_nephew'); + END LOOP; + END km_populate_flat_object_hier; + + procedure km_logger ( + v_who_is_logging varchar2, + v_log_text varchar2) + as + pragma autonomous_transaction; + begin + insert into km_logger_table values (sysdate, v_who_is_logging, v_log_text ); + commit; + end km_logger; + + function shortname_string (p_object_id in sn_objects.object_id%TYPE, + p_question_id1 in sn_questions.question_id%TYPE, + p_question_id2 in sn_questions.question_id%TYPE, + p_question_id3 in sn_questions.question_id%TYPE default 0) + return varchar2 + is + v_result_string varchar2(4000) := ''; + v_result_string1 varchar2(4000) := ''; + v_result_string2 varchar2(4000) := ''; + v_result_string3 varchar2(4000) := ''; + v_length_string1 integer; + v_length_string2 integer; + v_length_string3 integer; + begin + begin + select trim(dbms_lob.substr(content,1300,1)) + into v_result_string1 + from sn_content + where question_id=p_question_id1 + and object_id=p_object_id; + exception + when others then + v_result_string1 := ''; + end; + + begin + select trim(dbms_lob.substr(content,1300,1)) + into v_result_string2 + from sn_content + where question_id=p_question_id2 + and object_id=p_object_id; + exception + when others then + v_result_string2 := ''; + end; + + begin + if p_question_id3 > 0 then + select trim(dbms_lob.substr(content,1300,1)) + into v_result_string3 + from sn_content + where question_id=p_question_id3 + and object_id=p_object_id; + end if; + exception + when others then + v_result_string3 := ''; + end; + + v_length_string1 := length(v_result_string1); + v_length_string2 := length(v_result_string2); + v_length_string3 := length(v_result_string3); + + if (v_length_string1 > 0) then + v_result_string := v_result_string1; + if (v_length_string2 > 0) then + v_result_string := v_result_string || ', ' || v_result_string2; + end if; + if (v_length_string3 > 0) then + v_result_string := v_result_string || ', ' || v_result_string3; + end if; + else + if (v_length_string2 > 0) then + v_result_string := v_result_string2; + if (v_length_string3 > 0) then + v_result_string := v_result_string || ', ' || v_result_string3; + end if; + else + if (v_length_string3 > 0) then + v_result_string := v_result_string3; + end if; + end if; + end if; + return v_result_string; + end shortname_string; + + function strip_html ( input_text in varchar2) + return varchar2 + is + output varchar2(4000); + i number; + tag_start number; + tag_end number; + char_count number; + begin + + i := 1; + output := ''; + while instr(input_text, '<', i) >= i + loop + tag_start := instr(input_text, '<', i); + tag_end := instr(input_text, '>', tag_start); + if tag_end > 0 then + char_count := tag_start - i; + + if char_count > 0 then + output := output || substr(input_text, i, char_count); + end if; + + i := tag_end + 1; + else + exit; + end if; + end loop; + + output := output || substr(input_text, i); + + select replace(output, '\<', '<') into output from dual; + select replace(output, '\>', '>') into output from dual; + select replace(output, '\"', '"') into output from dual; + return (output); + end strip_html; + + function strip_html_and_limit_size + (p_overview in sn_objects.overview%TYPE) + return VARCHAR2 + is + v_overview sn_objects.overview%TYPE; + begin + v_overview := strip_html(p_overview); + if (length(p_overview)>200) then + v_overview := substr(v_overview,1,200) || '...'; + end if; + return v_overview; + end strip_html_and_limit_size; +end km_utilities; +/ +show errors + + + +create or replace trigger km_flat_object_hier_insert_tr +before insert on sn_links for each row +begin + if :new.link_type = 'parent_child' or :new.link_type = 'uncle_nephew' then + insert into km_flat_object_hierarchy (object_hierarchy_id, parent, child, distance, link_type) + values (acs_object_id_seq.nextval, :new.object_id_a, :new.object_id_b, 1, :new.link_type); + + insert into km_flat_object_hierarchy (object_hierarchy_id, parent, child, distance, link_type) + select acs_object_id_seq.nextval, parent, :new.object_id_b, distance+1, :new.link_type + from km_flat_object_hierarchy + where child = :new.object_id_a; + end if; +end ; +/ +show errors + + +create or replace trigger km_flat_object_hier_delete_tr +before delete on sn_links for each row +begin + if :old.link_type = 'parent_child' or :old.link_type = 'uncle_nephew' then + delete from km_flat_object_hierarchy + where child = :old.object_id_b; + end if; +end ; +/ +show errors + +create or replace function im_convert( + query in varchar2 default null + ) return varchar2 +is + i number :=0; + len number :=0; + char varchar2(1); + minusString varchar2(4000); + plusString varchar2(4000); + mainString varchar2(4000); + mainAboutString varchar2(4000); + finalString varchar2(4000); + hasMain number :=0; + hasPlus number :=0; + hasMinus number :=0; + token varchar2(4000); + tokenStart number :=1; + tokenFinish number :=0; + inPhrase number :=0; + inPlus number :=0; + inWord number :=0; + inMinus number :=0; + completePhrase number :=0; + completeWord number :=0; + code number :=0; +begin + + len := length(query); + +-- we iterate over the string to find special web operators + for i in 1..len loop + char := substr(query,i,1); + if(char = '"') then + if(inPhrase = 0) then + inPhrase := 1; + tokenStart := i; + else + inPhrase := 0; + completePhrase := 1; + tokenFinish := i-1; + end if; + elsif(char = ' ') then + if(inPhrase = 0) then + completeWord := 1; + tokenFinish := i-1; + end if; + elsif(char = '+') then + inPlus := 1; + tokenStart := i+1; + elsif((char = '-') and (i = tokenStart)) then + inMinus :=1; + tokenStart := i+1; + end if; + + if(completeWord=1) then + token := '{ '||substr(query,tokenStart,tokenFinish-tokenStart+1)||' }'; + if(inPlus=1) then + plusString := plusString||','||token||'*10'; + hasPlus :=1; + elsif(inMinus=1) then + minusString := minusString||'OR '||token||' '; + hasMinus :=1; + else + mainString := mainString||' NEAR '||token; + mainAboutString := mainAboutString||' '||token; + hasMain :=1; + end if; + tokenStart :=i+1; + tokenFinish :=0; + inPlus := 0; + inMinus :=0; + end if; + completePhrase := 0; + completeWord :=0; + end loop; + + -- find the last token + token := '{ '||substr(query,tokenStart,len-tokenStart+1)||' }'; + if(inPlus=1) then + plusString := plusString||','||token||'*10'; + hasPlus :=1; + elsif(inMinus=1) then + minusString := minusString||'OR '||token||' '; + hasMinus :=1; + else + mainString := mainString||' NEAR '||token; + mainAboutString := mainAboutString||' '||token; + hasMain :=1; + end if; + + + mainString := substr(mainString,6,length(mainString)-5); + mainAboutString := replace(mainAboutString,'{',' '); + mainAboutString := replace(mainAboutString,'}',' '); + plusString := substr(plusString,2,length(plusString)-1); + minusString := substr(minusString,4,length(minusString)-4); + + -- we find the components present and then process them based on the specific combinations + code := hasMain*4+hasPlus*2+hasMinus; + if(code = 7) then + finalString := '('||plusString||','||mainString||'*2.0,about('||mainAboutString||')*0.5) NOT ('||minusString||')'; + elsif (code = 6) then + finalString := plusString||','||mainString||'*2.0'||',about('||mainAboutString||')*0.5'; + elsif (code = 5) then + finalString := '('||mainString||',about('||mainAboutString||')) NOT ('||minusString||')'; + elsif (code = 4) then + finalString := mainString; + finalString := replace(finalString,'*1,',NULL); + finalString := '('||finalString||')*2.0,about('||mainAboutString||')'; + elsif (code = 3) then + finalString := '('||plusString||') NOT ('||minusString||')'; + elsif (code = 2) then + finalString := plusString; + elsif (code = 1) then + -- not is a binary operator for intermedia text + finalString := 'totallyImpossibleString'||' NOT ('||minusString||')'; + elsif (code = 0) then + finalString := ''; + end if; + + return finalString; +end; +/ + +create or replace package body psn_res_application +as + procedure create_magic_objects ( + package_id in apm_packages.package_id%TYPE, + creation_user in acs_objects.creation_user%TYPE default null, + creation_ip in acs_objects.creation_ip%TYPE default null + ) + is + v_role_object_id acs_objects.object_id%TYPE; + v_language_object_id acs_objects.object_id%TYPE; + v_proficiency_object_id acs_objects.object_id%TYPE; + begin + v_role_object_id := acs_object.new ( + object_type => 'psn_tree_object', + creation_date => sysdate, + creation_user => creation_user, + creation_ip => creation_ip, + context_id => package_id + ); + acs_object.new_description ( + v_object_id => v_role_object_id, + v_shortname => 'Role Category Tree', + v_overview => 'Role Category Tree for Knowledge Library #' || package_id, + v_overview_html_p => 'f', + v_package_id => package_id + ); + v_language_object_id := acs_object.new ( + object_type => 'psn_tree_object', + creation_date => sysdate, + creation_user => creation_user, + creation_ip => creation_ip, + context_id => package_id + ); + acs_object.new_description ( + v_object_id => v_language_object_id, + v_shortname => 'Language Category Tree', + v_overview => 'Language Category Tree for Knowledge Library #' || package_id, + v_overview_html_p => 'f', + v_package_id => package_id + ); + v_proficiency_object_id := acs_object.new ( + object_type => 'psn_tree_object', + creation_date => sysdate, + creation_user => creation_user, + creation_ip => creation_ip, + context_id => package_id + ); + acs_object.new_description ( + v_object_id => v_proficiency_object_id, + v_shortname => 'Language Proficiency Category Tree', + v_overview => 'Language Proficiency Category Tree for Knowledge Library #' || package_id, + v_overview_html_p => 'f', + v_package_id => package_id + ); + + insert into psn_category_trees (package_id, role_magic_id, language_magic_id, proficiency_magic_id) + values (package_id, v_role_object_id, v_language_object_id, v_proficiency_object_id); + + end create_magic_objects; + + procedure copy ( + src_package_id in apm_packages.package_id%TYPE, + dst_package_id in apm_packages.package_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE + ) + is + begin + + -- Copy relations between magic objects and category trees. + -- We do this with a cursor because some of the relations may not exist. + + for c in ( + select r.object_id_two as tree_id, octr.subtree_root_node_id as node_id, ct2.role_magic_id as object_id + from psn_category_trees ct1, psn_category_trees ct2, acs_rels r, + object_category_tree_rels octr + where ct1.package_id = src_package_id + and ct2.package_id = dst_package_id + and r.object_id_one = ct1.role_magic_id + and r.rel_type = 'object_category_tree_rel' + and octr.rel_id = r.rel_id + union all + select r.object_id_two, octr.subtree_root_node_id, ct2.language_magic_id + from psn_category_trees ct1, psn_category_trees ct2, acs_rels r, + object_category_tree_rels octr + where ct1.package_id = src_package_id + and ct2.package_id = dst_package_id + and r.object_id_one = ct1.language_magic_id + and r.rel_type = 'object_category_tree_rel' + and octr.rel_id = r.rel_id + union all + select r.object_id_two, octr.subtree_root_node_id, ct2.proficiency_magic_id + from psn_category_trees ct1, psn_category_trees ct2, acs_rels r, + object_category_tree_rels octr + where ct1.package_id = src_package_id + and ct2.package_id = dst_package_id + and r.object_id_one = ct1.proficiency_magic_id + and r.rel_type = 'object_category_tree_rel' + and octr.rel_id = r.rel_id + ) loop + category.map_tree(c.object_id, c.node_id, c.tree_id); + end loop; + + end copy; + +end psn_res_application; +/ +show errors Index: openacs-4/contrib/obsolete-packages/library/sql/oracle/library-packages.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/sql/oracle/library-packages.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/sql/oracle/library-packages.sql 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,251 @@ +-- @cvs-id $Id: library-packages.sql,v 1.1 2003/07/02 12:19:42 peterm Exp $ + +create or replace package library +as + procedure copy ( + src_package_id in apm_packages.package_id%TYPE, + dst_package_id in apm_packages.package_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE + ); +end library; +/ + +create or replace package question +as + function insert_question ( + v_question_id in sn_questions.question_id%TYPE default null, + v_pretty_name in sn_questions.pretty_name%TYPE, + v_abstract_data_type in sn_questions.abstract_data_type%TYPE, + v_order_by in sn_questions.order_by%TYPE, + v_default_value in sn_questions.default_value%TYPE, + v_entry_explanation in sn_questions.entry_explanation%TYPE, + v_creation_user in acs_objects.creation_user%TYPE, + v_creation_ip in acs_objects.creation_ip%TYPE, + v_context_id in acs_objects.context_id%TYPE default null, + v_insertion_date in acs_objects.creation_date%TYPE default sysdate, + v_references_q_id in sn_questions.question_id%TYPE default null + ) return sn_questions.question_id%TYPE; + + procedure update_question ( + v_question_id in sn_questions.question_id%TYPE, + v_pretty_name in sn_questions.pretty_name%TYPE, + v_abstract_data_type in sn_questions.abstract_data_type%TYPE, + v_order_by in sn_questions.order_by%TYPE, + v_default_value in sn_questions.default_value%TYPE, + v_entry_explanation in sn_questions.entry_explanation%TYPE, + v_modifying_user in acs_objects.creation_user%TYPE, + v_modifying_ip in acs_objects.modifying_ip%TYPE, + v_update_date in acs_objects.last_modified%TYPE default sysdate, + v_references_q_id in sn_questions.question_id%TYPE default null, + v_def_question_id in sn_questions.question_id%TYPE default null, + v_max_categories in sn_questions.max_categories%TYPE default null, + v_browse_p in sn_questions.browse_p%TYPE default 't' + ); + + procedure delete_question ( + v_question_id in sn_questions.question_id%TYPE + ); + + procedure map_question_on_object ( + v_question_id in sn_questions.question_id%TYPE, + v_object_type_id in sn_objects.object_type_id%TYPE, + v_form_number in sn_question_object_type_map.form_number%TYPE, + v_mandatory_p in sn_question_object_type_map.mandatory_p%TYPE, + v_question_state in sn_question_object_type_map.question_state%TYPE + ); + + function root_branch_p ( + v_question_id in sn_questions.question_id%TYPE + ) return char; + + procedure delete_all_questions( + v_context_id in acs_objects.context_id%TYPE + ) ; + +end question; +/ +show errors + +create or replace package object_type +as + function insert_object_type ( + v_pretty_name in sn_object_types.pretty_name%TYPE, + v_pretty_plural in sn_object_types.pretty_plural%TYPE, + v_graphic in sn_object_types.graphic%TYPE, + v_deleted_p in sn_object_types.deleted_p%TYPE, + v_browse_p in sn_object_types.browse_p%TYPE, + v_public_p in sn_object_types.public_p%TYPE, + v_sort_key in sn_object_types.sort_key%TYPE, + v_short_description in sn_object_types.short_description%TYPE, + v_long_description in sn_object_types.long_description%TYPE, + v_linked_question_id in sn_object_types.linked_question_id%TYPE, + v_public_until in sn_object_types.public_until%TYPE, + v_default_age_filter in sn_object_types.default_age_filter%TYPE, + v_creation_user in acs_objects.creation_user%TYPE, + v_creation_ip in acs_objects.creation_ip%TYPE, + v_context_id in acs_objects.context_id%TYPE, + v_short_name in sn_object_types.short_name%TYPE default null, + v_insertion_date in acs_objects.creation_date%TYPE default sysdate + ) return sn_object_types.object_type_id%TYPE; + + function insert_object_type ( + v_pretty_name in sn_object_types.pretty_name%TYPE, + v_pretty_plural in sn_object_types.pretty_plural%TYPE, + v_browse_p in sn_object_types.browse_p%TYPE, + v_default_age_filter in sn_object_types.default_age_filter%TYPE, + v_creation_user in acs_objects.creation_user%TYPE, + v_creation_ip in acs_objects.creation_ip%TYPE, + v_context_id in acs_objects.context_id%TYPE, + v_short_name in sn_object_types.short_name%TYPE default null, + v_insertion_date in acs_objects.creation_date%TYPE default sysdate + ) return sn_object_types.object_type_id%TYPE; + + procedure delete_object_type ( + v_object_type_id in sn_object_types.object_type_id%TYPE + ); + + procedure delete_all_object_types ( + v_context_id in acs_objects.context_id%TYPE + ); + + procedure copy_object_type ( + v_object_type_id in sn_object_types.object_type_id%TYPE, + v_target_context_id in acs_objects.context_id%TYPE, + v_creation_user in acs_objects.creation_user%TYPE, + v_creation_ip in acs_objects.creation_ip%TYPE + ); + + procedure copy_all_object_types ( + src_package_id in acs_objects.context_id%TYPE, + dst_package_id in acs_objects.context_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE + ); + +end object_type; +/ +show errors + +create or replace package object +as + function name ( + object_id in sn_objects.object_id%TYPE + ) return varchar2; + + function insert_object ( + v_object_type_id in sn_objects.object_type_id%TYPE, + v_creation_user in acs_objects.creation_user%TYPE, + v_creation_ip in acs_objects.creation_ip%TYPE, + v_context_id in acs_objects.context_id%TYPE, + v_insertion_date in acs_objects.creation_date%TYPE default sysdate + ) return sn_objects.object_id%TYPE; + + function insert_object ( + v_object_id in acs_objects.object_id%TYPE, + v_object_type_id in sn_objects.object_type_id%TYPE, + v_creation_user in acs_objects.creation_user%TYPE default null, + v_creation_ip in acs_objects.creation_ip%TYPE default null, + v_context_id in acs_objects.context_id%TYPE default null, + v_insertion_date in acs_objects.creation_date%TYPE default sysdate + ) return sn_objects.object_id%TYPE; + + procedure delete_object ( + v_object_id in sn_objects.object_id%TYPE + ); + + procedure save_content ( + v_object_id in sn_objects.object_id%TYPE, + v_question_id in sn_questions.question_id%TYPE, + v_html_p in sn_content.html_p%TYPE, + v_content_length in integer, + v_modifying_user in acs_objects.creation_user%TYPE, + v_modifying_ip in acs_objects.modifying_ip%TYPE, + v_update_date in acs_objects.last_modified%TYPE default sysdate + ); + + procedure delete_all_objects_of_a_type ( + v_object_type_id in sn_object_types.object_type_id%TYPE + ); + + procedure delete_all_objects_of_an_inst ( + v_context_id in acs_objects.context_id%TYPE + ); + + procedure audit_object ( + v_object_id in sn_objects.object_id%TYPE, + v_question_id in sn_questions.question_id%TYPE, + v_last_modifying_user_id in acs_objects.modifying_ip%TYPE, + v_modifying_ip in acs_objects.modifying_ip%TYPE, + v_content in sn_audit_table.content%TYPE, + v_last_modified in acs_objects.last_modified%TYPE default sysdate + ); + + function copy_object ( + v_object_id in acs_objects.object_id%TYPE, + v_target_id in acs_objects.object_id%TYPE default null, + v_creation_user in acs_objects.creation_user%TYPE default null, + v_creation_ip in acs_objects.creation_ip%TYPE default null, + v_context_id in acs_objects.context_id%TYPE default null + ) return sn_objects.object_id%TYPE; + +end object; +/ +show errors + + +create or replace package km_utilities +as + function km_ancestor_list ( + v_object_id in integer) + return varchar; + + function km_category_list ( + v_object_id in integer, + v_parent_node_id in varchar) + return varchar; + + function km_xml ( + id sn_objects.object_id%type) + return clob; + + procedure km_populate_flat_object_hier; + + procedure km_logger ( + v_who_is_logging varchar2, + v_log_text varchar2); + + function shortname_string ( + p_object_id in sn_objects.object_id%TYPE, + p_question_id1 in sn_questions.question_id%TYPE, + p_question_id2 in sn_questions.question_id%TYPE, + p_question_id3 in sn_questions.question_id%TYPE default 0) + return varchar2; + + function strip_html_and_limit_size + (p_overview in sn_objects.overview%TYPE) + return VARCHAR2; + +end km_utilities; +/ +show errors + +create or replace package psn_res_application +as + + procedure create_magic_objects ( + package_id in apm_packages.package_id%TYPE, + creation_user in acs_objects.creation_user%TYPE default null, + creation_ip in acs_objects.creation_ip%TYPE default null + ); + + procedure copy ( + src_package_id in apm_packages.package_id%TYPE, + dst_package_id in apm_packages.package_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE + ); + +end psn_res_application; +/ +show errors Index: openacs-4/contrib/obsolete-packages/library/sql/oracle/library-temp-tables.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/sql/oracle/library-temp-tables.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/sql/oracle/library-temp-tables.sql 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,18 @@ +-- Here are the temporary tables that are being used by library-internal +-- functions. Read Tom Kyte's book if you want to understand why I'm using +-- temporary tables. + +create global temporary table km_temp_questions + (old_id integer , + new_id integer) + on commit delete rows ; + +create global temporary table km_temp_object_types + (old_id integer , + new_id integer) + on commit delete rows ; + +create global temporary table km_temp_answer_options + (old_id integer , + new_id integer) + on commit delete rows ; Index: openacs-4/contrib/obsolete-packages/library/sql/oracle/library-triggers.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/sql/oracle/library-triggers.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/sql/oracle/library-triggers.sql 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,175 @@ +create or replace trigger sn_object_types_in_tr +after insert on sn_object_types +for each row +begin + acs_object.new_description( + v_object_id => :new.object_type_id, + v_shortname => :new.pretty_name, + v_package_id => :new.context_id); +end sn_objects_in_tr; +/ +show errors + +create or replace trigger sn_object_types_up_tr +after update on sn_object_types +for each row +declare +begin + acs_object.set_shortname( + v_object_id => :new.object_type_id, + v_shortname => :new.pretty_name); + + acs_object.set_package_id( + v_object_id => :new.object_type_id, + v_package_id => :new.context_id); + +end sn_object_types_up_tr; +/ +show errors + + +create or replace trigger sn_objects_in_tr +after insert on sn_objects +for each row +declare + v_new_one_line_description sn_objects.one_line_description%TYPE; + v_creation_date acs_objects.creation_date%TYPE; +begin + if :new.one_line_description is null or length(trim(:new.one_line_description)) = 0 then + select 'Unnamed ' || pretty_name + into v_new_one_line_description + from sn_object_types + where object_type_id = :new.object_type_id; + else + v_new_one_line_description := :new.one_line_description; + end if; + + select creation_date into v_creation_date + from acs_objects + where object_id = :new.object_id; + + acs_object.new_description( + v_object_id => :new.object_id, + v_shortname => substr(v_new_one_line_description,0,199), + v_overview => :new.overview, + v_presentation => 'presentation=private,object_type_id=' || :new.object_type_id, + v_overview_html_p => :new.overview_html_p, + v_package_id => :new.context_id, + v_publish_date => v_creation_date); + + -- Fill the content areas + insert into acs_object_areas + (object_id, area_id, package_id) + values + (:new.object_id, :new.object_type_id, :new.context_id); +end sn_objects_in_tr; +/ +show errors + +create or replace trigger sn_objects_up_tr +after update of one_line_description, overview, overview_html_p, context_id, public_p, + archived_p, in_review_p, expiration_date, user_checkoff_date, original_author_id on sn_objects +for each row +declare + v_new_one_line_description sn_objects.one_line_description%TYPE; + v_presentation acs_objects_description.presentation%TYPE; + v_state acs_objects_description.state%TYPE; + v_creation_date acs_objects.creation_date%TYPE; +begin + if :new.one_line_description is null or length(trim(:new.one_line_description)) = 0 then + select 'Unnamed ' || pretty_name + into v_new_one_line_description + from sn_object_types + where object_type_id = :new.object_type_id; + else + v_new_one_line_description := :new.one_line_description; + end if; + + if :new.original_author_id <> :old.original_author_id then + update acs_objects set creation_user = :new.original_author_id + where object_id = :new.object_id; + end if; + + acs_object.set_shortname( + v_object_id => :new.object_id, + v_shortname => substr(v_new_one_line_description,0,199)); + + acs_object.set_overview( + v_object_id => :new.object_id, + v_overview => :new.overview, + v_overview_html_p => :new.overview_html_p); + + if :new.context_id <> :old.context_id then + acs_object.set_package_id( + v_object_id => :new.object_id, + v_package_id => :new.context_id); + + update acs_object_areas + set area_id = :new.object_type_id, + package_id= :new.context_id + where object_id = :new.object_id; + end if; + + if :new.public_p <> :old.public_p + or :new.archived_p <> :old.archived_p + or :new.in_review_p <> :old.in_review_p then + + if :new.public_p = 't' then + v_presentation := 'presentation=public'; + elsif :new.public_p = 'f' then + v_presentation := 'presentation=private'; + end if; + + v_presentation := v_presentation || ',object_type_id=' || :new.object_type_id; + + if :new.archived_p = 't' then + v_presentation := v_presentation || ',archived'; + end if; + + if :new.in_review_p = 't' then + v_presentation := v_presentation || ',in_review'; + end if; + + acs_object.set_presentation( + v_object_id => :new.object_id, + v_presentation => v_presentation); + end if; + + if :new.expiration_date <> :old.expiration_date + or :new.archived_p <> :old.archived_p then + if :new.expiration_date <= sysdate then + v_state := 'd'; + else + if :new.archived_p = 't' then + v_state := 'a'; + elsif :new.archived_p = 'f' then + v_state := 'l'; + end if; + end if; + + acs_object.set_state( + v_object_id => :new.object_id, + v_state => v_state); + end if; + + if :new.user_checkoff_date <> :old.user_checkoff_date + or (:new.user_checkoff_date is not null and :old.user_checkoff_date is null) then + acs_object.set_publish_date( + v_object_id => :new.object_id, + v_publish_date => :new.user_checkoff_date); + end if; + + if :new.user_checkoff_date is null and :old.user_checkoff_date is not null then + select creation_date + into v_creation_date + from acs_objects + where object_id = :new.object_id; + + acs_object.set_publish_date( + v_object_id => :new.object_id, + v_publish_date => v_creation_date); + end if; + +end sn_objects_up_tr; +/ +show errors Index: openacs-4/contrib/obsolete-packages/library/sql/oracle/library-workflow-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/sql/oracle/library-workflow-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/sql/oracle/library-workflow-create.sql 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,355 @@ +/* + * Business Process Definition: Library Approval (library_approval_wf) + * + * Auto-generated by ACS Workflow Export, version 4.0.2 + * + * Context: default + */ + +-- This table will be used to queue email notifications from Oracle, +-- which will then be composed and sent by a scheduled Tcl procedure. +create table wf_library_notifications ( + notification_id + integer + constraint wf_libr_notifications_pk + primary key, + task_id + integer + constraint wf_libr_n_task_id_fk + references wf_tasks + constraint wf_libr_n_task_id_nn + not null, + template_key + varchar2(64) + constraint wf_libr_n_template_fk + references et_templates(key) + constraint wf_libr_n_template_nn + not null, + recipient_id + integer + constraint wf_libr_n_recipient_fk + references users + constraint wf_libr_n_recipient_nn + not null, + sender_id + integer + constraint wf_libr_n_sender_fk + references users + constraint wf_libr_n_sender_nn + not null, + body + varchar2(4000) + default null +); + +create sequence library_notification_id_seq start with 1; + +create or replace trigger wf_library_notifications_itrg + before insert on wf_library_notifications for each row +begin + select library_notification_id_seq.nextval into :new.notification_id from dual; +end; +/ +show errors + +-- This table will hold one row for each case using this workflow. +create table wf_library_approval_cases ( + case_id integer + constraint wf_library_appr_cases_pk + primary key + constraint wf_library_appr_cases_case_fk + references wf_cases +); + +declare + v_workflow_key wf_workflows.workflow_key%TYPE; +begin + v_workflow_key := workflow.create_workflow( + workflow_key => 'library_approval_wf', + pretty_name => 'Library Approval Process', + pretty_plural => 'Library Approval Process', + description => 'Workflow for Approving a Knowledge Object Publication in the Library', + table_name => 'wf_library_approval_cases' + ); + + -- Creating places + workflow.add_place ( + workflow_key => 'library_approval_wf', + place_key => 'start', + place_name => 'Needs to be reviewed', + sort_order => 1 + ); + workflow.add_place ( + workflow_key => 'library_approval_wf', + place_key => 'to_be_clarified', + place_name => 'Needs to be clarified', + sort_order => 2 + ); + workflow.add_place ( + workflow_key => 'library_approval_wf', + place_key => 'ready_for_publication', + place_name => 'Ready for Publication', + sort_order => 3 + ); + workflow.add_place ( + workflow_key => 'library_approval_wf', + place_key => 'end', + place_name => 'Closed', + sort_order => 4 + ); + + -- Creating transitions + workflow.add_transition ( + workflow_key => 'library_approval_wf', + transition_key => 'library_review', + transition_name => 'Review Knowledge Object', + sort_order => 1, + trigger_type => 'user' + ); + workflow.add_transition ( + workflow_key => 'library_approval_wf', + transition_key => 'library_clarify', + transition_name => 'Clarify Knowledge Object', + sort_order => 2, + trigger_type => 'user' + ); + workflow.add_transition ( + workflow_key => 'library_approval_wf', + transition_key => 'library_publish', + transition_name => 'Publish Knowledge Object', + sort_order => 3, + trigger_type => 'automatic' + ); +end; +/ +show errors + +begin + -- creating arcs + -- review in + -- in + workflow.add_arc ( + workflow_key => 'library_approval_wf', + transition_key => 'library_review', + place_key => 'start', + direction => 'in' + ); + -- out + workflow.add_arc ( + workflow_key => 'library_approval_wf', + transition_key => 'library_review', + place_key => 'to_be_clarified', + direction => 'out', + guard_callback => 'wf_callback.guard_attribute_true', + guard_custom_arg => 'library_object_needs_clarification', + guard_description => 'Knowledge Object needs clarification' + ); + workflow.add_arc ( + workflow_key => 'library_approval_wf', + transition_key => 'library_review', + place_key => 'ready_for_publication', + direction => 'out', + guard_callback => '#', + guard_description => 'Knowledge Object ready for publication' + ); + + -- clarify + -- in + workflow.add_arc ( + workflow_key => 'library_approval_wf', + transition_key => 'library_clarify', + place_key => 'to_be_clarified', + direction => 'in' + ); + -- out + workflow.add_arc ( + workflow_key => 'library_approval_wf', + transition_key => 'library_clarify', + place_key => 'start', + direction => 'out' + ); + + -- publish + -- in + workflow.add_arc ( + workflow_key => 'library_approval_wf', + transition_key => 'library_publish', + place_key => 'ready_for_publication', + direction => 'in' + ); + + -- out + workflow.add_arc ( + workflow_key => 'library_approval_wf', + transition_key => 'library_publish', + place_key => 'end', + direction => 'out', + guard_callback => 'wf_callback.guard_attribute_true', + guard_custom_arg => 'library_object_published', + guard_description => 'Knowledge Object published' + ); + +end; +/ +show errors + +declare + v_attribute_id acs_attributes.attribute_id%TYPE; +begin + v_attribute_id := workflow.create_attribute( + workflow_key => 'library_approval_wf', + attribute_name => 'library_object_needs_clarification', + datatype => 'boolean', + pretty_name => 'Knowledge Object needs clarification', + default_value => 'f' + ); + + insert into wf_transition_attribute_map + (workflow_key, transition_key, attribute_id, sort_order) + values + ('library_approval_wf', 'library_review', v_attribute_id, 1); + + v_attribute_id := workflow.create_attribute( + workflow_key => 'library_approval_wf', + attribute_name => 'verified', + datatype => 'boolean', + pretty_name => 'Result is okay', + default_value => 't' + ); + + v_attribute_id := workflow.create_attribute( + workflow_key => 'library_approval_wf', + attribute_name => 'library_object_published', + datatype => 'boolean', + pretty_name => 'Knowledge Object published', + default_value => 't' + ); + +end; +/ +show errors + +insert into wf_context_transition_info ( + context_key, + workflow_key, + transition_key, + assignment_callback, + fire_callback, + notification_callback, + notification_custom_arg, + unassigned_callback, + access_privilege +) values ( + 'default', + 'library_approval_wf', + 'library_review', + 'library_callback.assign_task_to_assignee', + 'library_callback.review_fire', + 'library_callback.notification', + 'library_review_object', + 'library_callback.notify_admin', + 'write' +); + +insert into wf_context_transition_info ( + context_key, + workflow_key, + transition_key, + assignment_callback, + fire_callback, + notification_callback, + notification_custom_arg, + access_privilege +) values ( + 'default', + 'library_approval_wf', + 'library_clarify', + 'library_callback.assign_task_to_submitter', + 'library_callback.clarify_fire', + 'library_callback.notification', + 'library_clarify_object', + 'admin' +); + +insert into wf_context_transition_info ( + context_key, + workflow_key, + transition_key, + fire_callback, + notification_callback, + notification_custom_arg, + access_privilege +) values ( + 'default', + 'library_approval_wf', + 'library_publish', + 'library_callback.publish_fire', + 'library_callback.notification', + 'library_published', + 'admin' +); +insert into wf_context_task_panels ( + context_key, + workflow_key, + transition_key, + sort_key, + header, + template_url +) values ( + 'default', + 'library_approval_wf', + 'library_review', + 1, + 'Knowledge Object Info', + '/packages/library/wf-templates/object-info' +); + +insert into wf_context_task_panels ( + context_key, + workflow_key, + transition_key, + sort_key, + header, + template_url +) values ( + 'default', + 'library_approval_wf', + 'library_review', + 2, + 'What to do', + '/packages/library/wf-templates/review' +); + +insert into wf_context_task_panels ( + context_key, + workflow_key, + transition_key, + sort_key, + header, + template_url +) values ( + 'default', + 'library_approval_wf', + 'library_clarify', + 1, + 'Knowledge Object Info', + '/packages/library/wf-templates/object-info' +); + +insert into wf_context_task_panels ( + context_key, + workflow_key, + transition_key, + sort_key, + header, + template_url +) values ( + 'default', + 'library_approval_wf', + 'library_clarify', + 2, + 'What to do', + '/packages/library/wf-templates/clarify' +); + +commit; Index: openacs-4/contrib/obsolete-packages/library/sql/oracle/library-workflow-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/sql/oracle/library-workflow-drop.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/sql/oracle/library-workflow-drop.sql 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,30 @@ +-- +-- packages/library/sql/library-workflow-drop.sql +-- +-- +-- @author Dirk Gomez (sharenet@dirkgomez.de) +-- @author Timo Hentschel (timo@arsidigta.com) +-- +-- @creation-date 2002-02-22 +-- +-- @cvs-id $Id: library-workflow-drop.sql,v 1.1 2003/07/02 12:19:42 peterm Exp $ +-- + +truncate table wf_library_notifications; +truncate table wf_ttracker_notifications; + +begin + workflow.delete_cases('library_approval_wf'); +end; +/ +show errors + +drop table wf_library_approval_cases; +begin + workflow.drop_workflow('library_approval_wf'); +end; +/ +show errors + +drop table wf_library_notifications; +drop sequence library_notification_id_seq; Index: openacs-4/contrib/obsolete-packages/library/sql/oracle/library-workflow-packages.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/sql/oracle/library-workflow-packages.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/sql/oracle/library-workflow-packages.sql 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,458 @@ +create or replace package library_workflow +as + function new_workflow_case ( + p_object_id in sn_objects.object_id%TYPE, + p_creation_date in acs_objects.creation_date%TYPE default sysdate, + p_creation_user in acs_objects.creation_user%TYPE, + p_creation_ip in acs_objects.creation_ip%TYPE default null, + p_publisher_id in sn_objects.publisher_id%TYPE default null + ) return integer; + + procedure delete_workflow_case ( + object_id in sn_objects.object_id%TYPE + ); + + function workflow_url ( + absolute_p in char default 't' + ) return varchar2; + + function notification_sender ( + package_id in apm_packages.package_id%TYPE + ) return users.user_id%TYPE; + +end library_workflow; +/ +show errors + + +create or replace package body library_workflow +as + function new_workflow_case ( + p_object_id in sn_objects.object_id%TYPE, + p_creation_date in acs_objects.creation_date%TYPE default sysdate, + p_creation_user in acs_objects.creation_user%TYPE, + p_creation_ip in acs_objects.creation_ip%TYPE default null, + p_publisher_id in sn_objects.publisher_id%TYPE default null + ) return integer + is + v_case_id wf_cases.case_id%TYPE; + begin + -- create a new case + v_case_id := workflow_case.new ( + workflow_key => 'library_approval_wf', + object_id => p_object_id, + creation_user => p_creation_user, + creation_ip => p_creation_ip + ); + + -- start the case + workflow_case.start_case ( + case_id => v_case_id, + creation_user => p_creation_user, + creation_ip => p_creation_ip + ); + + -- now automatically assign the task to the coordinator. The workflow + -- package requires static assignment otherwise. + return v_case_id; + end new_workflow_case ; + + procedure delete_workflow_case ( + object_id in sn_objects.object_id%TYPE + ) + is + cursor case_cur is + select case_id + from wf_cases + where object_id = object_id; + case_rec case_cur%ROWTYPE; + begin + open case_cur; + fetch case_cur into case_rec; + + -- delete the workflow case that's associated with this object + + if case_cur%FOUND then + workflow_case.delete(case_rec.case_id); + end if; + + close case_cur; + end delete_workflow_case ; + + function workflow_url ( + absolute_p in char default 't' + ) return varchar2 + is + v_system_url apm_parameter_values.attr_value%TYPE; + cursor node_cur is + select sn.node_id + from site_nodes sn, + apm_packages ap + where ap.package_key = 'acs-workflow' + and sn.object_id = ap.package_id; + node_rec node_cur%ROWTYPE; + begin + -- try to get the id of the site node that contains acs workflow + open node_cur; + fetch node_cur into node_rec; + if node_cur%NOTFOUND then + close node_cur; + raise_application_error(-20000, 'ACS Workflow must be mounted'); + end if; + close node_cur; + + -- if only relative url is needed + if absolute_p <> 't' then + return site_node.url(node_rec.node_id); + end if; + + -- since there's only 1 instance of the kernel + -- it's ok to use select.. into.. + select apv.attr_value into v_system_url + from apm_parameter_values apv, + apm_parameters ap + where ap.package_key = 'acs-kernel' + and ap.parameter_name = 'SystemURL' + and ap.parameter_id = apv.parameter_id; + + return v_system_url||site_node.url(node_rec.node_id); + + end workflow_url; + + function notification_sender ( + package_id in apm_packages.package_id%TYPE + ) return users.user_id%TYPE + is + v_result users.user_id%TYPE; + begin + select nvl(apm.get_value(notification_sender.package_id,'NotificationSender'),-1) + into v_result + from dual; + + return v_result; + end notification_sender; + +end library_workflow; +/ +show errors + +create or replace package library_callback +as + procedure assign_task_to_submitter ( + task_id in number, + custom_arg in varchar2 + ); + + procedure assign_task_to_assignee ( + task_id in number, + custom_arg in varchar2 + ); + + procedure publish_fire ( + case_id in number, + transition_key in varchar2, + custom_arg in varchar2 + ); + + procedure clarify_fire ( + case_id in number, + transition_key in varchar2, + custom_arg in varchar2 + ); + + procedure review_fire ( + case_id in number, + transition_key in varchar2, + custom_arg in varchar2 + ); + + procedure notification ( + task_id in number, + custom_arg in varchar2, + party_to in integer, + party_from in out integer, + subject in out varchar2, + body in out varchar2, + sent_p in out char + ); + + procedure notify_admin ( + task_id in number, + custom_arg in varchar2 + ) ; + +end library_callback; +/ +show errors + +create or replace package body library_callback +as + procedure assign_task_to_assignee ( + task_id in number, + custom_arg in varchar2 + ) + is + v_publisher_id users.user_id%TYPE; + v_case_id wf_tasks.case_id%TYPE; + v_transition_key wf_tasks.transition_key%TYPE; + begin + begin + -- let's look up the last publisher. + select o.publisher_id, wt.case_id, wt.transition_key + into v_publisher_id, v_case_id, v_transition_key + from sn_objects o, wf_tasks wt, wf_cases wc + where wt.task_id = assign_task_to_assignee.task_id + and wt.case_id = wc.case_id + and wc.object_id = o.object_id + and o.publisher_id is not null + and (acs_permission.permission_p(o.object_id, o.publisher_id , 'km_publish'))='t'; + + workflow_case.add_task_assignment(assign_task_to_assignee.task_id, v_publisher_id); + workflow_case.add_manual_assignment ( + case_id => v_case_id, + transition_key => v_transition_key, + party_id => v_publisher_id + ); + + exception + when no_data_found then + -- find the default assignees for this community + + for v_approval_coordinators in ( + select ac.coordinator_id, + wt.case_id, + wt.transition_key + from acs_objects ao, wf_tasks wt,wf_cases wc, + approval_coordinators ac + where wt.task_id = assign_task_to_assignee.task_id + and wt.case_id = wc.case_id + and wc.object_id = ao.object_id + and ac.package_id = ao.context_id ) + loop + workflow_case.add_task_assignment(assign_task_to_assignee.task_id, v_approval_coordinators.coordinator_id); + workflow_case.add_manual_assignment ( + case_id => v_approval_coordinators.case_id, + transition_key => v_approval_coordinators.transition_key, + party_id => v_approval_coordinators.coordinator_id + ); + end loop; + end; + end assign_task_to_assignee; + + procedure assign_task_to_submitter ( + task_id in number, + custom_arg in varchar2 + ) + is + cursor object_cur is + select ao.creation_user, + wt.case_id, + wt.transition_key + from acs_objects ao, wf_tasks wt,wf_cases wc + where wt.task_id = assign_task_to_submitter.task_id + and wt.case_id = wc.case_id + and wc.object_id = ao.object_id; + object_rec object_cur%ROWTYPE; + begin + -- find the creation user of the object (submitter) + open object_cur; + fetch object_cur into object_rec; + close object_cur; + + -- assign the task to the object submitter + workflow_case.add_task_assignment(assign_task_to_submitter.task_id, object_rec.creation_user); + workflow_case.add_manual_assignment ( + case_id => object_rec.case_id, + transition_key => object_rec.transition_key, + party_id => object_rec.creation_user + ); + + end assign_task_to_submitter; + + procedure publish_fire ( + case_id in number, + transition_key in varchar2, + custom_arg in varchar2 + ) + is + v_journal_id journal_entries.journal_id%TYPE; + v_task_id wf_tasks.task_id%TYPE; + v_party_from users.user_id%TYPE; + v_party_to users.user_id%TYPE; + v_author_id users.user_id%TYPE; + v_subject varchar2(4000); + v_body varchar2(4000); + v_request_id integer; + v_sent_p char(1); + begin + select distinct(task_id) into v_task_id + from wf_tasks t + where case_id = publish_fire.case_id + and rownum = 1 + order by task_id desc; + + select ao.creation_user, so.original_author_id + into v_party_to, v_author_id + from acs_objects ao, wf_cases c, sn_objects so + where ao.object_id = c.case_id + and c.case_id = publish_fire.case_id + and so.object_id = c.object_id; + + v_party_from := -1; + v_subject := 'default'; + v_body := 'default'; + v_sent_p := 'f'; + + library_callback.notification ( + task_id => v_task_id, + custom_arg => 'library_published', + party_to => v_party_to, + party_from => v_party_from, + subject => v_subject, + body => v_body, + sent_p => v_sent_p + ); + + if v_party_to != v_author_id then + library_callback.notification ( + task_id => v_task_id, + custom_arg => 'library_published', + party_to => v_author_id, + party_from => v_party_from, + subject => v_subject, + body => v_body, + sent_p => v_sent_p + ); + end if; + + v_journal_id := journal_entry.new ( + object_id => case_id, + action => 'modify', + action_pretty => 'Attribute Change', + msg => 'Automatic action by the workflow process' + ); + workflow_case.set_attribute_value ( + journal_id => v_journal_id, + attribute_name => 'library_object_published', + value => 't' + ); + + end publish_fire; + + procedure clarify_fire ( + case_id in number, + transition_key in varchar2, + custom_arg in varchar2 + ) + is + v_journal_id journal_entries.journal_id%TYPE; + begin + v_journal_id := journal_entry.new ( + object_id => case_id, + action => 'modify', + action_pretty => 'Attribute Change', + msg => 'Automatic action by the workflow process' + ); + workflow_case.set_attribute_value ( + journal_id => v_journal_id, + attribute_name => 'library_object_needs_clarification', + value => 'f' + ); + + end clarify_fire; + + procedure review_fire ( + case_id in number, + transition_key in varchar2, + custom_arg in varchar2 + ) + is + v_journal_id journal_entries.journal_id%TYPE; + begin + v_journal_id := journal_entry.new ( + object_id => case_id, + action => 'modify', + action_pretty => 'Attribute Change', + msg => 'Automatic action by the workflow process' + ); + workflow_case.set_attribute_value ( + journal_id => v_journal_id, + attribute_name => 'verified', + value => 't' + ); + end review_fire; + + procedure notification ( + task_id in number, + custom_arg in varchar2, + party_to in integer, + party_from in out integer, + subject in out varchar2, + body in out varchar2, + sent_p in out char + ) + is + begin + select o.creation_user, j.msg into notification.party_from, notification.body + from acs_objects o, journal_entries j + where o.object_id = j.journal_id + and j.journal_id = (select max(j2.journal_id) from journal_entries j2, wf_tasks t, acs_objects o2 + where t.case_id = j2.object_id + and t.task_id = notification.task_id + and o2.object_id = j2.journal_id + and o2.creation_user is not null); + + insert into wf_library_notifications (task_id, template_key, recipient_id, sender_id, body) + values (notification.task_id, notification.custom_arg, notification.party_to, + notification.party_from, notification.body); + + sent_p := 't'; + end notification; + + procedure notify_admin ( + task_id in number, + custom_arg in varchar2 + ) + is + -- uses 2 separate queries to find out who has 'admin' privilege on this package + -- because we don't want to join any table with acs_object_party_privilege_map + -- unless we absolutely have to (in this case, users table) + -- the first query is only used to gather object info and package id + cursor object_cur is + select o.object_id, + o.one_line_description, + o.context_id as package_id + from sn_objects o, + wf_cases wc, + wf_tasks wt + where wt.task_id = notify_admin.task_id + and wc.case_id = wt.case_id + and wc.object_id = o.object_id; + object_rec object_cur%ROWTYPE; + cursor admin_cur is + select u.user_id + from users u, + acs_object_party_privilege_map m + where m.object_id = object_rec.package_id + and m.party_id = u.user_id + and m.privilege = 'admin'; + v_request_id integer; + begin + open object_cur; + fetch object_cur into object_rec; + close object_cur; + for admin_rec in admin_cur loop + v_request_id := nt.post_request ( + party_from => library_workflow.notification_sender(object_rec.package_id), + party_to => admin_rec.user_id, + expand_group => 'f', + subject => 'Object #'||object_rec.object_id||' -- '||'Assign Object', + message => 'Subject: '||object_rec.one_line_description||'To do: '||'Assign Object Manage via: '||library_workflow.workflow_url||'task?task_id='||task_id, + max_retries => 3 + ); + end loop; + end notify_admin; + +end library_callback; +/ +show errors Index: openacs-4/contrib/obsolete-packages/library/tcl/km-00-defs-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/tcl/km-00-defs-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/tcl/km-00-defs-procs.tcl 2 Jul 2003 12:19:41 -0000 1.1 @@ -0,0 +1,1337 @@ +# /tcl/km-00-defs.tcl +# +# $Id: km-00-defs-procs.tcl,v 1.1 2003/07/02 12:19:41 peterm Exp $ + +util_report_library_entry +proc km_file_path {} { return [ad_parameter FilePath library "[acs_root_dir]/library-files"] } + +ad_proc util_GetUserAgentHeader {} { + get users browser etc +} { + set header [ns_conn headers] + set userag [ns_set iget $header "USER-AGENT"] + return $userag +} + +ad_proc km_get_community_name {} { + returns the name of the current community +} { + array set node [site_node_closest_ancestor_site_node "acs-subsite"] + return $node(instance_name) +} + +ad_proc msie_p {} { + check if browser is microsoft or other +} { + return [regexp -nocase {msie} [util_GetUserAgentHeader]] +} + +ad_proc -public km_conn {args} { + + km_conn works much like ad_conn. It caches http-session specific + information. + + Example: + set admin_p [km_conn admin_p] + +} { + global km_conn + + set flag [lindex $args 0] + if {[string index $flag 0] != "-"} { + set var $flag + set flag "-get" + } else { + set var [lindex $args 1] + } + + switch -- $flag { + -set { + set km_conn($var) [lindex $args 2] + } + + -unset { + unset km_conn($var) + } + + -reset { + if {[info exists km_conn]} { + unset km_conn + } + array set km_conn { + admin_p "" + publish_p "" + read_p "" + write_p "" + delete_p "" + create_p "" + public_p "" + archived_p "" + deleted_p "" + expiration_date "" + object_type_id "" + object_name "" + overview "" + last_modified "" + creation_date "" + user_checkoff_date "" + original_author_id "" + original_author_name "" + access_total "" + access_month "" + public_until "" + start_date "" + end_date "" + publisher_id "" + in_review_p "" + review_state "" + } + } + + -get { + if { [info exists km_conn($var)] } { + return $km_conn($var) + } else { + return "" + } + } + + default { + error "km_conn: unknown flag $flag" + } + } +} + + + +ad_proc -public km_static {args} { + + km_static caches information about objects whose value is more or + less static throughout the system's life time. The first time a + particular information is being looked for, this information is being + loaded from the database into the cache. km_static does _not_ do any + error checking at the moment. It is also not the smartest caching + system under the sun (not yet at least). + + - There should be proc that loads the cache on server + startup. + + Example: + set pretty_type_plural [km_static object_type_pretty_plural $object_type_id] + +} { +# global km_static + + set flag [lindex $args 0] + if {[string index $flag 0] != "-"} { + set var $flag + set flag "-get" + set array_index [lindex $args 1] + set value [lindex $args 2] + } else { + set var [lindex $args 1] + set array_index [lindex $args 2] + set value [lindex $args 3] + } + + if {[empty_string_p $array_index]} { + set var_index "${var}" + } else { + set var_index "${var}${array_index}" + } + + switch -- $flag { + -set { + nsv_set km_static ${var_index} $value + } + + -reset { + server_cluster_httpget_from_peers "/SYSTEM/flush-km-static-cache.tcl?id=$var" + km_static_reset $var + } + + -get { + if { [nsv_exists km_static $var_index] } { + set retval [nsv_get km_static $var_index] + return $retval + } else { + switch -regexp $var { + {package_object_types} { + set package_object_types_list [list] + db_foreach km_static_10 {select pretty_name, object_type_id + from sn_object_types + where context_id=:array_index} { + lappend package_object_types_list [list $pretty_name $object_type_id] + } + km_static -set package_object_types $array_index $package_object_types_list + return $package_object_types_list + } + {^object_type} { + db_1row object_type_info { + select pretty_name, pretty_plural, + graphic, graphic_p, + decode(deleted_p,'t',1,0) as deleted_p, + decode(browse_p,'t',1,0) as browse_p, + decode(public_p,'t',1,0) as public_p, + decode(create_p,'t',1,0) as create_p, + decode(archive_p,'t',1,0) as archive_p, + decode(copy_p,'t',1,0) as copy_p, + default_age_filter, start_date, end_date, + long_description, + public_until, linked_question_id, short_name + from sn_object_types + where object_type_id=:array_index} + set short_description [db_list get_short_description_list { + select short_description + from sn_types_map_short_name + where object_type_id=:array_index + order by position}] + km_static -set object_type_pretty_name $array_index $pretty_name + km_static -set object_type_short_name $array_index $short_name + km_static -set object_type_pretty_plural $array_index $pretty_plural + km_static -set object_type_graphic $array_index $graphic + km_static -set object_type_graphic_p $array_index $graphic_p + km_static -set object_type_deleted_p $array_index $deleted_p + km_static -set object_type_browse_p $array_index $browse_p + km_static -set object_type_public_p $array_index $public_p + km_static -set object_type_create_p $array_index $create_p + km_static -set object_type_archive_p $array_index $archive_p + km_static -set object_type_copy_p $array_index $copy_p + km_static -set object_type_default_age_filter $array_index $default_age_filter + km_static -set object_type_short_description $array_index $short_description + km_static -set object_type_long_description $array_index $long_description + km_static -set object_type_public_until $array_index $public_until + km_static -set object_type_start_date $array_index $start_date + km_static -set object_type_end_date $array_index $end_date + km_static -set object_type_linked_question_id $array_index $linked_question_id + regsub {object_type_} $var "" var + return [set $var] + } + {^question_} { + db_1row km_static_30 { + select pretty_name, abstract_data_type, order_by, target_object_type_id, + presentation_type, defaults_question_id, max_categories + from sn_questions + where question_id=:array_index} + km_static -set question_pretty_name $array_index $pretty_name + km_static -set question_abstract_data_type $array_index $abstract_data_type + km_static -set question_order_by $array_index $order_by + km_static -set question_target_object_type_id $array_index $target_object_type_id + km_static -set question_presentation_type $array_index $presentation_type + km_static -set question_defaults_question_id $array_index $defaults_question_id + km_static -set question_max_categories $array_index $max_categories + return [km_static ${var} ${array_index}] + } + {km_dummy_object_id} { + set new_km_dummy_object_id [db_string km_static_40 { + select object_id + from acs_magic_objects + where name='km_dummy_object'}] + km_static -set km_dummy_object_id $new_km_dummy_object_id + return $new_km_dummy_object_id + } + {^approval_} { + set coordinators [db_list km_static_10 { + select coordinator_id + from approval_coordinators + where package_id=:array_index + }] + km_static -set approval_coordinators $array_index $coordinators + if {[empty_string_p $coordinators]} { + km_static -set approval_p $array_index 0 + } else { + km_static -set approval_p $array_index 1 + } + return [km_static ${var} ${array_index}] + } + default { + error "km_static: unknown flag $flag" + } + } + } + } + + default { + error "km_static: unknown flag $flag" + } +} +} + +ad_proc -public km_static_reset { id } { + Actually flush the km_static cache. +} { + set all_the_cached_crud [nsv_array names km_static] + foreach cached_crud_item $all_the_cached_crud { + if {[regexp "$id\$" $cached_crud_item match matched_id]} { + nsv_unset km_static $cached_crud_item + } + } +} + +ad_proc approval_coordinator_p {user_id} { + + checks whether the user with user_id is approval coordinator +} { + set package_id [ad_conn package_id] + if {[lsearch [km_static approval_coordinators $package_id] $user_id] > -1} { + return 1 + } else { + return 0 + } +} + +proc_doc km_question_attributes {question_id_list} { + + Returns the question_id, abstract_data_type, pretty_name as triples + for each question_id in the list. + +} { + set integer_list [filter_integers $question_id_list] + if {![null_p $integer_list]} { + + + if {[llength $integer_list] > 1} { + set where_clauses "where question_id in ([join $integer_list ","])" + } else { + set question_id [lindex $integer_list 0] + set where_clauses "where question_id = :question_id" + } + + + set sql " + select question_id, pretty_name, abstract_data_type + from sn_questions + $where_clauses + " + set result [db_list_of_lists km_question_attributes $sql] + return $result + } +} + +# ********** Metadata ********** + +ad_proc km_get_all_object_types { + { + -browsable_only_p 1 + -createable_only_p 0 + } +} { + Returns a list of object_type_id, pretty_name, pretty_plural, browse_p, graphic, sort_key +} { + set user_id [ad_conn user_id] + set package_id [ad_conn package_id] + + if {$browsable_only_p} { + set browse_not "and browse_p='t'" + } else { + set browse_not "" + } + + if {$createable_only_p} { + set privilege "create" + } else { + set privilege "read" + } + + set result [db_list_of_lists object_types " + select object_type_id, pretty_name, pretty_plural, + decode(browse_p,'t',1,0), graphic, sort_key + from sn_object_types + where deleted_p = 'f' + and context_id = :package_id + $browse_not + and acs_permission.permission_p(object_type_id, :user_id, :privilege) = 't' + order by sort_key + "] + + return $result +} + +ad_proc km_get_questions { + { + -all_properties_p 0 + -form_view "" + -root_node_p 1 + -branch_children_p 1 + -question_ids {} + -object_id 0 + -object_type_id 0 + -question_states {active} + -answers_p 0 + -answered_p 0 + -mandatory_p 0 + } +} { + + Returns the column_name, pretty_name, abstract_data_type of all + questions for this object type or for this object as a *keyed* list. + root_node_p means it returns only top level questions for + branches. branch_children_p true means that branch children will ALSO be + listed individually + +} { + set columns {q.question_id q.pretty_name q.abstract_data_type} + set order_by "" + set tables {"sn_questions q" "sn_question_object_type_map m"} + + if ![null_p $question_ids] { + # Return information about the given question. + + lappend where_clauses "q.question_id=m.question_id" + + if {[llength $question_ids] > 1} { + lappend where_clauses "q.question_id in ([join $question_ids ","])" + } else { + set question_id [lindex $question_ids 0] + lappend where_clauses "q.question_id = :question_id" + } + set order_by "order by m.sort_key" + } else { + if { $object_id } { set object_type_id [km_get_object_type $object_id] } + + lappend join_tables "sn_questions q" "sn_question_object_type_map m" + lappend where_clauses "(m.object_type_id=$object_type_id and q.question_id=m.question_id)" + set order_by "order by m.sort_key" + } + + if { $form_view == 1 } { + lappend where_clauses "form_number=1" + } elseif { $form_view == 2 } { + lappend where_clauses "q.abstract_data_type in ('text', 'option', 'category', 'other_category', 'date', 'file', 'integer', 'object_link', 'content_link', 'user_link', 'child_object', 'nephew_object')" + } + + if {$answers_p} { + lappend columns "content as answer" "decode(nvl(html_p,'f'),'t',1,0) as html_p" + lappend where_clauses "c.object_id=$object_id and c.question_id=m.question_id" + lappend tables "sn_content c" + } + + # we only want to know here, _if_ there is an answer. If html_p is null, + # then the outer join has retrieved a null row for sn_content, so there is + # no answer. Otherwise there is an answer. + if {$answered_p} { + lappend columns "nvl2(c.object_id,1,0) as answered_p" + lappend where_clauses "c.object_id(+)=$object_id and c.question_id(+)=m.question_id" + lappend tables "sn_content c" + } + + if { $all_properties_p } { + lappend columns presentation_type tag_height tag_width entry_explanation year_from year_to \ + m.mandatory_p m.question_state m.form_number m.sort_key q.node_id q.defaults_question_id \ + q.order_by q.default_value q.target_object_type_id q.references_question_id m.object_type_id \ + "decode(m.branch_p,'t',1,0) as branch_p" q.max_categories browse_p \ + "(select decode(count(*),0,0,1) from dual + where exists (select 1 + from sn_question_object_type_map m2 + where m2.parent_question_id = q.question_id + and m2.branch_p='t' + and m2.object_type_id=$object_type_id)) as root_branch_p" \ + parent_question_id + } + + # Both branch and composite questions can have have parent and child questions + if { $root_node_p && !$branch_children_p } { + + # We want to include questions at the root of branches in the selection but no children of branches + lappend where_clauses " m.parent_question_id=[km_static km_dummy_object_id]" + + } elseif { $root_node_p } { + + # We want branch children, too, but no composite children + lappend where_clauses " ( m.parent_question_id=[km_static km_dummy_object_id] or branch_p='t')" + } + + if ![null_p $question_states] { + lappend where_clauses "m.question_state in ('[join $question_states "','"]')" + } + + if { $mandatory_p } { lappend where_clauses "m.mandatory_p = 't'" } + + # Get the question attributes out of the table + set sql_km_get_questions " + select [join $columns ", "] + from [join $tables ", "] + where [join $where_clauses " and "] + $order_by" + set result [km_db_to_named_list_list km_get_questions $sql_km_get_questions] + + return $result +} + +ad_proc km_get_question { + { + -previous_p 0 + -next_p 0 + -object_id 0 + -entry_explanation_p 0 + -all_types_p 0 + } + question_id object_type_id +} { + + Returns the question_id, pretty_name, abstract_data_type, question_state, + optionally the entry_explanation as a list. + + Set previous_p to 1 and it returns the previous question in the series + that belongs to this object type. Set next_p to 1 and it returns the + next in the series. This proc does NOT do branch analysis. + See km-branch.tcl. + + What it does do is search for the next unanswered question that is not + in a branch when called with a branch question - not necessarily higher + on the sort key list. + +} { + if { $entry_explanation_p } { + set entry_string ", q.entry_explanation" + } else { + set entry_string "" + } + + set sql_km_get_question_1 "select sort_key, decode(branch_p,'t',1,0) + as branch_p, sort_key as current_sort_key, question_state + from sn_question_object_type_map + where question_id=:question_id and object_type_id=:object_type_id" + + if { ![db_0or1row km_get_question_1 $sql_km_get_question_1]} { + return "" + } + + if { $next_p || $previous_p } { + # We need some extra limitations here so that we don't pull out composite questions or branches. + + set question_state_sql "and question_state <> 'invisible'" + if { $all_types_p } { + set question_state_sql "" + } + if { $next_p } { + + if { $branch_p } { + # This is a branch leaf. We determine the next question + # relative to its root. + set root_id [km_get_root_branch $question_id $object_type_id] + set current_sort_key "(select sort_key from sn_question_object_type_map where question_id=:root_id and object_type_id = :object_type_id)" + } + set limitation " and qm.sort_key = ( + select min(sort_key) + from sn_question_object_type_map + where object_type_id=:object_type_id + and sort_key > :current_sort_key + $question_state_sql + and branch_p='f' + and parent_question_id=[km_static km_dummy_object_id])" + + } elseif { $previous_p } { + set limitation " and qm.sort_key = ( + select max(sort_key) from sn_question_object_type_map + where object_type_id=:object_type_id + and sort_key < :current_sort_key + $question_state_sql + and branch_p='f' + and parent_question_id=[km_static km_dummy_object_id])" + } + } else { + set limitation "and q.question_id=:question_id" + } + + set question_state_sql "and qm.question_state <> 'invisible'" + if { $all_types_p } { + set question_state_sql "" + } + set result [km_db_1row_to_list km_get_question_2 " + select q.question_id, q.pretty_name, q.abstract_data_type, qm.question_state $entry_string + from sn_questions q, sn_question_object_type_map qm + where qm.question_id = q.question_id + and qm.object_type_id = :object_type_id + $question_state_sql + $limitation"] + + if { ($next_p || $previous_p) && ![empty_string_p $result] } { + # We want to skip deprecated and read-only questions + # which have not been answered. + + set new_question_id [fst $result] + set new_abstract_data_type [thd $result] + set new_question_state [lindex $result 3] + + set answer [fst [km_get_object_data -questions [list {question_id pretty_name abstract_data_type question_state} $result] $object_id]] + + if { $new_question_state != "active" && ![km_answered_p $new_abstract_data_type $answer] } { + set result [km_get_question -next_p $next_p -previous_p $previous_p -entry_explanation_p $entry_explanation_p -object_id $object_id $new_question_id $object_type_id] + } + } + + return $result +} + +proc_doc km_get_child_questions {composite_id} { + Returns a list of child question_ids for this composite question. +} { + set sql "select question_id from sn_question_object_type_map + where parent_question_id = :composite_id and branch_p='f' and question_state <> 'invisible'" + set result [db_list km_get_child_questions $sql] + return $result +} + +proc_doc km_get_answer_options {question_id} { + + Returns the list of key-value-sort_key tuples of answer options + for this question_id, assuming that this question is actually + a question of type option. + +} { + set result [db_list_of_lists km_get_answer_options " + select option_id, answer_option, sort_key + from sn_answer_options + where question_id = :question_id + order by sort_key"] + return $result +} + +proc_doc km_answer_option {option_id} { + Returns an the pretty name of an answer option. +} { + set sql "select answer_option from sn_answer_options where option_id = :option_id" + set result [db_string km_answer_option $sql -default ""] + return $result +} + +proc km_pretty_question_state { question_state } { + switch $question_state { + "active" { return "Active" } + "deprecated" { return "To be phased out" } + "read-only" { return "Read-Only" } + "invisible" { return "Invisible" } + } +} + +# ******************** Input checking ******************** + +proc_doc km_sort_form { key_value_tuples } { + Sorts form vars into a list of tuples of keys and value_lists. Date variables are assembled to make one value. Note that + even if one key has only one value associated with it that this value will be represented as a single element list. +} { + set sorted_tuples [list] + set sister_tag_p 0 + + #Put dates together + set tuples [km_assemble_dates -filter_p 0 [fst [transpose $key_value_tuples]] [snd [transpose $key_value_tuples]]] + # Sort the tuple values into new value_lists by key + foreach tuple $tuples { + + set key [fst $tuple] + set value [snd $tuple] + + # Put textareas and their sister html_p tags together + if {[regexp {(.*)\.html_p} $key match x] } { + set key $x + set sister_tag_p 1 + } + + # Get the index of the element in sorted_tuples to be manipulated + set ix [lsearch [fst [transpose $sorted_tuples]] $key] + + if {$ix >= 0} { + + # This key is already in sorted_tuples list so add this value to the value_list in the tuple + set new_value_list [concat [snd [lindex $sorted_tuples $ix]] $value] + + # Replace the old element of sorted_tuples with the new tuple + set sorted_tuples [lreplace $sorted_tuples $ix $ix [list $key $new_value_list]] + set sister_tag_p 0 + + } elseif {$sister_tag_p} { + + # Then this is an html_p tag that has no sister textarea tag: i.e. the textarea tag is an empty string + lappend sorted_tuples [list $key [list "" $value]] + set sister_tag_p 0 + + } else { + + + # This key isn't yet in the sorted_tuple list so append a new tuple to it + lappend sorted_tuples [list $key [list $value]] + + } + } + return $sorted_tuples +} + +proc_doc km_filter_valid_keys { key_value_list} { + Returns the tuple if it is valid- i.e. it has an integer key value. +} { + set filtered_tuples [list] + foreach tuple $key_value_list { + if {[integer_p [fst $tuple]]} {lappend filtered_tuples $tuple} + } + return $filtered_tuples +} + +proc_doc km_filter_other_category_keys { key_value_list} { + Returns the tuple if it is originating from extra input field for category 'Other' +} { + set filtered_tuples [list] + foreach tuple $key_value_list { + set key [fst $tuple] + if { [regexp {([0-9]+)_other$} $key match question_id] && [integer_p $question_id] } { + lappend filtered_tuples [list $question_id [snd $tuple]] + } + } + return $filtered_tuples +} + +proc_doc km_required_questions {object_id} { + Returns a list of required (or mandatory) questions for this object. +} { + set context_id [ad_conn package_id] + set result [db_list km_required_questions " + select q.question_id + from sn_questions q, sn_question_object_type_map qm, sn_objects o + where q.question_id = qm.question_id + and qm.object_type_id = o.object_type_id + and o.object_id = :object_id + and qm.question_state = 'active' + and o.context_id=:context_id + and qm.mandatory_p = 't'"] + return $result +} + +ad_proc km_mandatory_child_p { { -parent_id 0 -child_ids {} } } { + + Returns 1 if this composite parent has a mandatory child + or if one of the child_ids passed is mandatory. + +} { + if { $parent_id } { set child_ids [km_get_child_questions $parent_id] } + + if [null_p $child_ids] { return 0 } + set children [km_get_questions -all_properties_p 1 -branch_children_p 1 -root_node_p 0 -question_ids $child_ids] + set key [fst $children] + set children [tail $children] + + foreach child $children { + set mandatory_p [ad_decode [lindex $child [lsearch $key mandatory_p]] t 1 0] + if { $mandatory_p } { return 1 } + } + + return 0 +} + +ad_proc km_is_required { + { + -object_id 0 + -object_type_id 0 + } + question_id +} { + Checks if a question is mandatory. +} { + if !$object_type_id { set object_type_id [km_get_object_type $object_id] } + set result [db_list km_is_required " + select decode(mandatory_p,'t',1,0) + from sn_question_object_type_map + where question_id=:question_id and object_type_id=:object_type_id"] + return $result +} + +proc_doc km_answered_p { abstract_data_type answer } { + Determines on the basis of the abstract_data_type if this question has been answered or is empty. +} { + switch $abstract_data_type { + "object_link" { return [expr ![null_p [tail $answer]]] } + "composite" { + # This is a bit tricky. Composite questions come in as little + # packets of other questions from km_object_data. + # A composite question is considered answered if at least one + # child has been answered. + + foreach item $answer { + if [km_answered_p [lindex $item 3] [fst $item]] { return 1 } + } + return 0 + } + "option" - "other_category" - + "category" { return [expr ![null_p $answer]] } + "integer" - + "text" { return [expr ![empty_string_p [fst $answer]]] } + default { return [expr ![empty_string_p $answer]]} + } +} + +ad_proc km_check_input { + { + -required_p 0 + -complete_p 0 + } + object_id + key_value_list +} { + + This proc determines if the list of question_ids and their value + are valid entries according to their abstract data type. + It will also check if the set of keys and values submitted are + enough to make this object complete if complete_p is true. Or it will + check if a each key is a required question and if so, it will + check if that question is answered when required_p is true. + + This proc returns a tuple for ad_return_complaint if it has reason + to complain. + +} { + set invalid_questions {} + set missing_ids {} + set required_ids {} + + #Remove any key value tuples that do not have an integer key + set key_value_list [km_filter_valid_keys $key_value_list] + + # The keys in key value tuples are the question_ids + set submitted_ids [fst [transpose $key_value_list]] + set values [snd [transpose $key_value_list]] + + #Get a list of required questions to check for completeness + if {$complete_p || $required_p} { set required_ids [km_required_questions $object_id] } + + # Get the abstract data types and pretty_names of the questions + set questions [km_question_attributes [concat $submitted_ids $required_ids]] + set question_ids [fst [transpose $questions]] + set abstract_data_types [thd [transpose $questions]] + set pretty_names [snd [transpose $questions]] + + foreach submitted_id $submitted_ids { + + # check the input + set abstract_data_type [lindex $abstract_data_types [lsearch $question_ids $submitted_id]] + set value_list [lindex $values [lsearch $submitted_ids $submitted_id]] + + switch $abstract_data_type { + "text" { + if {($complete_p || $required_p) && ([elem_p $submitted_id $required_ids] && ([null_p $value_list] \ + || [empty_string_p [fst $value_list]])) } { + lappend missing_ids $submitted_id + } + } + "category" - "other_category" - "option" { + set max_categories [km_static question_max_categories $submitted_id] + if {($complete_p || $required_p) && [elem_p $submitted_id $required_ids] && [null_p $value_list]} { + lappend missing_ids $submitted_id + } elseif {![empty_string_p $max_categories] && ([llength $value_list] > $max_categories)} { + lappend invalid_questions [list $submitted_id "more than the allowed $max_categories categories chosen"] + } + } + "date" { + if {($complete_p || $required_p) && [elem_p $submitted_id $required_ids] && [empty_date_p $value_list]} { + lappend missing_ids $submitted_id + } elseif {![empty_date_p $value_list] && ![date_p $value_list]} { + lappend invalid_questions [list $submitted_id "no valid date"] + } + } + "integer" { + if {($complete_p || $required_p) && ([elem_p $submitted_id $required_ids] && ([null_p $value_list] \ + || [empty_string_p [fst $value_list]])) } { + lappend missing_ids $submitted_id + } elseif {![integer_p [fst $value_list]]} { + lappend invalid_questions [list $submitted_id "no valid number"] + } + } + "file" { + set client_filename [fst $value_list] + + if {($complete_p || $required_p) && [elem_p $submitted_id $required_ids] } { + if [empty_string_p $client_filename] { + # Go to the db and see if a file already exists for this variable. + if ![km_upload_exists_p $object_id $submitted_id] { + lappend missing_ids $submitted_id + } + } + } + + if { ![empty_string_p $client_filename] } { + # If the temporary file is empty, there has been an error. + set tmpfilename [ns_queryget $submitted_id.tmpfile] + if ![file size $tmpfilename] { + lappend invalid_questions [list $submitted_id "invalid file"] + } + } + } + default { continue } + } + } + + foreach question_id $required_ids { + set abstract_data_type [lindex $abstract_data_types [lsearch [fst [transpose $questions]] $question_id]] + switch $abstract_data_type { + "user_link" { + if ![null_p [km8_get_to_links $object_id $question_id]] { + # If there already are links for this question, we pretend + # it has been submitted. + lappend submitted_ids $question_id + } + } + "file" { + if ![km_upload_exists_p $submitted_id $object_id] { + lappend submitted_ids $question_id + } + } + "child_object" { + if {![null_p [km_get_child_objects $object_id $question_id]] } { + lappend submitted_ids $question_id + } + } + "nephew_object" { + if {![null_p [km_get_nephew_objects $object_id $question_id]] } { + lappend submitted_ids $question_id + } + } + } + } + + # Check if there are some other keys that also should be submitted to make this complete + if { $complete_p } { set missing_ids [concat $missing_ids [minus $required_ids $submitted_ids]] } + + #Prepare the complaint messages + foreach missing_id $missing_ids { + set pretty_name [lindex $pretty_names [lsearch $question_ids $missing_id]] + append message "You must supply a value for $pretty_name
" + } + foreach invalid_question $invalid_questions { + set invalid_id [fst $invalid_question] + set invalid_msg [snd $invalid_question] + set pretty_name [lindex $pretty_names [lsearch $question_ids $invalid_id]] + append message "You have entered an invalid entry for $pretty_name ($invalid_msg)
" + } + set i [expr [llength $invalid_questions] + [llength $missing_ids]] + if { $i } { + return [list $i $message] + } else { + return + } +} + +proc_doc km_upload_exists_p { object_id question_id } { + Looks if a file has been uploaded for this object_id and question_id +} { + set client_filename [db_string km_upload_exists_p " + select content from sn_content + where object_id=:object_id + and question_id=:question_id" -default ""] + + if ![empty_string_p $client_filename] { + return 1 + } else { + return 0 + } +} + +ad_proc km_original_author_p { user_id object_id } { + Test if the user is the original author of this object. +} { + set context_id [ad_conn package_id] + set result [db_string km_original_author_p " + select count(*) from sn_objects where object_id=:object_id and original_author_id=:user_id and context_id=:context_id"] + + return $result +} + +proc_doc km_type_has_data_type_p { object_type_id data_type } { + Determines if an object type has a column of the given abstract datatype. +} { + return [db_string km_type_has_data_type_p " + select decode(count(*),0,0,1) from dual where exists (select 1 + from sn_questions q, sn_question_object_type_map qm + where qm.question_id = q.question_id + and qm.object_type_id = :object_type_id + and qm.question_state <> 'invisible' + and q.abstract_data_type = :data_type)"] +} + +# ******************** Date Procs ******************** + +proc_doc month_list {} { + Returns a list of months, the second row holds the corresponding 2 digit values. +} { + set months [list Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec] + set values [list 01 02 03 04 05 06 07 08 09 10 11 12] + return [list $months $values] +} + +proc_doc km_default_date {question_id} { + Calculates a default date based on the question_id +} { + set default_value [db_string km_default_date_1 " + select default_value from sn_questions where question_id=:question_id" -default ""] + if [empty_string_p $default_value] { + set result {} + } else { + if { ![catch {set default_date [db_string km_default_date_2 "select $default_value from dual"]}] } { + set result [km_break_date $default_date] + } else { + set result {} + } + } + return $result +} + +ad_proc km_get_year_range {question_id} { + Calculates the year range for this date question +} { + db_1row get_year_range { + select (to_char(add_months(sysdate,12*year_from),'YYYY')) as year_from, + (to_char(add_months(sysdate,12*year_to),'YYYY')) as year_to + from sn_questions + where question_id = :question_id + } + return [list $year_from $year_to] +} + +ad_proc km_assemble_dates { {-filter_p 1} keys values } { + + Given a list of keys and values, this proc searches for all keys with the form + key_name:month, key_name:year, key_name:day, which is how km-date-tags + returns them in this module. It returns a list of key value tuples + of the form: key_name YYYY-MM-DD. It does not check if these are valid dates, that's + what date_p does. If filter_p is set to 1, it returns only the date tuples back. + Otherwise it returns all other keys and values in the same order. + +} { + # we need a list of key_name tags and their values, sort them so that + # all key_names are grouped together and that :day, :month, :year + # will be evaluated in that order + + set key_name "" + set tuples [zip $keys $values] + set tuples [qsort $tuples] + set last_key_name "" + set result [list] + + set counter 0 + foreach tuple $tuples { + + if { [regexp {(.*)\.(month|year|day)} [fst $tuple] match key_name] } { + # Looks like a date value. + + if { [string compare $key_name $last_key_name] == 0 } { + lappend ${key_name}_value [snd $tuple] + } else { + + # It's a different key_name so append the last_key_name and + # its date to the list (if there is one). + + if ![empty_string_p $last_key_name] { + lappend dates [list $last_key_name [set ${last_key_name}_value]] + } + + # Start assembling the next date + lappend ${key_name}_value [snd $tuple] + } + + set last_key_name $key_name + incr counter + + } elseif !$filter_p { + # No date value, but we are not allowed to filter other values out. + # So just copy it. + + lappend result $tuple + } + } + + if { $counter } { + + # Append the last last_key_name and its date to the list. + lappend dates [list $last_key_name [set ${last_key_name}_value]] + + # Oracle will want the date YYY-MM-DD instead of a list DD MM YYYY, + # so split the tuples up again and format the date part. + + set formatted_dates [map {flip join "-"} [map reverse [snd [transpose $dates]]]] + + # Pack them up again to be returned as a list of tuples. + set result "$result [zip [fst [transpose $dates]] $formatted_dates]" + } + + return $result +} + + +# ******************** Navigation ******************** + +proc_doc generate_path_id {} { + + Generates a random number to uniquely define this excursion state in + the knowledge management library. + + This number will be passed from one form to the next throughout the excursion. + +} { + while 1 { + # Note that ns_rand only gives us six digits - so we call it twice. + set path_id "[ns_rand 1000000][ns_rand 1000000]" + + if ![db_string generate_path_id "select count(*) from km_path where path_id=:path_id"] { + return $path_id + } + } +} + +ad_proc set_path_values {{-question_id ""} object_id category_id } { + + Returns a simple list of name and value tuples that should be stored + for library excursions in the km_excursion_path table + +} { + + if ![empty_string_p $question_id] { + set values [list object_id $object_id question_id $question_id category_id $category_id] + } else { + set values [list object_id $object_id category_id $category_id] + } + return $values +} + +ad_proc init_path { + { + -last_path_id "" + } + values_list return_to action +} { + + Initializes the path variable for an excursion through the library. + + Begins an excursion by saving all the information that will be + necessary at the end of this excursion to return to the same place it + started. It is assumed that an excursion is only occuring while + editing, creating or linking an object. In all other cases there will + be no excursion state and also no object_id. Important! The + last_path_id that is being passed is the id of the excursion state out + of which this excursion is being launched! + +} { + set path_id [generate_path_id] + if [empty_string_p $last_path_id] { set last_path_id [db_null] } + + # Insert the info about this particular excursion into the database + + db_dml init_path "insert into km_path + (path_id, last_path_id, action, values_list, return_to, start_time) + values (:path_id, :last_path_id, :action, + :values_list, :return_to, sysdate)" + + return $path_id +} + +proc_doc get_path_return_url {path_id} { + + Returns the destination of a path if it's a valid path, otherwise + it returns an empty string. + +} { + if [empty_string_p $path_id] { return "" } + + set calc_excursion_timeout [expr [excursion_timeout]/24] + set sql "select return_to from km_path + where path_id=:path_id and sysdate - start_time < :calc_excursion_timeout" + + if {[catch {set destination [db_string get_path_return_url $sql]}]} { + set result "" + } else { + set result $destination + } + + return $result +} + +ad_proc get_path_values { {-action_only_p 1} path_id } { + + Given an excursion's path_id, this proc returns the action of this + excursion as a two-part list: {action action_value}. This is often + necessary for a page to know what it is supposed to do. If the option + action_only_p is set to 0 then a simple list is returned with the name + and value of the variables in the same order that they were given to + km_set_path_values + +} { + + set timeout [excursion_timeout] + + if !$action_only_p { + # Return a list with all excursion details + set values ", values_list " + } else { + set values "" + } + + # Get out the action and the list of values from oracle and + # turn it into a list of action and the other values + + set values_list {} + if { ![db_0or1row get_path_values " + select action $values from km_path + where path_id=:path_id and sysdate - start_time < :timeout/24"]} { + set result {} + } else { + + split $values_list + + set result {} + foreach value $values_list { lappend result $value } + lappend result action $action + } + + return $result +} + +proc_doc get_path_action {path_id} { + Returns the path's action as a plain value. +} { + return [snd [get_path_values $path_id]] +} + +proc_doc get_last_path {path_id} { + + If this was an excursion launched within another excursion then we + want to return the path_id of that excursion. + +} { + set last_path_id [db_string get_last_path " + select last_path_id from km_path where path_id=:path_id" -default ""] + + return $last_path_id +} + +proc_doc path_valid_p {path_id} { + Checks if the given path (still) exists. +} { + if [empty_string_p $path_id] { return 0 } + + set calc_excursion_timeout [expr [excursion_timeout]/24] + set result [db_string path_valid_p " + select count(*) from km_path + where path_id=:path_id and sysdate - start_time <= :calc_excursion_timeout"] + return $result +} + +proc_doc value_from_tuples {key_values key} { + + Given a list of key/value tuples, returns the value associated with + the given key. + +} { + if { [lsearch $key_values $key] == -1 } { + return "" + } else { + return [lindex $key_values [expr [lsearch $key_values $key] + 1]] + } +} + +ad_proc sn_success_story_id {} { + Returns the object_type_id for the Success Stories. +} { + set context_id [ad_conn package_id] + set result [db_string sn_success_story_id " + select object_type_id from sn_object_types + where upper(pretty_name) = upper('success story') and context_id=:context_id" -default "0"] + + return $result +} + + +ad_proc km_workflow_task_per_object {object_id} { + Return information about the current workflow task for this object_id +} { + # dirk: remove the rownum - it's only in for debugging purposes. + if {[db_0or1row km_workflow_task_per_object { + select t.task_id, + t.case_id, + t.transition_key, + t.state, + t.transition_name as task_name + from wf_cases c, + wf_user_tasks t + where c.case_id = t.case_id + and c.object_id=:object_id + and rownum=1}]} { + return [list \ + workflow_task_p t \ + task_id $task_id \ + case_id $case_id \ + transition_key $transition_key \ + state $state \ + task_name $task_name] + } else { + return [list \ + workflow_task_p f \ + task_id "" \ + case_id "" \ + transition_key "" \ + state "" \ + task_name ""] + } + return "" +} + + +ad_proc library_approval_process_notifications {} { + + Processes the notifications queued in table wf_library_notifications. + +} { + # Make sure that only one thread is processing the queue at a time. + if {[nsv_incr library library_notifications_p] > 1} { + nsv_incr library library_notifications_p -1 + return + } + + with_finally { + + db_foreach get_notifications { + select notification_id, task_id, template_key, recipient_id, sender_id, body + from wf_library_notifications + } { + + db_1row ticket_info { + select o.object_id, + o.one_line_description as shortname, sn.node_id, + u1.email as sender_email, u2.email as recipient_email, + u1.first_names || ' ' || u1.last_name as sender_name, + u2.first_names || ' ' || u2.last_name as recipient_name, + apm_package.name(o.context_id) as package_name + from wf_tasks wt, wf_cases wc, sn_objects o, users u2, + site_nodes sn, users u1 + where u1.user_id = :sender_id + and u2.user_id = :recipient_id + and wc.case_id = wt.case_id + and wt.task_id = :task_id + and o.object_id = wc.object_id + and sn.object_id = o.context_id + } + + set community_id [sn_community::leaf_community $node_id] + + set replacement_list \ + [list \ + object_id $object_id \ + object_link "[ad_url]/o/$object_id" \ + package_name $package_name \ + shortname $shortname \ + submitter_name $sender_name \ + submitter_email $sender_email \ + recipient_email $recipient_email \ + notification_sender $sender_email \ + body $body] + + db_dml delete_notification { + delete from wf_library_notifications + where notification_id = :notification_id + } + + et_send_email [et_process -community_id $community_id $template_key $replacement_list] + } + + } finally { + nsv_incr library library_notifications_p -1 + } +} + + +util_report_successful_library_load Index: openacs-4/contrib/obsolete-packages/library/tcl/km-access-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/tcl/km-access-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/tcl/km-access-procs.tcl 2 Jul 2003 12:19:41 -0000 1.1 @@ -0,0 +1,315 @@ +# /tcl/km-access-procs.tcl +# +# Functions related to access control. +# +# Created by carsten@arsdigita.com in June 2000 +# +# $Id: km-access-procs.tcl,v 1.1 2003/07/02 12:19:41 peterm Exp $ + +ad_proc km_check_object_id { + { + -check_deleted_p 1 + -check_read_p 1 + -check_edit_p 0 + -check_delete_p 0 + -print_errors_p 1 + } + object_id +} { + + Check if the object exists, and print an error message if it + doesn't. Returns 0 if the object_id is invalid. + + If check_deleted_p is 1, also checks if the object has been deleted. + If check_read_p is 1, also checks if the user may view the object. + If check_edit_p is 1, also checks if the user may edit the object. + Only complains to the user if print_errors_p is 1. + +} { + set package_id [ad_conn package_id] + set user_id [ad_conn user_id] + + if { ![db_0or1row get_object_info " + select decode(sign(sysdate-o.expiration_date),1,1,0,1,0) as deleted_p, + o.original_author_id, o.expiration_date, o.object_type_id, + o.one_line_description as object_name, o.overview, + o.last_modifying_user_id, o.start_date, o.end_date, + decode(o.public_p,'t',1,0) as public_p, o.public_until, + decode(o.archived_p,'t',1,0) as archived_p, + o.original_author_id, to_char(o.creation_date) as creation_date, + to_char(o.last_modified) as last_modified, + to_char(o.user_checkoff_date) as user_checkoff_date, + u.first_names || ' ' || u.last_name as original_author_name, + u.email as original_author_email, o.publisher_id, + decode([tcl_permission_p ":object_id" ":user_id" "'read'"],'t',1,0) as read_p, + decode([tcl_permission_p ":object_id" ":user_id" "'write'"],'t',1,0) as write_p, + decode([tcl_permission_p ":object_id" ":user_id" "'delete'"],'t',1,0) as delete_p, + decode([tcl_permission_p ":package_id" ":user_id" "'admin'"],'t',1,0) as admin_p, + decode([tcl_permission_p ":package_id" ":user_id" "'km_publish'"],'t',1,0) as publish_p, + decode(acs_permission.permission_p(o.object_type_id, :user_id, 'create'),'t',1,0) as create_p, + nvl(o.access_total,0) as access_total, nvl(o.access_month,0) as access_month, + decode(o.in_review_p,'t',1,0) as in_review_p + from sn_objects o, users u + where o.object_id = :object_id + and u.user_id = o.original_author_id + "] } { + # Error: The object does not exist. + + if { $print_errors_p } { + ad_return_exception_page 404 "Entry does not exist." " + The entry with id $object_id does not exist. + We never really delete object IDs from the database so this is quite + unusual. Unless you tried to hack the URL manually this might be a bug + in our software." + } + return 0 + } + + if { [empty_string_p $object_name] } { + set object_name "Unnamed [km_static object_type_pretty_name $object_type_id]" + } + # review process enabled? + if { [km_static approval_p $package_id] && !$publish_p } { + if {$public_p || $in_review_p} { + # revoke delete permission from object owners if object is + # public or review process started + set delete_p $admin_p + } + } + + # The state of a workflow task is user-dependant! + if {$in_review_p} { + set state [db_string workflow_case_state {select distinct t.transition_key + from wf_cases c, + wf_user_tasks t + where c.case_id = t.case_id + and c.object_id=:object_id + and c.state = 'active' + and rownum = 1 + order by t.transition_key desc} -default ""] + } else { + set state "" + } +## and t.user_id = :user_id + + km_conn -reset + km_conn -set public_p $public_p + km_conn -set archived_p $archived_p + km_conn -set deleted_p $deleted_p + km_conn -set expiration_date $expiration_date + km_conn -set object_type_id $object_type_id + km_conn -set object_name $object_name + km_conn -set overview $overview + km_conn -set original_author_id $original_author_id + km_conn -set original_author_name $original_author_name + km_conn -set original_author_email $original_author_email + km_conn -set creation_date $creation_date + km_conn -set last_modified $last_modified + km_conn -set user_checkoff_date $user_checkoff_date + km_conn -set admin_p $admin_p + km_conn -set publish_p $publish_p + km_conn -set read_p $read_p + km_conn -set write_p $write_p + km_conn -set delete_p $delete_p + km_conn -set create_p $create_p + km_conn -set last_modifying_user_id $last_modifying_user_id + km_conn -set access_total $access_total + km_conn -set access_month $access_month + km_conn -set public_until $public_until + km_conn -set start_date $start_date + km_conn -set end_date $end_date + km_conn -set publisher_id $publisher_id + km_conn -set in_review_p $in_review_p + km_conn -set review_state $state + + if { $check_deleted_p && $deleted_p } { + # Error: The object has been deleted. + + set expiration_date [util_AnsiDatetoPrettyDate $expiration_date] + + if {![empty_string_p $last_modifying_user_id]} { + # If we know who deleted the object, we want to give the + # user a link to that user's community page. + + set deletor_name [db_string km_check_object_id_2 " + select first_names || ' ' || last_name + from users where user_id=:last_modifying_user_id"] + + set deletion_text "This object was deleted on $expiration_date by [ad_present_user $last_modifying_user_id $deletor_name]." + + set reason_for_deleting [db_string km_check_object_id_3 " + select reason_for_deleting + from sn_object_delete_reasons + where object_id=:object_id" -default ""] + + if {![empty_string_p $reason_for_deleting]} { + append deletion_text "

Reason:

$reason_for_deleting
" + } + + } else { + set deletion_text "This object was deleted on $expiration_date." + } + + if { $print_errors_p } { ad_returnredirect "object-deleted?object_id=$object_id" } + + return 0 + } + + if { $check_read_p && !$read_p } { + # A user only has read access if the object is public, + # or he has been given read permission. + + if { $print_errors_p } { + ad_return_forbidden "Not Authorized" \ + "You are not authorized to view this object." + } + return 0 + } elseif { $check_edit_p && !$admin_p && (!$write_p || $archived_p) } { + if { $print_errors_p } { + ad_return_forbidden "Not Authorized" \ + "You are not authorized to edit this object." + } + return 0 + } elseif { $check_delete_p && !$admin_p && !$delete_p } { + if { $print_errors_p } { + ad_return_forbidden "Not Authorized" \ + "You are not authorized to delete this object." + } + return 0 + } + + # Check if the object type (still) exists, and if the user is allowed + # to view it. + + if { [km_static object_type_deleted_p $object_type_id] } { + if { $print_errors_p } { + # Only complain to the user if we were told so. + + set pretty_type [km_static object_type_pretty_name $object_type_id] + ad_return_exception_page 404 "The object type \"$pretty_type\" has been removed from the system." "The object type \"$pretty_type\" has been removed from the system. +You therefore cannot view this object" + } + return 0 + } + + if { $check_read_p && ![km_static object_type_public_p $object_type_id] && !$admin_p } { + # The object type may not be viewed by this user. + + if { $print_errors_p } { + ad_return_forbidden "Not Authorized" \ + "You are not authorized to view this object." + } + return 0 + } + + return 1 +} + +ad_proc km_check_object_type_id { + { + -check_view_p 1 + -check_create_p 0 + -print_errors_p 1 + } + object_type_id +} { + + Check if the user may access the given object type. Checks for + read and create permissions, whether the object type + has been deleted, and whether it belongs to the current package. + + If check_create_p is set, also complains when the object type + is not browsable. + +} { + set package_id [ad_conn package_id] + set user_id [ad_conn user_id] + + if { ![db_0or1row km_check_object_type_id " + select deleted_p, browse_p, public_p, + decode([tcl_permission_p ":package_id" ":user_id" "'admin'"],'t',1,0) as admin_p, + decode([tcl_permission_p ":object_type_id" ":user_id" "'create'"],'t',1,0) as create_p + from sn_object_types + where object_type_id = :object_type_id + and context_id = :package_id + "] } { + if { $print_errors_p } { + ad_return_exception_page 404 "Invalid object_type_id" \ + "The given object_type_id is invalid." + } + return 0 + } + + km_conn -reset + km_conn -set admin_p $admin_p + km_conn -set create_p $create_p + + if { $deleted_p == "t" } { + if { $print_errors_p } { + ad_return_exception_page 410 "Object type no longer exists" \ + "This object type has been removed from the system." + } + return 0 + } + + if { $check_view_p && $public_p == "f" && !$admin_p } { + if { $print_errors_p } { + ad_return_forbidden "Not Authorized" \ + "You are not authorized to view objects of this type." + } + return 0 + } + + if { $check_create_p && ($public_p == "f" || !$create_p) && !$admin_p } { + if { $print_errors_p } { + ad_return_forbidden "Not Authorized" \ + "You are not authorized to create objects of this type." + } + return 0 + } + + return 1 +} + +ad_proc km_check_owner_change { + { + -print_errors_p 1 + } + object_id +} { + + Checks if the user may change the ownership of the given + object. This is only allowed for the object owner and administrators. + +} { + set user_id [ad_conn user_id] + set package_id [ad_conn package_id] + + set result [db_string check_owner_change " + select decode(count(*),0,0,1) from dual where exists + (select 1 + from sn_objects + where object_id = :object_id + and context_id = :package_id + and (original_author_id = :user_id or + [tcl_permission_p ":package_id" ":user_id" "'admin'"] = 't')) + "] + + if { !$result && $print_errors_p } { + ad_return_forbidden "Not Authorized" \ + "You are not authorized to change the ownership of this object." + } + + return $result +} + +proc_doc km_object_type_private_p {object_type_id} { + Checks if an object type is not visible to the public. +} { + set context_id [ad_conn package_id] + set result [db_string km_object_type_private_p " + select decode(public_p,'t',0,1) + from sn_object_types where object_type_id=:object_type_id" -default ""] + + return $result +} Index: openacs-4/contrib/obsolete-packages/library/tcl/km-admin-lib-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/tcl/km-admin-lib-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/tcl/km-admin-lib-procs.tcl 2 Jul 2003 12:19:41 -0000 1.1 @@ -0,0 +1,161 @@ +ad_proc km_db_1row_to_list { statement_name sql args } { + + Performs the SQL query $sql. Returns a list of the results. + +} { + ad_arg_parser { bind } $args + + # Query Dispatcher (OpenACS - ben) + set full_statement_name [db_qd_get_fullname $statement_name] + + db_with_handle db { + set selection [db_exec 0or1row $db $full_statement_name $sql] + } + + if { [empty_string_p $selection] } { + return "" + } + + set list_to_return "" + + for { set i 0 } { $i < [ns_set size $selection] } { incr i } { + lappend list_to_return [ns_set value $selection $i] + } + + + for { set i 0 } { $i < [ns_set size $selection] } { incr i } { + upvar 1 [ns_set key $selection $i] value + set value [ns_set value $selection $i] + } + + return $list_to_return +} + +ad_proc km_db_to_named_list_list { statement_name sql args} { + Returns a list of Tcl lists, with each sublist containing the columns returned + by the database; if no rows are returned by the database, returns the + empty list (empty string in Tcl 7.x and 8.x)" +} { + ad_arg_parser { bind } $args + + # Query Dispatcher (OpenACS ) + set full_statement_name [db_qd_get_fullname $statement_name] + + db_with_handle db { + set selection [db_exec select $db $full_statement_name $sql] + + set keys [list] + for {set i 0} {$i<[ns_set size $selection]} {incr i} { + lappend keys [ns_set key $selection $i] + } + set list_to_return [list $keys] + while {[ns_db getrow $db $selection]} { + set row_list "" + set size [ns_set size $selection] + set i 0 + while {$i<$size} { + lappend row_list [ns_set value $selection $i] + incr i + } + lappend list_to_return $row_list + } + } + + return $list_to_return +} + +proc_doc km_new_acs_object_id {} { + Returns a new acs_object_id +} { + set result [db_string km_new_acs_object_id "select acs_object_id_seq.nextval from dual"] + return $result +} + +proc_doc km_sort_key_list { object_type_id } { + + Returns a list of sort_keys available for this object_type + (sort_keys are offered as increments of 10 and should *NEVER* be + the same for 2 questions of one object_type) + +} { + set result "" + set existing_keys [db_list km_sort_key_list "select sort_key from + sn_question_object_type_map + where object_type_id=$object_type_id"] + set i 0 + while { $i < 400 } { + + set i [expr $i + 10] + if {[elem_p $i $existing_keys]} { + continue + } else { + lappend result $i + } + } + return $result +} + +ad_proc km_adt_list { { -pretty_names_p 0 } } { + Returns a list of abstract data types as a list or as a list of tuples + with the pretty name as the second element. +} { + set adts { + text option category other_category integer date file composite + object_link user_link content_link child_object nephew_object + other_category + } + set pretty_names { + Text "Multiple Choice" Category "Category with 'Other' field" Number Date File + Composite "Object-Object Link" "Object-User Link" "Object-Content Link" + "Child Object Type" "Nephew Object Type" + + } + + if { $pretty_names_p } { + return [zip $adts $pretty_names] + } else { + return $adts + } +} + +proc_doc km_pretty_adt { abstract_data_type } { + Returns the pretty abstract data type +} { + switch $abstract_data_type { + "text" { return Text } + "option" { return "Multiple Choice" } + "category" { return "Category" } + "other_category" { return "Category with 'Other' field" } + "date" { return "Date" } + "file" { return "Attachment" } + "composite" { return "Composite" } + "object_link" { return "Object Link" } + "user_link" { return "User Link" } + "content_link" { return "Content Link" } + "child_object" { return "Child Object Type" } + "nephew_object" { return "Nephew Object Type" } + "integer" { return "Number" } + default { return} + } +} + + +proc_doc km_pretty_tag { presentation_type } { + Returns the pretty tag name +} { + switch $presentation_type { + "shorttext" { return "Short Text" } + "text" { return "Short Text" } + "textarea" {return "Textarea" } + "textarea_with_refs" {return "Textarea with Reference Buttons"} + "select" { return Select} + "selectmultiple" {return "Select Multiple" } + "checkbox" {return "Checkbox"} + "radio" {return "Radio Buttons"} + "custom" { return "Custom"} + "application" { return "Application Form"} + default { return } + } +} + + Index: openacs-4/contrib/obsolete-packages/library/tcl/km-branch-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/tcl/km-branch-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/tcl/km-branch-procs.tcl 2 Jul 2003 12:19:41 -0000 1.1 @@ -0,0 +1,319 @@ +# /tcl/km-branch.tcl +# +# These procs have to do with the branches to questions. Branches are +# answer-dependent questions that follow other questions. +# +# $Id: km-branch-procs.tcl,v 1.1 2003/07/02 12:19:41 peterm Exp $ + +ad_proc km_get_branches { + { + -question_attributes_p 0 + -branch_id 0 + } + root_question_id + object_type_id +} { + Returns a list of the question_ids directly beneath this question_id in the branch tree. If + this question is not a branched question then it returns nothing. +} { + + set join_tables [list "sn_question_object_type_map m1" "sn_question_object_type_map m2"] + set join_clause "" + set columns "" + set limitation "" + + if { $question_attributes_p } { + + # We need to know the abstract_data_type of the parent question to know + # if the answer is stored as an option or as a foreign key in the branch recipe. + + set abstract_data_type [thd [km_get_question $root_question_id $object_type_id]] + + switch $abstract_data_type { + "integer" - + "text" { + append columns ", m1.branch_answer branch_answer" + } + "category" - "other_category" { + append columns ",c.category_id, c.long_name branch_answer" + lappend join_tables "categories c" + append join_clause " and m1.branch_answer_foreign_key = c.category_id(+)" + } + "option" { + append columns ", ao.option_id, ao.answer_option branch_answer" + lappend join_tables "sn_answer_options ao" + append join_clause " and m1.branch_answer_foreign_key = ao.option_id(+)" + } + default { return } + } + lappend join_tables " sn_questions q" + append join_clause " and q.question_id = m1.question_id" + append columns ", m1.branch_operator, pretty_name, q.entry_explanation, q.presentation_type, q.abstract_data_type" + } + if { $branch_id } { set limitation " and m1.question_id = :branch_id " } + + set sql "select m1.question_id $columns from [join $join_tables ","] + where m2.question_id = m1.parent_question_id + and m1.branch_p = 't' + and m1.object_type_id = :object_type_id + and m1.parent_question_id = :root_question_id + $join_clause $limitation" + set result [km_db_to_named_list_list km_get_branches $sql] + return $result +} + +proc_doc km_default_branch { root_branch_id } { + Returns the default branch of a branch node. +} { + set default_branch [db_string km_default_branch " + select default_branch + from sn_question_object_type_map qm + where question_id=$root_branch_id + and (select qm2.branch_p + from sn_question_object_type_map qm2 + where qm2.question_id = qm.default_branch) = 't'" -default ""] + + return $default_branch +} + +proc_doc km_branch_parent { question_id object_type_id } { + Returns the parent_question_id of this question iff this is a branch. +} { + set result [db_string km_branch_parent " + select parent_question_id + from sn_question_object_type_map + where question_id=:question_id + and branch_p='t' + and object_type_id=:object_type_id" -default ""] + + return $result +} + +proc_doc km_composite_parent { question_id object_type_id } { + Returns the parent_question_id of this question if this is a composite child. +} { + set result [db_string km_composite_parent " + select parent_question_id + from sn_question_object_type_map + where question_id=:question_id + and branch_p='f' + and object_type_id=:object_type_id" -default ""] + if {$result == [km_static km_dummy_object_id]} { + return "" + } + return $result +} + +proc_doc km_get_root_branch { question_id object_type_id} { + Returns the id of the root question of this branch. +} { + set result [db_string km_get_root_branch " + select question_id + from sn_question_object_type_map + where question_id <> :question_id and branch_p='f' + start with question_id=:question_id and object_type_id=:object_type_id + connect by question_id = prior parent_question_id" -default ""] + + return $result +} + +proc_doc km_root_branch_p { question_id } { + Returns true if this question is a root of a branch (at any level) +} { + return [db_string km_root_branch_p { + select decode(count(*),0,0,1) from dual where exists + (select 1 + from sn_question_object_type_map + where parent_question_id = :question_id and branch_p='t') + }] +} + +proc_doc km_composite_child_p { question_id object_type_id } { + Returns 1 if this question is the child of a composite question, 0 otherwise. + Included here because the distinction between branches and composite children is slight. +} { + set result [db_string km_composite_child_p " + select decode(parent_question_id,[km_static km_dummy_object_id],0,1) + from sn_question_object_type_map + where branch_p='f' + and question_id=:question_id + and object_type_id=:object_type_id" -default "0"] + + return 0 +} + +proc_doc km_active_branch_path { root_question_id object_id object_type_id } { + + Returns the sequence of questions after this root branch question that + are part of the active branch path for this object. + +} { + set branch_id $root_question_id + set branch_list {} + if ![km_root_branch_p $root_question_id] { return $branch_list } + + # Loop through hierarchy until we reach a leaf node or an unanswered question. + set i 0 + while { 1 == 1 } { + # Get object data for the branch_id. + set question [km_get_question $branch_id $object_type_id] + if [empty_string_p $question] { + ns_log Error "Question $branch_id not found in km_active_branch_path" + return + } + + set answer [fst [km_get_object_data -answers_only_p 0 -questions [list {question_id pretty_name abstract_data_type} $question] $object_id]] + set value [fst $answer] + set abstract_data_type [lindex $answer 3] + + # Append this question to the list + lappend branch_list $branch_id + + if ![km_answered_p $abstract_data_type $value] { + # the answer is empty so return the list + return $branch_list + } else { + # Get next branch + set branch_id [km_next_branch -abstract_data_type $abstract_data_type $branch_id $value $object_type_id] + if [empty_string_p $branch_id ] { return $branch_list } + } + + incr i + if { $i > 100 } { + ns_log Error "Endless loop in km_active_branch_path" + return + } + } +} + +proc_doc km_active_path_p { question_id object_id object_type_id } { + + Returns 1 if this question is on an active branch path or is not on a branch at all. + Returns 0 if this question is not on a central branch path (i.e. it is decoupled + from the normal question sequence) + +} { + set root_question_id [km_get_root_branch $question_id $object_type_id] + if [empty_string_p $root_question_id] { return 1 } + + set active_branches [km_active_branch_path $root_question_id $object_id $object_type_id] + if [elem_p $question_id $active_branches] { + return 1 + } else { + return 0 + } +} + +ad_proc km_next_branch { { -abstract_data_type "" } root_branch_id answer object_type_id } { + + Returns the question_id that should follow this question as a result of + the answers. It returns the default question if the answer hasn't been matched or is empty. + If it can't figure out the next question it returns nothing. + +} { + if [empty_string_p $abstract_data_type] { + set abstract_data_type [km_static question_abstract_data_type $root_branch_id] + } + + # If it's not one of these abstract data types then this proc should never have been called! + if { [lsearch {"category" "other_category" "option"} $abstract_data_type] >= 0 } { + + # Data answers are always tuples - we need the first value of the first pair + set answer [fst [fst $answer]] + + # Then the answer is the integer value of the option, a foreign key + set column "branch_answer_foreign_key" + + if { [empty_string_p $answer] || ![integer_p $answer] } { return } + + } elseif { [lsearch {"text" "integer"} $abstract_data_type] >= 0 } { + set column "branch_answer" + set answer [fst $answer] + if { [empty_string_p $answer] || ![integer_p $answer] } { return } + } else { + return "" + } + + set default_branch [km_default_branch $root_branch_id] + + set branches [db_list_of_lists km_next_branch " + select question_id, branch_operator, $column + from sn_question_object_type_map + where parent_question_id=$root_branch_id + and object_type_id=$object_type_id"] + + # Go through each of the branches and see if the operator matches this value + foreach branch $branches { + set branch_id [fst $branch] + set operator [snd $branch] + set branch_answer [thd $branch] + + if [eval_binary $operator $answer $branch_answer] { return $branch_id } + } + + return $default_branch +} + +proc km_pretty_operator { operator } { + switch $operator { + "=" { return "Equals =" } + "<" { return "Less Than <" } + ">" { return "Greater Than >" } + default { return } + } +} + +ad_proc km_branch_questions { + { + -branch_id 0 + -all_properties_p 1 + -root_question_id 0 + -composite_children_p 1 + } + object_type_id +} { + + This proc returns keyed question lists with attributes on the basis of variable branch + properties. i.e. It can return a list that shows all questions of an object_type that + are NOT branches, or these plus the one that IS this branch_id. + + This proc has become more a general admin questions list, since it can do some stuff + for composite questions, too. + +} { + if { $all_properties_p } { + set additional_columns ",presentation_type, tag_height, tag_width, entry_explanation, qm.mandatory_p, qm.question_state, qm.form_number, qm.sort_key " + } + + set limitation "parent_question_id=[km_static km_dummy_object_id] and question_state <> 'invisible'" + set counter 1 + + if { $root_question_id } { + append limitation " and qm.question_id != :root_question_id" + incr counter + } + if { $branch_id } { + append limitation " or qm.question_id = :branch_id " + incr counter + } + if { $counter > 1 } { + set limitation " and ($limitation)" + } else { + set limitation " and $limitation" + } + if { $composite_children_p } { + append limitation " +and q.abstract_data_type in ('text', 'option', 'category', 'other_category', 'date', 'file', 'integer', 'object_link', 'content_link', 'user_link', 'child_object', 'nephew_object') +and q.question_id not in (select parent_question_id from sn_question_object_type_map where object_type_id=:object_type_id and branch_p='t')" + } + set result [km_db_to_named_list_list km_branch_questions " + select q.question_id, q.pretty_name, q.abstract_data_type + $additional_columns + from sn_questions q, sn_question_object_type_map qm + where q.question_id=qm.question_id + and qm.object_type_id = :object_type_id + $limitation + order by qm.sort_key"] + + return $result +} Index: openacs-4/contrib/obsolete-packages/library/tcl/km-browse-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/tcl/km-browse-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/tcl/km-browse-procs.tcl 2 Jul 2003 12:19:41 -0000 1.1 @@ -0,0 +1,375 @@ +# /tcl/km-browsing.tcl +# +# Browsing of knowledge objects. +# Created by carsten@arsdigita.com in June 2000 +# +# $Id: km-browse-procs.tcl,v 1.1 2003/07/02 12:19:41 peterm Exp $ + +proc_doc km_ancestors_context_list {ancestors {category_id ""} {pre_url ""}} { + + Get a list of links to the parent objects, plus a link + to the root parent's object type. + +} { + set root_object_id [fst [fst $ancestors]] + + db_1row get_root_info { + select o.one_line_description as ancestor_name, + o.object_type_id as ancestor_object_type_id, + ot.pretty_plural as ancestor_object_type, + o.archived_p as ancestor_archived_p + from sn_objects o, sn_object_types ot + where o.object_id = :root_object_id + and ot.object_type_id = o.object_type_id + } + + if {$ancestor_archived_p == "t"} { + set ancestor_object_type "$ancestor_object_type (Archived)" + set archive t + } + lappend result [list "${pre_url}browse-one-type?[export_vars [list [list object_type_id $ancestor_object_type_id] archive]]" $ancestor_object_type] + + if {![empty_string_p $category_id] && $category_id != "none"} { + if {[db_string is_object_of_category {select count(*) from sw_object_category_map where category_id = :category_id and object_id = :root_object_id}] > 0} { + lappend result [list "${pre_url}browse-one-category?[export_vars [list [list object_type_id $ancestor_object_type_id] category_id archive]]" [km_category_name $category_id]] + } + } + + foreach ancestor $ancestors { + set name [sn_striphtml [snd $ancestor]] + if {[empty_string_p $name]} { + set name "Unnamed [km_static object_type_pretty_name [thd $ancestor]]" + } + lappend result [list "${pre_url}object-view?object_id=[fst $ancestor]&category_id=$category_id" $name] + } + + return $result +} + +proc_doc km_sort_by_bar { sort_by child_type_p } { + Sort: Object name | Modification date +} { + set sort_by_list {{name "name"} {last_modified "modification date"}} + lappend sort_by_list {average_rating "user rating"} + if { $child_type_p } { lappend sort_by_list {parent "parent object"} } + + foreach sort_item $sort_by_list { + set sort_column [lindex $sort_item 0] + set sort_description [lindex $sort_item 1] + + if {$sort_column == $sort_by} { + lappend sort_text "$sort_description" + } else { + lappend sort_text "$sort_description" + } + } + + return "\[ [join [concat $sort_text] " | "] \]" +} + +proc_doc km_category_display_limit {} { + + If the object list contains more than this many objects, + no categorization will be shown. + +} { + return [ad_parameter CategoryDisplayLimit library 20] +} + +ad_proc km8_output_object_list { + { + -object_type_id 0 + -header "" + -current_action "" + -path_id "" + -pool all + -age all + -sort_by "" + -show short + -category_id "" + -question_id 0 + -where_clauses {} + -minus_join_tables {} + -minus_where_clauses {} + -first_row 0 + -last_row 0 + -begin_letter "" + -archived "f" + -start_date "" + -end_date "" + -more_join_tables {} + } +} { + + Output a list of objects. + +} { + ! Entered km8_output_object_list +more_join_tables + set user_id [ad_conn user_id] + set package_id [ad_conn package_id] + set instance_read_p [ad_permission_p $package_id "read"] + + template::multirow create object_list public_p archived_p review_p object_view_link object_name user_link last_modified number_ratings rating_avg rating_avg_img rating_max rating_max_img access_total access_month overview categories_html + + set child_type_p [db_string km_output_object_list_1 " + select decode(count(*),0,0,1) from sn_questions + where abstract_data_type in ('child_object','nephew_object') + and target_object_type_id = :object_type_id"] + + # If the user is linking, or adding a SN reference, + # we add a button to each object. + + # Make sure the user cannot see expired or private objects. + # Exceptions: Administrators, Sharenet Managers, and users who have been granted + # view permission for the object. + + set join_tables [list "sn_objects obj"] + + set package_id [ad_conn package_id] + lappend where_clauses \ + "obj.expiration_date > sysdate" \ + "obj.object_type_id = :object_type_id" \ + "obj.context_id = :package_id" \ + "obj.archived_p = :archived" + + if { !$instance_read_p && $pool == "all" } { + # Only count published objects, or objects for which the user + # has view permission. + + # Note that we only check direct read permission on flat + # groups and users. Since the context_id of private objects is + # NULL, and we only grant permissions to private groups, this + # is sufficient. + + lappend where_clauses \ + "(obj.public_p = 't' or obj.object_id in ( + select object_id from acs_permissions + where (grantee_id = :user_id + or grantee_id in (select group_id from membership_rels + where person_id = :user_id)) + and privilege = 'read'))" + } + + if { [string compare $age all] != 0 } { + # Filter by time of last modification. + lappend where_clauses "sysdate - obj.last_modified < :age" + } + + # Filter by author and co-owners. + switch $pool { + own { lappend where_clauses "obj.original_author_id = :user_id" } + coown { + lappend join_tables "acs_permissions p" + + lappend where_clauses \ + "obj.object_id = p.object_id" \ + "p.privilege = 'write'" \ + "(p.grantee_id = :user_id + or p.grantee_id in (select group_id from membership_rels where person_id = :user_id))" + } + } + + # Sort by time of last modification or by name. + set columns {1} + switch $sort_by { + average_rating { + set sort_by_clause "nvl(cr.rating_sum,0) / nvl(cr.rating_count,1) desc, obj.last_modified desc" + set sort_by_clause2 "rating_avg desc, last_modified desc" + } + last_modified { + set sort_by_clause "obj.last_modified desc, lower(obj.one_line_description)" + set sort_by_clause2 "last_modified desc, lower(name)" + } + name { + set sort_by_clause "lower(obj.one_line_description), obj.last_modified desc" + set sort_by_clause2 "lower(name), last_modified desc" + } + parent { + set sort_by_clause "lower(obj2.one_line_description), lower(obj.one_line_description), obj.last_modified desc" + set sort_by_clause2 "lower(parent_name), lower(name), last_modified desc" + + lappend columns "obj2.one_line_description as parent_name" + lappend join_tables "km_flat_object_hierarchy fo" "sn_objects obj2" + lappend where_clauses \ + "fo.child(+) = obj.object_id" \ + "(fo.distance = 1 or fo.distance is null)" \ + "fo.parent = obj2.object_id(+)" + } + default { + set sort_by_clause "$sort_by, obj.last_modified desc" + set sort_by_clause2 "$sort_by, last_modified desc" + } + } + + if { ![string equal $begin_letter all] } { + if { ![string equal $begin_letter other] } { + lappend where_clauses "substr(upper(obj.one_line_description),1,1) = '[string toupper $begin_letter]'" + } else { + lappend where_clauses "(substr(upper(obj.one_line_description),1,1) < 'A' or substr(upper(obj.one_line_description),1,1) > 'Z')" + } + } + + if { ![empty_string_p $start_date] && ![empty_string_p $end_date]} { + lappend where_clauses "obj.start_date <= :end_date" "obj.end_date >= :start_date" + } + + set join_tables [concat $join_tables $more_join_tables] + + # We first need to get the number of listed objects, because + # depending on this number, we will or will not display object + # categorization. + + ! Get the number of listed objects + set num_found_objects [db_string count_all_objects " + select count(unique obj.object_id) + from [join $join_tables ", "] + where [join $where_clauses "\nand "]"] + ! Got the number of listed objects +num_found_objects + + if { ![null_p $minus_join_tables] } { + ! Get the number of excluded objects + set num_excluded_objects [db_string count_excluded_objects " + select count(unique obj.object_id) + from [join [concat $join_tables $minus_join_tables] ", "] + where [join [concat $where_clauses $minus_where_clauses] "\nand "]"] + ! Got the number of excluded objects +num_excluded_objects + + set num_found_objects [expr $num_found_objects - $num_excluded_objects] + } + + if { $child_type_p } { + lappend columns "km_utilities.km_ancestor_list(obj.object_id) as ancestors" + } + + set display_limit [km_category_display_limit] + set category_questions {} + if { $num_found_objects < $display_limit } { + # Get node_id, category, question_id, question_pretty_name. + set category_questions [km_node_question_list $object_type_id] + + foreach category_tuple $category_questions { + set root_node_id [fst $category_tuple] + lappend columns "km_utilities.km_category_list(obj.object_id, $root_node_id) as cat$root_node_id" + } + } + + if { [null_p $minus_join_tables] } { + set sql " + select * from (select obj.object_id, + decode(obj.public_p,'t',1,0) as public_p, + decode(obj.archived_p,'t',1,0) as archived_p, + decode(obj.in_review_p,'t',1,0) as review_p, + u.first_names || ' ' || u.last_name as owner, u.user_id as owner_id, + obj.one_line_description as name, obj.overview, + decode(obj.overview_html_p,'t',1,0) as overview_html_p, + obj.last_modified, nvl(obj.access_total,0) as access_total, + nvl(obj.access_month,0) as access_month, + round(nvl(cr.rating_sum,0) / nvl(cr.rating_count,1),1) as rating_avg, + nvl(cr.rating_max,0) as rating_max, + nvl(cr.rating_count,0) as number_ratings, + dense_rank() over (order by $sort_by_clause) dr, + [join $columns ", "] + from [join $join_tables ", "], sn_comments_ratings cr, users u + where u.user_id = obj.original_author_id + and cr.object_id(+) = obj.object_id + and [join $where_clauses "\nand "]) + where dr >= :first_row and (:last_row = 0 or dr <= :last_row) + order by $sort_by_clause2" + } else { + # This will be a bit complicated. We were called from browse-one-category + # to display a list of uncategorized objects. The fastest way to do this + # is with a MINUS, using only the object_id column. We then join the result + # with the query we would normally use to get the data we want. + + set sql " +select * from (select obj.object_id, + decode(obj.public_p,'t',1,0) as public_p, + decode(obj.archived_p,'t',1,0) as archived_p, + decode(obj.in_review_p,'t',1,0) as review_p, + u.first_names || ' ' || u.last_name as owner, u.user_id as owner_id, + obj.one_line_description as name, obj.overview, + decode(obj.overview_html_p,'t',1,0) as overview_html_p, + obj.last_modified, nvl(obj.access_total,0) as access_total, + nvl(obj.access_month,0) as access_month, + round(nvl(cr.rating_sum,0) / nvl(cr.rating_count,1),1) as rating_avg, + nvl(cr.rating_max,0) as rating_max, + nvl(cr.rating_count,0) as number_ratings, + dense_rank() over (order by $sort_by_clause) dr, + [join $columns ", "] +from [join $join_tables ", "], sn_comments_ratings cr, users u, + (select obj.object_id + from [join $join_tables ", "] + where [join $where_clauses "\nand "] + minus + select /*+ORDERED*/ obj.object_id + from [join [concat $join_tables $minus_join_tables] ", "] + where [join [concat $where_clauses $minus_where_clauses] "\nand "]) filtered +where u.user_id = obj.original_author_id + and cr.object_id(+) = obj.object_id + and obj.object_id = filtered.object_id) +where dr >= :first_row and (:last_row = 0 or dr <= :last_row) +order by $sort_by_clause2" + } + + # We pass use a path to pass a couple of values to object-view, + # so they can be used as return URLs. (This is important because + # we want to preserve the user's filter and sort settings.) + + set value_list [list browse_type [export_url_vars pool age sort_by show begin_letter]] + set parameters "" + if { ![empty_string_p $category_id] } { + set value_list [concat $value_list [list browse_category [export_url_vars pool age sort_by show begin_letter question_id column_name]]] + set parameters "&category_id=$category_id" + } + set new_path_id [init_path -last_path_id $path_id $value_list "" "browse"] + + ! Getting the object list + set old_rank "0" + db_foreach get_object_list $sql { + ## filter out duplicate rows with the same dense_rank than the row + ## before + if {$dr == $old_rank} { + continue + } + set old_rank $dr + set categories_html "" + + # Display the object's parent. + if { $child_type_p && ![empty_string_p $ancestors] } { + append categories_html "Related Objects: " + foreach ancestor $ancestors { + append categories_html "[snd $ancestor]; " + } + set categories_html [string range $categories_html 0 end-2] + } + + if { $num_found_objects <= $display_limit && ![null_p $category_questions] } { + # List the object's categories. + foreach category_pair $category_questions { + set root_node_id [fst $category_pair] + set question_name [lindex $category_pair 3] + set category_value [set cat$root_node_id] + + if ![empty_string_p $category_value] { + if ![empty_string_p $categories_html] { append categories_html "; " } + append categories_html "$question_name: $category_value" + } + } + } + + if ![empty_string_p $overview] { + set overview [util_trim_string_with_hrefs [sn_striphtml $overview]] + } + + if [empty_string_p $name] { + set name "Unnamed [km_static object_type_pretty_name $object_type_id]" + } + + set object_view_link "object-view?object_id=$object_id$parameters&path_id=$new_path_id" + template::multirow append object_list $public_p $archived_p $review_p $object_view_link [sn_striphtml $name] [ad_present_user $owner_id $owner] [util_AnsiDatetoPrettyDate $last_modified] $number_ratings $rating_avg [gf_feedback_points_img $rating_avg 5] $rating_max [gf_feedback_points_img $rating_max 5] $access_total $access_month $overview $categories_html + } + ! Got the object list + + ! Exiting km8_output_object_list + return $num_found_objects +} Index: openacs-4/contrib/obsolete-packages/library/tcl/km-callback-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/tcl/km-callback-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/tcl/km-callback-procs.tcl 2 Jul 2003 12:19:41 -0000 1.1 @@ -0,0 +1,200 @@ +# /tcl/km-callback-procs.tcl +# +# Procs called from other modules. +# +# @author Carsten Clasohm (carsten@arsdigita.de) +# @creation-date 2001-10-10 +# @cvs-id $Id: km-callback-procs.tcl,v 1.1 2003/07/02 12:19:41 peterm Exp $ + +ad_proc -public library_post_instantiation { + package_id +} { + This is the TCL proc that is called automatically by the APM + whenever a new instance of the application is created. +} { + sn_community::grant_role_permissions $package_id { + maintainer {access create km_publish} + member {access create} + guest {access} + } + db_exec_plsql create_magic_psn_category_objects { + begin + psn_res_application.create_magic_objects ( + package_id => :package_id + ); + end; + } +} + +ad_proc -public library_supported_privileges {} { + + Returns a list of instance-level privileges supported by the Library. + Used by sn-communities to set permissions for role groups. + +} { + return { + {admin "Administer"} + {access "Access"} + {create "Create new objects"} + {read "Read private objects"} + {write "Edit all objects"} + {delete "Delete all objects"} + {km_publish "Publish an object if approval process is true"} + } +} + +ad_proc -public library_copy_data {source_package_id target_package_id} { + Copy object type structure to the target package. +} { + set ip_address [ns_conn peeraddr] + set user_id [ad_get_user_id] + + db_exec_plsql copy_all_object_types { + begin + library.copy ( + src_package_id => :source_package_id, + dst_package_id => :target_package_id, + creation_user => :user_id, + creation_ip => :ip_address); + end; + } +} + +ad_proc -public library_get_category_trees {package_id} { + + Returns a list of all category trees used by this instance. + Used during community copying, to grant permissions on the trees. + +} { + + return [db_list get_categories { + -- Categories used for object type questions. + select tree_id + from sn_object_types ot, sn_question_object_type_map qm, sn_questions q + where ot.context_id = :package_id + and qm.object_type_id = ot.object_type_id + and q.question_id = qm.question_id + and q.abstract_data_type in ('category', 'other_category') + and q.tree_id is not null + union + -- Categories used for object feedback. + select object_id_two + from acs_rels + where rel_type = 'object_category_tree_rel' + and object_id_one = :package_id + union + -- Categories used on the PeopleShareNet application form. + select object_id_two + from acs_rels r, psn_category_trees ct + where r.rel_type = 'object_category_tree_rel' + and ct.package_id = :package_id + and (r.object_id_one = ct.role_magic_id + or r.object_id_one = ct.language_magic_id + or r.object_id_one = ct.proficiency_magic_id) + + }] + +} + +namespace eval categories::packages::library { + ad_proc -public get_instances { tree_id } { + Returns a list of all library instances using a certain category tree + } { + set instance_list [list] + set user_id [ad_conn user_id] + + db_foreach get_library_instances_for_tree { + select v.object_id, p.instance_name, v.object_name, + ci.community_id, p2.instance_name as community_name, + acs_permission.permission_p(p.package_id, :user_id, 'access') as show_p + from apm_packages p, apm_packages p2, sn_community_instances_all ci, + (select distinct q.question_id, ot.object_type_id as object_id, + ot.pretty_plural || ' (Question "' || q.pretty_name || '")' as object_name, + ot.context_id as package_id + from sn_object_types ot, sn_questions q, + sn_question_object_type_map qm, sw_category_dim d + where d.parent_node_id = q.node_id + and d.tree_id = :tree_id + and q.question_id = qm.question_id + and qm.object_type_id = ot.object_type_id + union + select 0 as question_id, p.package_id as object_id, + 'Feedback' as object_name, p.package_id + from acs_rels r, apm_packages p + where r.object_id_two = :tree_id + and r.rel_type = 'object_category_tree_rel' + and r.object_id_one = p.package_id + and p.package_key = 'library') v + where p.package_id = v.package_id + and ci.package_id = v.package_id + and p2.package_id = ci.community_id + order by p2.instance_name, p.instance_name, v.object_name + } { + lappend instance_list [list Libraries $object_id $object_name $instance_name $community_id $community_name $show_p $show_p] + } + return $instance_list + } +} + +namespace eval sn_presentation::types::sn_object { + ad_proc linkable_item {object_id url object_data_var} { + upvar 1 $object_data_var object_data + + set public_p 0 + if { [string first "presentation=public" $object_data(presentation)] != -1 } { + set public_p 1 + } + set archived_p 0 + if { [string first "archived" $object_data(presentation)] != -1 } { + set archived_p 1 + } + set in_review_p 0 + if { [string first "in_review" $object_data(presentation)] != -1 } { + set in_review_p 1 + } + + set result "[sn_striphtml $object_data(name)]" + if { !$public_p } { append result " \[Private\]" } + if { $archived_p } { append result " \[Archived\]" } + if { $in_review_p } { append result " \[In review\]" } + return $result + } + + ad_proc item {object_id object_data_var} { + upvar 1 $object_data_var object_data + + set public_p 0 + if { [string first "presentation=public" $object_data(presentation)] != -1 } { + set public_p 1 + } + set archived_p 0 + if { [string first "archived" $object_data(presentation)] != -1 } { + set archived_p 1 + } + set in_review_p 0 + if { [string first "in_review" $object_data(presentation)] != -1 } { + set in_review_p 1 + } + + set result [sn_striphtml $object_data(name)] + if { !$public_p } { append result " \[Private\]" } + if { $archived_p } { append result " \[Archived\]" } + if { $in_review_p } { append result " \[In review\]" } + return $result + } +} + +namespace eval alerts { + namespace eval types { + namespace eval sn_object { + ad_proc -public get_object {object_id} { + } { + if { [catch { set object_as_clob [db_string object_public_object_clob \ + {select site_wide_search.indexed_content(:object_id) from dual}]} errmsg] } { + return [list "" 0] + } + return [list $object_as_clob 0] + } + } + } +} Index: openacs-4/contrib/obsolete-packages/library/tcl/km-categories-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/tcl/km-categories-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/tcl/km-categories-procs.tcl 2 Jul 2003 12:19:41 -0000 1.1 @@ -0,0 +1,876 @@ +# /tcl/km-categories.tcl +# +# Categorization of knowledge objects. +# +# Created by carsten@arsdigita.com in June 2000 +# +# Modified by tvujec@arsdigita.com in August 2001 +# +# $Id: km-categories-procs.tcl,v 1.1 2003/07/02 12:19:41 peterm Exp $ + +# Category hierarchy +# +# location [Placeholder] +# Global [Location] + +ad_proc km_category_table { + { + -object_type_id 0 + -question_id 0 + -parent_node_id 0 + -uncategorized_p 1 + -target {} + -category_counts {} + -maximum_sub_columns 1 + } +} { + + Generate the table of links for a category tree. Returns 0 if + the table is empty, otherwise returns a non-zero integer. + +} { + template::multirow create categorization_widget category target category_id sum_count parent_node_id question_id + template::multirow create categorization_widget_header header_name + if { !$parent_node_id } { + + # If no parent categories have been specified, we get all the + # categories that can be associated with the given object type + # and question. + + set questions [db_list_of_lists get_category_questions { + select q.question_id, q.node_id, q.pretty_name + from sn_questions q, sn_question_object_type_map qm + where qm.object_type_id = :object_type_id + and qm.question_id = q.question_id + and qm.question_state <> 'invisible' + and q.browse_p = 't' + and q.abstract_data_type in ('category','other_category') + order by qm.sort_key}] + + if [null_p $questions] { return 0 } + } else { + set pretty_question [db_string get_pretty_question { + select pretty_name + from sn_questions + where question_id = :question_id}] + set questions [list [list $question_id $parent_node_id $pretty_question]] + } + + set category_list {} + foreach question $questions { + # For each of the parent categories we display the child categories. + + set question_id [fst $question] + set parent_node_id [snd $question] + set pretty_question [thd $question] + + if { $uncategorized_p && ![empty_string_p $category_counts] } { + set uncategorized_target "${target}none&question_id=$question_id" + set uncategorized_count [ns_set get $category_counts "uncat $question_id"] + } else { + set uncategorized_target "" + set uncategorized_count 0 + } + + set elem [km8_categorization_widget \ + -uncategorized_p $uncategorized_p \ + -parent_node_id $parent_node_id -target $target \ + -question_id $question_id \ + -category_count $category_counts \ + -uncategorized_target $uncategorized_target \ + -uncategorized_count $uncategorized_count \ + -maximum_columns $maximum_sub_columns] + + if ![null_p $elem] { + lappend category_list [list $pretty_question $elem] + } + } + + set n_total 0 + set i 0 + set category_type_count [llength $category_list] + while { $i < $category_type_count } { + template::multirow append categorization_widget_header [fst [lindex $category_list $i]] + incr i + } + + return $i +} + +proc_doc km_get_child_categories {question_id} { + + Returns all the categories associated with the given question + as a list of tuples holding the category_id and the indented + category name. + +} { + set root_node_id [db_string get_node_id { + select node_id from sn_questions + where question_id = :question_id + }] + + if ![empty_string_p $root_node_id] { + set result [util_memoize "swc_get_category_tree $root_node_id 0 {}"] + } else { + set result {} + } + + return $result +} + +proc_doc km_get_node_id {question_id} { + + Returns the node_id for this question_id or an empty string. + +} { + set result [db_string km_get_category_id " + select node_id from sn_questions where question_id=:question_id" -default ""] + return $result +} + +proc_doc km_categorize_object { question_id object_id category_ids } { + + Inserts a row into the sw_object_category_map which maps each + object to a list of categories. + + Also takes care of removing old categorizations which are of the same type + as the given category_ids. + + Returns a list of 1 for each successfully inserted and 0 for each + failed category_id. + +} { + foreach category_id $category_ids { + if ![empty_string_p $category_id] { + lappend nonempty_category_ids $category_id + } + } + if {![info exists nonempty_category_ids]} { + km_uncategorize_object $object_id $question_id + return + } + set category_ids $nonempty_category_ids + + set user_id [ad_conn user_id] + set ip_address [ns_conn peeraddr] + + db_transaction { + # First get rid of any old categorizations of this object + # that belongs to the same question. + + db_dml uncategorize { + delete from sw_object_category_map + where object_id = :object_id + and category_id in (select child_category_id from sw_flat_cat + where parent = (select node_id from sn_questions + where question_id = :question_id)) + } + + # Insert the new categorization. + # The insert query gracefully ignores duplicate categorization. + + foreach category_id $category_ids { + db_dml categorize { + insert into sw_object_category_map (object_id, category_id) + select :object_id, :category_id + from dual + where not exists (select 1 from sw_object_category_map + where object_id = :object_id + and category_id = :category_id) + } + } + + db_exec_plsql last_modified { + begin + acs_object.last_modified ( + v_object_id => :object_id, + v_modifying_user => :user_id, + v_modifying_ip => :ip_address + ); + end; + } + + set pretty_categories [db_list km_categorize_object_50 " + select long_name from categories + where category_id in ([join $category_ids ","])"] + + if { [llength $pretty_categories] > 1 } { + set label "categories" + } else { + set label "category" + } + + set content "Set $label [DoubleApos [join $pretty_categories ", "]]." + db_exec_plsql km_categorize_object_6 { + begin + object.audit_object ( + v_object_id => :object_id, + v_question_id => :question_id, + v_last_modifying_user_id => :user_id, + v_modifying_ip => :ip_address, + v_content => :content + ); + end; + } + } + + # After the user has changed the categorization of an object, we + # want to give him up-to-date category counts. So we flush the + # memoized km_get_category_count results for him. + km_flush_category_count -object_id $object_id +} + +ad_proc km_flush_category_count { + { + -object_id 0 + -object_type_id 0 + -user_id 0 + -local 0 + } +} { + Clears the cached category count for the current user. + Note that we only flush for "begin_letter all". Flushing + for all letters would take too much time. +} { + if !$user_id { set user_id [ad_conn user_id] } + if !$object_type_id { set object_type_id [km_get_object_type $object_id] } + + if !$local { + server_cluster_httpget_from_peers "/SYSTEM/flush-category-count.tcl?[export_url_vars object_type_id user_id]" + } + + foreach pool {all own coown} { + foreach age {90 180 365 730 all} { + foreach archived {t f} { + util_memoize_flush_local "km_get_category_count_internal -age $age -pool $pool -begin_letter all -archived $archived $object_type_id $user_id" + } + } + } +} + +ad_proc km_uncategorize_object { object_id question_id } { + + Removes all categorization of this object for this question. + This is used for non-mandatory fields were the user hasn't selected + any categories. + +} { + db_transaction { + db_dml uncategorize { + delete from sw_object_category_map + where object_id = :object_id + and category_id in (select child_category_id from sw_flat_cat + where parent = (select node_id from sn_questions + where question_id = :question_id)) + } + + set user_id [ad_conn user_id] + set ip_address [ns_conn peeraddr] + + db_exec_plsql km_uncategorize_object_10 { + begin + acs_object.last_modified ( + v_object_id => :object_id, + v_modifying_user => :user_id, + v_modifying_ip => :ip_address + ); + end; + } + + set content "Deleted all categories." + set ip_address [ns_conn peeraddr] + db_exec_plsql km_uncategorize_object_3 { + begin + object.audit_object ( + v_object_id => :object_id, + v_question_id => :question_id, + v_last_modifying_user_id => :user_id, + v_modifying_ip => :ip_address, + v_content => :content + ); + end; + } + } + + km_flush_category_count -object_id $object_id +} + +ad_proc km_get_categories {object_id question_id } { + Returns a list of {category_id category} mapped to this object and this question. +} { + return [db_list_of_lists get_categories { + select c.category_id, c.long_name + from categories c, sw_flat_cat fc, sw_object_category_map cm, sn_questions q + where cm.object_id = :object_id + and q.question_id = :question_id + and fc.parent = q.node_id + and c.category_id = fc.child_category_id + and cm.category_id = c.category_id + }] +} + +ad_proc km_get_category_counts { + { + -age "all" + -pool "all" + -begin_letter "all" + -start_category_id 0 + -archived "f" + -start_date "" + -end_date "" + } + object_type_id result +} { + + Returns the count of number of objects as a new ns_set. + Caches things for a few minutes. + +} { + set category_count_timeout [ad_parameter CategoryCountTimeout library 300] + set user_id [ad_conn user_id] + + set category_count_list [util_memoize "km_get_category_count_internal -age $age -pool $pool -begin_letter $begin_letter -start_category_id $start_category_id -archived $archived -start_date $start_date -end_date $end_date $object_type_id $user_id" $category_count_timeout] + + foreach elem $category_count_list { + ns_set put $result [lindex $elem 0] [lindex $elem 1] + } + + return $result +} + +ad_proc km_get_category_count_internal { + { + -age "all" + -pool "all" + -begin_letter "all" + -start_category_id 0 + -archived "f" + -start_date "" + -end_date "" + } + object_type_id user_id +} { + + Counts the number of objects the user can view, grouped by + category. (Internal version.) + +} { + ! We're not caching. Entering km_get_category_count_internal + set package_id [ad_conn package_id] + set instance_read_p [ad_permission_p $package_id "read"] + + set category_count_list {} + + lappend where_clauses \ + "o.object_type_id = :object_type_id" \ + "o.context_id = :package_id" \ + "o.expiration_date > sysdate" \ + "o.archived_p = :archived" + + set tables "sw_category_dim swcd, sw_flat_cat fc, sw_object_category_map swcm, sn_objects o" + set total_tables "sn_objects o" + if { !$instance_read_p && $pool == "all" } { + # Only count published objects, or objects for which the user + # has view permission. + + # Note that we only check direct read permission on flat + # groups and users. Since the context_id of private objects is + # NULL, and we only grant permissions to private groups, this + # is sufficient. + + lappend where_clauses \ + "(o.public_p = 't' or o.object_id in ( + select object_id from acs_permissions + where (grantee_id = :user_id + or grantee_id in (select group_id from membership_rels + where person_id = :user_id)) + and privilege = 'read'))" + } + + if { $age != "all" } { lappend where_clauses "sysdate - o.last_modified < :age" } + + # Filter by author. + switch $pool { + own { + lappend where_clauses "o.original_author_id = :user_id" + } + coown { + set tables "(select group_id as grantee_id from membership_rels where person_id = :user_id union select $user_id as grantee_id from dual) g, acs_permissions p, sn_objects o, sw_object_category_map swcm, sw_flat_cat fc, sw_category_dim swcd" + set total_tables "(select group_id as grantee_id from membership_rels where person_id = :user_id union select $user_id as grantee_id from dual) g, acs_permissions p, sn_objects o" + lappend where_clauses \ + "o.object_id = p.object_id" \ + "p.grantee_id = g.grantee_id" \ + "p.privilege = 'write'" + } + } + + if { ![string equal $begin_letter all] } { + if { ![string equal $begin_letter other] } { + lappend where_clauses "upper(o.one_line_description) like '[string toupper $begin_letter]%'" + } else { + lappend where_clauses "(upper(o.one_line_description) < 'A' or upper(o.one_line_description) > 'Z')" + } + } + + if { ![empty_string_p $start_date] && ![empty_string_p $end_date]} { + lappend where_clauses "o.start_date <= :end_date" "o.end_date >= :start_date" + } + + # Count the total number of viewable objects. + + set total_viewable_objects_count [db_string get_total_count [subst { + select count(unique o.object_id) + from $total_tables + where [join $where_clauses "\nand "] + }]] + + lappend category_count_list [list total $total_viewable_objects_count] + + if { $start_category_id == 0 } { + + # Count the uncategorized stuff for each question. + # We do this by counting all the categorized objects + # and subtracting the resulting number from the total number + # of objects. This is much faster than letting Oracle do + # the job. + + set questions [km_node_question_list -browse_p $object_type_id] + + foreach question $questions { + util_unlist $question question_node_id dummy question_id + + set count [db_string count_categorized_objects [subst { + select /*+ORDERED*/ count(unique o.object_id) + from $total_tables, sw_object_category_map swcm, sw_flat_cat fc + where [join $where_clauses "\n and "] + and swcm.object_id = o.object_id + and swcm.category_id = fc.child_category_id + and fc.parent = :question_node_id + }]] + + lappend category_count_list \ + [list "uncat $question_id" [expr $total_viewable_objects_count - $count]] + + # Count categorized stuff by category on the first level below the question. + + db_foreach get_category_counts [subst { + select /*+ORDERED*/ fc.parent_category_id, + count(unique o.object_id) as object_count + from $tables + where [join $where_clauses "\n and "] + and swcd.parent_node_id = :question_node_id + and fc.parent = swcd.node_id + and swcm.category_id = fc.child_category_id + and swcm.object_id = o.object_id + group by fc.parent_category_id + }] { + lappend category_count_list [list $parent_category_id $object_count] + } + } + + } else { + + # Get counts below a certain root category. + + set count [db_string count_categorized_objects [subst { + select /*+ORDERED*/ count(unique o.object_id) + from $total_tables, sw_object_category_map swcm, sw_flat_cat fc + where [join $where_clauses "\n and "] + and swcm.object_id = o.object_id + and swcm.category_id = fc.child_category_id + and fc.parent_category_id = :start_category_id + }]] + + lappend category_count_list \ + [list $start_category_id $count] \ + [list "uncat" [expr $total_viewable_objects_count - $count]] + + # Count categorized stuff by category on the first level below the question. + + set node_id [db_string get_start_node_id { + select node_id + from sw_category_dim + where object_id = :start_category_id + }] + + db_foreach get_category_counts [subst { + select /*+ORDERED*/ fc.parent_category_id, + count(unique o.object_id) as object_count + from $tables + where [join $where_clauses "\n and "] + and swcd.parent_node_id = :node_id + and fc.parent = swcd.node_id + and swcm.category_id = fc.child_category_id + and swcm.object_id = o.object_id + group by fc.parent_category_id + }] { + lappend category_count_list [list $parent_category_id $object_count] + } + + } + + ! Exiting km_get_category_count_internal + return $category_count_list +} + +ad_proc km_node_question_list { {-browse_p:boolean 0} object_type_id } { + + Returns a list of questions that are categorizations for the given + object type, each element being a list of + node ID, category or tree name, question ID, pretty_name. + if -browse_p is given, it will return only browseable category + questions. + +} { + if {$browse_p} { + set browse_clause "and q.browse_p = 't'" + } else { + set browse_clause "" + } + + set result [db_list_of_lists km_node_question_list " + select q.node_id, g.tree_name, q.question_id, q.pretty_name + from sn_questions q, sn_question_object_type_map qm, generic_trees g + where q.question_id = qm.question_id + and g.tree_id = q.tree_id + and qm.object_type_id = :object_type_id + and qm.question_state <> 'invisible' + $browse_clause + order by qm.sort_key"] + + return $result +} + +ad_proc km_question_in_object_type { } { + Replaces the PL/SQL function sn_question_in_object_type. + Returns an exists clause that should be much faster than the previous +PL/SQL function. +} { + return "and 1= (select count(*) + from sn_question_object_type_map + where object_type_id = :object_type_id + and question_id = :question_id + and question_state <> 'invisible')" +} + +proc_doc km_node_question { object_type_id node_id } { + + Given an object type and a top-level node ID, determine + which question this category belongs to. + +} { + # rownum=1 added by dirk (11-july-2001). remove it...it's most likely + # wrong, but I just want to get this big piece of software to run + + set result [db_string km_node_question " + select question_id from sn_questions + where node_id=:node_id + [km_question_in_object_type] and rownum=1" -default ""] + return $result +} + +ad_proc km_node_question_parent { object_type_id node_id } { + + Given an object type and a node ID, determine which question this + category belongs to. + +} { + return [km_db_1row_to_list km_node_question_parent { + select q.question_id, q.node_id + from sn_questions q, sw_flat_cat fc, sn_question_object_type_map qm + where fc.child = :node_id + and fc.parent = q.node_id + and qm.object_type_id = :object_type_id + and qm.question_id = q.question_id + and qm.question_state <> 'invisible' + }] +} + +ad_proc km_category_name { category_id } { + Get the name of the of a category +} { + if [empty_string_p $category_id] { return -code error "Missing category_id" } + if {[string equal $category_id none]} { + return "" + } + set result [db_string km_category_name " + select long_name from categories + where category_id = :category_id" -default ""] + + return $result +} + +ad_proc km_root_node { + { + -question_id 0 + } + object_type_id +} { + + Get the parent node_id for a given object type. + + If question_id is 0, a list of the parents for all the questions + of this object type is returned. + Else, the parent for the given question_id is returned. + +} { + if !$question_id { + # Select all categorization questions. + + set result [db_list km_root_node " + select node_id + from sn_questions q, sn_question_object_type_map qm + where q.node_id is not null + and qm.object_type_id = :object_type_id + and qm.question_id = q.question_id + and qm.question_state <> 'invisible' + order by sort_key"] + } else { + set result [db_string km_root_node_2 " + select node_id from sn_questions where question_id=:question_id" -default ""] + } + + return $result +} + +ad_proc km_object_filter_bar { + { + -child_type_p 0 + } + pool age sort_by +} { + + Filters and sorting options displayed on the top of most category pages. + Note that *you* have to provide the TABLE tag. + +} { + return " +Owner:[km_ownership_bar $pool] +Sort: [km_sort_by_bar $sort_by $child_type_p]" +} + +proc_doc km_object_view_bar_top_level { show short_title all_title } { + View: Just category descriptions | All objects +} { + set show_list [list [list short $short_title] [list all $all_title]] + + foreach show_pair $show_list { + set show_value [lindex $show_pair 0] + set show_annotation [lindex $show_pair 1] + + if {$show == $show_value} { + lappend show_bar "$show_annotation" + } else { + lappend show_bar "$show_annotation" + } + } + + return "\[ [join $show_bar " | "] \]" +} + +proc_doc km_ownership_bar { current_pool } { + Filter: My objects | My objects & co-owner | All +} { + return [ad_choice_bar \ + { "my objects" "my objects & co-owner" "all" } \ + "[ns_conn url]?[export_ns_set_vars url {pool}]&pool=\$value" \ + { own coown all } \ + $current_pool] +} + +proc_doc km_archive_bar { current_archive } { + Filter: Live Objects | Archived Objects +} { + return [ad_choice_bar \ + { "live objects" "archived objects" } \ + "[ns_conn url]?[export_ns_set_vars url {archive}]&archive=\$value" \ + { f t } \ + $current_archive] +} + +proc_doc km_age_bar { current_age } { + Filter: 3 6 12 24 months | All +} { + proc mk_link { default parms } { + set label [fst $parms] + set value [snd $parms] + + if { $value == $default } { + return "$label" + } else { + return "$label" + } + } + + return "[join [map "mk_link $current_age" [list "3 90" "6 180" "12 365" "24 730"]] " "] months | [mk_link $current_age "All all"]" +} + +ad_proc km8_categorization_widget { + { + -parent_node_id {} + -uncategorized_p 0 + -target {} + -question_id {} + -category_count {} + -uncategorized_target {} + -uncategorized_count {} + -maximum_columns 1 + } +} { + + Build the table showing category counts for a given parent category. + +} { + # Translate ns_set category_count into a Tcl array + # + if { ![null_p $category_count] } { + for {set i 0} {$i < [ns_set size $category_count]} {incr i} { + set sum_count([ns_set key $category_count $i]) [ns_set value $category_count $i] + } + } + + # Fetch the category hierarchy. + # + + set ordered {} + set select_size 0 + db_foreach categories { + select c.long_name as category, c.category_id + from categories c, sw_category_dim d + where d.parent_node_id = :parent_node_id + and c.category_id = d.object_id + order by nvl(c.sort_key,9999) + } { + if { [empty_string_p $category_count] || + ([info exists sum_count($category_id)] && $sum_count($category_id) > 0) } { + lappend ordered [list $category $category_id] + incr select_size + } + } + + if { !$select_size } { return "" } + + # Generate the widget open tag, now that we know the size + if { $maximum_columns > 1 } { + if { $select_size < 15 } { + set maximum_columns 1 + } else { + set column_size [expr $select_size / $maximum_columns] + } + } + + # What column are we currently writing to + set column_no 1 + # How many rows have we written to that + set column_count 0 + set show_category_p 0 + + # Iterate to generate the HTML + # + foreach elem $ordered { + set category [fst $elem] + set category_id [snd $elem] + + set option "" + + if { $maximum_columns > 1 } { + incr column_count + if { $column_count > $column_size && $column_no < $maximum_columns } { + incr column_no + set column_count 0 + } + } + + if {![info exists sum_count($category_id)]} { + set sum_count($category_id) "" + } + + set show_category_p 1 + template::multirow append categorization_widget $category $target $category_id "$sum_count($category_id)" $parent_node_id $question_id + + } + # foreach + + if { $uncategorized_p } { + if {![empty_string_p $uncategorized_count] && $uncategorized_count != 0} { + if { ![empty_string_p $uncategorized_target]} { + set target ${uncategorized_target} + } + set show_category_p 1 + template::multirow append categorization_widget Uncategorized $target "" $uncategorized_count $parent_node_id + + } + } + return $show_category_p +} + + +proc_doc ad_category_parentage_list {category_id {known_parent_id ""}} { + + Returns a list of lists, where each sublist is one line of + parentage up from the specified category to the hierarchy root. In + turn, each parentage line list consists of two-item lists: category_id + and long_name. A list of lists is needed since a category can have + multiple parents. If this category has no parents, then return the + empty list. + +} { + + set n_parents [db_string ad_category_parentage_list_10 "select count(*) from sw_category_dim where object_id = :category_id"] + + if { $n_parents == 0 } { + return [list] + } + + set sql_ad_category_parentage_list_20 "SELECT c.category_id AS parent_id, c.long_name AS parent_category, hc.level_col +FROM categories c, +(SELECT h.object_id as child, LEVEL AS level_col, ROWNUM AS row_col + FROM sw_category_dim h + START WITH h.object_id = :category_id + CONNECT BY h.node_id = PRIOR h.parent_node_id) hc +WHERE c.category_id = hc.child +ORDER BY hc.row_col" + + set parentage_list [list] + set parentage_line [list] + set prior_level 0 + set stop_everything 0 + db_foreach ad_category_parentage_list_20 $sql_ad_category_parentage_list_20 { + if {$stop_everything== 1} { + + if {$level_col <= $prior_level} { + # Parent line is now completed, flush it + lappend parentage_list $parentage_line + + # Keep the last bit of the parentage chain + # lars@pinds.com, Feb 2000 + # + set parentage_line [lrange $parentage_line [expr $prior_level - $level_col + 1] end] + } + + set prior_level $level_col + + # We're moving up the hierarchy so put this category at + # the beginning of the parentage line. + # + set parentage_line [concat [list [list $parent_id $parent_category]] $parentage_line] + + if { ![empty_string_p $known_parent_id] && $known_parent_id == $parent_id } { + set stop_everything 1 + } + } + + } + + if {$stop_everything == 1} { + # you cannot return from within db_foreach + return $parentage_line + } + if { [empty_string_p $known_parent_id] } { + # Don't forget the last parentage line + return [lappend parentage_list $parentage_line] + } else { + # We didn't find the wanted parent + return [list] + } +} Index: openacs-4/contrib/obsolete-packages/library/tcl/km-display-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/tcl/km-display-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/tcl/km-display-procs.tcl 2 Jul 2003 12:19:41 -0000 1.1 @@ -0,0 +1,490 @@ +# /tcl/km-display-procs.tcl +# +# Display of data. +# +# $Id: km-display-procs.tcl,v 1.1 2003/07/02 12:19:41 peterm Exp $ + +# ********** Display procs for questions of various abstract data types- No Form ********** +proc_doc km_display_category_value {category_value_list} { + Formats a list of category_id and category value tuples for simple display. +} { + set category_names [snd [transpose $category_value_list]] + set formatted_values [join $category_names ", "] + return $formatted_values +} + +proc_doc km_display_other_category_value {category_value_list object_id question_id} { + Formats a list of category_id and category value tuples for simple display. +} { + set other_value [snd [fst [km_get_object_content -question_ids [list $question_id] $object_id]]] + set category_names [snd [transpose $category_value_list]] + set category_list [list] + foreach category $category_names { + if { [string equal [string toupper $category] "OTHER"] && ![empty_string_p $other_value] } { + append category " ($other_value)" + } + lappend category_list $category + } + set formatted_values [join $category_list ", "] + return $formatted_values +} + +proc_doc km_display_options {answer_option_list} { + Displays tuples in an option list for simple display. +} { + return [join [snd [transpose $answer_option_list]] ", "] +} + +# *********Buttons********** + +ad_proc km_get_button_names {} { + Returns a list of all the constant submit button names in the km library. +} { + + return { + proceed + finish + details + add_web_ref + add_sn_ref + add_user_ref + add_content_ref + next_question + last_question + link + browse + all_questions + unanswered + answered + add_child + add_nephew + copy_child + copy_nephew + volunteer + previous_question + next_question + delete + } +} + +proc_doc km8_button_panel {question_id object_id object_type_id} { + + This proc returns the submit button-panel. + + Note that I'm getting the buttons to the same size manually, since netscape 4x + can't do width as a style for an input button. You have to pass the object_id + since the active branch path can only be determined from object data. + + } { + set captions {} + set button_values "" + set next_value "" + set next_name "" + + # If this question leads to a branch, we set the default answer as next question. + set root_branch_p [km_root_branch_p $question_id] + + # If this question is a branch, then we need to know its parent. + set branch_parent [km_branch_parent $question_id $object_type_id] + + # Determine the next question. + if { $root_branch_p } { + # The branch continues - so we don't know where to go to yet. + set next_question 0 + } elseif ![empty_string_p $branch_parent] { + # End of branch. We determine the next question relative to the branch root. + set branch_root [km_get_root_branch $question_id $object_type_id] + set next_question [km_get_question -next_p 1 -object_id $object_id $branch_root $object_type_id] + } else { + # This is no branch. So just use the current question_id for determining + # the next. + set next_question [km_get_question -next_p 1 -object_id $object_id $question_id $object_type_id] + } + + # Determine the previous question. + if ![empty_string_p $branch_parent] { + # When in a branch, Previous always takes us back to our parent. + set previous_question $branch_parent + } else { + set previous_question [km_get_question -previous_p 1 -object_id $object_id $question_id $object_type_id] + if ![empty_string_p $previous_question] { + if [km_root_branch_p [fst $previous_question]] { + # The previous question is the root of a branch. To find the actual "previous" + # question, we have to traverse this branch until the last active question. + set active_branches [km_active_branch_path [fst $previous_question] $object_id $object_type_id] + set previous_question [fst [reverse $active_branches]] + } + } + } + + set button_values {" << " " >> "} + if ![empty_string_p $previous_question] { + set previous_value [fst $button_values] + set previous_name "previous_question.[fst $previous_question]" + } + if ![empty_string_p $next_question] { + set next_value [snd $button_values] + set next_name "next_question.[fst $next_question]" + } + + set button_1 "" + set button_2 "" + if { ![empty_string_p $previous_question] && ![empty_string_p $next_question] } { + set button_1 $previous_name + set button_2 $next_name + } elseif ![empty_string_p $previous_question] { + set button_1 $previous_name + } elseif ![empty_string_p $next_question] { + set button_2 $next_name + } + + set button_names {"all_questions." "unanswered." "answered."} + set button_values {"All Questions" "Completed Content"} + return [list $button_1 \ + [fst $button_names] \ + [snd $button_names] \ + [thd $button_names] \ + $button_2] +} + +# ********** Basic Display Procs ********** +proc_doc km_count_object_view { user_id object_id } { + Record an object view. +} { + if {![km_original_author_p $user_id $object_id]} { + db_dml km_count_object_view_10 " + update sn_access_counts + set access_count = access_count + 1 + where object_id=:object_id + and access_date = (trunc(sysdate,'month'))" + + if {![db_resultrows]} { + db_dml insert_access_count { + insert into sn_access_counts (object_id, access_count, access_date) + select :object_id, 1, (trunc(sysdate,'month')) from dual + where not exists (select 1 from sn_access_counts + where object_id=:object_id + and access_date = (trunc(sysdate,'month'))) + } + db_dml reset_sn_object_monthly_count { + update sn_objects + set access_total = access_total +1, + access_month = 1 + where object_id = :object_id + } + } else { + db_dml increment_sn_object_count { + update sn_objects + set access_total = access_total +1, + access_month = access_month +1 + where object_id = :object_id + } + } + } +} + +proc_doc km_get_access_count { object_id } { +} { + return [db_string access_count { + select nvl(sum(access_count),0) + from sn_access_counts + where object_id = :object_id + }] +} + +proc_doc km_get_access_count_month { object_id } { +} { + return [db_string access_count_month { + select nvl(sum(access_count),0) + from sn_access_counts + where object_id = :object_id + and access_date = (trunc(sysdate,'month')) + }] +} + + +proc_doc km_object_access_toolbar {object_id {category_id ""}} { + Toolbar: [Private] Make public | Access Control | Delete Object +} { + set user_id [ad_conn user_id] + set package_id [ad_conn package_id] + + set return_url "object-view?[export_url_vars object_id category_id]" + + set result {} + set write_p [km_conn write_p] + set admin_p [km_conn admin_p] + set publish_p [km_conn publish_p] + set public_p [km_conn public_p] + set archived_p [km_conn archived_p] + set archive_p [km_static object_type_archive_p [km_conn object_type_id]] + set approval_p [km_static approval_p $package_id] + set in_review_p [km_conn in_review_p] + set review_state [km_conn review_state] + + # admins or users with write permission (if object is not archived) + # can make object public/private + if {$admin_p || ($approval_p && $publish_p)} { + if {!$public_p} { + if {$approval_p && $in_review_p} { + if {[string equal $review_state library_review]} { + lappend result "\[Private\] \[In review\] Make public" + } else { + lappend result "\[Private\] \[Needs clarification\] Make public" + } + } else { + lappend result "\[Private\] Make public" + } + } else { + lappend result "\[Public\] Make private" + } + } elseif {$write_p && !$archived_p} { + if { !$public_p } { + if {!$in_review_p && $approval_p} { + lappend result "\[Private\] Propose to publish" + } elseif {!$in_review_p} { + lappend result "\[Private\] Make public" + } else { + # The state of a workflow task is user-dependant, hence we need the + # else clause. A task might be in review, but there's nothing going + # on for the user. + db_1row get_workflow_task { + select distinct(ut.task_id) + from wf_cases c, wf_user_tasks ut + where c.object_id = :object_id + and c.case_id = ut.case_id + and c.state = 'active' + and rownum = 1 + order by ut.task_id desc + } + if {[string equal $review_state library_review]} { + lappend result "\[Private\] In review" + } elseif {[string equal $review_state library_clarify]} { + lappend result "\[Private\] Review: Needs clarification" + } else { + lappend result "\[Private\] \[In review\]" + } + } + } elseif {!$approval_p} { + lappend result "\[Public\] Make private" + } else { + lappend result "\[Public\]" + } + } else { + if { $in_review_p } { + lappend result "\[Private\] \[In review\]" + } elseif { !$public_p } { + lappend result "\[Private\]" + } + } + ## users with write permission can archive/unarchive object + ## (and admins and publishers) + if {$write_p || $admin_p || ($approval_p && $publish_p)} { + if {$archived_p} { + lappend result "\[Archived\] Remove from archive" + } + if {$archive_p && !$archived_p && ($admin_p || $publish_p || !$approval_p || (!$public_p && !$in_review_p))} { + lappend result "Put in archive" + } + } + # admins or users with write permission (if object is not archived) + # can change permissions on the object + if {$admin_p || ($write_p && !$archived_p)} { + lappend result "Access Control" + } + # users with delete permissions (owner or admins) can delete an object + if [km_conn delete_p] { + if {[empty_string_p $category_id] || $category_id == "none"} { + set return_delete "browse-one-type?object_type_id=[km_conn object_type_id]" + } else { + set return_delete "browse-one-category?object_type_id=[km_conn object_type_id]&category_id=$category_id" + } + lappend result "Delete Object" + } + + # admins or publishers have access to the approval task + if {$approval_p && $in_review_p && ($publish_p || $admin_p)} { + db_1row get_workflow_task { + select distinct(ut.task_id) + from wf_cases c, wf_user_tasks ut + where c.object_id = :object_id + and c.case_id = ut.case_id + and c.state = 'active' + and rownum = 1 + order by ut.task_id desc + } + lappend result "Manage Approval" + } + + return [join $result " | "] +} + +proc_doc km_shorten_question { question } { + Shortens a question up to the question mark in the question. +} { + set line_end [string first ? $question] + if { $line_end >= 0 } { + return [string range $question 0 $line_end] + } else { + return $question + } +} + +#-------------------------------------------------------- + + +proc_doc util_trim_string_with_hrefs { string_to_trim { final_length 200 } } { + Will return the trimmed string without cutting off an href before the tag. +} { + + if {[string length $string_to_trim] < $final_length} { + return $string_to_trim + } + + set string_trimmed [string range $string_to_trim 0 $final_length] + set string_trimmed_lower [string tolower $string_trimmed] + + # find the last occurance of " + set last_href_close [string last "" $string_trimmed_lower] + + # if there is no after the last $last_href_close} { + set string_trimmed [string range $string_trimmed 0 [expr $last_href - 1]] + } + } + + return "$string_trimmed..." +} + + +proc_doc util_make_href_and_mailto_links { text } { + Changes http:// and https:// to links and email formats to mailto's +} { + # (bd) if there are any A HREF or IMG SRCs this guy know how to use them + # so we don't touch his HTML. It may be hard to see but I am using + # carriage returns, # newlines, tabs and spaces (in that order) in these + # regexps: + set text " $text" + if {!([regexp -nocase {<[ + ]*a[ + ]*href[ + ]*=} $text] || [regexp -nocase {<[ + ]*img[ + ]*src[ + ]*=} $text])} { + # if something is " http://" or " https://" + # we assume it is a link to an outside source. + + # (bd) The only purpose of thiese sTaRtUrL and + # eNdUrL markers is to get rid of trailing dots, + # commas and things like that. Note that there + # is a TAB before and after each marker. + + regsub -nocase -all {"} $text {"} text + regsub -nocase -all {"} $text {"} text + regsub -nocase -all {([^a-zA-Z0-9]+)(http://[^\(\)"<> + ]+)} $text {\1 sTaRtUrL\2eNdUrL } text + regsub -nocase -all {([^a-zA-Z0-9]+)(https://[^\(\)"<> + ]+)} $text {\1 sTaRtUrL\2eNdUrL } text + regsub -nocase -all {([^a-zA-Z0-9]+)(ftp://[^\(\)"<> + ]+)} $text {\1 sTaRtUrL\2eNdUrL } text + + # email links have the form xxx@xxx.xxx + regsub -nocase -all {([^a-zA-Z0-9]+)([^\(\) + :;,@<>]+@[^\(\) + .:;,@<>]+[.][^\(\) + :;,@<>]+)} $text {\1 sTaRtEmAiL\2eNdEmAiL } text + # + regsub -all {([]!?.:;,<>\(\)\}-]+)(eNdUrL )} $text {\2\1} text + regsub -all {([]!?.:;,<>\(\)\}-]+)(eNdEmAiL )} $text {\2\1} text + regsub -all { sTaRtUrL([^ ]*)eNdUrL } $text {\1} text + regsub -all { sTaRtEmAiL([^ ]*)eNdEmAiL } $text {\1} text + } + return [string trimleft $text] +} + +proc_doc util_make_href_and_mailto_links_and_convert_to_html { text {html_p 0} } { + + util_make_href_and_mailto_links interferes badly with util_convert_to_html. + That's why I had to write a special procedure that does both things correctly. + See those two procs for details. + +} { + + if { $html_p } { return $text } + + set text " $text" + # if something is " http://" or " https://" + # we assume it is a link to an outside source. + + # (bd) The only purpose of thiese sTaRtUrL and + # eNdUrL markers is to get rid of trailing dots, + # commas and things like that. Note that there + # is a TAB before and after each marker. + + regsub -nocase -all {([^a-zA-Z0-9]+)(http://[^\(\)"<> + ]+)} $text {\1 sTaRtUrL\2eNdUrL } text + regsub -nocase -all {([^a-zA-Z0-9]+)(https://[^\(\)"<> + ]+)} $text {\1 sTaRtUrL\2eNdUrL } text + regsub -nocase -all {([^a-zA-Z0-9]+)(ftp://[^\(\)"<> + ]+)} $text {\1 sTaRtUrL\2eNdUrL } text + + # email links have the form xxx@xxx.xxx + regsub -nocase -all {([^a-zA-Z0-9]+)([^\(\) + :;,@<>]+@[^\(\) + .:;,@<>]+[.][^\(\) + :;,@<>]+)} $text {\1 sTaRtEmAiL\2eNdEmAiL } text + # At this point, before inserting some of our own <, >, and "'s + # we quote the ones entered by the user: + set text [util_quotehtml $text] + # turn CRLFCRLF into

+ if { [regsub -all "\015\012\015\012" $text "

" text] == 0 } { + # try LFLF + if { [regsub -all "\012\012" $text "

" text] == 0 } { + # try CRCR + regsub -all "\015\015" $text "

" text + } + } + # turn CRLF into
+ if { [regsub -all "\015\012" $text "
" text] == 0 } { + # try LF + if { [regsub -all "\012" $text "
" text] == 0 } { + # try CR + regsub -all "\015" $text "
" text + } + } + # Dress the links and emails with A HREF + regsub -all {([]!?.:;,<>\(\)\}-]+)(eNdUrL )} $text {\2\1} text + regsub -all {([]!?.:;,<>\(\)\}-]+)(eNdEmAiL )} $text {\2\1} text + regsub -all { sTaRtUrL([^ ]*)eNdUrL } $text {\1} text + regsub -all { sTaRtEmAiL([^ ]*)eNdEmAiL } $text {\1} text + return [string trimleft $text] +} + +proc_doc library_icon_height {} "Returns the height for an object icon" { + return "50" +} + +proc_doc library_icon_width {} "Returns the width for an object icon" { + return "50" +} + +ad_proc space {{-size 20}} "returns an html space" { + + set space "" + set i 0 + while { $i < $size } { + append space " " + incr i + } + return $space + +} Index: openacs-4/contrib/obsolete-packages/library/tcl/km-feedback-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/tcl/km-feedback-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/tcl/km-feedback-procs.tcl 2 Jul 2003 12:19:41 -0000 1.1 @@ -0,0 +1,165 @@ +# /tcl/km-feedback.tcl +# +# General comment system adapted to KM. +# +# Created by carsten@arsdigita.com in June 2000 +# modified by bernd@arsdigita.com in Jan. 2001 +# +# ported by dirk@arsdigita.com in July 2001 + +proc_doc km_check_comment_id { user_id comment_id } { + + Checks if the user may edit the comment. If not, 0 is returned. + If he has edit permission, the associated object_id is returned. + +} { + if {![db_0or1row km_check_comment_id_10 { + select object_id, user_id as comment_user_id + from sn_comments where comment_id = :comment_id + }] } { + ad_return_exception_page 404 "" \ + "The entry $comment_id does not exist in table general_comments." + return 0 + } + + if ![km_check_object_id $object_id] { return 0 } + + if { $user_id != $comment_user_id && ![km_conn admin_p] } { + ad_return_complaint 1 "

  • You cannot edit this entry because you did not post it." + return 0 + } + + return $object_id +} + +ad_proc km_general_comment_add { + object_id user_id html_p reuse_points scale feedback_category_id public_p comment +} { + + Inserts a comment into the general comment system with additional + possibility of giving feedback. + +} { + set ip_address [ns_conn peeraddr] + set package_id [ad_conn package_id] + set short_comment [string range $comment 0 3999] + + if {$reuse_points > $scale} { + return 0 + } + + db_transaction { + set new_comment_id [db_exec_plsql km_general_comment_add_10 { + begin + :1 := sn_comment.new_comment ( + object_id => :object_id, + html_p => :html_p, + display_p => :public_p, + rating => :reuse_points, + scale => :scale, + user_id => :user_id, + ip_address => :ip_address, + package_id => :package_id, + category_id => :feedback_category_id, + short_content => :short_comment + ); + end; + }] + + db_dml km_general_comment_add_20 { + update sn_comments + set content = empty_clob() + where comment_id = :new_comment_id + returning content into :1 + } -clobs [list $comment] + } + + return $new_comment_id +} + +ad_proc km_general_comment_update { + { + -html_p "f" + -public_p "t" + -feedback_category_id "" + } + user_id object_id comment_id comment +} { + Updates a comment in the general comment system. +} { + set ip_address [ns_conn peeraddr] + set short_comment [string range $comment 0 3999] + + db_exec_plsql km_general_comments_update_10 { + begin + sn_comment.update_comment ( + comment_id => :comment_id, + html_p => :html_p, + display_p => :public_p, + user_id => :user_id, + ip_address => :ip_address, + category_id => :feedback_category_id, + short_content => :short_comment + ); + end; + } + + db_transaction { + db_dml km_general_comments_update_20 " + update sn_comments + set content = empty_clob() + where comment_id = :comment_id + returning content into :1" -clobs [list $comment] + + } +} + +ad_proc feedback_points_img { feedback_points scale } { + Returns an IMG tag that shows via stars how valuable a posting was. + We have up to 5 stars, so we might need to scale. +} { + if { $scale == 5 } { + set scaled_feedback_points $feedback_points + } else { + set scaled_feedback_points [expr [expr [expr $feedback_points * 1.0] / $scale] * 5] + } + + if {$scaled_feedback_points <= 0} { + set gif_number "00" + } elseif {$scaled_feedback_points > 0 && $scaled_feedback_points < 1} { + set gif_number "05" + } elseif {$scaled_feedback_points == 1} { + set gif_number "10" + } elseif {$scaled_feedback_points > 1 && $scaled_feedback_points < 2} { + set gif_number "15" + } elseif {$scaled_feedback_points == 2} { + set gif_number "20" + } elseif {$scaled_feedback_points > 2 && $scaled_feedback_points < 3} { + set gif_number "25" + } elseif {$scaled_feedback_points == 3} { + set gif_number "30" + } elseif {$scaled_feedback_points > 3 && $scaled_feedback_points < 4} { + set gif_number "35" + } elseif {$scaled_feedback_points == 4} { + set gif_number "40" + } elseif {$scaled_feedback_points > 4 && $scaled_feedback_points < 5} { + set gif_number "45" + } else { + set gif_number "50" + } + + set points [format "%.1f" $feedback_points] + regsub {\.0} $points "" points + return "stars[set gif_number].gif" + +# return "$points \"$feedback_points" +} + + + + + + + + + Index: openacs-4/contrib/obsolete-packages/library/tcl/km-links-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/tcl/km-links-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/tcl/km-links-procs.tcl 2 Jul 2003 12:19:41 -0000 1.1 @@ -0,0 +1,1069 @@ +# /tcl/km-links.tcl +# +# Knowledge object linking. +# +# Created by carsten@arsdigita.com in June 2000 +# +# $Id: km-links-procs.tcl,v 1.1 2003/07/02 12:19:41 peterm Exp $ + +proc_doc km_linked_object_types { object_type_id } { + + Returns an array in the form: object_type_id, pretty_type, pretty_plural, graphic + for all object_types that are linkable with this object_type. + +} { + # Only object_types that have been listed for a question in + # sn_questions are considered to be linkable with this + # object_type. + + set context_id [ad_conn package_id] + + set result [db_list_of_lists km_linked_object_types " + select ot.object_type_id, ot.pretty_name, ot.pretty_plural, ot.graphic + from sn_questions q, sn_question_object_type_map qm, sn_object_types ot + where q.question_id = qm.question_id + and qm.object_type_id = :object_type_id + and qm.question_state <> 'invisible' + and ot.object_type_id = :object_type_id + and context_id=:context_id + and q.abstract_data_type = 'object_link'"] + + return $result +} + +ad_proc km_get_linked_objects { + { + -question_id 0 + -to_p 0 + -from_p 0 + -reference_links_p 1 + -family_members_p 1 + -only_unarchived_p 0 + } + user_id object_id +} { + + Returns objects linked to this object as specified in the + parameters. Note that this function does not enforce + access control rules, but only returns two colunms named + view_p and edit_p. + +} { + if { !$to_p && !$from_p } { return {} } + + set admin_p [km_conn admin_p] + set package_id [ad_conn package_id] + set instance_read_p [ad_permission_p $package_id "read"] + + set join_tables { + "sn_links l" + "sn_objects obj1" + "sn_objects obj2" + "users u" + "sn_object_types ot" + "sn_question_object_type_map qotm" + "sn_question_link_map qlm" + } + + set order_by "order by linked_object_type, question_id, name" + + set parent_link_type parent_child + + set join_tables_from {} + lappend where_from \ + "obj1.object_id = l.object_id_a " \ + "l.object_id_b = obj2.object_id " \ + "obj2.original_author_id = u.user_id" \ + "obj1.object_id = :object_id " \ + "obj2.expiration_date > sysdate" \ + "qotm.object_type_id = obj1.object_type_id" \ + "qotm.question_id = qlm.question_id" \ + "l.link_id = qlm.link_id" \ + "qotm.question_state <> 'invisible'" \ + "ot.object_type_id = obj2.object_type_id" \ + "ot.deleted_p = 'f'" + + if !$admin_p { lappend where_from "ot.public_p = 't'" } + + if !$instance_read_p { + lappend where_from \ + "(obj2.public_p = 't' or obj2.object_id in ( + select object_id from acs_permissions + where (grantee_id = :user_id + or grantee_id in (select group_id from membership_rels + where person_id = :user_id)) + and privilege = 'read'))" + } + + lappend where_to \ + "obj1.object_id = l.object_id_a " \ + "l.object_id_b = obj2.object_id " \ + "obj1.original_author_id = u.user_id" \ + "obj2.object_id = :object_id " \ + "obj1.expiration_date > sysdate" \ + "qotm.object_type_id = obj1.object_type_id" \ + "qotm.question_id = qlm.question_id" \ + "l.link_id = qlm.link_id" \ + "qotm.question_state <> 'invisible'" \ + "ot.object_type_id = obj1.object_type_id" \ + "ot.deleted_p = 'f'" + + if !$family_members_p { + lappend where_to "l.link_type not in ('uncle_nephew','parent_child')" + lappend where_from "l.link_type not in ('uncle_nephew','parent_child')" + } + + if { $only_unarchived_p } { + lappend where_to "obj1.archived_p = 'f'" + lappend where_from "obj2.archived_p = 'f'" + } + + if !$admin_p { lappend where_to "ot.public_p = 't'" } + + if !$instance_read_p { + lappend where_to \ + "(obj1.public_p = 't' or obj1.object_id in ( + select object_id from acs_permissions + where (grantee_id = :user_id + or grantee_id in (select group_id from membership_rels + where person_id = :user_id)) + and privilege = 'read'))" + } + + if { $question_id } { + lappend where_from "qlm.question_id = :question_id" + lappend where_to "qlm.question_id = :question_id" + } + + if { $reference_links_p == 0 } { + # We were told to exclude links which may already have been + # displayed as answers in the target object. + + lappend where_to { + qlm.question_id not in + (select references_question_id + from sn_questions + where references_question_id is not null and question_id in + (select question_id from sn_question_object_type_map + where object_type_id = obj2.object_type_id)) + } + } + + set links_from " + select l.link_id, l.link_comment, decode(html_p,'t',1,0) as comment_html_p, + obj2.object_id linked_object_id, obj2.object_type_id linked_object_type, + qlm.question_id, obj2.one_line_description name, obj2.last_modified, + km_utilities.strip_html_and_limit_size(obj2.overview) as overview, + decode(obj2.public_p,'t',1,0) as public_p, u.user_id as owner_id, + u.first_names || ' ' || u.last_name as owner_name, + 1 as view_p, decode(obj2.archived_p,'t',1,0) as archived_p, + decode(obj2.in_review_p,'t',1,0) as review_p, + decode(acs_permission.permission_p(obj2.object_id, :user_id, 'write'),'t',1,0) as edit_p, + 1 as from_p + from [join [concat $join_tables $join_tables_from] ","] + where [join $where_from " and "]" + + set links_to " + select l.link_id, l.link_comment, decode(html_p,'t',1,0) as comment_html_p, + obj1.object_id linked_object_id, obj1.object_type_id linked_object_type, + qlm.question_id, obj1.one_line_description name, obj1.last_modified, + km_utilities.strip_html_and_limit_size(obj1.overview) as overview, + decode(obj1.public_p,'t',1,0) as public_p, u.user_id as owner_id, + u.first_names || ' ' || u.last_name as owner_name, + 1 as view_p, decode(obj1.archived_p,'t',1,0) as archived_p, + decode(obj1.in_review_p,'t',1,0) as review_p, + decode(acs_permission.permission_p(obj1.object_id, :user_id, 'write'),'t',1,0) as edit_p, + 0 as from_p + from [join $join_tables ","] + where [join $where_to " and "]" + + # Put the SQL together. + if { $from_p && $to_p } { + set sql "$links_from union $links_to $order_by" + } elseif { $from_p } { + set sql "$links_from $order_by" + } else { + set sql "$links_to $order_by" + } + + # strip html from overview + set result [km_db_to_named_list_list km_get_linked_objects_2 $sql] + + return $result +} + +proc_doc km8_get_to_links { {-only_unarchived_p 0} object_id question_id } { + +} { + set current_user_id [ad_conn user_id] + set result [db_list_of_lists km8_get_to_links { + select * from ( + select object_id_b, aodesc.shortname, aodesc.overview, + aodesc.overview_html_p, l.link_id, object_id_a, ao.object_type, + aodesc.presentation, acs_permission.permission_p(l.object_id_b, :current_user_id, 'sw_read') sw_read_p, + (select decode(count(*),0,'f','t') + from membership_rels mr_lm + where mr_lm.person_id = l.object_id_b + and sn_group.group_list_members_p(mr_lm.group_id, :current_user_id) > 0 ) as user_list_p, + l.link_comment, decode(l.html_p,'t',1,0) as comment_html_p + from sn_links l, sn_question_link_map map, acs_objects_description aodesc, + acs_objects ao + where l.object_id_a = :object_id + and aodesc.object_id = ao.object_id + and aodesc.object_id = l.object_id_b + and aodesc.state <> 'd' + and (:only_unarchived_p = 0 or ao.object_type <> 'sn_object' or aodesc.state <> 'a') + and map.question_id = :question_id + and l.link_id = map.link_id + order by shortname + ) where sw_read_p='t' or user_list_p='t'}] + return $result +} + +ad_proc km_get_linked_names { object_id question_id } { + Returns the names of users, objects or ACS content linked from this object and question. +} { + set context_id [ad_conn package_id] + + set result [db_list_of_lists km_get_linked_names " + select obj1.one_line_description + from sn_links l, sn_objects obj1, sn_objects obj2, sn_question_link_map map + where l.object_id_a = obj2.object_id + and l.object_id_b = obj1.object_id + and map.question_id = :question_id + and l.link_id = map.link_id + and obj2.object_id = :object_id + and obj1.context_id = :context_id + and obj2.context_id = :context_id + order by one_line_description"] + + return [map fst $result] +} + +proc_doc sn_people_responsible {user_id object_id} { + + Returns a list of triples:user_id, full name, email of people + responsible for this xchange_task project. + +} { + set package_id [ad_conn package_id] + set contact_person_p [db_0or1row get_contact_person_question { + select q.question_id + from sn_objects o, sn_questions q, sn_question_object_type_map qm + where q.question_id = qm.question_id + and qm.question_state = 'active' + and qm.object_type_id = o.object_type_id + and o.object_id = :object_id + and o.context_id = :package_id + and q.pretty_name = 'Contact Person' + }] + + set result "" + if {$contact_person_p} { + db_0or1row get_contact_person { + select content as result + from sn_content + where object_id = :object_id + and question_id = :question_id + } + } + if [empty_string_p $result] { + db_1row get_author_email { + select u.first_names || ' ' || u.last_name author_name, u.email author_email + from users u, sn_objects o + where u.user_id = o.original_author_id + and o.object_id = :object_id + } + set result "$author_name <$author_email>" + } + + return $result +} + +ad_proc km_get_parent { object_id } { + Returns the parent of an object +} { + if { [db_0or1row km_get_parent { + select obj.object_id as parent_id, obj.one_line_description as parent_name, obj.object_type_id + from sn_objects obj, km_flat_object_hierarchy fo + where fo.child = :object_id + and obj.object_id = fo.parent + and fo.link_type = 'parent_child' + and fo.distance = 1 }] } { + + if {[empty_string_p $parent_name]} { + set parent_name "Unnamed [km_static object_type_pretty_name $object_type_id]" + } + return [list $parent_id $parent_name $object_type_id] + } else { + return + } +} + +ad_proc km_get_uncle { object_id } { + Returns the uncle of an object +} { + if { [db_0or1row km_get_uncle { + select obj.object_id as uncle_id, obj.one_line_description as uncle_name, obj.object_type_id + from sn_objects obj, km_flat_object_hierarchy fo + where fo.child = :object_id + and obj.object_id = fo.parent + and fo.link_type = 'uncle_nephew' + and fo.distance = 1 }] } { + + if {[empty_string_p $uncle_name]} { + set uncle_name "Unnamed [km_static object_type_pretty_name $object_type_id]" + } + return [list $uncle_id $uncle_name $object_type_id] + } else { + return + } +} + +ad_proc km_is_nephew_p { object_id } { + Checks if this object is linked as a nephew to an uncle +} { + set result [db_string km_is_nephew_p { + select count(*) + from km_flat_object_hierarchy + where child = :object_id + and link_type = 'uncle_nephew' + and distance = 1 + }] + return $result +} + +ad_proc km_is_uncle_p { object_id } { + Checks if this object is linked as a uncle to an object +} { + set result [db_string km_is_uncle_p { + select count(*) + from km_flat_object_hierarchy foh, sn_objects o + where foh.parent = :object_id + and foh.link_type = 'uncle_nephew' + and foh.distance = 1 + and foh.child = o.object_id + and o.expiration_date > sysdate + }] + return $result +} + +ad_proc km_is_parent_p { object_id } { + Checks if this object is linked as a parent to an object +} { + set result [db_string km_is_parent_p { + select count(*) + from km_flat_object_hierarchy foh, sn_objects o + where foh.parent = :object_id + and foh.link_type = 'parent_child' + and foh.distance = 1 + and foh.child = o.object_id + and o.expiration_date > sysdate + }] + return $result +} + +ad_proc km_is_child_p { object_id } { + Checks if this object is linked as a child to a parent +} { + set result [db_string km_is_child_p { + select count(*) + from km_flat_object_hierarchy + where child = :object_id + and link_type = 'parent_child' + and distance = 1 + }] + return $result +} + +ad_proc km_is_descendant_p { object_id } { + Checks if this object is linked as a child/nephew to a parent/uncle +} { + set result [db_string km_is_child_p { + select count(*) + from km_flat_object_hierarchy + where child = :object_id + and distance = 1 + }] + return $result +} + +ad_proc km_is_mandatory_nephew_p { object_id } { + Checks if this object is linked as a nephew to an uncle via a mandatory question +} { + set result [db_string km_is_mandatory_nephew_p { + select count(*) + from sn_links l, sn_question_link_map map, sn_question_object_type_map qm + where l.object_id_b = :object_id + and l.link_type = 'uncle_nephew' + and l.link_id = map.link_id + and map.question_id = qm.question_id + and qm.question_state = 'active' + and qm.mandatory_p = 't' + }] + return $result +} + +ad_proc km_is_mandatory_uncle_p { object_id } { + Checks if this object is linked as a uncle to an object via a mandatory question +} { + set result [db_string km_is_mandatory_uncle_p { + select count(*) + from sn_links l, sn_question_link_map map, + sn_question_object_type_map qm, sn_objects o + where l.object_id_a = :object_id + and l.object_id_b = o.object_id + and o.expiration_date > sysdate + and l.link_type = 'uncle_nephew' + and l.link_id = map.link_id + and map.question_id = qm.question_id + and qm.question_state = 'active' + and qm.mandatory_p = 't' + }] + return $result +} + +ad_proc km_is_nephew_with_private_uncle_p { object_id {public_p "f"} } { + Checks if this object is linked as a nephew to an uncle +} { + set result [db_string km_is_nephew_with_private_uncle_p { + select count(*) + from km_flat_object_hierarchy ko, sn_objects o + where ko.child = :object_id + and ko.parent = o.object_id + and ko.link_type = 'uncle_nephew' + and ko.distance = 1 + and o.public_p = :public_p + }] + return $result +} + +ad_proc km_is_child_with_private_parent_p { object_id {public_p "f"} } { + Checks if this object is linked as a child to a parent +} { + set result [db_string km_is_child_with_private_parent_p { + select count(*) + from km_flat_object_hierarchy ko, sn_objects o + where ko.child = :object_id + and ko.parent = o.object_id + and ko.link_type = 'parent_child' + and ko.distance = 1 + and o.public_p = :public_p + }] + return $result +} + +ad_proc km_private_ancestor_p { object_id {public_p "f"} } { + Checks if this object is linked as a child or nephew to a private ancestor. +} { + set result [db_string km_private_ancestor_p { + select count(*) + from km_flat_object_hierarchy ko, sn_objects o + where ko.child = :object_id + and ko.parent = o.object_id + and ko.distance = 1 + and o.public_p = :public_p + }] + return $result +} + +ad_proc km_archived_ancestor_p { object_id {archived_p "t"} } { + Checks if this object is linked as a child or nephew to an archived ancestor. +} { + set result [db_string km_archived_ancestor_p { + select count(*) + from km_flat_object_hierarchy ko, sn_objects o + where ko.child = :object_id + and ko.parent = o.object_id + and ko.distance = 1 + and o.archived_p = :archived_p + }] + return $result +} + +ad_proc km_check_public_status_after_edit { object_id } { + Checks the public status of the object, it's descendants and it's uncle after + editing the object. +} { + set nephew_p [km_is_mandatory_nephew_p $object_id] + set complete_p [km_object_complete_p $object_id] + db_1row km_check_public_status_after_edit_10 { + select public_p, archived_p + from sn_objects where + object_id = :object_id + } + if { $complete_p && $public_p == "f" } { + if {[km_private_ancestor_p $object_id "t"]} { + # if object is uncle then publish it and all nephews - user can later + # unpublish some nephews + km_object_publish [concat $object_id [map fst [km_get_descendents $object_id]]] + } + } + if { !$complete_p && $public_p == "t" } { + km_object_unpublish $object_id + if {$nephew_p} { + set uncle_id [km_get_uncle $object_id] + if {[km_uncle_needs_private_status_p $uncle_id]} { + km_object_unpublish $uncle_id + } + } + } +} + +ad_proc km_object_publish { object_list } { + Publishes an object and all its selected descendants +} { + set user_id [ad_conn user_id] + + foreach child_id $object_list { + if [km_object_complete_p $child_id] { + lappend object_list $child_id + } + } + set object_sql [join $object_list ","] + + db_transaction { + db_exec_plsql km_object_publish_10 " + declare + v_the_public acs_objects.object_id%TYPE; + begin + select acs.magic_object_id('the_public') into v_the_public from dual; + for v_objects in (select object_id from sn_objects where object_id in ($object_sql)) + loop + acs_permission.grant_permission(v_objects.object_id, v_the_public, 'read'); + insert into sn_audit_table + (object_id, question_id, last_modified, last_modifying_user_id, content) + values + (v_objects.object_id, null, sysdate, :user_id, 'Object Published'); + end loop; + end; + " + + db_dml km_object_publish_20 " + update sn_objects + set user_checkoff_date = sysdate, public_p = 't', in_review_p = 'f' + where object_id in ($object_sql)" + + } +} + +ad_proc km_object_unpublish { object_id } { + Unpublishes an object and all its descendants +} { + if {[ad_conn -connected_p]} { + set user_id [ad_conn user_id] + } else { + set user_id [db_null] + } + + db_transaction { + db_exec_plsql km_object_unpublish_10 { + declare + v_the_public acs_objects.object_id%TYPE; + begin + select acs.magic_object_id('the_public') into v_the_public from dual; + for v_objects in (select object_id from sn_objects + where object_id = :object_id + or object_id in (select o.object_id + from km_flat_object_hierarchy foh, sn_objects o + where foh.parent = :object_id + and foh.child = o.object_id + and o.public_p = 't') ) + loop + acs_permission.revoke_permission(v_objects.object_id, v_the_public, 'read'); + insert into sn_audit_table + (object_id, question_id, last_modified, last_modifying_user_id, content) + values + (v_objects.object_id, null, sysdate, :user_id, 'Set to Private'); + end loop; + end; + } + + db_dml km_object_unpublish_20 { + update sn_objects + set user_checkoff_date = null, public_p = 'f' + where object_id = :object_id + or object_id in (select o.object_id + from km_flat_object_hierarchy foh, sn_objects o + where foh.parent = :object_id + and foh.child = o.object_id + and o.public_p = 't') + } + } +} + +ad_proc km_object_archive { object_id reason } { + archives an object and all its descendants +} { + set reason "Archived: [ad_quotehtml $reason]" + if {[ad_conn -connected_p]} { + set user_id [ad_conn user_id] + } else { + set user_id [db_null] + } + + db_transaction { + set object_list [db_list get_archivable_objects { + ( select o.object_id + from km_flat_object_hierarchy foh, sn_objects o, sn_object_types ot + where foh.parent = :object_id + and foh.child = o.object_id + and o.archived_p = 'f' + and o.object_type_id = ot.object_type_id + and ot.archive_p = 't' ) + minus + ( select child as object_id + from km_flat_object_hierarchy + where parent in (select o.object_id + from km_flat_object_hierarchy foh, sn_objects o, + sn_object_types ot + where foh.parent = :object_id + and foh.child = o.object_id + and o.archived_p = 'f' + and o.object_type_id = ot.object_type_id + and ot.archive_p = 'f') ) + }] + set object_sql [join [concat $object_id $object_list] ","] + + db_dml km_object_archive_10 " + insert into sn_audit_table ( + select o.object_id, null as question_id, sysdate as last_modified, + :user_id as last_modifying_user_id, :reason as content + from sn_objects o + where o.object_id in ($object_sql) + ) + " + + db_dml km_object_archive_20 " + update sn_objects + set archiving_date = sysdate, + archived_p = 't' + where object_id in ($object_sql) + " + } +} + +ad_proc km_object_unarchive { object_id object_id_list } { + Unarchives an object and all selected descendants (-> private) +} { + set user_id [ad_conn user_id] + lappend object_id_list $object_id + set object_sql [join $object_id_list ","] + + db_transaction { + ## revoke public permissions from all objects + descendants + db_exec_plsql km_object_unarchive_10 { + declare + v_the_public acs_objects.object_id%TYPE; + begin + select acs.magic_object_id('the_public') into v_the_public from dual; + for v_objects in (select object_id from sn_objects + where object_id = :object_id + or object_id in (select o.object_id + from km_flat_object_hierarchy foh, sn_objects o + where foh.parent = :object_id + and foh.child = o.object_id + and o.public_p = 't') ) + loop + acs_permission.revoke_permission(v_objects.object_id, v_the_public, 'read'); + end loop; + end; + } + + ## make a note in the audit table that objects got unarchived + db_dml km_object_unarchive_20 " + insert into sn_audit_table ( + select o.object_id, null as question_id, sysdate as last_modified, + :user_id as last_modifying_user_id, 'Unarchived, set to Private' as content + from sn_objects o + where object_id in ($object_sql) + ) + " + + ## remove objects from archive and make private + db_dml km_object_unarchive_30 " + update sn_objects + set archiving_date = null, + user_checkoff_date = null, + public_p = 'f', + archived_p = 'f' + where object_id in ($object_sql) + " + + ## make a note in the audit table that all other descendants + ## got private + db_dml km_object_unarchive_40 " + insert into sn_audit_table ( + select o.object_id, null as question_id, sysdate as last_modified, + :user_id as last_modifying_user_id, 'Set to Private' as content + from km_flat_object_hierarchy foh, sn_objects o + where foh.parent = :object_id + and foh.child = o.object_id + and o.public_p = 't' + ) + " + + ## make all other desendants private + db_dml km_object_unarchive_50 " + update sn_objects + set user_checkoff_date = null, + public_p = 'f' + where object_id in (select o.object_id + from km_flat_object_hierarchy foh, sn_objects o + where foh.parent = :object_id + and foh.child = o.object_id + and o.public_p = 't') + " + } +} + +proc_doc km_get_object_ancestors { object_id } { + + Returns a list of ids of the parent of this object, the parent of + the parent of this object, etc. Will do this for normal links if + the link type_id is set to the one for bidirectional links. + +} { + set result [db_list_of_lists km_get_object_ancestors " + select obj.object_id, obj.one_line_description, obj.object_type_id + from sn_objects obj, km_flat_object_hierarchy fo + where fo.child = :object_id + and obj.object_id = fo.parent + order by distance"] + + return $result +} + +proc_doc km_get_descendents { object_id } { + Almost identical to the ancestor proc. +} { + set result [db_list_of_lists km_get_descendents " + select obj.object_id, obj.one_line_description + from sn_objects obj, km_flat_object_hierarchy fo + where fo.parent = :object_id + and obj.object_id = fo.child + and obj.expiration_date > sysdate + order by distance"] + + return $result +} + +ad_proc km_get_child_descendents { object_id } { + Returns only children and grandchildren. +} { + set result [db_list km_get_child_descendents { + select fo.child + from km_flat_object_hierarchy fo, sn_objects o + where fo.parent = :object_id + and fo.link_type = 'parent_child' + and o.object_id = fo.child + and o.expiration_date > sysdate + order by distance }] + + return $result +} + +ad_proc km_get_objects_descendents { object_list } { + Returns descendents of a list of objects. +} { + set result [db_list km_get_objects_descendents " + select fo.child + from km_flat_object_hierarchy fo, sn_objects o + where fo.parent in ([join $object_list ","]) + and o.object_id = fo.child + and o.expiration_date > sysdate + order by distance"] + + return $result +} + +ad_proc km_get_presentation_type_of_nephew_question { object_id } { + Returns the presentation_type of the uncle's nephew question under + which this object is linked +} { + set result [db_string km_get_presentation_type_of_nephew_question_10 { + select q.presentation_type + from sn_questions q, sn_question_link_map map, sn_links l + where q.abstract_data_type = 'nephew_object' + and q.question_id = map.question_id + and l.link_id = map.link_id + and l.link_type = 'uncle_nephew' + and l.object_id_b = :object_id + } -default "custom"] + + return $result +} + +proc_doc km_get_child_objects { + {-only_unarchived_p 0} object_id question_id +} { + Returns an array containing the object_ids of the child objects + associated with this object_id and question_id. + +} { + set order_by [db_string order_by { + select nvl(order_by,'name') + from sn_questions + where question_id = :question_id}] + + # We select more columns than we need because of sorting. + return [map fst [db_list child_objects { + select obj2.object_id, obj2.one_line_description as name, obj2.last_modified, l.link_id + from sn_objects obj1,sn_objects obj2, sn_links l, sn_question_link_map map + where l.object_id_b = obj2.object_id + and l.object_id_a = obj1.object_id + and map.question_id = :question_id + and l.link_id = map.link_id + and l.link_type = 'parent_child' + and obj1.object_id = :object_id + and obj2.expiration_date > sysdate + and obj2.archived_p <> decode(:only_unarchived_p,'0','a','t') + order by :order_by}]] +} + +proc_doc km_get_nephew_objects { + {-only_unarchived_p 0} object_id question_id +} { + Returns an array containing the object_ids of the nephew objects + associated with this object_id and question_id. + +} { + set user_id [ad_conn user_id] + set order_by [db_string order_by { + select nvl(order_by,'name') + from sn_questions + where question_id = :question_id}] + + # We select more columns than we need because of sorting. + return [map fst [db_list nephew_objects { + select obj2.object_id, obj2.one_line_description as name, obj2.last_modified, l.link_id + from sn_objects obj1,sn_objects obj2, sn_links l, sn_question_link_map map + where l.object_id_b = obj2.object_id + and l.object_id_a = obj1.object_id + and map.question_id = :question_id + and l.link_id = map.link_id + and l.link_type = 'uncle_nephew' + and obj1.object_id = :object_id + and obj2.expiration_date > sysdate + and obj2.archived_p <> decode(:only_unarchived_p,'0','a','t') + and acs_permission.permission_p (obj2.object_id, :user_id, 'read') = 't' + order by :order_by}]] +} + +ad_proc km_get_nephew_count { object_id } { + Returns the total number of nephew objects for a particular object. +} { + set result [db_string km_get_nephew_count { + select count(*) + from sn_links l, sn_objects o + where l.link_type = 'uncle_nephew' + and l.object_id_a = :object_id + and l.object_id_b = o.object_id + and o.expiration_date > sysdate + } + return $result +} + +ad_proc km_uncle_needs_private_status_p { object_id {nephew_id ""} } { + Checks if uncle need to be private after making a nephew private +} { + set context_id [ad_conn package_id] + if {[empty_string_p $nephew_id]} { + set nephew_questions_without_public_nephews [db_string km_uncle_needs_private_status_p_10 { + select count(*) + from sn_questions q, sn_question_object_type_map qm, sn_objects o + where q.question_id = qm.question_id + and qm.question_state = 'active' + and qm.mandatory_p = 't' + and qm.object_type_id = o.object_type_id + and o.object_id = :object_id + and o.context_id=:context_id + and q.abstract_data_type = 'nephew_object' + and not exists (select nephew.object_id + from sn_objects nephew, sn_question_link_map map, sn_links l + where l.object_id_a = :object_id + and l.object_id_b = nephew.object_id + and l.link_type = 'uncle_nephew' + and l.link_id = map.link_id + and map.question_id = q.question_id + and nephew.expiration_date > sysdate + and nephew.archived_p = o.archived_p + and nephew.public_p = 't') + }] + } else { + set nephew_questions_without_public_nephews [db_string km_uncle_needs_private_status_p_20 { + select count(*) + from sn_questions q, sn_question_object_type_map qm, sn_objects o + where q.question_id = qm.question_id + and qm.question_state = 'active' + and qm.mandatory_p = 't' + and qm.object_type_id = o.object_type_id + and o.object_id = :object_id + and o.context_id=:context_id + and q.abstract_data_type = 'nephew_object' + and not exists (select nephew.object_id + from sn_objects nephew, sn_question_link_map map, sn_links l + where l.object_id_a = :object_id + and l.object_id_b = nephew.object_id + and l.link_type = 'uncle_nephew' + and l.link_id = map.link_id + and map.question_id = q.question_id + and nephew.expiration_date > sysdate + and nephew.public_p = 't' + and nephew.archived_p = o.archived_p + and nephew.object_id <> :nephew_id) + }] + } + return $nephew_questions_without_public_nephews +} + +proc_doc km_link_question_attributes { question_id } { + Returns the object_type_attributes for this object_link question. +} { + set context_id [ad_conn package_id] + set sql "select ot.object_type_id, ot.pretty_name, ot.pretty_plural, ot.graphic + from sn_questions q, sn_object_types ot + where q.target_object_type_id = ot.object_type_id + and q.question_id = :question_id" + set result [km_db_1row_to_list km_link_question_attributes $sql] + return $result +} + +ad_proc km_link_objects { + { + -link_type "" + } + question_id user_id object_id_a object_id_b link_comment html_p +} { + Creates a new link between two objects. +} { + if [empty_string_p $link_type] { + set link_type bi_directional + } + + if {[string equal $link_type "parent_child"] || [string equal $link_type "uncle_nephew"]} { + if {[db_string check_parent_or_uncle " + select count(*) from sn_links + where object_id_b = :object_id_b + and link_type in ('parent_child','uncle_nephew')"] > 0} { + return 0 + } + } + + set new_link_id [db_string km_link_objects_10 "select sn_links_seq.nextval from dual"] + + db_dml km_link_objects_20 {insert into sn_links (link_id, link_type, object_id_a, + object_id_b, link_comment, html_p, creation_user, creation_date) + values (:new_link_id, :link_type, :object_id_a, + :object_id_b, :link_comment, :html_p, :user_id, sysdate)} + + if { ![db_0or1row km_link_objects_25 { + select nvl(one_line_description,'Unnamed ' || pretty_name) as target_name, pretty_name as target_type + from sn_objects o, sn_object_types ot + where o.object_id = :object_id_b + and o.object_type_id = ot.object_type_id}] + } { + db_1row km_link_objects_26 { + select + shortname as target_type, + overview as target_name + from + acs_objects_description + where + object_id = :object_id_b + } + } + + set content "Added link to $target_type \"$target_name\" $link_comment" + set ip_address [ns_conn peeraddr] + + db_exec_plsql km_link_objects_30 { + begin + object.audit_object ( + v_object_id => :object_id_a, + v_question_id => :question_id, + v_last_modifying_user_id => :user_id, + v_modifying_ip => :ip_address, + v_content => :content + ); + end; + } + + db_dml km_link_objects_40 {insert into sn_question_link_map (link_id, question_id) + values (:new_link_id, :question_id)} + + set sql_fragment "[km_link_description_update $object_id_a $question_id]" + if {![empty_string_p $sql_fragment]} { + db_dml km_link_objects_50 " + update sn_objects + set $sql_fragment + where object_id = :object_id_a" + } + return 1 +} + +ad_proc km_link_description_update { object_id question_id } { + + Returns a SQL fragment for updating the short or long description + of an object, if the given question is set as the object type's + description. Works for all linking questions. + +} { + db_1row km_link_description_update " + select long_description + from sn_object_types + where object_type_id = (select object_type_id from sn_objects + where object_id=:object_id)" + + set short_desc_list [db_list_of_lists question_info_short_desc { + select map.short_description + from sn_types_map_short_name map + where map.object_type_id = (select object_type_id from sn_objects + where object_id=:object_id) + order by position + }] + + set result "" + if { [lsearch $short_desc_list $question_id] != -1 || $question_id == $long_description } { + set QQlinked_names [util_trim_string_with_hrefs [DoubleApos [join [km_get_linked_names $object_id $question_id] ", "]] 2000] + + if { $question_id == $long_description } { + set result "overview = '$QQlinked_names', overview_html_p = 'f'" + } else { + set result "one_line_description = '$QQlinked_names'" + } + } + + return $result +} + +namespace eval sn_links::objects::sn_object { + ad_proc -public restrict {source_id target_id target_presentation pass} { + + Limit knowledge object types in linking service. + + } { + + if { [regexp {exclude ([0-9 ]+)} $pass match exclude_ids] } { + if { [lsearch $exclude_ids $target_id] != -1 } { + return 0 + } + } + + if {![regexp {restriction(\d*)} $pass match restrict_to_object_type_id]} { + # The restriction is not required, so show all objects. + return 1 + } else { + if {![regexp {object_type_id=(\d*)} $target_presentation match object_type_id]} { + # Bug in the database, the presentation column is wrong. + ns_log Notice "Presentation is wrong for object_id $target_id." + return 1 + } else { + if {$object_type_id == $restrict_to_object_type_id} { + return 1 + } + return 0 + } + } + } +} Index: openacs-4/contrib/obsolete-packages/library/tcl/km-object-data-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/tcl/km-object-data-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/tcl/km-object-data-procs.tcl 2 Jul 2003 12:19:41 -0000 1.1 @@ -0,0 +1,933 @@ +# /tcl/km-object-data.tcl +# +# $Id: km-object-data-procs.tcl,v 1.1 2003/07/02 12:19:41 peterm Exp $ + +util_report_library_entry + +# ********** Procs that get data from an object ********** + +proc_doc km_object_exists_p {object_id} "Returns 1 if this object exists in the library" { + if [empty_string_p [km_get_object_type $object_id]] { + return 0 + } else { + return 1 + } +} + +ad_proc km_get_object_type { object_id } "Returns the object type for any given object." { + set this_object_type [db_string km_get_object_type " + select object_type_id + from sn_objects + where object_id=:object_id" -default ""] + + return $this_object_type +} + +ad_proc km_object_nephews_p { object_id } { + Returns 1 if the object has a uncle-nephew question and some nephews. +} { + set context_id [ad_conn package_id] + set nephew_questions_without_nephews [db_string km_object_nephews_p { + select count(*) + from sn_questions q, sn_question_object_type_map qm, sn_objects o + where q.question_id = qm.question_id + and qm.question_state = 'active' + and qm.mandatory_p = 't' + and qm.object_type_id = o.object_type_id + and o.object_id = :object_id + and o.context_id=:context_id + and q.abstract_data_type = 'nephew_object' + and not exists (select nephew.object_id + from sn_objects nephew, sn_question_link_map map, sn_links l + where l.object_id_a = :object_id + and l.object_id_b = nephew.object_id + and l.link_type = 'uncle_nephew' + and l.link_id = map.link_id + and map.question_id = q.question_id + and nephew.expiration_date > sysdate) + }] + if {$nephew_questions_without_nephews > 0} { + return 0 + } else { + return 1 + } +} + +ad_proc km_valid_nephew_publish_list_p { object_id nephew_list } { + Returns 1 if for every uncle-nephew question of the object there is at least one + nephew object in the list to be published. +} { + set context_id [ad_conn package_id] + set nephew_questions_without_nephews [db_string km_valid_nephew_publish_list_p " + select count(*) + from sn_questions q, sn_question_object_type_map qm, sn_objects o + where q.question_id = qm.question_id + and qm.question_state = 'active' + and qm.mandatory_p = 't' + and qm.object_type_id = o.object_type_id + and o.object_id = :object_id + and o.context_id=:context_id + and q.abstract_data_type = 'nephew_object' + and not exists (select nephew.object_id + from sn_objects nephew, sn_question_link_map map, sn_links l + where l.object_id_a = :object_id + and l.object_id_b = nephew.object_id + and l.link_type = 'uncle_nephew' + and l.link_id = map.link_id + and map.question_id = q.question_id + and nephew.expiration_date > sysdate + and nephew.object_id in ([join $nephew_list ","])) + "] + if {$nephew_questions_without_nephews > 0} { + return 0 + } else { + foreach nephew_id $nephew_list { + if {![km_object_complete_p $nephew_id]} { + return 0 + } + } + return 1 + } +} + +ad_proc km_uncle_nephew_questions { object_id } { + Returns a list of all questions of the object (question_ids) that are of uncle-nephew type +} { + set context_id [ad_conn package_id] + set nephew_question_list [db_list_of_lists km_uncle_nephew_questions { + select q.question_id, q.pretty_name + from sn_objects o, sn_questions q, sn_question_object_type_map qm + where q.question_id = qm.question_id + and qm.question_state = 'active' + and qm.mandatory_p = 't' + and qm.object_type_id = o.object_type_id + and o.object_id = :object_id + and o.context_id = :context_id + and q.abstract_data_type = 'nephew_object' + }] + return $nephew_question_list +} + +ad_proc km_publishable_nephews { object_id question_id } { + Returns the list of all publishable nephews for the object and question +} { + set archived_p [db_string get_archived_status {select archived_p from sn_objects where object_id = :object_id}] + set nephew_list [db_list_of_lists km_publishable_nephews { + select nephew.object_id, nephew.one_line_description, nephew.in_review_p + from sn_objects nephew, sn_links l, sn_question_link_map map + where l.object_id_a = :object_id + and l.object_id_b = nephew.object_id + and l.link_type = 'uncle_nephew' + and l.link_id = map.link_id + and map.question_id = :question_id + and nephew.archived_p = :archived_p + and nephew.expiration_date > sysdate + }] + set result [list] + foreach nephew $nephew_list { + if {[km_object_complete_p [fst $nephew]]} { + lappend result $nephew + } + } + return $result +} + +ad_proc km_object_complete_p { object_id } { + Returns 1 if the object is complete, 0 if not. +} { + set required_questions [km_question_attributes [km_required_questions $object_id]] + db_1row get_object_type_id { + select object_type_id, decode(archived_p,'t',0,1) as unarchived_p + from sn_objects + where object_id = :object_id + } + if ![null_p $required_questions] { + set questions {{question_id pretty_name abstract_data_type}} + set questions [concat {{question_id pretty_name abstract_data_type}} $required_questions] + set object_data [km_get_object_data -questions $questions -answers_only_p 0 -only_unarchived_p $unarchived_p $object_id] + } else { + return 1 + } + foreach item $object_data { + set value [fst $item] + set abstract_data_type [lindex $item 3] + set answered_p [km_answered_p $abstract_data_type $value] + if !$answered_p { + set question_id [snd $item] + if {[km_active_path_p $question_id $object_id $object_type_id]} { + return 0 + } + } + } + return 1 +} + +ad_proc km_get_object_summary { object_id } { + Returns a tuple of object_id, public_p, archived_p, review_p, short_description, long_description of an object +} { + set result [km_db_1row_to_list km_get_object_summary " + select object_id, public_p, archived_p, in_review_p as review_p, one_line_description, overview + from sn_objects + where object_id=:object_id"] + + return $result +} + +ad_proc km_get_object_name { object_id } { + Returns the name or short_description of an object. +} { + db_1row get_object_name { + select one_line_description as object_name, object_type_id + from sn_objects + where object_id = :object_id + } + + if [empty_string_p $object_name] { + return "Unnamed [km_static object_type_pretty_name $object_type_id]" + } else { + return $object_name + } +} + +ad_proc km_get_object_data { + { + -answers_only_p 1 + -questions {} + -show_values_p 1 + -only_unarchived_p 0 + } + object_id +} { + + Retrieves the data mapped to the given questions (as returned by + km_get_questions) and returns it as a list of lists in the form: + answer question_id pretty_question abstract_data_type branch_p + or as just the answers if answers_only_p is set. + +} { + set user_id [ad_conn user_id] + set archived_p [db_string get_archived_flag {select decode(archived_p,'t',1,0) from sn_objects where object_id = :object_id} -default 0] + + if [null_p $questions] { + # Retrieve all possible questions for this object + set question_states [list active deprecated read-only] + if { $archived_p } { + lappend question_states invisible + } + set questions [km_get_questions -question_states $question_states -root_node_p 1 -branch_children_p 1 -all_properties_p 1 -object_id $object_id] + + # Get all text answers for all questions. + # (So we don't have to query for each question.) + if { $show_values_p} { + set content_answers [km_get_object_content $object_id] + } else { + set content_answers "" + } + + # Do the same for all linking questions. + set linked_objects_from [km_get_linked_objects -from_p 1 -only_unarchived_p $only_unarchived_p $user_id $object_id] + set linked_objects_to [km_get_linked_objects -to_p 1 -only_unarchived_p $only_unarchived_p $user_id $object_id] + set link_question_id_ix [lsearch [head $linked_objects_from] "question_id"] + } else { + set question_ids [map fst [tail $questions]] + if { $show_values_p} { + set content_answers [km_get_object_content -question_ids $question_ids $object_id] + } else { + set content_answers "" + } + set linked_objects_to {} + set linked_objects_from {} + set link_question_id_ix -1 + } + + set key [fst $questions] + set questions [tail $questions] + + set answer_list {} + set question_id_ix [lsearch $key "question_id"] + set pretty_name_ix [lsearch $key "pretty_name"] + set abstract_data_type_ix [lsearch $key "abstract_data_type"] + set question_state_ix [lsearch $key "question_state"] + set branch_p_ix [lsearch $key "branch_p"] + set root_branch_p_ix [lsearch $key "root_branch_p"] + set references_question_id_ix [lsearch $key "references_question_id"] + + foreach question $questions { + set question_id [lindex $question $question_id_ix] + set pretty_name [lindex $question $pretty_name_ix] + set abstract_data_type [lindex $question $abstract_data_type_ix] + set references_question_id [lindex $question $references_question_id_ix] + set question_state [lindex $question $question_state_ix] + if { $branch_p_ix != -1 } { + set branch_p [lindex $question $branch_p_ix] + } else { + set branch_p "" + } + if { $root_branch_p_ix != -1 } { + set root_branch_p [lindex $question $root_branch_p_ix] + } else { + set root_branch_p "" + } + + # Collect the data on the basis of the abstract_data_type + switch $abstract_data_type { + "text" { + if { $show_values_p} { + set text_value [lindex [snd [transpose $content_answers]] [lsearch [fst [transpose $content_answers]] $question_id]] + set html_p [lindex [thd [transpose $content_answers]] [lsearch [fst [transpose $content_answers]] $question_id]] + set answer [list $text_value $html_p] + } else { + set text_value "" + set html_p "" + set answer "" + } + } + "integer" - + "date" - + "file" { + if { $show_values_p} { + set answer [lindex [snd [transpose $content_answers]] [lsearch [fst [transpose $content_answers]] $question_id]] + } else { + set answer "" + } + } + "object_link" { + if { $show_values_p} { + if { $link_question_id_ix == -1 } { + set answer [km_get_linked_objects -question_id $question_id -from_p 1 -only_unarchived_p $only_unarchived_p $user_id $object_id] + } else { + set answer [list [head $linked_objects_from]] + foreach linked_object [tail $linked_objects_from] { + set link_question_id [lindex $linked_object $link_question_id_ix] + if { $link_question_id == $question_id } { + lappend answer $linked_object + } + } + foreach linked_object [tail $linked_objects_to] { + set link_question_id [lindex $linked_object $link_question_id_ix] + if { $link_question_id == $references_question_id } { + lappend answer $linked_object + } + } + } + } else { + set answer "" + } + } + "composite" { + set child_ids [km_get_child_questions $question_id] + if ![null_p $child_ids] { + set child_questions [km_get_questions -question_states {active deprecated read-only} -root_node_p 0 -question_ids $child_ids] + set answer [km_get_object_data -questions $child_questions -answers_only_p 0 -only_unarchived_p $only_unarchived_p $object_id] + } else { + set answer {} + } + } + "category" { set answer [km_get_categories $object_id $question_id] } + "other_category" { set answer [km_get_categories $object_id $question_id] } + "option" { set answer [km_get_object_answers $object_id $question_id] } + "user_link" { set answer [km8_get_to_links $object_id $question_id] } + "content_link" { set answer [km8_get_to_links -only_unarchived_p $only_unarchived_p $object_id $question_id] } + "child_object" { + set answer "" + set child_ids [km_get_child_objects -only_unarchived_p $only_unarchived_p $object_id $question_id] + foreach child_id $child_ids { + lappend answer [km_get_object_summary $child_id] + } + } + "nephew_object" { + set answer "" + set nephew_ids [km_get_nephew_objects -only_unarchived_p $only_unarchived_p $object_id $question_id] + foreach nephew_id $nephew_ids { + lappend answer [km_get_object_summary $nephew_id] + } + } + default { set answer "" } + } + if { $answers_only_p } { + lappend answer_list $answer + } else { + lappend answer_list [list $answer $question_id $pretty_name $abstract_data_type $branch_p $root_branch_p] + } + } + return $answer_list +} + + +ad_proc km_get_object_content { { -question_ids {} } object_id } { + Returns all content about this object_id. +} { + set result {} + if ![null_p $question_ids] { + foreach question_id $question_ids { + if {[db_0or1row km_get_object_content_10 " + select content,decode(html_p,'t',1,0) as html_p from sn_content + where object_id=:object_id and question_id=:question_id"]} { + lappend result [list $question_id $content $html_p] + } + } + } else { + set sql "select question_id, content, + decode(html_p,'t',1,0) as html_p from sn_content + where object_id=:object_id" + db_foreach km_get_object_content_20 $sql { + lappend result [list $question_id $content $html_p] + } + } + + return $result +} + +proc_doc km_get_object_answers { object_id question_id } { + Returns the option_ids, pretty_names as tuples that answer this question for this object. +} { + set sql "select a.option_id, a.answer_option + from sn_answer_options a, sn_object_option_map m + where a.option_id =m.option_id + and m.object_id = :object_id + and a.question_id = :question_id" + set result [db_list_of_lists km_get_object_answers $sql] + return $result +} + +# ********** Saving data ********** + +proc_doc km_create_object { object_type_id user_id } { + + Creates a new knowledge object as a row in sn_objects. Note that the + object is first considered completed when all required questions + concerning the object have been answered. + +} { + set package_id [ad_conn package_id] + set user_id [ad_verify_and_get_user_id] + set creation_ip [ad_conn peeraddr] + + set new_object_id [db_exec_plsql create_object_10 { + begin + :1 := object.insert_object ( + v_object_type_id => :object_type_id, + v_creation_user => :user_id, + v_creation_ip => :creation_ip, + v_context_id => :package_id + ); + end; + }] + + return $new_object_id +} + + +proc_doc km_save_object_data { object_id user_id key_values } { + Takes object data in as a list of keys value tuples and saves it in the database + according to its abstract data type. +} { + if ![km_object_exists_p $object_id] { return } + + # Filter extra input field for category 'other' + set other_category_key_values [km_filter_other_category_keys $key_values] + set other_category_question_ids [fst [transpose $other_category_key_values]] + set other_category_values [snd [transpose $other_category_key_values]] + + #Make sure every key is an integer because all tag names here are question_ids. + set key_values [km_filter_valid_keys $key_values] + set submitted_question_ids [fst [transpose $key_values]] + set values [snd [transpose $key_values]] + if [null_p $submitted_question_ids] { return } + + db_1row km_save_object_data_10 " + select long_description, public_until, start_date, end_date + from sn_object_types + where object_type_id = (select object_type_id from sn_objects + where object_id = :object_id)" + + set short_description [db_list_of_lists question_info_short_desc { + select map.short_description + from sn_types_map_short_name map + where map.object_type_id = (select object_type_id from sn_objects + where object_id=:object_id) + order by position + }] + + #Get the attributes of the submitted_question_ids. + set questions [km_question_attributes $submitted_question_ids] + + db_transaction { + #Save the value according to the abstract_data_type + foreach question $questions { + + set question_id [fst $question] + set abstract_data_type [thd $question] + set value_list [lindex $values [lsearch $submitted_question_ids $question_id]] + + switch $abstract_data_type { + "category" { km_categorize_object $question_id $object_id $value_list } + "other_category" { + km_categorize_object $question_id $object_id $value_list + if {[lsearch -exact $value_list [km_get_other_category_id $question_id]] == -1} { + set other_value "" + } else { + set other_value [fst [lindex $other_category_values [lsearch $other_category_question_ids $question_id]]] + } + km_save_object_content -html_p 0 $question_id $object_id $user_id $other_value + } + "option" { km_map_object_answers $question_id $object_id $value_list } + "text" { + set content [fst $value_list] + set html_p [snd $value_list] + km_save_object_content -html_p $html_p $question_id $object_id $user_id $content + km_update_descriptions \ + -short_description $short_description -long_description $long_description \ + -html_p $html_p $object_id $question_id $content + } + "file" { + set filename [fst $value_list] + if ![empty_string_p $filename] { + # First test if the file is empty. If so, we ignore it. + + set tmpfilename [ns_queryget $question_id.tmpfile] + if [file size $tmpfilename] { + ns_cp $tmpfilename "[km_file_path]/$object_id.$question_id" + + # switch from DOS (\) to UNIX (/) path separators. + regsub -all {\\} $filename "/" filename + set filename [file tail $filename] + + km_save_object_content $question_id $object_id $user_id $filename + km_update_descriptions \ + -short_description $short_description -long_description $long_description \ + $object_id $question_id $filename + } + } + } + "integer" { + km_save_object_content $question_id $object_id $user_id [fst $value_list] + km_update_descriptions \ + -short_description $short_description -long_description $long_description \ + $object_id $question_id [fst $value_list] + } + "date" { + if [date_p $value_list] { + km_save_object_content $question_id $object_id $user_id $value_list + if { $question_id == $public_until } { + db_dml km_save_object_data_20 " + update sn_objects + set public_until=:value_list, + expired_warning_date = null + where object_id=:object_id" + } + if { $question_id == $start_date } { + db_dml km_save_object_data_22 " + update sn_objects + set start_date=:value_list + where object_id=:object_id" + } + if { $question_id == $end_date } { + db_dml km_save_object_data_24 " + update sn_objects + set end_date=:value_list + where object_id=:object_id" + } + km_update_descriptions \ + -short_description $short_description -long_description $long_description \ + $object_id $question_id [util_AnsiDatetoPrettyDate $value_list] + } + } + default { + ns_log Error "Unknown abstract_data_type in km_save_object_data: $abstract_data_type" + } + } + } + } + + return +} + +ad_proc km_append_object_content { {-html_p "f"} object_id question_id new_content } { + + Similar to km_save_object_content, but appends text to an already existing + entry in sn_content. + +} { + set content [db_string km_append_object_content_1 " + select content from sn_content + where object_id=:object_id and question_id=:question_id" -default ""] + + append content $new_content + + km_save_object_content -html_p $html_p $question_id $object_id [ad_get_user_id] $content +} + +ad_proc km_save_object_content { { -html_p ""} question_id object_id user_id content } { + Saves content into sn_content and and modification facts in sn_objects. +} { + set user_id [ad_get_user_id] + set ip_address [ns_conn peeraddr] + db_transaction { + if {[string length [string trim $content]] == 0} { + db_dml km_save_object_content_2 {delete from sn_content + where question_id=:question_id and object_id=:object_id + } + db_exec_plsql km_save_object_content_10 { + begin + object.audit_object ( + v_object_id => :object_id, + v_question_id => :question_id, + v_last_modifying_user_id => :user_id, + v_modifying_ip => :ip_address, + v_content => :content + ); + end; + } + } else { + set html_p [ad_decode $html_p 0 "f" "t"] + set content_length [string bytelength $content] + + db_exec_plsql km_save_object_content_10 { + begin + object.save_content ( + v_object_id => :object_id, + v_question_id => :question_id, + v_html_p => :html_p, + v_content_length => :content_length, + v_modifying_user => :user_id, + v_modifying_ip => :ip_address + ); + end; + } + + db_dml km_save_object_content_20 " + update sn_content + set content = empty_clob() + where object_id = :object_id and question_id = :question_id + returning content into :1" -clobs [list $content] + + if {$content_length>4000} { + set content [string range $content 0 2000] + } + + db_exec_plsql km_save_object_content_10 { + begin + object.audit_object ( + v_object_id => :object_id, + v_question_id => :question_id, + v_last_modifying_user_id => :user_id, + v_modifying_ip => :ip_address, + v_content => :content + ); + end; + } + + } + } +} + +ad_proc km_update_descriptions { + { + -short_description 0 + -long_description 0 + -html_p 0 + } + object_id question_id content +} { + Updates one_line_description and overview in sn_objects + if the question_id matches the given IDs. +} { + if { [lsearch $short_description $question_id] == -1 && $question_id != $long_description } { + return + } + + if [empty_string_p $html_p] { set html_p 0 } + set content [util_trim_string_with_hrefs [string trim $content] 2000] + + if { [lsearch $short_description $question_id] != -1} { + if {$short_description==$question_id} { + set object_name [sn_striphtml $content] + + db_dml km_update_descriptions_10 { + update sn_objects + set one_line_description = :object_name + where object_id = :object_id + } + } else { + set question1 [lindex $short_description 0] + set question2 [lindex $short_description 1] + set question3 [lindex $short_description 2] + db_dml km_update_descriptions_15 { + update sn_objects + set one_line_description = km_utilities.shortname_string(:object_id,:question1,:question2,:question3) + where object_id=:object_id} + } + } elseif { $question_id == $long_description } { + set decoded_html_p [ad_decode $html_p 0 "f" "t"] + db_dml km_update_descriptions_20 { + update sn_objects + set overview = :content, overview_html_p = :decoded_html_p + where object_id = :object_id + } + } +} + +proc_doc km_map_object_answers { question_id object_id option_ids } { + Maps any number of answer_options to a +} { + db_dml km_map_object_answers_1 "delete from sn_object_option_map where object_id=:object_id + and option_id in ( select option_id from sn_answer_options + where question_id = :question_id)" + foreach option_id $option_ids { + set sql "insert into sn_object_option_map (object_id, option_id) values (:object_id, :option_id)" + catch { [db_dml km_map_object_answers_2 $sql] } + } +} + +ad_proc km_unoptionize_object { object_id question_id } { + Removes options for this object and question +} { + db_dml km_unoptionize_object_1 " + delete from sn_object_option_map + where object_id = :object_id and + option_id in (select option_id from sn_answer_options where question_id = :question_id)" + +} + +proc_doc km_delete_object_data { object_id question_id } { + Removes the answer for a question. (Used for read-only questions.) +} { + set abstract_data_type [db_string km_delete_object_data_1 " + select abstract_data_type from sn_questions where question_id = :question_id"] + + switch $abstract_data_type { + "text" - + "integer" - + "date" { + db_dml km_delete_object_data_2 " + delete from sn_content where object_id=:object_id and question_id=:question_id" + } + "file" { + db_dml km_delete_object_data_3 " + delete from sn_content where object_id=:object_id and question_id=:question_id" + ns_unlink -nocomplain "[km_file_path]/$object_id.$question_id" + } + "option" { km_unoptionize_object $object_id $question_id } + "category" { km_uncategorize_object $object_id $question_id } + "other_category" { km_uncategorize_object $object_id $question_id } + default { ns_log Error "km_delete_object_data cannot handle abstract_data_type $abstract_data_type" } + } +} + + +# ********** Filters/Validators ********** + +proc_doc km_filter_content_questions {question_ids abstract_data_types} { + Returns a list of question_ids that are actually a row in sn_content. +} { + set questions [zip $question_ids $abstract_data_types] + set content [list] + foreach pair $questions { + set question_id [fst $pair] + set abstract_data_type [snd $pair] + if [lsearch [list text date upload] $abstract_data_type] >= 0 { + lappend filtered_questions $question_id + } + } + return $filtered_questions +} + +proc_doc integer_p {number} "returns 1 if this is an integer" { + if [regexp {[^0-9]} $number] { + return 0 + } else { + return 1 + } +} + +proc_doc filter_integers {char_list} { + returns a filtered list of characters in the list that are integers +} { + set result [list] + foreach char $char_list { + if [integer_p $char] {lappend result $char} + } + return $result +} + +proc_doc date_p {date} "returns 1 if this is a date" { + set result [catch {db_0or1row date_p "select to_date('$date') from dual"}] + if {$result} { + return 0 + } else { + return 1 + } +} + +proc_doc km_break_date {date} { + Breaks an Oracle date in the form YYYY-MM-DD up into a list YYYY MM DD +} { + if {![regexp {([0-9]*)-.*} $date match YYYY]} { return ""} + if {![regexp {[0-9]*-([0-9]*)-*} $date match MM]} { return ""} + if {![regexp {[0-9]*-[0-9]*-([0-9]*)} $date match DD]} {return ""} + + return [list $YYYY $MM $DD] +} + +proc_doc empty_date_p {date} "returns 1 if this is an empty date in the form xx--" { + + if [regexp {.+-.+-.+} $date] {return 0} + return 1 +} + +# Serve the abstract URL +# download/./ + +proc km_serve_document {} { + if { ![regexp {/download/([0-9]+)\.([0-9]+)/([^/]+)$} [ns_conn url] match object_id question_id client_filename] } { + ad_return_warning "Malformed Document Request" \ + "Your request for a document was malformed." + return + } + + if [km_check_object_id $object_id] { + ns_returnfile 200 [ns_guesstype $client_filename] "[km_file_path]/$object_id.$question_id" + } +} + +ad_proc set_the_usual_klib_context_bar { object_id {category_id ""} {pre_url ""} } { + Display normal klib context bar - you have to use km_check_object_id first +} { + set object_type_id [km_conn object_type_id] + set object_name [km_conn object_name] + set object_link "${pre_url}object-view?[export_url_vars object_id category_id]" + set pretty_type_plural [km_static object_type_pretty_plural $object_type_id] + if {[km_conn archived_p]} { + set pretty_type_plural "$pretty_type_plural (Archived)" + set archive t + } + set stripped_name [sn_striphtml $object_name] + set browse_type "${pre_url}browse-one-type?[export_url_vars object_type_id archive]" + set browse_category "${pre_url}browse-one-category?[export_url_vars object_type_id category_id archive]" + set ancestors [reverse [km_get_object_ancestors $object_id]] + + if {![null_p $ancestors]} { + set context_list [km_ancestors_context_list $ancestors $category_id $pre_url] + lappend context_list [list $object_link $stripped_name] + eval set_context_bar_data -link_last $context_list + } elseif { ![empty_string_p $category_id] && ![string equal $category_id "none"] } { + set_context_bar_data -link_last \ + [list $browse_type $pretty_type_plural] \ + [list $browse_category [km_category_name $category_id]] \ + [list $object_link $stripped_name] + } else { + set_context_bar_data -link_last [list $browse_type $pretty_type_plural] [list $object_link $stripped_name] + } +} + +ad_proc km_other_category_set { object_id question_id content } { + Insert or update the text the user entered in the text field for category 'other' +} { + if [empty_string_p $content] { + km_other_category_delete $object_id $question_id + } else { + set content_length [string bytelength $content] + set ip_address [ns_conn peeraddr] + set user_id [ad_conn user_id] + + db_exec_plsql km_other_category_set_1 { + begin + object.save_content ( + v_object_id => :object_id, + v_question_id => :question_id, + v_html_p => 'f', + v_content_length => :content_length, + v_modifying_user => :user_id, + v_modifying_ip => :ip_address + ); + end; + } + + db_dml km_other_category_set_2 " + update sn_content + set content = empty_clob() + where object_id = :object_id and question_id = :question_id + returning content into :1" -clobs [list $content] + + if {$content_length>4000} { + set content [string range $content 0 2000] + } + + db_exec_plsql km_other_category_set_3 { + begin + object.audit_object ( + v_object_id => :object_id, + v_question_id => :question_id, + v_last_modifying_user_id => :user_id, + v_modifying_ip => :ip_address, + v_content => :content + ); + end; + } + } +} + +ad_proc km_other_category_get { object_id question_id } { + Get the text the user entered in the text field for category 'other' +} { + set result [db_string km_other_category_get { + select content + from sn_content + where object_id = :object_id + and question_id = :question_id + } -default ""] + + return $result +} + +ad_proc km_other_category_delete { object_id question_id } { + Delete the text the user entered in the text field for category 'other' +} { + set ip_address [ns_conn peeraddr] + set user_id [ad_conn user_id] + set content [km_other_category_get $object_id $question_id + + db_dml km_other_category_delete_1 { + delete from sn_content + where object_id = :object_id + and question_id = :question_id + } + + db_exec_plsql km_other_category_delete_2 { + begin + object.audit_object ( + v_object_id => :object_id, + v_question_id => :question_id, + v_last_modifying_user_id => :user_id, + v_modifying_ip => :ip_address, + v_content => :content + ); + end; + } +} + +ad_proc km_get_other_category_id { question_id } { + get the category_id of the category "other" - or the last category in + sorted list +} { + set categories [db_list_of_lists check_other_category_id { + select /*+INDEX(sw_category_dim sw_category_dim_long_name) */ category.long_name(object_id) as name, + object_id as other_category_id + from sw_category_dim + start with node_id = (select node_id from sn_questions where question_id = :question_id) + connect by prior node_id = parent_node_id + }] + + set values [fst [transpose $categories]] + set ids [snd [transpose $categories]] + set found_pos [lsearch $values "Other"] + if {$found_pos > -1} { + set other_category_id [lindex $ids $found_pos] + } else { + set other_category_id [snd [fst [reverse $categories]]] + } + return $other_category_id +} + +util_report_successful_library_load Index: openacs-4/contrib/obsolete-packages/library/tcl/km-psn-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/tcl/km-psn-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/tcl/km-psn-procs.tcl 2 Jul 2003 12:19:41 -0000 1.1 @@ -0,0 +1,1770 @@ +# /tcl/km-psn-procs.tcl +# +# People Sharenet Procs. +# +# Created by timo@arsdigita.com in late October 2001 +# +# $Id: km-psn-procs.tcl,v 1.1 2003/07/02 12:19:41 peterm Exp $ + +ad_proc -public portal_saved_applications { cf } { + Displays the list of the saved and unfinished applications for demand + descriptions. +} { + set user_id [ad_conn user_id] + set return_url "[ad_conn url]?[ad_conn query]" + + template::multirow create saved_applications project_name demand_name application_id library_url return_url + + db_foreach portal_saved_applications_10 { + select o1.one_line_description as demand_name, a.object_id, + o2.one_line_description as project_name, a.application_id + from sn_objects o1, sn_objects o2, psn_res_applications a + where a.user_id = :user_id + and a.sent_p = 'f' + and o1.object_id = a.object_id + and o2.object_id = a.resource_req_id + } { + db_1row portal_saved_applications_20 { + select site_node.url(sn.node_id) as library_url + from site_nodes sn, acs_objects_description dsc + where sn.object_id = dsc.package_id + and dsc.object_id = :object_id + and rownum = 1 + } + template::multirow append saved_applications $project_name $demand_name $application_id $library_url $return_url + } +} + +ad_proc -public portal_approval_processes { cf } { + Displays the list of the approval workflows. +} { + set user_id [ad_conn user_id] + + set package_id [portal_arg $cf package_id] + if [empty_string_p $package_id] { + # grab the community_id + set where_sql "o.context_id in (select package_id + from sn_community_mounts_all cm + where cm.community_id = :community_id + and acs_permission.permission_p(package_id, :user_id, 'access') = 't')" + } else { + set where_sql "o.context_id = :package_id" + } + + set last_package_id "" + + template::multirow create task_list task_id enabled_date enabled_time started_date started_time state object_id object_name object_type_id object_type_pretty workflow_key task_name task_url submitter_id submitter_name package_id package_name package_url + + db_transaction { + if { [empty_string_p $package_id] } { + array set node [site_node_closest_ancestor_site_node "acs-subsite"] + set community_id $node(package_id) + + db_dml check_package_access " + insert into yp_package_access + select p.package_id + from sn_community_mounts cm, apm_packages p + where cm.community_id = :community_id + and p.package_id = cm.package_id + and p.package_key = 'library' + and [tcl_permission_for_bind_vars_p "p.package_id" ":user_id" "'access'"] = 't' + " + } else { + db_dml check_package_access_one { + insert into yp_package_access + select :package_id + from dual + where acs_permission.permission_p(:package_id, :user_id, 'access') = 't' + } + } + + db_foreach get_workflows { + select t.task_id, t.state, c.object_id, o.object_type_id, + t.enabled_date, t.started_date, + to_char(t.enabled_date, 'HH24;MI') as enabled_time_pretty, + to_char(t.started_date, 'HH24:MI') as started_time_pretty, + ot.pretty_name as object_type_pretty, o.one_line_description as object_name, + c.workflow_key, t.transition_name as task_name, u.user_id as submitter_id, + u.first_names || ' ' || u.last_name as submitter_name, + o.context_id as package_id + from wf_cases c, sn_objects o, sn_object_types ot, wf_user_tasks t, + users u, acs_objects ao, yp_package_access ypa + where c.case_id = t.case_id + and c.object_id = o.object_id + and ot.object_type_id = o.object_type_id + and t.user_id = :user_id + and (t.state = 'enabled' or (t.state = 'started' and t.holding_user = t.user_id)) + and c.workflow_key = 'library_approval_wf' + and ao.object_id = c.case_id + and ao.creation_user = u.user_id + and o.context_id = ypa.package_id + order by o.context_id, t.transition_name, t.enabled_date desc, ot.pretty_name, o.one_line_description + } { + if {$package_id != $last_package_id} { + set last_package_id $package_id + db_1row get_package_data { + select site_node.url(n.node_id) as package_url, p.instance_name as package_name + from site_nodes n, apm_packages p + where n.object_id = :package_id + and p.package_id = :package_id + and rownum = 1 + } + } + + template::multirow append task_list $task_id \ + [util_AnsiDatetoPrettyDate $enabled_date] $enabled_time_pretty \ + [util_AnsiDatetoPrettyDate $started_date] $started_time_pretty \ + $state $object_id $object_name $object_type_id $object_type_pretty \ + $workflow_key $task_name "../approval-tasks/task?task_id=$task_id" \ + $submitter_id $submitter_name $package_id $package_name $package_url + } + } +} + +ad_proc -public km_sweeper_daily { } { + db_transaction { + km_sweeper_warn "outdated" + km_sweeper_warn "expired" + km_sweeper "outdated" + km_sweeper "expired" + } +} + +ad_proc -private km_sweeper_warn { time } { +} { + if {[string equal $time "expired"]} { + set time_sql "o.expired_warning_date is null and o.public_until is not null and o.public_until + 1 - ot.sweeper_warning_time < sysdate" + } else { + set time_sql "o.outdated_warning_date is null and o.last_modified + ot.sweeper_outdated_time - ot.sweeper_warning_time < sysdate" + } + + db_transaction { + ################ + ## process the single objects + ################ + set count 0 + db_foreach get_outdated_objects_for_warning " + select o.object_id, o.object_type_id, o.one_line_description as object_name, + ot.pretty_name as object_type, o.original_author_id, o.context_id, + ot.sweeper_action, (sysdate - o.last_modified) as days_unchanged, + ot.sweeper_warning_time + from sn_objects o, sn_object_types ot + where ot.object_type_id = o.object_type_id + and o.public_p = 't' + and o.archived_p = 'f' + and o.expiration_date > sysdate + and ot.sweeper = :time + and ot.sweeper_warning_time > 0 + and $time_sql + " { + lappend o_object_id $object_id + lappend o_object_type_id $object_type_id + lappend o_object_name $object_name + lappend o_object_type $object_type + lappend o_original_author_id $original_author_id + lappend o_context_id $context_id + lappend o_sweeper_action $sweeper_action + lappend o_days_unchanged $days_unchanged + lappend o_sweeper_warning_time $sweeper_warning_time + incr count + } + + if {$count>0} { + foreach object_id $o_object_id object_type_id $o_object_type_id \ + object_name $o_object_name object_type $o_object_type \ + original_author_id $o_original_author_id \ + context_id $o_context_id sweeper_action $o_sweeper_action \ + days_unchanged $o_days_unchanged \ + sweeper_warning_time $o_sweeper_warning_time { + + if [empty_string_p $object_name] { + set object_name "Unnamed $object_type" + } + + ## set mail_body [km_sweeper_single_objects_warning_mail $time $sweeper_action $object_type $object_name $object_id $days_unchanged $sweeper_warning_time] + set mail_body "$object_name ([ad_url]/o/$object_id)\n" + + db_dml warn_single_object_outdated { + insert into km_sweeper (user_id, package_id, object_type_id, object_id, object_name, content) + values (:original_author_id, :context_id, :object_type_id, :object_id, :object_name, :mail_body) + } + } + + ## now register that warnings got send for these objects + db_dml object_warnings " + update sn_objects + set $time\_warning_date = trunc(sysdate) + where object_id in (select o.object_id + from sn_objects o, sn_object_types ot + where ot.object_type_id = o.object_type_id + and o.public_p = 't' + and o.archived_p = 'f' + and ot.sweeper = :time + and ot.sweeper_warning_time > 0 + and $time_sql ) + " + + unset o_object_id + unset o_object_type_id + unset o_object_name + unset o_object_type + unset o_original_author_id + unset o_context_id + unset o_sweeper_action + unset o_days_unchanged + unset o_sweeper_warning_time + + } + + ################ + ## now send all the email, one per user, ordered by object_type + ################ + set mail "" + set last_user_id "" + set last_user_email "" + set last_community_id "" + set last_package_id "" + set last_object_type_id "" + set count 0 + db_foreach get_mail_bodies_per_user { + select u.user_id, u.email as user_email, s.content as mail_body, + ot.object_type_id, ot.pretty_plural as object_type, + p.instance_name as package_name, s.package_id, + p2.instance_name as community_name, ci.community_id, + ot.sweeper_warning_time, ot.sweeper_outdated_time + from km_sweeper s, users u, sn_object_types ot, + sn_community_instances ci, apm_packages p, apm_packages p2 + where u.user_id = s.user_id + and s.object_type_id = ot.object_type_id + and ci.package_id = s.package_id + and p.package_id = s.package_id + and p2.package_id = ci.community_id + order by s.user_id, p2.instance_name, p.instance_name, + ot.pretty_plural, s.object_name + } { + lappend o_user_id $user_id + lappend o_user_email $user_email + lappend o_mail_body $mail_body + lappend o_object_type_id $object_type_id + lappend o_object_type $object_type + lappend o_package_name $package_name + lappend o_package_id $package_id + lappend o_community_name $community_name + lappend o_community_id $community_id + lappend o_sweeper_warning_time $sweeper_warning_time + lappend o_sweeper_outdated_time [expr $sweeper_outdated_time - $sweeper_warning_time] + incr count + } + + if {$count>0} { + foreach user_id $o_user_id user_email $o_user_email \ + mail_body $o_mail_body object_type_id $o_object_type_id \ + object_type $o_object_type package_name $o_package_name \ + package_id $o_package_id community_name $o_community_name \ + community_id $o_community_id \ + sweeper_warning_time $o_sweeper_warning_time \ + sweeper_outdated_time $o_sweeper_outdated_time { + + if {($last_user_id != $user_id) && ![empty_string_p $last_user_id]} { + set replacement_list \ + [list \ + type $time \ + mail_body $mail \ + recipient $last_user_email] + + et_queue_email [et_process "km_sweeper_warn" $replacement_list] + set last_user_id "" + set last_user_email "" + set last_community_id "" + set last_package_id "" + set last_object_type_id "" + set mail "" + } + if {$last_community_id != $community_id} { + append mail "Community: $community_name\n===========\n" + set last_community_id $community_id + } + if {$last_package_id != $package_id} { + append mail "\n$package_name:\n===========\n" + set last_package_id $package_id + } + if {$last_object_type_id != $object_type_id} { + append mail "\n$object_type:\n===========\n\n" + if {![string equal $time "expired"]} { + append mail "The following objects haven't been changed in the last $sweeper_outdated_time days. " + } + append mail "Please change the objects in the next $sweeper_warning_time days:\n\n" + set last_object_type_id $object_type_id + } + append mail $mail_body + set last_user_id $user_id + set last_user_email $user_email + } + if ![empty_string_p $mail] { + set replacement_list \ + [list \ + type $time \ + mail_body $mail \ + recipient $user_email] + + et_queue_email [et_process "km_sweeper_warn" $replacement_list] + } + + unset o_user_id + unset o_user_email + unset o_mail_body + unset o_object_type_id + unset o_object_type + unset o_package_name + unset o_package_id + unset o_community_name + unset o_community_id + unset o_sweeper_warning_time + unset o_sweeper_outdated_time + } + + ################ + ## now send the email to object publisher + ## one per user, ordered by object_type + ################ + set mail "" + set last_publisher_id "" + set last_publisher_email "" + set last_community_id "" + set last_package_id "" + set last_object_type_id "" + set count 0 + db_foreach get_publisher_mail_bodies_per_user { + select u.user_id as publisher_id, u.email as publisher_email, + s.content as mail_body, ot.object_type_id, + ot.pretty_plural as object_type, + p.instance_name as package_name, s.package_id, + p2.instance_name as community_name, ci.community_id, + ot.sweeper_warning_time, ot.sweeper_outdated_time + from km_sweeper s, users u, sn_object_types ot, sn_objects o, + sn_community_instances ci, apm_packages p, apm_packages p2 + where u.user_id = o.publisher_id + and o.publisher_id <> s.user_id + and s.object_id = o.object_id + and s.object_type_id = ot.object_type_id + and ci.package_id = s.package_id + and p.package_id = s.package_id + and p2.package_id = ci.community_id + and s.package_id in (select distinct ac.package_id + from approval_coordinators ac) + order by s.user_id, p2.instance_name, p.instance_name, + ot.pretty_plural, s.object_name + } { + lappend o_publisher_id $publisher_id + lappend o_publisher_email $publisher_email + lappend o_mail_body $mail_body + lappend o_object_type_id $object_type_id + lappend o_object_type $object_type + lappend o_package_name $package_name + lappend o_package_id $package_id + lappend o_community_name $community_name + lappend o_community_id $community_id + lappend o_sweeper_warning_time $sweeper_warning_time + lappend o_sweeper_outdated_time [expr $sweeper_outdated_time - $sweeper_warning_time] + incr count + } + + if {$count>0} { + foreach publisher_id $o_publisher_id publisher_email $o_publisher_email \ + mail_body $o_mail_body object_type_id $o_object_type_id \ + object_type $o_object_type package_name $o_package_name \ + package_id $o_package_id community_name $o_community_name \ + community_id $o_community_id \ + sweeper_warning_time $o_sweeper_warning_time \ + sweeper_outdated_time $o_sweeper_outdated_time { + + if {($last_publisher_id != $publisher_id) && ![empty_string_p $last_publisher_id]} { + set replacement_list \ + [list \ + type $time \ + mail_body $mail \ + recipient $last_publisher_email] + + et_queue_email [et_process "km_sweeper_warn_publisher" $replacement_list] + set last_publisher_id "" + set last_publisher_email "" + set last_community_id "" + set last_package_id "" + set last_object_type_id "" + set mail "" + } + if {$last_community_id != $community_id} { + append mail "Community: $community_name\n===========\n" + set last_community_id $community_id + } + if {$last_package_id != $package_id} { + append mail "\n$package_name:\n===========\n" + set last_package_id $package_id + } + if {$last_object_type_id != $object_type_id} { + append mail "\n$object_type:\n===========\n\n" + if {![string equal $time "expired"]} { + append mail "The following objects haven't been changed in the last $sweeper_outdated_time days. " + } + append mail "Please change the objects in the next $sweeper_warning_time days:\n\n" + set last_object_type_id $object_type_id + } + append mail $mail_body + set last_publisher_id $publisher_id + set last_publisher_email $publisher_email + } + if ![empty_string_p $mail] { + set replacement_list \ + [list \ + type $time \ + mail_body $mail \ + recipient $publisher_email] + + et_queue_email [et_process "km_sweeper_warn_publisher" $replacement_list] + } + + unset o_publisher_id + unset o_publisher_email + unset o_mail_body + unset o_object_type_id + unset o_object_type + unset o_package_name + unset o_package_id + unset o_community_name + unset o_community_id + unset o_sweeper_warning_time + unset o_sweeper_outdated_time + } + + ############### + ## now cleanup: delete temp table + ############### + db_dml km_sweeper_cleanup { + delete from km_sweeper + } + } +} + +# time: expired / outdated +ad_proc -private km_sweeper { time } { + Sets objects with outdated publication date to private and sends an email + notification to the object owner +} { + if {[string equal $time "expired"]} { + set time_sql "(o.public_until is not null and o.public_until+1 < sysdate and (o.expired_warning_date is null or o.expired_warning_date + ot.sweeper_warning_time < sysdate))" + set time_sql2 "(o2.public_until is not null and o2.public_until+1 < sysdate and (o2.expired_warning_date is null or o2.expired_warning_date + ot2.sweeper_warning_time < sysdate))" + } else { + set time_sql "(o.last_modified + ot.sweeper_outdated_time < sysdate and (o.outdated_warning_date is null or o.outdated_warning_date + ot.sweeper_warning_time < sysdate))" + set time_sql2 "(o2.last_modified + ot2.sweeper_outdated_time < sysdate and (o2.outdated_warning_date is null or o2.outdated_warning_date + ot2.sweeper_warning_time < sysdate))" + } + + db_transaction { + ################# + ## deal with uncle objects that won't have public nephews any longer + ################# + ## IMPORTANT NOTE: this supports only ONE hierarchy level in the sense + ## that only the DIRECT uncle of outdated objects will get private + ## - but then all it's descendants (multiple levels) will get private also + ################# + set outdated_uncles [db_list get_uncles_need_private_status " + select foh.parent + from km_flat_object_hierarchy foh, sn_objects o, sn_object_types ot + where foh.parent = o.object_id + and o.public_p = 't' + and o.archived_p = 'f' + and o.expiration_date > sysdate + and o.object_type_id = ot.object_type_id + and not ((ot.sweeper = 'expired' and o.public_until is not null and o.public_until+1 < sysdate and (o.expired_warning_date is null or o.expired_warning_date + ot.sweeper_warning_time < sysdate)) + or (ot.sweeper = 'outdated' and o.last_modified + ot.sweeper_outdated_time < sysdate and (o.outdated_warning_date is null or o.outdated_warning_date + ot.sweeper_warning_time < sysdate))) + and foh.link_type = 'uncle_nephew' + and exists (select 1 + from sn_questions q, sn_question_object_type_map qotm, + sn_object_types ot3 + where qotm.object_type_id = o.object_type_id + and qotm.question_id = q.question_id + and q.abstract_data_type = 'nephew_object' + and qotm.mandatory_p = 't' + and qotm.question_state = 'active' + and q.target_object_type_id = ot3.object_type_id + and ot3.sweeper = :time + and not exists (select 1 + from sn_question_link_map qlm, sn_links l, + sn_objects o2, sn_object_types ot2 + where qlm.question_id = q.question_id + and qlm.link_id = l.link_id + and l.object_id_a = o.object_id + and l.object_id_b = o2.object_id + and o2.object_type_id = ot2.object_type_id + and o2.public_p = 't' + and o2.archived_p = 'f' + and ot2.sweeper = :time + and not $time_sql2 ) ) + order by foh.distance desc + "] + + foreach outdated_uncle $outdated_uncles { + # check if uncle is still public and get uncle data + # get the questions that won't have any public nephews any longer + # get all nephews that result in private uncle + # get all other descendants + # send email to uncle owner + # loop over nephews again, but with different owner + # if different owner -> send email + # loop over other descendants again, but with different owner + # if different owner -> send email + # unpublish uncle and all descendants + + db_1row get_outdated_uncle_object_data { + select o.object_id as uncle_id, o.object_type_id as uncle_object_type_id, + o.one_line_description as uncle_name, ot.sweeper_action, + ot.pretty_name as uncle_object_type, o.public_p, o.archived_p, + u.email as uncle_author_email, u.user_id as uncle_author_id, + u.first_names || ' ' || u.last_name as uncle_author, o.context_id, + ci.community_id, o.publisher_id as uncle_publisher_id + from sn_objects o, sn_object_types ot, users u, + sn_community_instances ci + where ot.object_type_id = o.object_type_id + and u.user_id = o.original_author_id + and o.object_id = :outdated_uncle + and ci.package_id = o.context_id + } + + if [empty_string_p $uncle_name] { + set uncle_name "Unnamed $uncle_object_type" + } + + ## if uncle of this object already got private, so did this object, so check + ## if it's still public + if {$public_p == "t" && $archived_p == "f"} { + + if {[string equal $time "expired"]} { + set archive_sql "o.archived_p = 'f'" + set archive_sql2 "o2.archived_p = 'f'" + } else { + set archive_sql "o.public_p = 't'" + set archive_sql2 "o2.public_p = 't'" + } + + ## get all violated questions with outdated nephews + set question_ids [db_list get_violated_questions " + select q.question_id + from sn_questions q, sn_question_object_type_map qotm, + sn_objects o, sn_object_types ot + where q.abstract_data_type = 'nephew_object' + and qotm.question_id = q.question_id + and qotm.mandatory_p = 't' + and qotm.question_state = 'active' + and qotm.object_type_id = o.object_type_id + and o.object_id = :uncle_id + and q.target_object_type_id = ot.object_type_id + and ot.sweeper = :time + and not exists (select 1 + from sn_question_link_map qlm, sn_links l, + sn_objects o2, sn_object_types ot2 + where qlm.question_id = q.question_id + and l.link_id = qlm.link_id + and l.object_id_a = :uncle_id + and l.object_id_b = o2.object_id + and o2.object_type_id = ot2.object_type_id + and o2.public_p = 't' + and o2.archived_p = 'f' + and ot2.sweeper = :time + and not $time_sql2 ) + "] + + ## get all outdated nephews for the violated questions + set last_object_type_id "" + set nephew_list "" + set nephew_ids [list] + + db_foreach get_outdated_violating_nephews " + select o.object_id, o.object_type_id, + o.one_line_description as object_name, + ot.pretty_plural as object_type_plural, + ot.pretty_name as object_type + from sn_objects o, sn_object_types ot, sn_question_link_map qlm, + sn_links l + where ot.object_type_id = o.object_type_id + and o.public_p = 't' + and o.archived_p = 'f' + and ot.sweeper = :time + and $time_sql + and l.object_id_a = :uncle_id + and l.object_id_b = o.object_id + and l.link_id = qlm.link_id + and qlm.question_id in ([join $question_ids ,]) + order by o.object_type_id + " { + if [empty_string_p $object_name] { + set object_name "Unnamed $object_type" + } + + if {$last_object_type_id != $object_type_id} { + append nephew_list "\n$object_type_plural: $object_name" + } else { + append nephew_list ", $object_name" + } + set last_object_type_id $object_type_id + lappend nephew_ids $object_id + } + + ## get all other public descendants + set last_object_type_id "" + set object_list "" + + db_foreach get_all_other_public_descendants " + select o.object_id, o.object_type_id, + o.one_line_description as object_name, + ot.pretty_plural as object_type_plural, + ot.pretty_name as object_type + from sn_objects o, sn_object_types ot, km_flat_object_hierarchy foh + where ot.object_type_id = o.object_type_id + and $archive_sql + and foh.parent = :uncle_id + and o.object_id = foh.child + and o.object_id not in ([join $nephew_ids ,]) + order by o.object_type_id + " { + if [empty_string_p $object_name] { + set object_name "Unnamed $object_type" + } + + if {$last_object_type_id != $object_type_id} { + append object_list "\n$object_type_plural: $object_name" + } else { + append object_list ", $object_name" + } + set last_object_type_id $object_type_id + } + + ## send email to object owner + set mail_body [km_sweeper_uncle_with_nephews_mail $community_id $time $sweeper_action $uncle_object_type $uncle_name $uncle_id $nephew_list $object_list] + + db_dml uncle_with_nephews_outdated { + insert into km_sweeper (user_id, package_id, object_type_id, object_id, object_name, content) + values (:uncle_author_id, :context_id, :uncle_object_type_id, :uncle_id, :uncle_name, :mail_body) + } + + if {![empty_string_p $uncle_publisher_id] && $uncle_publisher_id != $uncle_author_id} { + db_dml uncle_with_nephews_outdated_publisher { + insert into km_sweeper_publisher (user_id, package_id, object_type_id, object_id, object_name, content) + values (:uncle_publisher_id, :context_id, :uncle_object_type_id, :uncle_id, :uncle_name, :mail_body) + } + } + + ## get all outdated nephews for the violated questions with different + ## owners and send them email + ################## + set last_author_id "" + set last_object_type_id "" + set outdated_nephew_list "" + set count 0 + + db_foreach get_outdated_violating_nephews_other_owner " + select o.object_id, o.object_type_id, o.original_author_id as author_id, + o.one_line_description as object_name, u.email as author_email, + ot.pretty_plural as object_type_plural, + ot.pretty_name as object_type + from sn_objects o, sn_object_types ot, users u + where ot.object_type_id = o.object_type_id + and u.user_id = o.original_author_id + and u.user_id <> :uncle_author_id + and o.object_id in ([join $nephew_ids ,]) + order by u.user_id, o.object_type_id + " { + lappend o_object_id $object_id + lappend o_object_type_id $object_type_id + lappend o_author_id $author_id + lappend o_object_name $object_name + lappend o_author_email $author_email + lappend o_object_type_plural $object_type_plural + lappend o_object_type $object_type + incr count + } + + if {$count>0} { + foreach object_id $o_object_id object_type_id $o_object_type_id \ + author_id $o_author_id author_email $o_author_email \ + object_name $o_object_name object_type $o_object_type \ + object_type_plural $o_object_type_plural { + + if [empty_string_p $object_name] { + set object_name "Unnamed $object_type" + } + + if {($last_author_id != $author_id) && ![empty_string_p $last_author_id]} { + set mail_body [km_sweeper_nephew_objects_mail $community_id $time $sweeper_action $uncle_object_type $uncle_name $uncle_id $uncle_author $outdated_nephew_list $object_list] + + db_dml uncle_with_nephews_outdated { + insert into km_sweeper (user_id, package_id, object_type_id, object_id, object_name, content) + values (:author_id, :context_id, :uncle_object_type_id, :uncle_id, :uncle_name, :mail_body) + } + + set last_object_type_id "" + set outdated_nephew_list "" + } + if {$last_object_type_id != $object_type_id} { + append outdated_nephew_list "\n\n$object_type_plural:" + set last_object_type_id $object_type_id + set last_author_id $author_id + } + append outdated_nephew_list "\n$object_name ([ad_url]/o/$object_id)" + } + if ![empty_string_p $outdated_nephew_list] { + + set mail_body [km_sweeper_nephew_objects_mail $community_id $time $sweeper_action $uncle_object_type $uncle_name $uncle_id $uncle_author $outdated_nephew_list $object_list] + + db_dml uncle_with_nephews_outdated { + insert into km_sweeper (user_id, package_id, object_type_id, object_id, object_name, content) + values (:author_id, :context_id, :uncle_object_type_id, :uncle_id, :uncle_name, :mail_body) + } + } + + unset o_object_id + unset o_object_type_id + unset o_author_id + unset o_author_email + unset o_object_name + unset o_object_type + unset o_object_type_plural + } + + ## get all other descendants with different owners and send them email + set last_author_id "" + set last_object_type_id "" + set descendants_list "" + set count 0 + + db_foreach get_all_other_public_descendants_other_owner " + select o.object_id, o.object_type_id, o.original_author_id as author_id, + o.one_line_description as object_name, u.email as author_email, + ot.pretty_plural as object_type_plural, + ot.pretty_name as object_type + from sn_objects o, sn_object_types ot, km_flat_object_hierarchy foh, + users u + where ot.object_type_id = o.object_type_id + and u.user_id = o.original_author_id + and u.user_id <> :uncle_author_id + and u.user_id not in (select distinct o2.original_author_id + from sn_objects o2 + where o2.object_id in ([join $nephew_ids ,])) + and $archive_sql + and foh.parent = :uncle_id + and o.object_id = foh.child + and o.object_id not in ([join $nephew_ids ,]) + order by u.user_id, o.object_type_id + " { + lappend o_object_id $object_id + lappend o_object_type_id $object_type_id + lappend o_author_id $author_id + lappend o_object_name $object_name + lappend o_author_email $author_email + lappend o_object_type_plural $object_type_plural + lappend o_object_type $object_type + incr count + } + + if {$count>0} { + foreach object_id $o_object_id object_type_id $o_object_type_id \ + author_id $o_author_id author_email $o_author_email \ + object_name $o_object_name object_type $o_object_type \ + object_type_plural $o_object_type_plural { + + if [empty_string_p $object_name] { + set object_name "Unnamed $object_type" + } + + if {($last_author_id != $author_id) && ![empty_string_p $last_author_id]} { + set mail_body [km_uncles_descendant_objects_mail $community_id $time $sweeper_action $uncle_object_type $uncle_name $uncle_id $uncle_author $nephew_list $descendants_list] + + db_dml uncle_with_nephews_outdated { + insert into km_sweeper (user_id, package_id, object_type_id, object_id, object_name, content) + values (:author_id, :context_id, :uncle_object_type_id, :uncle_id, :uncle_name, :mail_body) + } + set last_object_type_id "" + set descendants_list "" + } + if {$last_object_type_id != $object_type_id} { + append descendants_list "\n\n$object_type_plural:" + set last_object_type_id $object_type_id + set last_author_id $author_id + } + append descendants_list "\n$object_name ([ad_url]/o/$object_id)" + } + if ![empty_string_p $descendants_list] { + + set mail_body [km_uncles_descendant_objects_mail $community_id $time $sweeper_action $uncle_object_type $uncle_name $uncle_id $uncle_author $nephew_list $descendants_list] + + db_dml uncle_with_nephews_outdated { + insert into km_sweeper (user_id, package_id, object_type_id, object_id, object_name, content) + values (:author_id, :context_id, :uncle_object_type_id, :uncle_id, :uncle_name, :mail_body) + } + } + + unset o_object_id + unset o_object_type_id + unset o_author_id + unset o_author_email + unset o_object_name + unset o_object_type + unset o_object_type_plural + } + + ## get all outdated nephews for the violated questions with different + ## publishers and send them email + ################## + if {[empty_string_p $uncle_publisher_id]} { + set uncle_publisher_id 0 + } + set last_publisher_id "" + set last_object_type_id "" + set outdated_nephew_list "" + set count 0 + + db_foreach get_outdated_violating_nephews_other_publisher " + select o.object_id, o.object_type_id, o.publisher_id, + o.one_line_description as object_name, + ot.pretty_plural as object_type_plural, + ot.pretty_name as object_type + from sn_objects o, sn_object_types ot + where ot.object_type_id = o.object_type_id + and o.publisher_id is not null + and o.publisher_id <> :uncle_publisher_id + and o.publisher_id <> :uncle_author_id + and o.object_id in ([join $nephew_ids ,]) + and o.publisher_id not in (select distinct o2.original_author_id + from sn_objects o2, km_flat_object_hierarchy foh + where foh.child = o2.object_id + and foh.parent = :uncle_id + and $archive_sql2) + order by o.publisher_id, o.object_type_id + " { + lappend o_object_id $object_id + lappend o_object_type_id $object_type_id + lappend o_publisher_id $publisher_id + lappend o_object_name $object_name + lappend o_object_type_plural $object_type_plural + lappend o_object_type $object_type + incr count + } + + if {$count>0} { + foreach object_id $o_object_id object_type_id $o_object_type_id \ + publisher_id $o_publisher_id object_name $o_object_name \ + object_type $o_object_type \ + object_type_plural $o_object_type_plural { + + if [empty_string_p $object_name] { + set object_name "Unnamed $object_type" + } + + if {($last_publisher_id != $publisher_id) && ![empty_string_p $last_publisher_id]} { + set mail_body [km_sweeper_nephew_objects_mail $community_id $time $sweeper_action $uncle_object_type $uncle_name $uncle_id $uncle_author $outdated_nephew_list $object_list] + + db_dml uncle_with_nephews_outdated_publisher { + insert into km_sweeper_publisher (user_id, package_id, object_type_id, object_id, object_name, content) + values (:publisher_id, :context_id, :uncle_object_type_id, :uncle_id, :uncle_name, :mail_body) + } + + set last_object_type_id "" + set outdated_nephew_list "" + } + if {$last_object_type_id != $object_type_id} { + append outdated_nephew_list "\n\n$object_type_plural:" + set last_object_type_id $object_type_id + set last_publisher_id $publisher_id + } + append outdated_nephew_list "\n$object_name ([ad_url]/o/$object_id)" + } + if ![empty_string_p $outdated_nephew_list] { + + set mail_body [km_sweeper_nephew_objects_mail $community_id $time $sweeper_action $uncle_object_type $uncle_name $uncle_id $uncle_author $outdated_nephew_list $object_list] + + db_dml uncle_with_nephews_outdated_publisher { + insert into km_sweeper_publisher (user_id, package_id, object_type_id, object_id, object_name, content) + values (:publisher_id, :context_id, :uncle_object_type_id, :uncle_id, :uncle_name, :mail_body) + } + } + + unset o_object_id + unset o_object_type_id + unset o_publisher_id + unset o_object_name + unset o_object_type + unset o_object_type_plural + } + + ## get all other descendants with different publisher + ## and send them email + set last_publisher_id "" + set last_object_type_id "" + set descendants_list "" + set count 0 + + db_foreach get_all_other_public_descendants_other_publisher " + select o.object_id, o.object_type_id, o.publisher_id, + o.one_line_description as object_name, + ot.pretty_plural as object_type_plural, + ot.pretty_name as object_type + from sn_objects o, sn_object_types ot, km_flat_object_hierarchy foh + where ot.object_type_id = o.object_type_id + and o.publisher_id is not null + and o.publisher_id <> :uncle_author_id + and o.publisher_id not in (select distinct o2.publisher_id + from sn_objects o2 + where o2.object_id in ([join $nephew_ids ,])) + and o.publisher_id not in (select distinct o2.original_author_id + from sn_objects o2, km_flat_object_hierarchy foh2 + where foh2.child = o2.object_id + and foh2.parent = :uncle_id + and $archive_sql2) + and o.public_p = 't' + and foh.parent = :uncle_id + and o.object_id = foh.child + and o.object_id not in ([join $nephew_ids ,]) + order by o.publisher_id, o.object_type_id + " { + lappend o_object_id $object_id + lappend o_object_type_id $object_type_id + lappend o_publisher_id $publisher_id + lappend o_object_name $object_name + lappend o_object_type_plural $object_type_plural + lappend o_object_type $object_type + incr count + } + + if {$count>0} { + foreach object_id $o_object_id object_type_id $o_object_type_id \ + publisher_id $o_publisher_id object_name $o_object_name \ + object_type $o_object_type \ + object_type_plural $o_object_type_plural { + + if [empty_string_p $object_name] { + set object_name "Unnamed $object_type" + } + + if {($last_publisher_id != $publisher_id) && ![empty_string_p $last_publisher_id]} { + set mail_body [km_uncles_descendant_objects_mail $community_id $time $sweeper_action $uncle_object_type $uncle_name $uncle_id $uncle_author $nephew_list $descendants_list] + + db_dml uncle_with_nephews_outdated_publisher { + insert into km_sweeper_publisher (user_id, package_id, object_type_id, object_id, object_name, content) + values (:publisher_id, :context_id, :uncle_object_type_id, :uncle_id, :uncle_name, :mail_body) + } + set last_object_type_id "" + set descendants_list "" + } + if {$last_object_type_id != $object_type_id} { + append descendants_list "\n\n$object_type_plural:" + set last_object_type_id $object_type_id + set last_publisher_id $publisher_id + } + append descendants_list "\n$object_name ([ad_url]/o/$object_id)" + } + if ![empty_string_p $descendants_list] { + + set mail_body [km_uncles_descendant_objects_mail $community_id $time $sweeper_action $uncle_object_type $uncle_name $uncle_id $uncle_author $nephew_list $descendants_list] + + db_dml uncle_with_nephews_outdated_publisher { + insert into km_sweeper_publisher (user_id, package_id, object_type_id, object_id, object_name, content) + values (:publisher_id, :context_id, :uncle_object_type_id, :uncle_id, :uncle_name, :mail_body) + } + } + + unset o_object_id + unset o_object_type_id + unset o_publisher_id + unset o_object_name + unset o_object_type + unset o_object_type_plural + } + + ## now finally unpublish / archive the uncle and all descendants + ########## + if {[string equal $sweeper_action "archive"]} { + foreach nephew_id $nephew_ids { + km_object_archive $nephew_id "object $time, archived by sweeper" + } + km_object_archive $uncle_id "linked objects $time, archived by sweeper" + } else { + km_object_unpublish $uncle_id + } + } + } + + ################# + ## deal with outdated parent objects + ################# + set outdated_parents [db_list get_outdated_parent_objects " + select foh.parent + from km_flat_object_hierarchy foh, sn_objects o, sn_object_types ot + where foh.parent = o.object_id + and o.public_p = 't' + and o.archived_p = 'f' + and o.expiration_date > sysdate + and ot.object_type_id = o.object_type_id + and ot.sweeper = :time + and $time_sql + order by distance desc + "] + + foreach outdated_parent $outdated_parents { + # check if object is still public and get object data + # loop over children, order by object_type + # append children to email + # loop over children with different owner, order by owner, object type + # if different child owner -> send email + # unpublish children, unpublish parent + + db_1row get_outdated_parent_object_data { + select o.object_id as parent_id, o.object_type_id as parent_object_type_id, + o.one_line_description as parent_name, ot.sweeper_action, + ot.pretty_name as parent_object_type, o.public_p, o.archived_p, + u.email as parent_author_email, u.user_id as parent_author_id, + u.first_names || ' ' || u.last_name as parent_author, + trunc(sysdate - o.last_modified) as days_unchanged, + o.context_id, ci.community_id, + o.publisher_id as parent_publisher_id + from sn_objects o, sn_object_types ot, users u, + sn_community_instances ci + where ot.object_type_id = o.object_type_id + and u.user_id = o.original_author_id + and o.object_id = :outdated_parent + and ci.package_id = o.context_id + } + + if [empty_string_p $parent_name] { + set parent_name "Unnamed $parent_object_type" + } + + ## if parent of this object already got private, so did this object, so check + ## if it's still public + if {$public_p == "t" && $archived_p == "f"} { + + ## create list of all children to be made private for the email to + ## the owner of the parent + set last_object_type_id "" + set object_list "" + + if {[string equal $sweeper_action "archive"]} { + ## we have to archive all children, as long as they can + ## be archived (=> cut the tree off at this point) + set sql "( select o2.object_id + from km_flat_object_hierarchy foh, sn_objects o2, sn_object_types ot2 + where foh.parent = :parent_id + and foh.child = o2.object_id + and o2.archived_p = 'f' + and o2.object_type_id = ot2.object_type_id + and ot2.archive_p = 't' ) + minus + ( select child as object_id + from km_flat_object_hierarchy + where parent in (select o2.object_id + from km_flat_object_hierarchy foh, sn_objects o2, + sn_object_types ot2 + where foh.parent = :parent_id + and foh.child = o2.object_id + and o2.archived_p = 'f' + and o2.object_type_id = ot2.object_type_id + and ot2.archive_p = 'f') )" + + set sql "select o.object_id, o.object_type_id, + o.one_line_description as object_name, + ot.pretty_plural as object_type_plural, + ot.pretty_name as object_type, o.publisher_id + from sn_objects o, sn_object_types ot + where ot.object_type_id = o.object_type_id + and o.object_id in ($sql) + order by o.object_type_id" + } else { + ## we have to make all children private + set sql "select o.object_id, o.object_type_id, + o.one_line_description as object_name, + ot.pretty_plural as object_type_plural, + ot.pretty_name as object_type, o.publisher_id + from sn_objects o, sn_object_types ot, km_flat_object_hierarchy foh + where ot.object_type_id = o.object_type_id + and o.public_p = 't' + and foh.parent = :parent_id + and o.object_id = foh.child + order by o.object_type_id" + } + + set child_list [list] + db_foreach get_all_children_of_parent $sql { + if [empty_string_p $object_name] { + set object_name "Unnamed $object_type" + } + + if {$last_object_type_id != $object_type_id} { + append object_list "\n$object_type_plural: $object_name" + } else { + append object_list ", $object_name" + } + set last_object_type_id $object_type_id + lappend child_list $object_id + } + + + ## send email to object owner + if {![llength $child_list]} { + ## so there are no children that will be put in the archive + ## so treat the parent as a single object + set mail_body [km_sweeper_single_objects_mail $community_id $time $sweeper_action $parent_object_type $parent_name $parent_id $days_unchanged] + + db_dml object_without_children_outdated { + insert into km_sweeper (user_id, package_id, object_type_id, object_id, object_name, content) + values (:parent_author_id, :context_id, :parent_object_type_id, :parent_id, :parent_name, :mail_body) + } + + if {![empty_string_p $parent_publisher_id] && $parent_publisher_id != $parent_author_id} { + db_dml object_without_children_outdated { + insert into km_sweeper_publisher (user_id, package_id, object_type_id, object_id, object_name, content) + values (:parent_publisher_id, :context_id, :parent_object_type_id, :parent_id, :parent_name, :mail_body) + } + } + + } else { + ## so there are actually children + set mail_body [km_sweeper_object_with_children_mail $community_id $time $sweeper_action $parent_object_type $parent_name $parent_id $days_unchanged $object_list] + + db_dml object_with_children_outdated { + insert into km_sweeper (user_id, package_id, object_type_id, object_id, object_name, content) + values (:parent_author_id, :context_id, :parent_object_type_id, :parent_id, :parent_name, :mail_body) + } + + if {![empty_string_p $parent_publisher_id] && $parent_publisher_id != $parent_author_id} { + db_dml object_with_children_outdated_publisher { + insert into km_sweeper_publisher (user_id, package_id, object_type_id, object_id, object_name, content) + values (:parent_publisher_id, :context_id, :parent_object_type_id, :parent_id, :parent_name, :mail_body) + } + } + + set last_author_id "" + set last_object_type_id "" + set object_list "" + set count 0 + + ## if children owner is not the same as parent owner, sent him + ## an email + ############# + db_foreach get_all_children_of_parent_other_owner " + select o.object_id, o.object_type_id, o.original_author_id as author_id, + o.one_line_description as object_name, + ot.pretty_plural as object_type_plural, + ot.pretty_name as object_type + from sn_objects o, sn_object_types ot + where ot.object_type_id = o.object_type_id + and o.original_author_id <> :parent_author_id + and o.object_id in ([join $child_list ,]) + order by o.original_author_id, o.object_type_id + " { + lappend o_object_id $object_id + lappend o_object_type_id $object_type_id + lappend o_author_id $author_id + lappend o_object_name $object_name + lappend o_object_type_plural $object_type_plural + lappend o_object_type $object_type + incr count + } + + if {$count>0} { + foreach object_id $o_object_id object_type_id $o_object_type_id \ + author_id $o_author_id object_name $o_object_name \ + object_type $o_object_type \ + object_type_plural $o_object_type_plural { + + if [empty_string_p $object_name] { + set object_name "Unnamed $object_type" + } + + if {($last_author_id != $author_id) && ![empty_string_p $last_author_id]} { + set mail_body [km_sweeper_child_object_mail $community_id $time $sweeper_action $parent_object_type $parent_name $parent_id $parent_author $days_unchanged $object_list] + + db_dml child_objects_outdated { + insert into km_sweeper (user_id, package_id, object_type_id, object_id, object_name, content) + values (:author_id, :context_id, :parent_object_type_id, :parent_id, :parent_name, :mail_body) + } + set last_object_type_id "" + set object_list "" + } + if {$last_object_type_id != $object_type_id} { + append object_list "\n\n$object_type_plural:" + set last_object_type_id $object_type_id + set last_author_id $author_id + } + append object_list "\n$object_name ([ad_url]/o/$object_id)" + } + if ![empty_string_p $object_list] { + set mail_body [km_sweeper_child_object_mail $community_id $time $sweeper_action $parent_object_type $parent_name $parent_id $parent_author $days_unchanged $object_list] + + db_dml child_objects_outdated { + insert into km_sweeper (user_id, package_id, object_type_id, object_id, object_name, content) + values (:author_id, :context_id, :parent_object_type_id, :parent_id, :parent_name, :mail_body) + } + } + + unset o_object_id + unset o_object_type_id + unset o_author_id + unset o_object_name + unset o_object_type + unset o_object_type_plural + } + + set last_publisher_id "" + set last_object_type_id "" + set object_list "" + set count 0 + + ## if children publisher is not the same as of parent, sent him + ## an email + ############# + if {[empty_string_p $parent_publisher_id]} { + set parent_publisher_id 0 + } + db_foreach get_all_children_of_parent_other_publisher " + select o.object_id, o.object_type_id, + o.one_line_description as object_name, + ot.pretty_plural as object_type_plural, + ot.pretty_name as object_type, o.publisher_id + from sn_objects o, sn_object_types ot + where ot.object_type_id = o.object_type_id + and o.publisher_id <> :parent_publisher_id + and o.publisher_id <> :parent_author_id + and o.publisher_id is not null + and o.object_id in ([join $child_list ,]) + and o.publisher_id not in (select distinct o2.original_author_id + from sn_objects o2 + where o2.object_id in ([join $child_list ,])) + order by o.publisher_id, o.object_type_id + " { + lappend o_object_id $object_id + lappend o_object_type_id $object_type_id + lappend o_publisher_id $publisher_id + lappend o_object_name $object_name + lappend o_object_type_plural $object_type_plural + lappend o_object_type $object_type + incr count + } + + if {$count>0} { + foreach object_id $o_object_id object_type_id $o_object_type_id \ + publisher_id $o_publisher_id object_name $o_object_name \ + object_type $o_object_type \ + object_type_plural $o_object_type_plural { + + if [empty_string_p $object_name] { + set object_name "Unnamed $object_type" + } + + if {($last_publisher_id != $publisher_id) && ![empty_string_p $last_publisher_id]} { + set mail_body [km_sweeper_child_object_mail $community_id $time $sweeper_action $parent_object_type $parent_name $parent_id $parent_author $days_unchanged $object_list] + + db_dml child_objects_outdated_publisher { + insert into km_sweeper_publisher (user_id, package_id, object_type_id, object_id, object_name, content) + values (:publisher_id, :context_id, :parent_object_type_id, :parent_id, :parent_name, :mail_body) + } + set last_object_type_id "" + set object_list "" + } + if {$last_object_type_id != $object_type_id} { + append object_list "\n\n$object_type_plural:" + set last_object_type_id $object_type_id + set last_publisher_id $publisher_id + } + append object_list "\n$object_name ([ad_url]/o/$object_id)" + } + if ![empty_string_p $object_list] { + set mail_body [km_sweeper_child_object_mail $community_id $time $sweeper_action $parent_object_type $parent_name $parent_id $parent_author $days_unchanged $object_list] + + db_dml child_objects_outdated_publisher { + insert into km_sweeper_publisher (user_id, package_id, object_type_id, object_id, object_name, content) + values (:publisher_id, :context_id, :parent_object_type_id, :parent_id, :parent_name, :mail_body) + } + } + + unset o_object_id + unset o_object_type_id + unset o_publisher_id + unset o_object_name + unset o_object_type + unset o_object_type_plural + } + } + + ## now finally archive/publish the objects + if {[string equal $sweeper_action "archive"]} { + km_object_archive $parent_id "object $time, archived by sweeper" + } else { + km_object_unpublish $parent_id + } + } + } + + ################ + ## now process the single objects + ################ + set count 0 + db_foreach get_outdated_single_objects " + select o.object_id, o.object_type_id, o.one_line_description as object_name, + ot.pretty_name as object_type, o.original_author_id, o.context_id, + ot.sweeper_action, trunc(sysdate - o.last_modified) as days_unchanged, + ci.community_id, o.publisher_id + from sn_objects o, sn_object_types ot, sn_community_instances ci + where ot.object_type_id = o.object_type_id + and o.public_p = 't' + and o.archived_p = 'f' + and o.expiration_date > sysdate + and ot.sweeper = :time + and $time_sql + and ci.package_id = o.context_id + " { + lappend o_object_id $object_id + lappend o_object_type_id $object_type_id + lappend o_object_name $object_name + lappend o_object_type $object_type + lappend o_original_author_id $original_author_id + lappend o_context_id $context_id + lappend o_sweeper_action $sweeper_action + lappend o_days_unchanged $days_unchanged + lappend o_community_id $community_id + lappend o_publisher_id $publisher_id + incr count + } + + if {$count>0} { + foreach object_id $o_object_id object_type_id $o_object_type_id \ + object_name $o_object_name object_type $o_object_type \ + original_author_id $o_original_author_id context_id $o_context_id \ + sweeper_action $o_sweeper_action days_unchanged $o_days_unchanged \ + community_id $o_community_id publisher_id $o_publisher_id { + + if [empty_string_p $object_name] { + set object_name "Unnamed $object_type" + } + + set mail_body [km_sweeper_single_objects_mail $community_id $time $sweeper_action $object_type $object_name $object_id $days_unchanged] + + db_dml single_object_outdated { + insert into km_sweeper (user_id, package_id, object_type_id, object_id, object_name, content) + values (:original_author_id, :context_id, :object_type_id, :object_id, :object_name, :mail_body) + } + + if {![empty_string_p $publisher_id] && $publisher_id != $original_author_id} { + db_dml single_object_outdated_publisher { + insert into km_sweeper_publisher (user_id, package_id, object_type_id, object_id, object_name, content) + values (:publisher_id, :context_id, :object_type_id, :object_id, :object_name, :mail_body) + } + } + + if {[string equal $sweeper_action "archive"]} { + km_object_archive $object_id "object $time, archived by sweeper" + } else { + km_object_unpublish $object_id + } + } + + unset o_object_id + unset o_object_type_id + unset o_object_name + unset o_object_type + unset o_original_author_id + unset o_context_id + unset o_sweeper_action + unset o_days_unchanged + unset o_community_id + unset o_publisher_id + } + + ########################### + ## now send all the email, one per user, ordered by object_type + ########################### + set mail "" + set last_user_id "" + set last_user_email "" + set last_community_id "" + set last_package_id "" + set last_object_type_id "" + set count 0 + db_foreach get_mail_bodies_per_user { + select u.user_id, u.email as user_email, s.content as mail_body, + ot.object_type_id, ot.pretty_plural as object_type, + p.instance_name as package_name, s.package_id, + p2.instance_name as community_name, ci.community_id + from km_sweeper s, users u, sn_object_types ot, + sn_community_instances ci, apm_packages p, apm_packages p2 + where u.user_id = s.user_id + and s.object_type_id = ot.object_type_id + and ci.package_id = s.package_id + and p.package_id = s.package_id + and p2.package_id = ci.community_id + order by s.user_id, p2.instance_name, p.instance_name, + ot.pretty_plural, s.object_name + } { + lappend o_user_id $user_id + lappend o_user_email $user_email + lappend o_mail_body $mail_body + lappend o_object_type_id $object_type_id + lappend o_object_type $object_type + lappend o_package_name $package_name + lappend o_package_id $package_id + lappend o_community_name $community_name + lappend o_community_id $community_id + incr count + } + + if {$count>0} { + foreach user_id $o_user_id user_email $o_user_email \ + mail_body $o_mail_body object_type_id $o_object_type_id \ + object_type $o_object_type package_name $o_package_name \ + package_id $o_package_id community_name $o_community_name \ + community_id $o_community_id { + + if {($last_user_id != $user_id) && ![empty_string_p $last_user_id]} { + set replacement_list \ + [list \ + type $time \ + mail_body $mail \ + recipient $last_user_email] + + et_queue_email [et_process "km_sweeper" $replacement_list] + set last_user_id "" + set last_user_email "" + set last_community_id "" + set last_package_id "" + set last_object_type_id "" + set mail "" + } + if {$last_community_id != $community_id} { + append mail "Community: $community_name\n===========\n\n" + set last_community_id $community_id + } + if {$last_package_id != $package_id} { + append mail "$package_name:\n===========\n\n" + set last_package_id $package_id + } + if {$last_object_type_id != $object_type_id} { + append mail "$object_type:\n===========\n\n" + set last_object_type_id $object_type_id + } + append mail "$mail_body\n---------------\n\n" + set last_user_id $user_id + set last_user_email $user_email + } + if ![empty_string_p $mail] { + set replacement_list \ + [list \ + type $time \ + mail_body $mail \ + recipient $user_email] + + et_queue_email [et_process "km_sweeper" $replacement_list] + } + + unset o_user_id + unset o_user_email + unset o_mail_body + unset o_object_type_id + unset o_object_type + unset o_package_name + unset o_package_id + unset o_community_name + unset o_community_id + } + + ########################### + ## now send the email to object publisher + ## one per user, ordered by object_type + ########################### + set mail "" + set last_publisher_id "" + set last_publisher_email "" + set last_community_id "" + set last_package_id "" + set last_object_type_id "" + set count 0 + db_foreach get_mail_bodies_per_publisher { + select u.user_id as publisher_id, u.email as publisher_email, + s.content as mail_body, ot.object_type_id, + ot.pretty_plural as object_type, p.instance_name as package_name, + s.package_id, p2.instance_name as community_name, ci.community_id + from km_sweeper_publisher s, users u, sn_object_types ot, + sn_community_instances ci, apm_packages p, apm_packages p2 + where u.user_id = s.user_id + and s.object_type_id = ot.object_type_id + and ci.package_id = s.package_id + and p.package_id = s.package_id + and p2.package_id = ci.community_id + order by u.user_id, p2.instance_name, p.instance_name, + ot.pretty_plural, s.object_name + } { + lappend o_publisher_id $publisher_id + lappend o_publisher_email $publisher_email + lappend o_mail_body $mail_body + lappend o_object_type_id $object_type_id + lappend o_object_type $object_type + lappend o_package_name $package_name + lappend o_package_id $package_id + lappend o_community_name $community_name + lappend o_community_id $community_id + incr count + } + + if {$count>0} { + foreach publisher_id $o_publisher_id publisher_email $o_publisher_email \ + mail_body $o_mail_body object_type_id $o_object_type_id \ + object_type $o_object_type package_name $o_package_name \ + package_id $o_package_id community_name $o_community_name \ + community_id $o_community_id { + + if {($last_publisher_id != $publisher_id) && ![empty_string_p $last_publisher_id]} { + set replacement_list \ + [list \ + type $time \ + mail_body $mail \ + recipient $last_publisher_email] + + et_queue_email [et_process "km_sweeper_publisher" $replacement_list] + set last_publisher_id "" + set last_publisher_email "" + set last_community_id "" + set last_package_id "" + set last_object_type_id "" + set mail "" + } + if {$last_community_id != $community_id} { + append mail "Community: $community_name\n===========\n\n" + set last_community_id $community_id + } + if {$last_package_id != $package_id} { + append mail "$package_name:\n===========\n\n" + set last_package_id $package_id + } + if {$last_object_type_id != $object_type_id} { + append mail "$object_type:\n===========\n\n" + set last_object_type_id $object_type_id + } + append mail "$mail_body\n---------------\n\n" + set last_publisher_id $publisher_id + set last_publisher_email $publisher_email + } + if ![empty_string_p $mail] { + set replacement_list \ + [list \ + type $time \ + mail_body $mail \ + recipient $publisher_email] + + et_queue_email [et_process "km_sweeper_publisher" $replacement_list] + } + + unset o_publisher_id + unset o_publisher_email + unset o_mail_body + unset o_object_type_id + unset o_object_type + unset o_package_name + unset o_package_id + unset o_community_name + unset o_community_id + } + + ############## + ## now cleanup: delete temp tables + ############## + db_dml km_sweeper_cleanup { + delete from km_sweeper + } + db_dml km_sweeper_publisher_cleanup { + delete from km_sweeper_publisher + } +## end of transaction +} +} + + +ad_proc km_sweeper_uncle_with_nephews_mail { community_id time action object_type object_name object_id nephew_list object_list } { +} { + set template "km_sweeper_uncle_$action\_$time" + set replace_list [list \ + ad_url [ad_url] \ + object_type $object_type \ + object_name $object_name \ + object_id $object_id \ + object_list $object_list \ + nephew_list $nephew_list] + set result [et_process -community_id $community_id $template $replace_list] + + return [ns_set get $result body] +} + + +ad_proc km_sweeper_nephew_objects_mail { community_id time action object_type object_name object_id object_author nephew_list object_list } { +} { + set template "km_sweeper_nephew_$action\_$time" + set replace_list [list \ + ad_url [ad_url] \ + object_type $object_type \ + object_name $object_name \ + object_id $object_id \ + object_author $object_author \ + object_list $object_list \ + nephew_list $nephew_list] + set result [et_process -community_id $community_id $template $replace_list] + + return [ns_set get $result body] +} + + +ad_proc km_uncles_descendant_objects_mail { community_id time action object_type object_name object_id object_author nephew_list object_list } { +} { + set template "km_sweeper_descendants_$action\_$time" + set replace_list [list \ + ad_url [ad_url] \ + object_type $object_type \ + object_name $object_name \ + object_id $object_id \ + object_author $object_author \ + object_list $object_list \ + nephew_list $nephew_list] + set result [et_process -community_id $community_id $template $replace_list] + + return [ns_set get $result body] +} + + +ad_proc km_sweeper_object_with_children_mail { community_id time action object_type object_name object_id days_unchanged object_list } { +} { + set template "km_sweeper_parent_$action\_$time" + set replace_list [list \ + ad_url [ad_url] \ + object_type $object_type \ + object_name $object_name \ + object_id $object_id \ + object_list $object_list] + if {[string equal $time "outdated"]} { + lappend replace_list days_unchanged $days_unchanged + } + set result [et_process -community_id $community_id $template $replace_list] + + return [ns_set get $result body] +} + + +ad_proc km_sweeper_child_object_mail { community_id time action object_type object_name object_id object_author days_unchanged object_list } { +} { + set template "km_sweeper_child_$action\_$time" + set replace_list [list \ + ad_url [ad_url] \ + object_type $object_type \ + object_name $object_name \ + object_id $object_id \ + object_author $object_author \ + object_list $object_list] + if {[string equal $time "outdated"]} { + lappend replace_list days_unchanged $days_unchanged + } + set result [et_process -community_id $community_id $template $replace_list] + + return [ns_set get $result body] +} + + +ad_proc km_sweeper_single_objects_mail { community_id time action object_type object_name object_id days_unchanged } { +} { + set template "km_sweeper_single_$action\_$time" + set replace_list [list \ + ad_url [ad_url] \ + object_type $object_type \ + object_name $object_name \ + object_id $object_id] + if {[string equal $time "outdated"]} { + lappend replace_list days_unchanged $days_unchanged + } + set result [et_process -community_id $community_id $template $replace_list] + + return [ns_set get $result body] +} + + +ad_proc km_sweeper_single_objects_warning_mail { time action object_type object_name object_id days_unchanged days_untill_change } { +} { + set template "km_warn_sweeper_$action\_$time" + set replace_list [list \ + ad_url [ad_url] \ + object_type $object_type \ + object_name $object_name \ + object_id $object_id \ + days_untill_change $days_untill_change] + if {[string equal $time "outdated"]} { + lappend replace_list days_unchanged $days_unchanged + } + set result [et_process -community_id 0 $template $replace_list] + + return [ns_set get $result body] +} + + +ad_proc km_copy_object { object_id target_id } { + copies the object object_id to the new object target_id. + copies only active questions and no parent-child/uncle-nephew questions +} { + set user_id [ad_conn user_id] + set package_id [ad_conn package_id] + set ip_addr [ns_conn peeraddr] + + db_1row get_object_name { + select one_line_description as object_name, object_type_id + from sn_objects + where object_id = :object_id + } + set object_type [km_static object_type_pretty_name $object_type_id] + if [empty_string_p $object_name] { + set object_name "Unnamed $object_type" + } + set msg "Copied from $object_type \"$object_name\"" + + db_transaction { + set target_id [db_exec_plsql create_object { + begin + :1 := object.copy_object ( + v_object_id => :object_id, + v_target_id => :target_id, + v_creation_user => :user_id, + v_creation_ip => :ip_addr, + v_context_id => :package_id + ); + end; + }] + + db_exec_plsql grant_owner_permissions { + begin + acs_permission.grant_permission(:target_id, :user_id, 'read'); + acs_permission.grant_permission(:target_id, :user_id, 'write'); + acs_permission.grant_permission(:target_id, :user_id, 'delete'); + end; + } + + db_dml add_audit_entry { + insert into sn_audit_table + (object_id, question_id, last_modified, last_modifying_user_id, + content) + values + (:target_id, null, sysdate, :user_id, :msg) + } + } + + return $target_id +} + +ad_proc km_clean_sweeper_tmp_table { } { + Deletes all old data from sweepers temp table in the event that the sweeper + didn't finish. +} { + db_dml km_sweeper_cleanup { + delete from km_sweeper + } + db_dml km_sweeper_publisher_cleanup { + delete from km_sweeper_publisher + } +} Index: openacs-4/contrib/obsolete-packages/library/tcl/km-users-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/tcl/km-users-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/tcl/km-users-procs.tcl 2 Jul 2003 12:19:41 -0000 1.1 @@ -0,0 +1,82 @@ +# /tcl/km-users.tcl +# User centric knowledge management. +# (My Objects, User Contributions, etc.) +# +# Created by carsten@arsdigita.com in June 2000 +# +# $Id: km-users-procs.tcl,v 1.1 2003/07/02 12:19:41 peterm Exp $ + +proc_doc km_workspace_toolbar {object_id {category_id ""} {child_p 0}} { + + Show a toolbar to allow the user to add an object to his workspace + or list of alerts, or send it to a colleague. + +} { + set user_id [ad_conn user_id] + set original_author_id [km_conn original_author_id] + + if { $user_id != $original_author_id } { + set parameters "[export_url_vars object_id category_id]&return_url=[ns_urlencode "object-view?[export_url_vars object_id category_id]"]" + + } + + # Always allow the user to send the page to a colleague. + + set page_url "[ns_conn url]?[export_ns_set_vars url {path_id}]" + set return_title [km_conn object_name] + + lappend result "Send this page to a colleague" + + if { $user_id != $original_author_id && [km_conn public_p] && ![km_conn archived_p] } { + lappend result "Give Feedback" + } + + set object_type_id [km_conn object_type_id] + set object_type [util_quotehtml [km_static object_type_pretty_name $object_type_id]] + set copy_p [km_static object_type_copy_p $object_type_id] + set create_p [km_conn create_p] + set write_p [km_conn write_p] + if {![km_static object_type_create_p $object_type_id]} { + set create_p 0 + } + + if {$create_p && !$child_p} { + lappend result "Create new $object_type" + } + + if {$write_p && $copy_p && $create_p} { + lappend result "Copy this $object_type" + } + + return [join $result " | "] +} + +proc_doc km_list_user_searches {user_id} { + + Returns a list of the searches the user has done in the past. + Each row looks like this: name url_params + +} { + set result [db_list_of_lists km_list_user_searches " + select name, url_params from km_library_searches + where user_id=:user_id + and name is not null"] + + return $result +} + +proc_doc km_user_info {user_id} { + + Given an user_id, returns a list with + full name, email, affiliation, work phone, country + +} { + set result [km_db_1row_to_list km_user_info " + select first_names || ' ' || last_name, email + from users u + where u.user_id=$user_id"] + return $result +} + + + Index: openacs-4/contrib/obsolete-packages/library/tcl/library-init.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/tcl/library-init.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/tcl/library-init.tcl 2 Jul 2003 12:19:41 -0000 1.1 @@ -0,0 +1,69 @@ +# packages/library/tcl/library-init.tcl +# +# $Id: library-init.tcl,v 1.1 2003/07/02 12:19:41 peterm Exp $ + +proc_doc excursion_timeout {} { + + Returns the amount of time in hours that an excursion exists + before being timed out. + +} { + return 120 +} + +proc purge_old_paths {} { + set timeout [expr [excursion_timeout]/24] + db_dml purge_old_paths { + delete from km_path + where sysdate - start_time > :timeout + } +} + +proc reset_access_counts_monthly {} { + if {[ns_fmttime [ns_time] "%e"] == 1} { + ns_log Notice "resetting access_month counts to 0" + db_dml reset_access_counts_monthly { + update sn_objects + set access_month = 0 + where access_month <> 0 + } + } +} + +if { ([server_cluster_enabled_p] && [ad_canonical_server_p]) || ![server_cluster_enabled_p]} { + # Register sn_object with the bookmarks module, if it's present. + ad_call_proc_if_exists bookmarks::register_type "sn_object" + ad_call_proc_if_exists yp::register_type "sn_object" + + # Do the same for incentives. + ad_call_proc_if_exists incentives::register_charge_category \ + -key_usage key_with_default \ + kl_rating_give library "Object feedback given" + ad_call_proc_if_exists incentives::register_charge_category \ + -key_usage key_with_default \ + -value_meaning factor \ + kl_rating_receive library "Object feedback received" + ad_call_proc_if_exists incentives::register_charge_category \ + -key_usage key_with_default \ + kl_object_publish library "Objects published" + + # Register library as a module which can be used in communities. + ad_call_proc_if_exists sn_community::register_package library library f f + + # Register library as a module using category trees + ad_call_proc_if_exists categories::register_package library +} + +# Register sweeper proc for outdated knowledge objects +ad_schedule_daily -thread t 3 17 km_sweeper_daily + +ad_schedule_proc -once t 10 reset_access_counts_monthly + +# clear sweeper tmp table if sweeper didn't finish +ad_schedule_daily 21 0 km_clean_sweeper_tmp_table + +#schedule emails for workflow tasks +nsv_set library library_notifications_p 0 +ad_schedule_proc -thread t 300 library_approval_process_notifications + +ad_schedule_daily -thread t 3 15 purge_old_paths Index: openacs-4/contrib/obsolete-packages/library/wf-templates/clarify.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/wf-templates/clarify.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/wf-templates/clarify.adp 2 Jul 2003 12:19:45 -0000 1.1 @@ -0,0 +1,6 @@ +
      +
    1. Hit 'Start task' +
    2. Clarify the Knowledge Object. Click here to look at it +
    3. Hit 'Task done' +
    \ No newline at end of file Index: openacs-4/contrib/obsolete-packages/library/wf-templates/object-info.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/wf-templates/object-info.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/wf-templates/object-info.adp 2 Jul 2003 12:19:45 -0000 1.1 @@ -0,0 +1,2 @@ +@object_name@ + Index: openacs-4/contrib/obsolete-packages/library/wf-templates/object-info.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/wf-templates/object-info.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/wf-templates/object-info.tcl 2 Jul 2003 12:19:45 -0000 1.1 @@ -0,0 +1,39 @@ +# /packages/ticket-tracker/wf-templates/ticket-info.tcl + +ad_page_contract { + Return info about an object. + + @author Dirk Gomez (sharenet@dirkgomez.de) + @author Timo Hentschel (timo@arsdigita.com) + @creation-date 2002-02-27 + @cvs-id $Id: object-info.tcl,v 1.1 2003/07/02 12:19:45 peterm Exp $ +} + +# task is one of the datasources specified in the tag in /packages/acs-workflow/www/task.adp +set object_id $task(object_id) + +if { ![db_0or1row get_object_info " + select o.object_type_id, o.one_line_description as object_name, + decode(o.public_p,'t',1,0) as public_p, + o.original_author_id, u.first_names || ' ' || u.last_name as original_author_name, + u.email as original_author_email + from sn_objects o, users u + where o.object_id = :object_id + and u.user_id = o.original_author_id +"] } { + # Error: The object does not exist. + + if { $print_errors_p } { + ad_return_exception_page 404 "Entry does not exist." " + The entry with id $object_id does not exist. + We never really delete object IDs from the database so this is quite + unusual. Unless you tried to hack the URL manually this might be a bug + in our software." + } + return 0 +} + +set pretty_type [km_static object_type_pretty_name $object_type_id] +set pretty_type_plural [km_static object_type_pretty_plural $object_type_id] +set stripped_name [sn_striphtml $object_name] +set object_name [km_get_object_name $object_id] Index: openacs-4/contrib/obsolete-packages/library/wf-templates/review.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/wf-templates/review.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/wf-templates/review.adp 2 Jul 2003 12:19:45 -0000 1.1 @@ -0,0 +1,6 @@ +
      +
    1. Hit 'Start task +
    2. Check to see if the object needs to be clarified. Click here to look at it +
    3. Select the appropriate answer, add a comment and hit 'Task done' +
    Index: openacs-4/contrib/obsolete-packages/library/wf-templates/verify.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/wf-templates/verify.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/wf-templates/verify.adp 2 Jul 2003 12:19:45 -0000 1.1 @@ -0,0 +1,7 @@ +
      +
    1. Hit 'Start task' +
    2. Verify that the result is as you expected. +
    3. If it is, select 'yes' at the right. +
    4. If not, select 'no' at the right. +
    5. Hit 'Task done' +
    \ No newline at end of file Index: openacs-4/contrib/obsolete-packages/library/www/add-sharenet-ref.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/add-sharenet-ref.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/add-sharenet-ref.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,52 @@ +ad_page_contract { + /www/library/add-sharenet-ref.tcl + + Called after the user has selected an existing or created a new + object. Appends a reference to this object to the question + associated with the current path. + + @cvs-id $Id: add-sharenet-ref.tcl,v 1.1 2003/07/02 12:19:42 peterm Exp $ +} { + path_id:notnull + object_id:notnull,integer +} +csrf::authenticate + +if ![path_valid_p $path_id] { + ad_return_error "Invalid Path" \ + "The current path ID is invalid. Perhaps you used your browser's Back button + and tried to press the Link button a second time?" + return +} + +set user_id [ad_maybe_redirect_for_registration] + + +# Determine to which object we are going to add the href, +# and if the current user is allowed to do this. + +set values [get_path_values -action_only_p 0 $path_id] +set original_object_id [value_from_tuples $values object_id] +set sub_object_id [value_from_tuples $values sub_object_id] + +if ![km_check_object_id -check_edit_p 1 $original_object_id] { return } + + +# OK, let's insert it. + +if [empty_string_p $sub_object_id] { + set question_id [value_from_tuples $values question_id] + set row_id $original_object_id +} else { + set question_id [value_from_tuples $values subquestion_id] + set row_id $sub_object_id +} + +km_append_object_content -html_p "t" $row_id $question_id \ + "[km_get_object_name $object_id]" + +km_check_public_status_after_edit $row_id + +# All done, back to the path's origin. + +ad_returnredirect [get_path_return_url $path_id] Index: openacs-4/contrib/obsolete-packages/library/www/add-web-ref-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/add-web-ref-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/add-web-ref-2.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,87 @@ +ad_page_contract { + /www/library/add-web-ref-2.tcl + + Verify Web or email reference, and append it to the column given as + part of the path. + + @cvs-id $Id: add-web-ref-2.tcl,v 1.1 2003/07/02 12:19:42 peterm Exp $ +} { + path_id:notnull,integer + url + url_title +} +csrf::authenticate + +if ![path_valid_p $path_id] { + ad_return_error "Invalid Path" \ + "The current path ID is invalid. Perhaps you used your browser's Back button + and tried to enter another Web/email reference?" + return +} + +set user_id [ad_maybe_redirect_for_registration] + +# Determine to which object we are going to add the href, +# and if the current user is allowed to do this. + +set values [get_path_values -action_only_p 0 $path_id] +set object_id [value_from_tuples $values object_id] +set sub_object_id [value_from_tuples $values sub_object_id] + + +# Check the user input. + +if ![km_check_object_id -check_edit_p 1 $object_id] { return } + +set examples " +
      +
    • A valid URL would be something like http://photo.net/philg/, +
    • A valid E-mail address would be something like: philg@mit.edu. +
    " + +set exception_count 0 +set exception_text "" + +if { ![empty_string_p $url] && ![util_url_valid_p $url] && ![util_email_valid_p $url] } { + # There is a URL or email, but it doesn't match our REGEXP. + + incr exception_count + append exception_text "
  • The text you entered: $url looks + neither like an URL nor like an E-mail address. + $examples + " +} + +if [empty_string_p $url] { + incr exception_count + append exception_text "
  • Please enter an URL or an E-mail address. + $examples" +} + +if { $exception_count > 0 } { + ad_return_complaint $exception_count $exception_text + return +} + +if [empty_string_p $url_title] { set url_title $url } +if [util_email_valid_p $url] { set url "mailto:$url" } + + +# OK, let's append it. + +if [empty_string_p $sub_object_id] { + set question_id [value_from_tuples $values question_id] +} else { + set question_id [value_from_tuples $values subquestion_id] + set object_id $sub_object_id +} + +km_append_object_content -html_p "t" $object_id $question_id "$url_title" + +km_check_public_status_after_edit $object_id + +# All done, back to the path's origin. + +ad_returnredirect [get_path_return_url $path_id] + + Index: openacs-4/contrib/obsolete-packages/library/www/add-web-ref.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/add-web-ref.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/add-web-ref.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,26 @@ + +@title;noquote@ + +
    + +@form_vars;noquote@ + + + + + +
    + +URL - example: http://dir.yahoo.com/Arts/
    +or E-mail address - example: bugs@microsoft.com
    + +

    +Title - + example: +Yahoo Arts page or Bill's E-mail address
    +(This text will be blue, underlined and clickable)
    + + +

    + + Index: openacs-4/contrib/obsolete-packages/library/www/add-web-ref.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/add-web-ref.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/add-web-ref.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,32 @@ +ad_page_contract { + /library/add-web-ref.tcl + + @cvs-id $Id: add-web-ref.tcl,v 1.1 2003/07/02 12:19:42 peterm Exp $ +} { + path_id:notnull,integer +} -properties { + title:onevalue + target:onevalue + form_vars:onevalue +} + +set return_url [get_path_return_url $path_id] +set user_id [ad_maybe_redirect_for_registration] + +# Determine to which object we are going to add the href, +# and if the current user is allowed to do this. + +set values [get_path_values -action_only_p 0 $path_id] +set object_id [value_from_tuples $values object_id] +set sub_object_id [value_from_tuples $values sub_object_id] +set category_id [value_from_tuples $values category_id] + +if ![km_check_object_id -check_edit_p 1 $object_id] { return } + +set title "Add a Web/Email Reference" +set_the_usual_klib_context_bar $object_id $category_id +append_context_bar_data [list $return_url "Edit"] "Web/Email Reference" +set target "add-web-ref-2" +set form_vars [export_form_vars path_id] + +ad_return_template Index: openacs-4/contrib/obsolete-packages/library/www/alert-categories.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/alert-categories.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/alert-categories.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,5 @@ + Index: openacs-4/contrib/obsolete-packages/library/www/alert-categories.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/alert-categories.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/alert-categories.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,9 @@ +ad_page_contract { + alerting. +} { + return_uri + category_id:integer + content_type_id:integer +} + +ad_return_template Index: openacs-4/contrib/obsolete-packages/library/www/alert-instance.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/alert-instance.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/alert-instance.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,3 @@ + Index: openacs-4/contrib/obsolete-packages/library/www/alert-instance.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/alert-instance.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/alert-instance.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,7 @@ +ad_page_contract { + alerting. +} { + return_uri +} + +ad_return_template Index: openacs-4/contrib/obsolete-packages/library/www/alert-types.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/alert-types.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/alert-types.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,4 @@ + Index: openacs-4/contrib/obsolete-packages/library/www/alert-types.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/alert-types.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/alert-types.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,10 @@ +ad_page_contract { + alerting. +} { + return_uri + object_type_id:integer +} + +if {![km_check_object_type_id $object_type_id]} { return } + +ad_return_template Index: openacs-4/contrib/obsolete-packages/library/www/alert.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/alert.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/alert.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,5 @@ + Index: openacs-4/contrib/obsolete-packages/library/www/alert.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/alert.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/alert.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,11 @@ +ad_page_contract { + alerting. +} { + return_uri + object_id:integer +} + +if {![km_check_object_id $object_id]} { return } + +set object_type_id [km_conn object_type_id] +ad_return_template Index: openacs-4/contrib/obsolete-packages/library/www/browse-one-category.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/browse-one-category.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/browse-one-category.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,144 @@ + +@title;noquote@ +@graphic@ +@graphic_width;noquote@ +@subsite_url;noquote@ +@subsite_name;noquote@ +@search_contexts;noquote@ + + + + + Number of objects in this category and it's subcategories (@total_num_objects@)

    + View items modified in the last @age_bar;noquote@ +

    + + + + + + + + + + + + +
    @categorization_widget_header.header_name@
    +
    +

    + +Number of objects that are not categorized by @pretty_question@ (@total_num_objects@)

    +

    View items modified in the last @age_bar;noquote@ + + + + + + + + + + + + +
    View: @object_view_bar_top_level;noquote@
    + + +
    Status:@archive_bar;noquote@
    Owner:@ownership_bar;noquote@
    Alphabet: [ + + + @alphabet.letter@ + + + @alphabet.letter@ + + ] +
    +

    No objects here. + + + + + + + + + + +
    View: @object_view_bar_top_level;noquote@
    + + +
    Status:@archive_bar;noquote@
    Owner:@ownership_bar;noquote@
    Sort: @object_sort_bar;noquote@
    Alphabet: [ + + + @alphabet.letter@ + + + @alphabet.letter@ + + ] +
    + +

    @pretty_type_plural;noquote@ + + @first_row@-@last_row@ of @num_displayed_objects@ + + (@num_displayed_objects@) +

    + + + (Note: When there are more than @category_display_limit@ objects found, + categories are not shown.) + + + No objects match your filters. + +
      + + +
    • + + [Private] + + + [Archived] + + + [In review] + + @object_list.object_name@ + by @object_list.user_link;noquote@ (@object_list.last_modified@) + + + (@object_list.access_total@ hits, @object_list.access_month@ this month) + + + + (@object_list.number_ratings@ user + ratings: average of: + @object_list.rating_avg@ @object_list.rating_avg@) + + + +
      @object_list.overview@ +
      + + +
      (@object_list.categories_html;noquote@) +
      + + +
    + + + + +
    + Index: openacs-4/contrib/obsolete-packages/library/www/browse-one-category.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/browse-one-category.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/browse-one-category.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,435 @@ +! Entering browse-one-category +ad_page_contract { + /packages/library/www/browse-one-category.tcl + + Show the subcategories and objects associated with a category. + + @cvs-id $Id: browse-one-category.tcl,v 1.1 2003/07/02 12:19:42 peterm Exp $ +} { + {object_type_id:integer 0} + {object_type ""} + {category_id 0} + {category ""} + {question_id:integer 0} + {path_id:integer ""} + {show short} + {pool all} + {age ""} + {sort_by last_modified} + {first_row:integer 1} + {last_row:integer 0} + {begin_letter all} + {archive "f"} + start:array,optional + end:array,optional +} -properties { + object_list:multirow + title:onevalue + graphic_width:onevalue + category_action:onevalue + category_id:onevalue + total_num_objects:onevalue + num_displayed_objects:onevalue + category_display_limit:onevalue + pretty_question:onevalue + object_type_id:onevalue + category_id:onevalue + path_id:onevalue + system_name:onevalue + age_bar:onevalue + ownership_bar:onevalue + archive_bar:onevalue + object_view_bar_top_level:onevalue + object_sort_bar:onevalue + objects:onevalue + first_row:onevalue + last_row:onevalue + alphabet:multirow + begin_letter:onevalue + subsite_url:onevalue + subsite_name:onevalue + default_age_filter:onevalue + archive:onevalue + archive_p:onevalue + start_date:onevalue + end_date:onevalue + date_filter_vars:onevalue + date_filter_p:onevalue +} + +set package_id [ad_conn package_id] +set form [ad_conn form] +# For backward compatibility, we still support the object_type parameter. + +if { [empty_string_p $object_type] && !$object_type_id } { + ad_return_warning "Missing object type" \ + "Either object_type or object_type_id have to be given." + return +} + +if [empty_string_p $show] { + set show short +} + +if !$object_type_id { + set object_type_id [db_string object_type_id { + select object_type_id from sn_object_types + where short_name = :object_type + and context_id = :package_id + and rownum = 1 + } -default ""] + if {[empty_string_p $object_type_id]} { + ad_return_complaint 1 "No such object type found." + return + } + # manipulate the form data so to export object_type_id + # via export_ns_set_vars + ns_set delkey $form object_type + ns_set put $form object_type_id $object_type_id +} + +if { $category_id != "none" && !$category_id } { + set category_id [db_string category_id { + select c.category_id + from categories c, sn_questions q, sn_question_object_type_map qm, + sw_category_dim d + where c.short_name = :category + and qm.object_type_id = :object_type_id + and qm.question_id = q.question_id + and qm.question_state <> 'invisible' + and d.parent_node_id = q.node_id + and c.category_id = d.object_id + and rownum = 1 + } -default ""] + if {[empty_string_p $category_id]} { + ad_return_complaint 1 "No such category found." + return + } + # manipulate the form data so to export category_id + # via export_ns_set_vars + ns_set delkey $form category + ns_set put $form category_id $category_id +} + +set child_type_p [db_string child_object_type { + select decode(count(*),0,0,1) from dual where exists + (select 1 + from sn_questions + where abstract_data_type = 'child_object' + and target_object_type_id = :object_type_id) +}] + +set user_id [ad_conn user_id] +if ![km_check_object_type_id $object_type_id] { return } + +if ![info exists start] { + set start_date "" +} else { + set start_date "$start(year)-$start(month)-$start(day)" + if ![date_p $start_date] { + ad_return_complaint 1 "Invalid start date" + return + } +} +if ![info exists end] { + set end_date "" +} else { + set end_date "$end(year)-$end(month)-$end(day)" + if ![date_p $end_date] { + ad_return_complaint 1 "Invalid end date" + return + } +} + +set archive_p [km_static object_type_archive_p $object_type_id] +if {!$archive_p} { + set archive f +} + +if [empty_string_p $path_id] { + set current_action browse +} else { + set current_action [get_path_action $path_id] +} + +set default_age_filter [km_static object_type_default_age_filter $object_type_id] + +if [empty_string_p $age] { + # First, we check if there is a default age filter for this object + # type. If not, we use "all" as our default. + + set age $default_age_filter + if [empty_string_p $age] { set age all } +} + +set return_uri [ad_urlencode "[ad_conn url]?[ad_conn query]"] +set date_filter_vars [export_ns_set_vars form {first_row last_row start.day start.month start.year end.day end.month end.year} $form] +if {![empty_string_p [km_static object_type_start_date $object_type_id]] && ![empty_string_p [km_static object_type_end_date $object_type_id]]} { + set date_filter_p t +} else { + set date_filter_p f +} + +# Get the name of the object type. +set pretty_type [km_static object_type_pretty_name $object_type_id] +set pretty_type_plural [km_static object_type_pretty_plural $object_type_id] +if {$archive=="t"} { + set pretty_type_plural "$pretty_type_plural (archived)" +} +set graphic [km_static object_type_graphic $object_type_id] +# Get the name of the category + +if { $category_id == "none" } { + + set have_alert 0 + set category "Uncategorized" + + if !$question_id { + ad_return_error "Deep trouble" " + We're looking for uncategorized things, but we weren't + told which question should be uncategorized. Probably our programming error." + return + } + + set node_id 0 + set root_node [km_root_node -question_id $question_id $object_type_id] + set pretty_question [snd [km_get_question $question_id $object_type_id]] + +} else { + + set have_alert [alerts::exists -category_id $category_id -content_type_id $object_type_id] + set category [km_category_name $category_id] + + if { [empty_string_p $category] } { + ad_return_error "Deep trouble" \ + "We're in deep trouble, because we couldn't find category_id $category_id" + return + } + + set node_id [db_string node_id " + select node_id from sw_category_dim where object_id=:category_id" -default ""] + set parent_info [km_node_question_parent $object_type_id $node_id] + set question_id [fst $parent_info] + set root_node [snd $parent_info] + set pretty_question [snd [km_get_question $question_id $object_type_id]] +} +# Check if the corresponding question has been made invisible. + +set question_info [km_get_question $question_id $object_type_id] +if [empty_string_p $question_info] { + ad_return_warning "Invalid Category" " + The given categorization does not exist, probably because it has been removed + from this object type. Please go back to the + browsing page + for $pretty_type_plural." + return +} + +set parameters [export_ns_set_vars url {first_row last_row category_id question_id show} $form] + +if { $category_id == "none" } { + set_context_bar_data [list "browse-one-type?$parameters" $pretty_type_plural] "Uncategorized by $pretty_question" +} else { + + set context_list [list] + + lappend context_list [list "browse-one-type?$parameters" $pretty_type_plural] + + if {!$root_node} { + set parent_info [km_category_question_parent $object_type_id $category_id] + set root_category [snd $parent_info] + } else { + set root_category $root_node + } + + set parentage_list [ad_category_parentage_list $category_id $root_category] + + set ancestor_count [llength $parentage_list] + + # We don't want to show a link for the current category. + incr ancestor_count -1 + for { set i 1 } { $i < $ancestor_count } { incr i } { + set parent [lindex $parentage_list $i] + set parent_id [fst $parent] + set parent_name [snd $parent] + lappend context_list ["[ad_conn url]?$parameters&category_id=$parent_id" $parent_name] + } + + lappend context_list [km_category_name $category_id] + + eval set_context_bar_data $context_list + + +} + +array set node [site_node_closest_ancestor_site_node "acs-subsite"] +set subsite_url $node(url) +set subsite_name $node(instance_name) + +set create_p [km_conn create_p] +set copy_p [km_static object_type_copy_p $object_type_id] +set object_type_pretty_name [km_static object_type_pretty_name $object_type_id] +set graphic_width [library_icon_width] + +if {![km_static object_type_create_p $object_type_id]} { + set create_p 0 +} + +if { [empty_string_p $category] } { + set maybe_category "" +} else { + set maybe_category "in $category" +} + +set title "$pretty_type_plural $maybe_category" + +! Getting count of objects in this category or subcategories + +set category_display_limit [km_category_display_limit] +set category_counts [ns_set create] + +if { $category_id == "none" } { + + km_get_category_counts -age $age -pool $pool -begin_letter $begin_letter -archived $archive -start_date $start_date -end_date $end_date $object_type_id $category_counts + set total_num_objects [ns_set get $category_counts "uncat $question_id"] + +} else { + + km_get_category_counts -age $age -pool $pool -begin_letter $begin_letter -archived $archive -start_category_id $category_id -start_date $start_date -end_date $end_date $object_type_id $category_counts + set total_num_objects [ns_set get $category_counts $category_id] + +} + +! Got the counts +total_num_objects + +set system_name [km_get_community_name] +set age_bar [km_age_bar $age] +set ownership_bar [km_ownership_bar $pool] + +set target_url "[ns_conn url]?[export_ns_set_vars url {category_id} $form]&category_id=" + +km_category_table -object_type_id $object_type_id \ + -question_id $question_id -parent_node_id $node_id -target $target_url \ + -category_counts $category_counts -maximum_sub_columns 3 -uncategorized_p 0 + +set object_view_bar_top_level [km_object_view_bar_top_level $show "just this category" "this category and its subcategories"] +set object_sort_bar [km_sort_by_bar $sort_by $child_type_p] + +set minus_join_tables {} +set where_clauses {} +set minus_where_clauses {} +set more_join_tables {} + +if { $category_id == "none" } { + + lappend minus_join_tables \ + "sw_object_category_map cm" \ + "sw_flat_cat fc" + + lappend minus_where_clauses \ + "cm.object_id = obj.object_id" \ + "cm.category_id = fc.child_category_id" \ + "fc.parent = $root_node" + +} else { + + switch $show { + + all { + ! We are showing objects on +category_id level AND all sublevels + lappend where_clauses "obj.object_id = swcm.object_id" + lappend where_clauses "fc.parent_category_id = :category_id" + lappend where_clauses "swcm.category_id = fc.child_category_id" + + lappend more_join_tables "sw_object_category_map swcm" + lappend more_join_tables "sw_flat_cat fc" + } + + default { + ! We are showing just objects on +category_id level + set show "short" + lappend where_clauses "obj.object_id = swcm.object_id" + lappend where_clauses "swcm.category_id = :category_id" + + lappend more_join_tables "sw_object_category_map swcm" + } + } +} + +if [empty_string_p $total_num_objects] { set total_num_objects 0 } + +if !$last_row { + if { $total_num_objects > [expr $first_row + 99] } { + set last_row [expr $first_row + 99] + } +} elseif { $last_row < $total_num_objects && $total_num_objects <= [expr $first_row + 99] } { + set last_row $total_num_objects +} + +set url_stub "browse-one-category?[export_ns_set_vars url {first_row last_row} $form]" + +set num_displayed_objects 0 +if { $total_num_objects > 0 } { + set header $pretty_type_plural + ! Calling km8_output_object_list +where_clauses +minus_join_tables +minus_where_clauses +more_join_tables + set num_displayed_objects [km8_output_object_list -object_type_id $object_type_id \ + -header $header -pool $pool -age $age -sort_by $sort_by \ + -show $show -current_action $current_action -path_id $path_id \ + -category_id $category_id -question_id $question_id \ + -first_row $first_row -last_row $last_row \ + -where_clauses $where_clauses -begin_letter $begin_letter \ + -minus_join_tables $minus_join_tables \ + -minus_where_clauses $minus_where_clauses \ + -archived $archive -start_date $start_date -end_date $end_date \ + -more_join_tables $more_join_tables] + ! Done with km8_output_object_list + + if { $last_row > $num_displayed_objects } { + set last_row $num_displayed_objects + } elseif !$last_row { + set last_row $num_displayed_objects + } +} + +set url_vars [export_ns_set_vars url {begin_letter first_row last_row} $form] +template::multirow create alphabet letter url +foreach letter {all A B C D E F G H I J K L M N O P Q R S T U V W X Y Z other} { + if [string equal $letter $begin_letter] { + template::multirow append alphabet $letter "" + } else { + template::multirow append alphabet $letter "browse-one-category?$url_vars&begin_letter=$letter" + } +} + +set archive_bar [km_archive_bar $archive] + +query get_package_name package_name onevalue { + select instance_name from apm_packages where package_id = :package_id +} +array set node [site_node_closest_ancestor_site_node "acs-subsite"] +set community_id $node(package_id) + +if [integer_p $category_id] { + query get_category_tree_info tree_info onerow { + select gt.tree_name, gt.tree_id, c.short_name + from sw_category_dim scd, generic_trees gt, categories c + where scd.object_id = :category_id + and scd.tree_id = gt.tree_id + and c.category_id = :category_id + } + set search_contexts [list \ + [list "lcat:$object_type_id,$tree_info(tree_id),$category_id" "$tree_info(short_name)"] \ + [list "ltype:$object_type_id" "$pretty_type_plural"] \ + [list "lib:$package_id" "$package_name"] \ + [list "sc:$community_id" "$subsite_name"] \ + [sws_km_site_search_context]] +} else { + set search_contexts [list \ + [list "ltype:$object_type_id" "$pretty_type_plural"] \ + [list "lib:$package_id" "$package_name"] \ + [list "sc:$community_id" "$subsite_name"] \ + [sws_km_site_search_context]] +} + +ad_return_template +! Exiting browse-one-category Index: openacs-4/contrib/obsolete-packages/library/www/browse-one-type.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/browse-one-type.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/browse-one-type.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,145 @@ + +@title;noquote@ +@graphic@ +@graphic_width;noquote@ +@subsite_url;noquote@ +@subsite_name;noquote@ +@search_contexts;noquote@ + + + +Number of objects (@total_num_objects@) +

    +View items modified in the last @age_bar;noquote@ +

    + + + + + + + + + + + + + +
    @categorization_widget_header.header_name@
    +
    +

    + + + + + + + + + + +
    View: + @object_view_bar_top_level;noquote@ +
    + +
    Status:@archive_bar;noquote@
    Owner:@ownership_bar;noquote@
    Alphabet: [ + + + @alphabet.letter@ + + + @alphabet.letter@ + + ] +
    +

    No objects here. + + + + + + + +
    View: + @object_view_bar_top_level;noquote@ +
    + + +
    Status:@archive_bar;noquote@
    Owner:@ownership_bar;noquote@
    + + + Status:@archive_bar;noquote@ + + Owner:@ownership_bar;noquote@ + Sort: @object_sort_bar;noquote@ + Alphabet: [ + + + @alphabet.letter@ + + + @alphabet.letter@ + + ] + + + +

    @pretty_type_plural;noquote@ + + @first_row@-@last_row@ of @total_num_objects@ + + (@total_num_objects@) +

    + + + (Note: When there are more than @category_display_limit@ objects found, + categories are not shown.) + + +
      + + +
    • + + [Private] + + + [Archived] + + + [In review] + + @object_list.object_name@ + by @object_list.user_link;noquote@ (@object_list.last_modified@) + + + (@object_list.access_total@ hits, @object_list.access_month@ this month) + + + + (@object_list.number_ratings@ user + ratings: average of: + @object_list.rating_avg@ @object_list.rating_avg@) + + + +
      @object_list.overview@ +
      + + +
      (@object_list.categories_html;noquote@) +
      + + +
    + + + + + Index: openacs-4/contrib/obsolete-packages/library/www/browse-one-type.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/browse-one-type.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/browse-one-type.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,250 @@ +! Entering browse-one-type +ad_page_contract { + /packages/library/www/browse-one-type.tcl + + Show all categories associated with the given object type. + + @author Carsten Clasohm (carsten@arsdigita.com) + @author Dirk Gomez (dirk@arsdigita.com) + + @cvs-id $Id: browse-one-type.tcl,v 1.1 2003/07/02 12:19:42 peterm Exp $ +} { + {object_type_id:integer 0} + {short_name ""} + {path_id:integer ""} + {show ""} + {pool all} + {age ""} + {sort_by last_modified} + {first_row:integer 1} + {last_row:integer 0} + {begin_letter all} + {archive "f"} + start:array,optional + end:array,optional +} -properties { + title:onevalue + graphic_width:onevalue + total_num_objects:onevalue + category_display_limit:onevalue + pretty_type_plural:onevalue + system_name:onevalue + object_type_id:onevalue + age_bar:onevalue + path_id:onevalue + ownership_bar:onevalue + archive_bar:onevalue + object_view_bar_top_level:onevalue + show:onevalue + object_sort_bar:onevalue + objects:onevalue + first_row:onevalue + last_row:onevalue + categorization_widget:multirow + alphabet:multirow + begin_letter:onevalue + subsite_url:onevalue + subsite_name:onevalue + default_age_filter:onevalue + search_contexts:onevalue + archive:onevalue + archive_p:onevalue + start_date:onevalue + end_date:onevalue + date_filter_vars:onevalue + date_filter_p:onevalue +} + +set user_id [ad_conn user_id] +set package_id [ad_conn package_id] +set instance_name [ad_conn instance_name] +set form [ad_conn form] + +if { [empty_string_p $short_name] && !$object_type_id } { + ad_return_warning "Invalid object type" \ + "short_name or object_type_id are either missing or invalid." + return +} + +if !$object_type_id { + set object_type_id [db_string object_type_id { + select object_type_id + from sn_object_types + where short_name = :short_name + and context_id = :package_id + and rownum = 1 + } -default ""] + # manipulate the form data so to export object_type_id + # via export_ns_set_vars + if {[empty_string_p $object_type_id]} { + ad_return_complaint 1 "No such object type found." + return + } + ns_set delkey $form short_name + ns_set put $form object_type_id $object_type_id +} + +if ![km_check_object_type_id $object_type_id] { return } + +if ![info exists start] { + set start_date "" +} else { + set start_date "$start(year)-$start(month)-$start(day)" + if ![date_p $start_date] { + ad_return_complaint 1 "Invalid start date" + return + } +} +if ![info exists end] { + set end_date "" +} else { + set end_date "$end(year)-$end(month)-$end(day)" + if ![date_p $end_date] { + ad_return_complaint 1 "Invalid end date" + return + } +} + +set archive_p [km_static object_type_archive_p $object_type_id] +if {!$archive_p} { + set archive f +} + +if ![path_valid_p $path_id] { + set current_action "browse" +} else { + set current_action [get_path_action $path_id] +} + +if [empty_string_p $pool] { set pool all } +if [empty_string_p $sort_by] { set sort_by last_modified } + +set default_age_filter [km_static object_type_default_age_filter $object_type_id] + +if [empty_string_p $age] { + # First, we check if there is a default age filter for this object + # type. If not, we use "all" as our default. + + set age $default_age_filter + if [empty_string_p $age] { set age all } +} + + +set return_uri [ad_urlencode "[ad_conn url]?[ad_conn query]"] +set have_alert [alerts::exists -content_type_id $object_type_id] +set date_filter_vars [export_ns_set_vars form {first_row last_row start.day start.month start.year end.day end.month end.year} $form] +if {![empty_string_p [km_static object_type_start_date $object_type_id]] && ![empty_string_p [km_static object_type_end_date $object_type_id]]} { + set date_filter_p t +} else { + set date_filter_p f +} + +# Get the pretty name of the object type + +set pretty_type [km_static object_type_pretty_name $object_type_id] +set pretty_type_plural [km_static object_type_pretty_plural $object_type_id] +if {$archive=="t"} { + set pretty_type_plural "$pretty_type_plural (archived)" + set have_alert 1 +} +set graphic [km_static object_type_graphic $object_type_id] +set age_bar [km_age_bar $age] + +set child_type_p [db_string child_object_type { + select decode(count(*),0,0,1) from dual where exists + (select 1 + from sn_questions + where abstract_data_type = 'child_object' and target_object_type_id=:object_type_id) +}] + +# Get the category counts. + +set category_counts [ns_set create] +km_get_category_counts -age $age -pool $pool -begin_letter $begin_letter -archived $archive -start_date $start_date -end_date $end_date $object_type_id $category_counts + +set total_num_objects [ns_set get $category_counts total] +set category_display_limit [km_category_display_limit] + +array set node [site_node_closest_ancestor_site_node "acs-subsite"] +set subsite_url $node(url) +set subsite_name $node(instance_name) +set subcommunity_id $node(package_id) + +set graphic_width [library_icon_width] +set_context_bar_data -- $pretty_type_plural + +set title $pretty_type_plural +set object_type_pretty_name [km_static object_type_pretty_name $object_type_id] +set system_name [km_get_community_name] +set ownership_bar [km_ownership_bar $pool] + +if ![km_static object_type_create_p $object_type_id] { + set create_p 0 +} else { + set create_p [km_conn create_p] +} +set copy_p [km_static object_type_copy_p $object_type_id] + +set target_url "browse-one-category?[export_ns_set_vars url {category_id show first_row last_row} $form]&category_id=" + +set categories_p [km_category_table -object_type_id $object_type_id \ + -target $target_url -category_counts $category_counts] + +if [empty_string_p $show] { + if { !$categories_p || $total_num_objects < $category_display_limit } { + set show all + } else { + set show short + } +} + +if { $show != "short" } { + set object_sort_bar [km_sort_by_bar $sort_by $child_type_p] +} else { + set object_sort_bar "" +} + +if !$last_row { + if { $total_num_objects > [expr $first_row + 99] } { + set last_row [expr $first_row + 99] + } +} elseif { $last_row < $total_num_objects && $total_num_objects <= [expr $first_row + 99] } { + set last_row $total_num_objects +} + +set url_stub "browse-one-type?[export_ns_set_vars url {first_row last_row} $form]" + +set objects "" +set total_num_objects2 [km8_output_object_list \ + -object_type_id $object_type_id \ + -pool $pool -age $age -sort_by $sort_by \ + -show $show -path_id $path_id -current_action $current_action \ + -first_row $first_row -last_row $last_row -begin_letter $begin_letter \ + -archived $archive -start_date $start_date -end_date $end_date] + +if !$last_row { set last_row $total_num_objects } + +set url_vars [export_ns_set_vars url {begin_letter first_row last_row} $form] +template::multirow create alphabet letter url +foreach letter {all A B C D E F G H I J K L M N O P Q R S T U V W X Y Z other} { + if [string equal $letter $begin_letter] { + template::multirow append alphabet $letter "" + } else { + template::multirow append alphabet $letter "browse-one-type?$url_vars&begin_letter=$letter" + } +} + +set object_view_bar_top_level [km_object_view_bar_top_level $show \ + "just category descriptions" \ + "all $pretty_type objects ($total_num_objects)"] + +set archive_bar [km_archive_bar $archive] + +set search_contexts [list \ + [list "ltype:$object_type_id" "$pretty_type_plural"] \ + [list "lib:$package_id" "$instance_name"] \ + [list "sc:$subcommunity_id" "$subsite_name"] \ + [sws_km_site_search_context]] + +ad_return_template +! Exiting browse-one-type Index: openacs-4/contrib/obsolete-packages/library/www/category-action.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/category-action.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/category-action.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,17 @@ + + + Set Alert + + Set Alert + + + + + | + Create new @object_type_pretty_name;noquote@ + + | Copy a @object_type_pretty_name;noquote@ + + + +

    Index: openacs-4/contrib/obsolete-packages/library/www/comment-add-2.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/comment-add-2.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/comment-add-2.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,86 @@ + +@title;noquote@ +@subsite_url;noquote@ +@subsite_name;noquote@ +@header_stuff;noquote@ + +

    +@object_name@:
    +@overview_with_href_and_mailto;noquote@ + +

    + +

    @headline@

    + +
    + +@form_vars;noquote@ + + +Please tell @author_name@ +how valuable you find her/his @object_type@ "@object_name@". + + He/she will receive a variable number of + Shares defined by you along with your comment. + +

    Select feedback points

    +

    By giving feedback points you help users to easily find + interesting content in . Also, @author_name@ + will receive a number of Shares proportional to the number of + feedback points you award.

    + + Answer didn't help me  + checked
    >@ratings.number@   + Perfect Answer

    +
    + + +

    + + +

    Comment

    +

    Please add a comment to your feedback. The system will include + it in the feedback E-Mail to the user. +
    Here you shall explain, describe or comment your feedback + (i.e. what project did you reuse the information for, + what did you learn, why do you think it's outdated or should have + more details, etc.).

    + + What comment would you like to add to the above @object_type@? + +

    + + + + +
    + + + +
    +

    +

    + +

    + checked> +Add this comment as a public comment to the knowledge object +

    + +
    + +
    + + +
    + + @form_vars;noquote@ + + +
    Index: openacs-4/contrib/obsolete-packages/library/www/comment-add-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/comment-add-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/comment-add-2.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,123 @@ +ad_page_contract { + /packages/library/www/comment-add-2.tcl + + Let the user enter a comment and the number of reuse points. + + @author Carsten Clasohm (carsten@arsdigita.com) + @author Bernd Schmeil (bernd@arsdigita.com) - did modifications + @author Timo Hentschel (timo@arsdigita.com) + + @cvs-id $Id: comment-add-2.tcl,v 1.1 2003/07/02 12:19:42 peterm Exp $ +} { + object_id:notnull,integer + {feedback_category_id:integer ""} + {category_id ""} + {path_id:integer ""} + {comment ""} + {html_p:oneof(t|f) "f"} + {public_p:optional "t"} + {reuse_points:integer "-1"} +} -properties { + title:onevalue + headline:onevalue + object_name:onevalue + object_type:onevalue + form_vars:onevalue + feedback_category:onevalue + feedback_category_id:onevalue + ratings:multirow + overview_with_href_and_mailto:onevalue + author_id:onevalue + author_name:onevalue + subsite_url:onevalue + subsite_name:onevalue + header_stuff:onevalue + comment:onevalue + html_p:onevalue + public_p:onevalue + reuse_points:onevalue +} + +set user_id [ad_maybe_redirect_for_registration] +set package_id [ad_conn package_id] + +array set node [site_node_closest_ancestor_site_node "acs-subsite"] +set community_id $node(package_id) + +if ![km_check_object_id $object_id] { return } +set author_id [km_conn original_author_id] +set author_name [km_conn original_author_name] + +if {$feedback_category_id == 0} { + ad_return_complaint 1 "Please select a feedback category!" + return +} + +if {[km_conn archived_p]} { + ad_return_complaint 1 "Only feedback for not archived knowledge objects is allowed!" + return +} + +set object_name [km_conn object_name] +set object_type [km_static object_type_pretty_name [km_conn object_type_id]] + +array set node [site_node_closest_ancestor_site_node "acs-subsite"] +set subsite_url $node(url) +set subsite_name $node(instance_name) +set header_stuff "" + +if {![empty_string_p $feedback_category_id]} { + set feedback_category [db_string get_category_name { + select long_name from categories + where category_id = :feedback_category_id} -default ""] + + # don't let user give feedback points if user is author + # or object is private + if {($user_id == $author_id) || ![km_conn public_p] || ![db_0or1row get_rating_scale { + select rating_p as reuse_p, scale + from sn_comments_category_settings + where object_id = :package_id + and category_id = :feedback_category_id }]} { + set reuse_p "f" + set scale 0 + } +} else { + set reuse_p "f" + set scale 0 + set feedback_category "" +} + +if {$reuse_p=="t"} { + set what "Give feedback" + set headline "Give Feedback" + set title "Give feedback for \"$object_name\"" +} else { + set what "Add comment" + set headline "Your Comment" + set title "Add a comment to \"$object_name\"" +} + +set_the_usual_klib_context_bar $object_id $category_id +if {[empty_string_p $feedback_category_id]} { + append_context_bar_data $what +} else { + append_context_bar_data [list "comment-add?[export_url_vars object_id category_id path_id]" "Feedback category"] $what +} + +set overview_with_href_and_mailto [util_make_href_and_mailto_links [km_conn overview]] +set form_vars [export_form_vars object_id feedback_category_id category_id path_id] +set original_author_p [km_original_author_p $user_id $object_id] + +template::multirow create ratings number + +if { $reuse_p=="t" } { + # Generate the list of valid reuse points. + if { $scale > 0} { + for { set counter 0 } { $counter <= $scale } { incr counter } { + template::multirow append ratings $counter + } + } +} + +ad_return_template + Index: openacs-4/contrib/obsolete-packages/library/www/comment-add-3.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/comment-add-3.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/comment-add-3.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,71 @@ + +@title;noquote@ + +The following is your comment as it would appear on the page +@object_name@. If it looks incorrect, please use the back button +on your browser to return and correct it. Otherwise, press +"Continue". + +
    + +

    Feedback type: @feedback_category@

    +
    +

    Comment:

    @comment;noquote@

    +
    +

    + + This comment will appear as a comment below the @object_type@ "@object_name@". + + + This comment will only get sent to the author + @author_name@ of the + @object_type@ "@object_name@" + and will NOT appear as a comment below the @object_type@. + + + + +

    Note: If the comment has lost all of its paragraph breaks then you + probably should have selected "Plain Text" rather than "HTML". + +

    Note: If the comment has a bunch of visible HTML tags then you probably + should have selected "HTML" rather than "Plain Text". Use your + browser's Back button to return to the submission form. + + + + +

    You will receive the following shares: +

      +
    • @own_shares.bank_name@: @own_shares.amount@ @own_shares.currency@ (New balance: @own_shares.balance@ @own_shares.currency@)
    • +
    +

    + @author_name@ + + + is about to receive no shares since you rated the object with 0. + + is about to receive no shares since no shares will be awarded for this feedback type. + + + is about to receive the following shares proportional to @reuse_points@ + points you awarded his knowledge object: +

      +
    • @author_shares.bank_name@: @author_shares.amount@ @author_shares.currency@
    • +
    +
    +

    + + + +

    + +@form_vars;noquote@ +@dc_export;noquote@ +
    + + +
    +@form_vars;noquote@ + +
    Index: openacs-4/contrib/obsolete-packages/library/www/comment-add-3.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/comment-add-3.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/comment-add-3.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,139 @@ +ad_page_contract { + /packages/library/www/comment-add-3.tcl + + Ask the user for confirmation before adding comment and reuse points. + + @author Carsten Clasohm (carsten@arsdigita.com) + @author Bernd Schmeil (bernd@arsdigita.com) - did modifications + @author Timo Hentschel (timo@arsdigita.com) + + @cvs-id $Id: comment-add-3.tcl,v 1.1 2003/07/02 12:19:42 peterm Exp $ +} { + object_id:notnull,integer + comment:notnull + html_p:notnull,oneof(t|f) + {reuse_points:integer "-1"} + {feedback_category_id:integer ""} + {public_p:optional "f"} + {category_id ""} + {path_id:integer ""} +} -properties { + title:onevalue + object_name:onevalue + object_type:onevalue + form_vars:onevalue + feedback_category:onevalue + comment:onevalue + html_p:onevalue + reuse_points:onevalue + original_author_p:onevalue + author_id:onevalue + author_name:onevalue + dc_export:onevalue + subsite_url:onevalue + subsite_name:onevalue + own_shares:multirow + author_shares:multirow + admin_p:onevalue +} + +set user_id [ad_maybe_redirect_for_registration] +set package_id [ad_conn package_id] + +if ![km_check_object_id $object_id] { return } +set author_id [km_conn original_author_id] +set author_name [km_conn original_author_name] +set admin_p [km_conn admin_p] + +if {$user_id == $author_id} { + set reuse_points -1 +} + +if {[km_conn archived_p]} { + ad_return_complaint 1 "Only feedback for not archived knowledge objects is allowed!" + return +} + +set object_name [km_conn object_name] +set object_type [km_static object_type_pretty_name [km_conn object_type_id]] +set title "Confirm comment on \"$object_name\"" + +set form_vars [export_form_vars object_id comment html_p reuse_points feedback_category_id public_p category_id path_id] +set original_author_p [km_original_author_p $user_id $object_id] + +set reuse_p "f" +if {![empty_string_p $feedback_category_id]} { + set feedback_category [db_string get_category_name " + select long_name from categories + where category_id = :feedback_category_id" -default ""] + if {[db_0or1row get_rating_scale { + select rating_p as reuse_p, scale + from sn_comments_category_settings + where object_id = :package_id + and category_id = :feedback_category_id }] && $reuse_p == "t" } { + if {[empty_string_p $reuse_points] || $reuse_points < 0 || $reuse_points > $scale} { + ad_return_complaint 1 "Please provide a rating!" + return + } + } +} else { + set feedback_category "" +} + +if {$reuse_p=="t"} { + set what "Give feedback" + set confirm "Confirm feedback" +} else { + set what "Add comment" + set confirm "Confirm comment" +} + +set_the_usual_klib_context_bar $object_id $category_id +if [empty_string_p $feedback_category_id] { + append_context_bar_data [list "comment-add-2?[export_url_vars object_id category_id path_id]" $what] $confirm +} else { + append_context_bar_data [list "comment-add?[export_url_vars object_id category_id path_id]" "Feedback category"] [list "comment-add-2?[export_url_vars object_id category_id path_id feedback_category_id]" $what] $confirm +} + +if { $html_p == "f" } { + set comment [util_make_href_and_mailto_links_and_convert_to_html $comment] +} + +template::multirow create own_shares bank_id bank_name currency amount balance +if {$reuse_points > -1 && ($user_id != $author_id) && ![empty_string_p $feedback_category_id] && [info exists incentives::initialized]} { + foreach bank_id [incentives::bank_list $package_id] { + set amount [incentives::charge_value -key $feedback_category_id kl_rating_give $bank_id] + if {$amount > 0} { + db_1row get_currency_name { + select pretty_name as bank_name, currency_name + from ir_banks + where bank_id = :bank_id + } + template::multirow append own_shares $bank_id $bank_name $currency_name $amount [expr $amount+[thd [incentives::account_balance $bank_id]]] + } + } +} + +template::multirow create author_shares bank_id bank_name currency amount balance +if {$reuse_points > 0 && ($user_id != $author_id) && ![empty_string_p $feedback_category_id] && [info exists incentives::initialized]} { + foreach bank_id [incentives::bank_list -user_id $author_id $package_id] { + set factor [incentives::charge_value -key $feedback_category_id kl_rating_receive $bank_id] + set amount [expr {$factor * $reuse_points}] + if {$amount > 0} { + db_1row get_currency_name { + select pretty_name as bank_name, currency_name + from ir_banks + where bank_id = :bank_id + } + template::multirow append author_shares $bank_id $bank_name $currency_name $amount [expr $amount+[thd [incentives::account_balance -user_id $author_id $bank_id]]] + } + } +} + +array set node [site_node_closest_ancestor_site_node "acs-subsite"] +set subsite_url $node(url) +set subsite_name $node(instance_name) + +set dc_export [doubleclick::signature_html] + +ad_return_template Index: openacs-4/contrib/obsolete-packages/library/www/comment-add-4.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/comment-add-4.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/comment-add-4.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,197 @@ +ad_page_contract { + /packages/library/www/comment-add-4.tcl + + Store comment and reuse points. + + @author Carsten Clasohm (carsten@arsdigita.com) + @author Bernd Schmeil (bernd@arsdigita.com) - modifications done in Jan 2001 + + @cvs-id $Id: comment-add-4.tcl,v 1.1 2003/07/02 12:19:42 peterm Exp $ +} { + object_id:notnull,integer + comment:notnull + {html_p:notnull,oneof(t|f) "f"} + {public_p:optional "f"} + {reuse_points:integer "-1"} + {feedback_category_id:integer ""} + {category_id ""} + {path_id:integer ""} +} +csrf::authenticate + +set user_id [ad_maybe_redirect_for_registration] +set package_id [ad_conn package_id] +if ![km_check_object_id $object_id] { return } +set author_id [km_conn original_author_id] + +if {$user_id == $author_id} { + set reuse_points -1 +} + +if {[km_conn archived_p]} { + ad_return_complaint 1 "Only feedback for not archived knowledge objects is allowed!" + return +} + +set object_type [km_static object_type_pretty_name [km_conn object_type_id]] + +set return_url "object-view?[export_url_vars object_id category_id path_id]" + +if {[doubleclick::check_all]} { + ns_sleep 2 + ad_returnredirect $return_url + return +} + +set category_forward_email "" +set scale 0 + +if {[db_0or1row get_rating_scale { + select rating_p as reuse_p, scale, email as category_forward_email + from sn_comments_category_settings + where object_id = :package_id + and category_id = :feedback_category_id +}] && $reuse_p == "t" } { + if {[empty_string_p $reuse_points] || $reuse_points < 0 || $reuse_points > $scale} { + ad_return_complaint 1 "Please provide a rating!" + return + } +} + +db_transaction { + # Save the comment. + set comment_id [km_general_comment_add $object_id $user_id $html_p \ + $reuse_points $scale $feedback_category_id $public_p $comment] + + # add comment to yellow page + db_dml insert_content_area { + insert into acs_object_areas (object_id, area_id, package_id) + values (:comment_id, null, :package_id) + } + + set author_id [km_conn original_author_id] + db_1row get_original_author_email { + select email as author_email from users where user_id = :author_id + } + + if {$comment_id && ($user_id != $author_id)} { + if {$reuse_points > -1 + && ![empty_string_p $feedback_category_id] + && [info exists incentives::initialized] + } { + # NOTE: this code almost exactly the same as the code in + # bboard/www/comment-add-3.tcl. + + # We have to award shares twice: to the user who received + # the rating, and to the user who gave the rating. + + # Note that we do need to loop over the banks twice, + # because the two users may not be in the same groups. + + # First handle the user who gives the rating. + foreach bank_id [incentives::bank_list [ad_conn package_id]] { + set amount [incentives::charge_value -key $feedback_category_id kl_rating_give $bank_id] + incentives::award_shares kl_rating_give $amount $bank_id $comment_id + } + + # Then the user who gets the rating. Check for 0 just so + # we don't bother with listing the banks and all if we're + # not going to award any shares in the end. + set shares_list [list] + set shares_awarded_p 0 + if {$reuse_points > 0} { + foreach bank_id [incentives::bank_list -user_id $author_id [ad_conn package_id]] { + set factor [incentives::charge_value -key $feedback_category_id kl_rating_receive $bank_id] + if {$factor > 0} { + set amount [expr {$factor * $reuse_points}] + incentives::award_shares -user_id $author_id \ + kl_rating_receive $amount $bank_id $comment_id + db_1row get_currency_name { + select pretty_name as bank_name, currency_name + from ir_banks + where bank_id = :bank_id + } + set balance [thd [incentives::account_balance -user_id $author_id $bank_id]] + lappend shares_list "$amount $currency_name (new total: $balance) for $bank_name ([ad_url]/incentives/user/shares?bank_id=$bank_id)" + set shares_awarded_p 1 + } + } + set shares_list [join $shares_list "\n"] + } + } + + # Send email to object owner. + + set object_name [sn_striphtml [km_conn object_name]] + + db_1row object_info { + select u.email as sender_email, + u.first_names || ' ' || u.last_name as sender_name, + site_node.url(sn.node_id) as package_url + from users u, site_nodes sn + where u.user_id = :user_id + and sn.object_id = :package_id + and rownum = 1 + } + + if {![empty_string_p $feedback_category_id]} { + set feedback_category [db_string comment_add_4_20 { + select long_name from categories + where category_id = :feedback_category_id + } -default ""] + } else { + set feedback_category "Comment" + } + + if { $html_p == "t" } { set comment [ad_html_to_text $comment] } + + set replacement_list \ + [list \ + knowledge_object $object_name \ + knowledge_object_link [ad_url]${package_url}object-view?object_id=$object_id \ + knowledge_object_type $object_type \ + feedback_type $feedback_category \ + recipient_email $author_email \ + sender_email $sender_email \ + sender_name $sender_name \ + comment $comment] + + if {$reuse_points == -1} { + set template_name "km_object_comment" + } else { + set template_name "km_object_feedback" + lappend replacement_list points $reuse_points + if {$shares_awarded_p} { + set template_name "km_object_feedback_shares" + lappend replacement_list shares_list $shares_list + } + } + + # This uses sn_community_instances_all. Should it be using + # sn_community_mounts_all instead? + set community_id [db_string get_community_id { + select community_id + from sn_community_instances_all + where package_id = :package_id + }] + + et_queue_email [et_process -community_id $community_id $template_name $replacement_list] + + if { ![empty_string_p $category_forward_email] } { + set replacement_list \ + [list \ + knowledge_object $object_name \ + knowledge_object_link [ad_url]${package_url}object-view?object_id=$object_id \ + knowledge_object_type $object_type \ + feedback_type $feedback_category \ + recipient_email $category_forward_email \ + sender_email $sender_email \ + sender_name $sender_name \ + comment $comment] + + et_queue_email [et_process -community_id $community_id "km_object_feedback_notify" $replacement_list] + } + } +} + +ad_returnredirect $return_url Index: openacs-4/contrib/obsolete-packages/library/www/comment-add.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/comment-add.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/comment-add.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,39 @@ + +@title;noquote@ + +
    +@object_name@:
    +@overview_with_href_and_mailto;noquote@ + +

    + +

    @headline@

    + +
    + +@form_vars;noquote@ + + +Please tell @author_name@ how valuable you find +her/his @object_type@ "@object_name@". + + He/she will receive a variable number of Shares defined by you along with your comment. + + +Please give your feedback on your @object_type@ "@object_name@". + + + +

    What sort of feedback do you give?

    +

    + + +

    + +

    + + +
    Index: openacs-4/contrib/obsolete-packages/library/www/comment-add.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/comment-add.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/comment-add.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,109 @@ +ad_page_contract { + /packages/library/www/comment-add.tcl + + Let the user choose a category for his feedback. + + @author Carsten Clasohm (carsten@arsdigita.com) + @author Timo Hentschel (timo@arsdigita.com) + + @cvs-id $Id: comment-add.tcl,v 1.1 2003/07/02 12:19:42 peterm Exp $ +} { + object_id:notnull,integer + {feedback_category_id:integer ""} + {category_id ""} + {path_id:integer ""} +} -properties { + title:onevalue + object_name:onevalue + object_type:onevalue + headline:onevalue + overview_with_href_and_mailto:onevalue + form_vars:onevalue + categories:multirow + author_id:onevalue + author_name:onevalue + feedback_category_id:onevalue + public_p:onevalue +} + +set user_id [ad_maybe_redirect_for_registration] +set package_id [ad_conn package_id] + +array set node [site_node_closest_ancestor_site_node "acs-subsite"] +set community_id $node(package_id) + +if ![km_check_object_id $object_id] { return } +set author_id [km_conn original_author_id] +set author_name [km_conn original_author_name] +set public_p [km_conn public_p] + +if {[km_conn archived_p]} { + ad_return_complaint 1 "Only feedback for not archived knowledge objects is allowed!" + return +} + +set object_name [km_conn object_name] +set object_type [km_static object_type_pretty_name [km_conn object_type_id]] + +set title "Give feedback for \"$object_name\"" +set headline "Give feedback" +set_the_usual_klib_context_bar $object_id $category_id +append_context_bar_data "Feedback category" +set overview_with_href_and_mailto [util_make_href_and_mailto_links [km_conn overview]] + +set form_vars [export_form_vars object_id path_id category_id] + +set feedback_category_tree_assigned_p [db_0or1row feedback_category_tree { + select gt.tree_name, octr.subtree_root_node_id, gt.root_node_id as original_root_node_id + from generic_trees gt, + acs_rels ar, + object_category_tree_rels octr + where ar.object_id_one = :package_id + and ar.object_id_two = gt.tree_id + and ar.rel_id = octr.rel_id + and rel_type = 'object_category_tree_rel'}] + +if { !$feedback_category_tree_assigned_p } { + ad_returnredirect "comment-add-2?[export_url_vars object_id path_id category_id]" + return +} else { + # get feedback categories + if { $subtree_root_node_id == $original_root_node_id } { + set level_correction 1 + } else { + set level_correction 0 + } + + template::multirow create categories name category_id level + + set sql_query " + select /*+INDEX(sw_category_dim sw_category_dim_long_name) */ category.long_name(object_id) as name, + object_id as category_id, deprecated_p, node_id, + level as sortlevel + from sw_category_dim + start with node_id = :subtree_root_node_id + connect by prior node_id = parent_node_id" + + # don't allow feedback categories with feedback points + # if user is author of the object or the object is private + if {($user_id == $author_id) || !$public_p} { + set sql_query " + select cat.name, cat.category_id, cat.deprecated_p, + cat.node_id, cat.sortlevel + from sn_comments_category_settings ccs, + ($sql_query) cat + where ccs.object_id = :package_id + and ccs.category_id (+) = cat.category_id + and nvl(ccs.rating_p,'f') = 'f'" + } + + db_foreach get_one_tree $sql_query { + if { [string equal $deprecated_p "f"]} { + if { $node_id!=$subtree_root_node_id || $subtree_root_node_id != $original_root_node_id } { + template::multirow append categories $name $category_id [gt_repeat_string " " [expr ($sortlevel - 1 -$level_correction) * 5]] + } + } + } +} + +ad_return_template Index: openacs-4/contrib/obsolete-packages/library/www/comment-delete-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/comment-delete-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/comment-delete-2.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,92 @@ +ad_page_contract { + /packages/library/www/comment-delete-2.tcl + + Allow the admin to delete feedback + + @author Timo Hentschel (timo@arsdigita.com) + + @cvs-id $Id: comment-delete-2.tcl,v 1.1 2003/07/02 12:19:42 peterm Exp $ +} { + comment_id:notnull,integer + {category_id ""} + {path_id ""} +} + +csrf::authenticate +set user_id [ad_maybe_redirect_for_registration] +set package_id [ad_conn package_id] +set object_id [km_check_comment_id $user_id $comment_id] +if !$object_id { return } + +set admin_p [km_conn admin_p] + +if {!$admin_p} { + ad_return_complaint 1 "Only admins can delete feedback!" + return +} + +set object_name [sn_striphtml [km_conn object_name]] +set object_type [km_static object_type_pretty_name [km_conn object_type_id]] + +set category_forward_email "" +set scale 0 + +set return_url "object-view?[export_url_vars object_id category_id path_id]" + +db_1row get_comment_data { + select sc.content, sc.html_p, c.long_name as feedback_category + from sn_comments sc, categories c + where comment_id=:comment_id + and sc.category_id = c.category_id(+) } + +db_transaction { + # remove the feedback from yellow pages + db_dml delete_content_area { + delete from acs_object_areas + where object_id = :comment_id + } + + # remove the feedback + db_exec_plsql delete_feedback { + begin + sn_comment.delete_comment ( :comment_id ); + end; + } + + if { $html_p == "t" } { set comment [ad_html_to_text $content] } + + set author_id [km_conn original_author_id] + set author_email [km_conn original_author_email] + + db_1row object_info { + select u.email as sender_email, + u.first_names || ' ' || u.last_name as sender_name, + site_node.url(sn.node_id) as package_url + from users u, site_nodes sn + where u.user_id = :user_id + and sn.object_id = :package_id + } + + set replacement_list \ + [list \ + knowledge_object $object_name \ + knowledge_object_link [ad_url]${package_url}object-view?object_id=$object_id \ + knowledge_object_type $object_type \ + feedback_type $feedback_category \ + recipient_email $author_email \ + sender_email $sender_email \ + sender_name $sender_name \ + comment $content] + + # This uses sn_community_instances_all. Should it be using + # sn_community_mounts_all instead? + set package_id [ad_conn package_id] + set community_id [db_string get_community_id { + select community_id + from sn_community_instances_all + where package_id = :package_id }] + + et_queue_email [et_process -community_id $community_id "km_object_feedback_delete" $replacement_list] +} + +ad_returnredirect $return_url Index: openacs-4/contrib/obsolete-packages/library/www/comment-delete.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/comment-delete.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/comment-delete.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,33 @@ + +@title;noquote@ + +
    @object_name@
    +@overview_with_href_and_mailto;noquote@ + +

    Feedback:

    + +
    + Feedback author: @author@
    + Feedback type: @feedback_category@
    + Rating: @rating@ out of @scale@ points +

    Comment:

    @content;noquote@ +
    + +

    Do you really want to delete this feedback? +

    Please be aware that the shares awarded for this feedback will NOT +be taken away by this action - you have to do these things in the Incentive system. +

    + +

    +
    + + @form_vars;noquote@ + @dc_export;noquote@ + + +
    + @form_vars_cancel;noquote@ + +
    +
    +
    Index: openacs-4/contrib/obsolete-packages/library/www/comment-delete.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/comment-delete.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/comment-delete.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,71 @@ +ad_page_contract { + /packages/library/www/comment-delete.tcl + + Allow the admin to delete feedback + + @author Timo Hentschel (timo@arsdigita.com) + + @cvs-id $Id: comment-delete.tcl,v 1.1 2003/07/02 12:19:42 peterm Exp $ +} { + comment_id:notnull,integer + {category_id ""} + {path_id:integer ""} +} -properties { + title:onevalue + object_name:onevalue + overview_with_href_and_mailto:onevalue + content:onevalue + author:onevalue + admin_p:onevalue + rating:onevalue + scale:onevalue + feedback_category:onevalue + form_vars:onevalue + form_vars_cancel:onevalue + dc_export:onevalue + subsite_url:onevalue + subsite_name:onevalue +} + +set user_id [ad_maybe_redirect_for_registration] +set package_id [ad_conn package_id] + +set object_id [km_check_comment_id $user_id $comment_id] +if !$object_id { return } + +set object_name [km_conn object_name] + +db_1row get_comment_data { + select sc.content, sc.html_p, rating, scale, + c.long_name as feedback_category, sc.display_p as public_p, + u.first_names || ' ' || u.last_name as author + from sn_comments sc, categories c, users u + where comment_id=:comment_id + and sc.category_id = c.category_id(+) + and u.user_id = sc.user_id } + +set admin_p [km_conn admin_p] + +if {!$admin_p} { + ad_return_complaint 1 "Only admins can delete feedback!" + return +} + +set title "Delete feedback on \"$object_name\"" +set_the_usual_klib_context_bar $object_id $category_id +append_context_bar_data "Delete feedback" +set overview_with_href_and_mailto [util_make_href_and_mailto_links [km_conn overview]] +set form_vars [export_form_vars comment_id category_id path_id] +set form_vars_cancel [export_form_vars object_id category_id path_id] + +array set node [site_node_closest_ancestor_site_node "acs-subsite"] +set subsite_url $node(url) +set subsite_name $node(instance_name) + +if { [string eq $html_p "f"] } { + set content [ad_quotehtml $content] +} + +set dc_export [doubleclick::signature_html] + +ad_return_template Index: openacs-4/contrib/obsolete-packages/library/www/comment-edit-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/comment-edit-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/comment-edit-2.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,122 @@ +ad_page_contract { + /packages/library/www/comment-edit-2.tcl + + Commits the feedback changes to the db. + + @author Timo Hentschel (timo@arsdigita.com) + + @cvs-id $Id: comment-edit-2.tcl,v 1.1 2003/07/02 12:19:42 peterm Exp $ +} { + comment_id:notnull,integer + comment:notnull + {html_p:oneof(t|f) "f"} + {feedback_category_id:integer ""} + {public_p:optional "f"} + {category_id ""} + {path_id:integer ""} +} +csrf::authenticate + +set user_id [ad_maybe_redirect_for_registration] +set package_id [ad_conn package_id] +set object_id [km_check_comment_id $user_id $comment_id] +if !$object_id { return } + +set admin_p [km_conn admin_p] +set object_name [sn_striphtml [km_conn object_name]] +set object_type [km_static object_type_pretty_name [km_conn object_type_id]] + +set category_forward_email "" +set scale 0 + +db_0or1row get_rating_scale { + select scale, email as category_forward_email + from sn_comments_category_settings + where object_id = :package_id + and category_id = :feedback_category_id +} + +db_1row get_message_data { + select u.email as feedback_author_email, u.user_id as feedback_author_id + from sn_comments sc, users u + where sc.comment_id = :comment_id + and u.user_id = sc.user_id } + +if {!$admin_p && (($user_id != $feedback_author_id) || [km_conn archived_p])} { + ad_return_forbidden "Only the feedback author or admins can edit feedback!" + return +} + +set return_url "object-view?[export_url_vars object_id category_id path_id]" + +db_transaction { + + km_general_comment_update -html_p $html_p -public_p $public_p -feedback_category_id $feedback_category_id $feedback_author_id $object_id $comment_id $comment + + if { $html_p == "t" } { set comment [ad_html_to_text $comment] } + + set author_id [km_conn original_author_id] + set author_email [km_conn original_author_email] + + db_1row object_info { + select u.email as sender_email, + u.first_names || ' ' || u.last_name as sender_name, + site_node.url(sn.node_id) as package_url + from users u, site_nodes sn + where u.user_id = :user_id + and sn.object_id = :package_id + and rownum = 1 + } + + if {![empty_string_p $feedback_category_id]} { + set feedback_category [db_string comment_edit_2_20 { + select long_name from categories + where category_id = :feedback_category_id + } -default ""] + } else { + set feedback_category "" + } + + # This uses sn_community_instances_all. Should it be using + # sn_community_mounts_all instead? + set community_id [db_string get_community_id { + select community_id + from sn_community_instances_all + where package_id = :package_id + }] + + if { $user_id != $author_id } { + set replacement_list \ + [list \ + knowledge_object $object_name \ + knowledge_object_link [ad_url]${package_url}object-view?object_id=$object_id \ + knowledge_object_type $object_type \ + feedback_type $feedback_category \ + recipient_email $author_email \ + sender_email $sender_email \ + sender_name $sender_name \ + comment $comment] + + et_queue_email [et_process -community_id $community_id "km_object_feedback_edit" $replacement_list] + } + + if { $admin_p && $feedback_author_id != $user_id } { + # we have to sent the feedback author an email that an admin changed + # his feedback + + set replacement_list \ + [list \ + knowledge_object $object_name \ + knowledge_object_link [ad_url]${package_url}object-view?object_id=$object_id \ + knowledge_object_type $object_type \ + feedback_type $feedback_category \ + recipient_email $feedback_author_email \ + sender_email $sender_email \ + sender_name $sender_name \ + comment $comment] + + et_queue_email [et_process -community_id $community_id "km_object_feedback_edit_admin" $replacement_list] + } +} + +ad_returnredirect $return_url Index: openacs-4/contrib/obsolete-packages/library/www/comment-edit.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/comment-edit.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/comment-edit.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,61 @@ + +@title;noquote@ +@subsite_url;noquote@ +@subsite_name;noquote@ +@header_stuff;noquote@ + +
    @object_name@
    +@overview_with_href_and_mailto;noquote@ + +

    Edit yourthe comment on the @object_type@ "@object_name@".
    + +

    + +@form_vars;noquote@ + + +

    What sort of feedback should this be?

    +

    + + +

    Feedback type: @feedback_category@

    +
    + + +

    Rating : @rating@ out of @scale@ points

    +
    + +

    +

    What comment do you want to make?

    +Here you shall explain, describe or comment your feedback +(i.e. what project did you reuse the information for, +what did you learn, why do think it's outdated or should have +more details, etc.). +

    + + + + +
    + + + +
    +

    +

    +

    + checked> +Add this comment as a public comment to the knowledge object +

    + +
    + + +
    Index: openacs-4/contrib/obsolete-packages/library/www/comment-edit.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/comment-edit.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/comment-edit.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,120 @@ +ad_page_contract { + /packages/library/www/comment-edit.tcl + + Allow the user to edit one of his general comments. + + @author Carsten Clasohm (carsten@arsdigita.com) + @author Timo Hentschel (timo@arsdigita.com) + + @cvs-id $Id: comment-edit.tcl,v 1.1 2003/07/02 12:19:42 peterm Exp $ +} { + comment_id:notnull,integer + {category_id ""} + {path_id:integer ""} +} -properties { + title:onevalue + object_name:onevalue + object_id:onevalue + objec_type:onevalue + overview_with_href_and_mailto:onevalue + content:onevalue + rating:onevalue + scale:onevalue + admin_p:onevalue + feedback_category_id:onevalue + feedback_category:onevalue + public_p:onevalue + categories:multirow + form_vars:onevalue + user_id:onevalue + author_id:onevalue + subsite_url:onevalue + subsite_name:onevalue + header_stuff:onevalue +} + +set user_id [ad_maybe_redirect_for_registration] +set package_id [ad_conn package_id] + +array set node [site_node_closest_ancestor_site_node "acs-subsite"] +set community_id $node(package_id) + +set object_id [km_check_comment_id $user_id $comment_id] +if { !$object_id } { return } + +set object_name [km_conn object_name] +set object_type [km_static object_type_pretty_name [km_conn object_type_id]] + +set author_id [km_conn original_author_id] +set author_name [km_conn original_author_name] + +set admin_p [km_conn admin_p] + +array set node [site_node_closest_ancestor_site_node "acs-subsite"] +set subsite_url $node(url) +set subsite_name $node(instance_name) +set header_stuff "" + +if {$admin_p} { + set title "Edit feedback for \"$object_name\"" + set header "Edit feedback" +} else { + set title "Edit comment on \"$object_name\"" + set header "Edit comment" +} + +set_the_usual_klib_context_bar $object_id $category_id +append_context_bar_data $header +set overview_with_href_and_mailto [util_make_href_and_mailto_links [km_conn overview]] + +template::multirow create categories category_id name deprecated_p level + +db_1row get_comment_data { + select sc.content, sc.html_p, rating, scale, c.category_id as feedback_category_id, + c.long_name as feedback_category, sc.display_p as public_p, sc.user_id as feedback_author_id + from sn_comments sc, categories c + where comment_id=:comment_id + and sc.category_id = c.category_id(+) } + +if {!$admin_p && (($user_id != $feedback_author_id) || [km_conn archived_p])} { + ad_return_forbidden "Only the feedback author or admins can edit feedback!" + return +} + +if { [string eq $html_p "f"] } { + set content [ad_quotehtml $content] +} + +set feedback_object_id 0 +set form_vars [export_form_vars comment_id category_id path_id feedback_category_id] + +if { $admin_p } { + #assuming that only one tree(subtree) is assigned to this object + + set feedback_category_tree_assigned_p [db_0or1row feedback_category_tree { + select gt.tree_name, octr.subtree_root_node_id, gt.root_node_id as original_root_node_id + from generic_trees gt, + acs_rels ar, + object_category_tree_rels octr + where ar.object_id_one = :package_id + and ar.object_id_two = gt.tree_id + and ar.rel_id = octr.rel_id + and rel_type = 'object_category_tree_rel'}] + + if {$feedback_category_tree_assigned_p} { + db_foreach get_one_tree_edit { + select /*+INDEX(sw_category_dim sw_category_dim_long_name) */ category.long_name(object_id) as name, + category.sort_key(object_id) as sort_key, + object_id as fb_category_id, deprecated_p, level + from sw_category_dim + start with node_id = :subtree_root_node_id + connect by prior node_id = parent_node_id + } { + template::multirow append categories $fb_category_id $name $deprecated_p $level + } + + set form_vars [export_form_vars comment_id category_id path_id] + } +} + +ad_return_template Index: openacs-4/contrib/obsolete-packages/library/www/content-link-add.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/content-link-add.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/content-link-add.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,86 @@ +ad_page_contract { + $Id: content-link-add.tcl,v 1.1 2003/07/02 12:19:42 peterm Exp $ +} { + target:integer,notnull + pass:integer,notnull + link_comment +} +csrf::authenticate + +if ![path_valid_p $pass] { + ad_return_error "Invalid Path" \ + "The current path ID is invalid. Perhaps you used your browser's Back button + and tried to add another user?" + return +} +set object_id $target +set user_id [ad_maybe_redirect_for_registration] + +# Determine to which object we are going to add the user reference, +# and if the current user is allowed to do this. + +set values [get_path_values -action_only_p 0 $pass] +set object_id_a [value_from_tuples $values object_id] +set question_id [value_from_tuples $values question_id] + +if ![km_check_object_id -check_edit_p 1 $object_id_a] { return } + +ad_permission_p $target read + +# Hardcoding the link type_id here. +set link_type bi_directional + +set exists_p [db_string content_link_add_10 " + select decode(count(*),0,0,1) from sn_links + where object_id_a=:object_id_a and object_id_b=:object_id"] + +if {!$exists_p} { + db_transaction { + + set new_link_id [db_string content_link_add_15 "select sn_links_seq.nextval from dual"] + + db_dml content_link_add_20 " + insert into sn_links (link_id, link_type, object_id_a, object_id_b, + creation_user, creation_date, link_comment) + select :new_link_id, 'bi_directional', :object_id_a, :object_id, + :user_id, sysdate, :link_comment + from dual + where not exists (select 1 from sn_links + where object_id_a=:object_id_a and object_id_b=:object_id)" + + db_dml content_link_add_25 " + insert into sn_question_link_map (link_id, question_id) + values (:new_link_id, :question_id)" + + db_dml content_link_add_30 " + update acs_objects + set last_modified = sysdate, modifying_user = :user_id + where object_id = :object_id_a" + + db_dml content_link_add_35 " + update sn_objects + set last_modified = sysdate, last_modifying_user_id = :user_id + [km_link_description_update $object_id_a $question_id] + where object_id = :object_id_a" + + db_dml content_link_add_40 " + update acs_objects_description + set state = state + where object_id = :object_id_a" + + set one_line_desc [db_string content_link_add_50 "select shortname + from acs_objects_description + where object_id=:object_id"] + + set audit_comment "Added link to \"$one_line_desc\"" + db_dml content_link_add_60 { + insert into sn_audit_table + (object_id, question_id, last_modified, last_modifying_user_id, content) + values (:object_id_a, :question_id, sysdate, :user_id, :audit_comment)} + +} +} + +# All done, back to the path's origin. + +ad_returnredirect [get_path_return_url $pass] Index: openacs-4/contrib/obsolete-packages/library/www/content-link-delete-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/content-link-delete-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/content-link-delete-2.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,58 @@ +# /www/library/content-link-delete-2.tcl +# +# Delete an object-content link. +# +# $Id: content-link-delete-2.tcl,v 1.1 2003/07/02 12:19:42 peterm Exp $ + +ad_page_variables { + link_id + return_url +} +csrf::authenticate + +set user_id [ad_maybe_redirect_for_registration] + +# We are dealing with object <-> content links here. +# The following query relies on the object being +# referenced by the object_id_a column. + +if {![db_0or1row content_link_delete_2_10 " + select obj1.object_id, obj2.shortname as one_line_description, map.question_id + from sn_links l, sn_objects obj1, acs_objects_description obj2, sn_question_link_map map + where l.link_id=:link_id + and obj1.object_id = l.object_id_a + and obj2.object_id = l.object_id_b + and l.link_id = map.link_id"]} { + # The link already has been deleted. + ad_returnredirect $return_url + return +} + +# Check if the user is authorized to delete this link. + +if ![ad_permission_p $object_id write] { + ad_return_error "Not authorized" "You are not authorized to delete this link." + return +} + +# All checks passed - let's delete the row. + +set audit_comment "Deleted link to '$one_line_description'" + +db_transaction { + db_dml content_link_delete_2_20 "delete from sn_links where link_id=:link_id" + db_dml content_link_delete_2_21 "delete from sn_question_link_map where link_id=:link_id" + + db_dml content_link_delete_2_40 { + insert into sn_audit_table + (object_id, question_id, last_modified, last_modifying_user_id, content) + values (:object_id, :question_id, sysdate, :user_id, :audit_comment)} + + db_dml content_link_delete_2_50 " + update sn_objects + set last_modified = sysdate, last_modifying_user_id = :user_id + [km_link_description_update $object_id $question_id] + where object_id = :object_id" +} + +ad_returnredirect $return_url Index: openacs-4/contrib/obsolete-packages/library/www/content-link-delete.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/content-link-delete.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/content-link-delete.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,22 @@ + +@title;noquote@ + +Are you sure that you want to delete this link? + +

    + + + + +
    +
    + + @form_vars1;noquote@ + + +
    +
    + @form_vars2;noquote@ + +
    +
    Index: openacs-4/contrib/obsolete-packages/library/www/content-link-delete.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/content-link-delete.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/content-link-delete.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,25 @@ +# /www/library/content-link-delete.tcl +# +# Ask for confirmation before deleting a object-content mapping. +# +# $Id: content-link-delete.tcl,v 1.1 2003/07/02 12:19:42 peterm Exp $ + +ad_page_variables { + link_id + object_id + question_id + {category_id ""} +} + +if ![km_check_object_id -check_edit_p 1 $object_id] { return } + +set return_url "one-question-edit?[export_url_vars object_id category_id question_id]" +set title "Delete Link [km_conn object_name]" + +set_the_usual_klib_context_bar $object_id $category_id +append_context_bar_data $title + +set form_vars1 [export_form_vars link_id return_url] +set form_vars2 [export_form_vars object_id category_id question_id] + +ad_return_template Index: openacs-4/contrib/obsolete-packages/library/www/date-filter.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/date-filter.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/date-filter.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,9 @@ +

    + +@form_vars;noquote@ +Start: + + End: + + Index: openacs-4/contrib/obsolete-packages/library/www/date-filter.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/date-filter.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/date-filter.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,26 @@ +if ![info exists presentation_type] { + set presentation_type "custom" +} + + +if ![empty_date_p $start] { + util_unlist [km_break_date $start] start_year start_month start_day +} elseif ![empty_string_p $start_offset] { + db_1row get_start_date "select sysdate+$start_offset as start_date from dual" + util_unlist [km_break_date $start_date] start_year start_month start_day +} else { + set start_year "" + set start_month "" + set start_day "" +} + +if ![empty_date_p $end] { + util_unlist [km_break_date $end] end_year end_month end_day +} elseif ![empty_string_p $end_offset] { + db_1row get_end_date "select sysdate+$end_offset as end_date from dual" + util_unlist [km_break_date $end_date] end_year end_month end_day +} else { + set end_year "" + set end_month "" + set end_day "" +} Index: openacs-4/contrib/obsolete-packages/library/www/delete-audit-trail.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/delete-audit-trail.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/delete-audit-trail.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,43 @@ +ad_page_contract { + /www/library/delete-audit-trail.tcl + + Delete a single row from sn_audit_table. Only admins may do this. + + @cvs-id $Id: delete-audit-trail.tcl,v 1.1 2003/07/02 12:19:42 peterm Exp $ +} { + object_id:notnull,integer + {category_id ""} + rowid:notnull +} +csrf::authenticate + +ad_require_permission [ad_conn package_id] "admin" + +set last_item [db_string last_item { + select max(rowid) + from sn_audit_table + where last_modified = (select max(last_modified) + from sn_audit_table + where object_id = :object_id) +}] + +set del_rowid $rowid + +db_transaction { + + db_dml delete_audit_trail "delete from sn_audit_table where rowid=:del_rowid" + + if { $last_item == $rowid } { + # If we just deleted the last audit item, we have to update the object timestamp. + db_dml update_last_modified { + update sn_objects + set last_modified = (select max(last_modified) + from sn_audit_table + where object_id = :object_id) + where object_id = :object_id + } + } + +} + +ad_returnredirect "object-audit-trail?object_id=$object_id&category_id=$category_id" Index: openacs-4/contrib/obsolete-packages/library/www/file-delete-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/file-delete-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/file-delete-2.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,30 @@ +ad_page_contract { + /www/library/file-delete-2.tcl + + Delete an attached document. + + @cvs-id $Id: file-delete-2.tcl,v 1.1 2003/07/02 12:19:42 peterm Exp $ +} { + object_id:notnull,integer + question_id:notnull,integer + {category_id ""} + {parent_question_id:integer 0} + {return_page "one-question-edit"} +} +csrf::authenticate + +set user_id [ad_maybe_redirect_for_registration] +if ![km_check_object_id -check_edit_p 1 $object_id] { return } + +if [km_is_required -object_id $object_id $question_id] { + ad_return_warning "Required Field" \ + "The attachment is mandatory and therefore may only be + overwritten, but not removed." + return +} + +km_delete_object_data $object_id $question_id + +if { $parent_question_id } { set question_id $parent_question_id } + +ad_returnredirect "$return_page?[export_url_vars object_id category_id question_id]" Index: openacs-4/contrib/obsolete-packages/library/www/file-delete.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/file-delete.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/file-delete.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,23 @@ + +@title;noquote@ + +Do you really wish to remove the attachment "@client_filename@" +from object "@object_name@"? + +

    + + + + +
    +
    + + @form_vars_proceed;noquote@ + + +
    +
    + @form_vars_cancel;noquote@ + +
    +
    Index: openacs-4/contrib/obsolete-packages/library/www/file-delete.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/file-delete.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/file-delete.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,49 @@ +ad_page_contract { + /www/library/file-delete.tcl + + Ask the user for confirmation before deleting an attached document. + + @cvs-id $Id: file-delete.tcl,v 1.1 2003/07/02 12:19:42 peterm Exp $ +} { + object_id:notnull,integer + question_id:notnull,integer + {parent_question_id:integer 0} + {category_id ""} + {return_page "one-question-edit"} +} -properties { + title:onevalue + client_filename:onevalue + object_name:onevalue + form_vars_proceed:onevalue + form_vars_cancel:onevalue + return_page:onevalue +} + +set user_id [ad_maybe_redirect_for_registration] +if ![km_check_object_id -check_edit_p 1 $object_id] { return } + +set client_filename [db_string file_delete_10 " + select content from sn_content + where object_id=:object_id and question_id=:question_id"] + +if [km_is_required -object_id $object_id $question_id] { + ad_return_warning "Required Field" \ + "The attachment is mandatory and therefore may only be + overwritten, but not removed." + return +} + +set object_name [km_conn object_name] +set title "Delete Attached File" + +set_the_usual_klib_context_bar $object_id $category_id +append_context_bar_data $title + +set form_vars_proceed [export_form_vars object_id category_id question_id parent_question_id return_page] + +if { $parent_question_id } { + set question_id $parent_question_id +} +set form_vars_cancel [export_form_vars object_id category_id question_id] + +ad_return_template Index: openacs-4/contrib/obsolete-packages/library/www/form.css =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/form.css,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/form.css 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,5 @@ +p { font-family:verdana,arial,helvetica,sans-serif; font-size:12px; line-height:16px; } +.snbgform { background-color:#dddddd; } +.sntextform { font-family:monospace; } +.sntextformelement { font-size:12px; line-height:14px; font-weight:bold; } +#snattention { color:#ff0000; } Index: openacs-4/contrib/obsolete-packages/library/www/index.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/index.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/index.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,68 @@ + +@title;noquote@ +@search_contexts;noquote@ + +Administer

    + + + Set Alert + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    GraphicBrowse Knowledge ObjectsCreate Knowledge Objects
    + + + + +   + + + @object_types.pretty_plural@ + +
    Archived @object_types.pretty_plural@ +
    +
    + + @object_types.pretty_name@ + +
    Copy a @object_types.pretty_name@ +
    +
    +
    + + +

    Object Approval Tasks

    + + + + + + + + +
    To doOn whatSubmittedStarted
    @task_list.task_name@ @task_list.object_type_pretty@ "@task_list.object_name@@task_list.enabled_date@ by @task_list.submitter_name@ @task_list.started_date@ 
    + Index: openacs-4/contrib/obsolete-packages/library/www/index.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/index.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/index.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,69 @@ +ad_page_contract { + /packages/library/www/admin/index.tcl + + @author Carsten Clasohm (carsten@arsdigita.com) + @author Dirk Gomez (dirk@arsdigita.com) + @author Jens Kordsmeier (jak@arsdigita.com) + + @cvs-id $Id: index.tcl,v 1.1 2003/07/02 12:19:42 peterm Exp $ +} { +} -properties { + context_bar:onevalue + instance_name:onevalue + object_types:multirow + graphic_height:onevalue + graphic_width:onevalue + subsite_url:onevalue + subsite_name:onevalue + subcommunity_id:onevalue + approval_p:onevalue + publish_p:onevalue + admin_p:onevalue +} + +# connection timeout +set user_id [ad_conn user_id] +set package_id [ad_conn package_id] +set instance_name [ad_conn instance_name] + +set return_uri [ad_urlencode "[ad_conn url]?[ad_conn query]"] +set have_alert [alerts::exists] + +set admin_p [ad_permission_p $package_id "admin"] +set create_p [ad_permission_p $package_id "create"] +set publish_p [ad_permission_p $package_id "km_publish"] +set approval_p [km_static approval_p $package_id] + +array set node [site_node_closest_ancestor_site_node "acs-subsite"] +set subsite_url $node(url) +set subsite_name $node(instance_name) +set subcommunity_id $node(package_id) + +db_multirow object_types object_type { + select object_type_id, pretty_name, pretty_plural, graphic, + decode(create_p,'t',1,0) as create_p, + decode(archive_p,'t',1,0) as archive_p, + decode(copy_p,'t',1,0) as copy_p + from sn_object_types + where deleted_p = 'f' + and browse_p = 't' + and (public_p = 't' or :admin_p = 1) + and context_id = :package_id + order by sort_key, pretty_name +} + +set title "Library Index" +set graphic_height [library_icon_height] +set graphic_width [library_icon_width] + +set_context_bar_data + +set cf(package_id) $package_id +portal_approval_processes [array get cf] + +set search_contexts [list \ + [list "lib:$package_id" "$instance_name" ] \ + [list "sc:$subcommunity_id" "$subsite_name" ] \ + [sws_km_site_search_context]] + +ad_return_template Index: openacs-4/contrib/obsolete-packages/library/www/km-checkbox-tag.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-checkbox-tag.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-checkbox-tag.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,3 @@ + + @tags.item;noquote@ @tags.break;noquote@ + Index: openacs-4/contrib/obsolete-packages/library/www/km-checkbox-tag.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-checkbox-tag.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-checkbox-tag.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,49 @@ +# Returns a series of checkboxes with the same name and differing items/values. + +if {![info exists default]} { + set default "" +} + +if {![info exists values]} { + set values {} +} + +if {![info exists verticle_p]} { + set verticle_p 1 +} + +if {![info exists size]} { + set size "" +} + +set counter 0 +set checked_string "" +template::multirow create tags name item_value checked_string item break +foreach item $items { + + set item_value [lindex $values $counter] + foreach default_value $default { + + #figure out if this item is to be checked + if {[string compare $item $default_value] == 0} { + set checked_string "checked" + break + } elseif {[string compare $item_value $default_value] == 0} { + set checked_string "checked" + break + } + set checked_string "" + } + + + if {[empty_string_p $item_value]} { + set item_value $item + } + if { $verticle_p == 0 } { + set break "  " + } else { + set break "
    " + } + template::multirow append tags $name $item_value $checked_string $item $break + incr counter +} Index: openacs-4/contrib/obsolete-packages/library/www/km-content-link-table.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-content-link-table.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-content-link-table.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + +
    NoHeadlineAction

    @content_links.i@

    @content_links.pretty_object;noquote@

    @content_links.link_comment;noquote@

    + Edit linking reason |  + Delete Link
    + Index: openacs-4/contrib/obsolete-packages/library/www/km-content-link-table.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-content-link-table.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-content-link-table.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,50 @@ +# Displays the list of content-object links when existing_links is supplied as +# a list of lists in the order: table_name one_line_description + +if {![info exists edit_p]} { + set edit_p 0 +} + +if {![info exists object_id]} { + set object_id 0 +} + +if {![info exists category_id]} { + set category_id "" +} + +if {![info exists question_id]} { + set question_id 0 +} + +# existing_links + +set return_url "[ns_conn url]?[ns_conn query]" + +template::multirow create content_links i pretty_object delete_url_vars reason_url_vars link_comment +set i 1 +foreach link $existing_links { + set object_id_b [lindex $link 0] + set one_line_description [lindex $link 1] + set link_id [lindex $link 4] + set object_id [lindex $link 5] + set object_type [lindex $link 6] + set presentation [lindex $link 7] + set link_comment [lindex $link 10] + set comment_html_p [lindex $link 11] + + if {![empty_string_p $link_comment]} { + if {$comment_html_p} { + set link_comment "([util_make_href_and_mailto_links $link_comment])" + } else { + set link_comment "([util_make_href_and_mailto_links [ad_quotehtml $link_comment]])" + } + } + + array unset od + array set od [list name [sn_striphtml $one_line_description] presentation $presentation] + + template::multirow append content_links $i [sn_presentation::generic::linkable_item $object_type $object_id_b /o/$object_id_b od] [export_url_vars link_id question_id category_id object_id] [export_url_vars object_id link_id category_id return_url] $link_comment + + incr i +} Index: openacs-4/contrib/obsolete-packages/library/www/km-date-tag.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-date-tag.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-date-tag.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,10 @@ + +   +   + + + +   +   + + Index: openacs-4/contrib/obsolete-packages/library/www/km-date-tag.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-date-tag.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-date-tag.tcl 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,37 @@ +# Returns three-part form elements for date entry: a select box for the month, +# and two small text fields for day and year. + +# named required parameters presentation_type question_id name + + +if {![info exists day_value]} { + set day_value "" +} + +if {![info exists month_value]} { + set month_value "" +} + +if {![info exists year_value]} { + set year_value "" +} + +util_unlist [month_list] months months_values + +if {[string equal $presentation_type "select"]} { + set days [list 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31] + if ![info exists year_from] { + util_unlist [km_get_year_range $question_id] year_from year_to + } + set years [list] + for { set year $year_from } { $year <= $year_to } { incr year } { + lappend years $year + } + if { $year_value < $year_from } { + set years [concat $year_value $years] + } elseif { $year_value > $year_to } { + set years [concat $years $year_value] + } +} + +ad_return_template Index: openacs-4/contrib/obsolete-packages/library/www/km-display-child-object.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-display-child-object.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-display-child-object.adp 2 Jul 2003 12:19:42 -0000 1.1 @@ -0,0 +1,41 @@ + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    No.Content
     @short_desc_list@  @long_pretty_name@ Action

    @children_list.i@

    @children_list.short_description@ [Private] [Archived] [In review]@children_list.long_description@@children_list.long_description@ [Private] [Archived] [In review]

    + + Edit | + + Delete

    +
    Index: openacs-4/contrib/obsolete-packages/library/www/km-display-child-object.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-display-child-object.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-display-child-object.tcl 2 Jul 2003 12:19:43 -0000 1.1 @@ -0,0 +1,87 @@ +# Takes a list of child_object_data and displays the short_description and +# long description in a blue box. + +if {![info exists edit_p]} { + set edit_p 0 +} + +if {![info exists category_id]} { + set category_id "" +} + +if {![info exists child_object_type]} { + set child_object_type 0 +} + +if {![info exists question_state]} { + set question_state "active" +} + +# question_id user_id object_id children + + +if !$child_object_type { + set child_object_type [db_string km_display_child_object_1 " + select target_object_type_id + from sn_questions where question_id=:question_id"] +} +set context_id [ad_conn package_id] + +# We need the pretty name of the short and long descriptions: +db_1row question_info_long_desc { + select nvl(q.question_id,0) as long_p, q.pretty_name as long_pretty_name + from sn_questions q, sn_object_types ot + where ot.long_description = q.question_id(+) + and ot.object_type_id = :child_object_type + and ot.context_id = :context_id +} + +set short_desc_list "" + +db_foreach question_info_short_desc { + select q1.pretty_name as short_pretty_name + from sn_questions q1, sn_types_map_short_name map, sn_object_types ot + where map.short_description = q1.question_id(+) + and map.object_type_id = :child_object_type + and map.object_type_id = ot.object_type_id + and ot.context_id = :context_id + order by position +} { + if {![empty_string_p $short_desc_list]} { + append short_desc_list ", $short_pretty_name" + } else { + set short_desc_list $short_pretty_name + } +} + +if {![empty_string_p $short_desc_list]} { + set short_p 1 +} else { + set short_p 0 +} + +set table "" + +set i 1 + +template::multirow create children_list short_p long_p short_description public_p archived_p review_p edit_p question_state i url_vars long_description +foreach child $children { + util_unlist $child object_id public_p archived_p review_p short_description long_description + + if {[empty_string_p $short_description]} { + set short_description [km_get_object_name $object_id] + } + set short_description [sn_striphtml $short_description] + + template::multirow append children_list $short_p $long_p $short_description $public_p $archived_p $review_p $edit_p $question_state $i [export_url_vars object_id category_id] $long_description + incr i +} + + + + + + + + + Index: openacs-4/contrib/obsolete-packages/library/www/km-display-composite.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-display-composite.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-display-composite.adp 2 Jul 2003 12:19:43 -0000 1.1 @@ -0,0 +1,5 @@ + + + + +
    Index: openacs-4/contrib/obsolete-packages/library/www/km-display-composite.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-display-composite.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-display-composite.tcl 2 Jul 2003 12:19:43 -0000 1.1 @@ -0,0 +1,12 @@ +if {![info exists category_id]} { + set category_id "" +} + +template::multirow create children_list value question_id pretty_name abstract_data_type pretty_question +foreach child $children { + util_unlist $child value question_id pretty_name abstract_data_type + + if [km_answered_p $abstract_data_type $value] { + template::multirow append children_list $value $question_id $pretty_name $abstract_data_type [km_static question_pretty_name $question_id] + } +} Index: openacs-4/contrib/obsolete-packages/library/www/km-display-file.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-display-file.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-display-file.adp 2 Jul 2003 12:19:43 -0000 1.1 @@ -0,0 +1,6 @@ + + @client_filename@ (@file_size@ bytes) + + + Something is wrong with the file. Sorry. + Index: openacs-4/contrib/obsolete-packages/library/www/km-display-file.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-display-file.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-display-file.tcl 2 Jul 2003 12:19:43 -0000 1.1 @@ -0,0 +1,16 @@ +# Link to a downloadable file and show its size. If the document has +# disappeared, tell the user so. + +# object_id question_id client_filename + + +regsub -all {[^-_.0-9a-zA-Z]+} $client_filename "_" url_filename + +if ![catch { set file_size [file size [km_file_path]/$object_id.$question_id] } errmsg] { + set everything_is_okay_p t +} else { + set everything_is_okay_p f + ns_log Warning "Something went wrong with the file [km_file_path]/$object_id.$question_id: $errmsg" +} + + Index: openacs-4/contrib/obsolete-packages/library/www/km-display-nephew-object.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-display-nephew-object.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-display-nephew-object.adp 2 Jul 2003 12:19:43 -0000 1.1 @@ -0,0 +1,65 @@ + + + + +
    + + + + + + + + + + + +@action_caption;noquote@ + + +@table;noquote@ + + + + + + + + + + + + + + + + + +
    No @short_desc_list;noquote@  @long_pretty_name;noquote@ 

    @nephews_list.i@

    @nephews_list.short_description@ + + [Private] + + + [Archived] + + + [In review] + +

    @nephews_list.long_description@@nephews_list.long_description@ + + + [Private] + + + [Archived] + + + [In review] + + +

    + + Edit | + + Delete

    +
    Index: openacs-4/contrib/obsolete-packages/library/www/km-display-nephew-object.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-display-nephew-object.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-display-nephew-object.tcl 2 Jul 2003 12:19:43 -0000 1.1 @@ -0,0 +1,88 @@ +# Takes a list of nephew_object_data and displays the short_description and +# long description in a blue box. + +if {![info exists edit_p]} { + set edit_p 0 +} + +if {![info exists category_id]} { + set category_id "" +} + +if {![info exists nephew_object_type]} { + set nephew_object_type 0 +} + +if {![info exists question_state]} { + set question_state "active" +} + +# question_id user_id object_id nephews + +# Takes a list of nephew_object_data and displays the short_description and +# long description in a blue box. + + +if { $edit_p } { + set action_caption "Action" +} else { + set action_caption "" +} +if !$nephew_object_type { + set nephew_object_type [km_static question_target_object_type_id $question_id] +} +set context_id [ad_conn package_id] + +# We need the pretty name of the short and long descriptions: +db_1row question_info_long_desc { + select nvl2(q.question_id,1,0) as long_p, q.pretty_name as long_pretty_name + from sn_questions q, sn_object_types ot + where ot.long_description = q.question_id(+) + and ot.object_type_id = :nephew_object_type + and ot.context_id = :context_id +} + +set short_desc_list "" +db_foreach question_info_short_desc { + select q1.pretty_name as short_pretty_name + from sn_questions q1, sn_types_map_short_name map, sn_object_types ot + where map.short_description = q1.question_id(+) + and map.object_type_id = :nephew_object_type + and map.object_type_id = ot.object_type_id + and ot.context_id = :context_id + order by position +} { + if {![empty_string_p $short_desc_list]} { + append short_desc_list ", $short_pretty_name" + } else { + set short_desc_list $short_pretty_name + } +} + +if {![empty_string_p $short_desc_list]} { + set short_p 1 + set short_desc_list [join $short_desc_list ", "] +} else { + set short_p 0 +} + +set table "" + +set i 1 +template::multirow create nephews_list edit_p question_state i short_p long_p short_description public_p archived_p review_p url_vars long_description + +foreach nephew $nephews { + util_unlist $nephew object_id public_p archived_p review_p short_description long_description + + set short_description "" + if { $short_p } { + if {[empty_string_p $short_description]} { + set short_description [km_get_object_name $object_id] + } + set short_description [sn_striphtml $short_description] + } + + template::multirow append nephews_list $edit_p $question_state $i $short_p $long_p $short_description $public_p $archived_p $review_p [export_url_vars object_id category_id] [util_trim_string_with_hrefs $long_description] + incr i +} + Index: openacs-4/contrib/obsolete-packages/library/www/km-display-question-answer.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-display-question-answer.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-display-question-answer.adp 2 Jul 2003 12:19:43 -0000 1.1 @@ -0,0 +1,68 @@ + + + + + + @pretty_question;noquote@ + + + + +   + + + + + + + + @text_value;noquote@ + + + + @integer_value@ + + + + + + + + + + + + + + + + + + + + + + + + @option_value@ + + + + @category_value@ + + + + @category_value@ + + + + @date_value@ + + + + + + + + + Index: openacs-4/contrib/obsolete-packages/library/www/km-display-question-answer.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-display-question-answer.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-display-question-answer.tcl 2 Jul 2003 12:19:43 -0000 1.1 @@ -0,0 +1,88 @@ +if {![info exists pretty_question]} { + set pretty_question "" +} + +if {![info exists value]} { + set value "" +} + +if {![info exists category_id]} { + set category_id "" +} + +if {![info exists edit_p]} { + set edit_p 0 +} + +if {![info exists branch_p]} { + set branch_p "" +} + +if {![info exists root_branch_p]} { + set root_branch_p "" +} + +if {![info exists value_only_p]} { + set value_only_p 0 +} + +set answered_p [km_answered_p $abstract_data_type $value] + +if {$answered_p} { + set user_id [ad_conn user_id] + if {[empty_string_p $root_branch_p]} { + set root_branch_p [km_root_branch_p $question_id] + } + + if { [empty_string_p $branch_p] || $branch_p } { + set object_type_id [km_conn object_type_id] + set branch_parent [km_branch_parent $question_id $object_type_id] + } else { + set branch_parent "" + } + + switch $abstract_data_type { + "category" { + set category_value [km_display_category_value $value] + } + "other_category" { + set category_value [km_display_other_category_value $value $object_id $question_id] + } + "option" { + set option_value [km_display_options $value] + } + "date" { + set date_value [util_AnsiDatetoPrettyDate [fst $value]] + } + "text" { + set text_value [fst $value] + if [empty_string_p $text_value] { return "" } + + set html_p [snd $value] + + if { [empty_string_p $html_p] || !$html_p == 1 } { + set text_value [ad_text_to_html -- $text_value] + } else { + set text_value [ad_activate_hyperlinks $text_value] + } + } + "integer" { + set integer_value [fst $value] + } + } + + if {($edit_p && ![km_conn archived_p]) || [km_conn admin_p]} { + # The edit links on object-view.tcl are set according to abstract_data_type: + if { $abstract_data_type == "object_link" } { + set pretty_question "[sn_striphtml $pretty_question]" + } else { + set pretty_question "[sn_striphtml $pretty_question]" + } + } else { + set pretty_question $pretty_question + } + + if {![empty_string_p $branch_parent]} { + set pretty_question "... $pretty_question" + } +} Index: openacs-4/contrib/obsolete-packages/library/www/km-form.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-form.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-form.adp 2 Jul 2003 12:19:43 -0000 1.1 @@ -0,0 +1,83 @@ + + + + +
    +

    @fields.pretty_name;noquote@

    +
    + +

    @fields.entry_explanation;noquote@

    +
    + +

    @fields.entry_explanation;noquote@

    +
    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Show + category descriptions +
    + +
    + + + + + + +
    Show + category descriptions +
    + +
    + +

    +
    Index: openacs-4/contrib/obsolete-packages/library/www/km-form.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-form.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-form.tcl 2 Jul 2003 12:19:43 -0000 1.1 @@ -0,0 +1,239 @@ +# Given an object_type_id or a question_id, this proc returns a +# create/edit form. You will only see values for a given object if you +# pass its object_id and set show_values_p 1. You set question_id if you +# just want to see one question. Important!!! YOU have to put in the +# form tags around this html. + +if {![info exists object_id]} { + set object_id 0 +} + +if {![info exists category_id]} { + set category_id "" +} + +if {![info exists show_values_p]} { + set show_values_p 0 +} + +if {![info exists all_types_p]} { + set all_types_p 0 +} + +if {![info exists form_view]} { + set form_view 1 +} + +if {![info exists question_ids]} { + set question_ids {} +} + +if {![info exists object_type_id]} { + set object_type_id 0 +} + +if {![info exists user_id]} { + set user_id 0 +} + +if {![info exists edit_p]} { + set edit_p 0 +} + +if {![info exists path_id]} { + set path_id "" +} + +if {![info exists fields_only_p]} { + set fields_only_p 0 +} + +if {![info exists mandatory_p]} { + set mandatory_p 0 +} + +if {![info exists ancestor_id]} { + set ancestor_id 0 +} + +if { $object_id && $show_values_p } { + set question_states {active deprecated read-only} + if {$all_types_p} { + lappend question_states invisible + } +} else { + set question_states {active} +} + +if ![null_p $question_ids] { + set questions [km_get_questions -question_states $question_states -question_ids $question_ids -root_node_p 0 -all_properties_p 1] +} elseif { $object_type_id } { + if { $mandatory_p } { set form_view "" } + set questions [km_get_questions -question_states $question_states -form_view $form_view -branch_children_p 0 -mandatory_p $mandatory_p -all_properties_p 1 -object_type_id $object_type_id] +} else { + return +} + +if { $object_id && $show_values_p } { + # try to display some values - the proc get_object_data expects a *keyed* list + set values [km_get_object_data -answers_only_p 1 -questions $questions $object_id] +} else { + set values {} +} + +# Separate the key list and the questions list. +set key [head $questions] +set questions [tail $questions] + +set counter 0 +set html "" +set question_id_ix [lsearch $key "question_id"] +set abstract_data_type_ix [lsearch $key "abstract_data_type"] +set pretty_name_ix [lsearch $key "pretty_name"] +set presentation_type_ix [lsearch $key "presentation_type"] +set entry_explanation_ix [lsearch $key "entry_explanation"] +set height_ix [lsearch $key "tag_height"] +set width_ix [lsearch $key "tag_width"] +set mandatory_p_ix [lsearch $key "mandatory_p"] +set question_state_ix [lsearch $key "question_state"] +set defaults_question_id_ix [lsearch $key "defaults_question_id"] + +if !$user_id { set user_id [ad_get_user_id] } +set return_url "[ns_conn url]?[ns_conn query]" + +template::multirow create fields object_id pretty_name abstract_data_type question_state entry_explanation height width value html_p presentation_type question_id question_state items item_values option_ids new_path_id descriptions option_ids option_answers other_value mandatory_p + +foreach question $questions { + + set value [lindex $values $counter] + set question_id [lindex $question $question_id_ix] + set abstract_data_type [lindex $question $abstract_data_type_ix] + set pretty_name [lindex $question $pretty_name_ix] + set presentation_type [lindex $question $presentation_type_ix] + set entry_explanation [lindex $question $entry_explanation_ix] + set height [lindex $question $height_ix] + set width [lindex $question $width_ix] + set mandatory_p [lindex $question $mandatory_p_ix] + set question_state [lindex $question $question_state_ix] + set defaults_question_id [lindex $question $defaults_question_id_ix] + set items "" + set item_values "" + set option_ids "" + set new_path_id "" + set descriptions "" + set html_p 0 + set option_ids "" + set option_answers "" + set other_value "" + set other_value_def "" + incr counter + + # if a default for this question should be taken from ancestor object, + # get the default if no value has been provided yet + if {([empty_string_p $value]) && ($ancestor_id > 0) && ($defaults_question_id > 0)} { + switch $abstract_data_type { + "text" - "integer" - "date" { + db_0or1row get_default_content { + select content as value, html_p + from sn_content + where question_id = :defaults_question_id + and object_id = :ancestor_id + } + if {[string equal $abstract_data_type "text"]} { + set value [list $value $html_p] + } + } + "category" { + set value [km_get_categories $ancestor_id $defaults_question_id] + } + "other_category" { + set value [km_get_categories $ancestor_id $defaults_question_id] + db_0or1row get_default_other_value_field { + select content as other_value_def + from sn_content + where question_id = :defaults_question_id + and object_id = :ancestor_id + } + } + } + } + + if { $question_state != "active" && ![km_answered_p $abstract_data_type $value] } { + # Don't show deprecated or read-only questions which haven't been answered yet. + continue + } + + if { $mandatory_p == "t" } { + set pretty_name "$pretty_name *" + } + + # Call the proc that know how to display this abstract_data_type. + switch $abstract_data_type { + "date" { + set value [fst $value] + } + "object_link" { + set path_vars [set_path_values -question_id $question_id $object_id $category_id] + set new_path_id [init_path -last_path_id $path_id $path_vars $return_url link] + } + "option" { + # Get the answer options for this question + util_unlist [transpose [km_get_answer_options $question_id]] \ + option_ids option_answers + + set value [fst [transpose $value]] + if {![empty_string_p $value]} { + #pass the list of checked items + set item_values [fst [transpose $value]] + } + } + "category" { + # Get the categories for this question + set item_values {} + set items {} + set descriptions {} + set show_descriptions_p 0 + foreach category [km_get_child_categories $question_id] { + util_unlist $category category_id category_name description node_id level + + lappend item_values $category_id + lappend items "[gt_repeat_string " " [expr $level*4]]$category_name" + lappend descriptions $description + + if { ![empty_string_p $description] } { set show_descriptions_p 1 } + } + if { !$show_descriptions_p } { set descriptions "" } + + if { ![null_p $value] } { set value [fst [transpose $value]] } + } + "other_category" { + # Get the categories for this question + set item_values {} + set items {} + set descriptions {} + set show_descriptions_p 0 + foreach category [km_get_child_categories $question_id] { + util_unlist $category category_id category_name description node_id level + + lappend item_values $category_id + lappend items "[gt_repeat_string " " [expr $level*4]]$category_name" + lappend descriptions $description + + if { ![empty_string_p $description] } { set show_descriptions_p 1 } + } + if { !$show_descriptions_p } { set descriptions "" } + + + set other_value [snd [fst [km_get_object_content -question_ids [list $question_id] $object_id]]] + if [empty_string_p $other_value] { set other_value $other_value_def } + + if { ![null_p $value] } { set value [fst [transpose $value]] } + } + "text" { + set html_p [snd $value] + set value [fst $value] + } + } + + template::multirow append fields $object_id $pretty_name $abstract_data_type $question_state $entry_explanation $height $width $value $html_p $presentation_type $question_id $question_state $items $item_values $option_ids $new_path_id $descriptions $option_ids $option_answers $other_value $mandatory_p +} Index: openacs-4/contrib/obsolete-packages/library/www/km-input-tag.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-input-tag.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-input-tag.adp 2 Jul 2003 12:19:43 -0000 1.1 @@ -0,0 +1 @@ + Index: openacs-4/contrib/obsolete-packages/library/www/km-input-tag.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-input-tag.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-input-tag.tcl 2 Jul 2003 12:19:43 -0000 1.1 @@ -0,0 +1,15 @@ +if {![info exists size] || [empty_string_p $size]} { + set size 60 +} + +if {![info exists maxlength]} { + set maxlength 199 +} + +if {![info exists value]} { + set value "" +} + +set value $value + +ad_return_template Index: openacs-4/contrib/obsolete-packages/library/www/km-linked-object-list.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/obsolete-packages/library/www/km-linked-object-list.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/contrib/obsolete-packages/library/www/km-linked-object-list.adp 2 Jul 2003 12:19:43 -0000 1.1 @@ -0,0 +1,74 @@ + + +