Index: openacs-4/ChangeLog =================================================================== RCS file: /usr/local/cvsroot/openacs-4/ChangeLog,v diff -u -N -r1.4 -r1.5 --- openacs-4/ChangeLog 20 Apr 2004 21:12:18 -0000 1.4 +++ openacs-4/ChangeLog 12 Jul 2004 14:49:33 -0000 1.5 @@ -1,543 +1,633 @@ -2004-04-18 00:24 lars +2004-07-03 01:21 gabrielb - * packages/acs-subsite/www/resources/site-master.css: Changed from - #developer-support-footer to .developer-support-footer + * www/blank-master.adp: Moved the textarea out of and added + required fields so it validates properly on validator.w3.org. -2004-04-18 00:12 lars +2004-07-02 18:26 jader - * packages/acs-tcl/tcl/community-core-procs.tcl: Fixed bug #1425: - person::update and party::update assume object is a user + * packages/acs-admin/www/developer.adp: Bug 1944: spelling mistake -2004-04-18 00:06 lars +2004-07-02 14:37 jeffd - * packages/acs-tcl/tcl/text-html-procs.tcl: Fixed bug #1450: Don't - dress img src URLs as links + * packages/acs-subsite/www/user/portrait/upload-2-postgresql.xql: + somehow had a oacs-5-0 version of this file, fix for n_bytes on + portrait upload -2004-04-17 23:38 lars +2004-07-02 13:40 jeffd - * packages/acs-admin/www/install/install.tcl: Made the package name - be a link to install the package, instead of having a separate - link at the far right side + * packages/acs-subsite/www/user/portrait/: upload-2-oracle.xql, + upload-2.tcl: remove inline sql from upload-2.tcl, clean up code, + set content_length on new upload -2004-04-17 23:32 lars +2004-07-01 22:18 donb - * packages/acs-admin/www/install/: index.adp, index.tcl, - install.adp, install.tcl: Implemented first step towards merging - the six different install options - now there are just 4 + * + packages/acs-kernel/sql/postgresql/upgrade/upgrade-5.1.1d1-5.1.1d2.sql: + Wouldn't let me tag after adding to HEAD so am committing + directly... -2004-04-17 23:31 lars +2004-07-01 22:12 donb - * packages/acs-tcl/tcl/00-database-procs.tcl: Added doc for - -unclobber switch to db_mutlirow + * + packages/acs-kernel/sql/postgresql/upgrade/upgrade-5.1.1d1-5.1.1d2.sql: + Oops did this wrong ... want to do exactly what Andrew did for + consistency -2004-04-17 23:31 lars +2004-07-01 22:09 donb - * packages/acs-templating/tcl/query-procs.tcl: - Added -unclobber - switch to template::multirow - Added local emacs code to set - indent level to 2 + * + packages/acs-kernel/sql/postgresql/upgrade/upgrade-5.1.1d1-5.1.1d2.sql: + Upgrade to apply previous register parameter bug fix -2004-04-17 16:11 jeffd +2004-07-01 15:01 jeffd - * packages/acs-core-docs/www/: files/groups.dia, files/openacs.txt, - files/tutorial/myfirstpackage-procs.tcl, - images/group-initial.png, images/group-model.png, - images/i18n-1.png, images/i18n-2.png, images/i18n-3.png, - images/production.dia, images/upgrade-cvs.png, xml/index.xml, - xml/developers-guide/i18n.xml, - xml/developers-guide/permissions.xml, - xml/developers-guide/tutorial-advanced.xml, - xml/developers-guide/tutorial-debug.xml, - xml/install-guide/aolserver4.xml, - xml/install-guide/maintenance.xml, - xml/install-guide/other-software.xml, - xml/install-guide/upgrade.xml: merge docbook docs from HEAD to - oacs-5-1 branch + * packages/acs-authentication/tcl/authority-procs.tcl: the sequence + for authority_id should be acs_object_id_seq not + auth_authority_id_seq (which does not exist) -2004-04-16 19:30 lars +2004-06-30 22:04 andrewg - * packages/acs-subsite/tcl/application-group-procs-oracle.xql: - Fixed bug #1526 - -2004-04-16 19:21 lars - - * packages/acs-templating/www/doc/tagref/include.html: Applied - patch #446 to fix bug #1594 - -2004-04-16 18:56 lars - - * packages/acs-templating/tcl/list-procs.tcl: Applied patch #476 to - fix bug #1687: listbuilder paginator doesn't cache all pages - -2004-04-16 18:14 lars - - * packages/acs-templating/tcl/list-procs.tcl: Fix list-builder to - allow using a variable for the list name instead of having to put - a hard value there - -2004-04-16 16:40 lars - - * packages/acs-service-contract/tcl/: - acs-service-contract-init.tcl, acs-service-contract-procs.tcl: - Pass in impl_alias and impl_pl directly to acs_sc_proc, which - avoids calling the expensive acs_sc_get_alias proc - -2004-04-16 16:38 lars - - * packages/acs-service-contract/tcl/implementation-procs.tcl: - Clarified unfinished nature of proc through clear comment - -2004-04-08 04:42 daveb - * - packages/acs-content-repository/sql/postgresql/upgrade/upgrade-5.0.0-5.1.0d1.sql: - Fix typos in content_item__move, add missing content_folder__move - function with name parameter, and cr_items_tree_update_tr along - with upgrade script. + packages/acs-kernel/sql/oracle/upgrade/upgrade-5.1.1d1-5.1.1d2.sql: + Update to apm package body in v1.26.2.1 of apm-create.sql,to + include a bugfix/simplication to the cursor in + apm.register_parameter. -2004-04-07 21:40 daveb +2004-06-30 20:16 donb - * packages/acs-content-repository/tcl/revision-procs.xql: - Add content-length to get_revision_info query. + * packages/acs-kernel/sql/postgresql/apm-create.sql: Ported + Andrew's Oracle register parameter patch. -2004-04-05 03:13 daveb +2004-06-29 18:38 jader - * packages/acs-content-repository/sql/oracle/content-revision.sql: - Copy content_length when copying a content_revision, otherwise - copied revisions end up with NULL content length. + * www/site-master.adp: Changed wording from users to members. See + http://openacs.org/forums/message-view?message_id=192598 -2004-04-04 14:29 joela +2004-06-27 13:30 joela - * etc/analog.cfg: added LOGFORMAT for bug 1359 + * packages/acs-authentication/catalog/: + acs-authentication.da_DK.ISO-8859-1.xml, + acs-authentication.es_ES.ISO-8859-1.xml, + acs-authentication.nl_NL.ISO-8859-1.xml, + acs-authentication.pl_PL.utf-8.xml: adding new translation + catalogs -2004-04-02 23:00 andrewg +2004-06-27 13:25 joela - * packages/acs-tcl/tcl/defs-procs.tcl: Fixed a simple bug in - deprecated proc ad_admin_footer. + * packages/: + acs-authentication/catalog/acs-authentication.ar_LB.utf-8.xml, + acs-authentication/catalog/acs-authentication.es_GT.ISO-8859-1.xml, + acs-authentication/catalog/acs-authentication.fa_IR.utf-8.xml, + acs-authentication/catalog/acs-authentication.zh_CN.utf-8.xml, + acs-kernel/catalog/acs-kernel.AR_EG.utf-8.xml, + acs-kernel/catalog/acs-kernel.AR_LB.utf-8.xml, + acs-kernel/catalog/acs-kernel.RO_RO.utf-8.xml, + acs-kernel/catalog/acs-kernel.ar_EG.utf-8.xml, + acs-kernel/catalog/acs-kernel.ar_LB.utf-8.xml, + acs-kernel/catalog/acs-kernel.da_DK.ISO-8859-1.xml, + acs-kernel/catalog/acs-kernel.en_US.ISO-8859-1.xml, + acs-kernel/catalog/acs-kernel.es_ES.ISO-8859-1.xml, + acs-kernel/catalog/acs-kernel.es_GT.ISO-8859-1.xml, + acs-kernel/catalog/acs-kernel.nl_NL.ISO-8859-1.xml, + acs-kernel/catalog/acs-kernel.pl_PL.utf-8.xml, + acs-kernel/catalog/acs-kernel.ro_RO.utf-8.xml, + acs-kernel/catalog/acs-kernel.zh_CN.utf-8.xml, + acs-lang/catalog/acs-lang.AR_EG.utf-8.xml, + acs-lang/catalog/acs-lang.AR_LB.utf-8.xml, + acs-lang/catalog/acs-lang.RO_RO.utf-8.xml, + acs-lang/catalog/acs-lang.TH_TH.utf-8.xml, + acs-lang/catalog/acs-lang.ar_EG.utf-8.xml, + acs-lang/catalog/acs-lang.ar_LB.utf-8.xml, + acs-lang/catalog/acs-lang.da_DK.ISO-8859-1.xml, + acs-lang/catalog/acs-lang.de_DE.ISO-8859-1.xml, + acs-lang/catalog/acs-lang.en_US.ISO-8859-1.xml, + acs-lang/catalog/acs-lang.es_GT.ISO-8859-1.xml, + acs-lang/catalog/acs-lang.fa_IR.utf-8.xml, + acs-lang/catalog/acs-lang.fi_FI.utf-8.xml, + acs-lang/catalog/acs-lang.nl_NL.ISO-8859-1.xml, + acs-lang/catalog/acs-lang.ro_RO.utf-8.xml, + acs-lang/catalog/acs-lang.th_TH.utf-8.xml, + acs-lang/catalog/acs-lang.zh_CN.utf-8.xml, + acs-subsite/catalog/acs-subsite.AR_EG.utf-8.xml, + acs-subsite/catalog/acs-subsite.AR_LB.utf-8.xml, + acs-subsite/catalog/acs-subsite.RO_RO.utf-8.xml, + acs-subsite/catalog/acs-subsite.ar_EG.utf-8.xml, + acs-subsite/catalog/acs-subsite.ar_LB.utf-8.xml, + acs-subsite/catalog/acs-subsite.da_DK.ISO-8859-1.xml, + acs-subsite/catalog/acs-subsite.es_ES.ISO-8859-1.xml, + acs-subsite/catalog/acs-subsite.es_GT.ISO-8859-1.xml, + acs-subsite/catalog/acs-subsite.nl_NL.ISO-8859-1.xml, + acs-subsite/catalog/acs-subsite.ro_RO.utf-8.xml, + acs-subsite/catalog/acs-subsite.zh_CN.utf-8.xml, + acs-tcl/catalog/acs-tcl.AR_EG.utf-8.xml, + acs-tcl/catalog/acs-tcl.AR_LB.utf-8.xml, + acs-tcl/catalog/acs-tcl.FA_IR.utf-8.xml, + acs-tcl/catalog/acs-tcl.RO_RO.utf-8.xml, + acs-tcl/catalog/acs-tcl.ar_EG.utf-8.xml, + acs-tcl/catalog/acs-tcl.ar_LB.utf-8.xml, + acs-tcl/catalog/acs-tcl.es_GT.ISO-8859-1.xml, + acs-tcl/catalog/acs-tcl.fa_IR.utf-8.xml, + acs-tcl/catalog/acs-tcl.ro_RO.utf-8.xml, + acs-tcl/catalog/acs-tcl.zh_CN.utf-8.xml, + acs-templating/catalog/acs-templating.RO_RO.utf-8.xml, + acs-templating/catalog/acs-templating.ar_LB.utf-8.xml, + acs-templating/catalog/acs-templating.da_DK.ISO-8859-1.xml, + acs-templating/catalog/acs-templating.es_ES.ISO-8859-1.xml, + acs-templating/catalog/acs-templating.es_GT.ISO-8859-1.xml, + acs-templating/catalog/acs-templating.nl_NL.ISO-8859-1.xml, + acs-templating/catalog/acs-templating.ro_RO.utf-8.xml, + acs-templating/catalog/acs-templating.zh_CN.utf-8.xml: updated + catalog files for 5.1.1; bug fix for 1519 means all catalog files + for ar_EG, ar_LB, zh_CN, th_TH, ro_RO, fa_IR, and hr_HR were + renamed to correct capitalization errors -2004-04-01 03:50 daveb +2004-06-26 16:04 joela - * packages/acs-content-repository/tcl/revision-procs.tcl: Add - support for Content-Length header and HEAD method to - cr_write_content for lob storage method. Include Jeff's trick to - output a correct content-length for file storage items from - ns_returnfile. + * packages/acs-lang/sql/: + oracle/upgrade/upgrade-5.1.1d1-5.1.1d2.sql, + postgresql/upgrade/upgrade-5.1.1d1-5.1.1d2.sql: typo in fa_IR + upgrade -2004-04-01 03:34 daveb +2004-06-26 15:52 joela - * packages/acs-kernel/acs-kernel.info: Add href to allowed - attributes and remove *. Fix bug#1310 + * packages/acs-lang/: catalog/acs-lang.es_ES.ISO-8859-1.xml, + sql/oracle/ad-locales.sql, + sql/oracle/upgrade/upgrade-5.1.1d1-5.1.1d2.sql, + sql/postgresql/ad-locales.sql, + sql/postgresql/upgrade/upgrade-5.1.1d1-5.1.1d2.sql: fixing bug + 1519 - misnamed locales -2004-04-01 03:20 daveb +2004-06-25 02:16 andrewg - * packages/acs-content-repository/tcl/: revision-procs-oracle.xql, - revision-procs-postgresql.xql, revision-procs.tcl: Fix - content-length support to use proper header name and actually - check in the queries that grab content length from cr_revisions. + * packages/acs-kernel/sql/oracle/apm-create.sql: Simplifying the + cursor in apm.register_parameter to fix a bug, and make it + simpler. Don's doing the PG version. -2004-03-31 05:14 daveb +2004-06-23 20:37 olah - * packages/acs-content-repository/tcl/revision-procs.tcl: Fix - reference to outputheaders, it should have been all lowercase. + * www/site-master.tcl: Using site_node::get_package_url to check + for mounted curriculum instances, now that it is implemented with + an nsv of url keyed by package key. Lars added this back in mars + and I hadn't noticed ... -2004-03-30 17:36 jeffd +2004-06-21 21:17 janine - * etc/config.tcl: add LOCK and UNLOCK to the tDAV options + * packages/acs-lang/www/admin/message-list.tcl: query didn't work + in oracle (should be in an xql file but at least this will make + it work) -2004-03-29 12:05 joela +2004-06-21 15:18 maltes - * packages/acs-lang/acs-lang.info: retagged packages to 5.1.0b1 + * etc/keepalive/: keepalive-config.tcl, keepalive-cron.sh, + keepalive.sh: Added cron support for keepalive -2004-03-27 14:31 daveb +2004-06-19 23:06 janine - * packages/acs-content-repository/tcl/item-procs-postgresql.xql: - set_live should be set_live_revision. bug#1686 + * packages/: acs-kernel/acs-kernel.info, + acs-subsite/acs-subsite.info, acs-tcl/tcl/admin-init.tcl: fix + from Sloan: allow admin to restrict to registered users on a + per-subsite basis -2004-03-26 17:02 peterm +2004-06-19 22:54 janine - * packages/acs-lang/catalog/acs-lang.fi_FI.utf-8.xml: adding - missing space in the localization-abmon message + * packages/acs-subsite/www/user/portrait/index.adp: fix from Sloan: + only show 'this is what we show other users' message to admins, + which includes the user looking at their own portrait -2004-03-26 15:43 gyang +2004-06-16 10:53 maltes - * packages/acs-subsite/www/admin/applications/application-add.tcl: - Fixed Bug #1563 by applying Patch #443 + * packages/acs-service-contract/www/index.tcl: Page broken due to + Orphans not having an owner. I took the owner out, if someone + disagrees, please fix ... -2004-03-26 15:38 gyang +2004-06-15 17:52 andrewg - * packages/: acs-tcl/tcl/apm-install-procs.tcl, - acs-admin/www/install/install.tcl: Fixed Bug #1646 by applying - Patch #1646 with modifications for a typo + * packages/acs-tcl/tcl/site-nodes-procs.tcl: Fixed a scalability + problem in site_node::update_cache -2004-03-26 14:46 gyang +2004-06-15 17:48 andrewg - * packages/: acs-authentication/tcl/local-procs.tcl, - acs-subsite/lib/user-new.tcl: Partial fix of Bug #1424 by - applying Patch #474 + * + packages/acs-kernel/sql/oracle/upgrade/upgrade-5.0.0b4-5.0.0b5.sql: + Applied Dave's bugfix for \#1419 here to fix the same bug -2004-03-26 14:33 peterm +2004-06-14 19:55 janine - * packages/acs-lang/www/admin/message-list.tcl: making sure the - message counts are correct. Not displaying deleted messages - except when you chooose deleted in the filter + * packages/acs-tcl/tcl/text-html-procs.tcl: fix from Sloan - 100 + iterations was not enough in some cases -2004-03-26 12:15 peterm +2004-06-14 19:49 janine - * packages/acs-subsite/www/permissions/one.tcl: The check on the - permissions/one page to prevent the admin from revoking read - permission for the public on the main site package was broken. - Fixes bug 1680 + * packages/acs-tcl/tcl/: rollout-email-init.tcl, + rollout-email-procs.tcl: update from Sloan -2004-03-26 10:55 bdolicki +2004-06-12 16:27 maltes - * packages/acs-templating/tcl/date-procs.tcl: This was accidentally - commited on HEAD instead of on oacs-5-1 + * etc/keepalive/keepalive-cron.sh: Added keepalive-cron.sh to be + used in a cron environment, where root does not get an email + every two minutes -2004-03-26 10:05 bdolicki +2004-06-12 13:00 maltes - * packages/: acs-tcl/tcl/apm-procs.tcl, - acs-templating/tcl/date-init.tcl: Part of this commit is fixing - #1176 (just a few acs-lang strings and properly splitting the - file into *-proc.tcl and *-init.tcl part). Part of this fix - (catalog file) was accidentally commited before by Joel + * packages/acs-core-docs/www/: xml/install-guide/aolserver4.xml, + aolserver4.html: Changed to use latest AOLserver (40r5). Fixed + small inconsistency. - The bigger part is changing load order of library files so that - acs-lang-init.tcl gets loaded before all other *-init.tcl files. +2004-06-11 22:43 janine - This is necessary because acs-lang is so fundamental and it is - quite possible (as we have seen with the example of - date-init.tcl) that there are *-init.tcl files that need - translated strings. + * + packages/acs-content-repository/sql/oracle/upgrade/upgrade-4.6.2-4.6.3.sql: + list columns to insert into (fix from Sloan) -2004-03-26 09:20 joela +2004-06-11 22:42 janine - * etc/backup.sh: fixed typo in backup.sh - bug 1658 + * + packages/acs-content-repository/sql/oracle/upgrade/upgrade-4.6.1-4.6.2.sql: + merge fix from head -2004-03-26 09:11 joela +2004-06-10 08:41 maltes - * packages/acs-tcl/tcl/utilities-init.tcl: adding error log rolling - scheduled proc + * etc/config.tcl: Changed the maxinput to 5MB with 1024*1024 + syntax. Added recvwait parameter. -2004-03-25 19:36 jeffd +2004-06-08 10:52 maltes - * packages/: acs-authentication/tcl/authority-procs.tcl, - acs-tcl/tcl/site-nodes-procs.tcl, - acs-templating/tcl/list-procs.tcl, - acs-templating/tcl/widget-procs.tcl: fix the very common error of - calling empty_string_p with var instead of $var + * etc/config.tcl: Added maxinput parameter. Set it to 5MB, which + allows OpenACS parameter to kick in more effectively. See + http://openacs.org/forums/message-view?message_id=161698 -2004-03-25 19:19 peterm +2004-06-07 18:56 jeffd - * packages/acs-subsite/www/register/user-join.tcl: removing abort - switch from call to ad_returnredirect (switch no longer - supported) + * + packages/acs-kernel/sql/postgresql/upgrade/upgrade-5.0d2-5.0d3.sql: + do not create the cc_users_of_package_id view since we dont + create application_users view anymore so its not used -2004-03-25 18:46 gyang +2004-06-02 18:26 lars - * packages/acs-subsite/tcl/group-type-procs.tcl: Fixed Bug #1187 by - applying Patch #472 + * packages/acs-tcl/tcl/: acs-permissions-procs.tcl, + security-procs.tcl: Fixed bug when bumping to login page from + within permission_p, but permission_p was called form within + ad_get_login_url, which is the proc that determines which login + page to use -2004-03-25 18:42 peterm +2004-06-02 01:24 donb - * packages/acs-templating/resources/lists/table.adp: making sure - elements.label is always noquoted for consistency. Fixing bug - 1184 + * packages/acs-content-repository/: acs-content-repository.info, + sql/oracle/upgrade/upgrade-4.7d6-5.0d1.sql, + sql/oracle/upgrade/upgrade-5.1.0-5.1.1.sql, + sql/oracle/upgrade/upgrade-5.1.1-5.1.2.sql, + sql/postgresql/upgrade/upgrade-5.1.1-5.1.2.sql: I'd accidently + changed some old upgrade files to use edit_name rather than + rename (for Oracle 9.2) and had not added the needed upgrade + files for 5.1. -2004-03-25 18:40 joela +2004-06-01 17:35 peterm - * packages/acs-subsite/: catalog/acs-subsite.en_US.ISO-8859-1.xml, - lib/user-info.adp, www/user/basic-info-update.tcl: added two keys - for bug #962 + * packages/acs-subsite/www/admin/: parties/new.tcl, users/new.tcl: + Making call to relation_add (on pages parties/new and users/new) + not use the form_id and variable_prefix switches as doing so + would make package_instantiate_object look for a rel_id in the + form which wasn't there. This is analogous to fix in version 1.5 + of groups/new. -2004-03-25 18:39 joela +2004-05-31 20:51 gabrielb - * packages/acs-core-docs/www/index.adp: changed formatting so that - lists are not centered in IE + * packages/acs-lang/tcl/: lang-util-procs-oracle.xql, + lang-util-procs-postgresql.xql, locale-procs.tcl: - There's no + consistent use of upper/lower case in the locale and language + columns of the ad_locales table so we need to do case insensitive + searches. - ad_locales defines the language column as char(3). + Searches for 2-letter language codes fail because (at least on + PG) all 2-letter entries have a trailing space in the database. -2004-03-25 17:36 peterm +2004-05-31 19:28 gabrielb - * packages/acs-admin/www/apm/: version-edit-2.tcl, - version-edit-2.xql: Making sure you can keep the version of a - package unchanged while editing it. Even if you keep the upgrade - checkbox selected it will now not attempt an upgrade if you - didn't change the version_name. fixing bug 1106 + * packages/acs-templating/tcl/spellcheck-init.tcl: Handle instances + where ad_locales does not contain the 2-letter language being + sought. -2004-03-25 17:30 peterm +2004-05-28 19:08 jader - * packages/acs-tcl/tcl/defs-procs.tcl: changing the - ad_return_complaint proc to use the ad-return-complain template. - It was broken with the complain template as it didn't create a - multirow + * packages/acs-kernel/acs-kernel.info: Removed a security hole in + new installations: see: + http://openacs.org/forums/message-view?message_id=187394 -2004-03-25 17:09 lars +2004-05-26 22:51 tils - * packages/acs-templating/tcl/list-procs.tcl: Internationalized - list-builder formats and sort order labels + * packages/acs-lang/www/admin/message-usage-include.tcl: The 'Show + files that use this message' functionality used to also find keys + like acs-kernel.foo_bar when searching for acs-kernel.foo, fixed. + Not touching the acs-lang.localization-* lookups because I don't + know how to test this. -2004-03-25 17:09 lars +2004-05-26 21:10 donb - * - packages/acs-templating/catalog/acs-templating.en_US.ISO-8859-1.xml: - Added message keys for sort order and formats + * packages/acs-content-repository/sql/postgresql/: + content-folder.sql, content-item.sql: Minor cosmetic change vs. + 1858 -2004-03-25 16:59 joela +2004-05-26 21:01 daveb - * packages/acs-tcl/tcl/utilities-procs.tcl: added roll_server_log - procedure + * packages/acs-content-repository/tcl/revision-procs.tcl: Return + content as string when string_p is true for file storage type. + Fixed bug#1823 -2004-03-25 16:22 jlaine +2004-05-26 20:50 donb - * packages/acs-subsite/tcl/group-procs.tcl: Fixed bug #1392: - Documented the behaviour of group::member_p + * packages/acs-content-repository/sql/oracle/: content-folder.sql, + content-item.sql, packages-create.sql, + upgrade/upgrade-5.1.0-5.1.1.sql: Further fixing of bug #1858 -2004-03-25 15:40 joela +2004-05-26 20:43 daveb - * packages/acs-templating/: - catalog/acs-templating.en_US.ISO-8859-1.xml, tcl/date-procs.tcl, - tcl/element-procs.tcl: applied Guan's patch adding some new - message keys and corresponding catalog entries to some date procs + * packages/acs-content-repository/tcl/filter-procs.tcl: + Check for html before processing content through + ad_html_text_convert. -2004-03-25 15:28 peterm +2004-05-26 20:12 donb - * packages/acs-tcl/tcl/membership-rel-procs.tcl: deleted user is - put in public group so that he has public privileges. fixing bug - 1468 + * packages/acs-content-repository/: sql/oracle/content-folder.sql, + sql/oracle/content-test.sql, + sql/oracle/upgrade/upgrade-4.7d6-5.0d1.sql, + sql/postgresql/content-folder.sql, + sql/postgresql/content-item.sql, sql/postgresql/content-test.sql, + www/doc/api/folder.html, www/doc/api/item.html: Fixed Bug #1858: + qualifying "rename" works in 8i bug chokes in 9i causing the + reported error on installation. Fixed by changing the name to + "edit_name" and implemented it for PG as well (to keep names + similar) -2004-03-25 15:27 peterm +2004-05-26 18:05 eduardop - * packages/acs-tcl/tcl/00-database-procs.tcl: fixing some variable - name misakes in my previous bind var/quoting fix + * packages/acs-lang/acs-lang.info: Fix for Bug #1834: set + SystemTimezone default="UTC" -2004-03-25 14:53 joela +2004-05-22 01:15 lars - * packages/: acs-templating/tcl/util-procs.tcl, - acs-tcl/tcl/utilities-procs.tcl: fixing bug 1318 + * packages/acs-subsite/tcl/subsite-procs.tcl: Do not require + subsite_id to subsite::get_element -2004-03-25 13:52 peterm +2004-05-22 01:11 lars - * packages/acs-tcl/tcl/: 00-database-procs.tcl, - test/acs-tcl-test-procs.tcl: Changing proc - db_bind_var_substitution (used only for db_exec_plsql) so that it - doesn't do bind var substitution for bind variables that are in - quotes. fixing bug 1113 + * packages/acs-lang/www/admin/message-list.adp: Clearer explanation + on the import/export links -2004-03-25 12:43 joela +2004-05-20 19:50 lars - * packages/acs-tcl/tcl/test/acs-tcl-test-procs.tcl: added test case - for 1450 + * packages/acs-tcl/tcl/acs-permissions-procs.tcl: Formatting + change: && at beginning of lines, instead of end -2004-03-25 10:58 jlaine +2004-05-20 19:31 lars - * packages/acs-subsite/www/admin/rel-types/new.adp: - Fixed bug #1299: added noquote to supertypes.name + * packages/acs-tcl/tcl/acs-permissions-procs.tcl: Make the + automatic detection of expired logins work when you explicitly + supply party_id 0 as well -2004-03-25 10:50 peterm +2004-05-20 18:38 tilmanns - * etc/config.tcl: changing ServerSessionCache to default to true. - Fixinb bug 1336 + * packages/acs-templating/tcl/date-procs.tcl: Trim leading zeros + since month_data is keyed by month number without leading zero, + and I have seen at least once getting it a month value with + leading zero from somewhere. -2004-03-25 04:25 donb +2004-05-18 18:23 rocaelh - * packages/acs-api-browser/tcl/acs-api-documentation-procs.tcl: - Moved my previous fix to 5.1 + * packages/acs-tcl/tcl/utilities-procs.tcl: attribute of a child + node function -2004-03-25 03:41 daveb +2004-05-18 18:15 rocaelh - * packages/acs-api-browser/tcl/acs-api-documentation-procs.tcl: Fix - bug#1562. + * packages/acs-tcl/tcl/30-xml-utils-procs.tcl: xpath wrapper + function -2004-03-24 20:26 andrewg +2004-05-14 15:12 jeffd - * packages/acs-authentication/tcl/authentication-procs.tcl: Added - -nologin flag to disable automatic login of a new user. This is - part of an initial foray into allowing certain kinds of - 'low-barrier' registration, such as on a weblog comments system. + * packages/acs-templating/: resources/lists/list.adp, + resources/lists/table.adp, tcl/list-procs.tcl: parameterize the + method for bulk actions, default is get since that used to be the + hard coded value -2004-03-24 16:34 joela +2004-05-13 18:43 lars - * packages/: acs-admin/acs-admin.info, - acs-api-browser/acs-api-browser.info, - acs-authentication/acs-authentication.info, - acs-automated-testing/acs-automated-testing.info, - acs-bootstrap-installer/acs-bootstrap-installer.info, - acs-content-repository/acs-content-repository.info, - acs-core-docs/acs-core-docs.info, acs-kernel/acs-kernel.info, - acs-lang/acs-lang.info, acs-mail/acs-mail.info, - acs-messaging/acs-messaging.info, - acs-reference/acs-reference.info, - acs-service-contract/acs-service-contract.info, - acs-subsite/acs-subsite.info, acs-tcl/acs-tcl.info, - acs-templating/acs-templating.info, - ref-timezones/ref-timezones.info, search/search.info: increased - core version numbers to alpha 2 + * packages/acs-subsite/www/resources/http.png: Added http link icon -2004-03-23 16:30 peterm +2004-05-13 17:16 lars - * packages/acs-subsite/www/admin/relations/: add-oracle.xql, - add-postgresql.xql, add.tcl: When adding a user to a group we - were checking read permission on the users offered for selection. - Since all OpenACS users have a null context_id only the - site-wide-admin would have read privilege on them. To also allow - subsite admins to add users to groups I removed the read - privilege check on the users. See - http://openacs.org/forums/message-view?message_id=171339 + * packages/acs-subsite/catalog/acs-subsite.en_US.ISO-8859-1.xml: + Show bio/portrait icon for members portlet -2004-03-23 12:32 jeffd +2004-05-13 17:05 lars - * packages/: acs-admin/acs-admin.info, - acs-api-browser/acs-api-browser.info, - acs-authentication/acs-authentication.info, - acs-bootstrap-installer/acs-bootstrap-installer.info, - acs-core-docs/acs-core-docs.info, acs-kernel/acs-kernel.info, - acs-lang/acs-lang.info, acs-mail/acs-mail.info, - acs-messaging/acs-messaging.info, - acs-service-contract/acs-service-contract.info, - acs-subsite/acs-subsite.info, acs-tcl/acs-tcl.info, - acs-templating/acs-templating.info, - ref-timezones/ref-timezones.info, search/search.info: repair the - borkulated provides lines for core packages may fix bug 1669 + * packages/acs-subsite/www/shared/community-member.adp: Fixed + missing @ sign in the inline_portrait_state if statement -2004-03-22 07:17 maltes +2004-05-13 15:29 lars - * etc/config.tcl: Some parameters where still using the /web - directory instead of . Found in - http://openacs.org/forums/message-view?message_id=171712. + * packages/acs-subsite/www/resources/profile-16.png: Added profile + icon -2004-03-22 03:52 lars +2004-05-06 23:25 daveb - * packages/acs-tcl/tcl/site-nodes-procs.tcl: Fixed - site_node::get_url_from_object_id slowness bug, plus added a - similar mechanism to find URL by package_key. + * packages/acs-content-repository/tcl/revision-procs.tcl: Make sure + content_length is returned as 0 if its set to NULL in + cr_revisions. -2004-03-22 03:46 lars +2004-05-06 02:35 daveb - * packages/acs-tcl/tcl/utilities-procs.tcl: Added proc to use with - lsort to compare strings based on their length + * packages/acs-content-repository/sql/postgresql/: + content-item.sql, upgrade/upgrade-5.1.1d1-5.1.1d2.sql: Fix typo + in parameter name, reference to non-existant parameter. Fixes + bug#1793 -2004-03-19 14:09 peterm +2004-05-06 02:24 daveb - * packages/: acs-admin/www/users/index.adp, - acs-admin/www/users/user-batch-add-2.adp, - acs-admin/www/users/user-batch-add-2.tcl, - acs-admin/www/users/user-batch-add.adp, - acs-admin/www/users/user-batch-add.tcl, - acs-subsite/tcl/subsite-procs.tcl, - acs-subsite/www/members/member-invite.adp, - acs-subsite/www/members/member-invite.tcl, - acs-subsite/www/members/user-batch-add-2.adp, - acs-subsite/www/members/user-batch-add-2.tcl, - acs-subsite/www/members/user-batch-add.adp, - acs-subsite/www/members/user-batch-add.tcl, - acs-subsite/www/members/user-new.tcl: moving bulk user add pages - from /acs-admin to subsite admin + * packages/acs-content-repository/acs-content-repository.info: Bump + up version number to match upgrade script. -2004-03-19 14:06 peterm +2004-05-06 02:12 daveb - * packages/acs-kernel/sql/: oracle/acs-install.sql, - postgresql/acs-install.sql: setting context_id of registered - users group to be the main site package so that admin privilege - on that package entitles you to add users. See - http://openacs.org/forums/message-view?message_id=171339 + * packages/acs-content-repository/sql/postgresql/: + content-create.sql, upgrade/upgrade-5.1.1d1-5.1.1d2.sql: Fix + reference to chid instead of child in cr_items_update_tr. Upgrade + script included. Fixes bug#1791 -2004-03-19 11:57 peterm +2004-05-05 11:40 maltes - * packages/acs-admin/www/users/: user-batch-add-2.adp, - user-batch-add-2.tcl, user-batch-add.adp: bringing over changes - by bdolicki from head + * packages/acs-subsite/www/members/user-batch-add-2.tcl: Adding + users in a subsite per batch did not add them to the subsite as + members. -2004-03-19 10:24 peterm +2004-05-04 15:42 joela - * packages/acs-subsite/lib/: user-info.adp, user-info.tcl: Applying - the groups your member of patch by Branimir from head: cvs update - -j1.4 -j1.5 packages/acs-subsite/lib/user-info.adp cvs update - -j1.11 -j1.12 packages/acs-subsite/lib/user-info.tcl + * packages/: + acs-authentication/catalog/acs-authentication.en_US.ISO-8859-1.xml, + acs-kernel/catalog/acs-kernel.AR_EG.utf-8.xml, + acs-kernel/catalog/acs-kernel.AR_LB.utf-8.xml, + acs-kernel/catalog/acs-kernel.RO_RO.utf-8.xml, + acs-kernel/catalog/acs-kernel.ast_ES.ISO-8859-1.xml, + acs-kernel/catalog/acs-kernel.ch_zh.utf-8.xml, + acs-kernel/catalog/acs-kernel.da_DK.ISO-8859-1.xml, + acs-kernel/catalog/acs-kernel.de_DE.ISO-8859-1.xml, + acs-kernel/catalog/acs-kernel.en_US.ISO-8859-1.xml, + acs-kernel/catalog/acs-kernel.es_ES.ISO-8859-1.xml, + acs-kernel/catalog/acs-kernel.fi_FI.utf-8.xml, + acs-kernel/catalog/acs-kernel.fr_FR.ISO-8859-1.xml, + acs-kernel/catalog/acs-kernel.gl_ES.ISO-8859-1.xml, + acs-kernel/catalog/acs-kernel.hu_HU.utf-8.xml, + acs-kernel/catalog/acs-kernel.it_IT.ISO-8859-1.xml, + acs-kernel/catalog/acs-kernel.ja_JP.utf-8.xml, + acs-kernel/catalog/acs-kernel.ko_KR.utf-8.xml, + acs-kernel/catalog/acs-kernel.ms_my.utf-8.xml, + acs-kernel/catalog/acs-kernel.nl_NL.ISO-8859-1.xml, + acs-kernel/catalog/acs-kernel.nn_NO.ISO-8859-1.xml, + acs-kernel/catalog/acs-kernel.no_NO.ISO-8859-1.xml, + acs-kernel/catalog/acs-kernel.pl_PL.utf-8.xml, + acs-kernel/catalog/acs-kernel.pt_BR.ISO-8859-1.xml, + acs-kernel/catalog/acs-kernel.pt_PT.ISO-8859-1.xml, + acs-kernel/catalog/acs-kernel.ru_RU.utf-8.xml, + acs-kernel/catalog/acs-kernel.sv_SE.ISO-8859-1.xml, + acs-kernel/catalog/acs-kernel.tr_TR.utf-8.xml, + acs-kernel/catalog/acs-kernel.zh_TW.utf-8.xml, + acs-lang/catalog/acs-lang.AR_EG.utf-8.xml, + acs-lang/catalog/acs-lang.AR_LB.utf-8.xml, + acs-lang/catalog/acs-lang.RO_RO.utf-8.xml, + acs-lang/catalog/acs-lang.TH_TH.utf-8.xml, + acs-lang/catalog/acs-lang.ast_ES.ISO-8859-1.xml, + acs-lang/catalog/acs-lang.ch_zh.utf-8.xml, + acs-lang/catalog/acs-lang.da_DK.ISO-8859-1.xml, + acs-lang/catalog/acs-lang.de_DE.ISO-8859-1.xml, + acs-lang/catalog/acs-lang.el_GR.utf-8.xml, + acs-lang/catalog/acs-lang.en_GB.ISO-8859-1.xml, + acs-lang/catalog/acs-lang.en_US.ISO-8859-1.xml, + acs-lang/catalog/acs-lang.es_ES.ISO-8859-1.xml, + acs-lang/catalog/acs-lang.fi_FI.utf-8.xml, + acs-lang/catalog/acs-lang.fr_FR.ISO-8859-1.xml, + acs-lang/catalog/acs-lang.gl_ES.ISO-8859-1.xml, + acs-lang/catalog/acs-lang.hu_HU.utf-8.xml, + acs-lang/catalog/acs-lang.it_IT.ISO-8859-1.xml, + acs-lang/catalog/acs-lang.ja_JP.utf-8.xml, + acs-lang/catalog/acs-lang.ko_KR.utf-8.xml, + acs-lang/catalog/acs-lang.ms_my.utf-8.xml, + acs-lang/catalog/acs-lang.nl_NL.ISO-8859-1.xml, + acs-lang/catalog/acs-lang.nn_NO.ISO-8859-1.xml, + acs-lang/catalog/acs-lang.no_NO.ISO-8859-1.xml, + acs-lang/catalog/acs-lang.pl_PL.utf-8.xml, + acs-lang/catalog/acs-lang.pt_BR.ISO-8859-1.xml, + acs-lang/catalog/acs-lang.pt_PT.ISO-8859-1.xml, + acs-lang/catalog/acs-lang.ru_RU.utf-8.xml, + acs-lang/catalog/acs-lang.sh_HR.utf-8.xml, + acs-lang/catalog/acs-lang.sv_SE.ISO-8859-1.xml, + acs-lang/catalog/acs-lang.tr_TR.utf-8.xml, + acs-lang/catalog/acs-lang.zh_TW.utf-8.xml, + acs-subsite/catalog/acs-subsite.AR_EG.utf-8.xml, + acs-subsite/catalog/acs-subsite.AR_LB.utf-8.xml, + acs-subsite/catalog/acs-subsite.RO_RO.utf-8.xml, + acs-subsite/catalog/acs-subsite.ast_ES.ISO-8859-1.xml, + acs-subsite/catalog/acs-subsite.ch_zh.utf-8.xml, + acs-subsite/catalog/acs-subsite.da_DK.ISO-8859-1.xml, + acs-subsite/catalog/acs-subsite.de_DE.ISO-8859-1.xml, + acs-subsite/catalog/acs-subsite.el_GR.utf-8.xml, + acs-subsite/catalog/acs-subsite.en_US.ISO-8859-1.xml, + acs-subsite/catalog/acs-subsite.es_ES.ISO-8859-1.xml, + acs-subsite/catalog/acs-subsite.fi_FI.utf-8.xml, + acs-subsite/catalog/acs-subsite.fr_FR.ISO-8859-1.xml, + acs-subsite/catalog/acs-subsite.gl_ES.ISO-8859-1.xml, + acs-subsite/catalog/acs-subsite.hu_HU.utf-8.xml, + acs-subsite/catalog/acs-subsite.it_IT.ISO-8859-1.xml, + acs-subsite/catalog/acs-subsite.ja_JP.utf-8.xml, + acs-subsite/catalog/acs-subsite.ko_KR.utf-8.xml, + acs-subsite/catalog/acs-subsite.ms_my.utf-8.xml, + acs-subsite/catalog/acs-subsite.nl_NL.ISO-8859-1.xml, + acs-subsite/catalog/acs-subsite.nn_NO.ISO-8859-1.xml, + acs-subsite/catalog/acs-subsite.no_NO.ISO-8859-1.xml, + acs-subsite/catalog/acs-subsite.pl_PL.utf-8.xml, + acs-subsite/catalog/acs-subsite.pt_BR.ISO-8859-1.xml, + acs-subsite/catalog/acs-subsite.pt_PT.ISO-8859-1.xml, + acs-subsite/catalog/acs-subsite.ru_RU.utf-8.xml, + acs-subsite/catalog/acs-subsite.sh_HR.utf-8.xml, + acs-subsite/catalog/acs-subsite.sv_SE.ISO-8859-1.xml, + acs-subsite/catalog/acs-subsite.tr_TR.utf-8.xml, + acs-subsite/catalog/acs-subsite.zh_TW.utf-8.xml, + acs-tcl/catalog/acs-tcl.AR_EG.utf-8.xml, + acs-tcl/catalog/acs-tcl.AR_LB.utf-8.xml, + acs-tcl/catalog/acs-tcl.FA_IR.utf-8.xml, + acs-tcl/catalog/acs-tcl.RO_RO.utf-8.xml, + acs-tcl/catalog/acs-tcl.ast_ES.ISO-8859-1.xml, + acs-tcl/catalog/acs-tcl.ch_zh.utf-8.xml, + acs-tcl/catalog/acs-tcl.da_DK.ISO-8859-1.xml, + acs-tcl/catalog/acs-tcl.de_DE.ISO-8859-1.xml, + acs-tcl/catalog/acs-tcl.en_US.ISO-8859-1.xml, + acs-tcl/catalog/acs-tcl.es_ES.ISO-8859-1.xml, + acs-tcl/catalog/acs-tcl.fi_FI.utf-8.xml, + acs-tcl/catalog/acs-tcl.fr_FR.ISO-8859-1.xml, + acs-tcl/catalog/acs-tcl.gl_ES.ISO-8859-1.xml, + acs-tcl/catalog/acs-tcl.hu_HU.utf-8.xml, + acs-tcl/catalog/acs-tcl.it_IT.ISO-8859-1.xml, + acs-tcl/catalog/acs-tcl.ja_JP.utf-8.xml, + acs-tcl/catalog/acs-tcl.ko_KR.utf-8.xml, + acs-tcl/catalog/acs-tcl.ms_my.utf-8.xml, + acs-tcl/catalog/acs-tcl.nl_NL.ISO-8859-1.xml, + acs-tcl/catalog/acs-tcl.nn_NO.ISO-8859-1.xml, + acs-tcl/catalog/acs-tcl.no_NO.ISO-8859-1.xml, + acs-tcl/catalog/acs-tcl.pl_PL.utf-8.xml, + acs-tcl/catalog/acs-tcl.pt_BR.ISO-8859-1.xml, + acs-tcl/catalog/acs-tcl.pt_PT.ISO-8859-1.xml, + acs-tcl/catalog/acs-tcl.ru_RU.utf-8.xml, + acs-tcl/catalog/acs-tcl.sh_HR.utf-8.xml, + acs-tcl/catalog/acs-tcl.sv_SE.ISO-8859-1.xml, + acs-tcl/catalog/acs-tcl.tr_TR.utf-8.xml, + acs-tcl/catalog/acs-tcl.zh_TW.utf-8.xml, + acs-templating/catalog/acs-templating.RO_RO.utf-8.xml, + acs-templating/catalog/acs-templating.ch_zh.utf-8.xml, + acs-templating/catalog/acs-templating.da_DK.ISO-8859-1.xml, + acs-templating/catalog/acs-templating.de_DE.ISO-8859-1.xml, + acs-templating/catalog/acs-templating.en_US.ISO-8859-1.xml, + acs-templating/catalog/acs-templating.es_ES.ISO-8859-1.xml, + acs-templating/catalog/acs-templating.fi_FI.utf-8.xml, + acs-templating/catalog/acs-templating.fr_FR.ISO-8859-1.xml, + acs-templating/catalog/acs-templating.hu_HU.utf-8.xml, + acs-templating/catalog/acs-templating.it_IT.ISO-8859-1.xml, + acs-templating/catalog/acs-templating.ko_KR.utf-8.xml, + acs-templating/catalog/acs-templating.ms_my.utf-8.xml, + acs-templating/catalog/acs-templating.nl_NL.ISO-8859-1.xml, + acs-templating/catalog/acs-templating.nn_NO.ISO-8859-1.xml, + acs-templating/catalog/acs-templating.no_NO.ISO-8859-1.xml, + acs-templating/catalog/acs-templating.pt_BR.ISO-8859-1.xml, + acs-templating/catalog/acs-templating.sv_SE.ISO-8859-1.xml, + acs-templating/catalog/acs-templating.zh_TW.utf-8.xml: added + current translations -2004-03-18 17:51 jeffd +2004-05-04 14:11 jeffd - * packages/acs-tcl/tcl/00-database-procs.tcl: use db_get_dbhost to - get host for windows remote connections to work bug 1258 fix by - John Sequeira + * packages/acs-subsite/www/user/portrait/upload-2-oracle.xql: set + content_length field in cr_revisions for uploaded portrait -2004-03-18 17:15 peterm +2004-05-04 14:06 jeffd - * packages/acs-lang/tcl/: lang-util-procs.tcl, - test/acs-lang-test-procs.tcl: stripping off trailing space in the - text of temporary tags on syntax <# key text #>. Checked new - functionality with test case. + * packages/acs-subsite/www/user/portrait/upload-2-postgresql.xql: + set content_length field in cr_revisions for uploaded portrait -2004-03-18 16:59 peterm +2004-05-02 21:13 daveb - * packages/acs-lang/www/admin/: edit-localized-message.adp, - edit-localized-message.tcl: on the message edit page - adding - info about who did the first translation and when + * + packages/acs-content-repository/sql/oracle/upgrade/upgrade-5.1.0-5.1.1.sql: + Fix content_folder.rename. -2004-03-18 16:14 jeffd +2004-05-01 10:32 jeffd - * packages/acs-tcl/tcl/acs-permissions-procs.tcl: fix for bug 1433, - PermissionCacheP used memoize on non list thing which would break - with empty object_id etc + * packages/acs-content-repository/sql/postgresql/content-type.sql: + content_type__drop_type doesn't work on OS X (7.2 was matching + sp[uriously) bug 1738 patch 498 Jarkko Laine -2004-03-18 11:12 peterm +2004-04-30 10:59 lars - * packages/acs-lang/tcl/: lang-message-procs.tcl, - test/acs-lang-test-procs.tcl: Proc lang::message::format (used by - lang::message::lookup) - implementing ability to have embedded - array variables in I18N messages on syntax %var_name.key_name%. - Adding corresponding test case. + * packages/acs-lang/www/admin/edit-localized-message.tcl: + export_vars -base instead of ?[export_vars] -2004-03-18 10:50 peterm +2004-04-30 04:49 daveb - * packages/acs-admin/www/apm/version-i18n.tcl: cosmetic change of - file filter + * packages/acs-content-repository/sql/oracle/content-folder.sql: + Fix content_folder.rename to actually change the label or + description if that parameter is specified. -2004-03-18 10:07 peterm - - * packages/: acs-templating/tcl/parse-procs.tcl, - acs-lang/tcl/lang-message-procs.tcl, - acs-lang/tcl/lang-util-procs.tcl, - acs-lang/tcl/test/acs-lang-test-procs.tcl: adding support for - variables embedded in I18N messages to have the noquote - instruction (from the corresponding adp variable). TODO: make - sure we do ad_quotehtml and lang::util::localize on the embedded - variables. Adding the proc - convert_percentage_signs_to_adp_variables that we don't currently - need, but I'm leaving it in in case it would be useful later on. - -2004-03-16 19:33 rocaelh - - * packages/acs-content-repository/sql/oracle/: content-folder.sql, - content-item.sql: fixing bug 1598 - -2004-03-16 11:52 joela - - * packages/: acs-admin/acs-admin.info, - acs-api-browser/acs-api-browser.info, - acs-authentication/acs-authentication.info, - acs-bootstrap-installer/acs-bootstrap-installer.info, - acs-core-docs/acs-core-docs.info, acs-kernel/acs-kernel.info, - acs-lang/acs-lang.info, acs-mail/acs-mail.info, - acs-messaging/acs-messaging.info, - acs-service-contract/acs-service-contract.info, - acs-subsite/acs-subsite.info, acs-tcl/acs-tcl.info, - acs-templating/acs-templating.info, - ref-timezones/ref-timezones.info, search/search.info: changed - package version numbers to 5.1.0a1 - -2004-03-14 15:39 gyang - - * packages/acs-authentication/: - catalog/acs-authentication.en_US.ISO-8859-1.xml, - tcl/local-procs.tcl: Fixed Bug #1506 in oacs-5-1 by adding the - message - -2004-03-14 14:17 gyang - - * packages/acs-subsite/www/admin/applications/application-add.tcl: - Oops. Wanted to fix Bug #1563 but realized after looking in - bugtracker that I'm not supposed to commit these things myself in - other peoples' packages. - -2004-03-14 14:12 gyang - - * packages/acs-subsite/www/admin/applications/application-add.tcl: - Fixed Bug #1563 by changing help_text in the application-add form - Index: openacs-4/packages/acs-admin/www/developer.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-admin/www/developer.adp,v diff -u -N -r1.1 -r1.2 --- openacs-4/packages/acs-admin/www/developer.adp 21 Sep 2003 19:21:47 -0000 1.1 +++ openacs-4/packages/acs-admin/www/developer.adp 12 Jul 2004 14:49:34 -0000 1.2 @@ -97,6 +97,6 @@ title="Software Development Manager on openacs.org">Bug Tracker. -
  • Please read our conbribution instructions to learn how you can become involved in the OpenACS project. +
  • Please read our contribution instructions to learn how you can become involved in the OpenACS project. If you develop your own OpenACS packages there is a good chance they will be useful to other people in the community and after review they can be included in the OpenACS distribution.
  • Index: openacs-4/packages/acs-api-browser/acs-api-browser.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-api-browser/acs-api-browser.info,v diff -u -N -r1.17 -r1.18 --- openacs-4/packages/acs-api-browser/acs-api-browser.info 17 May 2004 15:14:41 -0000 1.17 +++ openacs-4/packages/acs-api-browser/acs-api-browser.info 12 Jul 2004 14:49:34 -0000 1.18 @@ -7,7 +7,7 @@ t t - + OpenACS Interactive documentation for the Tcl and SQL APIs. 2004-04-29 @@ -16,7 +16,7 @@ 3 On line interactive documentation for the locally installed Tcl and SQL APIs. Links to the Tcl core and AOLServer online documentation as well. - + Index: openacs-4/packages/acs-authentication/acs-authentication.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-authentication/acs-authentication.info,v diff -u -N -r1.19 -r1.20 --- openacs-4/packages/acs-authentication/acs-authentication.info 10 Jun 2004 17:08:01 -0000 1.19 +++ openacs-4/packages/acs-authentication/acs-authentication.info 12 Jul 2004 14:49:34 -0000 1.20 @@ -7,7 +7,7 @@ t t - + Lars Pind Authentication, account management, and related functionality. 2004-04-29 @@ -16,7 +16,7 @@ GPL version 2 Implements authentication-related security functions for OpenACS, including password, account and session management, bulk account creation etc. Provides a contract based interface for different authentication methods such as PAM or LDAP based authentication. - + Index: openacs-4/packages/acs-authentication/tcl/apm-callback-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-authentication/tcl/apm-callback-procs.tcl,v diff -u -N -r1.12 -r1.13 --- openacs-4/packages/acs-authentication/tcl/apm-callback-procs.tcl 31 Oct 2003 10:29:19 -0000 1.12 +++ openacs-4/packages/acs-authentication/tcl/apm-callback-procs.tcl 12 Jul 2004 14:49:34 -0000 1.13 @@ -110,7 +110,12 @@ acs_sc::impl::delete -contract_name "auth_sync_process" -impl_name "IMS_Enterprise_v_1p1_old" } } - } + 5.1.1 5.1.2 { + db_transaction { + auth::authentication::quick_sc_update + } + } + } } ##### @@ -140,6 +145,7 @@ username:string password:string parameters:string,multiple + authority_id:integer } output { auth_status:string @@ -203,6 +209,7 @@ old_password:string new_password:string parameters:string,multiple + authority_id:integer } output { password_status:string @@ -261,6 +268,7 @@ input { username:string parameters:string,multiple + authority_id:integer } output { password_status:string @@ -538,4 +546,29 @@ } +ad_proc -private auth::authentication::quick_sc_update {} { + SC update related to add authority_id new input +} { + # this is a direct update to the SC tables, we should expect a new + # API for handling updates on SC, but since there's no one yet, + # we'll do this way now .... (roc) + + set sc_change [list {auth_authentication.Authenticate.InputType} {auth_password.ChangePassword.InputType} {auth_password.ResetPassword.InputType}] + set element_msg_type_name integer + + foreach msg_type_name $sc_change { + set msg_type_id [db_string get_msg_type_id { select msg_type_id from acs_sc_msg_types where msg_type_name = :msg_type_name }] + set element_pos [db_string get_pos { select max(element_pos) from acs_sc_msg_type_elements where msg_type_id = :msg_type_id }] + incr element_pos + + acs_sc::msg_type::element::new \ + -msg_type_name $msg_type_name \ + -element_name authority_id \ + -element_msg_type_name $element_msg_type_name \ + -element_msg_type_isset_p f \ + -element_pos $element_pos + + } + +} \ No newline at end of file Index: openacs-4/packages/acs-authentication/tcl/authentication-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-authentication/tcl/authentication-procs.tcl,v diff -u -N -r1.66 -r1.67 --- openacs-4/packages/acs-authentication/tcl/authentication-procs.tcl 10 Jun 2004 17:06:34 -0000 1.66 +++ openacs-4/packages/acs-authentication/tcl/authentication-procs.tcl 12 Jul 2004 14:49:34 -0000 1.67 @@ -1576,7 +1576,7 @@ -error \ -impl_id $impl_id \ -operation Authenticate \ - -call_args [list $username $password $parameters]] + -call_args [list $username $password $parameters $authority_id]] } ##### Index: openacs-4/packages/acs-authentication/tcl/local-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-authentication/tcl/local-procs.tcl,v diff -u -N -r1.27 -r1.28 --- openacs-4/packages/acs-authentication/tcl/local-procs.tcl 20 Apr 2004 21:12:31 -0000 1.27 +++ openacs-4/packages/acs-authentication/tcl/local-procs.tcl 12 Jul 2004 14:49:34 -0000 1.28 @@ -102,15 +102,18 @@ username password {parameters {}} + {authority_id {}} } { Implements the Authenticate operation of the auth_authentication service contract for the local account implementation. } { array set auth_info [list] - set authority_id [auth::authority::local] + if [empty_string_p $authority_id] { + set authority_id [auth::authority::local] + } - set user_id [acs_user::get_by_username -username $username] + set user_id [acs_user::get_by_username -authority_id $authority_id -username $username] if { [empty_string_p $user_id] } { set result(auth_status) "no_account" return [array get result] @@ -214,6 +217,7 @@ old_password new_password {parameters {}} + {authority_id {}} } { Implements the ChangePassword operation of the auth_password service contract for the local account implementation. @@ -223,7 +227,7 @@ password_message {} } - set user_id [acs_user::get_by_username -username $username] + set user_id [acs_user::get_by_username -authority_id $authority_id -username $username] if { [empty_string_p $user_id] } { set result(password_status) "no_account" return [array get result] @@ -244,7 +248,7 @@ if { [parameter::get -parameter EmailAccountOwnerOnPasswordChangeP -package_id [ad_acs_kernel_id] -default 1] } { with_catch errmsg { - acs_user::get -username $username -array user + acs_user::get -username $username -authority_id $authority_id -array user set system_name [ad_system_name] set pvt_home_name [ad_pvt_home_name] @@ -291,6 +295,8 @@ ad_proc -private auth::local::password::ResetPassword { username parameters + {authority_id {}} + {new_password {}} } { Implements the ResetPassword operation of the auth_password service contract for the local account implementation. @@ -300,14 +306,18 @@ password_message {} } - set user_id [acs_user::get_by_username -username $username] + set user_id [acs_user::get_by_username -authority_id $authority_id -username $username] if { [empty_string_p $user_id] } { set result(password_status) "no_account" return [array get result] } # Reset the password - set password [ad_generate_random_string] + if [empty_string_p $new_password] { + set password $new_password + } else { + set password [ad_generate_random_string] + } ad_change_password $user_id $password Index: openacs-4/packages/acs-authentication/tcl/password-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-authentication/tcl/password-procs.tcl,v diff -u -N -r1.11 -r1.12 --- openacs-4/packages/acs-authentication/tcl/password-procs.tcl 26 Jan 2004 15:39:41 -0000 1.11 +++ openacs-4/packages/acs-authentication/tcl/password-procs.tcl 12 Jul 2004 14:49:34 -0000 1.12 @@ -699,7 +699,8 @@ -call_args [list $username \ $old_password \ $new_password \ - $parameters]] + $parameters \ + $authority_id]] } ad_proc -private auth::password::RetrievePassword { @@ -763,5 +764,6 @@ -impl_id $impl_id \ -operation ResetPassword \ -call_args [list $username \ - $parameters]] + $parameters \ + $authority_id]] } Index: openacs-4/packages/acs-automated-testing/acs-automated-testing.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-automated-testing/acs-automated-testing.info,v diff -u -N -r1.15 -r1.16 --- openacs-4/packages/acs-automated-testing/acs-automated-testing.info 17 May 2004 15:14:43 -0000 1.15 +++ openacs-4/packages/acs-automated-testing/acs-automated-testing.info 12 Jul 2004 14:49:34 -0000 1.16 @@ -7,7 +7,7 @@ t f - + OpenACS The interface to the automated testing facilities within OpenACS. 2004-04-29 Index: openacs-4/packages/acs-bootstrap-installer/acs-bootstrap-installer.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-bootstrap-installer/acs-bootstrap-installer.info,v diff -u -N -r1.20 -r1.21 --- openacs-4/packages/acs-bootstrap-installer/acs-bootstrap-installer.info 17 May 2004 15:14:43 -0000 1.20 +++ openacs-4/packages/acs-bootstrap-installer/acs-bootstrap-installer.info 12 Jul 2004 14:49:35 -0000 1.21 @@ -7,7 +7,7 @@ t t - + Don Baccus Bootstraps an OpenACS installation. 2004-04-29 @@ -16,7 +16,7 @@ 3 This package bootstraps OpenACS. If the core packages have not yet been installed, it calls the installer which leads the user through the steps necessary to do so. It also checks that the installation meets the requirements for a successful install of OpenACS. - + Index: openacs-4/packages/acs-content-repository/acs-content-repository.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/acs-content-repository.info,v diff -u -N -r1.42 -r1.43 --- openacs-4/packages/acs-content-repository/acs-content-repository.info 1 Jul 2004 16:33:38 -0000 1.42 +++ openacs-4/packages/acs-content-repository/acs-content-repository.info 12 Jul 2004 14:49:35 -0000 1.43 @@ -9,6 +9,7 @@ OpenACS + The canonical repository for OpenACS content. 2004-04-29 OpenACS Index: openacs-4/packages/acs-content-repository/sql/oracle/upgrade/upgrade-5.1.1-5.1.2.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/sql/oracle/upgrade/Attic/upgrade-5.1.1-5.1.2.sql,v diff -u -N --- openacs-4/packages/acs-content-repository/sql/oracle/upgrade/upgrade-5.1.1-5.1.2.sql 29 Jun 2004 10:17:35 -0000 1.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,3084 +0,0 @@ - -create or replace package content_item -as - ---/** ---Content items store the overview of the content published on a ---website. The actual content is stored in content revisions. It is ---implemented this way so that there can be mulitple versions of the ---actual content while the main idea remains constant. For example: If ---there is a review for the movie "Terminator," there will exist a ---content item by the name "terminator" with all the right parameters ---(supertype, parent, etc), there will also exist at least one content ---revision pointing to this item with the actual review content. ---@see {content_revision}, {content_folder} ---*/ - -c_root_folder_id constant integer := -100; - -function get_root_folder ( - item_id in cr_items.item_id%TYPE default null -) return cr_folders.folder_id%TYPE; - -function new ( - --/** Creates a new content item. If the data, title or text - -- parameters are specified, also creates a revision for the item. - -- @author Karl Goldstein - -- @param name The name for the item, must be URL-encoded. - -- If an item with this name already exists under the specified - -- parent item, an error is thrown - -- @param parent_id The parent of this item, defaults to null - -- @param item_id The id of the new item. A new id will be allocated if this - -- parameter is null - -- @param locale The locale for this item, for use with Intermedia search - -- @param item_subtype The type of the new item, defaults to 'content_item' - -- This parameter is used to support inheritance, so that - -- subclasses of content_item can call this function - -- to initialize the parent class - -- @param content_type The content type for the item, defaults to - -- 'content_revision'. Only objects of this type - -- may be used as revisions for the item - -- @param title The user-readable title for the item, defaults to the item's - -- name - -- @param description A short description for the item (4000 characters maximum) - -- @param mime_type The file type of the item, defaults to 'text/plain' - -- @param nls_language The language for the item, used for Intermedia search - -- @param text The text content of the new revision, 4000 charcters maximum. - -- Cannot be specified simultaneously with the data - -- parameter - -- @param data The blob content of the new revision. Cannot be specified - -- simultaneously with the text parameter - -- @param relation_tag If a parent-child relationship is registered - -- for these content types, use this tag to - -- describe the parent-child relationship. Defaults - -- to 'parent content type'-'child content type' - -- @param is_live If 't', the new revision will become live - -- @param context_id Security context id, as in acs_object.new - -- If null, defaults to parent_id, and copies permissions - -- from the parent into the current item - -- @param storage_type in ('lob','file'). Indicates how content is to be stored. - -- 'file' content is stored externally in the file system. - -- @param others As in acs_object.new - -- @return The id of the newly created item - -- @see {acs_object.new} - --*/ - name in cr_items.name%TYPE, - parent_id in cr_items.parent_id%TYPE default null, - item_id in acs_objects.object_id%TYPE default null, - locale in cr_items.locale%TYPE default null, - creation_date in acs_objects.creation_date%TYPE - default sysdate, - creation_user in acs_objects.creation_user%TYPE - default null, - context_id in acs_objects.context_id%TYPE default null, - creation_ip in acs_objects.creation_ip%TYPE default null, - item_subtype in acs_object_types.object_type%TYPE - default 'content_item', - content_type in acs_object_types.object_type%TYPE - default 'content_revision', - title in cr_revisions.title%TYPE default null, - description in cr_revisions.description%TYPE default null, - mime_type in cr_revisions.mime_type%TYPE default 'text/plain', - nls_language in cr_revisions.nls_language%TYPE default null, - text in varchar2 default null, - data in cr_revisions.content%TYPE default null, - relation_tag in cr_child_rels.relation_tag%TYPE default null, - is_live in char default 'f', - storage_type in cr_items.storage_type%TYPE default 'lob' -) return cr_items.item_id%TYPE; - - -function is_published ( - --/** Determins whether an item is published or not. - -- @author Michael Pih - -- @param item_id The item ID - -- @return 't' if the item is published, 'f' otherwise - --*/ - item_id in cr_items.item_id%TYPE -) return char; - - -function is_publishable ( - --/** Determines if an item is publishable. Publishable items must - -- meet the following criteria: - -- 1) for each child type, the item has n children, min_n < n < max_n - -- 2) for each relation type, the item has n relations, min_n < n < max_n - -- 3) any 'publishing_wf' workflows are finished - -- @author Michael Pih - -- @param item_id The item ID - -- @return 't' if the item is publishable in it's present state, - -- Otherwise, returns 'f' - --*/ - item_id in cr_items.item_id%TYPE -) return char; - - - -function is_valid_child ( - --/** Determines if an item would be a valid child of another item by - -- checking if the parent allows children of the would-be child's - -- content type and if the parent already has n_max children of - -- that content type. - -- @author Michael Pih - -- @param item_id The item ID of the potential parent - -- @param content_type The content type of the potential child item - -- @return 't' if the item would be a valid child, 'f' otherwise - --*/ - - item_id in cr_items.item_id%TYPE, - content_type in acs_object_types.object_type%TYPE, - relation_tag in cr_child_rels.relation_tag%TYPE default null -) return char; - -procedure del ( - --/** Deletes the specified content item, along with any revisions, symlinks, - -- workflows, associated templates, associated keywords, - -- child and item relationships for the item. Use with caution - this - -- operation cannot be undone. - -- @author Karl Goldstein - -- @param item_id The id of the item to delete - -- @see {acs_object.delete} - --*/ - item_id in cr_items.item_id%TYPE -); - -procedure edit_name ( - --/** Renames the item. If an item with the specified name already exists - -- under this item's parent, an error is thrown - -- @author Karl Goldstein - -- @param item_id The id of the item to rename - -- @param name The new name for the item, must be URL-encoded - -- @see {content_item.new} - --*/ - item_id in cr_items.item_id%TYPE, - name in cr_items.name%TYPE -); - -function get_id ( - --/** Takes in a path, such as "/tv/programs/star_trek/episode_203" - -- and returns the id of the item with this path. Note: URLs are abstract (no - -- extensions are allowed in content item names and extensions are stripped when - -- looking up content items) - -- @author Karl Goldstein - -- @param item_path The path to be resolved - -- @param root_folder_id Starts path resolution from this folder. Defaults to - -- the root of the sitemap - -- @param resolve_index Boolean flag indicating whether to return the - -- id of the index page for folders (if one - -- exists). Defaults to 'f'. - -- @return The id of the item with the given path, or null if no such item exists - -- @see {content_item.get_path} - --*/ - item_path in varchar2, - root_folder_id in cr_items.item_id%TYPE default c_root_folder_id, - resolve_index in char default 'f' -) return cr_items.item_id%TYPE; - -function get_path ( - --/** Retrieves the full path to an item, in the form of - -- "/tv/programs/star_trek/episode_203" - -- @author Karl Goldstein - -- @param item_id The item for which the path is to be retrieved - -- @param root_folder_id Starts path resolution from this folder. - -- Defaults to the root of the sitemap - -- @return The path to the item - -- @see {content_item.get_id}, {content_item.write_to_file} - --*/ - item_id in cr_items.item_id%TYPE, - root_folder_id in cr_items.item_id%TYPE default null -) return varchar2; - -function get_virtual_path ( - --/** Retrieves the virtual path to an item, in the form of - -- "/tv/programs/star_trek/episode_203" - -- @author Michael Pih - -- @param item_id The item for which the path is to be retrieved - -- @param root_folder_id Starts path resolution from this folder. - -- Defaults to the root of the sitemap - -- @return The virtual path to the item - -- @see {content_item.get_id}, {content_item.write_to_file}, {content_item.get_path} - --*/ - item_id in cr_items.item_id%TYPE, - root_folder_id in cr_items.item_id%TYPE default c_root_folder_id -) return varchar2; - -procedure write_to_file ( - --/** Writes the content of the live revision of this item to a file, - -- creating all the neccessary directories in the process - -- @author Karl Goldstein - -- @param item_id The item to be written to a file - -- @param root_path The path in the filesystem to which the root of the - -- sitemap corresponds - -- @see {content_item.get_path} - --*/ - item_id in cr_items.item_id%TYPE, - root_path in varchar2 -); - -procedure register_template ( - --/** Registers a template which will be used to render this item. - -- @author Karl Goldstein - -- @param item_id The item for which the template will be registered - -- @param template_id The template to be registered - -- @param use_context The context in which the template is appropriate, such - -- as 'admin' or 'public' - -- @see {content_type.register_template}, {content_item.unregister_template}, - -- {content_item.get_template} - --*/ - item_id in cr_items.item_id%TYPE, - template_id in cr_templates.template_id%TYPE, - use_context in cr_item_template_map.use_context%TYPE -); - -procedure unregister_template ( - --/** Unregisters a template which will be used to render this item. - -- @author Karl Goldstein - -- @param item_id The item for which the template will be unregistered - -- @param template_id The template to be registered - -- @param use_context The context in which the template is appropriate, such - -- as 'admin' or 'public' - -- @see {content_type.register_template}, {content_item.register_template}, - -- {content_item.get_template} - --*/ - item_id in cr_items.item_id%TYPE, - template_id in cr_templates.template_id%TYPE default null, - use_context in cr_item_template_map.use_context%TYPE default null -); - -function get_template ( - --/** Retrieves the template which should be used to render this item. If no template - -- is registered to specifically render the item in the given context, the - -- default template for the item's type is returned. - -- @author Karl Goldstein - -- @param item_id The item for which the template will be unregistered - -- @param use_context The context in the item is to be rendered, such - -- as 'admin' or 'public' - -- @return The id of the registered template, or null if no template could be - -- found - -- @see {content_type.register_template}, {content_item.register_template}, - --*/ - item_id in cr_items.item_id%TYPE, - use_context in cr_item_template_map.use_context%TYPE -) return cr_templates.template_id%TYPE; - -function get_live_revision ( - --/** Retrieves the id of the live revision for the item - -- @param item_id The item for which the live revision is to be retrieved - -- @return The id of the live revision for this item, or null if no live revision - -- exists - -- @see {content_item.set_live_revision}, {content_item.get_latest_revision} - --*/ - item_id in cr_items.item_id%TYPE -) return cr_revisions.revision_id%TYPE; - -procedure set_live_revision ( - --/** Make the specified revision the live revision for the item - -- @author Karl Goldstein - -- @param revision_id The id of the revision which is to become live - -- for its corresponding item - -- @see {content_item.get_live_revision} - --*/ - revision_id in cr_revisions.revision_id%TYPE, - publish_status in cr_items.publish_status%TYPE default 'ready' -); - - -procedure unset_live_revision ( - --/** Set the live revision to null for the item - -- @author Michael Pih - -- @param item_id The id of the item for which to unset the live revision - -- @see {content_item.set_live_revision} - item_id in cr_items.item_id%TYPE -); - -procedure set_release_period ( - --/** Sets the release period for the item. This information may be - -- used by applications to update the publishing status of items - -- at periodic intervals. - -- @author Karl Goldstein - -- @param item_id The id the item. - -- @param start_when The time and date when the item should be released. - -- @param end_when The time and date when the item should be expired. - --*/ - item_id in cr_items.item_id%TYPE, - start_when date default null, - end_when date default null -); - - -function get_revision_count ( - --/** Return the total count of revisions for this item - -- @author Karl Goldstein - -- @param item_id The id the item - -- @return The number of revisions for this item - -- @see {content_revision.new} - --*/ - item_id in cr_items.item_id%TYPE -) return number; - --- Return the object type of this item -function get_content_type ( - --/** Retrieve the content type of this item. Only objects of this type may be - -- used as revisions for the item. - -- @author Karl Goldstein - -- @param item_id The item for which the content type is to be retrieved - -- @return The content type of the item - --*/ - item_id in cr_items.item_id%TYPE -) return cr_items.content_type%TYPE; - -function get_context ( - --/** Retrieve the parent of the given item - -- @author Karl Goldstein - -- @param item_id The item for which the parent is to be retrieved - -- @return The id of the parent for this item - --*/ - item_id in cr_items.item_id%TYPE -) return acs_objects.context_id%TYPE; - -procedure move ( - --/** Move the specified item to a different folder. If the target folder does - -- not exist, or if the folder already contains an item with the same name - -- as the given item, an error will be thrown. - -- @author Karl Goldstein - -- @param item_id The item to be moved - -- @param target_folder_id The new folder for the item - -- @see {content_item.new}, {content_folder.new}, {content_item.copy} - --*/ - item_id in cr_items.item_id%TYPE, - target_folder_id in cr_folders.folder_id%TYPE, - name in cr_items.name%TYPE default null -); - -procedure copy ( - --/** Copies the item to a new location, creating an identical item with - -- an identical latest revision (if any). If the target folder does - -- not exist, or if the folder already contains an item with the same name - -- as the given item, an error will be thrown. - -- @author Karl Goldstein, Michael Pih - -- @param item_id The item to be copied - -- @param target_folder_id The folder where the item is to be copied - -- @param creation_user The user_id of the creator - -- @param creation_ip The IP address of the creator - -- @see {content_item.new}, {content_folder.new}, {content_item.move} - --*/ - item_id in cr_items.item_id%TYPE, - target_folder_id in cr_folders.folder_id%TYPE, - creation_user in acs_objects.creation_user%TYPE, - creation_ip in acs_objects.creation_ip%TYPE default null, - name in cr_items.name%TYPE default null -); - -function copy2 ( - --/** Copies the item to a new location, creating an identical item with - -- an identical latest revision (if any). If the target folder does - -- not exist, or if the folder already contains an item with the same name - -- as the given item, an error will be thrown. - -- @author Karl Goldstein, Michael Pih - -- @param item_id The item to be copied - -- @param target_folder_id The folder where the item is to be copied - -- @param creation_user The user_id of the creator - -- @param creation_ip The IP address of the creator - -- @return The item ID of the new copy. - -- @see {content_item.new}, {content_folder.new}, {content_item.move} - --*/ - item_id in cr_items.item_id%TYPE, - target_folder_id in cr_folders.folder_id%TYPE, - creation_user in acs_objects.creation_user%TYPE, - creation_ip in acs_objects.creation_ip%TYPE default null, - name in cr_items.name%TYPE default null -) return cr_items.item_id%TYPE; - --- get the latest revision for an item -function get_latest_revision ( - --/** Retrieves the id of the latest revision for the item (as opposed to the live - -- revision) - -- @author Karl Goldstein - -- @param item_id The item for which the latest revision is to be retrieved - -- @return The id of the latest revision for this item, or null if no revisions - -- exist - -- @see {content_item.get_live_revision} - --*/ - item_id in cr_items.item_id%TYPE -) return cr_revisions.revision_id%TYPE; - - -function get_best_revision ( - --/** Retrieves the id of the live revision for the item if one exists, - -- otherwise retrieves the id of the latest revision if one exists. - -- revision) - -- @author Michael Pih - -- @param item_id The item for which the revision is to be retrieved - -- @return The id of the live or latest revision for this item, - -- or null if no revisions exist - -- @see {content_item.get_live_revision}, {content_item.get_latest_revision} - --*/ - item_id in cr_items.item_id%TYPE -) return cr_revisions.revision_id%TYPE; - -function get_title ( - --/** Retrieves the title for the item, using either the latest or the live revision. - -- If the specified item is in fact a folder, return the folder's label. - -- In addition, this function will automatically resolve symlinks. - -- @author Karl Goldstein - -- @param item_id The item for which the title is to be retrieved - -- @param is_live If 't', use the live revision to get the title. Otherwise, - -- use the latest revision. The default is 'f' - -- @return The title of the item - -- @see {content_item.get_live_revision}, {content_item.get_latest_revision}, - -- {content_symlink.resolve} - --*/ - item_id in cr_items.item_id%TYPE, - is_live in char default 'f' -) return cr_revisions.title%TYPE; - -function get_publish_date ( - --/** Retrieves the publish date for the item - -- @author Karl Goldstein - -- @param item_id The item for which the publish date is to be retrieved - -- @param is_live If 't', use the live revision for the item. Otherwise, use - -- the latest revision. The default is 'f' - -- @return The publish date for the item, or null if the item has no revisions - -- @see {content_item.get_live_revision}, {content_item.get_latest_revision}, - --*/ - item_id in cr_items.item_id%TYPE, - is_live in char default 'f' -) return cr_revisions.publish_date%TYPE; - -function is_subclass ( - --/** Determines if one type is a subclass of another. A class is always a subclass of - -- itself. - -- @author Karl Goldstein - -- @param object_type The child class - -- @param supertype The superclass - -- @return 't' if the child class is a subclass of the superclass, 'f' otherwise - -- @see {acs_object_type.create_type} - --*/ - object_type in acs_object_types.object_type%TYPE, - supertype in acs_object_types.supertype%TYPE -) return char; - -function relate ( - --/** Relates two content items - -- @author Karl Goldstein - -- @param item_id The item id - -- @param object_id The item id of the related object - -- @param relation_tag A tag to help identify the relation type, - -- defaults to 'generic' - -- @param order_n The order of this object among other objects - -- of the same relation type, defaults to null. - -- @param relation_type The object type of the relation, defaults to - -- 'cr_item_rel' - --*/ - item_id in cr_items.item_id%TYPE, - object_id in acs_objects.object_id%TYPE, - relation_tag in cr_type_relations.relation_tag%TYPE default 'generic', - order_n in cr_item_rels.order_n%TYPE default null, - relation_type in acs_object_types.object_type%TYPE default 'cr_item_rel' -) return cr_item_rels.rel_id%TYPE; - - -procedure unrelate ( - --/** Delete the item relationship between two items - -- @author Michael Pih - -- @param rel_id The relationship id - -- @see {content_item.relate} - --*/ - rel_id in cr_item_rels.rel_id%TYPE -); - -function is_index_page ( - --/** Determine if the item is an index page for the specified folder. - -- The item is an index page for the folder if it exists in the - -- folder and its item name is "index". - -- @author Karl Goldstein - -- @param item_id The item id - -- @param folder_id The folder id - -- @return 't' if the item is an index page for the specified - -- folder, 'f' otherwise - -- @see {content_folder.get_index_page} - --*/ - item_id in cr_items.item_id%TYPE, - folder_id in cr_folders.folder_id%TYPE -) return varchar2; - - -function get_parent_folder ( - --/** Get the parent folder. - -- @author Michael Pih - -- @param item_id The item id - -- @return the folder_id of the parent folder, null otherwise - --*/ - item_id in cr_items.item_id%TYPE -) return cr_folders.folder_id%TYPE; - -end content_item; -/ -show errors - -create or replace package content_folder -as - -function new ( - --/** Create a new folder - -- @author Karl Goldstein - -- @param label The label for the folder - -- @param description A short description of the folder, 4000 characters maximum - -- @param parent_id The parent of the folder - -- @param folder_id The id of the new folder. A new id will be allocated by default - -- @param context_id The context id. The parent id will be used as the default context - -- @param creation_date As in acs_object.new - -- @param creation_ip As in acs_object.new - -- @param creation_user As in acs_object.new - -- @return The id of the newly created folder - -- @see {acs_object.new}, {content_item.new} - --*/ - name in cr_items.name%TYPE, - label in cr_folders.label%TYPE, - description in cr_folders.description%TYPE default null, - parent_id in cr_items.parent_id%TYPE default null, - context_id in acs_objects.context_id%TYPE default null, - folder_id in cr_folders.folder_id%TYPE default null, - creation_date in acs_objects.creation_date%TYPE default sysdate, - creation_user in acs_objects.creation_user%TYPE default null, - creation_ip in acs_objects.creation_ip%TYPE default null -) return cr_folders.folder_id%TYPE; - -procedure del ( - --/** Delete a folder. An error is thrown if the folder is not empty - -- @author Karl Goldstein - -- @param folder_id The id of the folder to delete - -- @see {acs_object.delete}, {content_item.delete} - --*/ - folder_id in cr_folders.folder_id%TYPE, - cascade_p in char default 'f' -); - -procedure edit_name ( - --/** Change the name, label and/or description of the folder - -- @author Karl Goldstein - -- @param folder_id The id of the folder to modify - -- @param name The new name for the folder. An error will be thrown if - -- an item with this name already exists under this folder's - -- parent. If this parameter is null, the old name will be preserved - -- @param label The new label for the folder. The old label will be preserved if - -- this parameter is null - -- @param label The new description for the folder. The old description - -- will be preserved if this parameter is null - -- @see {content_folder.new} - --*/ - folder_id in cr_folders.folder_id%TYPE, - name in cr_items.name%TYPE default null, - label in cr_folders.label%TYPE default null, - description in cr_folders.description%TYPE default null -); - -procedure move ( - --/** Recursively move the folder and all items in into a new location. - -- An error is thrown if either of the parameters is not a folder. - -- The root folder of the sitemap and the root folder of the - -- templates cannot be moved. - -- @author Karl Goldstein - -- @param folder_id The id of the folder to move - -- @param target_folder_id The destination folder - -- @see {content_folder.new}, {content_folder.copy} - --*/ - folder_id in cr_folders.folder_id%TYPE, - target_folder_id in cr_folders.folder_id%TYPE, - name in cr_items.name%TYPE default null -); - -procedure copy ( - --/** Recursively copy the folder and all items in into a new location. - -- An error is thrown if either of the parameters is not a folder. - -- The root folder of the sitemap and the root folder of the - -- templates cannot be copied - -- @author Karl Goldstein - -- @param folder_id The id of the folder to copy - -- @param target_folder_id The destination folder - -- @param creation_user The id of the creation user - -- @param creation_ip The IP address of the creation user (defaults to null) - -- @see {content_folder.new}, {content_folder.copy} - --*/ - folder_id in cr_folders.folder_id%TYPE, - target_folder_id in cr_folders.folder_id%TYPE, - creation_user in acs_objects.creation_user%TYPE, - creation_ip in acs_objects.creation_ip%TYPE default null, - name in cr_items.name%TYPE default null -); - -function is_folder ( - --/** Determine if the item is a folder - -- @author Karl Goldstein - -- @param item_id The item id - -- @return 't' if the item is a folder, 'f' otherwise - -- @see {content_folder.new}, {content_folder.is_sub_folder} - --*/ - item_id in cr_items.item_id%TYPE -) return char; - -function is_sub_folder ( - --/** Determine if the item target_folder_id is a subfolder of - -- the item folder_id - -- @author Karl Goldstein - -- @param folder_id The superfolder id - -- @param target_folder_id The subfolder id - -- @return 't' if the item target_folder_id is a subfolder of - -- the item folder_id, 'f' otherwise - -- @see {content_folder.is_folder} - --*/ - folder_id in cr_folders.folder_id%TYPE, - target_folder_id in cr_folders.folder_id%TYPE -) return char; - -function is_empty ( - --/** Determine if the folder is empty - -- @author Karl Goldstein - -- @param folder_id The folder id - -- @return 't' if the folder contains no subfolders or items, 'f' otherwise - -- @see {content_folder.is_folder} - --*/ - folder_id in cr_folders.folder_id%TYPE -) return varchar2; - -function is_root ( - --/** Determine whether the folder is a root (has a parent_id of 0) - -- @author Karl Goldstein - -- @param folder_id The folder ID - -- @return 't' if the folder is a root or 'f' otherwise - --*/ - folder_id in cr_folders.folder_id%TYPE -) return char; - -procedure register_content_type ( - --/** Register a content type to the folder, if it is not already registered. - -- Only items of the registered type(s) may be added to the folder. - -- @author Karl Goldstein - -- @param folder_id The folder id - -- @param content_type The content type to be registered - -- @see {content_folder.unregister_content_type}, - -- {content_folder.is_registered} - --*/ - folder_id in cr_folders.folder_id%TYPE, - content_type in cr_folder_type_map.content_type%TYPE, - include_subtypes in varchar2 default 'f' -); - -procedure unregister_content_type ( - --/** Unregister a content type from the folder, if it has been registered. - -- Only items of the registered type(s) may be added to the folder. - -- If the folder already contains items of the type to be unregistered, the - -- items remain in the folder. - -- @author Karl Goldstein - -- @param folder_id The folder id - -- @param content_type The content type to be unregistered - -- @param include_subtypes If 't', all subtypes of content_type will be - -- unregistered as well - -- @see {content_folder.register_content_type}, {content_folder.is_registered} - --*/ - folder_id in cr_folders.folder_id%TYPE, - content_type in cr_folder_type_map.content_type%TYPE, - include_subtypes in varchar2 default 'f' -); - --- change this to is_type_registered -function is_registered ( - --/** Determines if a content type is registered to the folder - -- Only items of the registered type(s) may be added to the folder. - -- @author Karl Goldstein - -- @param folder_id The folder id - -- @param content_type The content type to be checked - -- @param include_subtypes If 't', all subtypes of the content_type - -- will be checked, returning 't' if all of them are registered. If 'f', - -- only an exact match with content_type will be - -- performed. - -- @return 't' if the type is registered to this folder, 'f' otherwise - -- @see {content_folder.register_content_type}, {content_folder.unregister_content_type}, - --*/ - folder_id in cr_folders.folder_id%TYPE, - content_type in cr_folder_type_map.content_type%TYPE, - include_subtypes in varchar2 default 'f' -) return varchar2; - - -function get_label ( - --/** Returns the label for the folder. This function is the default name method - -- for the folder object. - -- @author Karl Goldstein - -- @param folder_id The folder id - -- @return The folder's label - -- @see {acs_object_type.create_type}, the docs for the name_method parameter - --*/ - folder_id in cr_folders.folder_id%TYPE -) return cr_folders.label%TYPE; - - -function get_index_page ( - --/** Returns the item ID of the index page of the folder, null otherwise - -- @author Michael Pih - -- @param folder_id The folder id - -- @return The item ID of the index page - --*/ - folder_id in cr_folders.folder_id%TYPE -) return cr_items.item_id%TYPE; - - - -end content_folder; -/ -show errors - -create or replace package body content_item -as - -function get_root_folder ( - item_id in cr_items.item_id%TYPE default null -) return cr_folders.folder_id%TYPE is - - v_folder_id cr_folders.folder_id%TYPE; - -begin - - if item_id is NULL then - - v_folder_id := c_root_folder_id; - - else - - select - item_id into v_folder_id - from - cr_items - where - parent_id = 0 - connect by - prior parent_id = item_id - start with - item_id = get_root_folder.item_id; - - end if; - - return v_folder_id; - -exception - when NO_DATA_FOUND then - raise_application_error(-20000, - 'Could not find a root folder for item ID ' || item_id || '. ' || - 'Either the item does not exist or its parent value is corrupted.'); -end get_root_folder; - -function new ( - name in cr_items.name%TYPE, - parent_id in cr_items.parent_id%TYPE default null, - item_id in acs_objects.object_id%TYPE default null, - locale in cr_items.locale%TYPE default null, - creation_date in acs_objects.creation_date%TYPE - default sysdate, - creation_user in acs_objects.creation_user%TYPE - default null, - context_id in acs_objects.context_id%TYPE - default null, - creation_ip in acs_objects.creation_ip%TYPE default null, - item_subtype in acs_object_types.object_type%TYPE - default 'content_item', - content_type in acs_object_types.object_type%TYPE - default 'content_revision', - title in cr_revisions.title%TYPE default null, - description in cr_revisions.description%TYPE default null, - mime_type in cr_revisions.mime_type%TYPE default 'text/plain', - nls_language in cr_revisions.nls_language%TYPE default null, - text in varchar2 default null, - data in cr_revisions.content%TYPE default null, - relation_tag in cr_child_rels.relation_tag%TYPE default null, - is_live in char default 'f', - storage_type in cr_items.storage_type%TYPE default 'lob' -) return cr_items.item_id%TYPE -is - v_parent_id cr_items.parent_id%TYPE; - v_parent_type acs_objects.object_type%TYPE; - v_item_id cr_items.item_id%TYPE; - v_revision_id cr_revisions.revision_id%TYPE; - v_title cr_revisions.title%TYPE; - v_rel_id acs_objects.object_id%TYPE; - v_rel_tag cr_child_rels.relation_tag%TYPE; - v_context_id acs_objects.context_id%TYPE; - v_storage_type cr_items.storage_type%TYPE; -begin - - -- if content_item.is_subclass(item_subtype,'content_item') = 'f' then - -- raise_application_error(-20000, 'The object_type ' || item_subtype || - -- ' does not inherit from content_item.'); - -- end if; - - -- place the item in the context of the pages folder if no - -- context specified - - if storage_type = 'text' then - v_storage_type := 'lob'; - else - v_storage_type := storage_type; - end if; - - if parent_id is null then - v_parent_id := c_root_folder_id; - else - v_parent_id := parent_id; - end if; - - -- Determine context_id - if context_id is null then - v_context_id := v_parent_id; - else - v_context_id := context_id; - end if; - - if v_parent_id = 0 or - content_folder.is_folder(v_parent_id) = 't' then - - if v_parent_id ^= 0 and - content_folder.is_registered( - v_parent_id, content_item.new.content_type, 'f') = 'f' then - - raise_application_error(-20000, - 'This item''s content type ' || content_item.new.content_type || - ' is not registered to this folder ' || v_parent_id); - - end if; - - elsif v_parent_id ^= 0 then - - begin - - -- Figure out the relation_tag to use - if content_item.new.relation_tag is null then - v_rel_tag := content_item.get_content_type(v_parent_id) - || '-' || content_item.new.content_type; - else - v_rel_tag := content_item.new.relation_tag; - end if; - - select object_type into v_parent_type from acs_objects - where object_id = v_parent_id; - - if is_subclass(v_parent_type, 'content_item') = 't' and - is_valid_child(v_parent_id, content_item.new.content_type, v_rel_tag) = 'f' then - - raise_application_error(-20000, - 'This item''s content type ' || content_item.new.content_type || - ' is not allowed in this container ' || v_parent_id); - - end if; - - exception when NO_DATA_FOUND then - - raise_application_error(-20000, - 'Invalid parent ID ' || v_parent_id || - ' specified in content_item.new'); - - end; - - end if; - - -- Create the object - - v_item_id := acs_object.new( - object_id => content_item.new.item_id, - object_type => content_item.new.item_subtype, - context_id => v_context_id, - creation_date => content_item.new.creation_date, - creation_user => content_item.new.creation_user, - creation_ip => content_item.new.creation_ip - ); - - -- Turn off security inheritance if there is no security context - --if context_id is null then - -- update acs_objects set security_inherit_p = 'f' - -- where object_id = v_item_id; - --end if; - - insert into cr_items ( - item_id, name, content_type, parent_id, storage_type - ) values ( - v_item_id, content_item.new.name, - content_item.new.content_type, v_parent_id, v_storage_type - ); - - -- if the parent is not a folder, insert into cr_child_rels - -- We checked above before creating the object that it is a valid rel - if v_parent_id ^= 0 and - content_folder.is_folder(v_parent_id) = 'f' then - - v_rel_id := acs_object.new( - object_type => 'cr_item_child_rel', - context_id => v_parent_id - ); - - insert into cr_child_rels ( - rel_id, parent_id, child_id, relation_tag, order_n - ) values ( - v_rel_id, v_parent_id, v_item_id, v_rel_tag, v_item_id - ); - - end if; - - -- use the name of the item if no title is supplied - if content_item.new.title is null then - v_title := content_item.new.name; - else - v_title := content_item.new.title; - end if; - - -- create the revision if data or title or text is not null - -- note that the caller could theoretically specify both text - -- and data, in which case the text is ignored. - - if content_item.new.data is not null then - - v_revision_id := content_revision.new( - item_id => v_item_id, - title => v_title, - description => content_item.new.description, - data => content_item.new.data, - mime_type => content_item.new.mime_type, - creation_date => content_item.new.creation_date, - creation_user => content_item.new.creation_user, - creation_ip => content_item.new.creation_ip, - nls_language => content_item.new.nls_language - ); - - elsif content_item.new.title is not null or - content_item.new.text is not null then - - v_revision_id := content_revision.new( - item_id => v_item_id, - title => v_title, - description => content_item.new.description, - text => content_item.new.text, - mime_type => content_item.new.mime_type, - creation_date => content_item.new.creation_date, - creation_user => content_item.new.creation_user, - creation_ip => content_item.new.creation_ip - ); - - end if; - - -- make the revision live if is_live is 't' - if content_item.new.is_live = 't' then - content_item.set_live_revision(v_revision_id); - end if; - - -- Have the new item inherit the permission of the parent item - -- if no security context was specified - --if parent_id is not null and context_id is null then - -- content_permission.inherit_permissions ( - -- parent_id, v_item_id, creation_user - -- ); - --end if; - - return v_item_id; -end new; - -function is_published ( - item_id in cr_items.item_id%TYPE -) return char -is - v_is_published char(1); -begin - - select - 't' into v_is_published - from - cr_items - where - live_revision is not null - and - publish_status = 'live' - and - item_id = is_published.item_id; - - return v_is_published; - exception - when NO_DATA_FOUND then - return 'f'; -end is_published; - -function is_publishable ( - item_id in cr_items.item_id%TYPE -) return char -is - v_child_count integer; - v_rel_count integer; - v_template_id cr_templates.template_id%TYPE; - - -- get the child types registered to this content type - cursor c_child_types is - select - child_type, min_n, max_n - from - cr_type_children - where - parent_type = content_item.get_content_type( is_publishable.item_id ); - - -- get the relation types registered to this content type - cursor c_rel_types is - select - target_type, min_n, max_n - from - cr_type_relations - where - content_type = content_item.get_content_type( is_publishable.item_id ); - - -- get the publishing workflows associated with this content item - -- there should only be 1 if CMS exists, otherwise 0 - -- cursor c_pub_wf is - -- select - -- case_id, state - -- from - -- wf_cases - -- where - -- workflow_key = 'publishing_wf' - -- and - -- object_id = is_publishable.item_id; - -begin - - -- validate children - -- make sure the # of children of each type fall between min_n and max_n - for v_child_type in c_child_types loop - select - count(rel_id) into v_child_count - from - cr_child_rels - where - parent_id = is_publishable.item_id - and - content_item.get_content_type( child_id ) = v_child_type.child_type; - - -- make sure # of children is in range - if v_child_type.min_n is not null - and v_child_count < v_child_type.min_n then - return 'f'; - end if; - if v_child_type.max_n is not null - and v_child_count > v_child_type.max_n then - return 'f'; - end if; - - end loop; - - - -- validate relations - -- make sure the # of ext links of each type fall between min_n and max_n - for v_rel_type in c_rel_types loop - select - count(rel_id) into v_rel_count - from - cr_item_rels i, acs_objects o - where - i.related_object_id = o.object_id - and - i.item_id = is_publishable.item_id - and - nvl(content_item.get_content_type(o.object_id),o.object_type) = v_rel_type.target_type; - - -- make sure # of object relations is in range - if v_rel_type.min_n is not null - and v_rel_count < v_rel_type.min_n then - return 'f'; - end if; - if v_rel_type.max_n is not null - and v_rel_count > v_rel_type.max_n then - return 'f'; - end if; - end loop; - - -- validate publishing workflows - -- make sure any 'publishing_wf' associated with this item are finished - -- KG: logic is wrong here. Only the latest workflow matters, and even - -- that is a little problematic because more than one workflow may be - -- open on an item. In addition, this should be moved to CMS. - - -- Removed this as having workflow stuff in the CR is just plain wrong. - -- DanW, Aug 25th, 2001. - - -- for v_pub_wf in c_pub_wf loop - -- if v_pub_wf.state ^= 'finished' then - -- return 'f'; - -- end if; - -- end loop; - - return 't'; - exception - when NO_DATA_FOUND then - return 'f'; -end is_publishable; - -function is_valid_child ( - item_id in cr_items.item_id%TYPE, - content_type in acs_object_types.object_type%TYPE, - relation_tag in cr_child_rels.relation_tag%TYPE default null -) return char -is - v_is_valid_child char(1); - v_max_children cr_type_children.max_n%TYPE; - v_n_children integer; -begin - - v_is_valid_child := 'f'; - - -- first check if content_type is a registered child_type - begin - select - sum(max_n) into v_max_children - from - cr_type_children - where - parent_type = content_item.get_content_type( is_valid_child.item_id ) - and - child_type = is_valid_child.content_type - and - (is_valid_child.relation_tag is null - or is_valid_child.relation_tag = relation_tag); - - exception - when NO_DATA_FOUND then - return 'f'; - end; - - -- if the max is null then infinite number is allowed - if v_max_children is null then - return 't'; - end if; - - -- next check if there are already max_n children of that content type - select - count(rel_id) into v_n_children - from - cr_child_rels - where - parent_id = is_valid_child.item_id - and - content_item.get_content_type( child_id ) = is_valid_child.content_type - and - (is_valid_child.relation_tag is null - or is_valid_child.relation_tag = relation_tag); - - if v_n_children < v_max_children then - v_is_valid_child := 't'; - end if; - - return v_is_valid_child; - exception - when NO_DATA_FOUND then - return 'f'; -end is_valid_child; - -/* delete a content item - 1) delete all associated workflows - 2) delete all symlinks associated with this object - 3) delete any revisions for this item - 4) unregister template relations - 5) delete all permissions associated with this item - 6) delete keyword associations - 7) delete all associated comments */ -procedure del ( - item_id in cr_items.item_id%TYPE -) is - --- cursor c_wf_cases_cur is --- select --- case_id --- from --- wf_cases --- where --- object_id = item_id; - - cursor c_symlink_cur is - select - symlink_id - from - cr_symlinks - where - target_id = content_item.del.item_id; - - cursor c_revision_cur is - select - revision_id - from - cr_revisions - where - item_id = content_item.del.item_id; - - cursor c_rel_cur is - select - rel_id - from - cr_item_rels - where - item_id = content_item.del.item_id - or - related_object_id = content_item.del.item_id; - - cursor c_child_cur is - select - rel_id - from - cr_child_rels - where - child_id = content_item.del.item_id; - - cursor c_parent_cur is - select - rel_id, child_id - from - cr_child_rels - where - parent_id = content_item.del.item_id; - - -- this is strictly for debugging - -- cursor c_error_cur is - -- select - -- object_id, object_type - -- from - -- acs_objects - -- where - -- context_id = content_item.delete.item_id; - -begin - - -- Removed this as having workflow stuff in the CR is just plain wrong. - -- DanW, Aug 25th, 2001. - - -- dbms_output.put_line('Deleting associated workflows...'); - -- 1) delete all workflow cases associated with this item - -- for v_wf_cases_val in c_wf_cases_cur loop - -- workflow_case.delete(v_wf_cases_val.case_id); - -- end loop; - - dbms_output.put_line('Deleting symlinks...'); - -- 2) delete all symlinks to this item - for v_symlink_val in c_symlink_cur loop - content_symlink.del(v_symlink_val.symlink_id); - end loop; - - dbms_output.put_line('Unscheduling item...'); - delete from cr_release_periods - where item_id = content_item.del.item_id; - - dbms_output.put_line('Deleting associated revisions...'); - -- 3) delete all revisions of this item - delete from cr_item_publish_audit - where item_id = content_item.del.item_id; - for v_revision_val in c_revision_cur loop - content_revision.del(v_revision_val.revision_id); - end loop; - - dbms_output.put_line('Deleting associated item templates...'); - -- 4) unregister all templates to this item - delete from cr_item_template_map - where item_id = content_item.del.item_id; - - dbms_output.put_line('Deleting item relationships...'); - -- Delete all relations on this item - for v_rel_val in c_rel_cur loop - acs_rel.del(v_rel_val.rel_id); - end loop; - - dbms_output.put_line('Deleting child relationships...'); - for v_rel_val in c_child_cur loop - acs_rel.del(v_rel_val.rel_id); - end loop; - - dbms_output.put_line('Deleting parent relationships...'); - for v_rel_val in c_parent_cur loop - acs_rel.del(v_rel_val.rel_id); - content_item.del(v_rel_val.child_id); - end loop; - - dbms_output.put_line('Deleting associated permissions...'); - -- 5) delete associated permissions - delete from acs_permissions - where object_id = content_item.del.item_id; - - dbms_output.put_line('Deleting keyword associations...'); - -- 6) delete keyword associations - delete from cr_item_keyword_map - where item_id = content_item.del.item_id; - - dbms_output.put_line('Deleting associated comments...'); - -- 7) delete associated comments - journal_entry.delete_for_object( content_item.del.item_id ); - - -- context_id debugging loop - --for v_error_val in c_error_cur loop - -- dbms_output.put_line('ID=' || v_error_val.object_id || ' TYPE=' - -- || v_error_val.object_type); - --end loop; - - dbms_output.put_line('Deleting content item...'); - acs_object.del(content_item.del.item_id); - -end del; - - -procedure edit_name ( - item_id in cr_items.item_id%TYPE, - name in cr_items.name%TYPE -) is - cursor exists_cur is - select - item_id - from - cr_items - where - cr_items.name = content_item.edit_name.name - and - parent_id = (select - parent_id - from - cr_items - where - cr_items.item_id = content_item.edit_name.item_id); - - exists_id integer; -begin - - open exists_cur; - fetch exists_cur into exists_id; - - if exists_cur%NOTFOUND then - close exists_cur; - update cr_items - set cr_items.name = content_item.edit_name.name - where cr_items.item_id = content_item.edit_name.item_id; - else - close exists_cur; - if exists_id <> item_id then - raise_application_error(-20000, - 'An item with the name ' || name || - ' already exists in this directory.'); - end if; - end if; - -end edit_name; - -function get_id ( - item_path in varchar2, - root_folder_id in cr_items.item_id%TYPE default c_root_folder_id, - resolve_index in char default 'f' -) return cr_items.item_id%TYPE is - - v_item_path varchar2(4000); - v_root_folder_id cr_items.item_id%TYPE; - parent_id integer; - child_id integer; - start_pos integer := 1; - end_pos integer; - counter integer := 0; - item_name varchar2(200); - -begin - - v_root_folder_id := nvl(root_folder_id, c_root_folder_id); - - -- If the request path is the root, then just return the root folder - if item_path = '/' then - return v_root_folder_id; - end if; - - -- Remove leading, trailing spaces, leading slashes - v_item_path := rtrim(ltrim(trim(item_path), '/'), '/'); - - parent_id := v_root_folder_id; - - -- if parent_id is a symlink, resolve it - parent_id := content_symlink.resolve(parent_id); - - loop - - end_pos := instr(v_item_path, '/', start_pos); - - if end_pos = 0 then - item_name := substr(v_item_path, start_pos); - else - item_name := substr(v_item_path, start_pos, end_pos - start_pos); - end if; - - select - item_id into child_id - from - cr_items - where - parent_id = get_id.parent_id - and - name = item_name; - - exit when end_pos = 0; - - parent_id := child_id; - - -- if parent_id is a symlink, resolve it - parent_id := content_symlink.resolve(parent_id); - - start_pos := end_pos + 1; - - end loop; - - if get_id.resolve_index = 't' then - - -- if the item is a folder and has an index page, then return - - if content_folder.is_folder( child_id ) = 't' and - content_folder.get_index_page( child_id ) is not null then - - child_id := content_folder.get_index_page( child_id ); - - end if; - - end if; - - return child_id; - -exception - when NO_DATA_FOUND then - return null; -end get_id; - -function get_path ( - item_id in cr_items.item_id%TYPE, - root_folder_id in cr_items.item_id%TYPE default null -) return varchar2 -is - - cursor c_abs_cur is - select - name, parent_id, level as tree_level - from - cr_items - where - parent_id <> 0 - connect by - prior parent_id = item_id - start with - item_id = get_path.item_id - order by - tree_level desc; - - v_count integer; - v_name varchar2(400); - v_parent_id integer := 0; - v_tree_level integer; - - v_resolved_root_id integer; - - cursor c_rel_cur is - select - parent_id, level as tree_level - from - cr_items - where - parent_id <> 0 - connect by - prior parent_id = item_id - start with - item_id = v_resolved_root_id - order by - tree_level desc; - - v_rel_parent_id integer := 0; - v_rel_tree_level integer := 0; - - v_path varchar2(4000) := ''; - -begin - - -- check that the item exists - select count(*) into v_count from cr_items where item_id = get_path.item_id; - - if v_count = 0 then - raise_application_error(-20000, 'Invalid item ID: ' || item_id); - end if; - - -- begin walking down the path to the item (from the repository root) - open c_abs_cur; - - -- if the root folder is not null then prepare for a relative path - - if root_folder_id is not null then - - -- if root_folder_id is a symlink, resolve it (child items will point - -- to the actual folder, not the symlink) - - v_resolved_root_id := content_symlink.resolve(root_folder_id); - - -- begin walking down the path to the root folder. Discard - -- elements of the item path as long as they are the same as the root - -- folder - - open c_rel_cur; - - while v_parent_id = v_rel_parent_id loop - fetch c_abs_cur into v_name, v_parent_id, v_tree_level; - fetch c_rel_cur into v_rel_parent_id, v_rel_tree_level; - exit when c_abs_cur%NOTFOUND or c_rel_cur%NOTFOUND; - end loop; - - -- walk the remainder of the relative path, add a '..' for each - -- additional step - - loop - exit when c_rel_cur%NOTFOUND; - v_path := v_path || '../'; - fetch c_rel_cur into v_rel_parent_id, v_rel_tree_level; - end loop; - close c_rel_cur; - - -- an item relative to itself is '../item' - if v_resolved_root_id = item_id then - v_path := '../'; - end if; - - else - - -- this is an absolute path so prepend a '/' - v_path := '/'; - - -- prime the pump to be consistent with relative path execution plan - fetch c_abs_cur into v_name, v_parent_id, v_tree_level; - - end if; - - -- loop over the remainder of the absolute path - - loop - - v_path := v_path || v_name; - - fetch c_abs_cur into v_name, v_parent_id, v_tree_level; - - exit when c_abs_cur%NOTFOUND; - - v_path := v_path || '/'; - - end loop; - close c_abs_cur; - - return v_path; - -end get_path; - - -function get_virtual_path ( - item_id in cr_items.item_id%TYPE, - root_folder_id in cr_items.item_id%TYPE default c_root_folder_id -) return varchar2 -is - v_path varchar2(4000); - v_item_id cr_items.item_id%TYPE; - v_is_folder char(1); - v_index cr_items.item_id%TYPE; -begin - - -- first resolve the item - v_item_id := content_symlink.resolve( get_virtual_path.item_id ); - - v_is_folder := content_folder.is_folder( v_item_id ); - v_index := content_folder.get_index_page( v_item_id ); - - -- if the folder has an index page - if v_is_folder = 't' and v_index is not null then - v_path := content_item.get_path( content_symlink.resolve( v_index )); - else - v_path := content_item.get_path( v_item_id ); - end if; - - return v_path; - exception - when NO_DATA_FOUND then - return null; -end get_virtual_path; - - - -procedure write_to_file ( - item_id in cr_items.item_id%TYPE, - root_path in varchar2 -)is - - blob_loc cr_revisions.content%TYPE; - v_revision cr_items.live_revision%TYPE; - -begin - - v_revision := get_live_revision(item_id); - select content into blob_loc from cr_revisions - where revision_id = v_revision; - - blob_to_file(root_path || get_path(item_id), blob_loc); - -exception when no_data_found then - - raise_application_error(-20000, 'No live revision for content item' || - item_id || ' in content_item.write_to_file.'); - -end write_to_file; - -procedure register_template ( - item_id in cr_items.item_id%TYPE, - template_id in cr_templates.template_id%TYPE, - use_context in cr_item_template_map.use_context%TYPE -) is - -begin - - -- register template if it is not already registered - insert into cr_item_template_map ( - template_id, item_id, use_context - ) select - register_template.template_id, - register_template.item_id, - register_template.use_context - from - dual - where - not exists ( select 1 - from - cr_item_template_map - where - item_id = register_template.item_id - and - template_id = register_template.template_id - and - use_context = register_template.use_context ); - -end register_template; - -procedure unregister_template ( - item_id in cr_items.item_id%TYPE, - template_id in cr_templates.template_id%TYPE default null, - use_context in cr_item_template_map.use_context%TYPE default null -) is - -begin - - if use_context is null and template_id is null then - - delete from cr_item_template_map - where item_id = unregister_template.item_id; - - elsif use_context is null then - - delete from cr_item_template_map - where template_id = unregister_template.template_id - and item_id = unregister_template.item_id; - - elsif template_id is null then - - delete from cr_item_template_map - where item_id = unregister_template.item_id - and use_context = unregister_template.use_context; - - else - - delete from cr_item_template_map - where template_id = unregister_template.template_id - and item_id = unregister_template.item_id - and use_context = unregister_template.use_context; - - end if; - -end unregister_template; - -function get_template ( - item_id in cr_items.item_id%TYPE, - use_context in cr_item_template_map.use_context%TYPE -) return cr_templates.template_id%TYPE is - - v_template_id cr_templates.template_id%TYPE; - v_content_type cr_items.content_type%TYPE; - - cursor item_cur is - select - template_id - from - cr_item_template_map - where - item_id = get_template.item_id - and - use_context = get_template.use_context; - -begin - - -- look for a template assigned specifically to this item - open item_cur; - fetch item_cur into v_template_id; - - -- otherwise get the default for the content type - if item_cur%NOTFOUND then - select - m.template_id - into - v_template_id - from - cr_items i, cr_type_template_map m - where - i.item_id = get_template.item_id - and - i.content_type = m.content_type - and - m.use_context = get_template.use_context - and - m.is_default = 't'; - end if; - close item_cur; - - return v_template_id; - -exception - when NO_DATA_FOUND then - if item_cur%ISOPEN then - close item_cur; - end if; - return null; -end get_template; - --- Return the object type of this item - -function get_content_type ( - item_id in cr_items.item_id%TYPE -) return cr_items.content_type%TYPE is - v_content_type cr_items.content_type%TYPE; -begin - - select - content_type into v_content_type - from - cr_items - where - item_id = get_content_type.item_id; - - return v_content_type; -exception - when NO_DATA_FOUND then - return null; -end get_content_type; - -function get_live_revision ( - item_id in cr_items.item_id%TYPE -) return cr_revisions.revision_id%TYPE is - - v_revision_id acs_objects.object_id%TYPE; - -begin - - select - live_revision into v_revision_id - from - cr_items - where - item_id = get_live_revision.item_id; - - return v_revision_id; - -exception - when NO_DATA_FOUND then - return null; -end get_live_revision; - -procedure set_live_revision ( - revision_id in cr_revisions.revision_id%TYPE, - publish_status in cr_items.publish_status%TYPE default 'ready' -) is -begin - - update - cr_items - set - live_revision = set_live_revision.revision_id, - publish_status = set_live_revision.publish_status - where - item_id = (select - item_id - from - cr_revisions - where - revision_id = set_live_revision.revision_id); - - update - cr_revisions - set - publish_date = sysdate - where - revision_id = set_live_revision.revision_id; - -end set_live_revision; - - -procedure unset_live_revision ( - item_id in cr_items.item_id%TYPE -) is -begin - - update - cr_items - set - live_revision = NULL - where - item_id = unset_live_revision.item_id; - - -- if an items publish status is "live", change it to "ready" - update - cr_items - set - publish_status = 'production' - where - publish_status = 'live' - and - item_id = unset_live_revision.item_id; - - -end unset_live_revision; - - -procedure set_release_period ( - item_id in cr_items.item_id%TYPE, - start_when date default null, - end_when date default null -) is - - v_count integer; - -begin - - select decode(count(*),0,0,1) into v_count from cr_release_periods - where item_id = set_release_period.item_id; - - if v_count = 0 then - - insert into cr_release_periods ( - item_id, start_when, end_when - ) values ( - item_id, start_when, end_when - ); - - else - - update cr_release_periods - set start_when = set_release_period.start_when, - end_when = set_release_period.end_when - where - item_id = set_release_period.item_id; - - end if; - -end set_release_period; - - -function get_revision_count ( - item_id in cr_items.item_id%TYPE -) return number is - - v_count integer; - -begin - - select - count(*) into v_count - from - cr_revisions - where - item_id = get_revision_count.item_id; - - return v_count; - -end get_revision_count; - -function get_context ( - item_id in cr_items.item_id%TYPE -) return acs_objects.context_id%TYPE is - - v_context_id acs_objects.context_id%TYPE; - -begin - - select - context_id - into - v_context_id - from - acs_objects - where - object_id = get_context.item_id; - - return v_context_id; - -exception when no_data_found then - - raise_application_error(-20000, 'Content item ' || item_id || - ' does not exist in content_item.get_context'); - - -end get_context; - --- 1) make sure we are not moving the item to an invalid location: --- that is, the destination folder exists and is a valid folder --- 2) make sure the content type of the content item is registered --- to the target folder --- 3) update the parent_id for the item -procedure move ( - item_id in cr_items.item_id%TYPE, - target_folder_id in cr_folders.folder_id%TYPE, - name in cr_items.name%TYPE default null -) is -begin - - if content_folder.is_folder(item_id) = 't' then - content_folder.move(item_id, target_folder_id, name); - elsif content_folder.is_folder(target_folder_id) = 't' then - - - if content_folder.is_registered( move.target_folder_id, - get_content_type( move.item_id )) = 't' and - content_folder.is_registered( move.target_folder_id, - get_content_type( content_symlink.resolve( move.item_id)),'f') = 't' - then - - -- update the parent_id for the item - update cr_items - set parent_id = move.target_folder_id, - name = nvl (move.name, cr_items.name) - where item_id = move.item_id; - end if; - - end if; -end move; - -procedure copy ( - item_id in cr_items.item_id%TYPE, - target_folder_id in cr_folders.folder_id%TYPE, - creation_user in acs_objects.creation_user%TYPE, - creation_ip in acs_objects.creation_ip%TYPE default null, - name in cr_items.name%TYPE default null -) is - - copy_id cr_items.item_id%TYPE; - -begin - - copy_id := copy2(item_id, target_folder_id, creation_user, creation_ip, name); - -end copy; - --- copy a content item to a target folder --- 1) make sure we are not copying the item to an invalid location: --- that is, the destination folder exists, is a valid folder, --- and is not the current folder --- 2) make sure the content type of the content item is registered --- with the current folder --- 3) create a new item with no revisions in the target folder --- 4) copy the latest revision from the original item to the new item (if any) - -function copy2 ( - item_id in cr_items.item_id%TYPE, - target_folder_id in cr_folders.folder_id%TYPE, - creation_user in acs_objects.creation_user%TYPE, - creation_ip in acs_objects.creation_ip%TYPE default null, - name in cr_items.name%TYPE default null -) return cr_items.item_id%TYPE is - v_current_folder_id cr_folders.folder_id%TYPE; - v_num_revisions integer; - v_name cr_items.name%TYPE; - v_content_type cr_items.content_type%TYPE; - v_locale cr_items.locale%TYPE; - v_item_id cr_items.item_id%TYPE; - v_revision_id cr_revisions.revision_id%TYPE; - v_is_registered char(1); - v_old_revision_id cr_revisions.revision_id%TYPE; - v_new_revision_id cr_revisions.revision_id%TYPE; - v_storage_type cr_items.storage_type%TYPE; -begin - - -- call content_folder.copy if the item is a folder - if content_folder.is_folder(copy2.item_id) = 't' then - content_folder.copy( - folder_id => copy2.item_id, - target_folder_id => copy2.target_folder_id, - creation_user => copy2.creation_user, - creation_ip => copy2.creation_ip, - name => copy2.name - ); - -- call content_symlink.copy if the item is a symlink - elsif content_symlink.is_symlink(copy2.item_id) = 't' then - content_symlink.copy( - symlink_id => copy2.item_id, - target_folder_id => copy2.target_folder_id, - creation_user => copy2.creation_user, - creation_ip => copy2.creation_ip, - name => copy2.name - ); - -- call content_extlink.copy if the item is a extlink - elsif content_extlink.is_extlink(copy2.item_id) = 't' then - content_extlink.copy( - extlink_id => copy2.item_id, - target_folder_id => copy2.target_folder_id, - creation_user => copy2.creation_user, - creation_ip => copy2.creation_ip, - name => copy2.name - ); - -- call content_extlink.copy if the item is a extlink - elsif content_extlink.is_extlink(copy2.item_id) = 't' then - content_extlink.copy( - extlink_id => copy2.item_id, - target_folder_id => copy2.target_folder_id, - creation_user => copy2.creation_user, - creation_ip => copy2.creation_ip - ); - -- make sure the target folder is really a folder - elsif content_folder.is_folder(copy2.target_folder_id) = 't' then - - select - parent_id - into - v_current_folder_id - from - cr_items - where - item_id = copy2.item_id; - - select - content_type, name , locale, - nvl(live_revision, latest_revision), storage_type - into - v_content_type, v_name, v_locale, v_revision_id, v_storage_type - from - cr_items - where - item_id = copy2.item_id; - - -- can't copy to the same folder unless name is different - if copy2.target_folder_id ^= v_current_folder_id or (v_name != copy2.name and copy2.name is not null) then - - if copy2.name is not null then - v_name := copy2.name; - end if; - -- make sure the content type of the item is registered to the folder - v_is_registered := content_folder.is_registered( - folder_id => copy2.target_folder_id, - content_type => v_content_type, - include_subtypes => 'f' - ); - - if v_is_registered = 't' then - -- create the new content item - v_item_id := content_item.new( - parent_id => copy2.target_folder_id, - name => v_name, - locale => v_locale, - content_type => v_content_type, - creation_user => copy2.creation_user, - creation_ip => copy2.creation_ip, - storage_type => v_storage_type - ); - - -- get the latest revision of the old item - select - latest_revision into v_old_revision_id - from - cr_items - where - item_id = copy2.item_id; - - -- copy the latest revision (if any) to the new item - if v_old_revision_id is not null then - v_new_revision_id := content_revision.copy ( - revision_id => v_old_revision_id, - target_item_id => v_item_id, - creation_user => copy2.creation_user, - creation_ip => copy2.creation_ip - ); - end if; - end if; - - - end if; - end if; - - return v_item_id; - -end copy2; - --- get the latest revision for an item -function get_latest_revision ( - item_id in cr_items.item_id%TYPE -) return cr_revisions.revision_id%TYPE is - v_revision_id integer; - - cursor c_revision_cur is - select - r.revision_id - from - cr_revisions r, acs_objects o - where - r.revision_id = o.object_id - and - r.item_id = get_latest_revision.item_id - order by - o.creation_date desc; -begin - - if item_id is null then - return null; - end if; - - open c_revision_cur; - fetch c_revision_cur into v_revision_id; - if c_revision_cur%NOTFOUND then - close c_revision_cur; - return null; - end if; - close c_revision_cur; - return v_revision_id; - -exception - when NO_DATA_FOUND then - if c_revision_cur%ISOPEN then - close c_revision_cur; - end if; - return null; -end get_latest_revision; - - - -function get_best_revision ( - item_id in cr_items.item_id%TYPE -) return cr_revisions.revision_id%TYPE -is - v_revision_id cr_revisions.revision_id%TYPE; -begin - - select - NVL (live_revision, latest_revision ) - into - v_revision_id - from - cr_items - where - item_id = get_best_revision.item_id; - - return v_revision_id; -exception - when NO_DATA_FOUND then - return null; -end get_best_revision; - - - -function get_title ( - item_id in cr_items.item_id%TYPE, - is_live in char default 'f' -) return cr_revisions.title%TYPE is - - v_title cr_revisions.title%TYPE; - v_content_type cr_items.content_type%TYPE; - -begin - - select content_type into v_content_type from cr_items - where item_id = get_title.item_id; - - if v_content_type = 'content_folder' then - select label into v_title from cr_folders - where folder_id = get_title.item_id; - elsif v_content_type = 'content_symlink' then - select label into v_title from cr_symlinks - where symlink_id = get_title.item_id; - elsif v_content_type = 'content_extlink' then - select label into v_title from cr_extlinks - where extlink_id = get_title.item_id; - else - if is_live ^= 'f' then - select - title into v_title - from - cr_revisions r, cr_items i - where - i.item_id = get_title.item_id - and - r.revision_id = i.live_revision; - else - select - title into v_title - from - cr_revisions r, cr_items i - where - i.item_id = get_title.item_id - and - r.revision_id = i.latest_revision; - end if; - end if; - - return v_title; - -end get_title; - -function get_publish_date ( - item_id in cr_items.item_id%TYPE, - is_live in char default 'f' -) return cr_revisions.publish_date%TYPE -is - v_revision_id cr_revisions.revision_id%TYPE; - v_publish_date cr_revisions.publish_date%TYPE; -begin - - if is_live ^= 'f' then - select - publish_date into v_publish_date - from - cr_revisions r, cr_items i - where - i.item_id = get_publish_date.item_id - and - r.revision_id = i.live_revision; - else - select - publish_date into v_publish_date - from - cr_revisions r, cr_items i - where - i.item_id = get_publish_date.item_id - and - r.revision_id = i.latest_revision; - end if; - - return v_publish_date; - -exception when no_data_found then - return null; -end get_publish_date; - -function is_subclass ( - object_type in acs_object_types.object_type%TYPE, - supertype in acs_object_types.supertype%TYPE -) return char is - - v_subclass_p char; - - cursor c_inherit_cur is - select - object_type - from - acs_object_types - connect by - prior object_type = supertype - start with - object_type = is_subclass.supertype; - -begin - - v_subclass_p := 'f'; - - for v_inherit_val in c_inherit_cur loop - if v_inherit_val.object_type = is_subclass.object_type then - v_subclass_p := 't'; - end if; - end loop; - - return v_subclass_p; - -end is_subclass; - -function relate ( - item_id in cr_items.item_id%TYPE, - object_id in acs_objects.object_id%TYPE, - relation_tag in cr_type_relations.relation_tag%TYPE default 'generic', - order_n in cr_item_rels.order_n%TYPE default null, - relation_type in acs_object_types.object_type%TYPE default 'cr_item_rel' -) return cr_item_rels.rel_id%TYPE -is - v_content_type cr_items.content_type%TYPE; - v_object_type acs_objects.object_type%TYPE; - v_is_valid integer; - v_rel_id integer; - v_exists integer; - v_order_n cr_item_rels.order_n%TYPE; -begin - - -- check the relationship is valid - v_content_type := content_item.get_content_type ( relate.item_id ); - v_object_type := content_item.get_content_type ( relate.object_id ); - - select - decode( count(1),0,0,1) into v_is_valid - from - cr_type_relations - where - content_item.is_subclass( v_object_type, target_type ) = 't' - and - content_item.is_subclass( v_content_type, content_type ) = 't'; - - if v_is_valid = 0 then - raise_application_error(-20000, - 'There is no registered relation type matching this item relation.'); - end if; - - if relate.item_id ^= relate.object_id then - -- check that these two items are not related already - --dbms_output.put_line( 'checking if the items are already related...'); - begin - select - rel_id, 1 as v_exists into v_rel_id, v_exists - from - cr_item_rels - where - item_id = relate.item_id - and - related_object_id = relate.object_id - and - relation_tag = relate.relation_tag; - exception when no_data_found then - v_exists := 0; - end; - - - -- if order_n is null, use rel_id (the order the item was related) - if relate.order_n is null then - v_order_n := v_rel_id; - else - v_order_n := relate.order_n; - end if; - - - -- if relationship does not exist, create it - if v_exists <> 1 then - --dbms_output.put_line( 'creating new relationship...'); - v_rel_id := acs_object.new( - object_type => relation_type, - context_id => item_id - ); - insert into cr_item_rels ( - rel_id, item_id, related_object_id, order_n, relation_tag - ) values ( - v_rel_id, item_id, object_id, v_order_n, relation_tag - ); - - -- if relationship already exists, update it - else - --dbms_output.put_line( 'updating existing relationship...'); - update cr_item_rels set - relation_tag = relate.relation_tag, - order_n = v_order_n - where - rel_id = v_rel_id; - end if; - - end if; - return v_rel_id; -end relate; - - -procedure unrelate ( - rel_id in cr_item_rels.rel_id%TYPE -) is -begin - - -- delete the relation object - acs_rel.del( unrelate.rel_id ); - - -- delete the row from the cr_item_rels table - delete from cr_item_rels where rel_id = unrelate.rel_id; - -end unrelate; - -function is_index_page ( - item_id in cr_items.item_id%TYPE, - folder_id in cr_folders.folder_id%TYPE -) return varchar2 -is -begin - if content_folder.get_index_page(folder_id) = item_id then - return 't'; - else - return 'f'; - end if; -end is_index_page; - - - -function get_parent_folder ( - item_id in cr_items.item_id%TYPE -) return cr_folders.folder_id%TYPE -is - v_folder_id cr_folders.folder_id%TYPE; - v_parent_folder_p char(1); -begin - v_parent_folder_p := 'f'; - v_folder_id := get_parent_folder.item_id; - - while v_parent_folder_p = 'f' and v_folder_id is not null loop - select - parent_id, content_folder.is_folder( parent_id ) - into - v_folder_id, v_parent_folder_p - from - cr_items - where - item_id = v_folder_id; - - end loop; - - return v_folder_id; - -end get_parent_folder; - -end content_item; -/ -show errors - -create or replace package body content_folder -as - -function new ( - name in cr_items.name%TYPE, - label in cr_folders.label%TYPE, - description in cr_folders.description%TYPE default null, - parent_id in cr_items.parent_id%TYPE default null, - context_id in acs_objects.context_id%TYPE default null, - folder_id in cr_folders.folder_id%TYPE default null, - creation_date in acs_objects.creation_date%TYPE default sysdate, - creation_user in acs_objects.creation_user%TYPE default null, - creation_ip in acs_objects.creation_ip%TYPE default null -) return cr_folders.folder_id%TYPE is - v_folder_id cr_folders.folder_id%TYPE; - v_context_id acs_objects.context_id%TYPE; -begin - - -- set the context_id - if content_folder.new.context_id is null then - v_context_id := content_folder.new.parent_id; - else - v_context_id := content_folder.new.context_id; - end if; - - -- parent_id = 0 means that this is a mount point - if parent_id ^= 0 and - content_folder.is_registered(parent_id,'content_folder') = 'f' then - - raise_application_error(-20000, - 'This folder does not allow subfolders to be created'); - else - - v_folder_id := content_item.new( - item_id => folder_id, - name => name, - item_subtype => 'content_folder', - content_type => 'content_folder', - context_id => v_context_id, - creation_date => creation_date, - creation_user => creation_user, - creation_ip => creation_ip, - parent_id => parent_id - ); - - insert into cr_folders ( - folder_id, label, description - ) values ( - v_folder_id, label, description - ); - - -- inherit the attributes of the parent folder - if content_folder.new.parent_id is not null then - - insert into cr_folder_type_map ( - folder_id, content_type - ) select - v_folder_id, content_type - from - cr_folder_type_map - where - folder_id = content_folder.new.parent_id; - end if; - - -- update the child flag on the parent - update cr_folders set has_child_folders = 't' - where folder_id = content_folder.new.parent_id; - - return v_folder_id; - end if; - -end new; - -procedure del ( - folder_id in cr_folders.folder_id%TYPE, - cascade_p in char default 'f' -) is - - v_count integer; - v_parent_id cr_items.parent_id%TYPE; - v_child_item_id cr_items.item_id%TYPE; - - cursor c_folder_children_cur is - select - item_id - from - cr_items - connect by - prior item_id=parent_id - start with parent_id = del.folder_id; - -begin - - -- check if the folder contains any items - - select count(*) into v_count from cr_items where parent_id = folder_id; - - if v_count > 0 and content_folder.del.cascade_p='f' then - raise_application_error(-20000, - 'Folder ID ' || folder_id || ' (' || content_item.get_path(folder_id) || - ') cannot be deleted because it is not empty.'); - else - open c_folder_children_cur; - - loop - - fetch c_folder_children_cur into v_child_item_id; - exit when c_folder_children_cur%NOTFOUND; - if is_folder(v_child_item_id) = 't' then - content_folder.del(v_child_item_id,'t'); - else - - content_item.del(v_child_item_id); - end if; - end loop; - close c_folder_children_cur; - end if; - - content_folder.unregister_content_type( - folder_id => content_folder.del.folder_id, - content_type => 'content_revision', - include_subtypes => 't' ); - - delete from cr_folder_type_map - where folder_id = content_folder.del.folder_id; - - select parent_id into v_parent_id from cr_items - where item_id = content_folder.del.folder_id; - - content_item.del(folder_id); - - -- check if any folders are left in the parent - update cr_folders set has_child_folders = 'f' - where folder_id = v_parent_id and not exists ( - select 1 from cr_items - where parent_id = v_parent_id and content_type = 'content_folder'); - -end del; - --- renames a folder, making sure the new name is not already in use -procedure edit_name ( - folder_id in cr_folders.folder_id%TYPE, - name in cr_items.name%TYPE default null, - label in cr_folders.label%TYPE default null, - description in cr_folders.description%TYPE default null -) is - v_name_already_exists_p integer := 0; -begin - - if name is not null then - content_item.edit_name(folder_id, name); - end if; - - if label is not null and description is not null then - - update cr_folders - set cr_folders.label = content_folder.edit_name.label, - cr_folders.description = content_folder.edit_name.description - where cr_folders.folder_id = content_folder.edit_name.folder_id; - - elsif label is not null and description is null then - - update cr_folders - set cr_folders.label = content_folder.edit_name.label - where cr_folders.folder_id = content_folder.edit_name.folder_id; - - end if; - -end edit_name; - - --- 1) make sure we are not moving the folder to an invalid location: --- a. destination folder exists --- b. folder is not the webroot (folder_id = -1) --- c. destination folder is not the same as the folder --- d. destination folder is not a subfolder --- 2) make sure subfolders are allowed in the target_folder --- 3) update the parent_id for the folder - -procedure move ( - folder_id in cr_folders.folder_id%TYPE, - target_folder_id in cr_folders.folder_id%TYPE, - name in cr_items.name%TYPE default null -) is - v_source_folder_id integer; - v_valid_folders_p integer := 0; -begin - - select - count(*) - into - v_valid_folders_p - from - cr_folders - where - folder_id = move.target_folder_id - or - folder_id = move.folder_id; - - if v_valid_folders_p ^= 2 then - raise_application_error(-20000, - 'content_folder.move - Not valid folder(s)'); - end if; - - if folder_id = content_item.get_root_folder or - folder_id = content_template.get_root_folder then - raise_application_error( -20000, - 'content_folder.move - Cannot move root folder'); - end if; - - if target_folder_id = folder_id then - raise_application_error(-20000, - 'content_folder.move - Cannot move a folder to itself'); - end if; - - if is_sub_folder(folder_id, target_folder_id) = 't' then - raise_application_error(-20000, - 'content_folder.move - Destination folder is subfolder'); - end if; - - if is_registered(target_folder_id,'content_folder') ^= 't' then - raise_application_error(-20000, - 'content_folder.move - Destination folder does not allow subfolders'); - end if; - - select parent_id into v_source_folder_id from cr_items - where item_id = move.folder_id; - - -- update the parent_id for the folder - update cr_items - set parent_id = move.target_folder_id, - name=nvl(move.name, cr_items.name) - where item_id = move.folder_id; - - -- update the has_child_folders flags - - -- update the source - update cr_folders set has_child_folders = 'f' - where folder_id = v_source_folder_id and not exists ( - select 1 from cr_items - where parent_id = v_source_folder_id - and content_type = 'content_folder'); - - -- update the destination - update cr_folders set has_child_folders = 't' - where folder_id = target_folder_id; - -end move; - --- * make sure that subfolders are allowed in this folder --- * creates new folder in the target folder with the same attributes --- as the old one --- * copies all contents of folder to the new one -procedure copy ( - folder_id in cr_folders.folder_id%TYPE, - target_folder_id in cr_folders.folder_id%TYPE, - creation_user in acs_objects.creation_user%TYPE, - creation_ip in acs_objects.creation_ip%TYPE default null, - name in cr_items.name%TYPE default null -) is - v_valid_folders_p integer := 0; - v_current_folder_id cr_folders.folder_id%TYPE; - v_name cr_items.name%TYPE; - v_label cr_folders.label%TYPE; - v_description cr_folders.description%TYPE; - v_new_folder_id cr_folders.folder_id%TYPE; - - -- cursor: items in the folder - cursor c_folder_contents_cur is - select - item_id - from - cr_items - where - parent_id = copy.folder_id; - -begin - - select - count(*) - into - v_valid_folders_p - from - cr_folders - where - folder_id = copy.target_folder_id - or - folder_id = copy.folder_id; - - select - parent_id - into - v_current_folder_id - from - cr_items - where - item_id = copy.folder_id; - - if folder_id = content_item.get_root_folder or folder_id = content_template.get_root_folder or target_folder_id = folder_id then - v_valid_folders_p := 0; - end if; - - if v_valid_folders_p = 2 then - - -- get the source folder info - select - name, label, description - into - v_name, v_label, v_description - from - cr_items i, cr_folders f - where - f.folder_id = i.item_id - and - f.folder_id = copy.folder_id; - - if is_sub_folder(folder_id, target_folder_id) ^= 't' or v_current_folder_id != copy.target_folder_id or (v_name != copy.name and copy.name is not null) then - if copy.name is not null then - v_name := copy.name; - end if; - -- create the new folder - v_new_folder_id := content_folder.new( - parent_id => copy.target_folder_id, - name => nvl(copy.name,v_name), - label => v_label, - description => v_description, - creation_user => copy.creation_user, - creation_ip => copy.creation_ip - ); - - -- copy attributes of original folder - insert into cr_folder_type_map ( - folder_id, content_type - ) select - v_new_folder_id, content_type - from - cr_folder_type_map map - where - folder_id = copy.folder_id - and - -- do not register content_type if it is already registered - not exists ( select 1 from cr_folder_type_map - where folder_id = v_new_folder_id - and content_type = map.content_type ) ; - - -- for each item in the folder, copy it - for v_folder_contents_val in c_folder_contents_cur loop - - content_item.copy( - item_id => v_folder_contents_val.item_id, - target_folder_id => v_new_folder_id, - creation_user => copy.creation_user, - creation_ip => copy.creation_ip - ); - - end loop; - - end if; - end if; -end copy; - - - - - --- returns 1 if the item_id passed in is a folder -function is_folder ( - item_id in cr_items.item_id%TYPE -) return char is - - v_folder_p varchar2(1) := 'f'; - -begin - - select 't' into v_folder_p from cr_folders - where folder_id = item_id; - - return v_folder_p; - -exception - when NO_DATA_FOUND then - return 'f'; - -end is_folder; - --- target_folder_id is the possible sub folder -function is_sub_folder ( - folder_id in cr_folders.folder_id%TYPE, - target_folder_id in cr_folders.folder_id%TYPE -) return char -is - cursor c_tree_cur is - select - parent_id - from - cr_items - connect by - prior parent_id = item_id - start with - item_id = target_folder_id; - - v_parent_id integer := 0; - v_sub_folder_p char := 'f'; - -begin - - if folder_id = content_item.get_root_folder or - folder_id = content_template.get_root_folder then - v_sub_folder_p := 't'; - end if; - - -- Get the parents - open c_tree_cur; - while v_parent_id <> folder_id loop - fetch c_tree_cur into v_parent_id; - exit when c_tree_cur%NOTFOUND; - end loop; - close c_tree_cur; - - if v_parent_id ^= 0 then - v_sub_folder_p := 't'; - end if; - - return v_sub_folder_p; - -end is_sub_folder; - -function is_empty ( - folder_id in cr_folders.folder_id%TYPE -) return varchar2 -is - v_return varchar2(1); -begin - - select - decode( count(*), 0, 't', 'f' ) into v_return - from - cr_items - where - parent_id = is_empty.folder_id; - - return v_return; -end is_empty; - - -procedure register_content_type ( - folder_id in cr_folders.folder_id%TYPE, - content_type in cr_folder_type_map.content_type%TYPE, - include_subtypes in varchar2 default 'f' -) is - - v_is_registered varchar2(100); - -begin - - if register_content_type.include_subtypes = 'f' then - - v_is_registered := is_registered( - folder_id => register_content_type.folder_id, - content_type => register_content_type.content_type, - include_subtypes => 'f' ); - - if v_is_registered = 'f' then - - insert into cr_folder_type_map ( - folder_id, content_type - ) values ( - register_content_type.folder_id, - register_content_type.content_type - ); - - end if; - - else - - insert into cr_folder_type_map ( - folder_id, content_type - ) select - register_content_type.folder_id, object_type - from - acs_object_types - where - object_type ^= 'acs_object' - and - not exists (select 1 from cr_folder_type_map - where folder_id = register_content_type.folder_id - and content_type = acs_object_types.object_type) - connect by - prior object_type = supertype - start with - object_type = register_content_type.content_type; - - end if; - -end register_content_type; - -procedure unregister_content_type ( - folder_id in cr_folders.folder_id%TYPE, - content_type in cr_folder_type_map.content_type%TYPE, - include_subtypes in varchar2 default 'f' -) is -begin - - if unregister_content_type.include_subtypes = 'f' then - delete from cr_folder_type_map - where folder_id = unregister_content_type.folder_id - and content_type = unregister_content_type.content_type; - else - delete from cr_folder_type_map - where folder_id = unregister_content_type.folder_id - and content_type in (select object_type - from acs_object_types - where object_type ^= 'acs_object' - connect by prior object_type = supertype - start with - object_type = unregister_content_type.content_type); - - end if; - -end unregister_content_type; - - - - -function is_registered ( - folder_id in cr_folders.folder_id%TYPE, - content_type in cr_folder_type_map.content_type%TYPE, - include_subtypes in varchar2 default 'f' -) return varchar2 -is - v_is_registered integer; - cursor c_subtype_cur is - select - object_type - from - acs_object_types - where - object_type ^= 'acs_object' - connect by - prior object_type = supertype - start with - object_type = is_registered.content_type; - -begin - - if is_registered.include_subtypes = 'f' then - select - count(1) - into - v_is_registered - from - cr_folder_type_map - where - folder_id = is_registered.folder_id - and - content_type = is_registered.content_type; - - else - - v_is_registered := 1; - for v_subtype_val in c_subtype_cur loop - if is_registered(is_registered.folder_id, - v_subtype_val.object_type, 'f') = 'f' then - v_is_registered := 0; - end if; - end loop; - end if; - - if v_is_registered = 0 then - return 'f'; - else - return 't'; - end if; - -end is_registered; - -function get_label ( - folder_id in cr_folders.folder_id%TYPE -) return cr_folders.label%TYPE -is - v_label cr_folders.label%TYPE; -begin - - select - label into v_label - from - cr_folders - where - folder_id = get_label.folder_id; - - return v_label; -end get_label; - - -function get_index_page ( - folder_id in cr_folders.folder_id%TYPE -) return cr_items.item_id%TYPE -is - v_folder_id cr_folders.folder_id%TYPE; - v_index_page_id cr_items.item_id%TYPE; -begin - - -- if the folder is a symlink, resolve it - if content_symlink.is_symlink( get_index_page.folder_id ) = 't' then - v_folder_id := content_symlink.resolve( get_index_page.folder_id ); - else - v_folder_id := get_index_page.folder_id; - end if; - - select - item_id into v_index_page_id - from - cr_items - where - parent_id = v_folder_id - and - name = 'index' - and - content_item.is_subclass( - content_item.get_content_type( content_symlink.resolve(item_id) ), - 'content_folder') = 'f' - and - content_item.is_subclass( - content_item.get_content_type( content_symlink.resolve(item_id) ), - 'content_template') = 'f'; - - return v_index_page_id; - -exception when no_data_found then - return null; -end get_index_page; - -function is_root ( - folder_id in cr_folders.folder_id%TYPE -) return char is - v_is_root char(1); -begin - - select decode(parent_id, 0, 't', 'f') into v_is_root - from cr_items where item_id = is_root.folder_id; - - return v_is_root; -end is_root; - -end content_folder; -/ -show errors - Index: openacs-4/packages/acs-content-repository/sql/oracle/upgrade/upgrade-5.1.1d2-5.1.1d3.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/sql/oracle/upgrade/upgrade-5.1.1d2-5.1.1d3.sql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-content-repository/sql/oracle/upgrade/upgrade-5.1.1d2-5.1.1d3.sql 12 Jul 2004 14:49:35 -0000 1.2 @@ -0,0 +1,3084 @@ + +create or replace package content_item +as + +--/** +--Content items store the overview of the content published on a +--website. The actual content is stored in content revisions. It is +--implemented this way so that there can be mulitple versions of the +--actual content while the main idea remains constant. For example: If +--there is a review for the movie "Terminator," there will exist a +--content item by the name "terminator" with all the right parameters +--(supertype, parent, etc), there will also exist at least one content +--revision pointing to this item with the actual review content. +--@see {content_revision}, {content_folder} +--*/ + +c_root_folder_id constant integer := -100; + +function get_root_folder ( + item_id in cr_items.item_id%TYPE default null +) return cr_folders.folder_id%TYPE; + +function new ( + --/** Creates a new content item. If the data, title or text + -- parameters are specified, also creates a revision for the item. + -- @author Karl Goldstein + -- @param name The name for the item, must be URL-encoded. + -- If an item with this name already exists under the specified + -- parent item, an error is thrown + -- @param parent_id The parent of this item, defaults to null + -- @param item_id The id of the new item. A new id will be allocated if this + -- parameter is null + -- @param locale The locale for this item, for use with Intermedia search + -- @param item_subtype The type of the new item, defaults to 'content_item' + -- This parameter is used to support inheritance, so that + -- subclasses of content_item can call this function + -- to initialize the parent class + -- @param content_type The content type for the item, defaults to + -- 'content_revision'. Only objects of this type + -- may be used as revisions for the item + -- @param title The user-readable title for the item, defaults to the item's + -- name + -- @param description A short description for the item (4000 characters maximum) + -- @param mime_type The file type of the item, defaults to 'text/plain' + -- @param nls_language The language for the item, used for Intermedia search + -- @param text The text content of the new revision, 4000 charcters maximum. + -- Cannot be specified simultaneously with the data + -- parameter + -- @param data The blob content of the new revision. Cannot be specified + -- simultaneously with the text parameter + -- @param relation_tag If a parent-child relationship is registered + -- for these content types, use this tag to + -- describe the parent-child relationship. Defaults + -- to 'parent content type'-'child content type' + -- @param is_live If 't', the new revision will become live + -- @param context_id Security context id, as in acs_object.new + -- If null, defaults to parent_id, and copies permissions + -- from the parent into the current item + -- @param storage_type in ('lob','file'). Indicates how content is to be stored. + -- 'file' content is stored externally in the file system. + -- @param others As in acs_object.new + -- @return The id of the newly created item + -- @see {acs_object.new} + --*/ + name in cr_items.name%TYPE, + parent_id in cr_items.parent_id%TYPE default null, + item_id in acs_objects.object_id%TYPE default null, + locale in cr_items.locale%TYPE default null, + creation_date in acs_objects.creation_date%TYPE + default sysdate, + creation_user in acs_objects.creation_user%TYPE + default null, + context_id in acs_objects.context_id%TYPE default null, + creation_ip in acs_objects.creation_ip%TYPE default null, + item_subtype in acs_object_types.object_type%TYPE + default 'content_item', + content_type in acs_object_types.object_type%TYPE + default 'content_revision', + title in cr_revisions.title%TYPE default null, + description in cr_revisions.description%TYPE default null, + mime_type in cr_revisions.mime_type%TYPE default 'text/plain', + nls_language in cr_revisions.nls_language%TYPE default null, + text in varchar2 default null, + data in cr_revisions.content%TYPE default null, + relation_tag in cr_child_rels.relation_tag%TYPE default null, + is_live in char default 'f', + storage_type in cr_items.storage_type%TYPE default 'lob' +) return cr_items.item_id%TYPE; + + +function is_published ( + --/** Determins whether an item is published or not. + -- @author Michael Pih + -- @param item_id The item ID + -- @return 't' if the item is published, 'f' otherwise + --*/ + item_id in cr_items.item_id%TYPE +) return char; + + +function is_publishable ( + --/** Determines if an item is publishable. Publishable items must + -- meet the following criteria: + -- 1) for each child type, the item has n children, min_n < n < max_n + -- 2) for each relation type, the item has n relations, min_n < n < max_n + -- 3) any 'publishing_wf' workflows are finished + -- @author Michael Pih + -- @param item_id The item ID + -- @return 't' if the item is publishable in it's present state, + -- Otherwise, returns 'f' + --*/ + item_id in cr_items.item_id%TYPE +) return char; + + + +function is_valid_child ( + --/** Determines if an item would be a valid child of another item by + -- checking if the parent allows children of the would-be child's + -- content type and if the parent already has n_max children of + -- that content type. + -- @author Michael Pih + -- @param item_id The item ID of the potential parent + -- @param content_type The content type of the potential child item + -- @return 't' if the item would be a valid child, 'f' otherwise + --*/ + + item_id in cr_items.item_id%TYPE, + content_type in acs_object_types.object_type%TYPE, + relation_tag in cr_child_rels.relation_tag%TYPE default null +) return char; + +procedure del ( + --/** Deletes the specified content item, along with any revisions, symlinks, + -- workflows, associated templates, associated keywords, + -- child and item relationships for the item. Use with caution - this + -- operation cannot be undone. + -- @author Karl Goldstein + -- @param item_id The id of the item to delete + -- @see {acs_object.delete} + --*/ + item_id in cr_items.item_id%TYPE +); + +procedure edit_name ( + --/** Renames the item. If an item with the specified name already exists + -- under this item's parent, an error is thrown + -- @author Karl Goldstein + -- @param item_id The id of the item to rename + -- @param name The new name for the item, must be URL-encoded + -- @see {content_item.new} + --*/ + item_id in cr_items.item_id%TYPE, + name in cr_items.name%TYPE +); + +function get_id ( + --/** Takes in a path, such as "/tv/programs/star_trek/episode_203" + -- and returns the id of the item with this path. Note: URLs are abstract (no + -- extensions are allowed in content item names and extensions are stripped when + -- looking up content items) + -- @author Karl Goldstein + -- @param item_path The path to be resolved + -- @param root_folder_id Starts path resolution from this folder. Defaults to + -- the root of the sitemap + -- @param resolve_index Boolean flag indicating whether to return the + -- id of the index page for folders (if one + -- exists). Defaults to 'f'. + -- @return The id of the item with the given path, or null if no such item exists + -- @see {content_item.get_path} + --*/ + item_path in varchar2, + root_folder_id in cr_items.item_id%TYPE default c_root_folder_id, + resolve_index in char default 'f' +) return cr_items.item_id%TYPE; + +function get_path ( + --/** Retrieves the full path to an item, in the form of + -- "/tv/programs/star_trek/episode_203" + -- @author Karl Goldstein + -- @param item_id The item for which the path is to be retrieved + -- @param root_folder_id Starts path resolution from this folder. + -- Defaults to the root of the sitemap + -- @return The path to the item + -- @see {content_item.get_id}, {content_item.write_to_file} + --*/ + item_id in cr_items.item_id%TYPE, + root_folder_id in cr_items.item_id%TYPE default null +) return varchar2; + +function get_virtual_path ( + --/** Retrieves the virtual path to an item, in the form of + -- "/tv/programs/star_trek/episode_203" + -- @author Michael Pih + -- @param item_id The item for which the path is to be retrieved + -- @param root_folder_id Starts path resolution from this folder. + -- Defaults to the root of the sitemap + -- @return The virtual path to the item + -- @see {content_item.get_id}, {content_item.write_to_file}, {content_item.get_path} + --*/ + item_id in cr_items.item_id%TYPE, + root_folder_id in cr_items.item_id%TYPE default c_root_folder_id +) return varchar2; + +procedure write_to_file ( + --/** Writes the content of the live revision of this item to a file, + -- creating all the neccessary directories in the process + -- @author Karl Goldstein + -- @param item_id The item to be written to a file + -- @param root_path The path in the filesystem to which the root of the + -- sitemap corresponds + -- @see {content_item.get_path} + --*/ + item_id in cr_items.item_id%TYPE, + root_path in varchar2 +); + +procedure register_template ( + --/** Registers a template which will be used to render this item. + -- @author Karl Goldstein + -- @param item_id The item for which the template will be registered + -- @param template_id The template to be registered + -- @param use_context The context in which the template is appropriate, such + -- as 'admin' or 'public' + -- @see {content_type.register_template}, {content_item.unregister_template}, + -- {content_item.get_template} + --*/ + item_id in cr_items.item_id%TYPE, + template_id in cr_templates.template_id%TYPE, + use_context in cr_item_template_map.use_context%TYPE +); + +procedure unregister_template ( + --/** Unregisters a template which will be used to render this item. + -- @author Karl Goldstein + -- @param item_id The item for which the template will be unregistered + -- @param template_id The template to be registered + -- @param use_context The context in which the template is appropriate, such + -- as 'admin' or 'public' + -- @see {content_type.register_template}, {content_item.register_template}, + -- {content_item.get_template} + --*/ + item_id in cr_items.item_id%TYPE, + template_id in cr_templates.template_id%TYPE default null, + use_context in cr_item_template_map.use_context%TYPE default null +); + +function get_template ( + --/** Retrieves the template which should be used to render this item. If no template + -- is registered to specifically render the item in the given context, the + -- default template for the item's type is returned. + -- @author Karl Goldstein + -- @param item_id The item for which the template will be unregistered + -- @param use_context The context in the item is to be rendered, such + -- as 'admin' or 'public' + -- @return The id of the registered template, or null if no template could be + -- found + -- @see {content_type.register_template}, {content_item.register_template}, + --*/ + item_id in cr_items.item_id%TYPE, + use_context in cr_item_template_map.use_context%TYPE +) return cr_templates.template_id%TYPE; + +function get_live_revision ( + --/** Retrieves the id of the live revision for the item + -- @param item_id The item for which the live revision is to be retrieved + -- @return The id of the live revision for this item, or null if no live revision + -- exists + -- @see {content_item.set_live_revision}, {content_item.get_latest_revision} + --*/ + item_id in cr_items.item_id%TYPE +) return cr_revisions.revision_id%TYPE; + +procedure set_live_revision ( + --/** Make the specified revision the live revision for the item + -- @author Karl Goldstein + -- @param revision_id The id of the revision which is to become live + -- for its corresponding item + -- @see {content_item.get_live_revision} + --*/ + revision_id in cr_revisions.revision_id%TYPE, + publish_status in cr_items.publish_status%TYPE default 'ready' +); + + +procedure unset_live_revision ( + --/** Set the live revision to null for the item + -- @author Michael Pih + -- @param item_id The id of the item for which to unset the live revision + -- @see {content_item.set_live_revision} + item_id in cr_items.item_id%TYPE +); + +procedure set_release_period ( + --/** Sets the release period for the item. This information may be + -- used by applications to update the publishing status of items + -- at periodic intervals. + -- @author Karl Goldstein + -- @param item_id The id the item. + -- @param start_when The time and date when the item should be released. + -- @param end_when The time and date when the item should be expired. + --*/ + item_id in cr_items.item_id%TYPE, + start_when date default null, + end_when date default null +); + + +function get_revision_count ( + --/** Return the total count of revisions for this item + -- @author Karl Goldstein + -- @param item_id The id the item + -- @return The number of revisions for this item + -- @see {content_revision.new} + --*/ + item_id in cr_items.item_id%TYPE +) return number; + +-- Return the object type of this item +function get_content_type ( + --/** Retrieve the content type of this item. Only objects of this type may be + -- used as revisions for the item. + -- @author Karl Goldstein + -- @param item_id The item for which the content type is to be retrieved + -- @return The content type of the item + --*/ + item_id in cr_items.item_id%TYPE +) return cr_items.content_type%TYPE; + +function get_context ( + --/** Retrieve the parent of the given item + -- @author Karl Goldstein + -- @param item_id The item for which the parent is to be retrieved + -- @return The id of the parent for this item + --*/ + item_id in cr_items.item_id%TYPE +) return acs_objects.context_id%TYPE; + +procedure move ( + --/** Move the specified item to a different folder. If the target folder does + -- not exist, or if the folder already contains an item with the same name + -- as the given item, an error will be thrown. + -- @author Karl Goldstein + -- @param item_id The item to be moved + -- @param target_folder_id The new folder for the item + -- @see {content_item.new}, {content_folder.new}, {content_item.copy} + --*/ + item_id in cr_items.item_id%TYPE, + target_folder_id in cr_folders.folder_id%TYPE, + name in cr_items.name%TYPE default null +); + +procedure copy ( + --/** Copies the item to a new location, creating an identical item with + -- an identical latest revision (if any). If the target folder does + -- not exist, or if the folder already contains an item with the same name + -- as the given item, an error will be thrown. + -- @author Karl Goldstein, Michael Pih + -- @param item_id The item to be copied + -- @param target_folder_id The folder where the item is to be copied + -- @param creation_user The user_id of the creator + -- @param creation_ip The IP address of the creator + -- @see {content_item.new}, {content_folder.new}, {content_item.move} + --*/ + item_id in cr_items.item_id%TYPE, + target_folder_id in cr_folders.folder_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE default null, + name in cr_items.name%TYPE default null +); + +function copy2 ( + --/** Copies the item to a new location, creating an identical item with + -- an identical latest revision (if any). If the target folder does + -- not exist, or if the folder already contains an item with the same name + -- as the given item, an error will be thrown. + -- @author Karl Goldstein, Michael Pih + -- @param item_id The item to be copied + -- @param target_folder_id The folder where the item is to be copied + -- @param creation_user The user_id of the creator + -- @param creation_ip The IP address of the creator + -- @return The item ID of the new copy. + -- @see {content_item.new}, {content_folder.new}, {content_item.move} + --*/ + item_id in cr_items.item_id%TYPE, + target_folder_id in cr_folders.folder_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE default null, + name in cr_items.name%TYPE default null +) return cr_items.item_id%TYPE; + +-- get the latest revision for an item +function get_latest_revision ( + --/** Retrieves the id of the latest revision for the item (as opposed to the live + -- revision) + -- @author Karl Goldstein + -- @param item_id The item for which the latest revision is to be retrieved + -- @return The id of the latest revision for this item, or null if no revisions + -- exist + -- @see {content_item.get_live_revision} + --*/ + item_id in cr_items.item_id%TYPE +) return cr_revisions.revision_id%TYPE; + + +function get_best_revision ( + --/** Retrieves the id of the live revision for the item if one exists, + -- otherwise retrieves the id of the latest revision if one exists. + -- revision) + -- @author Michael Pih + -- @param item_id The item for which the revision is to be retrieved + -- @return The id of the live or latest revision for this item, + -- or null if no revisions exist + -- @see {content_item.get_live_revision}, {content_item.get_latest_revision} + --*/ + item_id in cr_items.item_id%TYPE +) return cr_revisions.revision_id%TYPE; + +function get_title ( + --/** Retrieves the title for the item, using either the latest or the live revision. + -- If the specified item is in fact a folder, return the folder's label. + -- In addition, this function will automatically resolve symlinks. + -- @author Karl Goldstein + -- @param item_id The item for which the title is to be retrieved + -- @param is_live If 't', use the live revision to get the title. Otherwise, + -- use the latest revision. The default is 'f' + -- @return The title of the item + -- @see {content_item.get_live_revision}, {content_item.get_latest_revision}, + -- {content_symlink.resolve} + --*/ + item_id in cr_items.item_id%TYPE, + is_live in char default 'f' +) return cr_revisions.title%TYPE; + +function get_publish_date ( + --/** Retrieves the publish date for the item + -- @author Karl Goldstein + -- @param item_id The item for which the publish date is to be retrieved + -- @param is_live If 't', use the live revision for the item. Otherwise, use + -- the latest revision. The default is 'f' + -- @return The publish date for the item, or null if the item has no revisions + -- @see {content_item.get_live_revision}, {content_item.get_latest_revision}, + --*/ + item_id in cr_items.item_id%TYPE, + is_live in char default 'f' +) return cr_revisions.publish_date%TYPE; + +function is_subclass ( + --/** Determines if one type is a subclass of another. A class is always a subclass of + -- itself. + -- @author Karl Goldstein + -- @param object_type The child class + -- @param supertype The superclass + -- @return 't' if the child class is a subclass of the superclass, 'f' otherwise + -- @see {acs_object_type.create_type} + --*/ + object_type in acs_object_types.object_type%TYPE, + supertype in acs_object_types.supertype%TYPE +) return char; + +function relate ( + --/** Relates two content items + -- @author Karl Goldstein + -- @param item_id The item id + -- @param object_id The item id of the related object + -- @param relation_tag A tag to help identify the relation type, + -- defaults to 'generic' + -- @param order_n The order of this object among other objects + -- of the same relation type, defaults to null. + -- @param relation_type The object type of the relation, defaults to + -- 'cr_item_rel' + --*/ + item_id in cr_items.item_id%TYPE, + object_id in acs_objects.object_id%TYPE, + relation_tag in cr_type_relations.relation_tag%TYPE default 'generic', + order_n in cr_item_rels.order_n%TYPE default null, + relation_type in acs_object_types.object_type%TYPE default 'cr_item_rel' +) return cr_item_rels.rel_id%TYPE; + + +procedure unrelate ( + --/** Delete the item relationship between two items + -- @author Michael Pih + -- @param rel_id The relationship id + -- @see {content_item.relate} + --*/ + rel_id in cr_item_rels.rel_id%TYPE +); + +function is_index_page ( + --/** Determine if the item is an index page for the specified folder. + -- The item is an index page for the folder if it exists in the + -- folder and its item name is "index". + -- @author Karl Goldstein + -- @param item_id The item id + -- @param folder_id The folder id + -- @return 't' if the item is an index page for the specified + -- folder, 'f' otherwise + -- @see {content_folder.get_index_page} + --*/ + item_id in cr_items.item_id%TYPE, + folder_id in cr_folders.folder_id%TYPE +) return varchar2; + + +function get_parent_folder ( + --/** Get the parent folder. + -- @author Michael Pih + -- @param item_id The item id + -- @return the folder_id of the parent folder, null otherwise + --*/ + item_id in cr_items.item_id%TYPE +) return cr_folders.folder_id%TYPE; + +end content_item; +/ +show errors + +create or replace package content_folder +as + +function new ( + --/** Create a new folder + -- @author Karl Goldstein + -- @param label The label for the folder + -- @param description A short description of the folder, 4000 characters maximum + -- @param parent_id The parent of the folder + -- @param folder_id The id of the new folder. A new id will be allocated by default + -- @param context_id The context id. The parent id will be used as the default context + -- @param creation_date As in acs_object.new + -- @param creation_ip As in acs_object.new + -- @param creation_user As in acs_object.new + -- @return The id of the newly created folder + -- @see {acs_object.new}, {content_item.new} + --*/ + name in cr_items.name%TYPE, + label in cr_folders.label%TYPE, + description in cr_folders.description%TYPE default null, + parent_id in cr_items.parent_id%TYPE default null, + context_id in acs_objects.context_id%TYPE default null, + folder_id in cr_folders.folder_id%TYPE default null, + creation_date in acs_objects.creation_date%TYPE default sysdate, + creation_user in acs_objects.creation_user%TYPE default null, + creation_ip in acs_objects.creation_ip%TYPE default null +) return cr_folders.folder_id%TYPE; + +procedure del ( + --/** Delete a folder. An error is thrown if the folder is not empty + -- @author Karl Goldstein + -- @param folder_id The id of the folder to delete + -- @see {acs_object.delete}, {content_item.delete} + --*/ + folder_id in cr_folders.folder_id%TYPE, + cascade_p in char default 'f' +); + +procedure edit_name ( + --/** Change the name, label and/or description of the folder + -- @author Karl Goldstein + -- @param folder_id The id of the folder to modify + -- @param name The new name for the folder. An error will be thrown if + -- an item with this name already exists under this folder's + -- parent. If this parameter is null, the old name will be preserved + -- @param label The new label for the folder. The old label will be preserved if + -- this parameter is null + -- @param label The new description for the folder. The old description + -- will be preserved if this parameter is null + -- @see {content_folder.new} + --*/ + folder_id in cr_folders.folder_id%TYPE, + name in cr_items.name%TYPE default null, + label in cr_folders.label%TYPE default null, + description in cr_folders.description%TYPE default null +); + +procedure move ( + --/** Recursively move the folder and all items in into a new location. + -- An error is thrown if either of the parameters is not a folder. + -- The root folder of the sitemap and the root folder of the + -- templates cannot be moved. + -- @author Karl Goldstein + -- @param folder_id The id of the folder to move + -- @param target_folder_id The destination folder + -- @see {content_folder.new}, {content_folder.copy} + --*/ + folder_id in cr_folders.folder_id%TYPE, + target_folder_id in cr_folders.folder_id%TYPE, + name in cr_items.name%TYPE default null +); + +procedure copy ( + --/** Recursively copy the folder and all items in into a new location. + -- An error is thrown if either of the parameters is not a folder. + -- The root folder of the sitemap and the root folder of the + -- templates cannot be copied + -- @author Karl Goldstein + -- @param folder_id The id of the folder to copy + -- @param target_folder_id The destination folder + -- @param creation_user The id of the creation user + -- @param creation_ip The IP address of the creation user (defaults to null) + -- @see {content_folder.new}, {content_folder.copy} + --*/ + folder_id in cr_folders.folder_id%TYPE, + target_folder_id in cr_folders.folder_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE default null, + name in cr_items.name%TYPE default null +); + +function is_folder ( + --/** Determine if the item is a folder + -- @author Karl Goldstein + -- @param item_id The item id + -- @return 't' if the item is a folder, 'f' otherwise + -- @see {content_folder.new}, {content_folder.is_sub_folder} + --*/ + item_id in cr_items.item_id%TYPE +) return char; + +function is_sub_folder ( + --/** Determine if the item target_folder_id is a subfolder of + -- the item folder_id + -- @author Karl Goldstein + -- @param folder_id The superfolder id + -- @param target_folder_id The subfolder id + -- @return 't' if the item target_folder_id is a subfolder of + -- the item folder_id, 'f' otherwise + -- @see {content_folder.is_folder} + --*/ + folder_id in cr_folders.folder_id%TYPE, + target_folder_id in cr_folders.folder_id%TYPE +) return char; + +function is_empty ( + --/** Determine if the folder is empty + -- @author Karl Goldstein + -- @param folder_id The folder id + -- @return 't' if the folder contains no subfolders or items, 'f' otherwise + -- @see {content_folder.is_folder} + --*/ + folder_id in cr_folders.folder_id%TYPE +) return varchar2; + +function is_root ( + --/** Determine whether the folder is a root (has a parent_id of 0) + -- @author Karl Goldstein + -- @param folder_id The folder ID + -- @return 't' if the folder is a root or 'f' otherwise + --*/ + folder_id in cr_folders.folder_id%TYPE +) return char; + +procedure register_content_type ( + --/** Register a content type to the folder, if it is not already registered. + -- Only items of the registered type(s) may be added to the folder. + -- @author Karl Goldstein + -- @param folder_id The folder id + -- @param content_type The content type to be registered + -- @see {content_folder.unregister_content_type}, + -- {content_folder.is_registered} + --*/ + folder_id in cr_folders.folder_id%TYPE, + content_type in cr_folder_type_map.content_type%TYPE, + include_subtypes in varchar2 default 'f' +); + +procedure unregister_content_type ( + --/** Unregister a content type from the folder, if it has been registered. + -- Only items of the registered type(s) may be added to the folder. + -- If the folder already contains items of the type to be unregistered, the + -- items remain in the folder. + -- @author Karl Goldstein + -- @param folder_id The folder id + -- @param content_type The content type to be unregistered + -- @param include_subtypes If 't', all subtypes of content_type will be + -- unregistered as well + -- @see {content_folder.register_content_type}, {content_folder.is_registered} + --*/ + folder_id in cr_folders.folder_id%TYPE, + content_type in cr_folder_type_map.content_type%TYPE, + include_subtypes in varchar2 default 'f' +); + +-- change this to is_type_registered +function is_registered ( + --/** Determines if a content type is registered to the folder + -- Only items of the registered type(s) may be added to the folder. + -- @author Karl Goldstein + -- @param folder_id The folder id + -- @param content_type The content type to be checked + -- @param include_subtypes If 't', all subtypes of the content_type + -- will be checked, returning 't' if all of them are registered. If 'f', + -- only an exact match with content_type will be + -- performed. + -- @return 't' if the type is registered to this folder, 'f' otherwise + -- @see {content_folder.register_content_type}, {content_folder.unregister_content_type}, + --*/ + folder_id in cr_folders.folder_id%TYPE, + content_type in cr_folder_type_map.content_type%TYPE, + include_subtypes in varchar2 default 'f' +) return varchar2; + + +function get_label ( + --/** Returns the label for the folder. This function is the default name method + -- for the folder object. + -- @author Karl Goldstein + -- @param folder_id The folder id + -- @return The folder's label + -- @see {acs_object_type.create_type}, the docs for the name_method parameter + --*/ + folder_id in cr_folders.folder_id%TYPE +) return cr_folders.label%TYPE; + + +function get_index_page ( + --/** Returns the item ID of the index page of the folder, null otherwise + -- @author Michael Pih + -- @param folder_id The folder id + -- @return The item ID of the index page + --*/ + folder_id in cr_folders.folder_id%TYPE +) return cr_items.item_id%TYPE; + + + +end content_folder; +/ +show errors + +create or replace package body content_item +as + +function get_root_folder ( + item_id in cr_items.item_id%TYPE default null +) return cr_folders.folder_id%TYPE is + + v_folder_id cr_folders.folder_id%TYPE; + +begin + + if item_id is NULL then + + v_folder_id := c_root_folder_id; + + else + + select + item_id into v_folder_id + from + cr_items + where + parent_id = 0 + connect by + prior parent_id = item_id + start with + item_id = get_root_folder.item_id; + + end if; + + return v_folder_id; + +exception + when NO_DATA_FOUND then + raise_application_error(-20000, + 'Could not find a root folder for item ID ' || item_id || '. ' || + 'Either the item does not exist or its parent value is corrupted.'); +end get_root_folder; + +function new ( + name in cr_items.name%TYPE, + parent_id in cr_items.parent_id%TYPE default null, + item_id in acs_objects.object_id%TYPE default null, + locale in cr_items.locale%TYPE default null, + creation_date in acs_objects.creation_date%TYPE + default sysdate, + creation_user in acs_objects.creation_user%TYPE + default null, + context_id in acs_objects.context_id%TYPE + default null, + creation_ip in acs_objects.creation_ip%TYPE default null, + item_subtype in acs_object_types.object_type%TYPE + default 'content_item', + content_type in acs_object_types.object_type%TYPE + default 'content_revision', + title in cr_revisions.title%TYPE default null, + description in cr_revisions.description%TYPE default null, + mime_type in cr_revisions.mime_type%TYPE default 'text/plain', + nls_language in cr_revisions.nls_language%TYPE default null, + text in varchar2 default null, + data in cr_revisions.content%TYPE default null, + relation_tag in cr_child_rels.relation_tag%TYPE default null, + is_live in char default 'f', + storage_type in cr_items.storage_type%TYPE default 'lob' +) return cr_items.item_id%TYPE +is + v_parent_id cr_items.parent_id%TYPE; + v_parent_type acs_objects.object_type%TYPE; + v_item_id cr_items.item_id%TYPE; + v_revision_id cr_revisions.revision_id%TYPE; + v_title cr_revisions.title%TYPE; + v_rel_id acs_objects.object_id%TYPE; + v_rel_tag cr_child_rels.relation_tag%TYPE; + v_context_id acs_objects.context_id%TYPE; + v_storage_type cr_items.storage_type%TYPE; +begin + + -- if content_item.is_subclass(item_subtype,'content_item') = 'f' then + -- raise_application_error(-20000, 'The object_type ' || item_subtype || + -- ' does not inherit from content_item.'); + -- end if; + + -- place the item in the context of the pages folder if no + -- context specified + + if storage_type = 'text' then + v_storage_type := 'lob'; + else + v_storage_type := storage_type; + end if; + + if parent_id is null then + v_parent_id := c_root_folder_id; + else + v_parent_id := parent_id; + end if; + + -- Determine context_id + if context_id is null then + v_context_id := v_parent_id; + else + v_context_id := context_id; + end if; + + if v_parent_id = 0 or + content_folder.is_folder(v_parent_id) = 't' then + + if v_parent_id ^= 0 and + content_folder.is_registered( + v_parent_id, content_item.new.content_type, 'f') = 'f' then + + raise_application_error(-20000, + 'This item''s content type ' || content_item.new.content_type || + ' is not registered to this folder ' || v_parent_id); + + end if; + + elsif v_parent_id ^= 0 then + + begin + + -- Figure out the relation_tag to use + if content_item.new.relation_tag is null then + v_rel_tag := content_item.get_content_type(v_parent_id) + || '-' || content_item.new.content_type; + else + v_rel_tag := content_item.new.relation_tag; + end if; + + select object_type into v_parent_type from acs_objects + where object_id = v_parent_id; + + if is_subclass(v_parent_type, 'content_item') = 't' and + is_valid_child(v_parent_id, content_item.new.content_type, v_rel_tag) = 'f' then + + raise_application_error(-20000, + 'This item''s content type ' || content_item.new.content_type || + ' is not allowed in this container ' || v_parent_id); + + end if; + + exception when NO_DATA_FOUND then + + raise_application_error(-20000, + 'Invalid parent ID ' || v_parent_id || + ' specified in content_item.new'); + + end; + + end if; + + -- Create the object + + v_item_id := acs_object.new( + object_id => content_item.new.item_id, + object_type => content_item.new.item_subtype, + context_id => v_context_id, + creation_date => content_item.new.creation_date, + creation_user => content_item.new.creation_user, + creation_ip => content_item.new.creation_ip + ); + + -- Turn off security inheritance if there is no security context + --if context_id is null then + -- update acs_objects set security_inherit_p = 'f' + -- where object_id = v_item_id; + --end if; + + insert into cr_items ( + item_id, name, content_type, parent_id, storage_type + ) values ( + v_item_id, content_item.new.name, + content_item.new.content_type, v_parent_id, v_storage_type + ); + + -- if the parent is not a folder, insert into cr_child_rels + -- We checked above before creating the object that it is a valid rel + if v_parent_id ^= 0 and + content_folder.is_folder(v_parent_id) = 'f' then + + v_rel_id := acs_object.new( + object_type => 'cr_item_child_rel', + context_id => v_parent_id + ); + + insert into cr_child_rels ( + rel_id, parent_id, child_id, relation_tag, order_n + ) values ( + v_rel_id, v_parent_id, v_item_id, v_rel_tag, v_item_id + ); + + end if; + + -- use the name of the item if no title is supplied + if content_item.new.title is null then + v_title := content_item.new.name; + else + v_title := content_item.new.title; + end if; + + -- create the revision if data or title or text is not null + -- note that the caller could theoretically specify both text + -- and data, in which case the text is ignored. + + if content_item.new.data is not null then + + v_revision_id := content_revision.new( + item_id => v_item_id, + title => v_title, + description => content_item.new.description, + data => content_item.new.data, + mime_type => content_item.new.mime_type, + creation_date => content_item.new.creation_date, + creation_user => content_item.new.creation_user, + creation_ip => content_item.new.creation_ip, + nls_language => content_item.new.nls_language + ); + + elsif content_item.new.title is not null or + content_item.new.text is not null then + + v_revision_id := content_revision.new( + item_id => v_item_id, + title => v_title, + description => content_item.new.description, + text => content_item.new.text, + mime_type => content_item.new.mime_type, + creation_date => content_item.new.creation_date, + creation_user => content_item.new.creation_user, + creation_ip => content_item.new.creation_ip + ); + + end if; + + -- make the revision live if is_live is 't' + if content_item.new.is_live = 't' then + content_item.set_live_revision(v_revision_id); + end if; + + -- Have the new item inherit the permission of the parent item + -- if no security context was specified + --if parent_id is not null and context_id is null then + -- content_permission.inherit_permissions ( + -- parent_id, v_item_id, creation_user + -- ); + --end if; + + return v_item_id; +end new; + +function is_published ( + item_id in cr_items.item_id%TYPE +) return char +is + v_is_published char(1); +begin + + select + 't' into v_is_published + from + cr_items + where + live_revision is not null + and + publish_status = 'live' + and + item_id = is_published.item_id; + + return v_is_published; + exception + when NO_DATA_FOUND then + return 'f'; +end is_published; + +function is_publishable ( + item_id in cr_items.item_id%TYPE +) return char +is + v_child_count integer; + v_rel_count integer; + v_template_id cr_templates.template_id%TYPE; + + -- get the child types registered to this content type + cursor c_child_types is + select + child_type, min_n, max_n + from + cr_type_children + where + parent_type = content_item.get_content_type( is_publishable.item_id ); + + -- get the relation types registered to this content type + cursor c_rel_types is + select + target_type, min_n, max_n + from + cr_type_relations + where + content_type = content_item.get_content_type( is_publishable.item_id ); + + -- get the publishing workflows associated with this content item + -- there should only be 1 if CMS exists, otherwise 0 + -- cursor c_pub_wf is + -- select + -- case_id, state + -- from + -- wf_cases + -- where + -- workflow_key = 'publishing_wf' + -- and + -- object_id = is_publishable.item_id; + +begin + + -- validate children + -- make sure the # of children of each type fall between min_n and max_n + for v_child_type in c_child_types loop + select + count(rel_id) into v_child_count + from + cr_child_rels + where + parent_id = is_publishable.item_id + and + content_item.get_content_type( child_id ) = v_child_type.child_type; + + -- make sure # of children is in range + if v_child_type.min_n is not null + and v_child_count < v_child_type.min_n then + return 'f'; + end if; + if v_child_type.max_n is not null + and v_child_count > v_child_type.max_n then + return 'f'; + end if; + + end loop; + + + -- validate relations + -- make sure the # of ext links of each type fall between min_n and max_n + for v_rel_type in c_rel_types loop + select + count(rel_id) into v_rel_count + from + cr_item_rels i, acs_objects o + where + i.related_object_id = o.object_id + and + i.item_id = is_publishable.item_id + and + nvl(content_item.get_content_type(o.object_id),o.object_type) = v_rel_type.target_type; + + -- make sure # of object relations is in range + if v_rel_type.min_n is not null + and v_rel_count < v_rel_type.min_n then + return 'f'; + end if; + if v_rel_type.max_n is not null + and v_rel_count > v_rel_type.max_n then + return 'f'; + end if; + end loop; + + -- validate publishing workflows + -- make sure any 'publishing_wf' associated with this item are finished + -- KG: logic is wrong here. Only the latest workflow matters, and even + -- that is a little problematic because more than one workflow may be + -- open on an item. In addition, this should be moved to CMS. + + -- Removed this as having workflow stuff in the CR is just plain wrong. + -- DanW, Aug 25th, 2001. + + -- for v_pub_wf in c_pub_wf loop + -- if v_pub_wf.state ^= 'finished' then + -- return 'f'; + -- end if; + -- end loop; + + return 't'; + exception + when NO_DATA_FOUND then + return 'f'; +end is_publishable; + +function is_valid_child ( + item_id in cr_items.item_id%TYPE, + content_type in acs_object_types.object_type%TYPE, + relation_tag in cr_child_rels.relation_tag%TYPE default null +) return char +is + v_is_valid_child char(1); + v_max_children cr_type_children.max_n%TYPE; + v_n_children integer; +begin + + v_is_valid_child := 'f'; + + -- first check if content_type is a registered child_type + begin + select + sum(max_n) into v_max_children + from + cr_type_children + where + parent_type = content_item.get_content_type( is_valid_child.item_id ) + and + child_type = is_valid_child.content_type + and + (is_valid_child.relation_tag is null + or is_valid_child.relation_tag = relation_tag); + + exception + when NO_DATA_FOUND then + return 'f'; + end; + + -- if the max is null then infinite number is allowed + if v_max_children is null then + return 't'; + end if; + + -- next check if there are already max_n children of that content type + select + count(rel_id) into v_n_children + from + cr_child_rels + where + parent_id = is_valid_child.item_id + and + content_item.get_content_type( child_id ) = is_valid_child.content_type + and + (is_valid_child.relation_tag is null + or is_valid_child.relation_tag = relation_tag); + + if v_n_children < v_max_children then + v_is_valid_child := 't'; + end if; + + return v_is_valid_child; + exception + when NO_DATA_FOUND then + return 'f'; +end is_valid_child; + +/* delete a content item + 1) delete all associated workflows + 2) delete all symlinks associated with this object + 3) delete any revisions for this item + 4) unregister template relations + 5) delete all permissions associated with this item + 6) delete keyword associations + 7) delete all associated comments */ +procedure del ( + item_id in cr_items.item_id%TYPE +) is + +-- cursor c_wf_cases_cur is +-- select +-- case_id +-- from +-- wf_cases +-- where +-- object_id = item_id; + + cursor c_symlink_cur is + select + symlink_id + from + cr_symlinks + where + target_id = content_item.del.item_id; + + cursor c_revision_cur is + select + revision_id + from + cr_revisions + where + item_id = content_item.del.item_id; + + cursor c_rel_cur is + select + rel_id + from + cr_item_rels + where + item_id = content_item.del.item_id + or + related_object_id = content_item.del.item_id; + + cursor c_child_cur is + select + rel_id + from + cr_child_rels + where + child_id = content_item.del.item_id; + + cursor c_parent_cur is + select + rel_id, child_id + from + cr_child_rels + where + parent_id = content_item.del.item_id; + + -- this is strictly for debugging + -- cursor c_error_cur is + -- select + -- object_id, object_type + -- from + -- acs_objects + -- where + -- context_id = content_item.delete.item_id; + +begin + + -- Removed this as having workflow stuff in the CR is just plain wrong. + -- DanW, Aug 25th, 2001. + + -- dbms_output.put_line('Deleting associated workflows...'); + -- 1) delete all workflow cases associated with this item + -- for v_wf_cases_val in c_wf_cases_cur loop + -- workflow_case.delete(v_wf_cases_val.case_id); + -- end loop; + + dbms_output.put_line('Deleting symlinks...'); + -- 2) delete all symlinks to this item + for v_symlink_val in c_symlink_cur loop + content_symlink.del(v_symlink_val.symlink_id); + end loop; + + dbms_output.put_line('Unscheduling item...'); + delete from cr_release_periods + where item_id = content_item.del.item_id; + + dbms_output.put_line('Deleting associated revisions...'); + -- 3) delete all revisions of this item + delete from cr_item_publish_audit + where item_id = content_item.del.item_id; + for v_revision_val in c_revision_cur loop + content_revision.del(v_revision_val.revision_id); + end loop; + + dbms_output.put_line('Deleting associated item templates...'); + -- 4) unregister all templates to this item + delete from cr_item_template_map + where item_id = content_item.del.item_id; + + dbms_output.put_line('Deleting item relationships...'); + -- Delete all relations on this item + for v_rel_val in c_rel_cur loop + acs_rel.del(v_rel_val.rel_id); + end loop; + + dbms_output.put_line('Deleting child relationships...'); + for v_rel_val in c_child_cur loop + acs_rel.del(v_rel_val.rel_id); + end loop; + + dbms_output.put_line('Deleting parent relationships...'); + for v_rel_val in c_parent_cur loop + acs_rel.del(v_rel_val.rel_id); + content_item.del(v_rel_val.child_id); + end loop; + + dbms_output.put_line('Deleting associated permissions...'); + -- 5) delete associated permissions + delete from acs_permissions + where object_id = content_item.del.item_id; + + dbms_output.put_line('Deleting keyword associations...'); + -- 6) delete keyword associations + delete from cr_item_keyword_map + where item_id = content_item.del.item_id; + + dbms_output.put_line('Deleting associated comments...'); + -- 7) delete associated comments + journal_entry.delete_for_object( content_item.del.item_id ); + + -- context_id debugging loop + --for v_error_val in c_error_cur loop + -- dbms_output.put_line('ID=' || v_error_val.object_id || ' TYPE=' + -- || v_error_val.object_type); + --end loop; + + dbms_output.put_line('Deleting content item...'); + acs_object.del(content_item.del.item_id); + +end del; + + +procedure edit_name ( + item_id in cr_items.item_id%TYPE, + name in cr_items.name%TYPE +) is + cursor exists_cur is + select + item_id + from + cr_items + where + cr_items.name = content_item.edit_name.name + and + parent_id = (select + parent_id + from + cr_items + where + cr_items.item_id = content_item.edit_name.item_id); + + exists_id integer; +begin + + open exists_cur; + fetch exists_cur into exists_id; + + if exists_cur%NOTFOUND then + close exists_cur; + update cr_items + set cr_items.name = content_item.edit_name.name + where cr_items.item_id = content_item.edit_name.item_id; + else + close exists_cur; + if exists_id <> item_id then + raise_application_error(-20000, + 'An item with the name ' || name || + ' already exists in this directory.'); + end if; + end if; + +end edit_name; + +function get_id ( + item_path in varchar2, + root_folder_id in cr_items.item_id%TYPE default c_root_folder_id, + resolve_index in char default 'f' +) return cr_items.item_id%TYPE is + + v_item_path varchar2(4000); + v_root_folder_id cr_items.item_id%TYPE; + parent_id integer; + child_id integer; + start_pos integer := 1; + end_pos integer; + counter integer := 0; + item_name varchar2(200); + +begin + + v_root_folder_id := nvl(root_folder_id, c_root_folder_id); + + -- If the request path is the root, then just return the root folder + if item_path = '/' then + return v_root_folder_id; + end if; + + -- Remove leading, trailing spaces, leading slashes + v_item_path := rtrim(ltrim(trim(item_path), '/'), '/'); + + parent_id := v_root_folder_id; + + -- if parent_id is a symlink, resolve it + parent_id := content_symlink.resolve(parent_id); + + loop + + end_pos := instr(v_item_path, '/', start_pos); + + if end_pos = 0 then + item_name := substr(v_item_path, start_pos); + else + item_name := substr(v_item_path, start_pos, end_pos - start_pos); + end if; + + select + item_id into child_id + from + cr_items + where + parent_id = get_id.parent_id + and + name = item_name; + + exit when end_pos = 0; + + parent_id := child_id; + + -- if parent_id is a symlink, resolve it + parent_id := content_symlink.resolve(parent_id); + + start_pos := end_pos + 1; + + end loop; + + if get_id.resolve_index = 't' then + + -- if the item is a folder and has an index page, then return + + if content_folder.is_folder( child_id ) = 't' and + content_folder.get_index_page( child_id ) is not null then + + child_id := content_folder.get_index_page( child_id ); + + end if; + + end if; + + return child_id; + +exception + when NO_DATA_FOUND then + return null; +end get_id; + +function get_path ( + item_id in cr_items.item_id%TYPE, + root_folder_id in cr_items.item_id%TYPE default null +) return varchar2 +is + + cursor c_abs_cur is + select + name, parent_id, level as tree_level + from + cr_items + where + parent_id <> 0 + connect by + prior parent_id = item_id + start with + item_id = get_path.item_id + order by + tree_level desc; + + v_count integer; + v_name varchar2(400); + v_parent_id integer := 0; + v_tree_level integer; + + v_resolved_root_id integer; + + cursor c_rel_cur is + select + parent_id, level as tree_level + from + cr_items + where + parent_id <> 0 + connect by + prior parent_id = item_id + start with + item_id = v_resolved_root_id + order by + tree_level desc; + + v_rel_parent_id integer := 0; + v_rel_tree_level integer := 0; + + v_path varchar2(4000) := ''; + +begin + + -- check that the item exists + select count(*) into v_count from cr_items where item_id = get_path.item_id; + + if v_count = 0 then + raise_application_error(-20000, 'Invalid item ID: ' || item_id); + end if; + + -- begin walking down the path to the item (from the repository root) + open c_abs_cur; + + -- if the root folder is not null then prepare for a relative path + + if root_folder_id is not null then + + -- if root_folder_id is a symlink, resolve it (child items will point + -- to the actual folder, not the symlink) + + v_resolved_root_id := content_symlink.resolve(root_folder_id); + + -- begin walking down the path to the root folder. Discard + -- elements of the item path as long as they are the same as the root + -- folder + + open c_rel_cur; + + while v_parent_id = v_rel_parent_id loop + fetch c_abs_cur into v_name, v_parent_id, v_tree_level; + fetch c_rel_cur into v_rel_parent_id, v_rel_tree_level; + exit when c_abs_cur%NOTFOUND or c_rel_cur%NOTFOUND; + end loop; + + -- walk the remainder of the relative path, add a '..' for each + -- additional step + + loop + exit when c_rel_cur%NOTFOUND; + v_path := v_path || '../'; + fetch c_rel_cur into v_rel_parent_id, v_rel_tree_level; + end loop; + close c_rel_cur; + + -- an item relative to itself is '../item' + if v_resolved_root_id = item_id then + v_path := '../'; + end if; + + else + + -- this is an absolute path so prepend a '/' + v_path := '/'; + + -- prime the pump to be consistent with relative path execution plan + fetch c_abs_cur into v_name, v_parent_id, v_tree_level; + + end if; + + -- loop over the remainder of the absolute path + + loop + + v_path := v_path || v_name; + + fetch c_abs_cur into v_name, v_parent_id, v_tree_level; + + exit when c_abs_cur%NOTFOUND; + + v_path := v_path || '/'; + + end loop; + close c_abs_cur; + + return v_path; + +end get_path; + + +function get_virtual_path ( + item_id in cr_items.item_id%TYPE, + root_folder_id in cr_items.item_id%TYPE default c_root_folder_id +) return varchar2 +is + v_path varchar2(4000); + v_item_id cr_items.item_id%TYPE; + v_is_folder char(1); + v_index cr_items.item_id%TYPE; +begin + + -- first resolve the item + v_item_id := content_symlink.resolve( get_virtual_path.item_id ); + + v_is_folder := content_folder.is_folder( v_item_id ); + v_index := content_folder.get_index_page( v_item_id ); + + -- if the folder has an index page + if v_is_folder = 't' and v_index is not null then + v_path := content_item.get_path( content_symlink.resolve( v_index )); + else + v_path := content_item.get_path( v_item_id ); + end if; + + return v_path; + exception + when NO_DATA_FOUND then + return null; +end get_virtual_path; + + + +procedure write_to_file ( + item_id in cr_items.item_id%TYPE, + root_path in varchar2 +)is + + blob_loc cr_revisions.content%TYPE; + v_revision cr_items.live_revision%TYPE; + +begin + + v_revision := get_live_revision(item_id); + select content into blob_loc from cr_revisions + where revision_id = v_revision; + + blob_to_file(root_path || get_path(item_id), blob_loc); + +exception when no_data_found then + + raise_application_error(-20000, 'No live revision for content item' || + item_id || ' in content_item.write_to_file.'); + +end write_to_file; + +procedure register_template ( + item_id in cr_items.item_id%TYPE, + template_id in cr_templates.template_id%TYPE, + use_context in cr_item_template_map.use_context%TYPE +) is + +begin + + -- register template if it is not already registered + insert into cr_item_template_map ( + template_id, item_id, use_context + ) select + register_template.template_id, + register_template.item_id, + register_template.use_context + from + dual + where + not exists ( select 1 + from + cr_item_template_map + where + item_id = register_template.item_id + and + template_id = register_template.template_id + and + use_context = register_template.use_context ); + +end register_template; + +procedure unregister_template ( + item_id in cr_items.item_id%TYPE, + template_id in cr_templates.template_id%TYPE default null, + use_context in cr_item_template_map.use_context%TYPE default null +) is + +begin + + if use_context is null and template_id is null then + + delete from cr_item_template_map + where item_id = unregister_template.item_id; + + elsif use_context is null then + + delete from cr_item_template_map + where template_id = unregister_template.template_id + and item_id = unregister_template.item_id; + + elsif template_id is null then + + delete from cr_item_template_map + where item_id = unregister_template.item_id + and use_context = unregister_template.use_context; + + else + + delete from cr_item_template_map + where template_id = unregister_template.template_id + and item_id = unregister_template.item_id + and use_context = unregister_template.use_context; + + end if; + +end unregister_template; + +function get_template ( + item_id in cr_items.item_id%TYPE, + use_context in cr_item_template_map.use_context%TYPE +) return cr_templates.template_id%TYPE is + + v_template_id cr_templates.template_id%TYPE; + v_content_type cr_items.content_type%TYPE; + + cursor item_cur is + select + template_id + from + cr_item_template_map + where + item_id = get_template.item_id + and + use_context = get_template.use_context; + +begin + + -- look for a template assigned specifically to this item + open item_cur; + fetch item_cur into v_template_id; + + -- otherwise get the default for the content type + if item_cur%NOTFOUND then + select + m.template_id + into + v_template_id + from + cr_items i, cr_type_template_map m + where + i.item_id = get_template.item_id + and + i.content_type = m.content_type + and + m.use_context = get_template.use_context + and + m.is_default = 't'; + end if; + close item_cur; + + return v_template_id; + +exception + when NO_DATA_FOUND then + if item_cur%ISOPEN then + close item_cur; + end if; + return null; +end get_template; + +-- Return the object type of this item + +function get_content_type ( + item_id in cr_items.item_id%TYPE +) return cr_items.content_type%TYPE is + v_content_type cr_items.content_type%TYPE; +begin + + select + content_type into v_content_type + from + cr_items + where + item_id = get_content_type.item_id; + + return v_content_type; +exception + when NO_DATA_FOUND then + return null; +end get_content_type; + +function get_live_revision ( + item_id in cr_items.item_id%TYPE +) return cr_revisions.revision_id%TYPE is + + v_revision_id acs_objects.object_id%TYPE; + +begin + + select + live_revision into v_revision_id + from + cr_items + where + item_id = get_live_revision.item_id; + + return v_revision_id; + +exception + when NO_DATA_FOUND then + return null; +end get_live_revision; + +procedure set_live_revision ( + revision_id in cr_revisions.revision_id%TYPE, + publish_status in cr_items.publish_status%TYPE default 'ready' +) is +begin + + update + cr_items + set + live_revision = set_live_revision.revision_id, + publish_status = set_live_revision.publish_status + where + item_id = (select + item_id + from + cr_revisions + where + revision_id = set_live_revision.revision_id); + + update + cr_revisions + set + publish_date = sysdate + where + revision_id = set_live_revision.revision_id; + +end set_live_revision; + + +procedure unset_live_revision ( + item_id in cr_items.item_id%TYPE +) is +begin + + update + cr_items + set + live_revision = NULL + where + item_id = unset_live_revision.item_id; + + -- if an items publish status is "live", change it to "ready" + update + cr_items + set + publish_status = 'production' + where + publish_status = 'live' + and + item_id = unset_live_revision.item_id; + + +end unset_live_revision; + + +procedure set_release_period ( + item_id in cr_items.item_id%TYPE, + start_when date default null, + end_when date default null +) is + + v_count integer; + +begin + + select decode(count(*),0,0,1) into v_count from cr_release_periods + where item_id = set_release_period.item_id; + + if v_count = 0 then + + insert into cr_release_periods ( + item_id, start_when, end_when + ) values ( + item_id, start_when, end_when + ); + + else + + update cr_release_periods + set start_when = set_release_period.start_when, + end_when = set_release_period.end_when + where + item_id = set_release_period.item_id; + + end if; + +end set_release_period; + + +function get_revision_count ( + item_id in cr_items.item_id%TYPE +) return number is + + v_count integer; + +begin + + select + count(*) into v_count + from + cr_revisions + where + item_id = get_revision_count.item_id; + + return v_count; + +end get_revision_count; + +function get_context ( + item_id in cr_items.item_id%TYPE +) return acs_objects.context_id%TYPE is + + v_context_id acs_objects.context_id%TYPE; + +begin + + select + context_id + into + v_context_id + from + acs_objects + where + object_id = get_context.item_id; + + return v_context_id; + +exception when no_data_found then + + raise_application_error(-20000, 'Content item ' || item_id || + ' does not exist in content_item.get_context'); + + +end get_context; + +-- 1) make sure we are not moving the item to an invalid location: +-- that is, the destination folder exists and is a valid folder +-- 2) make sure the content type of the content item is registered +-- to the target folder +-- 3) update the parent_id for the item +procedure move ( + item_id in cr_items.item_id%TYPE, + target_folder_id in cr_folders.folder_id%TYPE, + name in cr_items.name%TYPE default null +) is +begin + + if content_folder.is_folder(item_id) = 't' then + content_folder.move(item_id, target_folder_id, name); + elsif content_folder.is_folder(target_folder_id) = 't' then + + + if content_folder.is_registered( move.target_folder_id, + get_content_type( move.item_id )) = 't' and + content_folder.is_registered( move.target_folder_id, + get_content_type( content_symlink.resolve( move.item_id)),'f') = 't' + then + + -- update the parent_id for the item + update cr_items + set parent_id = move.target_folder_id, + name = nvl (move.name, cr_items.name) + where item_id = move.item_id; + end if; + + end if; +end move; + +procedure copy ( + item_id in cr_items.item_id%TYPE, + target_folder_id in cr_folders.folder_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE default null, + name in cr_items.name%TYPE default null +) is + + copy_id cr_items.item_id%TYPE; + +begin + + copy_id := copy2(item_id, target_folder_id, creation_user, creation_ip, name); + +end copy; + +-- copy a content item to a target folder +-- 1) make sure we are not copying the item to an invalid location: +-- that is, the destination folder exists, is a valid folder, +-- and is not the current folder +-- 2) make sure the content type of the content item is registered +-- with the current folder +-- 3) create a new item with no revisions in the target folder +-- 4) copy the latest revision from the original item to the new item (if any) + +function copy2 ( + item_id in cr_items.item_id%TYPE, + target_folder_id in cr_folders.folder_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE default null, + name in cr_items.name%TYPE default null +) return cr_items.item_id%TYPE is + v_current_folder_id cr_folders.folder_id%TYPE; + v_num_revisions integer; + v_name cr_items.name%TYPE; + v_content_type cr_items.content_type%TYPE; + v_locale cr_items.locale%TYPE; + v_item_id cr_items.item_id%TYPE; + v_revision_id cr_revisions.revision_id%TYPE; + v_is_registered char(1); + v_old_revision_id cr_revisions.revision_id%TYPE; + v_new_revision_id cr_revisions.revision_id%TYPE; + v_storage_type cr_items.storage_type%TYPE; +begin + + -- call content_folder.copy if the item is a folder + if content_folder.is_folder(copy2.item_id) = 't' then + content_folder.copy( + folder_id => copy2.item_id, + target_folder_id => copy2.target_folder_id, + creation_user => copy2.creation_user, + creation_ip => copy2.creation_ip, + name => copy2.name + ); + -- call content_symlink.copy if the item is a symlink + elsif content_symlink.is_symlink(copy2.item_id) = 't' then + content_symlink.copy( + symlink_id => copy2.item_id, + target_folder_id => copy2.target_folder_id, + creation_user => copy2.creation_user, + creation_ip => copy2.creation_ip, + name => copy2.name + ); + -- call content_extlink.copy if the item is a extlink + elsif content_extlink.is_extlink(copy2.item_id) = 't' then + content_extlink.copy( + extlink_id => copy2.item_id, + target_folder_id => copy2.target_folder_id, + creation_user => copy2.creation_user, + creation_ip => copy2.creation_ip, + name => copy2.name + ); + -- call content_extlink.copy if the item is a extlink + elsif content_extlink.is_extlink(copy2.item_id) = 't' then + content_extlink.copy( + extlink_id => copy2.item_id, + target_folder_id => copy2.target_folder_id, + creation_user => copy2.creation_user, + creation_ip => copy2.creation_ip + ); + -- make sure the target folder is really a folder + elsif content_folder.is_folder(copy2.target_folder_id) = 't' then + + select + parent_id + into + v_current_folder_id + from + cr_items + where + item_id = copy2.item_id; + + select + content_type, name , locale, + nvl(live_revision, latest_revision), storage_type + into + v_content_type, v_name, v_locale, v_revision_id, v_storage_type + from + cr_items + where + item_id = copy2.item_id; + + -- can't copy to the same folder unless name is different + if copy2.target_folder_id ^= v_current_folder_id or (v_name != copy2.name and copy2.name is not null) then + + if copy2.name is not null then + v_name := copy2.name; + end if; + -- make sure the content type of the item is registered to the folder + v_is_registered := content_folder.is_registered( + folder_id => copy2.target_folder_id, + content_type => v_content_type, + include_subtypes => 'f' + ); + + if v_is_registered = 't' then + -- create the new content item + v_item_id := content_item.new( + parent_id => copy2.target_folder_id, + name => v_name, + locale => v_locale, + content_type => v_content_type, + creation_user => copy2.creation_user, + creation_ip => copy2.creation_ip, + storage_type => v_storage_type + ); + + -- get the latest revision of the old item + select + latest_revision into v_old_revision_id + from + cr_items + where + item_id = copy2.item_id; + + -- copy the latest revision (if any) to the new item + if v_old_revision_id is not null then + v_new_revision_id := content_revision.copy ( + revision_id => v_old_revision_id, + target_item_id => v_item_id, + creation_user => copy2.creation_user, + creation_ip => copy2.creation_ip + ); + end if; + end if; + + + end if; + end if; + + return v_item_id; + +end copy2; + +-- get the latest revision for an item +function get_latest_revision ( + item_id in cr_items.item_id%TYPE +) return cr_revisions.revision_id%TYPE is + v_revision_id integer; + + cursor c_revision_cur is + select + r.revision_id + from + cr_revisions r, acs_objects o + where + r.revision_id = o.object_id + and + r.item_id = get_latest_revision.item_id + order by + o.creation_date desc; +begin + + if item_id is null then + return null; + end if; + + open c_revision_cur; + fetch c_revision_cur into v_revision_id; + if c_revision_cur%NOTFOUND then + close c_revision_cur; + return null; + end if; + close c_revision_cur; + return v_revision_id; + +exception + when NO_DATA_FOUND then + if c_revision_cur%ISOPEN then + close c_revision_cur; + end if; + return null; +end get_latest_revision; + + + +function get_best_revision ( + item_id in cr_items.item_id%TYPE +) return cr_revisions.revision_id%TYPE +is + v_revision_id cr_revisions.revision_id%TYPE; +begin + + select + NVL (live_revision, latest_revision ) + into + v_revision_id + from + cr_items + where + item_id = get_best_revision.item_id; + + return v_revision_id; +exception + when NO_DATA_FOUND then + return null; +end get_best_revision; + + + +function get_title ( + item_id in cr_items.item_id%TYPE, + is_live in char default 'f' +) return cr_revisions.title%TYPE is + + v_title cr_revisions.title%TYPE; + v_content_type cr_items.content_type%TYPE; + +begin + + select content_type into v_content_type from cr_items + where item_id = get_title.item_id; + + if v_content_type = 'content_folder' then + select label into v_title from cr_folders + where folder_id = get_title.item_id; + elsif v_content_type = 'content_symlink' then + select label into v_title from cr_symlinks + where symlink_id = get_title.item_id; + elsif v_content_type = 'content_extlink' then + select label into v_title from cr_extlinks + where extlink_id = get_title.item_id; + else + if is_live ^= 'f' then + select + title into v_title + from + cr_revisions r, cr_items i + where + i.item_id = get_title.item_id + and + r.revision_id = i.live_revision; + else + select + title into v_title + from + cr_revisions r, cr_items i + where + i.item_id = get_title.item_id + and + r.revision_id = i.latest_revision; + end if; + end if; + + return v_title; + +end get_title; + +function get_publish_date ( + item_id in cr_items.item_id%TYPE, + is_live in char default 'f' +) return cr_revisions.publish_date%TYPE +is + v_revision_id cr_revisions.revision_id%TYPE; + v_publish_date cr_revisions.publish_date%TYPE; +begin + + if is_live ^= 'f' then + select + publish_date into v_publish_date + from + cr_revisions r, cr_items i + where + i.item_id = get_publish_date.item_id + and + r.revision_id = i.live_revision; + else + select + publish_date into v_publish_date + from + cr_revisions r, cr_items i + where + i.item_id = get_publish_date.item_id + and + r.revision_id = i.latest_revision; + end if; + + return v_publish_date; + +exception when no_data_found then + return null; +end get_publish_date; + +function is_subclass ( + object_type in acs_object_types.object_type%TYPE, + supertype in acs_object_types.supertype%TYPE +) return char is + + v_subclass_p char; + + cursor c_inherit_cur is + select + object_type + from + acs_object_types + connect by + prior object_type = supertype + start with + object_type = is_subclass.supertype; + +begin + + v_subclass_p := 'f'; + + for v_inherit_val in c_inherit_cur loop + if v_inherit_val.object_type = is_subclass.object_type then + v_subclass_p := 't'; + end if; + end loop; + + return v_subclass_p; + +end is_subclass; + +function relate ( + item_id in cr_items.item_id%TYPE, + object_id in acs_objects.object_id%TYPE, + relation_tag in cr_type_relations.relation_tag%TYPE default 'generic', + order_n in cr_item_rels.order_n%TYPE default null, + relation_type in acs_object_types.object_type%TYPE default 'cr_item_rel' +) return cr_item_rels.rel_id%TYPE +is + v_content_type cr_items.content_type%TYPE; + v_object_type acs_objects.object_type%TYPE; + v_is_valid integer; + v_rel_id integer; + v_exists integer; + v_order_n cr_item_rels.order_n%TYPE; +begin + + -- check the relationship is valid + v_content_type := content_item.get_content_type ( relate.item_id ); + v_object_type := content_item.get_content_type ( relate.object_id ); + + select + decode( count(1),0,0,1) into v_is_valid + from + cr_type_relations + where + content_item.is_subclass( v_object_type, target_type ) = 't' + and + content_item.is_subclass( v_content_type, content_type ) = 't'; + + if v_is_valid = 0 then + raise_application_error(-20000, + 'There is no registered relation type matching this item relation.'); + end if; + + if relate.item_id ^= relate.object_id then + -- check that these two items are not related already + --dbms_output.put_line( 'checking if the items are already related...'); + begin + select + rel_id, 1 as v_exists into v_rel_id, v_exists + from + cr_item_rels + where + item_id = relate.item_id + and + related_object_id = relate.object_id + and + relation_tag = relate.relation_tag; + exception when no_data_found then + v_exists := 0; + end; + + + -- if order_n is null, use rel_id (the order the item was related) + if relate.order_n is null then + v_order_n := v_rel_id; + else + v_order_n := relate.order_n; + end if; + + + -- if relationship does not exist, create it + if v_exists <> 1 then + --dbms_output.put_line( 'creating new relationship...'); + v_rel_id := acs_object.new( + object_type => relation_type, + context_id => item_id + ); + insert into cr_item_rels ( + rel_id, item_id, related_object_id, order_n, relation_tag + ) values ( + v_rel_id, item_id, object_id, v_order_n, relation_tag + ); + + -- if relationship already exists, update it + else + --dbms_output.put_line( 'updating existing relationship...'); + update cr_item_rels set + relation_tag = relate.relation_tag, + order_n = v_order_n + where + rel_id = v_rel_id; + end if; + + end if; + return v_rel_id; +end relate; + + +procedure unrelate ( + rel_id in cr_item_rels.rel_id%TYPE +) is +begin + + -- delete the relation object + acs_rel.del( unrelate.rel_id ); + + -- delete the row from the cr_item_rels table + delete from cr_item_rels where rel_id = unrelate.rel_id; + +end unrelate; + +function is_index_page ( + item_id in cr_items.item_id%TYPE, + folder_id in cr_folders.folder_id%TYPE +) return varchar2 +is +begin + if content_folder.get_index_page(folder_id) = item_id then + return 't'; + else + return 'f'; + end if; +end is_index_page; + + + +function get_parent_folder ( + item_id in cr_items.item_id%TYPE +) return cr_folders.folder_id%TYPE +is + v_folder_id cr_folders.folder_id%TYPE; + v_parent_folder_p char(1); +begin + v_parent_folder_p := 'f'; + v_folder_id := get_parent_folder.item_id; + + while v_parent_folder_p = 'f' and v_folder_id is not null loop + select + parent_id, content_folder.is_folder( parent_id ) + into + v_folder_id, v_parent_folder_p + from + cr_items + where + item_id = v_folder_id; + + end loop; + + return v_folder_id; + +end get_parent_folder; + +end content_item; +/ +show errors + +create or replace package body content_folder +as + +function new ( + name in cr_items.name%TYPE, + label in cr_folders.label%TYPE, + description in cr_folders.description%TYPE default null, + parent_id in cr_items.parent_id%TYPE default null, + context_id in acs_objects.context_id%TYPE default null, + folder_id in cr_folders.folder_id%TYPE default null, + creation_date in acs_objects.creation_date%TYPE default sysdate, + creation_user in acs_objects.creation_user%TYPE default null, + creation_ip in acs_objects.creation_ip%TYPE default null +) return cr_folders.folder_id%TYPE is + v_folder_id cr_folders.folder_id%TYPE; + v_context_id acs_objects.context_id%TYPE; +begin + + -- set the context_id + if content_folder.new.context_id is null then + v_context_id := content_folder.new.parent_id; + else + v_context_id := content_folder.new.context_id; + end if; + + -- parent_id = 0 means that this is a mount point + if parent_id ^= 0 and + content_folder.is_registered(parent_id,'content_folder') = 'f' then + + raise_application_error(-20000, + 'This folder does not allow subfolders to be created'); + else + + v_folder_id := content_item.new( + item_id => folder_id, + name => name, + item_subtype => 'content_folder', + content_type => 'content_folder', + context_id => v_context_id, + creation_date => creation_date, + creation_user => creation_user, + creation_ip => creation_ip, + parent_id => parent_id + ); + + insert into cr_folders ( + folder_id, label, description + ) values ( + v_folder_id, label, description + ); + + -- inherit the attributes of the parent folder + if content_folder.new.parent_id is not null then + + insert into cr_folder_type_map ( + folder_id, content_type + ) select + v_folder_id, content_type + from + cr_folder_type_map + where + folder_id = content_folder.new.parent_id; + end if; + + -- update the child flag on the parent + update cr_folders set has_child_folders = 't' + where folder_id = content_folder.new.parent_id; + + return v_folder_id; + end if; + +end new; + +procedure del ( + folder_id in cr_folders.folder_id%TYPE, + cascade_p in char default 'f' +) is + + v_count integer; + v_parent_id cr_items.parent_id%TYPE; + v_child_item_id cr_items.item_id%TYPE; + + cursor c_folder_children_cur is + select + item_id + from + cr_items + connect by + prior item_id=parent_id + start with parent_id = del.folder_id; + +begin + + -- check if the folder contains any items + + select count(*) into v_count from cr_items where parent_id = folder_id; + + if v_count > 0 and content_folder.del.cascade_p='f' then + raise_application_error(-20000, + 'Folder ID ' || folder_id || ' (' || content_item.get_path(folder_id) || + ') cannot be deleted because it is not empty.'); + else + open c_folder_children_cur; + + loop + + fetch c_folder_children_cur into v_child_item_id; + exit when c_folder_children_cur%NOTFOUND; + if is_folder(v_child_item_id) = 't' then + content_folder.del(v_child_item_id,'t'); + else + + content_item.del(v_child_item_id); + end if; + end loop; + close c_folder_children_cur; + end if; + + content_folder.unregister_content_type( + folder_id => content_folder.del.folder_id, + content_type => 'content_revision', + include_subtypes => 't' ); + + delete from cr_folder_type_map + where folder_id = content_folder.del.folder_id; + + select parent_id into v_parent_id from cr_items + where item_id = content_folder.del.folder_id; + + content_item.del(folder_id); + + -- check if any folders are left in the parent + update cr_folders set has_child_folders = 'f' + where folder_id = v_parent_id and not exists ( + select 1 from cr_items + where parent_id = v_parent_id and content_type = 'content_folder'); + +end del; + +-- renames a folder, making sure the new name is not already in use +procedure edit_name ( + folder_id in cr_folders.folder_id%TYPE, + name in cr_items.name%TYPE default null, + label in cr_folders.label%TYPE default null, + description in cr_folders.description%TYPE default null +) is + v_name_already_exists_p integer := 0; +begin + + if name is not null then + content_item.edit_name(folder_id, name); + end if; + + if label is not null and description is not null then + + update cr_folders + set cr_folders.label = content_folder.edit_name.label, + cr_folders.description = content_folder.edit_name.description + where cr_folders.folder_id = content_folder.edit_name.folder_id; + + elsif label is not null and description is null then + + update cr_folders + set cr_folders.label = content_folder.edit_name.label + where cr_folders.folder_id = content_folder.edit_name.folder_id; + + end if; + +end edit_name; + + +-- 1) make sure we are not moving the folder to an invalid location: +-- a. destination folder exists +-- b. folder is not the webroot (folder_id = -1) +-- c. destination folder is not the same as the folder +-- d. destination folder is not a subfolder +-- 2) make sure subfolders are allowed in the target_folder +-- 3) update the parent_id for the folder + +procedure move ( + folder_id in cr_folders.folder_id%TYPE, + target_folder_id in cr_folders.folder_id%TYPE, + name in cr_items.name%TYPE default null +) is + v_source_folder_id integer; + v_valid_folders_p integer := 0; +begin + + select + count(*) + into + v_valid_folders_p + from + cr_folders + where + folder_id = move.target_folder_id + or + folder_id = move.folder_id; + + if v_valid_folders_p ^= 2 then + raise_application_error(-20000, + 'content_folder.move - Not valid folder(s)'); + end if; + + if folder_id = content_item.get_root_folder or + folder_id = content_template.get_root_folder then + raise_application_error( -20000, + 'content_folder.move - Cannot move root folder'); + end if; + + if target_folder_id = folder_id then + raise_application_error(-20000, + 'content_folder.move - Cannot move a folder to itself'); + end if; + + if is_sub_folder(folder_id, target_folder_id) = 't' then + raise_application_error(-20000, + 'content_folder.move - Destination folder is subfolder'); + end if; + + if is_registered(target_folder_id,'content_folder') ^= 't' then + raise_application_error(-20000, + 'content_folder.move - Destination folder does not allow subfolders'); + end if; + + select parent_id into v_source_folder_id from cr_items + where item_id = move.folder_id; + + -- update the parent_id for the folder + update cr_items + set parent_id = move.target_folder_id, + name=nvl(move.name, cr_items.name) + where item_id = move.folder_id; + + -- update the has_child_folders flags + + -- update the source + update cr_folders set has_child_folders = 'f' + where folder_id = v_source_folder_id and not exists ( + select 1 from cr_items + where parent_id = v_source_folder_id + and content_type = 'content_folder'); + + -- update the destination + update cr_folders set has_child_folders = 't' + where folder_id = target_folder_id; + +end move; + +-- * make sure that subfolders are allowed in this folder +-- * creates new folder in the target folder with the same attributes +-- as the old one +-- * copies all contents of folder to the new one +procedure copy ( + folder_id in cr_folders.folder_id%TYPE, + target_folder_id in cr_folders.folder_id%TYPE, + creation_user in acs_objects.creation_user%TYPE, + creation_ip in acs_objects.creation_ip%TYPE default null, + name in cr_items.name%TYPE default null +) is + v_valid_folders_p integer := 0; + v_current_folder_id cr_folders.folder_id%TYPE; + v_name cr_items.name%TYPE; + v_label cr_folders.label%TYPE; + v_description cr_folders.description%TYPE; + v_new_folder_id cr_folders.folder_id%TYPE; + + -- cursor: items in the folder + cursor c_folder_contents_cur is + select + item_id + from + cr_items + where + parent_id = copy.folder_id; + +begin + + select + count(*) + into + v_valid_folders_p + from + cr_folders + where + folder_id = copy.target_folder_id + or + folder_id = copy.folder_id; + + select + parent_id + into + v_current_folder_id + from + cr_items + where + item_id = copy.folder_id; + + if folder_id = content_item.get_root_folder or folder_id = content_template.get_root_folder or target_folder_id = folder_id then + v_valid_folders_p := 0; + end if; + + if v_valid_folders_p = 2 then + + -- get the source folder info + select + name, label, description + into + v_name, v_label, v_description + from + cr_items i, cr_folders f + where + f.folder_id = i.item_id + and + f.folder_id = copy.folder_id; + + if is_sub_folder(folder_id, target_folder_id) ^= 't' or v_current_folder_id != copy.target_folder_id or (v_name != copy.name and copy.name is not null) then + if copy.name is not null then + v_name := copy.name; + end if; + -- create the new folder + v_new_folder_id := content_folder.new( + parent_id => copy.target_folder_id, + name => nvl(copy.name,v_name), + label => v_label, + description => v_description, + creation_user => copy.creation_user, + creation_ip => copy.creation_ip + ); + + -- copy attributes of original folder + insert into cr_folder_type_map ( + folder_id, content_type + ) select + v_new_folder_id, content_type + from + cr_folder_type_map map + where + folder_id = copy.folder_id + and + -- do not register content_type if it is already registered + not exists ( select 1 from cr_folder_type_map + where folder_id = v_new_folder_id + and content_type = map.content_type ) ; + + -- for each item in the folder, copy it + for v_folder_contents_val in c_folder_contents_cur loop + + content_item.copy( + item_id => v_folder_contents_val.item_id, + target_folder_id => v_new_folder_id, + creation_user => copy.creation_user, + creation_ip => copy.creation_ip + ); + + end loop; + + end if; + end if; +end copy; + + + + + +-- returns 1 if the item_id passed in is a folder +function is_folder ( + item_id in cr_items.item_id%TYPE +) return char is + + v_folder_p varchar2(1) := 'f'; + +begin + + select 't' into v_folder_p from cr_folders + where folder_id = item_id; + + return v_folder_p; + +exception + when NO_DATA_FOUND then + return 'f'; + +end is_folder; + +-- target_folder_id is the possible sub folder +function is_sub_folder ( + folder_id in cr_folders.folder_id%TYPE, + target_folder_id in cr_folders.folder_id%TYPE +) return char +is + cursor c_tree_cur is + select + parent_id + from + cr_items + connect by + prior parent_id = item_id + start with + item_id = target_folder_id; + + v_parent_id integer := 0; + v_sub_folder_p char := 'f'; + +begin + + if folder_id = content_item.get_root_folder or + folder_id = content_template.get_root_folder then + v_sub_folder_p := 't'; + end if; + + -- Get the parents + open c_tree_cur; + while v_parent_id <> folder_id loop + fetch c_tree_cur into v_parent_id; + exit when c_tree_cur%NOTFOUND; + end loop; + close c_tree_cur; + + if v_parent_id ^= 0 then + v_sub_folder_p := 't'; + end if; + + return v_sub_folder_p; + +end is_sub_folder; + +function is_empty ( + folder_id in cr_folders.folder_id%TYPE +) return varchar2 +is + v_return varchar2(1); +begin + + select + decode( count(*), 0, 't', 'f' ) into v_return + from + cr_items + where + parent_id = is_empty.folder_id; + + return v_return; +end is_empty; + + +procedure register_content_type ( + folder_id in cr_folders.folder_id%TYPE, + content_type in cr_folder_type_map.content_type%TYPE, + include_subtypes in varchar2 default 'f' +) is + + v_is_registered varchar2(100); + +begin + + if register_content_type.include_subtypes = 'f' then + + v_is_registered := is_registered( + folder_id => register_content_type.folder_id, + content_type => register_content_type.content_type, + include_subtypes => 'f' ); + + if v_is_registered = 'f' then + + insert into cr_folder_type_map ( + folder_id, content_type + ) values ( + register_content_type.folder_id, + register_content_type.content_type + ); + + end if; + + else + + insert into cr_folder_type_map ( + folder_id, content_type + ) select + register_content_type.folder_id, object_type + from + acs_object_types + where + object_type ^= 'acs_object' + and + not exists (select 1 from cr_folder_type_map + where folder_id = register_content_type.folder_id + and content_type = acs_object_types.object_type) + connect by + prior object_type = supertype + start with + object_type = register_content_type.content_type; + + end if; + +end register_content_type; + +procedure unregister_content_type ( + folder_id in cr_folders.folder_id%TYPE, + content_type in cr_folder_type_map.content_type%TYPE, + include_subtypes in varchar2 default 'f' +) is +begin + + if unregister_content_type.include_subtypes = 'f' then + delete from cr_folder_type_map + where folder_id = unregister_content_type.folder_id + and content_type = unregister_content_type.content_type; + else + delete from cr_folder_type_map + where folder_id = unregister_content_type.folder_id + and content_type in (select object_type + from acs_object_types + where object_type ^= 'acs_object' + connect by prior object_type = supertype + start with + object_type = unregister_content_type.content_type); + + end if; + +end unregister_content_type; + + + + +function is_registered ( + folder_id in cr_folders.folder_id%TYPE, + content_type in cr_folder_type_map.content_type%TYPE, + include_subtypes in varchar2 default 'f' +) return varchar2 +is + v_is_registered integer; + cursor c_subtype_cur is + select + object_type + from + acs_object_types + where + object_type ^= 'acs_object' + connect by + prior object_type = supertype + start with + object_type = is_registered.content_type; + +begin + + if is_registered.include_subtypes = 'f' then + select + count(1) + into + v_is_registered + from + cr_folder_type_map + where + folder_id = is_registered.folder_id + and + content_type = is_registered.content_type; + + else + + v_is_registered := 1; + for v_subtype_val in c_subtype_cur loop + if is_registered(is_registered.folder_id, + v_subtype_val.object_type, 'f') = 'f' then + v_is_registered := 0; + end if; + end loop; + end if; + + if v_is_registered = 0 then + return 'f'; + else + return 't'; + end if; + +end is_registered; + +function get_label ( + folder_id in cr_folders.folder_id%TYPE +) return cr_folders.label%TYPE +is + v_label cr_folders.label%TYPE; +begin + + select + label into v_label + from + cr_folders + where + folder_id = get_label.folder_id; + + return v_label; +end get_label; + + +function get_index_page ( + folder_id in cr_folders.folder_id%TYPE +) return cr_items.item_id%TYPE +is + v_folder_id cr_folders.folder_id%TYPE; + v_index_page_id cr_items.item_id%TYPE; +begin + + -- if the folder is a symlink, resolve it + if content_symlink.is_symlink( get_index_page.folder_id ) = 't' then + v_folder_id := content_symlink.resolve( get_index_page.folder_id ); + else + v_folder_id := get_index_page.folder_id; + end if; + + select + item_id into v_index_page_id + from + cr_items + where + parent_id = v_folder_id + and + name = 'index' + and + content_item.is_subclass( + content_item.get_content_type( content_symlink.resolve(item_id) ), + 'content_folder') = 'f' + and + content_item.is_subclass( + content_item.get_content_type( content_symlink.resolve(item_id) ), + 'content_template') = 'f'; + + return v_index_page_id; + +exception when no_data_found then + return null; +end get_index_page; + +function is_root ( + folder_id in cr_folders.folder_id%TYPE +) return char is + v_is_root char(1); +begin + + select decode(parent_id, 0, 't', 'f') into v_is_root + from cr_items where item_id = is_root.folder_id; + + return v_is_root; +end is_root; + +end content_folder; +/ +show errors + Index: openacs-4/packages/acs-content-repository/sql/postgresql/upgrade/upgrade-5.1.1-5.1.2.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/sql/postgresql/upgrade/Attic/upgrade-5.1.1-5.1.2.sql,v diff -u -N --- openacs-4/packages/acs-content-repository/sql/postgresql/upgrade/upgrade-5.1.1-5.1.2.sql 5 Jun 2004 14:12:32 -0000 1.2 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,67 +0,0 @@ -create or replace function content_item__edit_name (integer,varchar) -returns integer as ' -declare - edit_name__item_id alias for $1; - edit_name__name alias for $2; - exists_id integer; -begin - select - item_id - into - exists_id - from - cr_items - where - name = edit_name__name - and - parent_id = (select - parent_id - from - cr_items - where - item_id = edit_name__item_id); - if NOT FOUND then - update cr_items - set name = edit_name__name - where item_id = edit_name__item_id; - else - if exists_id != edit_name__item_id then - raise EXCEPTION ''-20000: An item with the name % already exists in this directory.'', edit_name__name; - end if; - end if; - - return 0; -end;' language 'plpgsql'; - -create or replace function content_folder__edit_name (integer,varchar,varchar,varchar) -returns integer as ' -declare - edit_name__folder_id alias for $1; - edit_name__name alias for $2; -- default null - edit_name__label alias for $3; -- default null - edit_name__description alias for $4; -- default null - v_name_already_exists_p integer; -begin - - if edit_name__name is not null and edit_name__name != '''' then - PERFORM content_item__edit_name(edit_name__folder_id, edit_name__name); - end if; - - if edit_name__label is not null and edit_name__label != '''' and - edit_name__description is not null and edit_name__description != '''' then - - update cr_folders - set label = edit_name__label, - description = edit_name__description - where folder_id = edit_name__folder_id; - - else if(edit_name__label is not null and edit_name__label != '''') and - (edit_name__description is null or edit_name__description = '''') then - update cr_folders - set label = edit_name__label - where folder_id = edit_name__folder_id; - - end if; end if; - - return 0; -end;' language 'plpgsql'; Index: openacs-4/packages/acs-content-repository/sql/postgresql/upgrade/upgrade-5.1.1d2-5.1.1d3.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/sql/postgresql/upgrade/upgrade-5.1.1d2-5.1.1d3.sql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-content-repository/sql/postgresql/upgrade/upgrade-5.1.1d2-5.1.1d3.sql 12 Jul 2004 14:49:35 -0000 1.2 @@ -0,0 +1,67 @@ +create or replace function content_item__edit_name (integer,varchar) +returns integer as ' +declare + edit_name__item_id alias for $1; + edit_name__name alias for $2; + exists_id integer; +begin + select + item_id + into + exists_id + from + cr_items + where + name = edit_name__name + and + parent_id = (select + parent_id + from + cr_items + where + item_id = edit_name__item_id); + if NOT FOUND then + update cr_items + set name = edit_name__name + where item_id = edit_name__item_id; + else + if exists_id != edit_name__item_id then + raise EXCEPTION ''-20000: An item with the name % already exists in this directory.'', edit_name__name; + end if; + end if; + + return 0; +end;' language 'plpgsql'; + +create or replace function content_folder__edit_name (integer,varchar,varchar,varchar) +returns integer as ' +declare + edit_name__folder_id alias for $1; + edit_name__name alias for $2; -- default null + edit_name__label alias for $3; -- default null + edit_name__description alias for $4; -- default null + v_name_already_exists_p integer; +begin + + if edit_name__name is not null and edit_name__name != '''' then + PERFORM content_item__edit_name(edit_name__folder_id, edit_name__name); + end if; + + if edit_name__label is not null and edit_name__label != '''' and + edit_name__description is not null and edit_name__description != '''' then + + update cr_folders + set label = edit_name__label, + description = edit_name__description + where folder_id = edit_name__folder_id; + + else if(edit_name__label is not null and edit_name__label != '''') and + (edit_name__description is null or edit_name__description = '''') then + update cr_folders + set label = edit_name__label + where folder_id = edit_name__folder_id; + + end if; end if; + + return 0; +end;' language 'plpgsql'; Index: openacs-4/packages/acs-content-repository/tcl/filter-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/tcl/filter-procs.tcl,v diff -u -N -r1.21 -r1.22 --- openacs-4/packages/acs-content-repository/tcl/filter-procs.tcl 11 Jul 2004 19:11:03 -0000 1.21 +++ openacs-4/packages/acs-content-repository/tcl/filter-procs.tcl 12 Jul 2004 14:49:36 -0000 1.22 @@ -116,6 +116,7 @@ } + ad_proc -public content::get_template_url {} { variable template_url Index: openacs-4/packages/acs-core-docs/acs-core-docs.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/acs-core-docs.info,v diff -u -N -r1.17 -r1.18 --- openacs-4/packages/acs-core-docs/acs-core-docs.info 17 May 2004 15:14:45 -0000 1.17 +++ openacs-4/packages/acs-core-docs/acs-core-docs.info 12 Jul 2004 14:49:36 -0000 1.18 @@ -7,7 +7,7 @@ t t - + OpenACS Documentation Team Documentation for the OpenACS Core. 2004-04-29 @@ -18,7 +18,7 @@ Static HTML documentation for the OpenACS core (includes the DocBook sources). - + Index: openacs-4/packages/acs-core-docs/www/xml/engineering-standards/eng-standards-versioning.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/xml/engineering-standards/eng-standards-versioning.xml,v diff -u -N -r1.7 -r1.8 --- openacs-4/packages/acs-core-docs/www/xml/engineering-standards/eng-standards-versioning.xml 22 Jun 2004 12:54:18 -0000 1.7 +++ openacs-4/packages/acs-core-docs/www/xml/engineering-standards/eng-standards-versioning.xml 12 Jul 2004 14:49:47 -0000 1.8 @@ -129,7 +129,7 @@ - + Naming Database Upgrade Scripts Database upgrade scripts must be named very precisely in order for the Package Manager to run the correct script at the correct time. Index: openacs-4/packages/acs-core-docs/www/xml/for-everyone/release-notes.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/xml/for-everyone/release-notes.xml,v diff -u -N -r1.17 -r1.18 --- openacs-4/packages/acs-core-docs/www/xml/for-everyone/release-notes.xml 20 Apr 2004 21:12:38 -0000 1.17 +++ openacs-4/packages/acs-core-docs/www/xml/for-everyone/release-notes.xml 12 Jul 2004 14:49:47 -0000 1.18 @@ -33,8 +33,44 @@ END OF TEMPLATE --> + + Release 5.1.1 + + + This is the first release using the newest adjustment to the versioning convention. The OpenACS 5.1.1 tag will apply to OpenACS core as well as to the most recent released version of every package, including .LRN. + + + Translations syncronized with the translation server. + + + + Bug + 1519 fixed. This involved renaming all catalog + files for ch_ZH, TH_TH, AR_EG, AR_LB, ms_my, RO_RO, FA_IR, + and HR_HR. If you work with any of those locales, you + should do a full catalog export and then import (via + /acs-lang/admin) after + upgrading acs-lang. (And, of course, make a backup of both + the files and database before upgrading.) + + + Other bug fixes since 5.1.0: 1785, + 1793, + and over a dozen additional bug fixes. + + + For a complete change list, see the Change list since + 5.0.0 in Changelog. + + + + + - Version 5.1.0 + Release 5.1.0 @@ -49,7 +85,7 @@ - Version 5.0.4 + Release 5.0.4 @@ -59,7 +95,7 @@ - Version 5.0.3 + Release 5.0.3 @@ -70,7 +106,7 @@ - Version 5.0.2 + Release 5.0.2 @@ -86,7 +122,7 @@ - Version 5.0.1 + Release 5.0.1 All work on the translation server from 7 Nov 2003 to 7 Feb 2004 is now included in catalogs. @@ -104,7 +140,7 @@ - Version 5.0.0 + Release 5.0.0 This is OpenACS 5.0.0. This version contains no known security, data loss, or crashing bugs, nor any bugs judged release blockers. This version has received manual testing. It has passed current automated testing, which is not comprehensive. This release contains work done on the translation server http://translate.openacs.org through 7 Nov 2003. @@ -275,24 +311,30 @@ - Version 4.6.3 + Release 4.6.3 Release Notes for 4.6.3 - Version 4.6.2 + Release 4.6.2 Release Notes for 4.6.2 - Version 4.6 + Release 4.6 Release Notes for 4.6 - Version 4.5 + Release 4.5 Release Notes for 4.5 + + + Changelog + ChangeLog missing + + Index: openacs-4/packages/acs-core-docs/www/xml/install-guide/maintenance.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/xml/install-guide/maintenance.xml,v diff -u -N -r1.19 -r1.20 --- openacs-4/packages/acs-core-docs/www/xml/install-guide/maintenance.xml 6 Jul 2004 19:04:29 -0000 1.19 +++ openacs-4/packages/acs-core-docs/www/xml/install-guide/maintenance.xml 12 Jul 2004 14:49:47 -0000 1.20 @@ -445,7 +445,7 @@ /usr/local/pgsql/bin/psql -f /var/lib/aolserver/service0-dev/packages/acs-kernel/sql/postgresql/postgresql.sql service0 mv /var/lib/aolserver/service0/database-backup/service0-nightly-backup.dmp.gz /var/lib/aolserver/service0-dev/database-backup/service0-nightly-backup-old.dmp.gz /bin/gunzip /var/lib/aolserver/service0-dev/database-backup/service0-nightly-backup.dmp.gz -/usr/bin/perl -pi -e 's/^\\connect service0$/\\connect service0-dev/' /var/lib/aolserver/service0-dev/database-backup/service0-nightly-backup.dmp +/usr/bin/perl -pi -e "s/^\\connect service0$/\\connect service0-dev/" /var/lib/aolserver/service0-dev/database-backup/service0-nightly-backup.dmp /usr/local/pgsql/bin/psql service0-dev < /var/lib/aolserver/service0-dev/database-backup/service0-nightly-backup.dmp /usr/local/bin/svc -u /service/service0-dev /bin/gzip /var/lib/aolserver/service0-dev/database-backup/service0-nightly-backup-old.dmp @@ -809,6 +809,50 @@ - ($Id$) + + Creating an appropriate tuning and monitoring environment + + The first task is to create an appropriate environment for finding out + what is going on inside Oracle. Oracle provides Statspack, a package to + monitor and save the state of the v$ performance views. These reports + help finding severe problems by exposing summary data about the Oracle + wait interface, executed queries. You'll find the installation + instructions in $ORACLE_HOME/rdbms/admin/spdoc.txt. Follow the + instructions carefully and take periodic snapshots, this way you'll be + able to look at historical performance data. + + + + Also turn on the timed_statistics in your init.ora file, so that + Statspack reports (and all other Oracle reports) are timed, which makes + them a lot more meaningful. The overhead of timing data is about 1% per + Oracle Support information. + + + + + To be able to get a overview of how Oracle executes a particular query, + install "autotrace". I usually follow the instructions here http://asktom.oracle.com/~tkyte/article1/autotrace.html. + + + Make sure, that the Oracle CBO works with adequate statistics + + + The Oracle Cost Based optimizer is a piece of software that tries to find + the "optimal" execution plan for a given SQL statement. For that it + estimates the costs of running a SQL query in a particular way (by default + up to 80.000 permutations are being tested in a Oracle 8i). To get an + adequate cost estimate, the CBO needs to have adequate statistics. For + that Oracle supplies the dbms_stats + package. + + + + + + + ($Id$) Index: openacs-4/packages/acs-kernel/acs-kernel.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/acs-kernel.info,v diff -u -N -r1.67 -r1.68 --- openacs-4/packages/acs-kernel/acs-kernel.info 29 Jun 2004 10:17:37 -0000 1.67 +++ openacs-4/packages/acs-kernel/acs-kernel.info 12 Jul 2004 14:49:47 -0000 1.68 @@ -16,6 +16,11 @@ OpenACS The OpenACS kernel contains the core datamodel create and drop scripts for such things as objects, groups, partiies and the supporting PL/SQL and PL/pgSQL procedures. + + + 2 + + Index: openacs-4/packages/acs-kernel/sql/oracle/groups-body-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/groups-body-create.sql,v diff -u -N -r1.13 -r1.14 --- openacs-4/packages/acs-kernel/sql/oracle/groups-body-create.sql 12 Mar 2004 18:48:49 -0000 1.13 +++ openacs-4/packages/acs-kernel/sql/oracle/groups-body-create.sql 12 Jul 2004 14:49:48 -0000 1.14 @@ -799,15 +799,6 @@ is begin - -- Delete all segments defined for this group - for row in (select segment_id - from rel_segments - where group_id = acs_group.del.group_id) loop - - rel_segment.del(row.segment_id); - - end loop; - -- Delete all the relations of any type to this group for row in (select r.rel_id, t.package_name from acs_rels r, acs_object_types t @@ -817,6 +808,15 @@ execute immediate 'begin ' || row.package_name || '.del(' || row.rel_id || '); end;'; end loop; + -- Delete all segments defined for this group + for row in (select segment_id + from rel_segments + where group_id = acs_group.del.group_id) loop + + rel_segment.del(row.segment_id); + + end loop; + party.del(group_id); end del; Index: openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-5.1.2d1-5.1.2d2.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-5.1.2d1-5.1.2d2.sql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-5.1.2d1-5.1.2d2.sql 12 Jul 2004 14:49:48 -0000 1.2 @@ -0,0 +1,192 @@ +-- PATCH 267, BUG 775 Randy O'Meara +-- procedure delete +-- function acs_group_delete in file +-- acs-kernel/sql/postgresql/groups-body-create.sql attempts to delete +-- associated relational segments before removing any active relations on +-- those segments. The group delete request is not successful and the +-- following error is returned. +-- ERROR: party_member_party_fk referential integrity violation - key in +-- parties still referenced from party_approved_member_map +-- + +create or replace package body acs_group +is + function new ( + group_id in groups.group_id%TYPE default null, + object_type in acs_objects.object_type%TYPE + default 'group', + creation_date in acs_objects.creation_date%TYPE + default sysdate, + creation_user in acs_objects.creation_user%TYPE + default null, + creation_ip in acs_objects.creation_ip%TYPE default null, + email in parties.email%TYPE default null, + url in parties.url%TYPE default null, + group_name in groups.group_name%TYPE, + join_policy in groups.join_policy%TYPE default null, + context_id in acs_objects.context_id%TYPE default null + ) + return groups.group_id%TYPE + is + v_group_id groups.group_id%TYPE; + v_group_type_exists_p integer; + v_join_policy groups.join_policy%TYPE; + begin + v_group_id := + party.new(group_id, object_type, creation_date, creation_user, + creation_ip, email, url, context_id); + + v_join_policy := join_policy; + + -- if join policy wasn't specified, select the default based on group type + if v_join_policy is null then + select count(*) into v_group_type_exists_p + from group_types + where group_type = object_type; + + if v_group_type_exists_p = 1 then + select default_join_policy into v_join_policy + from group_types + where group_type = object_type; + else + v_join_policy := 'open'; + end if; + end if; + + insert into groups + (group_id, group_name, join_policy) + values + (v_group_id, group_name, v_join_policy); + + + -- setup the permissible relationship types for this group + insert into group_rels + (group_rel_id, group_id, rel_type) + select acs_object_id_seq.nextval, v_group_id, g.rel_type + from group_type_rels g + where g.group_type = new.object_type; + + return v_group_id; + end new; + + + procedure del ( + group_id in groups.group_id%TYPE + ) + is + begin + + -- Delete all the relations of any type to this group + for row in (select r.rel_id, t.package_name + from acs_rels r, acs_object_types t + where r.rel_type = t.object_type + and (r.object_id_one = acs_group.del.group_id + or r.object_id_two = acs_group.del.group_id)) loop + execute immediate 'begin ' || row.package_name || '.del(' || row.rel_id || '); end;'; + end loop; + + -- Delete all segments defined for this group + for row in (select segment_id + from rel_segments + where group_id = acs_group.del.group_id) loop + + rel_segment.del(row.segment_id); + + end loop; + + party.del(group_id); + end del; + + function name ( + group_id in groups.group_id%TYPE + ) + return varchar2 + is + group_name varchar2(200); + begin + select group_name + into group_name + from groups + where group_id = name.group_id; + + return group_name; + end name; + + function member_p ( + party_id in parties.party_id%TYPE, + group_id in groups.group_id%TYPE, + cascade_membership char + ) + return char + is + m_result integer; + begin + + if cascade_membership = 't' then + select count(*) + into m_result + from group_member_map + where group_id = member_p.group_id and + member_id = member_p.party_id; + + if m_result > 0 then + return 't'; + end if; + else + select count(*) + into m_result + from acs_rels rels, all_object_party_privilege_map perm + where perm.object_id = rels.rel_id + and perm.privilege = 'read' + and rels.rel_type = 'membership_rel' + and rels.object_id_one = member_p.group_id + and rels.object_id_two = member_p.party_id; + + if m_result > 0 then + return 't'; + end if; + end if; + + return 'f'; + end member_p; + + function check_representation ( + group_id in groups.group_id%TYPE + ) return char + is + result char(1); + begin + result := 't'; + acs_log.notice('acs_group.check_representation', + 'Running check_representation on group ' || group_id); + + if acs_object.check_representation(group_id) = 'f' then + result := 'f'; + end if; + + for c in (select c.rel_id + from acs_rels r, composition_rels c + where r.rel_id = c.rel_id + and r.object_id_one = group_id) loop + if composition_rel.check_representation(c.rel_id) = 'f' then + result := 'f'; + end if; + end loop; + + for m in (select m.rel_id + from acs_rels r, membership_rels m + where r.rel_id = m.rel_id + and r.object_id_one = group_id) loop + if membership_rel.check_representation(m.rel_id) = 'f' then + result := 'f'; + end if; + end loop; + + acs_log.notice('acs_group.check_representation', + 'Done running check_representation on group ' || group_id); + return result; + end; + +end acs_group; +/ +show errors Index: openacs-4/packages/acs-kernel/sql/postgresql/groups-body-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/groups-body-create.sql,v diff -u -N -r1.28 -r1.29 --- openacs-4/packages/acs-kernel/sql/postgresql/groups-body-create.sql 12 Mar 2004 18:48:50 -0000 1.28 +++ openacs-4/packages/acs-kernel/sql/postgresql/groups-body-create.sql 12 Jul 2004 14:49:48 -0000 1.29 @@ -887,14 +887,6 @@ row record; begin - -- Delete all segments defined for this group - for row in select segment_id - from rel_segments - where group_id = delete__group_id - LOOP - PERFORM rel_segment__delete(row.segment_id); - end loop; - -- Delete all the relations of any type to this group for row in select r.rel_id, t.package_name from acs_rels r, acs_object_types t @@ -905,6 +897,14 @@ execute ''select '' || row.package_name || ''__delete('' || row.rel_id || '')''; end loop; + -- Delete all segments defined for this group + for row in select segment_id + from rel_segments + where group_id = delete__group_id + LOOP + PERFORM rel_segment__delete(row.segment_id); + end loop; + PERFORM party__delete(delete__group_id); return 0; Index: openacs-4/packages/acs-kernel/sql/postgresql/upgrade/upgrade-5.1.2d1-5.1.2d2.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/upgrade/upgrade-5.1.2d1-5.1.2d2.sql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-kernel/sql/postgresql/upgrade/upgrade-5.1.2d1-5.1.2d2.sql 12 Jul 2004 14:49:48 -0000 1.2 @@ -0,0 +1,40 @@ +-- PATCH 267, BUG 775 Randy O'Meara +-- procedure delete +-- function acs_group_delete in file +-- acs-kernel/sql/postgresql/groups-body-create.sql attempts to delete +-- associated relational segments before removing any active relations on +-- those segments. The group delete request is not successful and the +-- following error is returned. +-- ERROR: party_member_party_fk referential integrity violation - key in +-- parties still referenced from party_approved_member_map +-- + +create or replace function acs_group__delete (integer) +returns integer as ' +declare + delete__group_id alias for $1; + row record; +begin + + -- Delete all the relations of any type to this group + for row in select r.rel_id, t.package_name + from acs_rels r, acs_object_types t + where r.rel_type = t.object_type + and (r.object_id_one = delete__group_id + or r.object_id_two = delete__group_id) + LOOP + execute ''select '' || row.package_name || ''__delete('' || row.rel_id || '')''; + end loop; + + -- Delete all segments defined for this group + for row in select segment_id + from rel_segments + where group_id = delete__group_id + LOOP + PERFORM rel_segment__delete(row.segment_id); + end loop; + + PERFORM party__delete(delete__group_id); + + return 0; +end;' language 'plpgsql'; Index: openacs-4/packages/acs-lang/acs-lang.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-lang/acs-lang.info,v diff -u -N -r1.39 -r1.40 --- openacs-4/packages/acs-lang/acs-lang.info 29 Jun 2004 10:17:38 -0000 1.39 +++ openacs-4/packages/acs-lang/acs-lang.info 12 Jul 2004 14:49:48 -0000 1.40 @@ -7,7 +7,7 @@ t t - + Peter Marklund OpenACS Internationalization Support. 2004-04-29 @@ -18,7 +18,7 @@ request processor hooks, templating, accessing and managing the message catalog, and locale-specific formatting functions for localizing dates, times, monetary amounts etc. - + Index: openacs-4/packages/acs-mail/acs-mail.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-mail/acs-mail.info,v diff -u -N -r1.21 -r1.22 --- openacs-4/packages/acs-mail/acs-mail.info 17 May 2004 15:14:48 -0000 1.21 +++ openacs-4/packages/acs-mail/acs-mail.info 12 Jul 2004 14:49:48 -0000 1.22 @@ -7,7 +7,7 @@ t t - + Vinod Kurup John Prevost General messaging system, mark II @@ -18,7 +18,7 @@ Provides generic message services, with email sending. The acs-mail-lite package is the prefered interface for new packages and it's anticipated that this package will ultimately be deprecated. - + Index: openacs-4/packages/acs-messaging/acs-messaging.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-messaging/acs-messaging.info,v diff -u -N -r1.17 -r1.18 --- openacs-4/packages/acs-messaging/acs-messaging.info 17 May 2004 15:14:49 -0000 1.17 +++ openacs-4/packages/acs-messaging/acs-messaging.info 12 Jul 2004 14:49:49 -0000 1.18 @@ -7,7 +7,7 @@ t t - + Anukul Kapoor John Prevost Vinod Kurup @@ -19,7 +19,7 @@ Provides generic message services, with email sending. acs-mail-lite and notifications are the prefered packages for delivering this functionality and it is anticipated that this package will ultimately be deprecated. - + Index: openacs-4/packages/acs-reference/acs-reference.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-reference/acs-reference.info,v diff -u -N -r1.18 -r1.19 --- openacs-4/packages/acs-reference/acs-reference.info 17 May 2004 15:14:49 -0000 1.18 +++ openacs-4/packages/acs-reference/acs-reference.info 12 Jul 2004 14:49:49 -0000 1.19 @@ -7,7 +7,7 @@ t t - + Jon Griffin Tools and API for managing refrence data. 2004-04-29 @@ -20,7 +20,7 @@ <li> Running standard reports on this data. <li> Monitoring the usage of reference data. </ul> - + Index: openacs-4/packages/acs-service-contract/acs-service-contract.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-service-contract/acs-service-contract.info,v diff -u -N -r1.25 -r1.26 --- openacs-4/packages/acs-service-contract/acs-service-contract.info 17 May 2004 15:14:49 -0000 1.25 +++ openacs-4/packages/acs-service-contract/acs-service-contract.info 12 Jul 2004 14:49:49 -0000 1.26 @@ -7,7 +7,7 @@ t t - + OpenACS API and UI for service contracts 2004-04-29 @@ -18,7 +18,7 @@ Examples are the contracts used for search which provide a means to get content on a given object and to translate an object_id to a url or the contracts used by dotlrn and new-portals to allow packages to provide portalized panes. - + Index: openacs-4/packages/acs-subsite/tcl/attribute-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-subsite/tcl/attribute-procs.tcl,v diff -u -N -r1.6 -r1.7 --- openacs-4/packages/acs-subsite/tcl/attribute-procs.tcl 10 Sep 2002 22:22:11 -0000 1.6 +++ openacs-4/packages/acs-subsite/tcl/attribute-procs.tcl 12 Jul 2004 14:49:49 -0000 1.7 @@ -197,7 +197,7 @@ switch $datatype { "string" { set type "varchar(1000)" } "boolean" { set type "char(1)" - set constraint "[generate_constraint $table $column "ck"] check ($column in ('t','f'))" } + set constraint "[plsql_utility::generate_constraint_name $table $column "ck"] check ($column in ('t','f'))" } "number" { set type "number" } "money" { set type "number (12,2)" } "date" { set type "date" } Index: openacs-4/packages/acs-subsite/www/register/account-closed.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-subsite/www/register/account-closed.tcl,v diff -u -N -r1.3 -r1.4 --- openacs-4/packages/acs-subsite/www/register/account-closed.tcl 17 May 2004 15:14:53 -0000 1.3 +++ openacs-4/packages/acs-subsite/www/register/account-closed.tcl 12 Jul 2004 14:49:49 -0000 1.4 @@ -6,6 +6,6 @@ {message:allhtml ""} } -set page_title $message +set page_title [ad_convert_to_text -html_p t -- $message] set context [list $page_title] Index: openacs-4/packages/acs-tcl/tcl/html-email-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/html-email-procs.tcl,v diff -u -N -r1.4 -r1.5 --- openacs-4/packages/acs-tcl/tcl/html-email-procs.tcl 7 Nov 2003 17:43:33 -0000 1.4 +++ openacs-4/packages/acs-tcl/tcl/html-email-procs.tcl 12 Jul 2004 14:49:49 -0000 1.5 @@ -25,135 +25,117 @@ to be unable to handle utf-8 encoding). A future version of this proc should probably support an alternative charset argument or switch. } { - + ## JCD: we moved these into -procs.tcl files so they get + ## sourced when we bootstrap. # this is always called from a scheduled proc - set r_dir [acs_root_dir]/packages/acs-tcl/tcl - source $r_dir/base64.tcl - source $r_dir/md5.tcl - source $r_dir/mime.tcl + # set r_dir [acs_root_dir]/packages/acs-tcl/tcl + #source $r_dir/base64.tcl + #source $r_dir/md5.tcl + #source $r_dir/mime.tcl package require mime - # since mime tries to treat =xx as a hex ascii code, replace any - # equals signs with "=3d" (mime encoding of equals sign) - regsub -all "=" $text_body "=3d" text_body - regsub -all "=" $html_body "=3d" html_body_for_non_base64 - # convert text to charset set encoding [ns_encodingforcharset $charset] if {[lsearch [encoding names] $encoding] != -1} { set html_body [encoding convertto $encoding $html_body] set text_body [encoding convertto $encoding $text_body] - } else { + } else { ns_log error "ad_html_sendmail: unknown charset passed in ($charset)" - } + } # build body - set base64_html_part [mime::initialize -canonical text/html \ - -param [list charset $charset] \ - -encoding base64 \ - -string $html_body] + + ## JCD: I fail to see why you would want both a base64 and a quoted-printable + ## version of html part of this email. I am removing the base64 version. + ## set base64_html_part [mime::initialize -canonical text/html -param [list charset $charset] -encoding base64 -string $html_body] set html_part [mime::initialize -canonical text/html \ - -param [list charset $charset] \ - -encoding quoted-printable \ - -string $html_body_for_non_base64] + -param [list charset $charset] \ + -encoding quoted-printable \ + -string $html_body] set text_part [mime::initialize -canonical text/plain \ - -param [list charset $charset] \ - -encoding quoted-printable \ - -string $text_body] - #It works better without 'charset'! - # set multi_part [mime::initialize -canonical multipart/alternative \ - # -param [list charset $charset] \ - # -parts [list $text_part $html_part]] - set multi_part [mime::initialize -canonical multipart/alternative \ - -parts [list $text_part $base64_html_part $html_part]] + -param [list charset $charset] \ + -encoding quoted-printable \ + -string $text_body] - # this gives us a complete mime message, minus the headers because - # we don't pass any in. This code is designed to send a fully-formed - # message out through an SMTP socket, but we're not doing that so we - # have to hijack the process a bit. - set mime_body [mime::buildmessage $multi_part] + set multi_part [mime::initialize \ + -canonical multipart/alternative \ + -parts [list $text_part $html_part]] - # the first three lines of the message are special; we need to grab - # the info, add it to the message headers, and discard the lines - set lines [split $mime_body \n] - set message_data [ns_set new] + # this gives us a complete mime message, minus the headers because + # we don't pass any in. This code is designed to send a fully-formed + # message out through an SMTP socket, but we're not doing that so we + # have to hijack the process a bit. + set mime_body [mime::buildmessage $multi_part] - # get mime version - regexp {MIME-Version: (.*)} [lindex $lines 0] junk mime_version - ns_set put $message_data MIME-Version $mime_version - # the content id - regexp {Content-ID: (.*)} [lindex $lines 1] junk content_id - ns_set put $message_data Content-ID $content_id - # and the content type and boundary - regexp {Content-Type: (.*)} [lindex $lines 2] junk content_type - set content_type "$content_type\n[lindex $lines 3]" - ns_set put $message_data Content-Type $content_type + # the first three lines of the message are special; we need to grab + # the info, add it to the message headers, and discard the lines + set lines [split $mime_body \n] + set message_data [ns_set new] - # the rest of the lines form the message body. We strip off the last - # line, which is the last boundary, because ns_sendmail seems to be - # adding another one on for us. - ns_set put $message_data body [join [lrange $lines 4 [expr [llength $lines] - 3]] \n] + # get mime version + regexp {MIME-Version: (.*)} [lindex $lines 0] junk mime_version + ns_set put $message_data MIME-Version $mime_version + # the content id + regexp {Content-ID: (.*)} [lindex $lines 1] junk content_id + ns_set put $message_data Content-ID $content_id + # and the content type and boundary + regexp {Content-Type: (.*)} [lindex $lines 2] junk content_type + set content_type "$content_type\n[lindex $lines 3]" + ns_set put $message_data Content-Type $content_type - return $message_data + # the rest of the lines form the message body. We strip off the last + # line, which is the last boundary, because ns_sendmail seems to be + # adding another one on for us. + + ## JCD: not anymore. maybe an aolserver 3.3 bug? removing the clipping. + ns_set put $message_data body [join [lrange $lines 4 end] \n] + + return $message_data } ad_proc parse_incoming_email { - message + message } { - Takes an incoming message and splits it into parts. The main goal - of this proc is to return something that can be stuffed into the - database somewhere, such as a forum message. Since we aggressively - filter HTML, the HTML tags are stripped out of the returned content. + Takes an incoming message and splits it into parts. The main goal + of this proc is to return something that can be stuffed into the + database somewhere, such as a forum message. Since we aggressively + filter HTML, the HTML tags are stripped out of the returned content. - The message may have only plain text, plain text and HTML, or plain - text and something else (Apple Mail uses text/enhanced, for example). - To make our lives simpler we support only text/html as a special case; - in all other cases the plain text is returned. + The message may have only plain text, plain text and HTML, or plain + text and something else (Apple Mail uses text/enhanced, for example). + To make our lives simpler we support only text/html as a special case; + in all other cases the plain text is returned. } { - # look for the files we need. If they aren't there, we can't do anything - # and will just return the message as-is (cringe) - set source_dir [acs_root_dir]/packages/acs-tcl/tcl - if { ![file exists $source_dir/base64-procs.tcl] || - ![file exists $source_dir/md5-procs.tcl] || - ![file exists $source_dir/mime-procs.tcl] } { - return $message - } + set mime [mime::initialize -string $message] + set content [mime::getproperty $mime content] - source $source_dir/base64-procs.tcl - source $source_dir/md5-procs.tcl - source $source_dir/mime-procs.tcl - package require mime + if { [string first "multipart" $content] != -1 } { + set parts [mime::getproperty $mime parts] + } else { + set parts [list $mime] + } - set mime [mime::initialize -string $message] - set content [mime::getproperty $mime content] + foreach part $parts { + switch [mime::getproperty $part content] { + "text/plain" { + set plain [mime::getbody $part] + } + "text/html" { + set html [mime::getbody $part] + } + } + } - if { [string first "multipart" $content] != -1 } { - set parts [mime::getproperty $mime parts] - } else { - set parts [list $mime] - } + if { [info exists html] } { + set body [ad_html_to_text -- $html] + } elseif { [info exists plain] } { + set body $plain + } else { + set body $message + } - foreach part $parts { - switch [mime::getproperty $part content] { - "text/plain" { - set plain [mime::getbody $part] - } - "text/html" { - set html [mime::getbody $part] - } - } - } - - if { [info exists html] } { - set body [ad_html_to_text -- $html] - } elseif { [info exists plain] } { - set body $plain - } else { - set body $message - } - - mime::finalize $mime -subordinates all - return $body + mime::finalize $mime -subordinates all + return $body } Index: openacs-4/packages/acs-tcl/tcl/request-processor-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/request-processor-procs.tcl,v diff -u -N -r1.65 -r1.66 --- openacs-4/packages/acs-tcl/tcl/request-processor-procs.tcl 5 Jul 2004 13:25:26 -0000 1.65 +++ openacs-4/packages/acs-tcl/tcl/request-processor-procs.tcl 12 Jul 2004 14:49:50 -0000 1.66 @@ -484,10 +484,10 @@ } { set path "[acs_package_root_dir [lindex [ns_conn urlv] 1]]/www/resources/[join [lrange [ns_conn urlv] 2 end] /]" - if { ![file exists $path] } { + if { ![file isfile $path] } { set path "[acs_root_dir]/www/resources/[join [lrange [ns_conn urlv] 1 end] /]" } - if { [file exists $path] } { + if { [file isfile $path] } { ns_returnfile 200 [ns_guesstype $path] $path return filter_return } else { Index: openacs-4/packages/acs-templating/resources/lists/list.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/resources/lists/list.adp,v diff -u -N -r1.4 -r1.5 --- openacs-4/packages/acs-templating/resources/lists/list.adp 17 May 2004 15:14:57 -0000 1.4 +++ openacs-4/packages/acs-templating/resources/lists/list.adp 12 Jul 2004 14:49:50 -0000 1.5 @@ -8,7 +8,13 @@ -
    + + + + + + + @list_properties.bulk_action_export_chunk;noquote@ Index: openacs-4/packages/acs-templating/resources/lists/table.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/resources/lists/table.adp,v diff -u -N -r1.9 -r1.10 --- openacs-4/packages/acs-templating/resources/lists/table.adp 17 May 2004 15:14:57 -0000 1.9 +++ openacs-4/packages/acs-templating/resources/lists/table.adp 12 Jul 2004 14:49:50 -0000 1.10 @@ -1,7 +1,12 @@ - + + + + + + @list_properties.bulk_action_export_chunk;noquote@ Index: openacs-4/packages/acs-templating/tcl/currency-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/tcl/currency-procs.tcl,v diff -u -N -r1.8 -r1.9 --- openacs-4/packages/acs-templating/tcl/currency-procs.tcl 26 Jan 2004 15:39:46 -0000 1.8 +++ openacs-4/packages/acs-templating/tcl/currency-procs.tcl 12 Jul 2004 14:49:50 -0000 1.9 @@ -234,7 +234,9 @@ } } -ad_proc -public template::widget::currency { element_reference tag_attributes } { +ad_proc -public template::widget::currency { + element_reference tag_attributes {mode edit} +} { upvar $element_reference element @@ -259,13 +261,19 @@ set i 0 foreach format_property $format { set value [lindex $values 0] - set values [lrange $values 1 end] - if { $i == 0 || $i == 2 || $i == 4 } { - append output "$format_property \n" - } elseif { $i == 1 || $i == 3 } { - append output "\n" - } - incr i + set values [lrange $values 1 end] + set trailing_zero "" + if { $i == 3 } { + set trailing_zero [string range [string repeat "0" $format_property] [string length $value] end] + } + if { $i == 0 || $i == 2 || $i == 4 } { + append output "$format_property" + } elseif { [string equal $element(mode) "edit"] && ($i == 1 || $i == 3) } { + append output "\n" + } else { + append output "$value$trailing_zero" + } + incr i } append output "\n" Index: openacs-4/packages/acs-templating/tcl/date-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/tcl/date-procs.tcl,v diff -u -N -r1.32 -r1.33 --- openacs-4/packages/acs-templating/tcl/date-procs.tcl 6 Jul 2004 19:57:51 -0000 1.32 +++ openacs-4/packages/acs-templating/tcl/date-procs.tcl 12 Jul 2004 14:49:50 -0000 1.33 @@ -411,6 +411,15 @@ } { + # if value is an empty string, just return the date that was + # passed in, otherwise this procedure will fail. + # This is needed for the automated sql/linear conversion used by + # ad_form. + + if {[empty_string_p $value]} { + return $date + } + # Erase leading zeroes from the value, but make sure that 00 # is not completely erased - but only for single-element properties Index: openacs-4/packages/auth-ldap/tcl/auth-ldap-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/auth-ldap/tcl/auth-ldap-procs.tcl,v diff -u -N -r1.7 -r1.8 --- openacs-4/packages/auth-ldap/tcl/auth-ldap-procs.tcl 30 Jun 2004 18:02:57 -0000 1.7 +++ openacs-4/packages/auth-ldap/tcl/auth-ldap-procs.tcl 12 Jul 2004 14:49:52 -0000 1.8 @@ -111,7 +111,12 @@ foreach { attribute value } [lindex $search_result 0] { if { [string equal $attribute $element] } { # Values are always wrapped in an additional list - return [lindex $value 0] + # not for dn (roc) + if [string equal $element "dn"] { + return $value + } else { + return [lindex $value 0] + } } } @@ -224,6 +229,7 @@ username password {parameters {}} + {authority_id {}} } { Implements the Authenticate operation of the auth_authentication service contract for LDAP. @@ -296,6 +302,7 @@ old_password new_password {parameters {}} + {authority_id {}} } { Implements the ChangePassword operation of the auth_password service contract for LDAP. @@ -351,6 +358,7 @@ ad_proc -private auth::ldap::password::ResetPassword { username parameters + {authority_id {}} } { Implements the ResetPassword operation of the auth_password service contract for LDAP. Index: openacs-4/packages/auth-pam/tcl/auth-pam-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/auth-pam/tcl/auth-pam-procs.tcl,v diff -u -N -r1.1 -r1.2 --- openacs-4/packages/auth-pam/tcl/auth-pam-procs.tcl 17 Sep 2003 11:30:08 -0000 1.1 +++ openacs-4/packages/auth-pam/tcl/auth-pam-procs.tcl 12 Jul 2004 14:49:52 -0000 1.2 @@ -65,6 +65,7 @@ username password {parameters {}} + {authority_id {}} } { Implements the Authenticate operation of the auth_authentication service contract for PAM. @@ -126,6 +127,7 @@ old_password new_password {parameters {}} + {authority_id {}} } { Implements the ChangePassword operation of the auth_password service contract for PAM. @@ -151,6 +153,7 @@ ad_proc -private auth::pam::password::ResetPassword { username parameters + {authority_id {}} } { Implements the ResetPassword operation of the auth_password service contract for PAM. Index: openacs-4/packages/bookmarks/bookmarks.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bookmarks/bookmarks.info,v diff -u -N -r1.25 -r1.26 --- openacs-4/packages/bookmarks/bookmarks.info 11 Dec 2003 21:39:58 -0000 1.25 +++ openacs-4/packages/bookmarks/bookmarks.info 12 Jul 2004 14:49:52 -0000 1.26 @@ -7,7 +7,7 @@ ff - + oracle postgresql Index: openacs-4/packages/bookmarks/sql/postgresql/bookmarks-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bookmarks/sql/postgresql/bookmarks-create.sql,v diff -u -N -r1.24 -r1.25 --- openacs-4/packages/bookmarks/sql/postgresql/bookmarks-create.sql 29 Jun 2004 10:17:47 -0000 1.24 +++ openacs-4/packages/bookmarks/sql/postgresql/bookmarks-create.sql 12 Jul 2004 14:49:52 -0000 1.25 @@ -114,6 +114,50 @@ return tree_sortkey from bm_bookmarks where bookmark_id = p_bookmark_id; end;' language 'plpgsql'; +create or replace function bm_bookmarks_get_folder_names( + -- + -- Returns the names of the parent folders of a bookmark, joined + -- together with an optional separator. + -- + -- @author Gabriel Burca (gburca-openacs@ebixio.com) + -- + + integer, -- bm_bookmarks.bookmark_id%TYPE + text -- Optional separator (set to NULL to use the default) +) returns text as ' +declare + p_bookmark_id alias for $1; + p_sep alias for $2; -- optional separator to use + v_rec record; + tree_key varbit; + separator text default '' :: ''; + folder_names text default ''''; -- If NULL, the || in the LOOP fails +begin + tree_key := bm_bookmarks_get_tree_sortkey(p_bookmark_id); + + -- Level 1 is the root folder, level 2 is items in the root folder + if tree_level(tree_key) <= 2 then + return ''''; + end if; + + if p_sep is not null then + separator := p_sep; + end if; + + for v_rec in select local_title + from bm_bookmarks + where tree_sortkey in + (select tree_ancestor_keys( -- get all parent folders up to level 2 + tree_ancestor_key( -- start with the parent folder key + tree_key, tree_level(tree_key) - 1), 2 ) ) + order by tree_sortkey + LOOP + folder_names := folder_names || separator || v_rec.local_title; + end LOOP; + + return trim(leading separator from folder_names); +end;' language 'plpgsql'; + create function bm_bookmarks_insert_tr () returns opaque as ' declare v_parent_sk varbit default null; Index: openacs-4/packages/bookmarks/sql/postgresql/upgrade/upgrade-5.0d1-5.0d2.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bookmarks/sql/postgresql/upgrade/upgrade-5.0d1-5.0d2.sql,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/bookmarks/sql/postgresql/upgrade/upgrade-5.0d1-5.0d2.sql 12 Jul 2004 14:49:52 -0000 1.2 @@ -0,0 +1,53 @@ +-- + +-- @author Gabriel Burca (gburca-openacs@ebixio.com) +-- @creation-date 2004-06-22 +-- @cvs-id $Id: upgrade-5.0d1-5.0d2.sql,v 1.2 2004/07/12 14:49:52 jeffd Exp $ +-- + +create or replace function bm_bookmarks_get_folder_names( + -- + -- Returns the names of the parent folders of a bookmark, joined + -- together with an optional separator. + -- + -- @author Gabriel Burca (gburca-openacs@ebixio.com) + -- + + integer, -- bm_bookmarks.bookmark_id%TYPE + text -- Optional separator (set to NULL to use the default) +) returns text as ' +declare + p_bookmark_id alias for $1; + p_sep alias for $2; -- optional separator to use + v_rec record; + tree_key varbit; + separator text default '' :: ''; + folder_names text default ''''; -- If NULL, the || in the LOOP fails +begin + tree_key := bm_bookmarks_get_tree_sortkey(p_bookmark_id); + + -- Level 1 is the root folder, level 2 is items in the root folder + if tree_level(tree_key) <= 2 then + return ''''; + end if; + + if p_sep is not null then + separator := p_sep; + end if; + + for v_rec in select local_title + from bm_bookmarks + where tree_sortkey in + (select tree_ancestor_keys( -- get all parent folders up to level 2 + tree_ancestor_key( -- start with the parent folder key + tree_key, tree_level(tree_key) - 1), 2 ) ) + order by tree_sortkey + LOOP + folder_names := folder_names || separator || v_rec.local_title; + end LOOP; + + return trim(leading separator from folder_names); +end;' language 'plpgsql'; + + + Index: openacs-4/packages/bookmarks/www/search-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bookmarks/www/search-oracle.xql,v diff -u -N -r1.1 -r1.2 --- openacs-4/packages/bookmarks/www/search-oracle.xql 8 Sep 2001 23:05:37 -0000 1.1 +++ openacs-4/packages/bookmarks/www/search-oracle.xql 12 Jul 2004 14:49:52 -0000 1.2 @@ -9,6 +9,7 @@ select bookmark_id, complete_url, nvl(local_title, url_title) as title, + 'N/A' as folder_names, meta_keywords, meta_description from (select bookmark_id, url_id, local_title, folder_p, owner_id @@ -36,6 +37,7 @@ select distinct complete_url, bookmark_id, nvl(local_title, url_title) as title, + 'N/A' as folder_names, meta_keywords, meta_description, folder_p, Index: openacs-4/packages/bookmarks/www/search-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bookmarks/www/search-postgresql.xql,v diff -u -N -r1.2 -r1.3 --- openacs-4/packages/bookmarks/www/search-postgresql.xql 8 Dec 2001 01:17:59 -0000 1.2 +++ openacs-4/packages/bookmarks/www/search-postgresql.xql 12 Jul 2004 14:49:53 -0000 1.3 @@ -9,9 +9,11 @@ select bookmark_id, complete_url, coalesce(local_title, url_title) as title, + bm_bookmarks_get_folder_names(bookmark_id, null) as folder_names, + tree_sortkey, meta_keywords, meta_description - from (select bm.bookmark_id, bm.url_id, bm.local_title, bm.folder_p, bm.owner_id + from (select bm.bookmark_id, bm.url_id, bm.local_title, bm.folder_p, bm.owner_id, bm.tree_sortkey from bm_bookmarks bm, bm_bookmarks bm2 where bm.tree_sortkey between bm2.tree_sortkey and tree_right(bm2.tree_sortkey) and bm2.bookmark_id = :root_folder_id @@ -26,7 +28,7 @@ or upper(complete_url) like :search_pattern or upper(meta_keywords) like :search_pattern or upper(meta_description) like :search_pattern) - order by title + order by tree_sortkey @@ -38,14 +40,16 @@ select distinct complete_url, bookmark_id, coalesce(local_title, url_title) as title, + bm_bookmarks_get_folder_names(bookmark_id, null) as folder_names, + tree_sortkey, meta_keywords, meta_description, folder_p, acs_permission__permission_p(bookmark_id, :browsing_user_id, 'admin') as admin_p from ( select o2.bookmark_id, o2.url_id, o2.local_title, - o2.folder_p, o2.owner_id + o2.folder_p, o2.owner_id, o2.tree_sortkey from bm_bookmarks o1, bm_bookmarks o2 where o1.parent_id = :package_id @@ -62,7 +66,7 @@ or upper(meta_keywords) like :search_pattern or upper(meta_description) like :search_pattern ) -order by title +order by tree_sortkey Index: openacs-4/packages/bookmarks/www/search.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bookmarks/www/search.tcl,v diff -u -N -r1.6 -r1.7 --- openacs-4/packages/bookmarks/www/search.tcl 29 Jun 2004 10:17:48 -0000 1.6 +++ openacs-4/packages/bookmarks/www/search.tcl 12 Jul 2004 14:49:53 -0000 1.7 @@ -85,8 +85,12 @@ template::list::create \ -name others_list -multirow others_list \ -elements { + folder_names { + label "Folders" + html {nowrap ""} + } title { - label "Matches from other bookmark lists" + label "Matches in other bookmark lists" link_url_eval {$complete_url} } invoke { @@ -105,3 +109,13 @@ db_multirow others_list bookmark_search_other {*SQL*} + +# Take this "if" statement out once oracle has a bm_bookmarks_get_folder_names equivalent. +# Until then we won't display the folder_names column when using oracle. +set db_type [db_rdbms_get_type [db_current_rdbms]] +if {$db_type != "postgresql"} { + template::list::element::set_property -list_name my_list \ + -element_name folder_names -property hide_p -value 1 + template::list::element::set_property -list_name others_list \ + -element_name folder_names -property hide_p -value 1 +} Index: openacs-4/packages/bookmarks/www/tree-dynamic.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bookmarks/www/tree-dynamic.tcl,v diff -u -N -r1.3 -r1.4 --- openacs-4/packages/bookmarks/www/tree-dynamic.tcl 29 Jun 2004 10:17:48 -0000 1.3 +++ openacs-4/packages/bookmarks/www/tree-dynamic.tcl 12 Jul 2004 14:49:53 -0000 1.4 @@ -87,4 +87,4 @@ append js "];\n" -doc_return 200 text/html "$js" +doc_return 200 text/plain "$js" Index: openacs-4/packages/bookshelf/lib/random-book.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bookshelf/lib/random-book.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/bookshelf/lib/random-book.adp 12 Jul 2004 14:49:54 -0000 1.2 @@ -0,0 +1,9 @@ + +
    +
    + @book.book_title@
    + by @book.book_author@ +
    +
    + + Index: openacs-4/packages/bookshelf/lib/random-book.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bookshelf/lib/random-book.tcl,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/bookshelf/lib/random-book.tcl 12 Jul 2004 14:49:54 -0000 1.2 @@ -0,0 +1,23 @@ +# expects package_id + +set book_no [db_string random { + select book_no, random() as seed + from bookshelf_books + where package_id = :package_id + and publish_status = 'publish' + order by seed + limit 1 +} -default {}] + +if { ![empty_string_p $book_no] } { + bookshelf::book::get -package_id $package_id -book_no $book_no -array book + + set book(url) [export_vars -base "[site_node::get_url_from_object_id -object_id $package_id]book-view" { book_no }] + + set book(image_url) [bookshelf::amazon::get_image_url $book(isbn)] + + bookshelf::amazon::get_image_info -array amazon_info $book(isbn) + set book(image_width) $amazon_info(image_width) + set book(image_height) $amazon_info(image_height) +} + Index: openacs-4/packages/bookshelf/www/doc/index.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/bookshelf/www/doc/index.html,v diff -u -N -r1.1 -r1.2 --- openacs-4/packages/bookshelf/www/doc/index.html 30 Sep 2002 18:10:57 -0000 1.1 +++ openacs-4/packages/bookshelf/www/doc/index.html 12 Jul 2004 14:49:54 -0000 1.2 @@ -55,6 +55,11 @@ src="/packages/bookshelf/www/bookshelf-titles-include"> gives you the short version which just lists the titles. +
  • + See this + forum posting on how to add in random bookshelf entries. +
  • @@ -103,4 +108,4 @@
    lars@pinds.com
    - \ No newline at end of file + Index: openacs-4/packages/calendar/tcl/cal-item-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/calendar/tcl/cal-item-procs.tcl,v diff -u -N -r1.19 -r1.20 --- openacs-4/packages/calendar/tcl/cal-item-procs.tcl 29 Jun 2004 10:17:51 -0000 1.19 +++ openacs-4/packages/calendar/tcl/cal-item-procs.tcl 12 Jul 2004 14:49:55 -0000 1.20 @@ -76,7 +76,7 @@ ad_proc -public calendar::item::get { {-cal_item_id:required} {-array:required} - {-normalize_system_time 1} + {-normalize_time_to_utc 0} } { Get the data for a calendar item @@ -90,12 +90,12 @@ } db_1row $query_name {} -column_array row - if {$normalize_system_time} { + if {$normalize_time_to_utc} { + set row(start_date_ansi) [lc_time_local_to_utc $row(start_date_ansi)] + set row(end_date_ansi) [lc_time_local_to_utc $row(end_date_ansi)] + } else { set row(start_date_ansi) [lc_time_system_to_conn $row(start_date_ansi)] set row(end_date_ansi) [lc_time_system_to_conn $row(end_date_ansi)] - } else { - set row(start_date_ansi) [lc_time_conn_to_system $row(start_date_ansi)] - set row(end_date_ansi) [lc_time_conn_to_system $row(end_date_ansi)] } if { $row(start_date_ansi) == $row(end_date_ansi) && [string equal [lc_time_fmt $row(start_date_ansi) "%T"] "00:00:00"]} { Index: openacs-4/packages/calendar/tcl/calendar-outlook-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/calendar/tcl/calendar-outlook-procs.tcl,v diff -u -N -r1.14 -r1.15 --- openacs-4/packages/calendar/tcl/calendar-outlook-procs.tcl 29 Jun 2004 10:17:51 -0000 1.14 +++ openacs-4/packages/calendar/tcl/calendar-outlook-procs.tcl 12 Jul 2004 14:49:55 -0000 1.15 @@ -61,7 +61,7 @@ The client timezone helps to make things right. It is the number offset from GMT. } { - calendar::item::get -cal_item_id $cal_item_id -array cal_item -normalize_system_time 1 + calendar::item::get -cal_item_id $cal_item_id -array cal_item -normalize_time_to_utc 1 # If necessary, select recurrence information # Here we have some fields Index: openacs-4/packages/calendar/www/cal-item-create-recurrence-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/calendar/www/Attic/cal-item-create-recurrence-2.tcl,v diff -u -N --- openacs-4/packages/calendar/www/cal-item-create-recurrence-2.tcl 19 Feb 2004 15:03:43 -0000 1.6 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,43 +0,0 @@ - -# /packages/calendar/www/cal-item-create.tcl - -ad_page_contract { - - Creation of new recurrence for cal item - - @author Ben Adida (ben@openforce.net) - @creation-date 10 Mar 2002 - @cvs-id $Id: cal-item-create-recurrence-2.tcl,v 1.6 2004/02/19 15:03:43 dirkg Exp $ -} { - cal_item_id - every_n - interval_type - recur_until:array - days_of_week:multiple - {return_url "./"} -} - - -# Verify permission -ad_require_permission $cal_item_id cal_item_write - -# Get basic information about the event. We need the start date -calendar::item::get -cal_item_id $cal_item_id -array cal_item - -set start_date $cal_item(start_date) -set end_date [calendar::make_datetime [array get recur_until]] - -if {![calendar::item::dates_valid_p -start_date $start_date -end_date $end_date]} { - ad_return_complaint 1 [_ calendar.start_date_before_end_date] - ad_script_abort -} - -# Set up the recurrence -calendar::item::add_recurrence \ - -cal_item_id $cal_item_id \ - -interval_type $interval_type \ - -every_n $every_n \ - -days_of_week $days_of_week \ - -recur_until [calendar_make_datetime [array get recur_until]] - -ad_returnredirect $return_url Index: openacs-4/packages/calendar/www/cal-item-create-recurrence.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/calendar/www/cal-item-create-recurrence.adp,v diff -u -N -r1.12 -r1.13 --- openacs-4/packages/calendar/www/cal-item-create-recurrence.adp 24 Nov 2003 11:07:55 -0000 1.12 +++ openacs-4/packages/calendar/www/cal-item-create-recurrence.adp 12 Jul 2004 14:49:55 -0000 1.13 @@ -18,32 +18,6 @@ #calendar.Details# @cal_item.description@

    - - - + -#calendar.Repeat_every# :
    - #calendar.day_s#
    - -<% -foreach dow [list [list "#calendar.Sunday#" 0] [list "#calendar.Monday#" 1] [list "#calendar.Tuesday#" 2] [list "#calendar.Wednesday#" 3] [list "#calendar.Thursday#" 4] [list "#calendar.Friday#" 5] [list "#calendar.Saturday#" 6]] { - if {[lindex $dow 1] == [expr "$cal_item(day_of_week) -1"]} { - set checked_html "CHECKED" - } else { - set checked_html "" - } - template::adp_puts "[lindex $dow 0]  " -} -%> -#calendar.of_the_week#
    - #calendar.day# -@cal_item.day_of_month@ #calendar.of_the_month#
    - #calendar.same# @cal_item.pretty_day_of_week@ #calendar.of_the_month#
    - #calendar.year#
    -#calendar.lt_Repeat_this_event_unt# <%= [dt_widget_datetime -default [dt_systime] recur_until] %> -

    - - - - Index: openacs-4/packages/calendar/www/cal-item-create-recurrence.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/calendar/www/cal-item-create-recurrence.tcl,v diff -u -N -r1.4 -r1.5 --- openacs-4/packages/calendar/www/cal-item-create-recurrence.tcl 22 Jul 2002 21:46:19 -0000 1.4 +++ openacs-4/packages/calendar/www/cal-item-create-recurrence.tcl 12 Jul 2004 14:49:55 -0000 1.5 @@ -11,13 +11,77 @@ } { cal_item_id {return_url "./"} + {days_of_week:multiple ""} } -# Verify permission + +auth::require_login ad_require_permission $cal_item_id cal_item_write -# Select basic information about the event calendar::item::get -cal_item_id $cal_item_id -array cal_item +set dow_string "" +foreach dow [list [list "#calendar.Sunday#" 0] [list "#calendar.Monday#" 1] [list "#calendar.Tuesday#" 2] [list "#calendar.Wednesday#" 3] [list "#calendar.Thursday#" 4] [list "#calendar.Friday#" 5] [list "#calendar.Saturday#" 6]] { + if {[lindex $dow 1] == [expr "$cal_item(day_of_week) -1"]} { + set checked_html "CHECKED" + } else { + set checked_html "" + } + + set dow_string "$dow_string [lindex $dow 0]  \n" +} + +set recurrance_options [list \ + [list [_ calendar.day_s] day] \ + [list "$dow_string [_ calendar.of_the_week]" week] \ + [list "[_ calendar.day] $cal_item(day_of_month) [_ calendar.of_the_month]" month_by_date] \ + [list "[_ calendar.same] $cal_item(pretty_day_of_week) [_ calendar.of_the_month]" month_by_day] \ + [list [_ calendar.year] year]] + + + +ad_form -name cal_item -export {return_url} -form { + {cal_item_id:key} + + {every_n:integer,optional + {label "[_ calendar.Repeat_every]"} + {value 1} + {html {size 4}} + } + + {interval_type:text(radio) + {label ""} + {options $recurrance_options} + } + + {recur_until:date + {label "[_ calendar.lt_Repeat_this_event_unt]"} + } + + {submit:text(submit) {label "[_ calendar.Add_Recurrence]"}} + +} -validate { + {recur_until + { + [calendar::item::dates_valid_p -start_date $cal_item(start_date) -end_date [calendar::to_sql_datetime -date $recur_until -time "" -time_p 0]] + } + {[_ calendar.start_time_before_end_time]} + } +} -edit_data { + calendar::item::add_recurrence \ + -cal_item_id $cal_item_id \ + -interval_type $interval_type \ + -every_n $every_n \ + -days_of_week $days_of_week \ + -recur_until [calendar::to_sql_datetime -date $recur_until -time "" -time_p 0] +} -edit_request { + set recur_until [template::util::date::from_ansi $cal_item(start_date)] + set interval_type week +} -after_submit { + ad_returnredirect $return_url + ad_script_abort +} -has_submit 1 + + ad_return_template Index: openacs-4/packages/categories/www/doc/design.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/categories/www/doc/design.html,v diff -u -N -r1.1 -r1.2 --- openacs-4/packages/categories/www/doc/design.html 18 Jan 2004 16:32:55 -0000 1.1 +++ openacs-4/packages/categories/www/doc/design.html 12 Jul 2004 14:49:55 -0000 1.2 @@ -123,7 +123,11 @@

    This table stores the tree hierarchy by holding the information about -the parent category. The tree is ordered by a nested index (left_ind, right_ind). +the parent category. The tree is ordered by a nested index (left_ind, +right_ind). Sorting is thus accomplished by means of a nested set. You +can read a description of how nested sets work. This also describes how to write queries that sort correctly when using categories. + +

     create table categories (
            category_id		    integer primary key
    Index: openacs-4/packages/dotlrn/tcl/community-procs-oracle.xql
    ===================================================================
    RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn/tcl/community-procs-oracle.xql,v
    diff -u -N -r1.24 -r1.25
    --- openacs-4/packages/dotlrn/tcl/community-procs-oracle.xql	29 Jun 2004 10:17:54 -0000	1.24
    +++ openacs-4/packages/dotlrn/tcl/community-procs-oracle.xql	12 Jul 2004 14:49:56 -0000	1.25
    @@ -30,7 +30,7 @@
             
                 declare
                 begin
    -                :1 := dotlrn_community_type.del(
    +                dotlrn_community_type.del(
                         community_type => :community_type_key
                     );
                 end;
    Index: openacs-4/packages/dotlrn/tcl/dotlrn-security-procs.tcl
    ===================================================================
    RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn/tcl/dotlrn-security-procs.tcl,v
    diff -u -N -r1.55 -r1.56
    --- openacs-4/packages/dotlrn/tcl/dotlrn-security-procs.tcl	20 Apr 2004 21:13:19 -0000	1.55
    +++ openacs-4/packages/dotlrn/tcl/dotlrn-security-procs.tcl	12 Jul 2004 14:49:56 -0000	1.56
    @@ -105,15 +105,13 @@
             ns_set put $extra_vars user_id $user_id
             ns_set put $extra_vars id $id
     
    -        set template_id [dotlrn::get_portal_id_from_type -type user]
    +        set portal_id [dotlrn::get_portal_id_from_type -type user]
     
             db_transaction {
                 set_can_browse -user_id $user_id -can_browse\=$can_browse_p
     
    -            set portal_id [portal::create \
    -                -template_id $template_id \
    -                -name "[_ dotlrn.lt_Your_dotLRN_Workspace]" \
    -                $user_id]
    +	    # The user will start with a the default portal.
    +	    # A new one will be created when they go to configure
     
                 ns_set put $extra_vars portal_id $portal_id
     
    Index: openacs-4/packages/dotlrn/www/communities-chunk.adp
    ===================================================================
    RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn/www/communities-chunk.adp,v
    diff -u -N -r1.10 -r1.11
    --- openacs-4/packages/dotlrn/www/communities-chunk.adp	29 Apr 2004 15:39:13 -0000	1.10
    +++ openacs-4/packages/dotlrn/www/communities-chunk.adp	12 Jul 2004 14:49:56 -0000	1.11
    @@ -31,10 +31,10 @@
           
    @communities.pretty_name@ - + - + Index: openacs-4/packages/dotlrn/www/communities-chunk.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn/www/communities-chunk.tcl,v diff -u -N -r1.9 -r1.10 --- openacs-4/packages/dotlrn/www/communities-chunk.tcl 23 Oct 2002 12:38:39 -0000 1.9 +++ openacs-4/packages/dotlrn/www/communities-chunk.tcl 12 Jul 2004 14:49:56 -0000 1.10 @@ -21,7 +21,7 @@ @creation-date Dec 07, 2001 @version $Id$ } -query { - {filter "select_all_non_memberships"} + {filter "select_all_memberships"} } -properties { n_communities:onevalue communities:multirow @@ -39,7 +39,7 @@ set n_communities [db_string select_all_communities_count {}] } -set filter_bar [ad_dimensional [list [list filter "[_ dotlrn.Memberships_1]" select_all_non_memberships \ +set filter_bar [ad_dimensional [list [list filter "[_ dotlrn.Memberships_1]" select_all_memberships \ { {select_all_memberships current {}} {select_all_non_memberships join {}} Index: openacs-4/packages/dotlrn/www/configure.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn/www/configure.tcl,v diff -u -N -r1.18 -r1.19 --- openacs-4/packages/dotlrn/www/configure.tcl 4 Dec 2002 09:51:04 -0000 1.18 +++ openacs-4/packages/dotlrn/www/configure.tcl 12 Jul 2004 14:49:56 -0000 1.19 @@ -28,7 +28,7 @@ @version $Id$ } - + if {[parameter::get -parameter community_type_level_p] == 1} { # at a community type level, redirect @@ -42,14 +42,49 @@ return } else { + set user_id [ad_conn user_id] # I don't see under what circumstance we wouldn't want users to # customize thier own portal. -Caroline. # dotlrn::require_user_browse -user_id $user_id + # On install, everyone is assigned the default portal + # If they would like to customize, a new portal will be + # created for them. + set portal_id [dotlrn::get_portal_id -user_id $user_id] + + # check if the portal_id is the default_portal_id + + set default_portal_p [db_string default_portal_p { + select count(*) from dotlrn_portal_types_map where portal_id = :portal_id + }] + + + if {$default_portal_p == 1} { + # user is set as the default portal + # give the user their own portal + + + set portal_id [portal::create \ + -template_id $portal_id \ + -name "[_ dotlrn.lt_Your_dotLRN_Workspace]" \ + $user_id] + + db_exec_plsql update_user_portal_id { + update dotlrn_user_profile_rels set portal_id = :portal_id + where dotlrn_user_profile_rels.rel_id = + (select rel_id from acs_rels, dotlrn_user_types + where acs_rels.object_id_two = :user_id + and acs_rels.object_id_one = dotlrn_user_types.group_id) + } + + util_memoize_flush "dotlrn::get_portal_id_not_cached -user_id $user_id" + } + + set name [portal::get_name $portal_id] set rendered_page [portal::configure -allow_theme_change_p 0 $portal_id "index"] } Index: openacs-4/packages/dotlrn/www/deregister-link.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn/www/deregister-link.adp,v diff -u -N -r1.12 -r1.13 --- openacs-4/packages/dotlrn/www/deregister-link.adp 29 Apr 2004 15:39:13 -0000 1.12 +++ openacs-4/packages/dotlrn/www/deregister-link.adp 12 Jul 2004 14:49:56 -0000 1.13 @@ -17,5 +17,4 @@ # %> - #dotlrn.drop_membership_link#@label@ Index: openacs-4/packages/dotlrn/www/dotlrn-master.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn/www/dotlrn-master.adp,v diff -u -N -r1.35 -r1.36 --- openacs-4/packages/dotlrn/www/dotlrn-master.adp 29 Jun 2004 10:18:00 -0000 1.35 +++ openacs-4/packages/dotlrn/www/dotlrn-master.adp 12 Jul 2004 14:49:56 -0000 1.36 @@ -1,117 +1,29 @@ -<% + + + + + @header_stuff;noquote@ + + @context;noquote@ + @context_bar;noquote@ + @focus;noquote@ + @doc_type;noquote@ + @title;noquote@ - # Copyright (C) 2001, 2002 MIT - # - # This file is part of dotLRN. - # - # dotLRN 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. - # - # dotLRN 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. +@navbar;noquote@ - - # /www/dotlrn-default-master.adp - # - # This is the 'default-master' template for dotlrn sites. - # - # Author: Arjun Sanyal (arjun@openforce.net), yon@openforce.net - # - # $Id$ - - -%> - - - - - -@title@ - - - - -@header_stuff;noquote@ - - @attribute.key@="@attribute.value@"> - - - - - - - - - - - - - - - - - - - - - - -
    @text;noquote@ - @user_name@ -
    - #dotlrn.user_portal_page_home_title# - - #dotlrn.help# - - #dotlrn.logout# -
    @navbar;noquote@
    -

    -

    +

    + +

    @title;noquote@

    - -
    -

    @title@

    - -

    @context_bar;noquote@

    -
    - - - +
    + - -

    - +@navbar;noquote@ - - - - - -
    @navbar;noquote@
    - - - -

    -

    - -

    - -

    - -

    - - + Index: openacs-4/packages/dotlrn/www/dotlrn-master.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/dotlrn/www/dotlrn-master.tcl,v diff -u -N -r1.31 -r1.32 --- openacs-4/packages/dotlrn/www/dotlrn-master.tcl 29 Jun 2004 10:18:00 -0000 1.31 +++ openacs-4/packages/dotlrn/www/dotlrn-master.tcl 12 Jul 2004 14:49:56 -0000 1.32 @@ -65,7 +65,6 @@ set header_img_file "[acs_root_dir]/packages/dotlrn/www/resources/logo" set header_img_alt_text "Header Logo" -set extra_spaces "" set td_align "align=\"center\" valign=\"top\"" if {[dotlrn::user_p -user_id $user_id]} { @@ -301,33 +300,18 @@ } if { $make_navbar_p } { - if {$link_control_panel} { - set link_control_panel 1 - } else { - set link_control_panel 0 - } - set extra_spaces "" set navbar [dotlrn::portal_navbar \ - -user_id $user_id \ - -link_control_panel $link_control_panel \ - -control_panel_text $control_panel_text \ - -pre_html "$extra_spaces" \ - -post_html $extra_spaces \ - -link_all $link_all - ] -} else { - set navbar "
    " + -user_id $user_id \ + -link_control_panel [template::util::is_true $link_control_panel] \ + -control_panel_text $control_panel_text \ + -link_all $link_all] } if { ![info exists header_stuff] } { set header_stuff "" } -if { [info exists text] } { - set text [lang::util::localize $text] -} - # This style sheet should be moved over to an external file for performance append header_stuff "