Index: openacs-4/packages/acs-core-docs/www/files/tutorial/myfirstpackage-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/files/tutorial/myfirstpackage-procs.tcl,v diff -u -r1.2 -r1.2.2.1 --- openacs-4/packages/acs-core-docs/www/files/tutorial/myfirstpackage-procs.tcl 4 Feb 2004 16:47:34 -0000 1.2 +++ openacs-4/packages/acs-core-docs/www/files/tutorial/myfirstpackage-procs.tcl 17 Apr 2004 14:11:02 -0000 1.2.2.1 @@ -2,23 +2,83 @@ Test cases for my first package. } -aa_register_case mfp_basic_test { - Test One -} { - aa_run_with_teardown \ - -rollback \ - -test_code { - set name [ad_generate_random_string] - set new_id [mfp::note::add -title $name] - aa_true "Note add succeeded" [exists_and_not_null new_id] +aa_register_case \ + -cats {smoke api} \ + -procs {mfp::note::add mfp::note::get mfp::note::delete} \ + mfp_basic_test \ + { + A simple test that adds, retrieves, and deletes a record. + } { + aa_run_with_teardown \ + -rollback \ + -test_code { + set name [ad_generate_random_string] + set new_id [mfp::note::add -title $name] + aa_true "Note add succeeded" [exists_and_not_null new_id] + + mfp::note::get -item_id $new_id -array note_array + aa_true "Note contains correct title" [string equal $note_array(title) $name] + + mfp::note::delete -item_id $new_id + + set get_again [catch {mfp::note::get -item_id $new_id -array note_array}] + aa_false "After deleting a note, retrieving it fails" [expr $get_again == 0] + } + } - mfp::note::get -item_id $new_id -array note_array - aa_true "Note contains correct title" [string equal $note_array(title) $name] +aa_register_case \ + -cats {api} \ + -procs {mfp::note::add mfp::note::get mfp::note::delete} \ + mfp_bad_data_test \ + { + A simple test that adds, retrieves, and deletes a record, using some tricky data. + } { + aa_run_with_teardown \ + -rollback \ + -test_code { + set name {-Bad [BAD] \077 { $Bad}} + append name [ad_generate_random_string] + set new_id [mfp::note::add -title $name] + aa_true "Note add succeeded" [exists_and_not_null new_id] + + mfp::note::get -item_id $new_id -array note_array + aa_true "Note contains correct title" [string equal $note_array(title) $name] + aa_log "Title is $name" + mfp::note::delete -item_id $new_id + + set get_again [catch {mfp::note::get -item_id $new_id -array note_array}] + aa_false "After deleting a note, retrieving it fails" [expr $get_again == 0] + } + } - mfp::note::delete -item_id $new_id +aa_register_case \ + -libraries tclwebtest \ + -cats {web} \ + mfp_basic_web_test \ + { + A simple test that adds, retrieves, and deletes a record through the web interface. INCOMPLETE. + } { + aa_run_with_teardown \ + -rollback \ + -test_code { + ############################################ + # Prepare + ############################################ - set get_again [catch {mfp::note::get -item_id $new_id -array note_array}] - aa_false "After deleting a note, retrieving it fails" [expr $get_again == 0] - } -} + set name [ad_generate_random_string] + tclwebtest::do_request + + + set new_id [mfp::note::add -title $name] + aa_true "Note add succeeded" [exists_and_not_null new_id] + + mfp::note::get -item_id $new_id -array note_array + aa_true "Note contains correct title" [string equal $note_array(title) $name] + aa_log "Title is $name" + mfp::note::delete -item_id $new_id + + set get_again [catch {mfp::note::get -item_id $new_id -array note_array}] + aa_false "After deleting a note, retrieving it fails" [expr $get_again == 0] + } + } \ No newline at end of file Index: openacs-4/packages/acs-core-docs/www/images/production.dia =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/images/production.dia,v diff -u -r1.1 -r1.1.2.1 Binary files differ Index: openacs-4/packages/acs-core-docs/www/images/upgrade-cvs.png =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/images/upgrade-cvs.png,v diff -u -r1.1 -r1.1.2.1 Binary files differ Index: openacs-4/packages/acs-core-docs/www/xml/index.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/xml/index.xml,v diff -u -r1.28 -r1.28.2.1 --- openacs-4/packages/acs-core-docs/www/xml/index.xml 27 Feb 2004 11:20:56 -0000 1.28 +++ openacs-4/packages/acs-core-docs/www/xml/index.xml 17 Apr 2004 14:11:03 -0000 1.28.2.1 @@ -1,7 +1,7 @@ - %myvars; Index: openacs-4/packages/acs-core-docs/www/xml/developers-guide/i18n.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/xml/developers-guide/i18n.xml,v diff -u -r1.13 -r1.13.2.1 --- openacs-4/packages/acs-core-docs/www/xml/developers-guide/i18n.xml 12 Mar 2004 13:44:56 -0000 1.13 +++ openacs-4/packages/acs-core-docs/www/xml/developers-guide/i18n.xml 17 Apr 2004 14:11:03 -0000 1.13.2.1 @@ -76,49 +76,8 @@ - - Translator's Guide - Most translators use the OpenACS Public Translation Server, because the process of getting new message keys onto the server and getting new translations back into the distribution are handled by the maintainers of that machine. You can also do translation work on your own OpenACS site; this makes your own translations more readily available to you but also means that your work will not be shared with other users unless you take extra steps (contacting an OpenACS core developer or submitting a patch) to get your work back to the OpenACS core. - The basic steps for translators: - - - Go to the Localization page and choose the locale that you are translating to. If the locale is not present you need to visit Administration of Localization and create the locale. - - - - Translating with Translator Mode - To translate messages in the pages they appear, Toggle Translator Mode and then browse to the page you want to translate. Untranslated messages will have a yellow background and a red star that you click to translate the message. Translated messages have a green star next to them that is a hyperlink to editing your translation. There is a history mechanism that allows you to see previous translations in case you would want to revert a translation. - - - - - - - While in Translator mode, a list of all message keys appears at the bottom of each page. - - - - - - - - - Batch translation - To translate many messages at once, go to Administration of Localization, click on the locale to translate, then click on a package, and then click Batch edit these messages. - - - - - - - - - - - - Introduction to Developing Internationalized Packages - + How Internationalization/Localization works in OpenACS This document describes how to develop internationalized OpenACS packages, including writing new packages with @@ -135,41 +94,24 @@ The main difference between monolingual and internationalized - packages is that all user-visible text in an internationalized + packages is that all user-visible text in the code of an internationalized package are coded as "message keys." The message keys correspond to a message catalog, which contains versions of the - text for each available language. Both script files - (ADP/TCL) and APM parameters are affected. + text for each available language. Script files (.adp and .tcl and .vuh), database files (.sql), and APM parameters are affected. + Other differences include: all dates read or written to the database must use internationalized functions. All displayed dates must use internationalized functions. All displayed numbers must use internationalized functions. - - - - - AOLserver Configuration for Multilingual Sites - - - For multilingual websites we recommend using the UTF8 - charset. In order for AOLserver to use utf8 you need to set - the config parameters OutputCharset and - URLCharset to utf-8 in your AOLserver config file (use the etc/config.tcl - template file). This is the default for OpenACS 5.1 and later. For sites running on Oracle you need to make - sure that AOLserver is running with the NLS_LANG environment - variable set to .UTF8. You should set this variable in the - nsd-oracle run script (use the - acs-core-docs/www/files/nds-oracle.txt template file). - - - - - Using the Message Catalog - + + User Content + OpenACS does not have a general system for supporting multiple, localized versions of user-input content. This document currently refers only to internationalizing the text in the package user interface. + + Localizable text must be handled in ADP files, in TCL files, and in APM Parameters. OpenACS provides two approaches, message @@ -182,13 +124,13 @@ distinguished by a file naming convention. + - Separate Templates for each Locale - If the request processor finds a file named filename.locale.adp, where locale matches the user's locale, it will process that file instead of filename.adp. For example, for a user with locale tl_PH, the file index.tl_PH.adp, if found, will be used instead of index.adp. The locale-specific file should thus contain text in the language appropriate for that locale. The code in the page, however, should still be in English. Message keys are still processed. - - - + If the request processor finds a file named filename.locale.adp, where locale matches the user's locale, it will process that file instead of filename.adp. For example, for a user with locale tl_PH, the file index.tl_PH.adp, if found, will be used instead of index.adp. The locale-specific file should thus contain text in the language appropriate for that locale. The code in the page, however, should still be in English. Message keys are processed normally. + + + Message Catalogs Message Keys in Template Files (ADP Files) @@ -280,27 +222,24 @@ - Typical static key lookup: [_ package_key.message_key] - The message key and package key used here must be string literals, they can't result from variable evaluation. + Typical static key lookup: [_ package_key.message_key] - The message key and package key used here must be string literals, they can't result from variable evaluation. - - Static key lookup with non-default locale: [lang::message::lookup $locale package_key.message_key] - The message key and package key used here must be string literals, they can't result from variable evaluation. + + Static key lookup with non-default locale: [lang::message::lookup $locale package_key.message_key] - The message key and package key used here must be string literals, they can't result from variable evaluation. - Dynamic key lookup: - -[lang::util::localize $var_with_embedded_message_keys] -- In this case the message keys in the variable var_with_embedded_message_keys must appear as string literals \#package_key.message_key\# somewhere in the code. Here is an example of a dynamic lookup: -set message_key_array { - dynamic_key_1 \#package_key.message_key1\# - dynamic_key_2 \#package_key.message_key2\# + + Dynamic key lookup: [lang::util::localize $var_with_embedded_message_keys] - In this case the message keys in the variable var_with_embedded_message_keys must appear as string literals \#package_key.message_key\# somewhere in the code. Here is an example of a dynamic lookup: + + set message_key_array { + dynamic_key_1 \#package_key.message_key1\# + dynamic_key_2 \#package_key.message_key2\# } -set my_text [lang::util::localize $message_key_array([get_dynamic_key])] - - - + set my_text [lang::util::localize $message_key_array([get_dynamic_key])] + @@ -408,34 +347,22 @@ procedure. - + - + Dates, Times, and Numbers in TCL files - Checking the Consistency of Catalog Files - - - This section describes how to check that the set of keys used in - message lookups in tcl, adp, and info files and the set of keys in - the catalog file are identical. The scripts below assume that - message lookups in adp and info files are on the format - \#package_key.message_key\#, and that message lookups in tcl files - are always is done with one of the valid lookups described above. The script further assumes - that you have perl installed and in your path. Run the script like - this: - - - - acs-lang/bin/check-catalog.sh package_key - - - - where package_key is the key of the package that you want to - test. If you don't provide the package_key argument then all - packages with catalog files will be checked. - The script will run its checks primarily on en_US xml catalog files. - - + + Most date, time, and number variables are calculated in TCL files. Dates and times must be converted when stored in the database, + when retrieved from the database, and when displayed. All dates + are stored in the database in the server's timezone, which is an + APM Parameter set at + /acs-lang/admin/set-system-timezone + and readable at + lang::system::timezone.. When + retrieved from the database and displayed, dates and times must + be localized to the user's locale. + + @@ -535,42 +462,205 @@ + - + + How to Internationalize a Package - Dates, Times, and Numbers - - - Dates and times must be converted when stored in the database, - when retrieved from the database, and when displayed. All dates - are stored in the database in the server's timezone, which is an - APM Parameter set at - /acs-lang/admin/set-system-timezone - and readable at - lang::system::timezone.. When - retrieved from the database and displayed, dates and times must - be localized to the user's locale. + + + For multilingual websites we recommend using the UTF8 + charset. In order for AOLserver to use utf8 you need to set + the config parameters OutputCharset and + URLCharset to utf-8 in your AOLserver config file (use the etc/config.tcl + template file). This is the default for OpenACS 5.1 and later. For sites running on Oracle you need to make + sure that AOLserver is running with the NLS_LANG environment + variable set to .UTF8. You should set this variable in the + nsd-oracle run script (use the + acs-core-docs/www/files/nds-oracle.txt template file). + + + + Replace all text with temporary message tags + From/acs-admin/apm/, select a + package and then click on + Internationalization, then + Convert ADP, Tcl, and SQL files to using the + message catalog.. This pass only changes the adp files; it does not affect catalog files or the catalog in the database. + + + + + + + You will now be walked through all of the selected adp pages. The UI shows you the intended changes and lets you edit or cancel them key by key. + + + + + + + + + The automatic process can easily get confused by tags within message texts, so that it tries to create two or three message keys for one long string with a tag in the middle. In these cases, uncheck those keys during the conversion and then edit the files directly. For example, this code: + <p class="form-help-text"><b>Invitations</b> are sent, + when this wizard is completed and casting begins.</p> + has a bold tag which confuses the converter into thinking there are two message keys for the text beginning "Invitations ..." where there should be one: + + + + + + Instead, we cancel those keys, edit the file manually, and put in a single temporary message tag: + <p class="form-help-text"> <#Invitations_are_sent <b>Invitations</b> are sent, + when this wizard is completed and casting begins.#> + </p> + + + Complex if statements may produce convoluted message keys that are very hard to localize. Rewrite these if statements. For example: + +Select which case <if @simulation.casting_type@ eq "open">and +role</if> to join, or create a new case for yourself. If you do not +select a case <if @simulation.casting_type@ eq "open">and role</if> +to join, you will be automatically assigned to a case <if +@simulation.casting_type@ eq "open">and role</if> when the +simulation begins. + ... can be rewritten: +<if @simulation.casting_type@ eq "open"> + +Select which case and role to join, or create a new case for +yourself. If you do not select a case and role to join, you will +be automatically assigned to a case and role when the simulation +begins. + +</if> +<else> + +Select which case to join, or create a new case for +yourself. If you do not select a case to join, you will +be automatically assigned to a case when the simulation +begins. + +</else> + + + Check for duplicate keys. For common words such as + Yes and No, you can use a library of keys at acs-kernel. + For example, instead of using + myfirstpackage.Yes, you + can use acs-kernel.Yes. + You can also use the Message Key Search facility to find duplicates. + Be careful, however, building up sentences from keys + because grammar and other elements may not be consistent + across different locales. + Additional discussion: Re: + Bug 961 ("Control Panel" displayed instead of + "Administer"), Translation + server upgraded, and Localization questions. + + + + - - Get the date in ANSI format from the database (YYYY-MM-DD - HH24:MI:SS; the time portion is optional). By convention, - we identify dates in ansi format by ending the column name - with _ansi. - Example: - select to_char(posting_date, 'YYYY-MM-DD HH24:MI:SS') as posting_date_ansi - from table - + + Replace the temporary message tags in ADP files + From the same Convert ADP ... page in /acs-admin/apm as in the last step, repeat the process but deselect Find human language text ... and select Replace <# ... #> tags ... and click OK. This step replaces all of the temporary tags with "short" message lookups, inserts the message keys into the database message catalog, and then writes that catalog out to an xml file. + + + + Replace human-readable text in TCL files with temporary tags + Examine all of the tcl files in the packages for human-readable text and replace it with temporary tags. The temporary tags in TCL are slightly different from those in ADP. If the first character in the temporary tag is an underscore (_), then the message keys will be auto-generated from the original message text. Here is an unmodified tcl file: + + +set title "Messages for $a(name) in $b(label)" +set context [list [list . "SimPlay"] \ + [list [export_vars -base case-admin { case_id }] \ + "Administer $a(name)"] \ + "Messages for $a(name)"] + +... and here is the same file after temporary message tags have been manually added: + +set title <#admin_title Messages for %a.name% in %b.label%#> +set context [list [list . <#_ SimPlay#>] \ + [list [export_vars -base case-admin { case_id }] \ + <#_ Administer %a.name%#>] \ + <#_ Messages for %a.name%#>] + + Note that the message key case_admin_page_title was manually selected, because an autogenerated key for this text, with its substitute variables, would have been very confusing + + - - Use the Tcl command lc_time_fmt to format the - date in "pretty" format. Several standard formats localize automatically: + + Replace the temporary message tags in TCL files + Repeat step 2 for tcl files. Here is the example TCL file after conversion: + + +set title [_ simulation.admin_title] +set context [list [list . [_ simulation.SimPlay]] \ + [list [export_vars -base case-admin { case_id }] \ + [_ simulation.lt_Administer_name_gt]] \ + [_ simulation.lt_Messages_for_role_pre]] + + + + + Internationalize SQL Code + If there is any user-visible TCL code in the .sql or .xql files, internationalize that the same way as for the TCL files. + + + + + Internationalize Package Parameters + + See + + + + + + Internationalize Date and Time queries + + + + + Find datetime in .xql files. Use command line tools to find suspect SQL code: + grep -r "to_char.*H" * +grep -r "to_date.*H" * + + + + In SQL statements, replace the format string with the ANSI standard format, YYYY-MM-DD HH24:MI:SS and change the field name to *_ansi so that it cannot be confused with previous, improperly formatting fields. For example, + to_char(timestamp,'MM/DD/YYYY HH:MI:SS') as foo_date_pretty + becomes + to_char(timestamp,'YYYY-MM-DD HH24:MI:SS') as foo_date_ansi + + + + In TCL files where the date fields are used, convert the datetime from local server timezone, which is how it's stored in the database, to the user's timezone for display. Do this with the localizing function lc_time_system_to_conn: + +set foo_date_ansi [lc_time_system_to_conn $foo_date_ansi] + When a datetime will be written to the database, first convert it from the user's local time to the server's timezone with lc_time_conn_to_system. + + + When a datetime field will be displayed, format it using the localizing function lc_time_fmt. lc_time_fmt takes two parameters, datetime and format code. Several format codes are usable for localization; they are placeholders that format dates with the appropriate codes for the user's locale. These codes are: %x, %X, %q, %Q, and %c. + set foo_date_pretty [lc_time_fmt $foo_date_ansi "%x %X"] + + + Use the _pretty version in your ADP page. + + + @@ -610,82 +700,52 @@ strftime). - set posting_date_pretty [lc_time_fmt $posting_date_ansi "%q"] - + + - - - Use the *_pretty version in your ADP page. - + + Internationalize Numbers + + To internationalize numbers, use lc_numeric $value, which formats the number using the appropriate decimal point and thousand separator for the locale. + + - - + + + Internationalizing Forms + When coding forms, remember to use message keys for each piece of text that is user-visible, including form option labels and button labels. + + - - To internationalize numbers, use lc_numeric $value, which formats the number using the appropriate decimal point and thousand separator for the locale. - - - + + - - Internationalizing Forms - When coding forms, remember to use message keys for each piece of text that is user-visible, including form option labels and button labels. - - + Checking the Consistency of Catalog Files - - - Internationalizing Existing Packages - - - Internationalize Message text in ADP and TCL - - Acs-lang includes tools to automate some - internationalization. From - /acs-admin/apm/, select a - package and then click on - Internationalization, then - Convert ADP, Tcl, and SQL files to using the - message catalog.. - - - - Internationalize Package Parameters with visible messages - See - - + This section describes how to check that the set of keys used in + message lookups in tcl, adp, and info files and the set of keys in + the catalog file are identical. The scripts below assume that + message lookups in adp and info files are on the format + \#package_key.message_key\#, and that message lookups in tcl files + are always is done with one of the valid lookups described above. The script further assumes + that you have perl installed and in your path. Run the script like + this: + + + + acs-lang/bin/check-catalog.sh package_key + - - Internationalize Date and Time queries - - - Find datetime in .xql files. Use command line tools to find suspect SQL code: - grep -r "to_char.*H" * -grep -r "to_date.*H" * - - - - In SQL statements, replace the format string with the ANSI standard format, YYYY-MM-DD HH24:MI:SS and change the field name to *_ansi so that it cannot be confused with previous, improperly formatting fields. For example, - to_char(timestamp,'MM/DD/YYYY HH:MI:SS') as foo_date_pretty - becomes - to_char(timestamp,'YYYY-MM-DD HH24:MI:SS') as foo_date_ansi - - - - In TCL files where the date fields are used, convert the datetime from local server timezone, which is how it's stored in the database, to the user's timezone for display. Do this with the localizing function lc_time_system_to_conn: - -set foo_date_ansi [lc_time_system_to_conn $foo_date_ansi] - When a datetime will be written to the database, first convert it from the user's local time to the server's timezone with lc_time_conn_to_system. - - - - When a datetime field will be displayed, format it using the localizing function lc_time_fmt. lc_time_fmt takes two parameters, datetime and format code. Several format codes are usable for localization; they are placeholders that format dates with the appropriate codes for the user's locale. These codes are: %x, %X, %q, %Q, and %c. - set foo_date_pretty [lc_time_fmt $foo_date_ansi "%x %X"] - - - + + where package_key is the key of the package that you want to + test. If you don't provide the package_key argument then all + packages with catalog files will be checked. + The script will run its checks primarily on en_US xml catalog files. + + + @@ -704,4 +764,43 @@ found, then that locale is offered instead. + + Translator's Guide + Most translators use the OpenACS Public Translation Server, because the process of getting new message keys onto the server and getting new translations back into the distribution are handled by the maintainers of that machine. You can also do translation work on your own OpenACS site; this makes your own translations more readily available to you but also means that your work will not be shared with other users unless you take extra steps (contacting an OpenACS core developer or submitting a patch) to get your work back to the OpenACS core. + The basic steps for translators: + + + Go to the Localization page and choose the locale that you are translating to. If the locale is not present you need to visit Administration of Localization and create the locale. + + + + Translating with Translator Mode + To translate messages in the pages they appear, Toggle Translator Mode and then browse to the page you want to translate. Untranslated messages will have a yellow background and a red star that you click to translate the message. Translated messages have a green star next to them that is a hyperlink to editing your translation. There is a history mechanism that allows you to see previous translations in case you would want to revert a translation. + + + + + + + While in Translator mode, a list of all message keys appears at the bottom of each page. + + + + + + + + + Batch translation + To translate many messages at once, go to Administration of Localization, click on the locale to translate, then click on a package, and then click Batch edit these messages. + + + + + + + + + + Index: openacs-4/packages/acs-core-docs/www/xml/developers-guide/permissions.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/xml/developers-guide/permissions.xml,v diff -u -r1.10 -r1.10.2.1 --- openacs-4/packages/acs-core-docs/www/xml/developers-guide/permissions.xml 12 Feb 2004 22:06:27 -0000 1.10 +++ openacs-4/packages/acs-core-docs/www/xml/developers-guide/permissions.xml 17 Apr 2004 14:11:03 -0000 1.10.2.1 @@ -416,7 +416,10 @@ set user_id [ad_conn user_id] set context_bar [ad_context_bar] -set create_p [ad_permission_p $package_id create] +set create_p [permission::permission_p \ + -object_id $package_id \ + -privilege create \ + -party_id $user_id] db_multirow notes notes { select note_id, owner_id, title, body, @@ -449,7 +452,7 @@ This example shows both the Tcl and PL/SQL APIs for checking -permissions. The Tcl proc ad_permission_p and the PL/SQL +permissions. The Tcl proc permission::permission_p and the PL/SQL function acs_permission.permission_p both return a flag indicating whether the current user has permission to perform the given action. By default, the Tcl procedure extracts the user_id out Index: openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-advanced.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-advanced.xml,v diff -u -r1.19 -r1.19.2.1 --- openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-advanced.xml 2 Mar 2004 19:02:15 -0000 1.19 +++ openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-advanced.xml 17 Apr 2004 14:11:03 -0000 1.19.2.1 @@ -613,6 +613,18 @@ + + Profile your code + There are several facilities for profiling your code in + OpenACS. The first thing to do is to install the + developer-support package and play around with it. But there + is also support in the API for profiling your code: + profiling + your code using ds_profile + + + Prepare the package for distribution. Browse to the package manager. Click on @@ -865,6 +877,116 @@ look at the forums package. + + Hierarchical data + + by Jade Rubick + with help from many people in the OpenACS community + + + One of the nice things about using the OpenACS object system + is that it has a built-in facility for tracking hierarchical data + in an efficient way. The algorithm behind this is called + tree_sortkey. + + Any time your tables are subclasses of the acs_objects + table, then you automatically get the ability to structure them + hierarchically. The way you do this is currently via the + context_id column of + acs_objects (Note that there is talk of adding in a + parent_id column instead, because + the use of context_id has been + ambiguous in the past). So when you want to build your hierarchy, + simply set the context_id values. Then, when you want to make + hierarchical queries, you can do them as follows: + + + db_multirow categories blog_categories " + SELECT + c.*, + o.context_id, + tree_level(o.tree_sortkey) + FROM + blog_categories c, + acs_objects o + WHERE + c.category_id = o.object_id + ORDER BY + o.tree_sortkey" + + + Note the use of the + tree_level() function, which + gives you the level, starting from 1, 2, 3... + + Here's an example, pulling all of the children for a given + parent: + + + SELECT + children.*, + tree_level(children.tree_sortkey) - + tree_level(parent.tree_sortkey) as level + FROM + some_table parent, + some_table children + WHERE + children.tree_sorktey between parent.tree_sortkey and tree_right(parent.tree_sortkey) + and parent.tree_sortkey <> children.tree_sortkey + and parent.key = :the_parent_key; + + + The reason we substract the parent's tree_level from the + child's tree_level is that the tree_levels are global, so if you + want the parent's tree_level to start with 0, you'll want the + subtraction in there. This is a reason you'll commonly see magic + numbers in tree_sortkey SQL queries, like + tree_level(children.tree_sortkey) - + 4. That is basically an incorrect way to do it, + and subtracting the parent's tree_level is the preferred method. + + This example does not include the parent. To return the entire subtree including the parent, leave out the non-equals clause: + + + SELECT + subtree.*, + tree_level(children.tree_sortkey) - + tree_level(parent.tree_sortkey) as level + FROM some_table parent, some_table subtree + WHERE + subtree.tree_sorktey between parent.tree_sortkey and tree_right(parent.tree_sortkey) + and parent.key = :the_parent_key; + + + If you are using the Content Repository, you get a similar + facility, but the parent_id + column is already there. Note you can do joins with + tree_sortkey: + + + SELECT + p.item_id, + repeat(:indent_pattern, (tree_level(p.tree_sortkey) - 5)* :indent_factor) as indent, + p.parent_id as folder_id, + p.project_name + FROM pm_projectsx p, cr_items i + WHERE p.project_id = i.live_revision + ORDER BY i.tree_sortkey + + + This rather long thread explains How + tree_sortkeys work and this paper describes + the technique for tree_sortkeys, although the OpenACS + implementation has a few differences in the + implementation, to make it work for many languages and the + LIKE construct in Postgres. + + + + Using .vuh files for pretty urls .Vuh files are special cases of .tcl files, used for rewriting incoming urls. We can use a vuh file to prettify the uri for our notes. Instead of note-edit?item_id=495, we can use note/495. To do this, we will need a new .vuh file for redirection and we will need to change the referring links in note-list. First, add the vuh: Index: openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-debug.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-debug.xml,v diff -u -r1.8 -r1.8.2.1 --- openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-debug.xml 26 Feb 2004 15:28:37 -0000 1.8 +++ openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-debug.xml 17 Apr 2004 14:11:03 -0000 1.8.2.1 @@ -110,7 +110,7 @@ } To create a test case you call -aa_register_case test_case_name.. +aa_register_case test_case_name.. Once you've created the test case you start writing the needed logic. We'll use the tutorial package, "myfirstpackage," as an example. Let's say you just wrote an API for adding and deleting notes in the @@ -147,11 +147,18 @@ set name [ad_generate_random_string] set new_id [mfp::note::add -title $name] aa_true "Note add succeeded" [exists_and_not_null new_id] - To test our simple case, we must load the test file into the system (just as with the /tcl file in the basic tutorial, since the file didn't exist when the system started, the system doesn't know about it.) To make this file take effect, go to the APM and choose "Reload changed" for "MyFirstPackage". Since we'll be changing it frequently, select "watch this file" on the next page. This will cause the system to check this file every time any page is requested, which is bad for production systems but convenient for developing. + To test our simple case, we must load the test file into the system (just as with the /tcl file in the basic tutorial, since the file didn't exist when the system started, the system doesn't know about it.) To make this file take effect, go to the APM and choose "Reload changed" for "MyFirstPackage". Since we'll be changing it frequently, select "watch this file" on the next page. This will cause the system to check this file every time any page is requested, which is bad for production systems but convenient for developing. We can also add some aa_register_case flags to make it easier to run the test. The -procs flag, which indicates which procs are tested by this test case, makes it easier to find procs in your package that aren't tested at all. The -cats flag, setting categories, makes it easier to control which tests to run. The smoke test setting means that this is a basic test case that can and should be run any time you are doing any test. (a definition of "smoke test") Once the file is loaded, go to ACS Automated Testing and click on myfirstpackage. You should see your test case. Run it and examine the results. - Now we can add the rest of the API tests. The complete test looks like: + + TCLWebtest tests + API testing can only test part of our package - it doesn't test the code in our adp/tcl pairs. For this, we can use TCLwebtest. TCLwebtest must be installed for this test to work. This provides a library of functions that make it easy to call a page through HTTP, examine the results, and drive forms. TCLwebtest's functions overlap slightly with acs-automated-testing; see the example provided for one approach on integrating them. + + + Example + Now we can add the rest of the API tests, including a test with deliberately bad data. The complete test looks like: example missing See also . + Index: openacs-4/packages/acs-core-docs/www/xml/install-guide/aolserver4.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/xml/install-guide/aolserver4.xml,v diff -u -r1.6 -r1.6.2.1 --- openacs-4/packages/acs-core-docs/www/xml/install-guide/aolserver4.xml 21 Feb 2004 07:03:59 -0000 1.6 +++ openacs-4/packages/acs-core-docs/www/xml/install-guide/aolserver4.xml 17 Apr 2004 14:11:03 -0000 1.6.2.1 @@ -104,6 +104,18 @@ nspostgres.c: In function `Ns_PgTableList': nspostgres.c:679: warning: passing arg 3 of `Tcl_DStringAppend' as signed due to prototype then PostGreSQL is probably not in the standard location. The location of PostGreSQL is very dependent on which method was used to install it. To correct the problem, replace LSB with the path to the path to your PostGreSQL installation. Often this is /usr/local/pgsql. + Another possibility is that you may need to set + the LD_LIBRARY_PATH environmental variable. You may + still get warnings, but sometimes this will fix things + enough to work. + [root nspostgres]# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/pgsql/lib + + You can use the + ldd command to verify + that all libraries are linked in: + ldd nspostgres.so + + If you run into problems with libpq.a do the following (and repeat the step above) [root nspostgres]# ranlib /usr/local/pgsql/lib/libpq.a If you run into problems with the linker, edit the Makefile. Add -lnsdb to the MODLIBS var. @@ -165,6 +177,8 @@ chmod 755 nsd-postgres + You may need to edit these scripts if you are not using + /usr/local/aolserver as the directory of Aolserver4. @@ -176,4 +190,4 @@ ($Id$) - \ No newline at end of file + 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 -r1.12 -r1.12.2.1 --- openacs-4/packages/acs-core-docs/www/xml/install-guide/maintenance.xml 12 Mar 2004 13:44:57 -0000 1.12 +++ openacs-4/packages/acs-core-docs/www/xml/install-guide/maintenance.xml 17 Apr 2004 14:11:03 -0000 1.12.2.1 @@ -474,13 +474,13 @@ - Installing SSL Support - nsopenssl is an open-sounce module for AOLserver which - adds support for the ssl encryption layer. To use it, you - must install the software, create or purchase certificates, - and configure your OpenACS instance to use it. + Installing SSL Support for an OpenACS service + Debian Users: apt-get install openssl before proceeding. + Make sure nsopenssl.so is installed for AOLserver. + + Uncomment this line from config.tcl. #ns_param nsopenssl ${bindir}/nsopenssl.so Index: openacs-4/packages/acs-core-docs/www/xml/install-guide/other-software.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/xml/install-guide/other-software.xml,v diff -u -r1.13 -r1.13.2.1 --- openacs-4/packages/acs-core-docs/www/xml/install-guide/other-software.xml 27 Feb 2004 11:20:58 -0000 1.13 +++ openacs-4/packages/acs-core-docs/www/xml/install-guide/other-software.xml 17 Apr 2004 14:11:03 -0000 1.13.2.1 @@ -817,7 +817,22 @@ - To enable SSL support in your server, make sure your config.tcl file has a section on "OpenSSL 3 with AOLserver4". If your ports for SSL are priviledged (below 1024), you will have to start AOLserver with prebinds for both your HTTP and your HTTPS port (usually by adding -b your_ip:your_http_port,your_ip:your_https_port to the nsd call). + + SSL support must be enabled seperately in each OpenACS + server (. + + If your ports for SSL are priviledged (below 1024), you + will have to start AOLserver with prebinds for both your HTTP + and your HTTPS port (usually by adding -b + your_ip:your_http_port,your_ip:your_https_port + to the nsd call. If you are using daemontools, this can be + changed in your etc/daemontools/run + file). + + To enable SSL support in your server, make sure your + etc/config.tcl file has a section on "OpenSSL 3 with AOLserver4". If + that section is not present, try looking at the README file in + /usr/local/src/aolserver/nsopenssl. Index: openacs-4/packages/acs-core-docs/www/xml/install-guide/upgrade.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/xml/install-guide/upgrade.xml,v diff -u -r1.15 -r1.15.2.1 --- openacs-4/packages/acs-core-docs/www/xml/install-guide/upgrade.xml 10 Mar 2004 03:49:51 -0000 1.15 +++ openacs-4/packages/acs-core-docs/www/xml/install-guide/upgrade.xml 17 Apr 2004 14:11:03 -0000 1.15.2.1 @@ -1,5 +1,5 @@ - %myvars; @@ -286,7 +286,7 @@ Upgrading a Custom or CVS site - If you have no custom code, and your site is not in a CVS repository, upgrade with these steps: + If you have custom code, and your site is in a CVS repository, upgrade with these steps: @@ -322,16 +322,16 @@ Unpack the tarball into a new directory and copy its contents on top of your working directory. [root root]# su - service0 - [service0 aolserver]$ cd /var/lib/aolserver - [service0 web]$ tar xzf /tmp/openacs-4-6.tgz - [service0 web]$ cp -r openacs-4-6/* openacs-4 - [service0 openacs-upgrade]$ exit - [root root]# - su - service0 - cd /var/lib/aolserver - tar xzf /tmp/openacs-4-6.tgz - cp -r openacs-4-6/* openacs-4 - exit +[service0 aolserver]$ cd /var/lib/aolserver +[service0 web]$ tar xzf /tmp/openacs-4-6.tgz +[service0 web]$ cp -r openacs-4-6/* openacs-4 +[service0 openacs-upgrade]$ exit +[root root]# +su - service0 +cd /var/lib/aolserver +tar xzf /tmp/openacs-4-6.tgz +cp -r openacs-4-6/* openacs-4 +exit @@ -345,69 +345,155 @@ - + - Unpack the new files into a working directory. + + Step 1: Import new CVS code + There are two common ways to get new OpenACS code into your local CVS repository - via tarball or with a working CVS checkout of OpenACS. Both methods work well for starting your local repository; the second method is better for incremental additions or upgrades. + + + + + (a): via tarball + Download a current tarball and unpack the new files into a working directory. + [root root]# su - service0 - [service0 aolserver]$ cd /tmp - [service0 tmp]$ tar xzf openacs-4-6.tgz - [service0 tmp]$ cd openacs-4.6 +[service0 aolserver]$ cd /tmp +[service0 tmp]$ tar xzf openacs-4-6.tgz +[service0 tmp]$ cd openacs-4.6 + + + + (b): via cvs working checkout + Create a CVS checkout from OpenACS. The first time you do this, you will need to create the checkout directory. We use one dedicated directory for each branch of OpenACS - if you are using OpenACS 5.0,x, you only need an OpenACS 5.0 branch. The openacs-5-0-compat tag identifies the latest released version of OpenACS 5.0 (ie, 5.0.3 or 5.0.4) and the latest compatible version of each package, including .LRN. Each minor release of OpenACS since 5.0 has this tagging structure. (Ie., OpenACS 5.1.x has openacs-5-1-compat.) + + [root root]# su - service0 +[service0 aolserver]$ cd /var/lib/aolserver +[service0 aolserver]$ cvs -d :pserver:anonymous@openacs.org:/cvsroot checkout -r openacs-5-0-compat openacs-4 +[service0 aolserver]$ mv openacs-4 openacs-5-0 + If this checkout already exists, you can simply update it instead of recreating it. + [root root]# su - service0 +[service0 aolserver]$ cd /var/lib/aolserver/openacs-5-0 +[service0 aolserver]$ cvs up -Pd + + + + (c) A single package via cvs working checkout + You can add or upgrade a single package at a time, if you already have a cvs working directory. + + [root root]# su - service0 +[service0 aolserver]$ cd /var/lib/aolserver/openacs-5-0 +[service0 openacs-5-0]$ cvs up -d myfirstpackage + In the next section, the import must be tailored to just this package. + + + + + + Step 2: Merge New OpenACS code + Now that you have a local copy of the new OpenACS code, you need to import it into your local CVS repository and resolve any conflicts that occur. + Import the new files into your cvs repository; where they match existing files, they will become the new version of the file. - [service0 openacs-4.6]$ cvs import -m "upgrade to OpenACS 4.6" openacs - OpenACS openacs-4-6 + [service0 openacs-4.6]$ cvs -d /var/lib/cvs import -m "upgrade to OpenACS 4.6" openacs OpenACS openacs-4-6 + + If adding or upgrading a single package, run the cvs import from within the base directory of that package, and adjust the cvs command accordingly. In this example, we are adding the myfirstpackage package. + [root root]# su - service0 +[service0 aolserver]$ cd /var/lib/aolserver/openacs-5-0/packagse/myfirstpackage +[service0 myfirstpackage]$ cvs -d /var/lib/cvs/ import -m "importing package" service0/packages/myfirstpackage + + Create a new directory as temporary working space to reconcile conflicts between the new files and your current work. The example uses the cvs keyword yesterday, making the assumption that you haven't checked in new code to your local tree in the last day. [service0 openacs-4.6]$ cd /var/lib/aolserver - [service0 tmp]$ mkdir openacs-upgrade - [service0 tmp]$ cvs checkout -d openacs-upgrade -jOpenACS:yesterday -jOpenACS openacs > cvs.txt 2>&1 - (CVS feedback here) - su - service0 - cd /tmp - tar xzv openacs-4-6.tgz - cd openacs-4.6 - cvs import -m "upgrade to OpenACS 4.6" openacs OpenACS openacs-4-6 - cd /tmp - mkdir openacs-upgrade - cvs checkout -d openacs-upgrade -jOpenACS:yesterday -jOpenACS openacs > cvs.txt 2>&1 - - - The file /tmp/openacs-upgrade/cvs.txt contains the results of the upgrade. If you changed files that are part of the OpenACS tarball and those changes conflict with the 4.5-4.6 upgrade, you'll have to manually reconcile them. Use the emacs command M-x sort-lines and then, for each line that starts with a C, open that file and manually resolve the conflict by deleting the excess lines. When you're finished, or if there aren't any conflicts, save and exit. - - +[service0 tmp]$ mkdir service0-upgrade +[service0 tmp]$ cvs checkout -d openacs-upgrade -jOpenACS:yesterday -jOpenACS openacs > cvs.txt 2>&1 +(CVS feedback here) + + The file /tmp/openacs-upgrade/cvs.txt contains the results of the upgrade. If you changed files that are part of the OpenACS tarball and those changes conflict with the 4.5-4.6 upgrade, you'll have to manually reconcile them. Use the emacs command M-x sort-lines and then, for each line that starts with a C, open that file and manually resolve the conflict by deleting the excess lines. When you're finished, or if there aren't any conflicts, save and exit. Once you've fixed any conflicts, commit the new code to your local tree. [service0 tmp]$ cd openacs-upgrade - [service0 openacs-upgrade]$ cvs commit -m "Upgraded to 4.6" - cd openacs-upgrade - cvs commit -m "Upgraded to 4.6" - +[service0 openacs-upgrade]$ cvs commit -m "Upgraded to 4.6" + + Step 3: Upgrade your local staging site Update your working tree with the new files. The CVS flags ensure that new directories are created and pruned directories destroyed. - [service0 openacs-upgrade]$ cd /var/lib/aolserver/service0 - [service0 service0]$ cvs up -Pd - (CVS feedback) - [service0 service0]$ exit - [root root]# - cd /var/lib/aolserver/service0 - cvs up -Pd - exit + +[service0 openacs-upgrade]$ cd /var/lib/aolserver/service0 +[service0 service0]$ cvs up -Pd +(CVS feedback) +[service0 service0]$ exit +[root root]# + + + + + + Upgrading files for a site using the OpenACS.org CVS repository + + + + [service0 ~]$ cd /var/lib/aolserver/service0 +[service0 service0]$ cvs up -Pd +(CVS feedback) +[service0 service0]$ - - - - - Upgrading files for a site using the OpenACS.org CVS repository - + + + Upgrading a Production Site Safely + If you are upgrading a production OpenACS site which is on a private CVS tree, this process lets you do the upgrade without risking extended downtime or an unusable site: + + + Declare a freeze on new cvs updates - ie, you cannot run cvs update + on the production site + + + + Make a manual backup of the production site in addition to the + automated backups + + + Import the new code (for example, OpenACS 5.0.4, openacs-5-0-compat versions of + ETP, blogger, and other applications) into a "vendor branch" of the + service0 CVS tree, as described in "Upgrading a local CVS repository", step 1, above. + As soon as we do this, any cvs update command on production might bring new code onto the production site, which + would be bad. + Do step 2 above (merging conflicts in a service0-upgrade working tree). + + + + Manually resolve any conflicts in the working upgrade tree + + + + Use the upgrade script and a recent backup of the production database, to ake + a new upgraded database called service0-upgrade. Now we + have a new website called service0-upgrade. + + + + + Test the service0-upgrade site + + + + If service0-upgrade is fully functional, do the real upgrade. - [service0 ~]$ cd /var/lib/aolserver/service0 - [service0 service0]$ cvs up -Pd - (CVS feedback) - [service0 service0]$ + Take down the service0 site and put up a "down for maintenance" page. + + Repeat the upgrade with the most recent database + + + Test the that the new site is functional. If so, change the upgraded site to respond to + yourserver.net requests. If not, bring the original production site back up and return to the merge. + - - + + + + Upgrading Platform components @@ -463,9 +549,9 @@ [service0 dev]$ exit [root root]# su - service0 - psql service0 -f /usr/local/pgsql/share/contrib/openfts.sql - psql service0 -f /usr/local/src/postgresql-7.2.3/contrib/tsearch/tsearch.sql - exit +psql service0 -f /usr/local/pgsql/share/contrib/openfts.sql +psql service0 -f /usr/local/src/postgresql-7.2.3/contrib/tsearch/tsearch.sql +exit