Index: openacs-4/packages/acs-core-docs/www/acs-admin.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/acs-admin.html,v diff -u -r1.44 -r1.44.2.1 --- openacs-4/packages/acs-core-docs/www/acs-admin.html 31 Jul 2011 23:11:45 -0000 1.44 +++ openacs-4/packages/acs-core-docs/www/acs-admin.html 21 Aug 2013 10:19:18 -0000 1.44.2.1 @@ -1,2 +1,2 @@ - -
Table of Contents
Table of Contents
Tutorials and reference material for creating new OpenACS packages. -
Table of Contents
Tutorials and reference material for creating new OpenACS packages. +
Table of Contents
Table of Contents
Prev | Home | Next |
Appendix C. Using CVS with an OpenACS Site | Up | Chapter 13. Kernel Documentation |
Table of Contents
Prev | Home | Next |
Appendix D. Using CVS with an OpenACS Site | Up | Chapter 15. Kernel Documentation |
Download the Analog source tarball in -/tmp. Unpack, compile, and install analog.
[root aolserver]# cd /usr/local/src -[root src]# tar xzf /tmp/analog-5.32.tar.gz -[root src]# cd analog-5.32 -[root analog-5.32]# make + +Install Analog web file analyzer Download the Analog source tarball in +
/tmp
. Unpack, compile, and install analog.[root aolserver]#cd /usr/local/src
+[root src]#tar xzf /tmp/analog-5.32.tar.gz
+[root src]#cd analog-5.32
+[root analog-5.32]#make
cd src && make make[1]: Entering directory `/usr/local/src/analog-5.32/src' (many lines omitted) ***IMPORTANT: You must read the licence before using analog *** make[1]: Leaving directory `/usr/local/src/analog-5.32/src' -[root analog-5.32]# cd .. -[root src]# mv analog-5.32 /usr/share/ +[root analog-5.32]#cd ..
+[root src]#mv analog-5.32 /usr/share/
[root src]# cd /usr/local/src tar xzf /tmp/analog-5.32.tar.gz cd analog-5.32 make cd .. -mv analog-5.32 /usr/share/See also ???
View comments on this page at openacs.org +mv analog-5.32 /usr/share/
Analog is a program with processes webserver access logs, + +
Analog is a program with processes webserver access logs, performs DNS lookup, and outputs HTML reports. Analog should - already be + already be installed. A modified configuration file is included in - the OpenACS tarball.
[root src]# su - $OPENACS_SERVICE_NAME -[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ cd /var/lib/aolserver/$OPENACS_SERVICE_NAME -[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ mkdir www/log -[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ cp -r /usr/share/analog-5.32/images www/log/ + the OpenACS tarball.
[root src]#su - $OPENACS_SERVICE_NAME
+[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$cd /var/lib/aolserver/$OPENACS_SERVICE_NAME
+[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$mkdir www/log
+[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$cp -r /usr/share/analog-5.32/images www/log/
[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ su - $OPENACS_SERVICE_NAME cd /var/lib/aolserver/$OPENACS_SERVICE_NAME cp /var/lib/aolserver/$OPENACS_SERVICE_NAME/packages/acs-core-docs/www/files/analog.cfg.txt etc/analog.cfg mkdir www/log cp -r /usr/share/analog-5.32/images www/log/Edit -/var/lib/aolserver/$OPENACS_SERVICE_NAME/etc/analog.cfg and change the variable in HOSTNAME "[my -organisation]" to reflect your website title. If you +
/var/lib/aolserver/$OPENACS_SERVICE_NAME/etc/analog.cfg
and change the variable inHOSTNAME "[my +organisation]"
to reflect your website title. If you don't want the traffic log to be publicly visible, change -OUTFILE /var/lib/aolserver/$OPENACS_SERVICE_NAME/www/log/traffic.html to use a private -directory. You'll also need to edit all instances of service0 to your $OPENACS_SERVICE_NAME.Run it.
[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ /usr/share/analog-5.32/analog -G -g/var/lib/aolserver/$OPENACS_SERVICE_NAME/etc/analog.cfg +OUTFILE /var/lib/aolserver/$OPENACS_SERVICE_NAME/www/log/traffic.html
to use a private +directory. You'll also need to edit all instances of service0 to your $OPENACS_SERVICE_NAME.Run it.
[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$/usr/share/analog-5.32/analog -G -g/var/lib/aolserver/$OPENACS_SERVICE_NAME/etc/analog.cfg
/usr/share/analog-5.32/analog: analog version 5.32/Unix /usr/share/analog-5.32/analog: Warning F: Failed to open DNS input file /home/$OPENACS_SERVICE_NAME/dnscache: ignoring it (For help on all errors and warnings, see docs/errors.html) /usr/share/analog-5.32/analog: Warning R: Turning off empty Search Word Report -[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$Verify that it works by browing to http://yourserver.test:8000/log/traffic.html
Automate this by creating a file in - /etc/cron.daily.
[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ exit +[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$Verify that it works by browing to
http://yourserver.test:8000/log/traffic.html
Automate this by creating a file in +
/etc/cron.daily
.[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$exit
logout -[root root]# emacs /etc/cron.daily/analogPut this into the file:
#!/bin/sh +[root root]#emacs /etc/cron.daily/analog
Put this into the file:
#!/bin/sh -/usr/share/analog-5.32/analog -G -g/var/lib/aolserver/$OPENACS_SERVICE_NAME/etc/analog.cfg
[root root]# chmod 755 /etc/cron.daily/analogTest it by running the script.
[root root]# sh /etc/cron.daily/analogBrowse to http://yourserver.test/log/traffic.html
Prev | Home | Next |
Installing SSL Support for an OpenACS service | Up | External uptime validation |
[root root]# chmod 755 /etc/cron.daily/analog
Test it by running the script.
[root root]# sh /etc/cron.daily/analog
Browse to http://yourserver.test/log/traffic.html
Prev | Home | Next |
Installing SSL Support for an OpenACS service | Up | External uptime validation |
by Vinod Kurup
+ +by Vinod Kurup
OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff. -We recommend the use of AOLserver 4.0.1 or later. These instructions are retained as a resource.
+
We recommend the use of AOLserver 4.0.1 or later. These instructions are retained as a resource.
Debian users: we do not recommend installing Debian packages for Aolserver or Postgres. Several people have reported problems while trying to install using apt-get instead of from source. If you have the time to debug these and submit what you did, that's great, but if not, you should stick to installing from source. -
Unpack the Aolserver tarball. Download the aolserver tarball and unpack it.
[root root]# cd /usr/local/src -[root src]# wget --passive http://uptime.openacs.org/aolserver-openacs/aolserver3.3oacs1.tar.gz +
Unpack the Aolserver tarball. Download the aolserver tarball and unpack it.
[root root]#cd /usr/local/src
+[root src]#wget --passive http://uptime.openacs.org/aolserver-openacs/aolserver3.3oacs1.tar.gz
--15:38:08-- http://uptime.openacs.org/aolserver-openacs/aolserver3.3oacs1.tar.gz => `aolserver3.3oacs1.tar.gz' Resolving uptime.openacs.org... done. @@ -21,41 +21,41 @@ 100%[====================================>] 3,858,074 66.56K/s ETA 00:00 15:39:05 (66.56 KB/s) - `aolserver3.3oacs1.tar.gz' saved [3858074/3858074] -[root src]# tar xzf aolserver3.3oacs1.tar.gz +[root src]#tar xzf aolserver3.3oacs1.tar.gz
[root src]# cd /usr/local/src wget --passive http://uptime.openacs.org/aolserver-openacs/aolserver3.3oacs1.tar.gz -tar xzf aolserver3.3oacs1.tar.gzThis section also relies on some OpenACS files, which you can get with Section , “Unpack the OpenACS tarball”.
Compile AOLserver. Compile and install AOLserver. First, prepare the installation directory and the source code. The message about BUILD-MODULES can be ignored.
root@yourserver root]# mkdir -p /usr/local/aolserver -[root root]# cd /usr/local/src/aolserver -[root aolserver]# ./conf-clean +tar xzf aolserver3.3oacs1.tar.gzThis section also relies on some OpenACS files, which you can get with the section called “Unpack the OpenACS tarball”.
Compile AOLserver. Compile and install AOLserver. First, prepare the installation directory and the source code. The message about BUILD-MODULES can be ignored.
root@yourserver root]#mkdir -p /usr/local/aolserver
+[root root]#cd /usr/local/src/aolserver
+[root aolserver]#./conf-clean
cat: BUILD-MODULES: No such file or directory Done. [root aolserver]#mkdir -p /usr/local/aolserver cd /usr/local/src/aolserver ./conf-cleanIf you are using Oracle, edit - conf-db and change - postgresql to - oracle, or to the word - both if you want both drivers +
conf-db
and change +postgresql
to +oracle
, or to the word +both
if you want both drivers installed. In order to get nsoracle to compile, you may need to su - oracle, and then su (without the -) root to set the environment variables properly. -conf-inst should contain the +
conf-inst
should contain the location where AOLserver is to be installed. Overwrite the - tarball's default value with our default value, /usr/local/aolserver:[root aolserver]# echo "/usr/local/aolserver" > conf-inst -[root aolserver]#conf-make should contain the + tarball's default value with our default value,
/usr/local/aolserver
:[root aolserver]#echo "/usr/local/aolserver" > conf-inst
+[root aolserver]#
conf-make
should contain the name of the GNU Make command on your system. It defaults to - gmake. Debian users: ln -s /usr/bin/make /usr/bin/gmake.Set an environment variable that the nspostgres driver +
gmake
. Debian users:.
ln -s /usr/bin/make /usr/bin/gmake
Set an environment variable that the nspostgres driver Makefile needs to compile correctly and run - conf, which compiles +
conf
, which compiles AOLserver, the default modules, and the database driver, and installs them.Debian users, see warning above, but if you do use apt-get for AOLserver 3.3+ad13 and postgresql from apt-get may need to - make these symlinks: ln -s - /usr/include/postgresql/ /usr/include/pgsql - and ln -s /usr/lib/postgresql /usr/local/pgsql)
[root aolserver]# export POSTGRES=/usr/local/pgsql; ./conf + make these symlinks:ln -s + /usr/include/postgresql/ /usr/include/pgsql
+ andln -s /usr/lib/postgresql /usr/local/pgsql
)[root aolserver]#export POSTGRES=/usr/local/pgsql; ./conf
Building in /usr/local/aolserver with the following modules: aolserver @@ -77,27 +77,27 @@ ================================================================== Done Building Sat Mar 8 10:31:35 PST 2003 [root aolserver]#- This takes about 5 minutes. It builds aolserver, several modules, and the database driver. (Upgraders, note that the postgres database driver has changed from postgres.so to nspostgres.so). All of the results are logged to files in /usr/local/src/aolserver/log. If you run into problems running AOLserver, check these files for build errors.
Add a database-specific wrapper script. This script + This takes about 5 minutes. It builds aolserver, several modules, and the database driver. (Upgraders, note that the postgres database driver has changed from postgres.so to nspostgres.so). All of the results are logged to files in
/usr/local/src/aolserver/log
. If you run into problems running AOLserver, check these files for build errors.Add a database-specific wrapper script. This script sets database environment variables before starting AOLserver; this allows the AOLserver instance can communicate with the database. There is one script each for Oracle and PostgreSQL. They don't conflict, so if you plan - to use both databases, install both.
Oracle
[root aolserver]# cd /usr/local/aolserver/bin -[root bin]# cp /var/tmp/openacs-5.7.0/packages/acs-core-docs/www/files/nsd-oracle.txt ./nsd-oracle -[root bin]# chmod 750 nsd-oracle + to use both databases, install both.
Oracle
[root aolserver]#cd /usr/local/aolserver/bin
+[root bin]#cp /var/tmp/openacs-5.7.0/packages/acs-core-docs/www/files/nsd-oracle.txt ./nsd-oracle
+[root bin]#chmod 750 nsd-oracle
[root bin]# cd /usr/local/aolserver/bin cp /var/tmp/openacs-5.7.0/packages/acs-core-docs/www/files/nsd-oracle.txt ./nsd-oracle -chmod 750 nsd-oraclePostgreSQL
[root aolserver]# cd /usr/local/aolserver/bin -[root bin]# cp /var/tmp/openacs-5.7.0/packages/acs-core-docs/www/files/nsd-postgres.txt ./nsd-postgres -[root bin]# chmod 755 nsd-postgres +chmod 750 nsd-oraclePostgreSQL
[root aolserver]#cd /usr/local/aolserver/bin
+[root bin]#cp /var/tmp/openacs-5.7.0/packages/acs-core-docs/www/files/nsd-postgres.txt ./nsd-postgres
+[root bin]#chmod 755 nsd-postgres
[root bin]# cd /usr/local/aolserver/bin cp /var/tmp/openacs-5.7.0/packages/acs-core-docs/www/files/nsd-postgres.txt ./nsd-postgres -chmod 755 nsd-postgresInstall tDOM. Download the tDOM +chmod 755 nsd-postgres
Install tDOM. Download the tDOM tarball, unpack it, adjust the configuration file to match our patched - distribution of aolserver, and compile it.
[root root]# cd /usr/local/src -[root src]# wget --passive http://www.tdom.org/tDOM-0.7.8.tar.gz + distribution of aolserver, and compile it.[root root]#cd /usr/local/src
+[root src]#wget --passive http://www.tdom.org/tDOM-0.7.8.tar.gz
--16:40:58-- http://www.tdom.org/tDOM-0.7.8.tar.gz => `tDOM-0.7.8.tar.gz' Resolving www.tdom.org... done. @@ -109,54 +109,54 @@ 16:41:04 (138.06 KB/s) - `tDOM-0.7.8.tar.gz' saved [826613/826613] -[root src]# tar xzf tDOM-0.7.8.tar.gz -[root src]# cd tDOM-0.7.8/unix +[root src]#tar xzf tDOM-0.7.8.tar.gz
+[root src]#cd tDOM-0.7.8/unix
[root unix]# cd /usr/local/src wget --passive http://www.tdom.org/tDOM-0.7.8.tar.gz tar xzf tDOM-0.7.8.tar.gz cd tDOM-0.7.8/unixEdit the file CONFIG and change this section:
# ---------------------------------------------------- -# aolsrc="/usr/src/aolserver-3.4" +# aolsrc="/usr/src/aolserver-3.4" # ../configure --enable-threads --disable-tdomalloc \ # --with-aolserver=$aolsrc \ # --with-tcl=$aolsrc/tcl8.3.4/unixto
# ---------------------------------------------------- -aolsrc="/usr/local/src/aolserver/aolserver" +aolsrc="/usr/local/src/aolserver/aolserver" ../configure --enable-threads --disable-tdomalloc \ --with-aolserver=$aolsrc \ - --with-tcl=$aolsrc/tcl8.3.2/unixAnd configure and compile:
[root unix]# sh CONFIG + --with-tcl=$aolsrc/tcl8.3.2/unixAnd configure and compile:
[root unix]#sh CONFIG
creating cache ./config.cache checking for memmove... yes (many lines omitted) creating Makefile creating tdomConfig.sh -[root unix]# make +[root unix]#make
gcc -pipe -DHAVE_UNISTD_H=1 -DHAVE_LIMITS_H=1 -DTCL_THREADS=1 -DHAVE_GETCWD=1 -DHAVE_OPENDIR=1 -DHAVE_STRSTR=1 -DHAVE_STRTOL=1 (many lines omitted) -Wl,-rpath,/usr/local/lib -o tcldomsh;\ fi -[root unix]# cp libtdom0.7.8.so /usr/local/aolserver/bin/ -[root unix]# cd /usr/local/aolserver/bin/ -[root bin]# ln -s libtdom0.7.8.so libtdom.so +[root unix]#cp libtdom0.7.8.so /usr/local/aolserver/bin/
+[root unix]#cd /usr/local/aolserver/bin/
+[root bin]#ln -s libtdom0.7.8.so libtdom.so
[root bin]# sh CONFIG make cp libtdom0.7.8.so /usr/local/aolserver/bin/ cd /usr/local/aolserver/bin -ln -s libtdom0.7.8.so libtdom.soInstall nsopenssl - (OPTIONAL)
Install Full Text Search with OpenFTS (OPTIONAL)
Install nspam (OPTIONAL)
Test AOLserver. In order to test AOLserver, we'll run it using the +ln -s libtdom0.7.8.so libtdom.so
Install nsopenssl + (OPTIONAL)
Install Full Text Search with OpenFTS (OPTIONAL)
Install nspam (OPTIONAL)
Test AOLserver. In order to test AOLserver, we'll run it using the sample-config.tcl file provided in the AOLserver distribution, - under the nobody user and web + under the nobody user and
web
group. The sample-config.tcl configuration writes to the default log locations, so we need to give it permission to do so - or it will fail. Grant the web + or it will fail. Grant theweb
group permission to write to - /usr/local/aolserver/log and - /usr/local/aolserver/servers.[root root]# cd /usr/local/aolserver -[root aolserver]# chown -R root.web log servers -[root aolserver]# chmod -R g+w log servers -[root aolserver]# ls -l +/usr/local/aolserver/log
and +/usr/local/aolserver/servers
.[root root]#cd /usr/local/aolserver
+[root aolserver]#chown -R root.web log servers
+[root aolserver]#chmod -R g+w log servers
+[root aolserver]#ls -l
total 32 drwxr-sr-x 2 root root 4096 Mar 8 12:57 bin drwxr-xr-x 3 root root 4096 Mar 8 10:34 include @@ -171,12 +171,12 @@ chown -R root.web log servers chmod -R g+w log servers ls -lNote: AOLserver4.x does not include a default start page, so we create one for this test. Type - echo "Welcome to AOLserver" > /usr/local/aolserver40r8/servers/server1/pages/index.html +
echo "Welcome to AOLserver" > /usr/local/aolserver40r8/servers/server1/pages/index.html
Now, we'll run a quick test to ensure AOLserver is running correctly. We'll use the sample config file provided with AOLserver. This file will attempt to guess your IP address and hostname. It will then start up the server at port 8000 of that - IP address.
[root aolserver]# ./bin/nsd -t sample-config.tcl -u nobody -g web + IP address.[root aolserver]#./bin/nsd -t sample-config.tcl -u nobody -g web
[root aolserver]# [08/Mar/2003:15:07:18][31175.8192][-main-] Notice: config.tcl: starting to read config file... [08/Mar/2003:15:07:18][31175.8192][-main-] Warning: config.tcl: nsssl not loaded -- key/cert files do not exist. [08/Mar/2003:15:07:18][31175.8192][-main-] Warning: config.tcl: nscp not loaded @@ -185,32 +185,32 @@ config file.The first warning, about nsssl, can be ignored. We won't be using nsssl; we'll be using nsopenssl instead, and we haven't fully configured it yet. The nscp warning refers to the fact that, without a user and password in the config file, the administrative panel of AOLserver won't load. We don't plan to use it and can ignore that error as well. Any other warning or error is unexpected and probably a problem.
Test to see if AOLserver is working by starting - Mozilla or - Lynx on the same +
Mozilla
or +Lynx
on the same computer and surfing over to your web page. If you browse from another computer and the sample config file didn't guess your hostname or ip correctly, you'll get a false negative test. -[root aolserver]# lynx localhost:8000+
[root aolserver]#lynx localhost:8000
- You should see a "Welcome to AOLserver" page. If this + You should see a "Welcome to AOLserver" page. If this doesn't work, try going to - http://127.0.0.1:8000/. If this - still doesn't work, check out the Troubleshooting AOLserver section below. Note that you will not be able to browse to the web page from another machine, because AOLserver is only listening to the local address. +
http://127.0.0.1:8000/
. If this + still doesn't work, check out the Troubleshooting AOLserver section below. Note that you will not be able to browse to the web page from another machine, because AOLserver is only listening to the local address. -Shutdown the test server:
[root aolserver]# killall nsd +Shutdown the test server:
[root aolserver]#killall nsd
[root aolserver]#- The killall command will kill - all processes with the name nsd, + The
killall
command will kill + all processes with the namensd
, but clearly this is not a good tool to use for managing your - services in general. We cover this topic in the ??? section. + services in general. We cover this topic in the Keep AOLserver alive section. -Troubleshooting. If you can't view the welcome page, it's likely there's a +
Troubleshooting. If you can't view the welcome page, it's likely there's a problem with your server configuration. Start by viewing your AOLserver log, which is in - /usr/local/aolserver/log/server.log. +
/usr/local/aolserver/log/server.log
. You should also try to find lines of the form:[01/Jun/2000:12:11:20][5914.4051][-nssock-] Notice: nssock: listening on http://localhost.localdomain:8000 (127.0.0.1:8000) @@ -219,12 +219,12 @@ If you can find these lines, try entering the URL the server is listening on. If you cannot find these lines, there must be an error somewhere in the file. Search for lines beginning with the word - Error instead of - Notice. +Error
instead of +Notice
.- The sample-config.tcl file grabs + The
sample-config.tcl
file grabs your address and hostname from your OS settings.@@ -234,11 +234,11 @@ If you get an error that nssock can't get the requested address, you can set these manually. If you type 0.0.0.0, AOLserver will try to listen on all available addresses. Note: - ns_info address doesn't appear +ns_info address
doesn't appear to be supported in current versions of AOLserver.set hostname [ns_info hostname] #set address [ns_info address] -set address 0.0.0.0Install - Analog web file analyzer. (OPTIONAL)
($Id$)
Prev | Home | Next |
Install LDAP for use as external authentication | Up | Part III. For OpenACS Package Developers |
Install + Analog web file analyzer. (OPTIONAL)
Prev | Home | Next |
Install LDAP for use as external authentication | Up | Appendix C. Credits |
Check suitability of previously installed TCL. Start tcl (type tclsh or find it using which tclsh). -
[root root]% info exists tcl_platform(threaded) +
Check suitability of previously installed TCL. Start tcl (type tclsh
or find it using which tclsh
).
+
[root root]%info exists tcl_platform(threaded)
1 -[root root]% info patchlevel +[root root]%info patchlevel
8.4.7 [root root]% tclsh info exists tcl_platform(threaded) info patchlevel -
If the first command returns anything other than 1, +
If the first command returns anything other than 1
,
then tcl is not threaded. If tcl is threaded and the version is 8.4 or higher, then installing
tcl from source is optional.
Retrieve TCL 8.4 (or higher). Download and install TCL 8.4 from source
Note for Debian users: you can apt-get install tcl8.4-dev if you have the right version (stable users will need to add tcl8.4 to their sources.list file as described on the - Install Postgres page). You'll + Install Postgres page). You'll have to use /usr/lib/tcl8.4/ instead of /usr/local/lib when you - try to find the tcl libraries, however.
If you have not installed TCL already, download the latest TCL version from Sourceforge
Debian: - apt-get install - tcl8.4 tcl8.4-dev and proceed to + try to find the tcl libraries, however.
If you have not installed TCL already, download the latest TCL version from Sourceforge
Debian:
+ apt-get install
+ tcl8.4 tcl8.4-dev
and proceed to
the next step. In that step, replace
- --with-tcl=/usr/local/lib/ with
- --with-tcl=/usr/lib/tcl8.4.
Remember that you have to be root if you want to follow these instructions. On Mac OS X type sudo su - to become root.
Alternatively use curl -L -O instead of wget (especially on Mac OS X).
[root root]# cd /usr/local/src -[root src]# wget http://heanet.dl.sourceforge.net/sourceforge/tcl/tcl8.4.9-src.tar.gz -[root src]# tar xfz tcl8.4.9-src.tar.gz -[root src]# cd tcl8.4.9/unix -[root unix]# ./configure --enable-threads -[root unix]# make install +--with-tcl=/usr/local/lib/
with +--with-tcl=/usr/lib/tcl8.4
.Remember that you have to be root if you want to follow these instructions. On Mac OS X type
sudo su -
to become root.Alternatively use
curl -L -O
instead ofwget
(especially on Mac OS X).[root root]#cd /usr/local/src
+[root src]#wget http://heanet.dl.sourceforge.net/sourceforge/tcl/tcl8.4.9-src.tar.gz
+[root src]#tar xfz tcl8.4.9-src.tar.gz
+[root src]#cd tcl8.4.9/unix
+[root unix]#./configure --enable-threads
+[root unix]#make install
[root root]# cd /usr/local/src wget http://heanet.dl.sourceforge.net/sourceforge/tcl/tcl8.4.9-src.tar.gz tar xfz tcl8.4.9-src.tar.gz cd tcl8.4.9/unix ./configure --enable-threads make install -
Retrieve AOLserver. Download the aolserver from CVS.
[root root]# cd /usr/local/src -[root src]# mkdir aolserver40r10 -[root src]# cd aolserver40r10 -[root aolserver]# cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/aolserver login -[root aolserver]# cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/aolserver co -r aolserver_v40_r10 aolserver -[root aolserver]# cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/aolserver co nscache -[root aolserver]# cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/aolserver co nspostgres -[root aolserver]# cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/aolserver co nssha1 -[root aolserver]# cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/aolserver co -r v2_7 nsoracle -[root aolserver]# wget http://www.tdom.org/tDOM-0.7.8.tar.gz -[root aolserver]# tar xvfz tDOM-0.7.8.tar.gz -[root aolserver]# cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/tcllib co -r tcllib-1-8 tcllib +
Retrieve AOLserver. Download the aolserver from CVS.
[root root]#cd /usr/local/src
+[root src]#mkdir aolserver40r10
+[root src]#cd aolserver40r10
+[root aolserver]#cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/aolserver login
+[root aolserver]#cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/aolserver co -r aolserver_v40_r10 aolserver
+[root aolserver]#cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/aolserver co nscache
+[root aolserver]#cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/aolserver co nspostgres
+[root aolserver]#cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/aolserver co nssha1
+[root aolserver]#cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/aolserver co -r v2_7 nsoracle
+[root aolserver]#wget http://www.tdom.org/tDOM-0.7.8.tar.gz
+[root aolserver]#tar xvfz tDOM-0.7.8.tar.gz
+[root aolserver]#cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/tcllib co -r tcllib-1-8 tcllib
[root root]# cd /usr/local/src mkdir aolserver40r10 @@ -60,32 +60,32 @@ cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/aolserver co -r v2_7 nsoracle wget http://www.tdom.org/files/tDOM-0.8.0.tar.gz tar xvfz tDOM-0.8.0.tar.gz -cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/tcllib co -r tcllib-1-8 tcllib
Configure, compile and install AOLserver. Many people need to run more than one version of AOLserver in parallel. This section accomodates future upgrades by installing AOLserver 4 in /usr/local/aolserver40r9.
[root aolserver]# cd /usr/local/src/aolserver40r10/aolserver -[root aolserver]# ./configure --prefix=/usr/local/aolserver40r10 --with-tcl=/usr/local/lib/ -[root aolserver]# make install +cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/tcllib co -r tcllib-1-8 tcllib
Configure, compile and install AOLserver. Many people need to run more than one version of AOLserver in parallel. This section accomodates future upgrades by installing AOLserver 4 in /usr/local/aolserver40r9
.
[root aolserver]#cd /usr/local/src/aolserver40r10/aolserver
+[root aolserver]#./configure --prefix=/usr/local/aolserver40r10 --with-tcl=/usr/local/lib/
+[root aolserver]#make install
cd /usr/local/src/aolserver40r10/aolserver ./configure --prefix=/usr/local/aolserver40r10 --with-tcl=/usr/local/lib/ make install -
If you are using gcc 4 or later, see http://openacs.org/forums/message-view?message_id=309814
If this is the only version of AOLserver in use, or is the default version, create a symlink. If not, then be sure to use /usr/local/aolserver40r10 instead of /usr/local/aolserver in the steps below and check both scripts and makefiles to ensure they use the correct path.
[root aolserver]# ln -s /usr/local/aolserver40r10 /usr/local/aolserver
Configure, compile and install the modules. -
[root aolserver]# cd /usr/local/src/aolserver40r10/nscache -[root nscache]# make install AOLSERVER=/usr/local/aolserver
Install nsoracle (if you want to use Oracle)
[root nscache]# cd ../nsoracle -[root nsoracle]# make install AOLSERVER=/usr/local/aolserver
OpenACS looks for the Oracle driver at +
If you are using gcc 4 or later, see http://openacs.org/forums/message-view?message_id=309814
If this is the only version of AOLserver in use, or is the default version, create a symlink. If not, then be sure to use /usr/local/aolserver40r10
instead of /usr/local/aolserver
in the steps below and check both scripts and makefiles to ensure they use the correct path.
[root aolserver]# ln -s /usr/local/aolserver40r10 /usr/local/aolserver
Configure, compile and install the modules. +
[root aolserver]#cd /usr/local/src/aolserver40r10/nscache
+[root nscache]#make install AOLSERVER=/usr/local/aolserver
Install nsoracle (if you want to use Oracle)
[root nscache]#cd ../nsoracle
+[root nsoracle]#make install AOLSERVER=/usr/local/aolserver
OpenACS looks for the Oracle driver at /usr/local/aolserver/bin/ora8.so, but some versions of nsoracle may create nsoracle.so instead. In that case, you - can symlink (ln -s nsoracle.so ora8.so) to fix it.
Install nspostgres (if you want to use Postgres)
[root nscache]# cd ../nspostgres
-[root nspostgres]# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/pgsql/lib:/usr/local/aolserver/lib
-[root nspostgres]# make install POSTGRES=LSB ACS=1 INST=/usr/local/aolserver AOLSERVER=/usr/local/aolserver
+ can symlink (ln -s nsoracle.so ora8.so
) to fix it.
Install nspostgres (if you want to use Postgres)
[root nscache]#cd ../nspostgres
+[root nspostgres]#export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/pgsql/lib:/usr/local/aolserver/lib
+[root nspostgres]#make install POSTGRES=LSB ACS=1 INST=/usr/local/aolserver AOLSERVER=/usr/local/aolserver
If you get errors like:
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.
You can use the - ldd command to verify +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
.
You can use the
+ ldd
command to verify
that all libraries are linked in:
- ldd /usr/local/src/aolserver40r10/nspostgres/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.
MODLIBS = -L$(PGLIB) -lpq -lnsdb
[root nspostgres]# cd ../nssha1
Now install nssha1:
[root nssha1]# make install AOLSERVER=/usr/local/aolserver
If the make fails you will have to edit nssha1.c. Comment out the following 2 lines (lines 139-140):
// typedef unsigned int u_int32_t; -// typedef unsigned char u_int8_t;
[root nssha1]# cd ../tDOM-0.8.0/unix
Edit the CONFIG file. Uncomment the instructions meant for AOLserver 4, but edit it to look like this:
../configure --enable-threads --disable-tdomalloc - --prefix=/usr/local/aolserver --with-tcl=/usr/local/lib
Note that the location of the Tcl library may vary on differnt platforms (e.g. for Debian 3.0: --with-tcl=/usr/lib/tcl8.4)
Now you can compile and configure tDOM
[root unix]# sh CONFIG -[root unix]# make install
[root nssha1]# cd ../tcllib
Configure and compile TCLLIB
[root unix]# ./configure -prefix=/usr/local/aolserver40r10 -[root unix]# make install
-
Add a database-specific wrapper script. This script
+ ldd /usr/local/src/aolserver40r10/nspostgres/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.
MODLIBS = -L$(PGLIB) -lpq -lnsdb
[root nspostgres]# cd ../nssha1
Now install nssha1:
[root nssha1]# make install AOLSERVER=/usr/local/aolserver
If the make fails you will have to edit nssha1.c. Comment out the following 2 lines (lines 139-140):
// typedef unsigned int u_int32_t; +// typedef unsigned char u_int8_t;
[root nssha1]# cd ../tDOM-0.8.0/unix
Edit the CONFIG
file. Uncomment the instructions meant for AOLserver 4, but edit it to look like this:
../configure --enable-threads --disable-tdomalloc + --prefix=/usr/local/aolserver --with-tcl=/usr/local/lib
Note that the location of the Tcl library may vary on differnt platforms (e.g. for Debian 3.0: --with-tcl=/usr/lib/tcl8.4)
Now you can compile and configure tDOM
[root unix]#sh CONFIG
+[root unix]#make install
[root nssha1]# cd ../tcllib
Configure and compile TCLLIB
[root unix]#./configure -prefix=/usr/local/aolserver40r10
+[root unix]#make install
+
Add a database-specific wrapper script. This script sets database environment variables before starting AOLserver; this allows the AOLserver instance to communicate with the database. There is one script for @@ -99,17 +99,17 @@ OpenACS code, but don't forget to come back. (Note to maintainers: this should be moved to the next page and integrated into the text there) -
Oracle
[root aolserver]# cd /usr/local/aolserver/bin -[root bin]# cp /tmp/openacs-5.7.0/packages/acs-core-docs/www/files/nsd-oracle.txt ./nsd-oracle -[root bin]# chmod 750 nsd-oracle +
Oracle
[root aolserver]#cd /usr/local/aolserver/bin
+[root bin]#cp /tmp/openacs-5.7.0/packages/acs-core-docs/www/files/nsd-oracle.txt ./nsd-oracle
+[root bin]#chmod 750 nsd-oracle
[root bin]# cd /usr/local/aolserver/bin cp /var/tmp/openacs-5.7.0/packages/acs-core-docs/www/files/nsd-oracle.txt ./nsd-oracle -chmod 750 nsd-oraclePostgreSQL
[root aolserver]# cd /usr/local/aolserver/bin -[root bin]# cp /var/tmp/openacs-5.7.0/packages/acs-core-docs/www/files/nsd-postgres.txt ./nsd-postgres -[root bin]# chmod 755 nsd-postgres +chmod 750 nsd-oraclePostgreSQL
[root aolserver]#cd /usr/local/aolserver/bin
+[root bin]#cp /var/tmp/openacs-5.7.0/packages/acs-core-docs/www/files/nsd-postgres.txt ./nsd-postgres
+[root bin]#chmod 755 nsd-postgres
[root bin]# cd /usr/local/aolserver/bin cp /var/tmp/openacs-5.7.0/packages/acs-core-docs/www/files/nsd-postgres.txt ./nsd-postgres chmod 755 nsd-postgresYou may need to edit these scripts if you are not using - /usr/local/aolserver as the directory of Aolserver4.
Change startup script (optional). If you want to run AOLserver on a port below 1024 (normally, for a webserver you will use 80), you will have to change the /var/lib/aolserver/service0/etc/daemontools/run script according to the documentation found there (namely: Add the -b yourip:yourport switch)
Change startup script (optional). If you want to run AOLserver on a port below 1024 (normally, for a webserver you will use 80), you will have to change the /var/lib/aolserver/service0/etc/daemontools/run
script according to the documentation found there (namely: Add the -b yourip:yourport switch)
By Bryan Quinn
+ +By Bryan Quinn
OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff. -Tcl API
-apm-install-procs.tcl (Supports installation of packages)
-20-apm-load-procs.tcl (Bootstraps APM for server startup)
-apm-admin-procs.tcl (Supports APM UI)
PL/SQL file
Tcl API
+apm-install-procs.tcl (Supports installation of packages)
+20-apm-load-procs.tcl (Bootstraps APM for server startup)
+apm-admin-procs.tcl (Supports APM UI)
PL/SQL file
+In general terms, a package is a unit of software that serves a single well-defined purpose. That purpose may be to provide a service directly to one or more classes of end-user, (e.g., discussion forums and file storage for community members, user profiling tools for the site publisher), or it may be to act as a building block for other packages (e.g., an application programming interface (API) for storing and querying access control rules, or an API for scheduling email alerts). Thus, packages fall into one of two categories: -
OpenACS Applications: a "program or group of programs -designed for end users" (the Webopedia +
OpenACS Applications: a "program or group of programs +designed for end users" (the Webopedia definition); also known as modules, for historical reasons. -Examples of applications include Forums and News. +Examples of applications include Forums and News. -
OpenACS Services: the aforementioned building blocks. -Examples of services include the OpenACS -Content Repository, the OpenACS Templating -System, and the OpenACS Kernel, which includes +
OpenACS Services: the aforementioned building blocks. +Examples of services include the OpenACS +Content Repository, the OpenACS Templating +System, and the OpenACS Kernel, which includes APM.
An installation of the OpenACS includes the OpenACS Kernel, some services that extend the kernel's functionality, and some applications intended for -end-users. Packages function as individual pieces of subsites. A subsite can contain multiple +end-users. Packages function as individual pieces of subsites. A subsite can contain multiple application and service instances that provide the end-user with capabilities and content customized to the particular subsite.
This architecture supports the growth of collaborative commerce. For example, Jane User starts a forum focusing on the merits of View Cameras by @@ -36,48 +36,48 @@ it in his subsite. As interest in Jane's forum grows, she creates a subsite specializing in providing information about View cameras. This subsite now includes several package instances beyond Forum; it could -potentially include its own Ecommerce capabilities (ala Yahoo! Shopping). This could include a +potentially include its own Ecommerce capabilities (ala Yahoo! Shopping). This could include a knowledge management application that allows users to spread expertise about view cameras and a portal application that links to reliable camera models and resellers. Any subsite enabled package that is added to the OpenACS installation through APM is another potential package instance that can become part of Jane's View Camera subsite.
The APM provides an architecture for packaging software, making instances of that software available to subsites, specifying configuration parameters -for each instance, and managing the creation and release of new packages.
+for each instance, and managing the creation and release of new packages.
Prior to ACS 3.3, all packages were lumped together into one monolithic distribution without explicit boundaries; the only way to ascertain what comprised a given package was to look at the top of the corresponding documentation page, where, by convention, the package developer would specify where to find: -
the data model
the Tcl procedures
the user-accessible pages
the administration pages
Experience has shown us that this lack of explicit boundaries causes a -number of maintainability problems for pre-3.3 installations:
Package interfaces were not guaranteed to be stable in any formal way, so +
the data model
the Tcl procedures
the user-accessible pages
the administration pages
Experience has shown us that this lack of explicit boundaries causes a +number of maintainability problems for pre-3.3 installations:
Package interfaces were not guaranteed to be stable in any formal way, so a change in the interface of one package would often break dependent packages (which we would only discover through manual regression testing). In this context, any of the following could constitute an interface change: -
renaming a file or directory that appears in a URL
changing what form variables are expected as input by a page
changing a procedural abstraction, e.g., a PL/SQL or Java stored -procedure or a Tcl procedure
changing a functional abstraction, e.g., a database view or a PL/SQL or -Java stored function
changing the data model
This last point is especially important. In most cases, changing the data +
renaming a file or directory that appears in a URL
changing what form variables are expected as input by a page
changing a procedural abstraction, e.g., a PL/SQL or Java stored +procedure or a Tcl procedure
changing a functional abstraction, e.g., a database view or a PL/SQL or +Java stored function
changing the data model
This last point is especially important. In most cases, changing the data model should not affect dependent packages. Rather, the package interface should provide a level of abstraction above the data model (as well as the rest of the package implementation). Then, users of the package can take advantage of implementation improvements that don't affect the interface (e.g., faster performance from intelligent denormalization of the data model), without having to worry that code outside the package will now -break.
A typical ACS-backed site only uses a few of the modules included in the +break.
A typical ACS-backed site only uses a few of the modules included in the distribution, yet there was no well-understood way to pick only what you needed when installing the ACS, or even to uninstall what you didn't need, post-installation. Unwanted code had to be removed manually. -
Releasing a new version of the ACS was complicated, owing again to the +
Releasing a new version of the ACS was complicated, owing again to the monolithic nature of the software. Since we released everything in the ACS together, all threads of ACS development had to converge on a single deadline, after which we would undertake a focused QA effort whose scale increased in direct proportion to the expansion of the ACS codebase. -
There was no standard way for developers outside of ArsDigita to extend +
There was no standard way for developers outside of ArsDigita to extend the ACS with their own packages. Along the same lines, ArsDigita programmers working on client projects had no standard way to keep custom development cleanly separated from ACS code. Consequently, upgrading an already installed @@ -88,43 +88,43 @@ packages for other OpenACS users to download and install.
For a simple illustration of the difference between ACS without APM (pre-3.3) and ACS with APM (3.3 and beyond), consider a hypothetical ACS installation that uses only two of the thirty-odd modules available circa ACS -3.2 (say, bboard and e-commerce):
APM itself is part of a package, the OpenACS Kernel, an OpenACS -service that is the only mandatory component of an OpenACS installation.
The OpenACS is a platform for web-based application software, and any software +3.2 (say, bboard and e-commerce):
APM itself is part of a package, the OpenACS Kernel, an OpenACS +service that is the only mandatory component of an OpenACS installation.
The OpenACS is a platform for web-based application software, and any software platform has the potential to develop problems like those described above. Fortunately, there are many precedents for systematic solutions, -including:
Borrowing from all of the above, OpenACS 3.3 introduces its own package -management system, the OpenACS Package Manager (APM), which consists of:
a standard format for APM packages (also called -"OpenACS packages"), including:
version numbering, independent of any other package and the OpenACS as a -whole
specification of the package interface
specification of dependencies on other packages (if any)
attribution (who wrote it) and ownership (who maintains it)
web-based tools for package management:
obtaining packages from a remote distribution point
installing packages, if and only if:
all prerequisite packages are installed
no conflicts will be created by the installation
configuring packages (obsoleting the monolithic OpenACS configuration -file)
upgrading packages, without clobbering local modifications
uninstalling unwanted packages
a registry of installed packages, database-backed and +including:
Borrowing from all of the above, OpenACS 3.3 introduces its own package +management system, the OpenACS Package Manager (APM), which consists of:
a standard format for APM packages (also called +"OpenACS packages"), including:
version numbering, independent of any other package and the OpenACS as a +whole
specification of the package interface
specification of dependencies on other packages (if any)
attribution (who wrote it) and ownership (who maintains it)
web-based tools for package management:
obtaining packages from a remote distribution point
installing packages, if and only if:
all prerequisite packages are installed
no conflicts will be created by the installation
configuring packages (obsoleting the monolithic OpenACS configuration +file)
upgrading packages, without clobbering local modifications
uninstalling unwanted packages
a registry of installed packages, database-backed and integrated with filesystem-based version control -
web-based tools for package development:
creating new packages locally
releasing new versions of locally-created packages
The design chosen for APM was meant to satisfy the following constraints: -
The process of authoring a package must be as simple as possible.
Strict conventions must be established that provide a set of canonical +
The process of authoring a package must be as simple as possible.
Strict conventions must be established that provide a set of canonical locations and names for files and patterns, for OpenACS application -development.
The processes of installing, upgrading, and using packages must be -straightforward and accessible through a web-based UI.
Package instances must be able to have subsite-specific content available +development.
The processes of installing, upgrading, and using packages must be +straightforward and accessible through a web-based UI.
Package instances must be able to have subsite-specific content available at an easily configurable URL.
All of these requirements were met, but at the cost of development -simplicity. As Packages demonstrates, a set of strict directory conventions are +simplicity. As Packages demonstrates, a set of strict directory conventions are required in order for a package to use APM. This contrasts with the apparent simplicity available to developers of the OpenACS 3.3 system. However, while the system has become more complex for developers to build packages, this complexity is easily managed and is compensated for by additional capabilities.
For example, to make a new application available to the system, a -developer must:
Create the necessary files to support the data model, Tcl API, and UI -pages.
Put the files in the correct locations for APM to be aware of them.
Use APM to create a new package and enable it.
Use the Site Map facility to create an instance of the package, mount it +developer must:
Create the necessary files to support the data model, Tcl API, and UI +pages.
Put the files in the correct locations for APM to be aware of them.
Use APM to create a new package and enable it.
Use the Site Map facility to create an instance of the package, mount it on an appropriate URL, and set parameters for that particular instance.
While this is complex, especially to a new OpenACS developer, the documentation walks the developer through each of these steps. Moreover, from following these steps, the package can be subsite specific, available to subsites across the system, and be available for distribution to other OpenACS -installations without doing a monolithic upgrade or reinstall.
The APM is composed of systems for accomplishing a set of package-related +installations without doing a monolithic upgrade or reinstall.
The APM is composed of systems for accomplishing a set of package-related tasks. Each of these tasks comprise a feature area that has an API, data -model, and a UI:
Authoring a Package
Maintaining Multiple Versions of a Package
Creating Instances of the Package
Specifying Configuration Parameters for each Instance
Authoring a Package
Full instructions on how to prepare an OpenACS package are available in Packages. The API here can be invoked manually by a package's data model -creation script, but need not to be used. This API is part of the APM PL/SQL +model, and a UI:
Authoring a Package
Maintaining Multiple Versions of a Package
Creating Instances of the Package
Specifying Configuration Parameters for each Instance
Authoring a Package
Full instructions on how to prepare an OpenACS package are available in Packages. The API here can be invoked manually by a package's data model +creation script, but need not to be used. This API is part of the APM PL/SQL package.
-- Informs the APM that this application is available for use. @@ -144,9 +144,9 @@
The procedure above registers an OpenACS application in the APM. It creates a new OpenACS object and stores information about the package, such as its name, in the APM data model. There is an analogous procedure for OpenACS services, called -apm.register_service.
To remove an application from the system, there are the calls -apm.unregister_application and -apm.unregister_service.
+apm.register_service
.To remove an application from the system, there are the calls +
apm.unregister_application
and +apm.unregister_service
.-- Remove the application from the system. procedure unregister_application ( @@ -155,22 +155,22 @@ cascade_p in char default 'f' ); -Use the cascade_p only if you want to completely remove the +
Use the cascade_p
only if you want to completely remove the
package from the OpenACS.
In order to determine if a particular package exists in the system, use -the register_p predicate. It returns 1 if the specified -package_key exists in the system, 0 otherwise.
+theregister_p
predicate. It returns 1 if the specified +package_key
exists in the system, 0 otherwise.function register_p ( package_key in apm_package_types.package_key%TYPE ) return integer; -Maintaining Multiple Versions of a Package
While the package authoring API provides a means for registering a +
Maintaining Multiple Versions of a Package
While the package authoring API provides a means for registering a package, some information about a package is version dependent. For example, between versions, the owner of a package, its vendor, its URI, and its dependency information may change. The API for package versions allows this -information to be specified. All of these APIs are part of the -apm_package_version PL/SQL package.
To create a new package version, use the -apm_package_version.new constructor function.
+information to be specified. All of these APIs are part of the +apm_package_version
PL/SQL package.To create a new package version, use the +
apm_package_version.new
constructor function.function new ( version_id in apm_package_versions.version_id%TYPE @@ -191,26 +191,26 @@ default 'f' ) return apm_package_versions.version_id%TYPE; -In order to use this function, an existing package_key must -be specified. The version_name parameter must follow a strict -convention:
A major version number
at least one minor version number. Although any number of minor version +
In order to use this function, an existing
package_key
must +be specified. Theversion_name
parameter must follow a strict +convention:
A major version number
at least one minor version number. Although any number of minor version numbers may be included, three minor version numbers is sufficient and is the -convention of software developers.
One of the following:
The letter d, indicating a development-only version
The letter a, indicating an alpha release
The letter b, indicating a beta release
No letter at all, indicating a final production release
In addition, the letters d, a, and -b may be followed by another integer, indicating a version +convention of software developers.
One of the following:
The letter
d
, indicating a development-only versionThe letter
a
, indicating an alpha releaseThe letter
b
, indicating a beta releaseNo letter at all, indicating a final production release
In addition, the letters
d
,a
, and +b
may be followed by another integer, indicating a version within the release.For those who like regular expressions:
version_number := ^[0-9]+((\.[0-9]+)+((d|a|b|)[0-9]?)?)$ -So the following is a valid progression for version numbers:
0.9d, 0.9d1, 0.9a1, 0.9b1, 0.9b2, 0.9, 1.0, 1.0.1, 1.1b1, -1.1
To delete a given version of a package, use the -apm_package_version.delete procedure:
+So the following is a valid progression for version numbers:
0.9d, 0.9d1, 0.9a1, 0.9b1, 0.9b2, 0.9, 1.0, 1.0.1, 1.1b1, +1.1
To delete a given version of a package, use the +
apm_package_version.delete
procedure:procedure delete ( package_id in apm_packages.package_id%TYPE );After creating a version, it is possible to edit the information -associated with it using apm_package_version.edit.
+associated with it usingapm_package_version.edit
.function edit ( new_version_id in apm_package_versions.version_id%TYPE @@ -244,8 +244,8 @@ );Files associated with a version can be added and removed. The path is -relative to the package-root which is -acs-server-root/packages/package-key.
+relative to the package-root which is +acs-server-root/packages/package-key
.-- Add a file to the indicated version. function add_file( file_id in apm_package_files.file_id%TYPE @@ -326,7 +326,7 @@ version_name_two in apm_package_versions.version_name%TYPE ) return integer; -Creating Instances of a Package
Once a package is registered in the system, it is possible to create +
Creating Instances of a Package
Once a package is registered in the system, it is possible to create instances of it. Each instance can maintain its own content and parameters.
@@ -353,7 +353,7 @@Just creating a package instance is not sufficient for it to be served from the web server. A corresponding site node must be created for it. As an -example, here is how the OpenACS API Documentation service +example, here is how the OpenACS API Documentation service makes itself available on the OpenACS main site:
declare @@ -381,15 +381,15 @@ show errors -Specifying Configuration Parameters for each Instance
A parameter is a setting that can be changed on a package instance basis. -Parameters are registered on each package_key, and the values +
Specifying Configuration Parameters for each Instance
A parameter is a setting that can be changed on a package instance basis. +Parameters are registered on each
package_key
, and the values are associated with each instance. Parameters can have default values and can be of type 'string' or 'number.' There is support with this API for setting a number of minimum and maximum values for each parameter, but for most instances, the minimum and maximum should be 1. It is useful to allow or require multiple values for packages that need to store multiple pieces of information under one parameter. Default values are automatically -set when instances are created, but can be changed for each instance.All of the functions below are in the APM PL/SQL +set when instances are created, but can be changed for each instance.
All of the functions below are in the APM PL/SQL package.
-- Indicate to APM that a parameter is available to the system. @@ -463,65 +463,65 @@ attr_value in apm_parameter_values.attr_value%TYPE ); -
The central piece of the data model is the apm_package_types
table where each package is registered. When a new application or service is
installed on an OpenACS instance, a corresponding row in this table is inserted
-with information about the type of package, e.g. if the forum package is installed on your OpenACS server, a row
-in apm_package_types will be created, noting that it's an
-application package type.
The apm_packages table is used to contain information about
+with information about the type of package, e.g. if the forum package is installed on your OpenACS server, a row
+in apm_package_types
will be created, noting that it's an
+application package type.
The apm_packages
table is used to contain information about
the instances of packages currently created in the system. The
-package_key column references the apm_package_types
+package_key
column references the apm_package_types
table to ensure that no package instance can be created for a type that does
-not exist.
The apm_package_versions table contains information specific +not exist.
The apm_package_versions
table contains information specific
to a particular version of a package. Several tables reference this one to
-provide further information about the particular version:
apm_package_owners +provide further information about the particular version:
apm_package_owners
Stores information about the owners of a particular version of a package.
-
apm_package_files +
apm_package_files
Stores information about the files that are part of a version.
-
apm_package_dependencies +
apm_package_dependencies
Stores information about what interfaces the package provides and
-requires.
Parameter information is maintained through two tables:
apm_parameters +requires.
Parameter information is maintained through two tables:
apm_parameters
This table contains the definition of each of the parameters for a package.
-
apm_parameter_values +
apm_parameter_values
This table holds all of the values of parameters for specific package
instances.
A number of views are available for obtaining information about packages -registered in the APM.
apm_package_version_info +registered in the APM.
apm_package_version_info
Provides information about all of the versions in the system with
-information available from the apm_package_types table.
+information available from the apm_package_types
table.
-
apm_enabled_package_versions +
apm_enabled_package_versions
A view (subset) of the above table with only enabled versions.
-
apm_file_info - Provides a public interface for querying file information.
The APM's user interface is part of the -OpenACS Administration Service. The UI is the primary +
apm_file_info
+ Provides a public interface for querying file information.
The APM's user interface is part of the +OpenACS Administration Service. The UI is the primary point of contact with APM by developers and administrators. It is part of OpenACS Administration, because only the site-wide administrator should be able to access it. Thus in order to develop a package, the developer must be granted -site-wide administration.
APM has two parameters for configuring how it interacts with the UNIX -filesystem, accessible via the Site Map admin +site-wide administration.
APM has two parameters for configuring how it interacts with the UNIX +filesystem, accessible via the Site Map admin page. These parameters need not be changed under most circumstances, but may -need to be tweaked for Windows compatibility.
GzipExecutableDirectory - This directory points to where the gunzip program can be found -for uncompressing gzip archives. This is needed for the -installation of .apm files which are simply gziped -tarballs. Default is /usr/local/bin +need to be tweaked for Windows compatibility.
GzipExecutableDirectory
+ This directory points to where the gunzip
program can be found
+for uncompressing gzip
archives. This is needed for the
+installation of .apm
files which are simply gzip
ed
+tarballs. Default is /usr/local/bin
-
InfoFilePermissionsMode +
InfoFilePermissionsMode This sets the default UNIX permissions used when creating files using the -APM. Default is 775.
APM has been in production since OpenACS 3.3, and as of version 4.0 offers a stable set of features. One major feature planned is integration with the OpenACS Package Repository for automatic dependency satisfaction. When a user tries to install a package that depends on other packages, the APM will contact the @@ -539,6 +539,6 @@ repositories worldwide.
Another anticipated change is to split the APM UI into separate systems for authoring, maintaining, and installing packages. The current UI presents all of this functionality in one interface and it can be confusing from a -usability perspective.
System creator: Bryan Quinn, Jon Salz, Michael Yoon, Lars Pind, Todd -Nightingale.
System owner: Bryan Quinn
Documentation author: Bryan Quinn, building from earlier versions by Jon -Salz, Michael Yoon, and Lars Pind.
System creator: Bryan Quinn, Jon Salz, Michael Yoon, Lars Pind, Todd +Nightingale.
System owner: Bryan Quinn
Documentation author: Bryan Quinn, building from earlier versions by Jon +Salz, Michael Yoon, and Lars Pind.
By Bryan Quinn and Todd Nightingale
+ +By Bryan Quinn and Todd Nightingale
OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff. -The following is a requirements document for the OpenACS Package Manager (APM), version 4.0 (APM4). APM4 offers a superset of APM v3.3 functionality -with the following specific enhancements:
A public procedural API. (v 3.3 only has web-based UI)
Support for dependency checking.
Support for compound packages (to support installation chaining).
Support for on-line parameter setting.
Support for sub-site level configuration (requires revised parameter +with the following specific enhancements:
A public procedural API. (v 3.3 only has web-based UI)
Support for dependency checking.
Support for compound packages (to support installation chaining).
Support for on-line parameter setting.
Support for sub-site level configuration (requires revised parameter and /admin pages at sub-site level; deprecation of site-wide parameter file).
To differentiate these new requirements from the requirements of version 3.3, all requirements new in v4 are prefaced with the number -4.
We gratefully acknowledge the authors of APM 3 for their original design +4.
We gratefully acknowledge the authors of APM 3 for their original design documentation which suggested these features, as well as the influence of the design and open-source implementation of the Red Hat Package manager, the Debian packaging system, and PERL's CPAN in the development of the ideas -behind this document.
A typical website will tend to offer its users a number of web-based +behind this document.
A typical website will tend to offer its users a number of web-based services or applications, e.g. a bulletin board, calendaring, classified ads, etc. A website may also have underlying subsystems, such as a permissions system, content management system, etc. For such applications and subsystem @@ -26,38 +26,38 @@ OpenACS sites.
In general terms, a package is a unit of software that serves a single well-defined purpose. The OpenACS Package Manager (APM) provides a mechanism for packaging, installing, and configuring OpenACS software in a consistent, -user-friendly, and subsite-aware manner.
The OpenACS Package Manager (APM) consists of: -
A standard format for APM packages including:
Version numbering, independent of any other package and the OpenACS as a -whole
Specification of the package interface
Specification of dependencies on other packages (if any)
Attribution (who wrote it) and ownership (who maintains it)
Web-based tools for package management:
Obtaining packages from a remote distribution point
Installing packages, if and only if:
All prerequisite packages are installed
No conflicts will be created by the installation
Configuring packages (obsoleting the monolithic OpenACS configuration -file)
Upgrading packages, without clobbering local modifications
Uninstalling unwanted packages
A registry of installed packages, database-backed and +
A standard format for APM packages including:
Version numbering, independent of any other package and the OpenACS as a +whole
Specification of the package interface
Specification of dependencies on other packages (if any)
Attribution (who wrote it) and ownership (who maintains it)
Web-based tools for package management:
Obtaining packages from a remote distribution point
Installing packages, if and only if:
All prerequisite packages are installed
No conflicts will be created by the installation
Configuring packages (obsoleting the monolithic OpenACS configuration +file)
Upgrading packages, without clobbering local modifications
Uninstalling unwanted packages
A registry of installed packages, database-backed and integrated with file system-based version control -
Web-based tools for package development:
Creating new packages locally
Releasing new versions of locally-created packages
Uploading packages to a global package repository on the web
Use of these tools should be safe, i.e. installing or removing a package -should never break an OpenACS installation
Web-based tools for package configuration:
The ability to change package parameter values on-line through a simple -web interface.
A new ad_parameter which does not require a monolithic site-wide -parameter's file or server restarts for changes to take effect.
The ability to manage multiple package instances at the sub-site -level.
+
Web-based tools for package development:
Creating new packages locally
Releasing new versions of locally-created packages
Uploading packages to a global package repository on the web
Use of these tools should be safe, i.e. installing or removing a package +should never break an OpenACS installation
Web-based tools for package configuration:
The ability to change package parameter values on-line through a simple +web interface.
A new ad_parameter which does not require a monolithic site-wide +parameter's file or server restarts for changes to take effect.
The ability to manage multiple package instances at the sub-site +level.
The APM is intended for the following classes of users, which may or may not -overlap:
Developers (referred to as 'the developer') use +overlap:
Developers (referred to as 'the developer') use the APM to create a software package for distribution and use the procedural -API for direct control of the APM system.
Site-wide administrators (referred to as 'the +API for direct control of the APM system.
Site-wide administrators (referred to as 'the administrator') use the APM to install packages for their OpenACS instance, -and optionally make them available to sub-sites.
Sub-site administrators (referred to as 'the +and optionally make them available to sub-sites.
Sub-site administrators (referred to as 'the sub-admin') use an administration interface to configure and enable -packages for their sub-site.
Initial Package Development
David Developer writes a piece of software used to do +packages for their sub-site.
Initial Package Development
David Developer writes a piece of software used to do knowledge management (km) for the OpenACS. He distributes his data model, procedure code, UI pages, and his documentation according to the APM specification. He splits the documentation and the code into sub-packages, and creates a KM installation-chain to install both with the APM developer -UI. Noting that his software was built with Patricia -Programmer's Super Widget toolkit, he specifies that as a +UI. Noting that his software was built with Patricia +Programmer's Super Widget toolkit, he specifies that as a dependency. Moreover, since this package is capable of being used at the sub-site level, David configures this option in the package. When the package development is complete, David uses the APM developer UI to construct a distribution file. He assigns it a version number, 1.0, and makes the package -available for download at the OpenACS package repository.
Initial Package Installation
Annie Admin learns of David's KM system by browsing +available for download at the OpenACS package repository.
Initial Package Installation
Annie Admin learns of David's KM system by browsing the OpenACS package repository. Annie Admin uses the APM administrator UI on her system. She selects to install a package from a URL and types the URL displayed on the system. The APM automatically downloads the package. The @@ -71,16 +71,16 @@ installation was successful, the package is available for use.
Since the package is available for use, its initialization routines are set to run automatically on server startup. Annie is warned that since there are initialization routines, she must restart the server for the package to -be ready for use. Annie restarts the server.
Initial Subsite Use of Package
Annie Admin decides to make the KM module available only to a particular +be ready for use. Annie restarts the server.
Initial Subsite Use of Package
Annie Admin decides to make the KM module available only to a particular sub-site type on her OpenACS system, and not others. She specifies this option -using the Sub-site type UI (not part of APM).
Annie Admin notifies Sally SubAdmin by e-mail that a new +using the Sub-site type UI (not part of APM).
Annie Admin notifies Sally SubAdmin by e-mail that a new package is now available for use. Sally goes to her sub-site /admin page and sees that a new entry, KM, is available. Sally clicks on it and finds links to the installed KM documentation and to the web based configuration utility. Then, Sally configures the package using an automatically generated web interface and enables KM for use on her sub-site. After some initial use of the package, Sally decides to change some parameters using the SubAdmin UI. -These changes take effect immediately, without any server restarts.
Upgrade Process
Sally SubAdmin finds a bug in the KM system and sends a report to David +These changes take effect immediately, without any server restarts.
Upgrade Process
Sally SubAdmin finds a bug in the KM system and sends a report to David Developer. David reads the bug report and verifies that the bugs are present in the current version. Because the bugs are present in the shared procedure file, David assigns a watch to the file. David makes the necessary @@ -91,199 +91,199 @@ repository.
Sally SubAdmin asks Annie Administrator to upgrade the package using the APM UI. This upgrade supersedes the old version of KM at the site-wide level. Once Annie upgrades the package, the new version starts working immediately -in Sally's sub-site.
Procedural API
Danielle Developer wants her software to perform +in Sally's sub-site.
Procedural API
Danielle Developer wants her software to perform different actions depending on what version of another package is installed. She uses the APM procedural API to check if KM version 1.0 is installed or version 1.1. Based on the results of this procedural call, the software -exhibits different behavior.
4.500.0 Package Identification -(All of these items are entered by the developer using the developer UI.)
4.500.1 A human readable package key that is guaranteed +exhibits different behavior.
4.500.0 Package Identification +(All of these items are entered by the developer using the developer UI.)
4.500.1 A human readable package key that is guaranteed to be unique to the local OpenACS site must be maintained by the APM. For -example, "apm."
4.500.5 A package id (primary key) that is guaranteed to +example, "apm."
4.500.5 A package id (primary key) that is guaranteed to be unique to the local site must be maintained by the APM. For example, -"25."
4.500.10 A package URL that is guaranteed to be unique +"25."
4.500.10 A package URL that is guaranteed to be unique across all sites must be maintained by the APM. The package URL should point to a server that allows download of the latest version of the package. For -example, "http://openacs.org/software." -
4.505.0 Version Identification - (All of these items are entered by the developer using the developer UI.)
4.505.1 A version id (primary key) that is guaranteed to -be unique to the local site must be maintained by the APM.
4.505.5 A version URL that is guaranteed to be unique +example, "http://openacs.org/software." +
4.505.0 Version Identification + (All of these items are entered by the developer using the developer UI.)
4.505.1 A version id (primary key) that is guaranteed to +be unique to the local site must be maintained by the APM.
4.505.5 A version URL that is guaranteed to be unique across all sites must be maintained by the APM. The version URL should point to a server that allows download of a specific version of the package. -
The API for APM v3 is explicitly a private API. However, it would be useful to obtain information from the APM through a procedural API. Implementing the API specified below is quite easy given that there are pages -that already do all of the below in raw SQL.
4.400.0 Packages Status Predicates
4.400.1 Given defining information such as a package URL, +that already do all of the below in raw SQL.
4.400.0 Packages Status Predicates
4.400.1 Given defining information such as a package URL, the APM API can return the status of the package on the local OpenACS -instance.
4.405.0 Package Information Procedures
4.405.1 The APM API can return information for any +instance.
4.405.0 Package Information Procedures
4.405.1 The APM API can return information for any locally installed packages, including the version number, paths and files, -and package key.
4.410.0 Sub-site Procedures
4.410.1 After a package has been installed at the +and package key.
4.410.0 Sub-site Procedures
4.410.1 After a package has been installed at the site-wide level, the system API will provide means to check for package -presence, creation, enabling, disabling, and destruction on a subsite.
4.415.0 Parameter Values (replaces ad_parameter)
4.415.1 The system API shall allow subsite parameters for +presence, creation, enabling, disabling, and destruction on a subsite.
4.415.0 Parameter Values (replaces ad_parameter)
4.415.1 The system API shall allow subsite parameters for an installed package to be set by either site-wide administrators or sub-site admins. The subsite parameter can be set to be non-persistent (but default is to survive server restarts). The subsite parameter can also be set to only -take effect after a server restart (default is immediate).
4.415.5 Parameters for a given subsite and package can be -returned by the system API.
Provisions will be made to assure that packages are securely -identified.
4.600.1 Each package will have a PGP signature and there +identified.
4.600.1 Each package will have a PGP signature and there will be MD5 time stamps for each file within the package. -
4.600.5 The APM will provide a facility to validate both -the PGP signature and MD5 stamps information before a package install.
The user interface is a set of HTML pages that are used to drive the underlying API. It is restricted to site-wide administrators because the -actions taken here can dramatically affect the state of the running OpenACS.
The intent of the developer's interface is to enable the developer to +actions taken here can dramatically affect the state of the running OpenACS.
The intent of the developer's interface is to enable the developer to construct and maintain APM packages. It will be possible to disable the developer's interface for production sites to help reduce the chance of site failure; much of the functionality here can have cascading effects -throughout the OpenACS and should not be used on a production site.
10.0 Define a package.
The developer must be able to create a new package by specifying some +throughout the OpenACS and should not be used on a production site.
10.0 Define a package.
The developer must be able to create a new package by specifying some identifying information for the package. This includes a package name, a -package key, version information, owner information, and a canonical URL.
10.1 The APM must maintain the state of all locally -generated packages.
10.50 If the developer fails to provide the required -information, the package cannot be created.
10.55 All of the package information should be editable -after creation, except for the package key.
4.10.60 The package creator must specify whether the +package key, version information, owner information, and a canonical URL.
10.1 The APM must maintain the state of all locally +generated packages.
10.50 If the developer fails to provide the required +information, the package cannot be created.
10.55 All of the package information should be editable +after creation, except for the package key.
4.10.60 The package creator must specify whether the package is capable of being used in sub-sites, or if only a single, global -instance of the package is permitted.
4.10.65 If the developer fails to provide unique +instance of the package is permitted.
4.10.65 If the developer fails to provide unique information for unique fields specified in the data model requirements, the -package cannot be created.
20.0 Add files to a package
20.1 The developer must be able to add files to the +package cannot be created.
20.0 Add files to a package
20.1 The developer must be able to add files to the package. This is done by copying the files into the package directory in the host OS's file system. Files can be added at any point after package -creation.
20.3 Once a package has been versioned and distributed, +creation.
20.3 Once a package has been versioned and distributed, no new files should be added to the package without incrementing the version -number.
20.5 The APM's UI should facilitate the process of +number.
20.5 The APM's UI should facilitate the process of adding new files, by scanning the file system for new files automatically, -and allowing the developer to confirm adding them.
20.10 The developer cannot add files to a given package -via the UI that do not exist in the file system already.
20.15 Package file structure must follow a specified -convention. Please see the design -document for what we do currently.
30.0 Remove files from a package
The developer must be able to remove files from a package. This can be -done in two ways.
30.1 Access the APM UI, browse the file list, and remove -files.
30.1.1If a file is removed from the package list, but not -from the file system, an error should be generated at package load time.
30.5 Remove the file from file system.
30.5.1 The APM UI should take note of the fact that the +and allowing the developer to confirm adding them.
20.10 The developer cannot add files to a given package +via the UI that do not exist in the file system already.
20.15 Package file structure must follow a specified +convention. Please see the design +document for what we do currently.
30.0 Remove files from a package
The developer must be able to remove files from a package. This can be +done in two ways.
30.1 Access the APM UI, browse the file list, and remove +files.
30.1.1If a file is removed from the package list, but not +from the file system, an error should be generated at package load time.
30.5 Remove the file from file system.
30.5.1 The APM UI should take note of the fact that the file is gone and offer the developer an option to confirm the file's deletion. -
40.0 Modify files in a package.
40.1 The developer should be able to modify files in the -file system. The APM UI should not interfere with this.
40.5 However, if the developer modifies files containing -procedural definitions, APM UI should allow a means to watch +
40.0 Modify files in a package.
40.1 The developer should be able to modify files in the +file system. The APM UI should not interfere with this.
40.5 However, if the developer modifies files containing +procedural definitions, APM UI should allow a means to watch those files and automatically reload them if changed. See requirement 50.0 -for more detail.
40.10 Also, although a change in files implies that the +for more detail.
40.10 Also, although a change in files implies that the package distribution file is out of date, it is the developer's -responsibility to update it.
4.45.0 Manage Package Dependency Information.
4.45.1 The developer should be able to specify which -interfaces the package requires.
4.45.5 The developer should be able to specify which -interfaces the package provides.
4.45.10 Circular dependencies are not allowed.
50.0 Watch a file
4.50.1 The developer should be able to assign a watch to -any Tcl procedure file, whether in /packages or /tcl.
50.5 If a watched file is locally modified, then it will +responsibility to update it.
4.45.0 Manage Package Dependency Information.
4.45.1 The developer should be able to specify which +interfaces the package requires.
4.45.5 The developer should be able to specify which +interfaces the package provides.
4.45.10 Circular dependencies are not allowed.
50.0 Watch a file
4.50.1 The developer should be able to assign a watch to +any Tcl procedure file, whether in /packages or /tcl.
50.5 If a watched file is locally modified, then it will be automatically reloaded, thus allowing for any changes made to take affect -immediately.
4.50.10 The setting of a watch should be persistent +immediately.
4.50.10 The setting of a watch should be persistent across server restarts. -
60.0 Display an XML package specification
60.1 The developer should be able to view the XML package +
60.0 Display an XML package specification
60.1 The developer should be able to view the XML package specification that encodes all package information. -
70.0 Write an XML package specification to the file -system
70.1 The developer should be able to write an up-to-date -XML specification to disk.
70.5 The developer should be able to request the current -XML specification for all installed, locally generated packages.
130.0 Distribution file generation
130.1 The developer should be able to generate a .APM -distribution file for the package with just one click.
130.5 Generating a distribution file implies doing an -"up-to-date" check on all of the files. If any of the files have +
70.0 Write an XML package specification to the file +system
70.1 The developer should be able to write an up-to-date +XML specification to disk.
70.5 The developer should be able to request the current +XML specification for all installed, locally generated packages.
130.0 Distribution file generation
130.1 The developer should be able to generate a .APM +distribution file for the package with just one click.
130.5 Generating a distribution file implies doing an +"up-to-date" check on all of the files. If any of the files have changed since package installation, then a new version of the package is created. -
140.0 Access CVS information
140.1 The developer should be able to determine the CVS +
140.0 Access CVS information
140.1 The developer should be able to determine the CVS status of a package, or all packages, with a single click. -
4.400.0 Compound Package Construction
4.400.1 The developer can include .APM packages +
4.400.0 Compound Package Construction
4.400.1 The developer can include .APM packages (sub-packages) within a package (the compound package) like any other -file.
4.400.5 The recommended usage for this feature is to +file.
4.400.5 The recommended usage for this feature is to
allow for separation of optional and required components from the
installation as well as better organization of files once installed. For
example, all documentation for the community-core can be packages as
-community-core-doc.apm. It is legal to include sub-packages with
+community-core-doc.apm
. It is legal to include sub-packages with
dependencies that are not satisfied by the packages in the compound package,
but this is discouraged. In such a case, the sub-package should really be a
-separate package that is required by the compound package.
4.400.10 If a sub-package is required for the +separate package that is required by the compound package.
4.400.10 If a sub-package is required for the installation of the compound package, the compound package should have a -registered dependency on the sub-package.
The requirement of the administrator's interface is to enable the administrator to install, enable, upgrade, disable, deinstall, and delete -packages.
80.0 Package Enable/Disable
4.80.1 The administrator should be able mark an installed +packages.
80.0 Package Enable/Disable
4.80.1 The administrator should be able mark an installed package as enabled. This means that the package is activated and its functionality is delivered through the Request Processor. As of OpenACS 4, this -is done through the sub-site system.
4.80.5 Moreover, the administrator must be able to +is done through the sub-site system.
4.80.5 Moreover, the administrator must be able to disable a package, thereby removing the functionality provided to a sub-site. As of OpenACS 4, this is done through the sub-site system. -
90.0 Package Install
90.1 The administrator must be able to install new -packages either from locally maintained .APM files or from URLs.
90.5 In the case of an URL, the APM transparently +
90.0 Package Install
90.1 The administrator must be able to install new +packages either from locally maintained .APM files or from URLs.
90.5 In the case of an URL, the APM transparently downloads the APM file off the web, proceeds with a file based installation, -and then optionally removes the .APM file just downloaded.
90.10.1 If .APM files are present in a package, then it -is considered a compound package (use 4.410.0).
90.15.0 Installation requires these steps:
90.15.1The package dependencies are scanned. If some +and then optionally removes the .APM file just downloaded.
90.10.1 If .APM files are present in a package, then it +is considered a compound package (use 4.410.0).
90.15.0 Installation requires these steps:
90.15.1The package dependencies are scanned. If some dependencies are not present, the system warns the administrator that -installation cannot proceed until those packages are installed.
90.15.2 Assuming all dependencies are present, APM -extracts the contents of the APM file into the /packages directory.
90.15.3 The administrator is offered the option of -importing directly into CVS.
90.15.4 The administrator is given a list of data model -scripts found in the package and can select which ones to be executed.
90.15.5 If no errors are recorded during this process, -the package is enabled.
4.410.0 Compound package Install
4.410.1 If .APM files are present in a package, then it -is considered a compound package.
4.410.5.0 Installation of a compound package proceeds -according to the following sequence:
4.410.5.1 Identify the set of all sub-packages within -the compound package by scanning for all files with .APM.
4.410.5.2 Identify which sub-packages are required by +installation cannot proceed until those packages are installed.
90.15.2 Assuming all dependencies are present, APM +extracts the contents of the APM file into the /packages directory.
90.15.3 The administrator is offered the option of +importing directly into CVS.
90.15.4 The administrator is given a list of data model +scripts found in the package and can select which ones to be executed.
90.15.5 If no errors are recorded during this process, +the package is enabled.
4.410.0 Compound package Install
4.410.1 If .APM files are present in a package, then it +is considered a compound package.
4.410.5.0 Installation of a compound package proceeds +according to the following sequence:
4.410.5.1 Identify the set of all sub-packages within +the compound package by scanning for all files with .APM.
4.410.5.2 Identify which sub-packages are required by checking the dependencies of the compound package. If there dependencies not satisfied by the current system or the packages included with the compound package, halt installation and inform user to install these packages -first.
4.410.5.3 Present Administrator with the ability to +first.
4.410.5.3 Present Administrator with the ability to choose which sub-packages to install. Required sub-packages must be -installed.
4.410.5.4 Proceed with the installation of each +installed.
4.410.5.4 Proceed with the installation of each sub-package, starting with required packages. If the sub-package is already installed, then do nothing. Else, If the sub-package is a normal package, -proceed according to 90.15.0, otherwise if it is a compound -package, proceed according to 4.410.5.0.
4.410.5.5 If all required sub-packages are installed, +proceed according to 90.15.0, otherwise if it is a compound +package, proceed according to 4.410.5.0.
4.410.5.5 If all required sub-packages are installed, proceed to install non-required sub-packages. If there was a failure during the installation of a required sub-package, then the installation of the -compound package is also a failure.
4.410.5.6 Any attempt to install a compound package in +compound package is also a failure.
4.410.5.6 Any attempt to install a compound package in the future involves a choice presented to the admin of installing any -uninstalled sub-packages.
4.420.0 Recovering from failed package installation
4.420.1 If any error is generated during package +uninstalled sub-packages.
4.420.0 Recovering from failed package installation
4.420.1 If any error is generated during package installation, the package is not considered installed. To recover from this -failure, the package should be selected for installation again.
100.0 Version Upgrade
100.1 The administrator can upgrade to a new version of a -package. This entails
100.1.1 Running any necessary and included upgrade -scripts.
100.1.5 Replacing any old files with new versions.
100.1.10 Marking the old version of the package as -'superseded' and disabling it.
100.1.15 Assuming no errors from above, the new package -is enabled.
110.0 Package Deinstall
110.1 The administrator must be able to deinstall a -package that has already been installed. Deinstallation entails:
110.1.1 Running any data model scripts necessary to drop -the package.
110.1.5 Moving all of the files into a separate location -in the file system from the installed packages.
4.110.1.10 If the package is a compound package, then +failure, the package should be selected for installation again.
100.0 Version Upgrade
100.1 The administrator can upgrade to a new version of a +package. This entails
100.1.1 Running any necessary and included upgrade +scripts.
100.1.5 Replacing any old files with new versions.
100.1.10 Marking the old version of the package as +'superseded' and disabling it.
100.1.15 Assuming no errors from above, the new package +is enabled.
110.0 Package Deinstall
110.1 The administrator must be able to deinstall a +package that has already been installed. Deinstallation entails:
110.1.1 Running any data model scripts necessary to drop +the package.
110.1.5 Moving all of the files into a separate location +in the file system from the installed packages.
4.110.1.10 If the package is a compound package, then the administrator must confirm removing all sub-packages. Optionally, some -sub-packages can be kept.
110.5 Deinstalled packages can be re-installed at a later -date.
4.110.10 If deinstalling a package or any of its +sub-packages can be kept.
110.5 Deinstalled packages can be re-installed at a later +date.
4.110.10 If deinstalling a package or any of its sub-packages breaks a dependency, then deinstallation cannot proceed until -the package registering the dependency is removed.
120.0 Package Deletion
120.1 The administrator should be able to completely +the package registering the dependency is removed.
120.0 Package Deletion
120.1 The administrator should be able to completely erase all records of the package. This involves removing all instances of the -package, all related database tables and content.
120.5 This option can only be used if all package +package, all related database tables and content.
120.5 This option can only be used if all package instances are deleted or marked as disabled. This is purposefully cumbersome because deleting all instances of a package can have far-sweeping -consequences throughout a site and should almost never be done.
150.0 Scan for new or modified packages
150.1 The administrator should be able to scan the file -system for any changes made in any of the installed package files.
150.5 The administrator should be able to scan the file +consequences throughout a site and should almost never be done.
150.0 Scan for new or modified packages
150.1 The administrator should be able to scan the file +system for any changes made in any of the installed package files.
150.5 The administrator should be able to scan the file system for any newly installed packages. -
If the developer is in charge of creating packages and the administrator for installing them, then the sub-site administrator is responsible for configuring and enabling packages. In order for a package to be available for a sub-site it must be associated with the sub-site's type specification. This interface is part of the sub-site /admin interface. -
4.300 Creating a package instance.
4.300.1 From the sub-site /admin interface, there should +
4.300 Creating a package instance.
4.300.1 From the sub-site /admin interface, there should be an option to view all packages available in the system as well as an -option to add a package to the subsite.
4.300.5 From the "add" option, the sub-admin +option to add a package to the subsite.
4.300.5 From the "add" option, the sub-admin can select from a list of packages registered as available in the sub-site -type to which the sub-site belongs.
4.300.19 Once a package instance is added, it is -available on the list of the subsite's available packages.
4.305 Configuring a package instance.
4.305.1 An automatic web interface that lists all -parameters with current values must be available.
4.305.5 Changing the values for the parameters is -accomplished simply by submitting an HTML form.
4.310 Enabling a package instance.
4.310.1 The sub-admin should be able to enable a package +type to which the sub-site belongs.
4.300.19 Once a package instance is added, it is +available on the list of the subsite's available packages.
4.305 Configuring a package instance.
4.305.1 An automatic web interface that lists all +parameters with current values must be available.
4.305.5 Changing the values for the parameters is +accomplished simply by submitting an HTML form.
4.310 Enabling a package instance.
4.310.1 The sub-admin should be able to enable a package with a single click. Enabling a package means that the OpenACS will serve its URLs properly. -
4.315 Disabling a package instance.
4.315.1 The sub-admin should be able to disable a package +
4.315 Disabling a package instance.
4.315.1 The sub-admin should be able to disable a package with a single click. Disabling a package means that the OpenACS will no longer -serve those URLs.
4.320 Deleting a package instance.
4.320.1 Deleting a package instance involves deleting not +serve those URLs.
4.320 Deleting a package instance.
4.320.1 Deleting a package instance involves deleting not only the package instance, but any and all content associated with it. It is questionable whether this option should even be available due to its drastic consequences. Reviewer comments appreciated. -
Despite the fact that requirements are meant to be design/implementation neutral, the following thoughts were in our head when specifying these requirements. You must be familiar with the new object design for this to be comprehensible.
When a package is installed system-wide, a corresponding acs_object_type @@ -292,4 +292,4 @@ are set using the acs_attribute_values table. The automatic web interface for setting package parameters should be one and the same with the interface for setting acs object attribute values. Consequently, the implementation of -these features should be quite straightforward.
Document Revision # | Action Taken, Notes | When? | By Whom? |
0.1 | Creation | 8/10/2000 | Bryan Quinn, Todd Nightingale |
Reviewed | 8/11/2000 | John Prevost, Mark Thomas, and Pete Su | |
0.2 | Revised and updated | 8/12/2000 | Bryan Quinn |
0.3 | Reviewed, revised, and updated - conforms to requirements template. | 8/18/2000 | Kai Wu |
0.4 | Minor edits before ACS 4 Beta. | 9/30/2000 | Kai Wu |
Document Revision # | Action Taken, Notes | When? | By Whom? |
0.1 | Creation | 8/10/2000 | Bryan Quinn, Todd Nightingale |
Reviewed | 8/11/2000 | John Prevost, Mark Thomas, and Pete Su | |
0.2 | Revised and updated | 8/12/2000 | Bryan Quinn |
0.3 | Reviewed, revised, and updated - conforms to requirements template. | 8/18/2000 | Kai Wu |
0.4 | Minor edits before ACS 4 Beta. | 9/30/2000 | Kai Wu |
The recommended backup strategy for a production sit is to use an automated script which first backs up the database to a file in /var/lib/aolserver/$OPENACS_SERVICE_NAME/database-backup and then backs up all of /var/lib/aolserver/$OPENACS_SERVICE_NAME to a single zip file, and then copies that zip file to another computer.
Make sure that the manual backup process described above works.
Customize the default backup script. Edit /var/lib/aolserver/$OPENACS_SERVICE_NAME/etc/backup.sh with your specific parameters.
- Make sure the file is executable:
chmod +x backup.sh
- Set this file to run automatically by adding a line to root's crontab. (Typically, with export EDITOR=emacs; crontab -e.) This example runs the backup script at 1:30 am every day.
30 1 * * * sh /var/lib/aolserver/$OPENACS_SERVICE_NAME/etc/backup.sh
The recommended backup strategy for a production sit is to use an automated script which first backs up the database to a file in /var/lib/aolserver/$OPENACS_SERVICE_NAME/database-backup
and then backs up all of /var/lib/aolserver/$OPENACS_SERVICE_NAME
to a single zip file, and then copies that zip file to another computer.
Make sure that the manual backup process described above works.
Customize the default backup script. Edit /var/lib/aolserver/$OPENACS_SERVICE_NAME/etc/backup.sh
with your specific parameters.
+ Make sure the file is executable:
chmod +x backup.sh
+ Set this file to run automatically by adding a line to root's crontab. (Typically, with export EDITOR=emacs; crontab -e
.) This example runs the backup script at 1:30 am every day.
30 1 * * * sh /var/lib/aolserver/$OPENACS_SERVICE_NAME/etc/backup.sh
By Jeff Davis
+ +By Jeff Davis
OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff. -Best practices in writing OpenACS automated tests
Special characters in Tcl. -Try strings starting with a -Bad and strings containing [BAD], {, \077, and $Bad. For user input, [BAD] should never be evaluated, \077 should not be turned into a ? and $Bad should not be interpolated. The string -Bad [BAD] \077 { $Bad should be valid user input, should pass through the system unaltered, and if it isn't that's a bug. -
Quoting issues. Put some html in plain text fields and make sure the result is -properly quoted anywhere it shows up (I use "<b>bold</b>" +
Best practices in writing OpenACS automated tests
Special characters in Tcl.
+Try strings starting with a -Bad
and strings containing [BAD]
, {
, \077
, and $Bad
. For user input, [BAD]
should never be evaluated, \077
should not be turned into a ?
and $Bad
should not be interpolated. The string -Bad [BAD] \077 { $Bad
should be valid user input, should pass through the system unaltered, and if it isn't that's a bug.
+
Quoting issues. Put some html in plain text fields and make sure the result is
+properly quoted anywhere it shows up (I use "<b>bold</b>"
usually). Look out especially for quoting errors in the context bar
and in round trips via an edit form. For fields that disallow html
-tags you can use & to check that the field is quoted
-properly. If it is not displayed as & then the quoting for the field is incorrect. (It's not clear whether this
+tags you can use &
to check that the field is quoted
+properly. If it is not displayed as &
then the quoting for the field is incorrect. (It's not clear whether this
should be considered an error but given that data for text fields can
come from various sources if it's text it should be properly quoted
and we should not rely on input validation to prevent XSS security
-holes.)
Whitespace input. Check that whitespace is not considered valid input for a field +holes.)
Whitespace input. Check that whitespace is not considered valid input for a field if it does not make sense. For example, the subject of a forum post is -used to construct a link and if it is " " it will have a link of -<a href="..."> </a> which would not be clickable if whitespace was allowed as a valid input. -
Doubleclick.
+used to construct a link and if it is " " it will have a link of
+<a href="..."> </a>
which would not be clickable if whitespace was allowed as a valid input.
+
Doubleclick. Make sure that if you submit a form, use the back button, and submit again that the behavior is reasonable (correct behavior depends on what the form is for, but a server error is not reasonable). -
Duplicate names. +
Duplicate names. Make sure that if a duplicate name is entered that there is a reasonable error rather than a server error. Check for insert, move, copy, and rename. -
Table of Contents
By Don Baccus with additions - by Joel Aufrecht
We will cover some basic backup and recovery strategies. These are intended to + +
Table of Contents
By Don Baccus with additions + by Joel Aufrecht
We will cover some basic backup and recovery strategies. These are intended to be robust but simple enough to set up. For a large scale production site you would probably need to create your own backup strategies (in particular full dumps from oracle, while easy to set up, are far from the best solution).
There are three basic things which need to be backed up, the database data, the server source tree, and the acs-content-repository (which is in the server source tree).
-
+
CVS-only backup is often appropriate for development sites. If you are already using CVS and your data is not important, you probably don't + +
CVS-only backup is often appropriate for development sites. If you are already using CVS and your data is not important, you probably don't need to do anything to back up your files. Just make sure that your current work is checked into the system. You can then roll back based on date - note the current system time, down to the minute. For maximum safety, you can apply a tag to your current - files. You will still need to back up your database.
Note that, if you did the CVS options in this document, the /var/lib/aolserver/$OPENACS_SERVICE_NAME/etc directory is not included in cvs and you may want to add it.
[root root]# su - $OPENACS_SERVICE_NAME -[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ cd /var/lib/aolserver/$OPENACS_SERVICE_NAME -[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ cvs commit -m "last-minute commits before upgrade to 4.6" + files. You will still need to back up your database.Note that, if you did the CVS options in this document, the
/var/lib/aolserver/$OPENACS_SERVICE_NAME/etc
directory is not included in cvs and you may want to add it.[root root]#su - $OPENACS_SERVICE_NAME
+[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$cd /var/lib/aolserver/$OPENACS_SERVICE_NAME
+[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$cvs commit -m "last-minute commits before upgrade to 4.6"
cvs commit: Examining . cvs commit: Examining bin (many lines omitted) -[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ cvs tag before_upgrade_to_4_6 +[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$cvs tag before_upgrade_to_4_6
cvs server: Tagging bin T bin/acs-4-0-publish.sh T bin/ad-context-server.pl (many lines omitted) -[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ exit +[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$exit
[root root]# su - $OPENACS_SERVICE_NAME cd /var/lib/aolserver/$OPENACS_SERVICE_NAME -cvs commit -m "last-minute commits before upgrade to 4.6" +cvs commit -m "last-minute commits before upgrade to 4.6" cvs tag before_upgrade_to_4_6 -exitTo restore files from a cvs tag such as the one used above:
[root root]# su - $OPENACS_SERVICE_NAME -[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ cd /var/lib/aolserver/$OPENACS_SERVICE_NAME -[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ cvs up -r current -[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ exit +exit
To restore files from a cvs tag such as the one used above:
[root root]#su - $OPENACS_SERVICE_NAME
+[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$cd /var/lib/aolserver/$OPENACS_SERVICE_NAME
+[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$cvs up -r current
+[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$exit
su - $OPENACS_SERVICE_NAME cd /var/lib/aolserver/$OPENACS_SERVICE_NAME cvs up -r current
By Jon Salz
+ +By Jon Salz
OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff. -Tcl code: /tcl/0-acs-init.tcl and /packages/acs-kernel/bootstrap.tcl
This document describes the startup (bootstrapping) process for an AOLserver +
Tcl code: /tcl/0-acs-init.tcl and /packages/acs-kernel/bootstrap.tcl
This document describes the startup (bootstrapping) process for an AOLserver running OpenACS. -
+
Before OpenACS 3.3, the OpenACS startup process was extremely simple: after AOLserver
performed its internal initialization (reading the configuration file,
loading shared libraries and module code, etc.) it scanned through the Tcl
-library directory (generally /var/lib/aolserver/yourservername/tcl),
+library directory (generally /var/lib/aolserver/
yourservername
/tcl
),
sourcing each file in sequence.
While this overall structure for initialization is still intact, package management has thrown a wrench into the works - there are a few extra things -to do during initialization, most notably:
Examine the OpenACS file tree for files that should not be present in OpenACS +to do during initialization, most notably:
Examine the OpenACS file tree for files that should not be present in OpenACS (i.e., that were once part of the OpenACS distribution but have since been -removed).
Scan the /packages directory for new packages.
Initialize enabled packages by sourcing their *-procs.tcl -and *-init.tcl files.
+removed).
Scan the /packages
directory for new packages.
Initialize enabled packages by sourcing their *-procs.tcl
+and *-init.tcl
files.
This document examines in detail each of the steps involved in AOLserver/OpenACS startup. -
+As soon as the nsd
daemon is executed by the init
process (or otherwise), AOLserver reads its configuration file and
-chroots itself if necessary. It then loads shared libraries
-indicated in the .ini file (e.g., the Oracle driver and
-nssock), and sources Tcl module files (generally in
-/home/aol30/modules/tcl). This step is, and has always been, the
+chroot
s itself if necessary. It then loads shared libraries
+indicated in the .ini
file (e.g., the Oracle driver and
+nssock
), and sources Tcl module files (generally in
+/home/aol30/modules/tcl
). This step is, and has always been, the
same for all AOLservers, regardless of whether they are running OpenACS.
Next AOLserver sources, in lexicographical order, each file in the
-/tcl directory. The first such file is
-0-acs-init.tcl, which doesn't do much directly except to
-determine the OpenACS path root (e.g., /var/lib/aolserver/yourservername)
+/tcl
directory. The first such file is
+0-acs-init.tcl
, which doesn't do much directly except to
+determine the OpenACS path root (e.g., /var/lib/aolserver/
yourservername
)
by trimming the final component from the path to the Tcl library directory
-(/var/lib/aolserver/yourservername/tcl). But
-0-acs-init.tcl's has an important function, namely sourcing
-/packages/acs-core/bootstrap.tcl, which does the following:
Initialize some NSVs used by the core. These NSVs are
-documented in /packages/acs-core/apm-procs.tcl - no need to
+(/var/lib/aolserver/
yourservername
/tcl
). But
+0-acs-init.tcl
's has an important function, namely sourcing
+/packages/acs-core/bootstrap.tcl
, which does the following:
Initialize some NSVs used by the core. These NSVs are
+documented in /packages/acs-core/apm-procs.tcl
- no need to
worry about them unless you're an OpenACS core hacker.
-
Verify the deletion of obsolete OpenACS files. The -/tcl directory has evolved quite a bit over the months and +
Verify the deletion of obsolete OpenACS files. The
+/tcl
directory has evolved quite a bit over the months and
years, and a few files have come and gone. The
-/www/doc/removed-files.txt file contains a list of files which
+/www/doc/removed-files.txt
file contains a list of files which
must be deleted from the AOLserver installation, at the risk of
causing weird conflicts, e.g., having several security filters registered.
-bootstrap.tcl scans through this list, logging error messages to
+bootstrap.tcl
scans through this list, logging error messages to
the log if any of these files exist.
-
Source *-procs.tcl files in the OpenACS core. -We source each file matching the *-procs.tcl glob in the -/packages/acs-kernel directory, in lexicographical order. These +
Source *-procs.tcl
files in the OpenACS core.
+We source each file matching the *-procs.tcl
glob in the
+/packages/acs-kernel
directory, in lexicographical order. These
procedure are needed to perform any of the following steps.
-
Ensure that the database is available by grabbing and +
Ensure that the database is available by grabbing and releasing a handle. If we can't obtain a handle, we terminate initialization (since OpenACS couldn't possibly start up the server without access to the database). -
Register any new packages in the /packages -directory. In each directory inside /packages, we look -for a .info file; if we find a package that hasn't yet been +
Register any new packages in the /packages
+directory. In each directory inside /packages
, we look
+for a .info
file; if we find a package that hasn't yet been
registered with the package manager (i.e., it's been copied there
manually), we insert information about it into the database. (The first time
OpenACS starts up, no packages will have been registered in the database
yet, so this step will registers every single package in the
-/packages directory.) Note that packages discovered here are
+/packages
directory.) Note that packages discovered here are
initially disabled; they must be manually enabled in the package manager
before they can be used.
-
Ensure that the acs-kernel package is -enabled. If the OpenACS core isn't initialized, the server +
Ensure that the acs-kernel
package is
+enabled. If the OpenACS core isn't initialized, the server
couldn't possibly be operational, so if there's no enabled version of
the OpenACS core we simply mark the latest installed one as enabled.
-
Load *-procs.tcl files for enabled -packages, activating their APIs. +
Load *-procs.tcl
files for enabled
+packages, activating their APIs.
-
Load *-init.tcl files for enabled packages, +
Load *-init.tcl
files for enabled packages,
giving packages a chance to register filters and procedures, initialize data
structures, etc.
-
Verify that the core has been properly initialized by +
Verify that the core has been properly initialized by checking for the existence of an NSV created by the request processor initialization code. If it's not present, the server won't be operational, so we log an error.
-At this point, bootstrap.tcl is done executing. AOLserver
-proceeds to source the remaining files in the /tcl directory
+At this point, bootstrap.tcl
is done executing. AOLserver
+proceeds to source the remaining files in the /tcl
directory
(i.e., unpackaged libraries) and begins listening for connections.
Prev | Home | Next |
Documenting Tcl Files: Page Contracts and Libraries | Up | External Authentication Requirements |
Prev | Home | Next |
Prerequisite Software | Up | Install a Unix-like system and supporting software |
Prev | Home | Next |
Prerequisite Software | Up | Install a Unix-like system and supporting software |
by Jade Rubick
+ +by Jade Rubick
OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff. -After you've installed and mounted your package, you can configure each instance to act as you would like.
This is done from the Applications page. Log in, go to the Admin or Control Panel, click on the subsite the application is in, and click on Applications. If you click on the 'Parameters' Index: openacs-4/packages/acs-core-docs/www/configuring-configuring-permissions.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/configuring-configuring-permissions.html,v diff -u -r1.9 -r1.9.2.1 --- openacs-4/packages/acs-core-docs/www/configuring-configuring-permissions.html 31 Jul 2011 23:11:45 -0000 1.9 +++ openacs-4/packages/acs-core-docs/www/configuring-configuring-permissions.html 21 Aug 2013 10:19:20 -0000 1.9.2.1 @@ -1,8 +1,8 @@ - -
by Jade Rubick
+ +by Jade Rubick
OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff. -After you've installed and mounted your package, you can configure each instance to act as you would like.
This is done from the Applications page. Log in, go to the Admin or Control Panel, click on the subsite the application is in, and click on Applications. If you click on the 'Permissions' Index: openacs-4/packages/acs-core-docs/www/configuring-install-packages.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/configuring-install-packages.html,v diff -u -r1.9 -r1.9.2.1 --- openacs-4/packages/acs-core-docs/www/configuring-install-packages.html 31 Jul 2011 23:11:45 -0000 1.9 +++ openacs-4/packages/acs-core-docs/www/configuring-install-packages.html 21 Aug 2013 10:19:20 -0000 1.9.2.1 @@ -1,8 +1,8 @@ - -
by Jade Rubick
+ +by Jade Rubick
OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff. -An OpenACS package extends your website and lets it do things it wasn't able to do before. You can have a weblog, a forums, a calendar, or even do sophisticated project-management via your website.
After you've installed OpenACS, you can congratulate @@ -22,7 +22,7 @@ you want depends on. If you're installing from Local Files, and you are missing any packages, you may have to add the packages your desired package depends on: - Section , “Upgrading the OpenACS files” + the section called “Upgrading the OpenACS files”
If you run into any errors at all, check your /var/lib/aolserver/$OPENACS_SERVICE_NAME/log/error.log file, and post your error on the OpenACS forums
Once the package has been installed, then you will need to Index: openacs-4/packages/acs-core-docs/www/configuring-mounting-packages.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/configuring-mounting-packages.html,v diff -u -r1.9 -r1.9.2.1 --- openacs-4/packages/acs-core-docs/www/configuring-mounting-packages.html 31 Jul 2011 23:11:45 -0000 1.9 +++ openacs-4/packages/acs-core-docs/www/configuring-mounting-packages.html 21 Aug 2013 10:19:20 -0000 1.9.2.1 @@ -1,8 +1,8 @@ - -
by Jade Rubick
+ +by Jade Rubick
OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff. -After you've installed your packages, you have to 'mount' them in order to make them appear on your website.
Make sure you are logged in, and then click on the 'Admin' or 'Control Panel' link to get to the Site-Wide Administration page (at /acs-admin). Click on the subsite you'd Index: openacs-4/packages/acs-core-docs/www/configuring-new-site.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/configuring-new-site.html,v diff -u -r1.14 -r1.14.2.1 --- openacs-4/packages/acs-core-docs/www/configuring-new-site.html 31 Jul 2011 23:11:45 -0000 1.14 +++ openacs-4/packages/acs-core-docs/www/configuring-new-site.html 21 Aug 2013 10:19:20 -0000 1.14.2.1 @@ -1,5 +1,5 @@ - -
Table of Contents
Table of Contents
In this chapter, Configuring refers to making changes to a new OpenACS site through the web interface. In crude terms, these changes happen in the database, and are upgrade-safe. Customizing refers to changes that touch the file system, and require some planning if easy upgradability is to be maintained.
Prev | Home | Next |
OpenACS Installation Guide for Mac OS X | Up | Installing OpenACS packages |
In this chapter, Configuring refers to making changes to a new OpenACS site through the web interface. In crude terms, these changes happen in the database, and are upgrade-safe. Customizing refers to changes that touch the file system, and require some planning if easy upgradability is to be maintained.
Prev | Home | Next |
OpenACS Installation Guide for Mac OS X | Up | Installing OpenACS packages |
Table of Contents
By Vinod Kurup
+Table of Contents
By Vinod Kurup
OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff.Vinod Kurup put together the January 2002 version of this guide from many sources of information.
Joel Aufrecht - updated the document starting in March 2003.
+ updated the document starting in March 2003.
Gilbert Wong's FreeBSD
Index: openacs-4/packages/acs-core-docs/www/cvs-guidelines.html
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/cvs-guidelines.html,v
diff -u -r1.9 -r1.9.2.1
--- openacs-4/packages/acs-core-docs/www/cvs-guidelines.html 31 Jul 2011 23:11:45 -0000 1.9
+++ openacs-4/packages/acs-core-docs/www/cvs-guidelines.html 21 Aug 2013 10:19:20 -0000 1.9.2.1
@@ -1,59 +1,57 @@
-
-
By Joel Aufrecht with input from Jeff Davis, Branimir Dolicki, and Jade Rubick.
All OpenACS code is available anonymously. To get code
anonymously, use the parameter
- -d:pserver:anonymous@cvs.openacs.org:/cvsroot immediately after cvs in a cvs command to check out or export code.
+
If you are an OpenACS developer, you should check out code so
that you or any other developer can commit it. To do this, use
the parameter
- -d:ext:cvs.openacs.org:/cvsroot
- immediately after cvs in
+
OpenACS.org supports non-anonymous cvs access only over ssh, so you
- must have CVS_RSH=ssh in your
+ must have
With this setup, you will be asked for your password with
each cvs command. To avoid this, set up ssh certificate
- authentication for your openacs account. (More
+ authentication for your openacs account. (More
information)
You may want to set some more default actions for CVS usage.
To do so, create the file
- ~/.cvsrc with the contents:
+ -z6 speeds up cvs access over the network quite a bit by enabling compressed
- connection by default. -q suppresses some verbose output from commands. For example, it makes the output of cvs up much easier to read. Administrator Note: These are the steps to grant CVS commit rights to a user: Create the user's account. On cvs.openacs.org: Administrator Note: These are the steps to grant CVS commit rights to a user: Create the user's account. On cvs.openacs.org: Grant cvs access to the user account. On any machine, in a temporary directory: Grant cvs access to the user account. On any machine, in a temporary directory: Add an avail line of the form: Branimir suggests an additional level of abstraction. If you put Add an avail line of the form: Branimir suggests an additional level of abstraction. If you put into your ~/.ssh/config file, then you can use -d :ext:cvs-server:/cvsroot instead of -d :ext:cvs.openacs.org:/cvsroot. You can then change the definition of cvs-server by changing one file instead of editing hundreds of CVSROOT/Repository files. If you are actively developing a non-core package, you
+ User yournamehere into your If you are actively developing a non-core package, you
should work from the latest core release branch. Currently this
is oacs-5-7. This ensures that you are working on top
of a stable OpenACS core, but still allows you to commit feature
@@ -64,34 +62,34 @@
want to use only acs-core plus some specific modules. To do
this, check out core first: Then add modules as needed: ... where packagename is the
- name of the package you want. Visit the Package
- Inventory and Package
+ name of the package you want. Visit the Package
+ Inventory and Package
maintainers and status for a list of available
packages and their current state.
- If you are actively developing packages in the OpenACS
Core, work from the HEAD branch. HEAD is used for active
development of the next version of core OpenACS. It may be very
buggy; it may not even install correctly. Do not use this branch for
development of non-core features unless your work depends on some
of the HEAD core work. To check out HEAD, omit the
- -r tag. To check out HEAD for development, which requires an OpenACS developer account: To check out HEAD anonymously:
+ To check out HEAD for development, which requires an OpenACS developer account: To check out HEAD anonymously:
.LRN consists of a given version openacs core, plus a set of
packages. These are collectively packages together to form a
distrubution of .LRN. F .LRN 2.0.0 sits on top of OpenACS 5.0.0.
.LRN also uses an OpenACS install.xml file during installation;
this file is distributed within the dotlrn package and must be
moved. To get a development checkout of .LRN in the subdirectory
- dotlrn:
+
Once you have a checkout you can use some commands to track
- what has changed since you checked out your copy. cvs -n update does not change any files, but reports which changes have been updated or locally modified, or are not present in CVS.
- To update your files, use cvs update. This will merge changes from the repository with your local files. It has no effect on the cvs.openacs.org repository.
- All OpenACS code resides within a single CVS module, openacs-4. (The openacs-4 directory contains code for all versions of OpenACS 4 and later, and .LRN 1 and later.) Checking out this module retrieves all openacs code of any type. For convenience, subsets of openacs-4 are repackaged as smaller modules.
- acs-core contains only critical common
+ what has changed since you checked out your copy. To update your files, use
+ All OpenACS code resides within a single CVS module,
+
- dotlrn-all contains the packages required, in combination with acs-core, to run the .LRN system.
+
- project-manager-all contains the packages required, in combination with acs-core, to run the project-manager package.
+
- Each OpenACS package (i.e., directory in openacs-4/packages/) is also aliased as a module of the same name.
-
Tags and Branches look similar in commands, but behave differently. A tag is a fixed point on a branch. Check out
a tag to get a specific version of OpenACS. Check out a branch to
get the most current code for that major-minor version (e.g., 5.0.x
or 5.1.x). You can only commit to a branch, not a tag, so check out
- a branch if you will be working on the code. openacs-x-y-z-final
- tags mark final releases of OpenACS. This tag is applied to the acs-core files for an OpenACS core release, and to the latest released versions of all other packages at the time of release. Example: openacs-5-0-4-final.
- dotlrn-x-y-z-final
- tags mark final releases of .LRN. These tags apply only to .LRN packages. Example: dotlrn-2-0-1-final
- packagename-x-y-z-final
- tags apply to releases of individual packages. For example, calendar-2-0-0-final is a tag that will retrieve only the files in the calendar 2.0.0 release. It applies only to the
+ a branch if you will be working on the code. openacs-x-y-compat tags point to the most recent released version of OpenACS X.Y.
+ oacs-x-y is a branch, , not a tag. All core packages in the 5.0 release series (5.0.0, 5.0.1, 5.0.2, etc) are also on the oacs-5-0 branch. Similarly, OpenACS core packages for 5.1.0 are on the oacs-5-1 branch. These branches are used for two purposes. OpenACS
+ oacs-x-y is a branch, , not a tag. All core packages in the 5.0 release series (5.0.0, 5.0.1, 5.0.2, etc) are also on the oacs-5-0 branch. Similarly, OpenACS core packages for 5.1.0 are on the oacs-5-1 branch. These branches are used for two purposes. OpenACS
Core packages on these branches are being tidied up for
release. Only bug fixes, not new features, should be
added to core packages on release branches. For all other
packages, release branches are the recommended location
for development. For example, if you are working on
calendar, which is compatible with openacs 5.0 but not
- 5.1, work on the oacs-5-0 branch. HEAD is a branch used
- for development of core packages. There are three main ways to contribute code to OpenACS: To contribute a small fix, if you do not have a developer account, submit a patch. If you are making many changes, or would like to become a direct contributor, send mail to the Core Team asking for commit rights. You can then commit code directly to the repository: Use one of the checkout methods described above to get files to your system. This takes the place of steps 1 and 2 in Section , “Installation Option 2: Install from tarball”. Continue setting up the site as described there. Fix bugs and add features.
- Commit that file (or files):
+ 5.1, work on the oacs-5-0 branch. There are three main ways to contribute code to OpenACS: To contribute a small fix, if you do not have a developer account, submit a patch. If you are making many changes, or would like to become a direct contributor, send mail to the Core Team asking for commit rights. You can then commit code directly to the repository: Use one of the checkout methods described above to get files to your system. This takes the place of steps 1 and 2 in the section called “Installation Option 2: Install from tarball”. Continue setting up the site as described there. Fix bugs and add features.
+ Commit that file (or files):
Because this occurs in your personal checkout and not an anonymous
one, this commit automagically moves back upstream to the Mother
Ship repository at cvs.openacs.org. The names of the changed files, and your comments, are sent to a mailing list for OpenACS developers. A Core Team developer may review or roll back your changes if necessary.
-
- Confirm via the
+
+ Confirm via the
OpenACS CVS browser
that your changes are where you intended them to be.
- Add a new package. Contact the Core Team to get approval and to get a module alias created.
+ Add a new package. Contact the Core Team to get approval and to get a module alias created.
Check out acs-core on the HEAD branch. (Weird things happen if you add files to a branch but not to HEAD): Copy your package directory from your working directory to this directory. Make sure not to copy any CVS directories. Import the package into the cvs.openacs.org cvs repository: Add the new package to the modules file. (An administrator has to do this step.) On any machine, in a temporary directory: Add the new package to the modules file. (An administrator has to do this step.) On any machine, in a temporary directory: Add a line of the form: Commit the change: This should print something like: cvs commit: Examining . Add a line of the form: Commit the change: This should print something like: cvs commit: Examining . Although you should add your package on HEAD, you should do package development on the latest release branch that your code is compatible with. So, after completing the import, you may want to branch your package: See Section , “How to package and release an OpenACS Package” Some packages are already in cvs at openacs-4/contrib/packages. Starting with OpenACS 5.1, we have a Maturity mechanism in the APM which makes the contrib directory un-necessary. If you are working on a contrib package, you should move it to /packages. This must be done by an OpenACS administrator. On cvs.openacs.org: Update the modules file as described above. Remove the directory from cvs in the old location using cvs rm. One approach for file in `find | grep -v CVS`; do rm $file; cvs remove $file; done Although you should add your package on HEAD, you should do package development on the latest release branch that your code is compatible with. So, after completing the import, you may want to branch your package: See the section called “How to package and release an OpenACS Package” Some packages are already in cvs at Update the modules file as described above. Remove the directory from cvs in the old location using
CVS commit procedures are governed by
-
+
TIP (Technical Improvement Proposal) #61: Guidelines for CVS committers
-
+
Which branch?
-
+
For core packages, new features should always be
committed on HEAD, not to release branches.
-
+
For core packages, bug fixes should be committed on the
current release branch whenever applicable.
-
+
For non-core packages, developers should work on a
checkout of the release branch of the lastest release. For example,
if OpenACS 5.1.0 is released, developers should work on the
@@ -201,27 +199,27 @@
released.
- Reason: First, this ensures that developers are working against stable core code. Second, it ensures that new package releases are available to OpenACS users immediately.
+ Reason: First, this ensures that developers are working against stable core code. Second, it ensures that new package releases are available to OpenACS users immediately.
The current release branch is merged back to HEAD after
each dot release.
-
+
New packages should be created in the
-
+
+
Code
-
+
Only GPL code and material should be committed to the
OpenACS CVS repository (cvs.openacs.org)
- Do not mix formatting changes with code changes. Instead, make a formatting-only change which does not affect the logic, and say so in the commit comment. Then, make the logic change in a separate commit. Reason: This makes auditing and merging code much easier.
-
+ Do not mix formatting changes with code changes. Instead, make a formatting-only change which does not affect the logic, and say so in the commit comment. Then, make the logic change in a separate commit. Reason: This makes auditing and merging code much easier.
+
Database upgrade scripts should only span one release
increment, and should follow
-
+
Naming Database Upgrade Scripts
.
@@ -234,57 +232,57 @@
that using rc1 instead of b1 would be nice, because that's the
convention with release codes in cvs, but the package manager
doesn't support rc tags.
-
+
Database upgrade scripts should never go to the release
version, e.g., should always have a letter suffix such as d1 or
b1.
-
+
CVS commit messages should be intelligible in the context
of Changelogs. They should not refer to the files or
versions.
-
+
CVS commit messages and code comments should refer to
- bug, tip, or patch number if appropriate, in the format "resolves
- bug 11", "resolves bugs 11, resolves bug 22". "implements tip 42",
- "implements tip 42, implements tip 50", "applies patch 456 by User
- Name", "applies patch 456 by User Name, applies patch 523 by
- ...".
-
+ bug, tip, or patch number if appropriate, in the format "resolves
+ bug 11", "resolves bugs 11, resolves bug 22". "implements tip 42",
+ "implements tip 42, implements tip 50", "applies patch 456 by User
+ Name", "applies patch 456 by User Name, applies patch 523 by
+ ...".
+
When to TIP
-
+
A TIP is a Techical Improvement Proposal (
-
+
more information
). A proposed change must be approved by TIP if:
-
+
It changes the core data model, or
-
+
It will change the behavior of any core package in a way
that affects existing code (typically, by changing public API), or
-
+
It is a non-backwards-compatible change to any core or
standard package.
-
+
A proposed change need not be TIPped if:
-
+
it adds a new function to a core package in a way that:
-
+
does not change the backwards-compatibility of public API
functions.
-
+
does not change the data model
-
+
has no negative impact on performance
-
+
it changes private API, or
-
+
it is a change to a non-core, non-standard package
-
+
Tags
-
+
When a package is released in final form, the developer
- shall tag it "packagename-x-y-z-final" and "openacs-x-y-compat". x-y
+ shall tag it "packagename-x-y-z-final" and "openacs-x-y-compat". x-y
should correspond to the current branch. If the package is
compatible with several different core versions, several compat
tags should be applied.
@@ -299,7 +297,7 @@
identify packages which have been released since the last core
release.Reason 3: The compat tag or something similar is required
to make Rule 6 possible.
-
+
When OpenACS core is released, the openacs-x-y-z-final
tag shall be applied to all compat packages.
@@ -317,110 +315,110 @@
flag which defaults to no-effect wouldn't require a TIP. Added a
new mandatory flag to an existing function would require a
TIP.
-
Informal guidelines which may be obsolete in places and should be reviewed:
-
+
Before committing to cvs you must submit a bug report and
patch to the
-
+
OpenACS
bug tracker
. The only exceptions to this rule are
for
-
+
package
maintainers
committing in a package they are
maintaining and for members of the core team.
-
+
If you are committing a bug fix you need to coordinate
with the package maintainer. If you are a maintainer then
coordinate with any fellow maintainers.
-
+
If you are to commit a new feature, an architecture
change, or a refactoring, you must coordinate with the OpenACS core
team first. Also, such changes should have a discussion in the
forums to allow for feedback from the whole community.
-
+
If you are changing the data model you *must* provide an
upgrade script and bump up the version number of the
package.
-
+
Consider any upgradability ramifications of your change.
Avoid changing the contract and behaviour of Tcl procedures. If you
want to build a new and clean API consider deprecating the old proc
and making it invoke the new one.
-
+
Never rush to commit something. Before committing double
check with cvs diff what exactly you are committing.
-
+
Always accompany a commit with a brief but informative
comment. If your commit is related to bug number N and/or patch
- number P, indicate this in the commit comment by including "bug N"
- and/or "patch P". This allows us to link bugs and patches in the
+ number P, indicate this in the commit comment by including "bug N"
+ and/or "patch P". This allows us to link bugs and patches in the
Bug Tracker with changes to the source code. For example suppose
you are committing a patch that closes a missing HTML tag, then an
- appropriate comment could be "Fixing bug 321 by applying patch 134.
- Added missing h3 HTML close tag".
-
+ appropriate comment could be "Fixing bug 321 by applying patch 134.
+ Added missing h3 HTML close tag".
+
Commit one cohesive bug fix or feature change at a time.
Don't put a bunch of unrelated changes into one commit.
-
+
Before you throw out or change a piece of code that you
don't fully understand, use cvs annotate and cvs log on the file to
see who wrote the code and why. Consider contacting the
author.
-
+
Test your change before committing. Use the OpenACS
package acs-automated-testing to test Tcl procedures and the tool
-
+
Tclwebtest
to test pages
-
+
Keep code simple, adhere to conventions, and use comments
liberally.
-
+
In general, treat the code with respect, at the same
time, never stop questioning what you see. The code can always be
improved, just make sure you change the code in a careful and
systematic fashion.
-
The
-
+
OpenACS cvs web
and
-
+
Jeff's cvs
browser
are useful tools in understanding what is
happening with the code.
-
+
There is a mailing list of cvs changes at
-
+
willfork.com
- There is an RSS feed of cvs changes at
-
+ There is an RSS feed of cvs changes at
+
RSS feed
-
- cvs manual
-
- backup with cvs
-
+ cvs manual
+
+ backup with cvs
+ Add the Service to CVS - OPTIONAL. These steps take an existing OpenACS directory and add
- it to a CVS
- repository. Create and set permissions on a subdirectory in the local cvs repository. Add the Service to CVS - OPTIONAL. These steps take an existing OpenACS directory and add
+ it to a CVS
+ repository. Create and set permissions on a subdirectory in the local cvs repository. Add the repository location to the user environment. On some systems, you may get better results with .bash_profile instead of .bashrc. Put this string into /home/$OPENACS_SERVICE_NAME/.bashrc: Add the repository location to the user environment. On some systems, you may get better results with .bash_profile instead of .bashrc. Put this string into Import all files into cvs. In order to work on
+[root root]# Import all files into cvs. In order to work on
files with source control, the files must be checked out
from cvs. So we will import, move aside, and then check
out all of the files. In the cvs import command,
- $OPENACS_SERVICE_NAME
+ Move the original directory to a temporary location, and check out the cvs repository in its place. Move the original directory to a temporary location, and check out the cvs repository in its place. If the service starts correctly, come back and remove the temporary copy of the uploaded files. If the service starts correctly, come back and remove the temporary copy of the uploaded files. Table of Contents Table of Contents By Jon Salz. Revised and expanded by Roberto Mello (rmello at fslc dot usu dot edu), July 2002. By Jon Salz. Revised and expanded by Roberto Mello (rmello at fslc dot usu dot edu), July 2002. Tcl procedures: /packages/acs-kernel/10-database-procs.tcl Tcl initialization: /packages/acs-kernel/database-init.tcl Tcl procedures: /packages/acs-kernel/10-database-procs.tcl Tcl initialization: /packages/acs-kernel/database-init.tcl
One of OpenACS's great strengths is that code written for it is very close to
the database. It is very easy to interact with the database from anywhere
within OpenACS. Our goal is to develop a coherent API for database access which
makes this even easier.
There were four significant problems with the way OpenACS previously used the
-database (i.e., directly through the ns_db interface): Handle management. We required code to pass database
+database (i.e., directly through the Handle management. We required code to pass database
handles around, and for routines which needed to perform database access but
didn't receive a database handle as input, it was difficult to know from
-which of the three "magic pools" (main, subquery, and log) to
+which of the three "magic pools" (main, subquery, and log) to
allocate a new handle.
- Nested transactions. In our Oracle driver, begin
-transaction really means "turn auto-commit mode off" and
-end transaction means "commit the current transaction and
-turn auto-commit mode on." Thus if transactional code needed to call a
+ Nested transactions. In our Oracle driver,
-This would insert greeble #33 and do all the stuff in foo
-transactionally, but the end transaction in foo
+This would insert greeble #33 and do all the stuff in Unorthodox use of variables. The standard mechanism for
+ Unorthodox use of variables. The standard mechanism for
mapping column values into variables involved the use of the
-set_variables_after_query routine, which relies on an uplevel
-variable named selection (likewise for
-set_variables_after_subquery and subselection).
+ Hard-coded reliance on Oracle. It's difficult to
+ Hard-coded reliance on Oracle. It's difficult to
write code supporting various different databases (dynamically using the
appropriate dialect based on the type of database being used, e.g., using
-DECODE on Oracle and CASE ... WHEN on
+
The Database Access API addresses the first three problems by:
- making use of database handles transparent wrapping common database operations (including transaction management) in
+ making use of database handles transparent wrapping common database operations (including transaction management) in
Tcl control structures (this is, after all, what Tcl is good at!)
It lays the groundwork for addressing the fourth problem by assigning each
SQL statement a logical name. In a future version of the OpenACS Core, this API
will translate logical statement names into actual SQL, based on the type of
database in use. (To smooth the learning curve, we provide a facility for
-writing SQL inline for a "default SQL dialect", which we assume to
+writing SQL inline for a "default SQL dialect", which we assume to
be Oracle for now.)
To be clear, SQL abstraction is not fully implemented in OpenACS
3.3.1. The statement names supplied to each call are not used by the API at
all. The API's design for SQL abstraction is in fact incomplete;
-unresolved issues include: how to add WHERE clause criteria dynamically how to build a dynamic ORDER BY clause (Ben Adida has a
-proposed solution for this) how to define a statement's formal interface (i.e., what bind
-variables it expects, what columns its SELECT clause must
+unresolved issues include: how to add how to build a dynamic how to define a statement's formal interface (i.e., what bind
+variables it expects, what columns its
So why is the incremental change of adding statement naming to the API worth
@@ -78,81 +78,81 @@
design. Therefore, we know that the effort will not be wasted, and taking
advantage of the new support for bind variables will already require code
that uses 3.3.0 version of the API to be updated.
-
-set_variables_after_query is gone! (Well, it's still there,
+
+
-Like ns_db 1row, this will bomb if the query doesn't return
+Like
Selecting a bunch of rows is a lot prettier now:
-That's right, db_foreach is now like ns_db
-select plus a while loop plus
-set_variables_after_query plus an if statement
+That's right,
The new API keeps track of which handles are in use, and automatically
allocates new handles when they are necessary (e.g., to perform subqueries
while a select is active). For example:
A new handle isn't actually allocated and released for every selection,
of course - as a performance optimization, the API keeps old handles around
-until db_release_unused_handles is invoked (or the script
+until Note that there is no analogue to ns_db gethandle - the
-handle is always automatically allocated the first time it's needed. Introduction
+ Note that there is no analogue to Introduction
Most SQL statements require that the code invoking the statement pass along
data associated with that statement, usually obtained from the user. For
instance, in order to delete a WimpyPoint presentation, a Tcl script might
@@ -162,10 +162,10 @@
delete from wp_presentations where presentation_id = some_presentation_id
-where some_presentation_id is a number which is a valid
+where
When this SQL statement is invoked, the value for the bind variable
-:some_presentation_id is pulled from the Tcl variable
-$some_presentation_id (in the caller's environment). Note
+ The value of a bind variable is taken literally by the database driver, so
there is never any need to put single-quotes around the value for a bind
-variable, or to use db_quote to escape single-quotes contained
+variable, or to use Note that you can use a bind variable in a SQL statement only where you
could use a literal (a number or single-quoted string). Bind variables cannot
be placeholders for things like SQL keywords, table names, or column names,
-so the following will not work, even if $table_name is set
+so the following will not work, even if Why Bind Variables Are Useful
+ Why Bind Variables Are Useful
Why bother with bind variables at all - why not just write the Tcl statement
above like this:
(Note the use of double-quotes to allow the variable reference to
-$some_presentation_id to be interpolated in.) This will work,
+ Usage Every db_* command accepting a SQL command as an argument
-supports bind variables. You can either specify the -bind switch to provide a set with bind variable
-values, or specify the -bind switch to explicitly provide a list of
-bind variable names and values, or not specify a bind variable list at all, in which case Tcl variables are
+ Usage Every specify the specify the not specify a bind variable list at all, in which case Tcl variables are
used as bind variables.
-The default behavior (i.e., if the -bind switch is omitted) is
+The default behavior (i.e., if the
-The value of the local Tcl variable user_id (123456) is bound to
-the user_id bind variable.
- The -bind switch can takes the name of an ns_set
+The value of the local Tcl variable The
-Alternatively, as an argument to -bind you can specify a list of
+Alternatively, as an argument to
+
When processing a DML statement, Oracle coerces empty strings into
-null. (This coercion does not occur in the
-WHERE clause of a query, i.e.
-col = '' and
-col is null are not equivalent.)
+ As a result, when using bind variables, the only way to make Oracle set a
-column value to null is to set the corresponding bind variable
+column value to These Oracle quirks complicate the process of writing clear and abstract
+"null" will be interpreted as the literal string
+"null". These Oracle quirks complicate the process of writing clear and abstract
DML difficult. Here is an example that illustrates why:
Since databases other than Oracle do not coerce empty strings into
-null, this code has different semantics depending on the
+ Therefore, the Database Access API provides a database-independent way to
-represent null (instead of the Oracle-specific idiom of the
-empty string): db_null. Use it instead of the empty string whenever you want to set a column value
-explicitly to null, e.g.: Use it instead of the empty string whenever you want to set a column value
+explicitly to
We now require that each SQL statement be assigned a logical name for the
statement that is unique to the procedure or page in which it is defined.
This is so that (eventually) we can implement logically named statements with
alternative SQL for non-Oracle databases (e.g., Postgres). More on this
later.
-
-Normally, db_foreach, db_0or1row, and
-db_1row places the results of queries in Tcl variables, so you
+
+Normally,
However, sometimes this is not sufficient: you may need to examine the rows
returned, to dynamically determine the set of columns returned by the query,
or to avoid collisions with existing variables. You can use the
--column_array and -column_set switches to
-db_foreach, db_0or1row, and db_1row to
+
will write something like:
- first_names is Jon. last_name is Salz. first_names is Lars. last_name is Pind. first_names is Michael. last_name is Yoon.
-Note that you never have to use ns_db anymore (including
-ns_db gethandle)! Just start doing stuff, and (if you want) call
-db_release_unused_handles when you're done as a hint to
+ first_names is Jon. last_name is Salz. first_names is Lars. last_name is Pind. first_names is Michael. last_name is Yoon.
+Note that you never have to use Returns a value which can be used in a bind variable to represent the SQL
-value null. See Nulls and Bind Variables
+value Performs the SQL query sql, executing
-code_block once for each row with variables set to
-column values (or a set or array populated if -column_array or
-column_set is specified). If the query returns no rows, executes
-if_no_rows_block (if provided). Example: Performs the SQL query Example:
-The code block may contain break statements (which terminate the
-loop and flush the database handle) and continue statements
-(which continue to the next row of the loop). Performs the SQL query sql, setting variables to
+ Performs the SQL query Example: Performs the SQL query sql. If a row is returned,
+ Performs the SQL query Returns the first column of the result of SQL query
-sql. If sql doesn't return a
-row, returns default (or throws an error if
-default is unspecified). Analogous to
-database_to_tcl_string and
-database_to_tcl_string_or_null.
+ Returns the next value for the sequence sequence-name (using a
-SQL statement like SELECT sequence-name.nextval FROM
-DUAL). If sequence pooling is enabled for the sequence, transparently
+SQL statement like Returns a Tcl list of the values in the first column of the result of SQL
-query sql. If sql doesn't
+query Returns a Tcl list, each element of which is a list of all column values
-in a row of the result of SQL query sql. If
-sql doesn't return any rows, returns an empty list.
-(Analogous to database_to_tcl_list_list.)
+in a row of the result of SQL query
Returns a list of ns_sets with the values of each column of each row
- returned by the sql query specified.
- Performs the DML or DDL statement sql. If a length-n list of blobs or clobs is provided, then the SQL
+ Performs the DML or DDL statement If a length-n list of blobs or clobs is provided, then the SQL
should return n blobs or clobs into the bind variables
-:1, :2, ... :n.
-blobs or clobs, if specified,
+ Example: Example:
-This inserts a new row into the photos table, with the contents
-of the files /var/tmp/the_photo and
-/var/tmp/the_thumbnail in the image and
-thumbnail columns, respectively.
+This inserts a new row into the Analagous to ns_ora write_clob/write_blob/blob_get_file.
+db_blob_get_file statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
+ Analagous to Releases any allocated, unused database handles. Executes code_block transactionally. Nested
-transactions are supported (end transaction is transparently
-ns_db dml'ed when the outermost transaction completes). The
-db_abort_transaction command can be used to abort all levels of
-transactions. It is possible to specify an optional on_error
+ Releases any allocated, unused database handles. Executes Example: Example: Aborts all levels of a transaction. That is if this is called within
several nested transactions, all of them are terminated. Use this insetead of
-db_dml "abort" "abort transaction".
+
- Performs the SQL query sql, saving results in variables
+ Performs the SQL query
Each row also has a column, rownum, automatically
added and set to the row number, starting with 1. Note that this will
override any column in the SQL statement named 'rownum', also if you're
using the Oracle rownum pseudo-column.
- If the -local is passed, the variables defined
+ If the
@@ -576,19 +576,19 @@
multirow.
You may also add additional, computed columns to the multirow, using the
- -extend { col_1 col_2 ... } switch. This is
+
If you're constructing your multirow through multiple queries with the
same set of columns, but with different rows, you can use the
- -append switch. This causes the rows returned by this query
+
- Your code block may call continue in order to skip a row
- and not include it in the multirow. Or you can call break
+ Your code block may call
@@ -603,28 +603,28 @@
} {
set user_url [acs_community_member_url -user_id $user_id]
}
- Returns the number of rows affected or returned by the previous
statement.
- Places a database handle into the variable var and
-executes code_block. This is useful when you don't
-want to have to use the new API (db_foreach,
-db_1row, etc.), but need to use database handles explicitly. Example: Places a database handle into the variable Example:
Returns the name of the database, as returned by the driver.
Returns the RDBMS type (i.e. oracle, postgresql) this OpenACS installation is
using. The nsv ad_database_type is set up during the bootstrap process.
Returns 1 if the given db_type is compatible with the current RDBMS.
Returns 1 if db_type_list contains the current RDMBS type. A package
intended to run with a given RDBMS must note this in it's package info
file regardless of whether or not it actually uses the database.
Returns 1 if the package is a legacy package. We can only tell for certain if
it explicitly supports Oracle 8.1.6 rather than the OpenACS more general oracle.
Returns the RDBMS version (i.e. 8.1.6 is a recent Oracle version; 7.1 a
recent PostgreSQL version.
Returns the current rdbms type and version.
Returns a list of three-element lists describing the database engines known
to OpenACS. Each sublist contains the internal database name (used in file
- paths, etc), the driver name, and a "pretty name" to be used in selection
+ paths, etc), the driver name, and a "pretty name" to be used in selection
forms displayed to the user.
The nsv containing the list is initialized by the bootstrap script and should
Index: openacs-4/packages/acs-core-docs/www/db-api.html
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/db-api.html,v
diff -u -r1.49 -r1.49.2.1
--- openacs-4/packages/acs-core-docs/www/db-api.html 31 Jul 2011 23:11:45 -0000 1.49
+++ openacs-4/packages/acs-core-docs/www/db-api.html 21 Aug 2013 10:19:21 -0000 1.49.2.1
@@ -1,22 +1,22 @@
-
-
+
+
By Pete Su and Jon Salz. Modified by Roberto Mello.
-
+
One of OpenACS's great strengths is that code written for it is
very close to the database. It is very easy to interact with the
database from anywhere within OpenACS, and we have a
coherent API for database access which makes this even easier.
More detailed information about the DB api is available at
- Database Access API.
-
+ Database Access API.
+
The OpenACS database API is meant to save developers from making
common mistakes and to provide a more structured syntax for
specifying database operations, including transactions. Here's
an example of the API.
There are several things to note here:
-
+
No explicit code for grabbing and releasing handles. Usage of the
Database API implicitly deals with all handle management issues.
-
- The db_transaction command
+
+ The
- The command db_foreach writes
+
+ The command
+
Every SQL query has a name, which is used in conjunction with .XQL files
to support multiple databases.
-
+
Finally and most importantly, there API implements bind variables, which we will cover next.
-
Bind variables are placeholders for literal values in an SQL
query being sent to the server. In the old way, data was
generally passed to directly to the DB backend, via Tcl string
@@ -69,14 +69,14 @@
where some_table.id=some_other_table.id
and some_table.condition_p = '$foo'
There are a few problems with this:
-
+
If the value of $foo is a huge string, then we waste a lot
of time in the database server doing useless parsing.
-
+
Second, if the literal value contains characters like single
quotes, we have to be careful to properly escape them,
because not quoting them will lead to surprising errors.
-
+
Third, no type checking occurs on the literal
value. Finally, if the Tcl variable is passed in or between
web forms or otherwise subject to external modification,
@@ -129,8 +129,8 @@
query, and Tcl style string interpolation does not happen. So you
cannot do something like:
@@ -142,24 +142,24 @@
Finally, the DB API has several different styles for passing bind
variable values to queries. In general, use the style presented here
because it is the most convenient.
- Every db_* command accepting a SQL command as an argument
- supports bind variables. You can either
- Specify the -bind switch to provide a set with bind variable
+ Every
+ Specify the
- Specify the -bind switch to explicitly provide a list of
+
+ Specify the
+
Not specify a bind variable list at all, in which case Tcl variables are
used as bind variables.
- The default behavior (i.e., if the -bind switch is omitted) is
+ The default behavior (i.e., if the
- The value of the local Tcl variable user_id (123456) is bound to
- the user_id bind variable.
- The -bind switch can takes the name of an ns_set
+ The value of the local Tcl variable The
- Alternatively, as an argument to -bind you can specify a list of
+ Alternatively, as an argument to
When processing a DML statement, Oracle coerces empty strings into
- null. (This coercion does not occur in the
- WHERE clause of a query, i.e.
- col = '' and
- col is null are not equivalent.)
+ As a result, when using bind variables, the only way to make Oracle set a
- column value to null is to set the corresponding bind variable
+ column value to These Oracle quirks complicate the process of writing clear and abstract
+ "null" will be interpreted as the literal string
+ "null". These Oracle quirks complicate the process of writing clear and abstract
DML difficult. Here is an example that illustrates why:
Since databases other than Oracle do not coerce empty strings into
- null, this code has different semantics depending on the
+ Therefore, the Database Access API provides a database-independent way to
- represent null (instead of the Oracle-specific idiom of the
- empty string): db_null. Use it instead of the empty string whenever you want to set a column value
- explicitly to null, e.g.: Use it instead of the empty string whenever you want to set a column value
+ explicitly to
The database library can transparently maintain pools of sequence values, so
- that each request for a new sequence value (using db_nextval)
+ that each request for a new sequence value (using
- in any configuration section in the yourservername.ini
+ in any configuration section in the
The Database API has several functions that wrap familiar parts of the
AOLserver database API.
- Note that you never have to use ns_db anymore (including
- ns_db gethandle)! Just start doing stuff, and (if you want) call
- db_release_unused_handles when you're done as a hint to
+ Note that you never have to use Aborts all levels of a transaction. That is if this is called within
several nested transactions, all of them are terminated. Use this insetead of
- db_dml "abort" "abort transaction".
+
- Performs the SQL query sql, saving results in variables
+ Performs the SQL query
Each row also has a column, rownum, automatically
added and set to the row number, starting with 1. Note that this will
override any column in the SQL statement named 'rownum', also if you're
using the Oracle rownum pseudo-column.
- If the -local is passed, the variables defined
+ If the
@@ -334,19 +334,19 @@
multirow.
You may also add additional, computed columns to the multirow, using the
- -extend { col_1 col_2 ... } switch. This is
+
If you're constructing your multirow through multiple queries with the
same set of columns, but with different rows, you can use the
- -append switch. This causes the rows returned by this query
+
- Your code block may call continue in order to skip a row
- and not include it in the multirow. Or you can call break
+ Your code block may call
Notice the nonstandard numbering (everything
@@ -380,240 +380,240 @@
Technically it's equivalent to using a code block on
the end of your db_multirow.
Returns a value which can be used in a bind variable
to represent the SQL value
- null.
- See Nulls and
+
Performs the SQL query
- sql
+ Example:
- The code block may contain break statements (which terminate the
- loop and flush the database handle) and continue statements
+ The code block may contain
Performs the SQL query
- sql,
+ Example:
Performs the SQL query
- sql.
+
Returns the next value for the sequence sequence-name (using a
- SQL statement like SELECT
- sequence-name.nextval FROM
- DUAL). If sequence pooling is enabled for the sequence, transparently
+ SQL statement like Registers the sequence sequence-name to be pooled, with a pool
size of pool-size sequence values
- (see Sequence Pooling).
+ (see Sequence Pooling).
- Returns the first column of the result of SQL query
- sql.
- If sql doesn't return a
+ Returns a Tcl list of the values in the first column of the result of SQL
query
- sql.
- If sql doesn't
+ Returns a Tcl list, each element of which is a list of all column values
- in a row of the result of SQL query sql. If
- sql doesn't return any rows, returns an empty list.
- (Analogous to database_to_tcl_list_list.)
+ in a row of the result of SQL query Performs the DML or DDL statement sql. If a length-n list of blobs or clobs is provided, then the SQL
+ Performs the DML or DDL statement If a length-n list of blobs or clobs is provided, then the SQL
should return n blobs or clobs into the bind variables
- :1, :2, ... :n.
- blobs or clobs, if specified,
+ Example: Example:
- This inserts a new row into the photos table, with the contents
- of the files /var/tmp/the_photo and
- /var/tmp/the_thumbnail in the image and
- thumbnail columns, respectively.
+ This inserts a new row into the Analagous to ns_ora write_clob/write_blob/blob_get_file.
+ Analagous to Releases any allocated, unused database handles. Releases any allocated, unused database handles. Executes code_block transactionally. Nested
- transactions are supported (end transaction is transparently
- ns_db dml'ed when the outermost transaction completes). The
- db_abort_transaction command can be used to abort all levels of
- transactions. It is possible to specify an optional on_error
+ Executes Example: Example: Returns the number of rows affected or returned by the previous
statement.
- Places a database handle into the variable var and
- executes code_block. This is useful when you don't
- want to have to use the new API (db_foreach,
- db_1row, etc.), but need to use database handles explicitly. Example: Places a database handle into the variable Example: For true SQL purists, we provide the convenience function
- db_nullify_empty_string, which returns
- [db_null] if its string argument is the empty string
+
- To balance out this asymmetry, you can explicitly set baz to
- null by writing:
+ To balance out this asymmetry, you can explicitly set
- The database API allows for direct caching of query results. Repeated calls will
+ The database API allows for direct caching of query results. Repeated calls will
return the cached value until it is either explicitly flushed using db_flush_cache,
times out (configured the ns_cache is called to create the cache), or another cached
query fills the cache, causing older entries to be flushed.
- Values returned by a query are cached if you pass the "-cache_key" switch
+ Values returned by a query are cached if you pass the "-cache_key" switch
to the database procedure. The switch value will be used as the key in the
ns_cache eval call used to execute the query and processing code. The
db_flush proc should be called to flush the cache when appropriate. The
- "-cache_pool" parameter can be used to specify the cache pool to be used,
+ "-cache_pool" parameter can be used to specify the cache pool to be used,
and defaults to db_cache_pool. The size of the default cache is governed
- by the kernel parameter "DBCacheSize" in the "caching" section.
+ by the kernel parameter "DBCacheSize" in the "caching" section.
Currently db_string, db_list, db_list_of_lists, db_1row, db_0or1row, and db_multirow support
caching.
@@ -677,7 +677,7 @@
more object_ids and a name that identifies the operation being done.
Here is an example from the layout-manager package: Table of Contents Table of Contents
+
+
By Claus Rasmussen, with additions by Roberto Mello, Vinod Kurup, and the OpenACS Community
-
+
OpenACS™ is a powerful system with
incredible possibilities and applications, but
this power comes with some complexity and a steep learning curve
@@ -41,40 +41,40 @@
This document attempts to shape ongoing documentation efforts by
using principles of continual improvement to re-engineer
documentation production.
-
Documentation production shares many of the challenges of
software development, such as managing contributions, revisions
and the (editorial) release cycle. This is yet another
experiment in improving documentation --this time by using
principles of continual improvement to focus the on-going
efforts. These processes are outlined as project management
phases:
-
- Requirements phase is about setting goals and
+
+ Requirements phase is about setting goals and
specifications, and includes exploration of scenarios, use cases
- etc. As an example, see the
+ etc. As an example, see the
OpenACS Documentation Requirements Template which focuses on
systems requirements for developers.
-
- Strategy phase is about creating an approach
+
+ Strategy phase is about creating an approach
to doing work. It sets behavioral guidelines and boundaries
that help keep perspective on how efforts are directed.
OpenACS developers discuss strategy when coordinating
efforts such as code revisioning and new features.
-
- Planning phase is about explicitly stating
+
+ Planning phase is about explicitly stating
the way to implement the strategy as a set of methods.
OpenACS system design requires planning. For example, see
- OpenACS
+ OpenACS
documentation template planning relating to package
design.
-
- Implementation phase is about performing the
+
+ Implementation phase is about performing the
work according to the plan, where decisions on how to handle
unforseen circumstances are guided by the strategy and
requirements.
-
- Verification phase measures how well the plan
+
+ Verification phase measures how well the plan
was implemented. Success is measured by A) verifying if the
project has met the established goals, and B) reviewing for
ongoing problem areas etc. OpenACS follows verification
@@ -88,56 +88,56 @@
phases are mainly organized and fulfilled by a designated documentation maintainer.
Hopefully the following sections will help spur greater
direct participation by the OpenACS community.
-
By the OpenACS Community. This section is a collection of
documentation requirements that have been expressed in the
OpenACS forums to 4th July 2003.
OpenACS documentation should meet the following requirements. No
significance has been given to the order presented, topic breadth or depth here.
-
- clarity in presentation. Life with
- qmail is a recommended example of "rated high" online
+
+ clarity in presentation. Life with
+ qmail is a recommended example of "rated high" online
documentation.
-
+
Avoid requirements that significantly increase the labor
required to maintain documentation.
-
+
Use best practices learned from the print world, web, and
other media, about use of gamma, space, writing style etc.
-
+
Consistency in publishing -Establishing and adhering to publishing standards
-
+
Use standardized language -Use international English
(without slang or colloquial terms) for ESL (English as
a second language) readers (and making translation
easier for those interested in translating the
documentation for internationalization efforts).
-
+
All jargon used in documentation needs to be defined.
Use standardized terms when available, avoiding implicit
understanding of specific OpenACS terms.
-
+
Document titles (for example on html pages) should
include whole document title (as in book title):
(chapter title) : (section), so that bookmarks etc.
indicate location in a manner similar to pages in books
(in print publishing world).
-
+
Organize document according to the needs of the reader
(which may be different than the wishes of the writers).
-
+
Do not make informal exclamations about difficulty/ease
for users to complete tasks or understand... for
- example, "Simply...". Readers come from many different
+ example, "Simply...". Readers come from many different
backgrounds --remember that the greater audience is
likely as varied as the readers on the internet--- If
important, state pre-conditions or knowledge
requirements etc. if different than the rest of the
- context of the document. For example, "requires basic
+ context of the document. For example, "requires basic
competency with a text-based editor such as vi or emacs
- via telnet"
-
+ via telnet"
+
Show where to find current information instead of writing
about current info that becomes obsolete. If the information
is not found elsewhere, then create one place for it, where
@@ -152,20 +152,20 @@
still be in 1 area, using a common layout of perhaps
summary, introduction and discussion requiring increasing
expertise, complexity or specificity.
-
+
Consistency in link descriptions -When link urls refer to
whole documents, make the link (anchor wrapped title) that
points to a document with the same title and/or heading of
the document.
-
+
Consider OpenACS documentation as a set of books (an
encyclopedic set organized like an atlas) that contains
volumes (books). Each book contains chapters and sections
much like how DocBook examples are shown, where each chapter
is a web page. This designation could help create an OpenACs
book in print, and help new readers visualize how the
documentation is organized.
-
+
The use licenses between OpenACS and Arsdigita's ACS are not
compatible, thereby creating strict limits on how much
OpenACS developers should have access to Arsdigita code and
@@ -175,60 +175,60 @@
inference of license noncompliance, while recognizing the
important work accomplished by Philip Greenspun, Arsdigita,
and the early ACS adopters.
-
+
Use a consistent general outline for each book.
-
+
Introduction (includes purpose/goal), Glossary of terms,
Credits, License, Copyright, Revision History
-
+
Table of Contents (TOC)s for each book: the end-users, content and site
administrators, marketing, developer tutorial, and
developers.
-
+
Priorities of order and content vary based on each of
the different readers mentioned. The developers guide
should be organized to be most useful to the priorities
of developers, while being consistent with the general
documentation requirements including publishing strategy,
style etc.
-
+
Use generic DocBook syntax to maximize reader familiarity with the documents.
-
By the OpenACS Community. This section is a collection of
documentation requirements that have been expressed in the
OpenACS forums to 4th July 2003.
OpenACS end-user documentation should meet the following requirements. No
significance has been given to the order presented, topic breadth or depth here.
-
+
End-users should not have to read docs to use the system.
-
+
Include how to get help. How and where to find answers,
contact others, what to do if one gets an AOLserver or other
error when using the system. Include types of available
support (open-source, private commercial etc.) including
references.
-
+
Explain/foster understanding of the overall structure of the
system. This would be an overview of the system components,
how it works, and how to find out more or dig deeper... To
promote the system by presenting the history of the system,
and writing about some tacit knowledge re: OpenACS.org and
the opensource culture.
-
+
Introduce and inspire readers about the uses, benefits, and
the possibilities this system brings (think customer
solution, customer cost, convenience, value). A
comprehensive community communications system; How this
system is valuable to users; Reasons others use OpenACS
- (with quotes in their own words) "...the most important
+ (with quotes in their own words) "...the most important
thing that the ACS does is manage users, i.e. provide a way
to group, view and manipulate members of the web community.
- -- Talli Somekh, September 19, 2001" using it to
+ -- Talli Somekh, September 19, 2001" using it to
communicate, cooperate, collaborate... OpenACS offers
directed content functionality with the OpenACS templating
system. ... OpenACS is more than a data collection and
@@ -238,32 +238,32 @@
is built and the library of tried and tested community
building tools that are waiting to be added. It seems that
most portals just add another layer of complexity to the
- cake. See Slides on OACS
+ cake. See Slides on OACS
features...a set of slides on OACS features that can
be used for beginners who want to know OACS is about and
what they can do with it. Screen captures that highlight
features. Example shows BBoard, calendar, news, file
storage, wimpy point, ticket tracking. An OpenACS tour; an
abbreviated, interactive set of demo pages.
-
+
From a marketing perspective,
-
- differentiate "product" by highlighting features,
+
+ differentiate "product" by highlighting features,
performance quality, conformance to standards,
durability (handling of technological obsolescence),
reliability, repairability, style of use, design
(strategy in design, specifications, integrated,
well-matched systems etc).
-
- differentiate "service" by highlighting software
+
+ differentiate "service" by highlighting software
availability (licensing and completeness from mature to early
adopters or development versions), community incident
support, project collaborative opportunities, and
contractor support availability
-
+
differentiate price (economic considerations of
opensource and features)
-
+
Discussion and details should rely on meeting criteria
of design, completeness of implementation, and related
system strengths and weaknesses. Marketing should not
@@ -272,10 +272,10 @@
opportunities and threats when compared to other systems
for a specific purpose, and thus is inappropriate (and
becomes stale quickly) for general documentation.
-
+
When identifying subsystems, such as tcl, include links
to their marketing material if available.
-
+
create an example/template comparison table that shows
versions of OpenACS and other systems (commonly
competing against OpenACS) versus a summary feature list
@@ -284,22 +284,22 @@
information was gathered, since information is likely
volatile.
-
+
To build awareness about OpenACS, consider product
differentiation: form, features, performance quality,
conformance quality (to standards and requirements),
durability, reliability, repairability, style, design: the
deliberate planning of these product attributes.
-
+
Include jargon definitions, glossary, FAQs, site map/index,
including where to find Instructions for using the packages.
FAQ should refer like answers to the same place for
consistency, brevity and maintainability.
-
+
Explain/tutorial on how the UI works (links do more than go
to places, they are active), Page flow, descriptions of form
elements; browser/interface strengths and limitations (cookies, other)
-
+
Discuss criteria used to decide which features are
important, and the quality of the implementation from a
users perspective. Each project implementation places a
@@ -308,19 +308,19 @@
than an actual comparison.
Package documentation requirements have additional requirements.
-
+
A list of all packages, their names, their purposes, what
they can and cannot do (strengths, limitations), what
differentiates them from similar packages, minimal
description, current version, implementation status,
author/maintainers, link(s) to more info. Current version
- available at the repository.
-
+ available at the repository.
+
Include dependencies/requirements, known conflicts, and
comments from the real world edited into a longer
description to quickly learn if a package is appropriate for
specific projects.
-
+
Create a long bulleted list of features. Feature list should
go deeper than high-level feature lists and look at the
quality of the implementations (from the user's perspective,
@@ -331,233 +331,233 @@
supported by the current e-commerce module? There are some
packages where the name is clear enough, but what are the
limitations of the standard package?
-
+
End-user docs should not be duplicative. The package
description information and almost everything about a
package for administrators and developers is already
described in the package itself through two basic
- development document templates: a
- Requirements Template and Detailed
+ development document templates: a
+ Requirements Template and Detailed
Design Document.
-
By the OpenACS Community. This section is a collection of
documentation requirements that have been expressed in the
OpenACS forums to 4th July 2003.
OpenACS administrators' documentation should meet the following requirements. No
significance has been given to the order presented, topic breadth or depth here.
-
+
For each requirement below, include links to developer tutorials
and other documentation for more detail.
-
+
Describe a structural overview of a working system and how
- the components work together. "The Layered Cake view" a
+ the components work together. "The Layered Cake view" a
general network view of system; a table showing system
levels versus roles to help with understanding how the
subsystems are interconnected.
-
+
Provide a comprehensive description of typical
administrative processes for operating an OpenACS system
responsibly, including reading logs and command line views that
describe status of various active processes.
-
+
Create a list of administrative tools that are useful to
administrating OpenACS, including developer support,
schema-browser and api browser. Link to AOLserver's config
file documentation.
-
+
Resources on high level subjects such as web services,
security guidelines
-
+
Describe typical skill sets (and perhaps mapped to
standardized job titles) for administrating an OpenACS
system (human-resources style). For a subsite
admin/moderator attributes might include trustworthy,
sociable, familiarity with the applications and
subsystems, work/group communication skills et cetera
-
+
Describe how to set up typical site moderation and
- administration including parameters, permissions, "Hello
- World" page
-
+ administration including parameters, permissions, "Hello
+ World" page
+
Show directory structure of a typical package, explanation
of the various file types in a package (tcl,adp,xql) and how
those relate to the previously described subsystems, when
they get refreshed etc.
-
- Ways to build a "Hello World" page
-
+
+ Ways to build a "Hello World" page
+
Show examples of how the OpenACS templating system is used,
including portal sections of pages. For example, create a
customised auto-refreshing startpage using lars-blogger, a
photo gallery, and latest posts from a forum. This should
rely heavily on documentation existing elsewhere to keep
current. This would essentially be a heavily annotated list
of links.
-
+
Show ways of modifying the look and feel across pages of an
OpenACS website. Refer to the skins package tutorial.
-
+
Describe a methodology for diagnosing problems, finding
error statements and interpreting them --for OpenACS and the
underlying processes.
-
+
FAQs: Administration tasks commonly discussed on boards:
admin page flow, how to change the looks of a subsite with a
- new master.adp, options on "user pages" , a quick
+ new master.adp, options on "user pages" , a quick
introduction to the functions and processes. info about the
user variables, file locations
-
By the OpenACS Community. This section is a collection of
documentation requirements that have been expressed in the
OpenACS forums to 4th July 2003.
OpenACS installation documentation should meet the following requirements. No
significance has been given to the order presented, topic breadth or depth here.
-
- state installation prerequisites. For example: "You should
+
+ state installation prerequisites. For example: "You should
read through the installation process to familiarize
yourself with the installation process, before beginning an
- installation."
-
+ installation."
+
list critical decisions (perhaps as questions) that need to
be made before starting: which OS, which DB, which aolserver
version, system name, dependencies et cetera. Maybe summarize
- options as tables or decision-trees. For example, "As you
+ options as tables or decision-trees. For example, "As you
proceed throughout the installation, you will be acting on
decisions that have an impact on how the remaining part of
the system is installed. Here is a list of questions you
- should answer before beginning."
-
+ should answer before beginning."
+
list pre-installation assumptions
-
+
Show chronological overview of the process of installing a
system to full working status: Install operating
system with supporting software, configure with preparations
for OpenACS, RDBMS(s) install and configure, Webserver
install and configure, OpenACS install and configure,
post-install work
-
By the OpenACS Community. This section is a collection of
documentation requirements that have been expressed in the
OpenACS forums to 4th July 2003.
OpenACS developer tutorial documentation should meet the following requirements. No
significance has been given to the order presented, topic breadth or depth here.
-
+
list learning prerequisites to customize, fix, and improve
OACS modules, and create new ones. You are expected to have
read and understand the information [minimum requirements
similar to adept at Using OpenACS Administrating Guide]
before reading this guide.
-
+
Refer to development documentation instead of duplicating here
-
+
List suggestions for installing and setting up a development
environment; these can be annotated links to the
installation documentation
-
+
Provide working examples that highlight the various
subsystems, tcl environment, OpenACS protocols, aolserver
template and ns_* commands, OpenACS templating, sql queries,
db triggers, scheduling protocols, how to use the page contract,
how to get the accessing user_id etc
-
+
Show how to construct basic SQL queries using the db API,
-
+
The life of an http request to a dynamic, templated page
-
+
General rules to follow for stability, scalability
-
+
Show the step by step customizing of an existing package
that meets current recommended coding styles of OpenACS
package development, by referring to developer resources.
-
- Use the ArsDigita problem sets and "what Lars produced for ACS Java" as inspiration for a
+
+ Use the ArsDigita problem sets and "what Lars produced for ACS Java" as inspiration for a
PostgreSQL equivalent tutorial about developing a new
OpenACS package including discussion of the significance of
the package documentation templates
-
+
Include a summary of important links used by developers
-
+
Note any deprecated tools and methods by linking to prior
versions instead of describing them in current docs
-
By the OpenACS Community. This section is a collection of
documentation requirements that have been expressed in the
OpenACS forums to 4th July 2003.
OpenACS developer documentation should meet the following requirements. No
significance has been given to the order presented, topic breadth or depth here.
-
+
list documentation assumptions, such as familiarity with
modifying OpenACS packages. All kernel docs are here etc.
-
+
This documentation should be written for ongoing use by
developers, not as a tutorial.
-
+
List of practical development and diagnostics tools and
methodologies.
-
+
List of OpenACS development resources, api-doc,
schema-browser, developer-support package etc.
-
+
Identify each OpenACS subsystem, explain why it is used
(instead of other choices). In the case of subsystems that
are developed outside of OpenACS such as tcl, include
external references to development and reference areas.
-
+
Show current engineering standards and indicate where
changes to the standards are in the works.
-
+
Sections should be dedicated to DotLRN standards as well, if
they are not available elsewhere.
-
+
Add overview diagrams showing the core parts of the
datamodel including an updated summary of Greenspun's
Chapter 4: Data Models and the Object System
-
+
package design guidelines and development process templates
including planning, core functions, testing, usability, and
creating case studies
-
- Standard package conventions, where to see "model" code, and
+
+ Standard package conventions, where to see "model" code, and
guidelines (or where to find them) for:
-
+
programming tcl/sql
-
+
using the acs-api
-
+
ad_form
-
+
coding permissions
-
+
OpenACS objects
-
+
scheduled protocols
-
+
call backs
-
+
directory structure
-
+
user interface
-
+
widgets
-
+
package_name and type_extension_table
-
+
adding optional services, including search, general
comments, attachments, notifications, workflow, CR and
the new CR Tcl API
-
+
Document kernel coding requirements, strategy and guidelines
to help code changers make decisions that meet kernel
designers' criteria
-
OpenACS documentation development is subject to the
constraints of the software project development and release
- methods and cycles (Section , “Using CVS with OpenACS”).
+ methods and cycles (the section called “Using CVS with OpenACS”).
Essentially, all phases of work may be active to accommodate
the asynchronous nature of multiple subprojects evolving by
the efforts of a global base of participants with culturally
@@ -567,50 +567,50 @@
involve others by collaborating or obtaining guidance or
feedback (peer review) to distribute the workload and increase
the overall value of output for the OpenACS project.
-
OpenACS documentation is taking a dual approach to publishing.
Documentation that is subject to rapid change and participation by
- the OpenACS community is managed through the OpenACS
+ the OpenACS community is managed through the OpenACS
xowiki Documentation Project
Formal documents that tend to remain static and require more
expressive publishing tools will be marked up to conform to the
- DocBook XML
+ DocBook XML
DTD. The remaining discussion is about publishing using
Docbook.
-
+
is a publishing standard based on XML with
similar goals to the OpenACS Documentation project. Some specific reasons why we are using DocBook:
-
+
It is open-source.
-
+
A growing community surrounds DocBook (has
- mailing lists)
-
+ mailing lists)
+
A number of free and commercial
- tools are available
+ tools are available
for editing and publishing DocBook documents.
-
+
It enables us to publish in a variety of formats.
-
+
XML separates content from presentation: It relieves each
contributor of the burden of presentation, freeing each writer
to focus on content and sharing knowledge.
-
+
It is well tested technology. It has been in development
- since the early 1990's).
+ since the early 1990's).
Reasons why we are using Docbook XML instead of Docbook SGML:
-
+
Consistency and history. We started with a collection
of DocBook XML files that ArsDigita wrote. Trying to re-write them to
conform to the SGML DTD would be unnecessary work.
-
+
XML does not require extra
effort. Writing in XML is almost identical to
SGML, with a couple extra rules. More details in the
- LDP Author Guide.
-
+ LDP Author Guide.
+
The tool chain has matured. xsltproc and other XML
based tools have improved to the point where they are about as good as
the SGML tools. Both can output html and pdf formats.
@@ -629,50 +629,50 @@
should be able to extract details of a specific reference from
a bibliographic (table) and present a footnote at the
point where referenced. DocBook 4.4 allows for this with
- bibliocoverage,
- bibliorelation, and
- bibliosource. DocBook:
+
The following DocBook primer walks you through the basics, and should cover the
needs for 95 percent of the documentation we produce. You are welcome to explore DocBook's
-
+
list of elements and use more exotic features in your
documents. The list is made up of SGML-elements but basically
- the same elements are valid in the XML DTD as long as you remember to:
-
-
You are going to need the following to work with the OpenACS
Docbook XML documentation:
-
+ Docbook XML
DTD - The document type definition for XML. You can
find an RPM or DEB package or you can download a zip file from
the site linked from here.
-
- XSL
+
+ XSL
Stylesheets (docbook-xsl) - The stylesheets to convert
to HTML. We have been using a stylesheet based upon
NWalsh's chunk.xsl.
-
- xsltproc - The processor that
+
+
+ DEB formats or from xmlsoft.org.
+
Some editing tool. A popular one is Emacs with the psgml and nXML
- modes. The LDP Author
- Guide and DocBook
+ modes. The LDP Author
+ Guide and DocBook
Wiki list some alternates.
-
After you have the tools mentioned above, you need to define a
title for your document. Then start thinking about the possible
sections and subsections you will have in your document. Make
@@ -682,200 +682,200 @@
please e-mail the gatekeeper in charge of documentation.
You can look at some templates for documents (in Docbook XML) in
- the sources
+ the sources
for acs-core-docs, especially the
Detailed Design Documentation Template and the
System/Application Requirements Template.
-
- The documentation for each package will make up a little "book" that is structured like this
+
+ The documentation for each package will make up a little "book" that is structured like this
- examples are emphasized:
-
+
The actual content is split up into documents that start at a
- sect1-level. These are then tied together in a top-level document that
+ For now you can take a look at the
- sources of these DocBook documents
+ sources of these DocBook documents
to get an idea of how they are tied together.
-
-
- Given that your job starts at the sect1-level, all your documents should open with a
- <sect1>-tag and end
- with the corresponding </sect1>.
+
+
+ Given that your job starts at the
-
- You need to feed every <sect1> two attributes. The first attribute,
- id, is standard and can be used with all elements. It comes in very
- handy when interlinking between documents (more about this when talking about links in Section , “Links”).
- The value of id has to be unique
- throughout the book you're making since the id's in your
- sect1's will turn into filenames when the book is parsed into HTML.
+
+ You need to feed every
-
- The other attribute is xreflabel. The value of this is the text that will appear
- as the link when referring to this sect1.
+
+ The other attribute is
Right after the opening tag you put the title of the document - this is usually the same as
- xreflabel-attribute. E.g. the top level of the document you're
+
-
+
Inside this container your document will be split up into
- <sect2>'s,
- each with the same requirements - id and xreflabel
- attributes, and a <title>-tag inside. Actually, the xreflabel is never required in sections, but it makes linking to that section a lot easier.
+
When it comes to naming your
- sect2's and below, prefix them with some abbreviation of the id in the sect1 such as requirements-overview.
-
-
+
+
For displaying a snippet of code, a filename or anything else you just want to appear as a part of
a sentence, we use
- <computeroutput>
- and <code><code></code>
+
For bigger chunks of code such as SQL-blocks, the tag
- <programlisting> is used. Just wrap your code block in it; mono-spacing, indents and all that stuff is taken care of
+ For expressing user interaction via a terminal window, we wrap
- the <screen>
- tag around text that has been wrapped by combinations of <computeroutput>
- and <userinput>
-
-
+ the
+
Linking falls into two different categories: inside the book you're making and outside:
-
- By having unique id's you can cross-reference any part of your book
+
+ By having unique Check out how I link to a subsection of the Developer's Guide: Put this in your XML: Check out how I link to a subsection of the Developer's Guide: Put this in your XML: And the output is:
Note that even though this is an empty tag, you have to either:
-
- Provide the end-tag, </xref>, or
-
- Put a slash before the ending-bracket: <xref linkend="blahblah"/>
- If the section you link to hasn't a specified xreflabel-attribute,
+
+ Provide the end-tag,
+ Put a slash before the ending-bracket: If the section you link to hasn't a specified Put this in your XML: And the output is:
- Note that since I haven't provided an xreflabel for the subsection,
- packages-looks, the
+ Note that since I haven't provided an
+
If you're hyper-linking out of the documentation, it works almost the same way as HTML - the tag is just
a little different
- (<ulink>):
+ (
+
....will create a hyper-link to Oracle in the HTML-version of the documentation.
- NOTE: Do NOT use
+ NOTE: Do NOT use
ampersands in your hyperlinks. These are reserved for
- referencing entities.
- To create an ampersand, use the entity <code>&</code>
+ referencing entities.
+ To create an ampersand, use the entity
- Note: The graphics guidelines
+ Note: The graphics guidelines
are not written in stone. Use another valid approach if it works better
for you.
-
+
To insert a graphic we use the elements
- <mediaobject>,
- <imageobject>,
- <imagedata>,
+
- Put your graphics in a separate directory ("images") and link to them
+ Put your graphics in a separate directory ("images") and link to them
only with relative paths.
-
+
Here's how you make the DocBook equivalent of the three usual HTML-lists:
-
- Making an unordered list is pretty much like doing the same thing in HTML - if you close your <li>, that is. The only differences are that each list item has to be wrapped in something more, such as
- <para>, and that the tags are called
- <itemizedlist>
+
+ Making an unordered list is pretty much like doing the same thing in HTML - if you close your
+
The ordered list is like the preceding, except that you use
- <orderedlist> instead:
- This kind of list is called a variablelist and these are the tags you'll need to
+
+ This kind of list is called a
+
DocBook supports several types of tables, but in most cases, the
- <informaltable>
+
If you want cells to span more than one row or column, it gets a bit more complicated - check out
- <table>
+
+
Our documentation uses two flavors of emphasis - italics and bold type. DocBook uses one -
- <emphasis>.
+
- The <emphasis> tag defaults to italics when parsed. If you're looking for
- emphasizing with bold type, use <emphasis role="strong">.
-
+ The
Words that are marked as index-words are referenced in an index
in the final, parsed document.
Use
- <indexterm>,
- <primary> and
- <secondary>
+ This section is quoted almost verbatim from the LDP Author Guide.
- Once you have the Docbook Tools
+ This section is quoted almost verbatim from the LDP Author Guide.
+ Once you have the Docbook Tools
installed, you can convert your xml documents to HTML or other
formats.
@@ -955,52 +955,52 @@
To generate a single HTML file from your DocBook XML file,
use the command:
- This example uses Daniel Veillard's xsltproc command available
- as part of libxslt from http://www.xmlsoft.org/XSLT/.
+ This example uses Daniel Veillard's xsltproc command available
+ as part of libxslt from http://www.xmlsoft.org/XSLT/.
If you are using other XML processors such as Xalan or Saxon,
you will need to change the command line appropriately.
To generate a set of linked HTML pages, with a separate page
for each <chapter>, <sect1> or <appendix> tag, use the
following command:
- You could also look at the acs-core-docs Makefile
+ You could also look at the acs-core-docs Makefile
for examples of how these documents are generated.
-
- The LDP Author
+
+ The LDP Author
Guide has a lot of good information, a table of
- docbook elements and their "look" in HTML and lots of good links
+ docbook elements and their "look" in HTML and lots of good links
for tools.
-
+
James Clark
- wrote nXML Mode, an alternative
+ wrote nXML Mode, an alternative
to PSGML Mode. nXML Mode can validate a file as it is edited.
-
+
David Lutterkort
- wrote an intro to the PSGML Mode in Emacs
-
+ wrote an intro to the PSGML Mode in Emacs
+
James Clark's free Java parser
- XP. Note that
+ XP. Note that
this does not validate XML, only parses it.
-
+ DocBook Tool for Linux:
Converts docbook documents to a number of formats. NOTE: I only got these to
work with Docbook SGML, NOT with Docbook XML. If you are
able to make it work with our XML, please let us know.
-
- AptConvert from PIXware is a Java editor that will produce
+
+ AptConvert from PIXware is a Java editor that will produce
DocBook documents and let you transform them into HTML and PDF for a local preview before you submit.
-
+
In the process of transforming your HTML into XML,
- HTML tidy
- can be a handy tool to make your HTML "regexp'able".
+ HTML tidy
+ can be a handy tool to make your HTML "regexp'able".
Brandoch Calef has made a
- Perl
+ Perl
script with directions (now via archive.org)
that gets you most of the way.
- By Michael Bryzek By Michael Bryzek
Constraint naming standard is important for one reason: The SYS_* name oracle
assigns to unnamed constraints is not very understandable. By correctly
naming all contraints, we can quickly associate a particular constraint
with our data model. This gives us two real advantages:
- We can quickly identify and fix any errors. We can reliabily modify or drop constraints
+ We can quickly identify and fix any errors. We can reliabily modify or drop constraints
-Oracle limits names,
+Oracle limits names,
in general, to 30 characters, which is hardly enough for a human readable constraint name.
-
We propose the following naming convention for all constraints, with
the following abbreviations taken from Oracle Docs at
-
+
http://oradoc.photo.net/ora81/DOC/server.815/a67779/ch4e.htm#8953.
Note that we shortened all of the constraint abbrevations to
two characters to save room.
-
+
<table name>_<column_name>_<constraint abbreviation>
In reality, this won't be possible because of the character limitation on
names inside oracle. When the name is too long, we will follow these two
steps in order:
- Abbreviate the table name with the table's initials (e.g. users -> u and users_contact -> uc).
- Truncate the column name until it fits.
+ Abbreviate the table name with the table's initials (e.g. users -> u and users_contact -> uc).
+ Truncate the column name until it fits.
If the constraint name is still too long, you should consider rewriting your
entire data model :)
- Notes: If you have to abbreviate the table name for one of the constraints, abbreviate it for all the constraints If you are defining a multi column constraint, try to truncate the two column names evenly Notes: If you have to abbreviate the table name for one of the constraints, abbreviate it for all the constraints If you are defining a multi column constraint, try to truncate the two column names evenly
Naming primary keys might not have any obvious advantages. However, here's an
example where naming the primary key really helps (and this is by no means
a rare case!
@@ -71,18 +71,18 @@
3 1 INDEX (UNIQUE SCAN) OF 'EXAMPLE_TOPICS_TOPIC_ID_PK' (UNI
QUE)
-Isn't it nice to see "EXAMPLE_TOPICS_TOPIC_ID_PK" in the trace
+Isn't it nice to see "EXAMPLE_TOPICS_TOPIC_ID_PK" in the trace
and know exactly which table oracle is using at each step?
-
People disagree on whether or not we should be naming not null
constraints. So, if you want to name them, please do so and follow
the above naming standard. But, naming not null constraints is not a
requirement.
-Though naming "not null" constraints doesn't help immeditately in error
+Though naming "not null" constraints doesn't help immeditately in error
debugging (e.g. the error will say something like
-"Cannot insert null value into column"), we recommend naming not null
+"Cannot insert null value into column"), we recommend naming not null
constraints to be consistent in our naming of all constraints.
By Michael Yoon and Aurelius Prochazka By Michael Yoon and Aurelius Prochazka
To ensure consistency (and its collateral benefit, maintainability),
we define and adhere to standards in the following areas:
-
+
Usually we organize our files so that they mainly serve one of the following three purposes:
- displaying objects and their properties manipulating or acting on objects in some way (by creating, editing, linking, etc) housing procedures, packages, data models and other prerequisite code
+ displaying objects and their properties manipulating or acting on objects in some way (by creating, editing, linking, etc) housing procedures, packages, data models and other prerequisite code
Essentially, we want our files named in a fashion that reflects their purpose.
-Under the page root (and the template root if using the Style package):
- For naming files that enable a specific action on an object, use this format:
-object-verb.extension
+Under the page root (and the template root if using the Style package):
+ For naming files that enable a specific action on an object, use this format:
+
For example, the page to erase a user's portrait from the database is
-/admin/users/portrait-erase.tcl.
- However, modules typically deal with only one primary type of object -
+ However, modules typically deal with only one primary type of object -
e.g.,
the Bookmarks module deals mainly with bookmarks - and so action-type files in modules don't need to be specified by the object they act on. Example: the user pages
-for the Bookmarks module live in the /bookmarks/
-directory, and so there is no need to name the bookmark editing page with a redundant url: /bookmarks/bookmark-edit.tcl. Instead, we omit the object type, and use this convention:
+for the Bookmarks module live in the
-verb.extension
+
-Thus, the page to edit a bookmark is /bookmarks/edit.tcl.
- For naming files that display the properties of a primary object - such as the bookmark object within the bookmark module - use this convention:
-one.extension
+Thus, the page to edit a bookmark is For naming files that display the properties of a primary object - such as the bookmark object within the bookmark module - use this convention:
+
For example, the page to view one bookmark is
-/bookmarks/one.tcl. Note that no verb is necessary for display-type files.
- Otherwise, if the object to be displayed is not the primary feature of a module, simply omit the verb and use the object name:
-object.extension
+ Otherwise, if the object to be displayed is not the primary feature of a module, simply omit the verb and use the object name:
+
For example, the page to view the properties of an
ecommerce product is
-/ecommerce/product.tcl.
- For naming files in a page flow, use the convention: foobar.extension (Step 1) foobar-2.extension (Step 2) ... foobar-N.extension (Step N)
-where foobar is determined by the above
+ For naming files in a page flow, use the convention: ...
+where
Typically, we use a three-step page flow when taking user information:
- Present a form to the user Present a confirmation page to the user Perform the database transaction, then redirect Put data model files in /www/doc/sql, and name them
+ Present a form to the user Present a confirmation page to the user Perform the database transaction, then redirect Put data model files in
-module.sql
+
In the Tcl library directory:
- For files that contain module-specific procedures, use the
+ For files that contain module-specific procedures, use the
convention:
-module-procs.tcl
- For files that contain procedures that are part of the core ACS,
+ For files that contain procedures that are part of the core ACS,
use the convention:
-ad-description-procs.tcl
-
File names also appear within pages, as linked URLs and
-form targets. When they do, always use abstract
-URLs (e.g., user-delete instead of
-user-delete.tcl), because they enhance maintainability.
+form targets. When they do, always use abstract
+URLs (e.g.,
Similarly, when linking to the index page of a directory, do not
-explicitly name the index file (index.tcl,
-index.adp, index.html, etc.). Instead, use
+explicitly name the index file (
Include the appropriate standard header in all scripts. The first
line should be a comment specifying the file path relative to the
ACS root directory. e.g.
-
+
+
or
-
+
+
For static content files (html or adp), include a CVS identification tag as a
comment at the top of the file, e.g.
For non-library Tcl files (those not in the private Tcl directory),
-use ad_page_contract
+use
-Salient features of ad_page_contract:
- A mandatory documentation string is the first argument. This has
-the standard form with javadoc-style @author, @cvs-id, etc, and should contain a short description of the recieved variables and any necessary explanations. The second argument specifies the page
+Salient features of A mandatory documentation string is the first argument. This has
+the standard form with javadoc-style @author, @cvs-id, etc, and should contain a short description of the recieved variables and any necessary explanations. The second argument specifies the page
inputs. The syntax for switches/flags (e.g. multiple-list, array,
etc.) uses a colon (:) followed by any number of flags
separated by commas (,),
-e.g. foo:integer,multiple,trim. In particular, multiple and
-array are the flags that correspond to the old
-ad_page_variables flags. There are new flags: trim, notnull and
-optional. They do what you'd expect; values will not be
+e.g. There are new flags: ad_page_contract can do validation for you: the flags integer
-and sql_identifier will make sure that the values
-supplied are integers/sql_identifiers. The integer flag
+unless you declare it optional. Note that ad_page_contract does not generate
+ Note that
-For shared Tcl library files, use ad_library after
+For shared Tcl library files, use
-Of course, replace "--" with the comment delimiter
+Of course, replace "
Construct the page as one Tcl variable (name it
-page_content), and then send it back to the browser with
-one call to doc_return, which will call
+
For example:
-The old convention was to call ReturnHeaders and
-then ns_write for each distinct chunk of the page. This
+The old convention was to call
Local procedures (i.e., procedures defined and used only within one
-page) should be prefixed with "module_" and
+page) should be prefixed with "
All files that prepare HTML to display should end with [ad_footer] or
@@ -225,7 +225,7 @@
edit ad_header (which quite possibly can start a <table>) and
ad_footer (which may need to end the table started in ad_footer) to
customize the look and feel of the entire site.
-
+
+
By Richard Li and Yon Feldman
+
All PL/SQL code must be well documented. We must write code that
is maintainable by others, this is especially true in our case
because we are building an open source toolkit than anyone can
download and browse the source code. So document like you are
- trying to impress your "Introduction to Programming" professor or
+ trying to impress your "Introduction to Programming" professor or
TA.
-
+
It is important to be consistent throughout an application as much
as is possible given the nature of team development. This means
carrying style and other conventions suchs as naming within an
application, not just within one file.
-
Encapsulation of related fuctionality is key to maintainability
and upgradeability of our software. Try to bundle your code into
- packages
+ packages
whenever possible. This will make upgrading, bug fixing, and
customizing, among other things, a possibility.
-
+
When creating functions or procedures use the following template,
it demonstrates most of the guidelines set forth in this document
that correspond to functions and procedures:
@@ -53,32 +53,32 @@
/
show errors
-
- Always use create or replace procedure|function
- <proc_or_func_name>. It makes reloading packages much
+
+ Always use
- Always qualify end statements, i.e., the
- end statement for a package should be end
- <package_name>;, not just end;; same
+
+ Always qualify
- Always use the "show errors" SQL*Plus command after each PL/SQL
+
+ Always use the "show errors" SQL*Plus command after each PL/SQL
block. It will help you debug when there are compilation errors in
your PL/SQL code.
-
+
Name parameters as simply as possible, i.e., use the column name
if the parameter corresponds to a table column. We're deprecating
the v_* and *_in syntax in favor of named parameters notation:
To achieve this we must fully qualify arguements passed into
@@ -107,23 +107,23 @@
/
show errors
-
- Explicitly designate each parameter as "in," "out," or "inout."
-
+
+ Explicitly designate each parameter as "in," "out," or "inout."
+
Each parameter should be on its own line, with a tab after the
parameter name, then in/out/inout, then a space, and finally the
datatype.
-
+
Use %TYPE and %ROWTYPE whenever possible.
-
- Use 't' and 'f' for booleans, not the PL/SQL "boolean" datatype
+
+ Use 't' and 'f' for booleans, not the PL/SQL "boolean" datatype
because it can't be used in SQL queries.
-
- All new functions (e.g., acs_object.new,
- party.new, etc.) should optionally accept an ID:
+
+ All
- takes the optional argument object_id. Do this to
+ takes the optional argument
Some general style guidelines to follow for the purpose of
consistency across applications.
-
+
Standard indentation is 4 spaces. Our PL/SQL code is not only
viewable in the SQL files but also through our SQL and PL/SQL
browsers. This means that we should try to make it as consistent
as possible to all source code readers.
-
+
Lowercase everything, with the exception of %TYPE and %ROWTYPE.
By Ron Henderson, Revised by Joel Aufrecht By Ron Henderson, Revised by Joel Aufrecht
OpenACS version numbers help identify at a high-level what is in a
particular release and what has changed since the last release.
- A "version number" is really just a string of the form:
- major.minor.dot[ milestone ] A major number change indicates a fundamental change in the architecture of the system, e.g. OpenACS 3 to ACS 4. A major change is required if core backwards compatibility is broken, if upgrade is non-trivial, or if the platform changes substantially. A minor change represents the addition of new functionality or changed UI. A dot holds only bug fixes and security patches. Dot releases are always recommended and safe.
- A milestone marker indicates the state of the release: d, for development, means the release is in active development and is not in its intended released form. a, for alpha, means new development is complete and code checkins are frozen. Alpha builds should work well enough to be testable. b, for beta, means most severe bugs are fixed and end users can start trying the release. Release Candidate builds (rc) are believed to meet all of the criteria for release and can be installed on test instances of production systems. Final releases have no milestone marker. (Exception: In CVS, they are tagged with -final to differentiate them from branch tags.)
+ A "version number" is really just a string of the form:
+ major.minor.dot[ milestone ] A major number change indicates a fundamental change in the architecture of the system, e.g. OpenACS 3 to ACS 4. A major change is required if core backwards compatibility is broken, if upgrade is non-trivial, or if the platform changes substantially. A minor change represents the addition of new functionality or changed UI. A dot holds only bug fixes and security patches. Dot releases are always recommended and safe.
+ A milestone marker indicates the state of the release: d, for development, means the release is in active development and is not in its intended released form. a, for alpha, means new development is complete and code checkins are frozen. Alpha builds should work well enough to be testable. b, for beta, means most severe bugs are fixed and end users can start trying the release. Release Candidate builds (rc) are believed to meet all of the criteria for release and can be installed on test instances of production systems. Final releases have no milestone marker. (Exception: In CVS, they are tagged with -final to differentiate them from branch tags.)
Milestone markers are numbered: d1, d2, ..., a1, b1, rc1, etc. A complete sequence of milestones between two releases:
In the future, OpenACS packages should follow this same
convention on version numbers.
- So what distinguishes an alpha release from a beta
+ So what distinguishes an alpha release from a beta
release? Or from a production release? We follow a specific set of
rules for how OpenACS makes the transition from one state of maturity to
-the next. These rules are fine-tuned with each release; an example is 5.0.0 Milestones and Milestone Criteria
+the next. These rules are fine-tuned with each release; an example is 5.0.0 Milestones and Milestone Criteria
Each package has a maturity level. Maturity level is recorded in the .info file for each major-minor release of OpenACS,
and is set to the appropriate value for that release of the package.
- Level -1: Incompatible. This package is not supported for this platform and should not be expected to work.
-
- Level 0: New Submission. This is the default for packages that do not have maturity explicitly set,
+
+ Level -1: Incompatible. This package is not supported for this platform and should not be expected to work.
+
+ Level 0: New Submission. This is the default for packages that do not have maturity explicitly set,
and for new contributions. The only criterion for level 0 is that at least one person asserts that it works on a given platform.
-
- Level 1: Immature. Has no open priority 1 or priority 2 bugs. Has been installed by at least
+
+ Level 1: Immature. Has no open priority 1 or priority 2 bugs. Has been installed by at least
10? different people, including 1 core developer. Has been available in a stable release for at least 1 month. Has API documentation.
-
- Level 2: Mature. Same as Level 1, plus has install guide and user documentation;
+
+ Level 2: Mature. Same as Level 1, plus has install guide and user documentation;
no serious deviations from general coding practices; no namespace conflicts with existing level 2 packages.
-
- Level 3: Mature and Standard. Same as level 2, plus meets published coding standards;
+
+ Level 3: Mature and Standard. Same as level 2, plus meets published coding standards;
is fully internationalized; available on both supported databases.
- Database upgrade scripts must be named very precisely in order for the Package Manager to run the correct script at the correct time. Upgrade scripts should be named /packages/myfirstpackage/sql/postgresql/upgrade/upgrade-OLDVERSION-NEWVERSION.sql If the version you are working on is a later version than the current released version, OLDVERSION should be the current version. The current version is package version in the APM and in /packages/myfirstpackage/myfirstpackage.info. So if forums is at 2.0.1, OLDVERSION should be 2.0.1d1. Note that this means that new version development that includes an upgrade must start at d2, not d1.
- If you are working on a pre-release version of a package, use the current package version as OLDVERSION. Increment the package version as appropriate (see above) and use the new version as NEWVERSION. For example, if you are working on 2.0.1d3, make it 2.0.1d4 and use upgrade-2.0.1d3-2.0.1d4.sql. Database upgrades should be confined to development releases, not alpha or beta releases.
- Never use a final release number as a NEWVERSION. If you do, then it is impossible to add any more database upgrades without incrementing the overall package version. Use only the d, a, and b letters in OLDVERSION and NEWVERSION. rc is not supported by OpenACS APM. The distance from OLDVERSION to NEWVERSION should never span a release. For example if we had a bug fix in
-acs-kernel on 5.1.0 you wouldn't want a file upgrade-5.0.4-5.1.0d1.sql since if you subsequently need to provide a 5.0.4-5.0.5 upgrade you will have to rename the 5.0.4-5.1.0 upgrade since you can't have upgrades which overlap like that. Instead, use upgrade-5.1.0d1-5.1.0d2.sql
+ Database upgrade scripts must be named very precisely in order for the Package Manager to run the correct script at the correct time. Upgrade scripts should be named If the version you are working on is a later version than the current released version, OLDVERSION should be the current version. The current version is package version in the APM and in If you are working on a pre-release version of a package, use the current package version as OLDVERSION. Increment the package version as appropriate (see above) and use the new version as NEWVERSION. For example, if you are working on 2.0.1d3, make it 2.0.1d4 and use Database upgrades should be confined to development releases, not alpha or beta releases.
+ Never use a final release number as a NEWVERSION. If you do, then it is impossible to add any more database upgrades without incrementing the overall package version. Use only the d, a, and b letters in OLDVERSION and NEWVERSION. rc is not supported by OpenACS APM. The distance from OLDVERSION to NEWVERSION should never span a release. For example if we had a bug fix in
+acs-kernel on 5.1.0 you wouldn't want a file upgrade-5.0.4-5.1.0d1.sql since if you subsequently need to provide a 5.0.4-5.0.5 upgrade you will have to rename the 5.0.4-5.1.0 upgrade since you can't have upgrades which overlap like that. Instead, use Table of Contents People have plenty of usernames and passwords already, we
+
+ People have plenty of usernames and passwords already, we
don't want them to have yet another. We want people to be able to
log in to OpenACS with the same password they use to log in to any
other system. Besides, administrators have better things to do than create
@@ -8,47 +8,47 @@
log on to OpenACS, an account will automatically be created for
them here. Finally, security is increased with fewer passwords, since
users generally can't remember all those passwords, so they tend to
-keep them all the same and never change them. Transparent: Users don't have to do anything special to
+keep them all the same and never change them. Transparent: Users don't have to do anything special to
get an account on the local OpenACS system, if they already have an
- account on the external authentication server. Fall-back: Users who don't have an account on the
+ account on the external authentication server. Fall-back: Users who don't have an account on the
external authentication server are still allowed to create a local
account on OpenACS. This could be for external students who should
have access to .LRN, but not to the rest of the university's
- resources. Authentication Client Only: We want OpenACS to be able to
+ resources. Authentication Client Only: We want OpenACS to be able to
authenticate by asking some remote authority to verify the user's
username/password combination. The goal is explicitly not (at this
point) to have OpenACS act as an authentication server for other
systems, although this could be easily added later. The goal is
also not to devise an infrastructure for letting OpenACS access
resources in various other systems on the user's behalf, such as
IMAP, iCalendar, SMB file servers, etc., although this is
- definitely an interesting use-case. Easy configuration: We would like people to be able to
+ definitely an interesting use-case. Easy configuration: We would like people to be able to
configure this without having to write code. In particular, we want
to build drivers that know how to talk with LDAP, RADIUS, PAM,
etc., and which won't have to be locally modified. Only
configuration and policies should change, code should
- not. Usability: The solution must be easy to use for end users
+ not. Usability: The solution must be easy to use for end users
and administrators alike. There's frequently a positive feedback
effect between usability and security, because when authentication
schemes have poor usability, users will think up ways to circumvent
- them. Open and modular: The design should be on the one hand
+ them. Open and modular: The design should be on the one hand
open to add other authentification mechanisms when needed and on
the other hand very modular to enable a start with minimal
requirements (driver implementations) as soon as
possible. The problem can be split into several logically separate
-parts. Each has a section below. Authority: The name of an authority trusted to authenticate
- users. Authentication Driver: An implementation of the
+parts. Each has a section below. Authority: The name of an authority trusted to authenticate
+ users. Authentication Driver: An implementation of the
authentication service contract, which talks to an authentication
of a certain type, e.g. PAM, RADIUS, LDAP, or Active
- Directory. Authentication API: The API through which login pages and
+ Directory. Authentication API: The API through which login pages and
applications talk to the authentication service. There's one and
only one implementation of the authentication API, namly the one
- included in OpenACS Core. Authentication Driver API: The service contract which
- authentication drivers implement. Authentication:
- Account Management (NO PICTURE YET) Batch Synchronization (NO PICTURE YET) Users will log in using a username, a authority, and a
+ included in OpenACS Core. Authentication Driver API: The service contract which
+ authentication drivers implement. Authentication:
+ Account Management (NO PICTURE YET) Batch Synchronization (NO PICTURE YET) Users will log in using a username, a authority, and a
password. The authority is the source for user/password
verification. OpenACS can be an authority itself. Each user in OpenACS will belong to exactly one authority, which
-can either be the "local" OpenACS users table, in which case the
+can either be the "local" OpenACS users table, in which case the
password column is used, or it can be some external authority,
which will be communicated with using some protocol, as implemented
by an authentication driver. Username will be separate from email address. It can be an
@@ -71,11 +71,11 @@
[Forgot my password]
[New user registration]
If there's only one active authority, we don't display the
-authority drop-down element at all. The site-wide systems administrator can configure the
-authentication process from a page linked under /acs-admin. Authorities - ordered list of authorities defined Account Registration Allowed: Yes/No. Account
- registration can be disabled altogether. Registration authority - the authority in which accounts should
+authority drop-down element at all. The site-wide systems administrator can configure the
+authentication process from a page linked under /acs-admin. Authorities - ordered list of authorities defined Account Registration Allowed: Yes/No. Account
+ registration can be disabled altogether. Registration authority - the authority in which accounts should
be created, using the relevant driver, if account registration is
- allowed. Username is email? - instead of asking for username,
+ allowed. Username is email? - instead of asking for username,
we'll ask for email. And we'll store the value in both columns,
username and email. This is a setting that spans all authorities, and
is primarily meant for backwards compatibility with the old OpenACS
@@ -84,42 +84,42 @@
other drivers call external functions. The possible functions
for each authority are split into several drivers for convenience.
One driver handles authentication, one account creation, and one
- changing passwords. Each authority is defined like this: Authority pretty-name, e.g. "URZ" Authentication Driver, e.g. "RADIUS". In practice, this
+ changing passwords. Each authority is defined like this: Authority pretty-name, e.g. "URZ" Authentication Driver, e.g. "RADIUS". In practice, this
would be a reference to a service contract
- implementation. Authentication Driver configuration settings, e.g. host
+ implementation. Authentication Driver configuration settings, e.g. host
name, port, etc., as required by the particular driver. Note that
this is per authority, not per driver, i.e., you can have multiple
authorities with the same driver but different configuration
- options. AuthenticationAllowed - true/false, so you can disable
+ options. AuthenticationAllowed - true/false, so you can disable
login through some authority without having to delete the authority, and
- hence also all the users who belong to that authority. ForgottenPasswordUrl - a URL to redirect to instead of
+ hence also all the users who belong to that authority. ForgottenPasswordUrl - a URL to redirect to instead of
trying to use the authentication driver's password management
- features. ChangePasswordUrl - a URL to redirect to instead of
+ features. ChangePasswordUrl - a URL to redirect to instead of
trying to use the authentication driver's password management
- features. Account Creation Driver, e.g. "RADIUS". In practice, this
+ features. Account Creation Driver, e.g. "RADIUS". In practice, this
would be a reference to a service contract implementation. The
reason we have separate drivers for authentication and account
creation is that organizations are likely to have a home-grown
- account registration process. Account Creation Driver configuration settings, e.g. host
+ account registration process. Account Creation Driver configuration settings, e.g. host
name, port, etc., as required by the particular driver. Note that
this is per authority, not per driver, i.e., you can have multiple
authorities with the same driver but different configuration
- options. RegistrationUrl - instead of registering using OpenACS,
- redirect to a certain URL site for account registration. RegistrationAllowed - true/false, so you can disable
- registration using this account. Sort order: Preference order of
- authorities. HelpContactText: Text or HTML to be displayed
+ options. RegistrationUrl - instead of registering using OpenACS,
+ redirect to a certain URL site for account registration. RegistrationAllowed - true/false, so you can disable
+ registration using this account. Sort order: Preference order of
+ authorities. HelpContactText: Text or HTML to be displayed
when user has trouble authenticating with the authority.
Should include contact information such as a phone number or email. Each authority driver will have a set of configuration options
dependent on the driver, such as host, port, etc. We will need to
find a mechanism for the driver to tell us which configuration
options are available, a way to set these, and a way for the driver
to access these settings. OpenACS will come pre-configured with one authority, which is
-the "local" authority, meaning we'll authenticate as normal using the
+the "local" authority, meaning we'll authenticate as normal using the
local users table. This will, just like any other authority, be
-implemetned using a service contract. Regardless of the login method, the user needs to have a row
+implemetned using a service contract. Regardless of the login method, the user needs to have a row
in the OpenACS users table. This can happen through a batch job, in
-real-time, or both in combination. We use the IMS Enterprise 1.1 specification. Batch job means that we do a synchronization (import new
+real-time, or both in combination. We use the IMS Enterprise 1.1 specification. Batch job means that we do a synchronization (import new
users, modify changed, purge deleted) on a regular interval, e.g.
every night. You can also decide to have a monthly full
synchronization, plus daily incremental ones. That's up to you. The
@@ -130,23 +130,23 @@
be remedied by using the real-time solution. The batch job will also
require error logging and an admin interface to view logs. If an email already belongs to some
other user, we log it as an error. A user will always belong to exactly one authority, which can be
-either the "local" authority or some other. Thus, the OpenACS user's
-table will have to be augmented with the following columns: Authority. Reference to the site-wide authorities list. The
- authority which can authenticate this user. Authority-specific username. Real-time means that the first time the user logs into
+either the "local" authority or some other. Thus, the OpenACS user's
+table will have to be augmented with the following columns: Authority. Reference to the site-wide authorities list. The
+ authority which can authenticate this user. Authority-specific username. Real-time means that the first time the user logs into
OpenACS, we'll query the authority that authenticated him
for information about this user. That authentication authority will
then give us at least first names, last name and email. The pros
and cons are the opposite of batch jobs. Using both in combination
-is ideal. Note: One solution to the "two users from different authorities
-have the same email" problem above would be to allow users to
+is ideal. Note: One solution to the "two users from different authorities
+have the same email" problem above would be to allow users to
belong to multiple authorities. Then we would notice that the email
already exists, ask the user if he thinks he's the same person, and
if so, ask him to prove so by authenticating using the other
authority. Thus he'll have just authenticated in two different
authorities, and we can record that this is the same person. We'd still
have a problem if there was an email conflict between two accounts
on the same authority. Hm. I don't think it's worth spending too much
-time trying to solve this problem through software. After having authenticated using the relevant authority driver,
+time trying to solve this problem through software. After having authenticated using the relevant authority driver,
we'll look for the username/authority pair in the users table. If we don't find any, that means that we're either not doing
batch synchronizing, or that the user has been added since the last
sync. In that case, we'll try to do a real-time synchronization, if
@@ -155,60 +155,60 @@
create a row in the local users table using that
information. If that doesn't work, we'll tell the user that their account
isn't yet available, and the driver will supply a message for us,
-which could say "The account should be available tomorrow. If not,
-contact X." If a user doesn't have an account, the site-wide
+which could say "The account should be available tomorrow. If not,
+contact X." If a user doesn't have an account, the site-wide
configuration can allow the user to register for one, as defined in
the configuration discussed above. This section is about normal
account registration through a authority driver. The account creation service contract implementation will
-need to tell us which information to ask the user for: Required Fields: A list of fields which are
- required. Optional Fields: A list of fields which are
- optional. The fields to choose from are these: Username First names Last name Email URL Password Secret question Secret answer It should return the following: Creation status (OK, Try-Again, Fail) Creation message: What went wrong, or a welcome
- message. Account status: Is the account ready for use? User information: first_names, last_name, email, url,
+need to tell us which information to ask the user for: Required Fields: A list of fields which are
+ required. Optional Fields: A list of fields which are
+ optional. The fields to choose from are these: Username First names Last name Email URL Password Secret question Secret answer It should return the following: Creation status (OK, Try-Again, Fail) Creation message: What went wrong, or a welcome
+ message. Account status: Is the account ready for use? User information: first_names, last_name, email, url,
password, password_hash, secret_question, secret_answer. The driver
only needs to return the columns which were changed or added
- through the registration process. Typically, only the "local"
+ through the registration process. Typically, only the "local"
driver will return password and secret question/answer. After creating the remote account, a local account is created
with the information gathered through the form/returned by the
driver. By default, a local account creation implementation is
provided, which will create a new OpenACS user, and, in addition to
the default local account creation above, also store the password
-in hashed form. Password management is about changing password, retrieving
password, and resetting password. It's up to the authority driver implementation to decide whether
to support any or all of these features, and to say so using the
CanXXX methods (see driver API below). Additionally, the authority can be configured with a URL to
redirect to in the case of forgotten passwords, or when the user
-desires to change password. Login pages must be able to be sent over a secure connection
+desires to change password. Login pages must be able to be sent over a secure connection
(https), so your password won't get sent over the wire in
cleartext, while leaving the rest of the site non-secure (http). I
believe that this requires some (minor) changes to the current
-session handling code. Email verification needs to be handled both at registration
+session handling code. Email verification needs to be handled both at registration
and at login. In both cases, it'll be handled by the driver sending
automatically sending the email containing a link for the user to
verify his account. Then the driver will return an account status
-of "closed,temporary", and a message that says "Check your inbox
-and click the link in the email". OpenACS will have a page which receives the email
+of "closed,temporary", and a message that says "Check your inbox
+and click the link in the email". OpenACS will have a page which receives the email
verification, for use by local accounts. Other authorities will
have to implement their own page, most likely on the authority's
-own server. There are a number of items which touch on external
authentication and session management. And even though they're not
directly linked to external authentication, I would recommend that
we handle a number of them, either because they're important for
security, or because it makes sense to fix them while we're messing
-with this part of the codebase anyway. I like the idea of having multiple login levels: Not logged in Untrusted login: We'll show you un-sensitive personal
+with this part of the codebase anyway. I like the idea of having multiple login levels: Not logged in Untrusted login: We'll show you un-sensitive personal
content, but won't let you modify anything or see personal data. A
normal login becomes untrusted after a certain amount of time, and
the user will have to re-enter his/her password in order to gain
access to personal data. Untrusted login never expires, unless
explicitly done so through either changing password or clicking a
- special "expire all logins" link. Normal login: The user is logged, and has type his
+ special "expire all logins" link. Normal login: The user is logged, and has type his
password sufficiently recently that we trust the login. All normal
operations are allowed. Will degrade to untrusted login after a
- specified amount of time. Secure login: The user is logged in over a secure
+ specified amount of time. Secure login: The user is logged in over a secure
connection (HTTPS), potentially even using a special secure
password. This would be for sensitive actions, such as credit card
transactions. There are two advantages to this. First, when people's login
@@ -224,19 +224,19 @@
example, we could let you browse publically available forums, and
only when you want to post do you need to log in. This makes it
even more feasible to have a more secure login expiration
-setting. By default, auth::require_login would
+setting. By default, Similarly, ad_conn user_id will continue
+mode. Similarly, This should ensure that we get full access to the new
feature, while leaving all current code just as secure as it was
-before. Currently, OpenACS is unusable in practice without persistent
+before. Currently, OpenACS is unusable in practice without persistent
login. The login will expire after just a few minutes of
inactivity, and you'll get bounced to the login page where you have
to enter both email and password again. Unacceptable in
@@ -247,15 +247,15 @@
login expire after a period of inactivity, but the amount of time
should be configurable and default to something reasonable like an
hour or so. This will require looking into and changing the design of the
-current session handling code. Instead of redirecting to the login page, auth::require_login
+current session handling code. Instead of redirecting to the login page, auth::require_login
can redirect to an authentication server, which can redirect back
to a page that logs the user in. This should be very easy to
implement. Alternatively, if you want to combine this with fallback to
OpenACS accounts, we would instead present the normal login screen,
-but put a button which says "Login using X", where X is the
-redirection-based external authority. Currently, if you've ever left a permanent login cookie on
+but put a button which says "Login using X", where X is the
+redirection-based external authority. Currently, if you've ever left a permanent login cookie on
someone elses machine, that person will be forever logged in until
he/she explicitly logs out. You can change your password, you can
do anything you want, but unless a logout is requested from that
@@ -270,32 +270,32 @@
void. Of course, we don't want to incur a DB hit on every request,
so we'll need to cache the secret token, or only check it when
refreshing the session cookie, which, I believe, normally happens
-every 10 minutes or so. As an additional security measure, we should email the
+every 10 minutes or so. As an additional security measure, we should email the
account's email address whenever the password is changed, so that
-he/she is at least alerted to the fact. Again, to increase security, we should add password policies,
+he/she is at least alerted to the fact. Again, to increase security, we should add password policies,
such as passwords needing to be changed after a certain number of
days, change on next login (after a new random password has been
generated), or requiring that the password satisfies certain
complexity rules, i.e. both upper and lowercase characters,
numbers, special chars, etc. It would good to extend the current maximum password length
-from 10 to at least 32 characters. In order to make it easier for people, we've been toying with
-the idea of a functionality like this: If the user enters "foobar@ix.urz.uni-heidelberg.de", it
- is translated to mean username = "foobar", authority =
- "ix.urz.uni-heidelberg.de". If the user enters "foobar", it's recognized to not
+from 10 to at least 32 characters. In order to make it easier for people, we've been toying with
+the idea of a functionality like this: If the user enters "foobar@ix.urz.uni-heidelberg.de", it
+ is translated to mean username = "foobar", authority =
+ "ix.urz.uni-heidelberg.de". If the user enters "foobar", it's recognized to not
include any authority, and the default authority of
- "ix.urz.uni-heidelberg.de" is used. If the user enters "foo@bar.com", it's recognized as not
+ "ix.urz.uni-heidelberg.de" is used. If the user enters "foo@bar.com", it's recognized as not
belonging to any known authority, and as such, it's translated to mean
- username = "foo@bar.com", authority = "local". If this is deemed desirable, a way to implement this would be
-through these settings: Split: A regexp which will split the user's entry into
- username and authority parts. For example "^([^@]+)(@[^@]+)?$". An
+ username = "foo@bar.com", authority = "local". If this is deemed desirable, a way to implement this would be
+through these settings: Split: A regexp which will split the user's entry into
+ username and authority parts. For example "^([^@]+)(@[^@]+)?$". An
easier to use but less flexible method would be that you simply
- specify a certain character to split by, such as "@" or "\". If the
+ specify a certain character to split by, such as "@" or "\". If the
regexp doesn't match, or in the latter case, if there's more than
one occurrence of the specified character sequence, the split will
- fail, signaling that the user's entry was not valid. Default authority: The default authority will be the first one
+ fail, signaling that the user's entry was not valid. Default authority: The default authority will be the first one
in the sort order. The relevant code in user-login.tcl would look like
this: While we're touching the session handling code, anyway, it
+ While we're touching the session handling code, anyway, it
would be nice to add a feature to show who's currently online, a
nice real-time collaboration feature frequently requested by
members of the community. This is particularly interesting when
@@ -314,18 +314,18 @@
which authenticated users have requested pags on the site in the
last x minutes (typically about 5), and thus are considered to be
currently online. There's nothing more to it. This lets us display
-a list of "active users" somewhere on the site, and make their name
+a list of "active users" somewhere on the site, and make their name
a link to a real-time chat service like Jabber. We've already made the changes necessary to
security-procs.tcl to do this on an earlier project, but haven't
-quite finished the work and put it back into the tree. If we want to, we could let subsite administrators configure
+quite finished the work and put it back into the tree. If we want to, we could let subsite administrators configure
the login process for that particular subsite. This would probably
only entail letting the subsite admin leave out certain authorities
defined site-wide, and change the sort order. I think we should leave this out until we have a use case for
-it, someone who'd need it. For completely free-form authentication logic and mechanisms,
+it, someone who'd need it. For completely free-form authentication logic and mechanisms,
something like Andrew Grumet's
-Pluggable
+Pluggable
Authentication for OACS Draft is interesting. He's
proposing a scheme where the entire user interaction is
encapsulated in, and left entirely to, a service contract. This
@@ -334,10 +334,10 @@
people are going to want to use a username/password-based scheme,
and having easy configuration through a web UI is more important
than total flexibility at this point. Besides, we can always do this in the future, by letting the
-public Authentication API (auth::require_login
-and auth::authenticate) be implemented through a
-service contract. Both OKI and OpenACS supports a form of stacking, where you
+public Authentication API ( Both OKI and OpenACS supports a form of stacking, where you
can be logged into multiple authorities at the same time. This is
useful if, for example, you need to get login tokens such as
Kerberos tickets for access to shared resources. I can see the value in this, but for simplicity's sake, I'm
@@ -350,30 +350,30 @@
for user/group data and access control lists, SMB for file storage,
etc. But at the moment, we don't have any users of such things that
are ready. We have some who are on the steps, but let's wait till
-they're there. We'll need drivers for: Operating system (Linux/Solaris) PAM: Delegate to the
+they're there. We'll need drivers for: Operating system (Linux/Solaris) PAM: Delegate to the
operating system, which can then talk to RADIUS, LDAP, whatever.
This is convenient because there'll be plenty of drivers for the OS
PAM level, so we don't have to write them all ourselves. The
downside is that we can't do things like account creation, password
management, real-time account synchronization, etc., not supported
by PAM (I'm not entirely sure what is and is not
- supported). RADIUS LDAP RADIUS is a simple username/password-type authentication
server. It also supports sending a challenge to which the user must
respond with the proper answer (e.g. mother's maiden name, or could
be additional password), but we will not support this
feature. A RADIUS client
-implementation
+implementation
in Python can be found in the
-exUserFolder
+exUserFolder
module for Zope
-(documentation). We'd really appreciate feedback on this proposal. Please
+(documentation). We'd really appreciate feedback on this proposal. Please
follow up at
-this
-openacs.org forums thread. Threads
-and links collected by Carl Blesius. Draft
-Proposal by Andrew Grumet. Threads
+and links collected by Carl Blesius. Draft
+Proposal by Andrew Grumet. Yale
CAS, a centrl authentication service a' la
- Passport. By You
+
+ By You
NOTE: Some of the sections of this template may not apply to your
package, e.g. there may be no user-visible UI elements for a component
of the OpenACS Core. Furthermore, it may be easier in some circumstances
@@ -11,48 +11,48 @@
your own judgment, consult with peers when possible, and adapt
intelligently.
- Also, bear in mind the audience for detailed design: fellow
+ Also, bear in mind the audience for detailed design: fellow
programmers who want to maintain/extend the software, AND parties
interested in evaluating software quality.
-
When applicable, each of the following items should receive its own link:
- User directory OpenACS administrator directory Subsite administrator directory Tcl script directory (link to the API browser page for the package) PL/SQL file (link to the API browser page for the package) Data model Requirements document ER diagram Transaction flow diagram
+ User directory OpenACS administrator directory Subsite administrator directory Tcl script directory (link to the API browser page for the package) PL/SQL file (link to the API browser page for the package) Data model Requirements document ER diagram Transaction flow diagram
This section should provide an overview of the package
and address at least the following issues:
- What this package is intended to allow the user (or different
- classes of users) to accomplish. Within reasonable bounds, what this package is not intended to allow users to
- accomplish. The application domains where this package is most likely to be of use. A high-level overview of how the package meets its
+ What this package is intended to allow the user (or different
+ classes of users) to accomplish. Within reasonable bounds, what this package is not intended to allow users to
+ accomplish. The application domains where this package is most likely to be of use. A high-level overview of how the package meets its
requirements (which should have been documented elsewhere). This
- is to include relevant material from the "features" section of the
+ is to include relevant material from the "features" section of the
cover sheet (the cover sheet is a wrapper doc with links to all
other package docs).
Also worthy of treatment in this section:
- When applicable, a careful demarcation between the
+ When applicable, a careful demarcation between the
functionality of this package and others which - at least
superficially - appear to address the same requirements.
Note: it's entirely possible that a discussion of what a package
is not intended to do differs from a discussion of future
improvements for the package.
-
For a given set of requirements, typically many possible
implementations and solutions exist. Although eventually only one
solution is implemented, a discussion of the alternative solutions
canvassed - noting why they were rejected - proves helpful to both
current and future developers. All readers would be reminded as to
why and how the particular solution developed over time, avoiding
re-analysis of problems already solved.
-
Although currently only a few package documentation pages contain a
discussion of competing software, (e.g. chat, portals), this section
should be present whenever such competition exists.
- If your package exhibits features missing from competing
- software, this fact should be underscored. If your package lacks features which are present in competing
+ If your package exhibits features missing from competing
+ software, this fact should be underscored. If your package lacks features which are present in competing
software, the reasons for this should be discussed here; our sales
team needs to be ready for inquiries regarding features our software
lacks.
Note that such a discussion may differ from a discussion of a
package's potential future improvements.
-
No single design solution can optimize every desirable software
attribute. For example, an increase in the security of a system will
likely entail a decrease in its ease-of-use, and an increase in the
@@ -62,14 +62,14 @@
should include a discussion of the tradeoffs involved with the design
chosen, and the reasons for your choices. Some areas of importance to
keep in mind are:
- Areas of interest to users: Performance: availability and efficiency Flexibility Interoperability Reliability and robustness Usability Areas of interest to developers: Maintainability Portability Reusability Testability
+ Areas of interest to users: Performance: availability and efficiency Flexibility Interoperability Reliability and robustness Usability Areas of interest to developers: Maintainability Portability Reusability Testability
Here's where you discuss the abstractions used by your package, such
as the procedures encapsulating the legal transactions on the data
model. Explain the organization of procedures and their
particulars (detail above and beyond what is documented in the
code), including:
- Problem-domain components: key algorithms, e.g. a specialized
- statistics package would implement specific mathematical procedures. User-interface components: e.g. HTML widgets that the package may need. Data management components: procedures that provide a stable
+ Problem-domain components: key algorithms, e.g. a specialized
+ statistics package would implement specific mathematical procedures. User-interface components: e.g. HTML widgets that the package may need. Data management components: procedures that provide a stable
interface to database objects and legal transactions - the latter
often correspond to tasks.
Remember that the correctness, completeness, and stability of the API
@@ -80,60 +80,60 @@
handle transactions, instead of encapsulating them via procedures).
Experience has taught us that we need to focus on the API for
maintainability of our systems in the face of constant change.
-
The data model discussion should do more than merely display the SQL
code, since this information is already be available via a link in the
- "essentials" section above. Instead, there should be a high-level
+ "essentials" section above. Instead, there should be a high-level
discussion of how your data model meets your solution requirements:
why the database entities were defined as they are, and what
transactions you expect to occur. (There may be some overlap with the
API section.) Here are some starting points:
- The data model discussion should address the intended usage
+ The data model discussion should address the intended usage
of each entity (table, trigger, view, procedure, etc.) when this
information is not obvious from an inspection of the data model
- itself. If a core service or other subsystem is being used (e.g., the
+ itself. If a core service or other subsystem is being used (e.g., the
new parties and groups, permissions, etc.) this should also be
- mentioned. Any default permissions should be identified herein. Discuss any data model extensions which tie into other
- packages. Transactions Discuss modifications which the database may undergo from
+ mentioned. Any default permissions should be identified herein. Discuss any data model extensions which tie into other
+ packages. Transactions Discuss modifications which the database may undergo from
your package. Consider grouping legal transactions according to
the invoking user class, i.e. transactions by an OpenACS-admin, by
- subsite-admin, by a user, by a developer, etc.
In this section, discuss user interface issues and pages to be built;
you can organize by the expected classes of users. These may include:
- Developers OpenACS administrators (previously known as site-wide administrators) Subsite administrators End users
+ Developers OpenACS administrators (previously known as site-wide administrators) Subsite administrators End users
You may want to include page mockups, site-maps, or other visual aids.
Ideally this section is informed by some prototyping you've done, to
establish the package's usability with the client and other interested
parties.
Note: In order that developer documentation be uniform across
different system documents, these users should herein be designated as
- "the developer," "the OpenACS-admin," "the sub-admin," and "the user,"
+ "the developer," "the OpenACS-admin," "the sub-admin," and "the user,"
respectively.
Finally, note that as our templating system becomes more entrenched
within the OpenACS, this section's details are likely to shift from UI
specifics to template interface specifics.
-
Under OpenACS 5.7.0, parameters are set at two levels: at the global level by
the OpenACS-admin, and at the subsite level by a sub-admin. In this
section, list and discuss both levels of parameters.
-
If the system presently lacks useful/desirable features, note details
here. You could also comment on non-functional improvements to the
package, such as usability.
- Note that a careful treatment of the earlier "competitive analysis"
+ Note that a careful treatment of the earlier "competitive analysis"
section can greatly facilitate the documenting of this section.
-
Although a system's data model file often contains this information,
this isn't always the case. Furthermore, data model files often
undergo substantial revision, making it difficult to track down the
system creator. An additional complication: package documentation may
be authored by people not directly involved in coding. Thus to avoid
unnecessary confusion, include email links to the following roles as
they may apply:
- System creator System owner Documentation author
The revision history table below is for this template - modify it
as needed for your actual design document.
Table of Contents OpenACS has a form manager called ad_form. Ad_form has an
adaptable UI. Error handling includes inline error reporting, and is customizable.
However, ad_form can be tricky to use. In addition to this document,
- the ad_form api
- documentation is helpful. Some elements have more than one choice, or can submit more than one value. Creating the form element. Populate a list of lists with values for the option list. Some elements have more than one choice, or can submit more than one value. Creating the form element. Populate a list of lists with values for the option list. The variable foo_options should resemble {{first foo} 1234} {{second foo} 1235}
- Within ad_form, set up the element to use this list: The variable Within ad_form, set up the element to use this list: This will result in a single name/value pair coming back in the submitted form. Handle this within the same ad_form structure, in the -new_data and -edit_data. In the example, it is available as $foo See also the
- W3C spec for "The SELECT, OPTGROUP, and OPTION elements".
- A situation you may run into often is where you want to pull
+ } This will result in a single name/value pair coming back in the submitted form. Handle this within the same ad_form structure, in the See also the
+ W3C spec for "The SELECT, OPTGROUP, and OPTION elements".
+ A situation you may run into often is where you want to pull
in form items from a sub-category when the first category is
selected. Ad_form makes this fairly easy to do. In the definition
of your form element, include an html section What this will do is set the value for pm_task_id and all the
@@ -39,17 +39,17 @@
-on_refresh section of your ad_form. In that section, you'll get
the values from the database, and set the values as so: A good way to troubleshoot when you're using ad_form is to
add the following code at the top of the .tcl page (thanks Jerry
Asher): Table of Contents Table of Contents By Rafael H. Schloming and Mark Thomas By Rafael H. Schloming and Mark Thomas User directory Sitewide administrator directory Subsite administrator directory TCL script directory Data model PL/SQL file ER diagram Transaction flow diagram User directory Sitewide administrator directory Subsite administrator directory TCL script directory Data model PL/SQL file ER diagram Transaction flow diagram Almost all database-backed websites have users, and need to model the
grouping of users. The OpenACS 4 Parties and Groups system is intended to provide
the flexibility needed to model complex real-world organizational structures,
particularly to support powerful subsite services; that is, where one OpenACS
installation can support what appears to the user as distinct web services
-for different user communities. The primary limitation of the OpenACS 3.x user group system is that it
-restricts the application developer to representing a "flat group"
-that contains only users: The user_groups table may contain the
-group_id of a parent group, but parent-child relationship
+for different user communities. The primary limitation of the OpenACS 3.x user group system is that it
+restricts the application developer to representing a "flat group"
+that contains only users: The In addition, the Module Scoping design in OpenACS 3.0 introduced a
party abstraction - a thing that is a person or a group of people -
though not in the form of an explicit table. Rather, the triple of
-scope, user_id, and group_id columns
+ add these three columns to each "scoped" table define a multi-column check constraint to protect against data corruption
-(e.g., a row with a scope value of "group" but a null
-group_id) perform extra checks in Tcl and PL/SQL
-functions and procedures to check both the user_id and
-group_id values The core of the Group Systems data model is quite simple, but it was
-designed in the hopes of modeling "real world" organizations which
+to: add these three columns to each "scoped" table define a multi-column check constraint to protect against data corruption
+(e.g., a row with a perform extra checks in The core of the Group Systems data model is quite simple, but it was
+designed in the hopes of modeling "real world" organizations which
can be complex graph structures. The Groups System only considers groups that
can be modeled using directed acyclic graphs, but queries over these
structures are still complex enough to slow the system down. Since almost
@@ -38,44 +38,44 @@
without making the system too complex or too slow. The added triggers, views,
and tables and will increase storage requirements and the insert and delete
times in an effort to speed access time. The limited flexibility (no updates
-on membership) trades against the complexity of the code. The Group System data model consists of the following tables: The Group System data model consists of the following tables: The set of all defined parties: any person, user, or
-group must have a corresponding row in this table. The set of all defined persons. To allow easy sorting of persons, the
-name requirement 30.10 is met by
-splitting the person's name into two columns: first_names and
-last_name. The set of all registered users; this table includes information about
-the user's email address and the user's visits to the site. Preferences for the user. Preferences for the user. The set of all defined groups. The set of all defined groups. When a new type of group is created, this table holds additional
-knowledge level attributes for the group and its subtypes. The set of direct membership relationships between a group and a
-party. A mapping of a party P to the groups
-{Gi}the party is a member of; this mapping
-includes the type of relationship by including the appropriaterel_id
-from the membership_rels table. A mapping of a party P to the groups
+{Gi}the party is a member of; this mapping
+includes the type of relationship by including the appropriate The set of direct component relationships between a group and another
-group. A mapping of a group Gto the set of groups
-{Gi} that G is a component of;
+ A mapping of a group Gto the set of groups
+{Gi} that G is a component of;
this mapping includes the type of relationship by including the
-appropriaterel_id from the composition_rels table. New groups are created through the group.new constructor.
+appropriate New groups are created through the The membership_rels and composition_rels tables indicate
+creation time by passing a parent group to the constructor. The The following triggers keep the group_*_index tables up to
-date: The following triggers keep the Is executed when a new group/member relationship is created (an insert on
-membership_rels) Is executed when a group/member relationship is deleted (a delete on
-membership_rels) Is executed when a new group/component relationship is created (an insert
-on composition_rels) Is executed when a group/component relationship is deleted (a delete on
-composition_rels) The data model provides the following views onto the
-group_member_index and group_component_index tables. No
-code outside of Groups System should modify the group_*_index
-tables. The data model provides the following views onto the
+ A mapping of a party to the groups the party is a member of; this mapping
-includes the type of relationship by including the appropriaterel_id
-from the membership_rels table. A mapping of a party to the groups the party is an approved member of
-(member_state is 'approved'); this mapping includes the type
-of relationship by including the appropriaterel_id from the
-membership_rels table. A person may appear in the group member map multiple times, for example,
by being a member of two different groups that are both components of a third
-group. This view is strictly a mapping of approved members
-to groups. A mapping of a group Gto the set of groups
-{Gi} group G is a component of;
+ A mapping of a group Gto the set of groups
+{Gi} group G is a component of;
this mapping includes the type of relationship by including the
-appropriaterel_id from the composition_rels table. A mapping of a party P to the set of parties
-{Pi} party P is a member
-of. A mapping of a party P to the set of parties
+{Pi} party P is a member
+of. A mapping of a party P to the set of parties
-{Pi} party P is an
-approved member of.
The API consists of tables and views and PL/SQL functions.
- The group_types table is used to create new types of groups. The group_member_map, group_approved_member_map,
-group_distinct_member_map, group_component_map,
-party_member_map, and party_approved_member_map views are
-used to query group membership and composition. Person person.new creates a new person and returns the
-person_id. The function must be given the full name of the person in
-two pieces: first_names and last_name. All other fields are
-optional and default to null except for object_type which defaults
-to person and creation_date which defaults to sysdate. The
+ The The Person person.delete deletes the person whose person_id is
+ person.name returns the name of the person whose
-person_id is passed to it. The interface for this function is: User acs_user.new creates a new user and returns the user_id.
+ User acs_user.delete deletes the user whose user_id is passed
+ acs_user.receives_alerts_p returns 't' if the user should
+ Use the procedures acs_user.approve_email and
-acs_user.unapprove_email to specify whether the user's email
+ Use the procedures Group acs_group.new creates a new group and returns the
-group_id. All fields are optional and default to null except for
-object_type which defaults to 'group',
-creation_date which defaults to sysdate, and
-group_name which is required. The interface for
+ Group acs_group.name returns the name of the group whose
-group_id is passed to it. The interface for this function is: acs_group.member_p returns 't' if the specified party is
+ Membership Relationship membership_rel.new creates a new membership relationship type
-between two parties and returns the relationship type's rel_id.
-All fields are optional and default to null except for rel_type
+ Membership Relationship membership_rel.ban sets the member_state of the given
-rel_id to 'banned'. The interface for this procedure is: membership_rel.approve sets the member_state of the
-given rel_id to 'approved'. The interface for this procedure
+ membership_rel.reject sets the member_state of the given
-rel_id to 'rejected. The interface for this procedure is: membership_rel.unapprove sets the member_state of the
-given rel_id to an empty string ''. The interface for this
+ membership_rel.deleted sets the member_state of the
-given rel_id to 'deleted'. The interface for this procedure
+ membership_rel.delete deletes the given rel_id. The
+ Composition Relationship composition_rel.new creates a new composition relationship type
-and returns the relationship's rel_id. All fields are optional
-and default to null except for rel_type which defaults to
+ Composition Relationship composition_rel.delete deletes the given rel_id. The
+ Mark Thomas Mark Thomas By Rafael H. Schloming, Mark Thomas By Rafael H. Schloming, Mark Thomas Almost all database-backed websites have users, and need to model the
grouping of users. The OpenACS 4 Parties and Groups system is intended to provide
the flexibility needed to model complex real-world organizational structures,
particularly to support powerful subsite services; that is, where one OpenACS
installation can support what appears to the user as distinct web services
- for different user communities. A powerful web service that can meet the needs of large enterprises must
+ for different user communities. A powerful web service that can meet the needs of large enterprises must
be able to model the the real world's very rich organizational structures
and many ways of decomposing the same organization. For example, a
corporation can be broken into structures (the corporation, its divisions,
and their departments) or regions (the Boston office, the LA office); a
person who is employed by (is a member of) a specific department is also a
member of the division and the corporation, and works at (is a member of, but
in a different sense) a particular office. OpenACS's Parties and Groups
- system will support such complex relations faithfully. Historical Motivations The primary limitation of the OpenACS 3.x user group system is that it
- restricts the application developer to representing a "flat group"
- that contains only users: The user_groups table may contain the
- group_id of a parent group, but parent-child relationship
+ system will support such complex relations faithfully. Historical Motivations The primary limitation of the OpenACS 3.x user group system is that it
+ restricts the application developer to representing a "flat group"
+ that contains only users: The In addition, the Module Scoping design in OpenACS 3.0 introduced a
party abstraction - a thing that is a person or a group of people -
though not in the form of an explicit table. Rather, the triple of
- scope, user_id, and group_id columns
+ add these three columns to each "scoped" table define a multi-column check constraint to protect against data corruption
- (e.g., a row with a scope value of "group" but a null
- group_id) perform extra checks in Tcl and PL/SQL
- functions and procedures to check both the user_id and
- group_id values In sum, the goal of the Parties and Groups system is to
+ to: add these three columns to each "scoped" table define a multi-column check constraint to protect against data corruption
+ (e.g., a row with a perform extra checks in In sum, the goal of the Parties and Groups system is to
provide OpenACS programmers and site administrators with simple tools that fully
describe the complex relationships that exist among groups in the real
- world. Pat Developer has a client project and wants to model the company, its
offices, its divisions, and its departments as groups and the employees as
- users. We start with Groups, which contain members; the
- member can be either a person or another group (i.e. a
+ users. We start with Groups, which contain members; the
+ member can be either a person or another group (i.e. a
member is a party). In addition to membership, the party and groups system defines a
- composition relationship that may exist between groups: A
- group can be a component of another group. The child group
+ composition relationship that may exist between groups: A
+ group can be a component of another group. The child group
is called a component group; the parent group is called a
- composite group. A group Gc can be a member and/or a component
- of another group Gp; the difference is in the way
- the members of Gc are related to
- Gp: If a party P is a member (or a component) of
- Gc and if Gc is a
- component of Gp, then P is also
- a member (or a component) of Gp If a party P is a member (or a component) of
- Gc and if Gc is a
- member of Gp, then no
- relationship between P and
- Gp exists as a result of the relationship between
- Gp and Gp. Consider an example to make this less abstract: Pretend that the Sierra
+ composite group. A group Gc can be a member and/or a component
+ of another group Gp; the difference is in the way
+ the members of Gc are related to
+ Gp: If a party P is a member (or a component) of
+ Gc and if Gc is a
+ component of Gp, then P is also
+ a member (or a component) of Gp If a party P is a member (or a component) of
+ Gc and if Gc is a
+ member of Gp, then no
+ relationship between P and
+ Gp exists as a result of the relationship between
+ Gp and Gp. Consider an example to make this less abstract: Pretend that the Sierra
Club is a member of Greenpeace. The Sierra Club has chapters; each
chapter is a component of the Sierra Club. If Eddie Environmentalist
is a member of the Massachusetts Chapter of the Sierra Club, Eddie is
@@ -67,158 +67,158 @@
Massachusetts chapter), and between the Sierra Club and Greenpeace. Membership requirements can vary from group to group. The parties and
groups system must provide a base type that specifies the bare minimum
necessary to join a group. The parties and groups system must support constraints between a composite
- group GP and any of its component groups,
- GC. For example, the system should be able to
- enforce a rule like: Do not allow a party P to become a
- member of GC unless P is already
- a member of GP. The data model for the parties and groups system must provide support for
- the following types of entities: The data model for the parties and groups system must provide support for
+ the following types of entities: A party is an entity used to represent either a
- group or a person. The data model should enforce these constraints: 10.10 A party has an email address, which can be
- empty. 10.20 A party may have multiple email addresses
- associated with it. 10.30 The email address of a party must be unique within
- an OpenACS system. A party is an entity used to represent either a
+ group or a person. The data model should enforce these constraints: 10.10 A party has an email address, which can be
+ empty. 10.20 A party may have multiple email addresses
+ associated with it. 10.30 The email address of a party must be unique within
+ an OpenACS system. A group is a collection of zero or more parties. 20.10 The data model should support the subclassing of
- groups via OpenACS Objects. A group is a collection of zero or more parties. 20.10 The data model should support the subclassing of
+ groups via OpenACS Objects. A person represents an actual human being, past or
- present. A person represents an actual human being, past or
+ present. A user is a person who has registered with an OpenACS site. A
- user may have additional attributes, such as a screen name. The data model should enforce these constraints: 40.10 A user must have a non-empty email address. 40.20 Two different users may not have the same email
+ A user is a person who has registered with an OpenACS site. A
+ user may have additional attributes, such as a screen name. The data model should enforce these constraints: 40.10 A user must have a non-empty email address. 40.20 Two different users may not have the same email
address on a single OpenACS installation; i.e., an email address identifies a
- single user on the system. 40.30 A user may have multiple email addresses; for
- example, two or more email addresses may identify a single user. 40.40 A user must have password field which can be
+ single user on the system. 40.30 A user may have multiple email addresses; for
+ example, two or more email addresses may identify a single user. 40.40 A user must have password field which can be
empty. The data model for the parties and groups system must provide support for
- the following types of relationships between entities:
- A party P is considered a member of a
- group G when a direct membership relationship exists between P
- and G or when there exists a direct membership relationship between
- P and some group GC and
- GC has a composition relationship (c.f., 60.0) with G. 50.10 A party may be a member of multiple groups. 50.20 A party may be a member of the same group multiple
+ A party P is considered a member of a
+ group G when a direct membership relationship exists between P
+ and G or when there exists a direct membership relationship between
+ P and some group GC and
+ GC has a composition relationship (c.f., 60.0) with G. 50.10 A party may be a member of multiple groups. 50.20 A party may be a member of the same group multiple
times only when all the memberships have different types; for example, Jane
may be a member of The Company by being both an Employee and an
- Executive. 50.30 A party as a member of itself is not supported. 50.40 The data model must support membership
- constraints. 50.50The data model should support the subclassing of
- membership via OpenACS Relationships. 50.30 A party as a member of itself is not supported. 50.40 The data model must support membership
+ constraints. 50.50The data model should support the subclassing of
+ membership via OpenACS Relationships. A group GC is considered a
- component of a second group
- GP when a direct composition relationship exists between
- GC and GP or when there exists a direct composition relationship between
- GC and some group Gi
- and Gi has a composition relationship with
- GP. 60.10A group may be a component of multiple groups. 60.20A group as a component of itself is not
- supported. 60.30The data model must support component
- constraints. 60.40The data model should support the subclassing of
- composition via OpenACS Relationships. The API should let programmers accomplish the following tasks: A group GC is considered a
+ component of a second group
+ GP when a direct composition relationship exists between
+ GC and GP or when there exists a direct composition relationship between
+ GC and some group Gi
+ and Gi has a composition relationship with
+ GP. 60.10A group may be a component of multiple groups. 60.20A group as a component of itself is not
+ supported. 60.30The data model must support component
+ constraints. 60.40The data model should support the subclassing of
+ composition via OpenACS Relationships. The API should let programmers accomplish the following tasks: The parties and groups system provides a well defined API call that
creates a new group by running the appropriate transactions on the parties
and groups system data model. This API is subject to the constraints laid out
- in the data model. The parties and groups system provides a well defined API call that
creates a new person by running the appropriate transactions on the parties
and groups system data model. This API is subject to the constraints laid out
- in the data model. The parties and groups system provides a well defined API call that
creates a new user by running the appropriate transactions on the parties and
groups system data model. This API is subject to the constraints laid out in
- the data model. The parties and groups system provides a well defined API call that
creates a new user by running the appropriate transactions on an existing
person entity. This API is subject to the constraints laid out in the data
- model. The parties and groups system provides a well defined API call that
demotes an existing user entity to a person entity by running the appropriate
transactions on the existing user. This API is subject to the constraints
- laid out in the data model. The programmer should be able to modify, add, and delete attributes on any
- party. This API is subject to the constraints laid out in the data model. The programmer should be able to view the attributes on any party. This
- API is subject to the constraints laid out in the data model. The system provides an API for deleting a party. This API is subject to
- the constraints laid out in the data model. 100.30 The system may provide a single API call to remove
- the party from all groups and then delete the party. 100.40 In the case of a group, the system may provide a
+ the constraints laid out in the data model. 100.30 The system may provide a single API call to remove
+ the party from all groups and then delete the party. 100.40 In the case of a group, the system may provide a
single API call to remove all parties from a group and then delete the
- group. The parties and groups system provides an API for adding a party as a
member of a group. This API is subject to the constraints laid out in the
- data model. The parties and groups system provides an API for adding a group as a
component of a second group. This API is subject to the constraints laid out
- in the data model. The parties and groups system provides an API for deleting a party's
membership in a group. This API is subject to the constraints laid out in the
- data model. The parties and groups system provides an API for deleting a group's
composition in a second group. This API is subject to the constraints laid
- out in the data model. The parties and groups system provides an API for answering the question:
- "Is party P a member of group
- G?" The parties and groups system provides an API for answering the question:
- "Is group GC a component of group
- GP?" The parties and groups system provides an API for answering the question:
- "Which parties are members of group G?" The parties and groups system provides an API for answering the question:
- "Which groups are components of group G?" The parties and groups system provides an API for answering the question:
- "Of which groups is party P a member?" The parties and groups system provides an API for answering the question:
- "Of which groups is group G a component?" The parties and groups system provides an API for answering the question:
- "Is party P allowed to become a member of group
- G?" The parties and groups system provides an API for answering the question:
- "Is group GC allowed to become a component
- of group GP?" Since many pages at a site may check membership in a group before serving
a page (e.g., as part of a general permissions check), the data model must
support the efficient storage and retrieval of party attributes and
- membership. Since many SQL queries will check membership in a group as part of the
- where clause, whatever mechanism is used to check membership in SQL
- should be fairly small and simple. The user interface is a set of HTML pages that are used to drive the
- underlying API. The user interface may provide the following functions: 200.0 Create a party 210.0 View the attributes of a party 220.0 Update the attributes of a party 240.0 Delete a party 250.0 Add a party to a group 260.0 Remove a party from a group 270.0 Perform the membership and composition checks
- outlined in 130.x to 165.x The user interface is a set of HTML pages that are used to drive the
+ underlying API. The user interface may provide the following functions: 200.0 Create a party 210.0 View the attributes of a party 220.0 Update the attributes of a party 240.0 Delete a party 250.0 Add a party to a group 260.0 Remove a party from a group 270.0 Perform the membership and composition checks
+ outlined in 130.x to 165.x The easiest way is to install the Edit-This-Page package. Log in to the web site as an administrator. Click on Admin > Install Software > Install from OpenACS Repository / Install new application Choose Edit This Page and install Follow the instructions within Edit This Page (the link will only work after Edit This Page is installed). Go to /admin/permissions and grant Create to Registered Users Suppose you install a new site and install Weblogger, and you want all visitors to see weblogger automatically. On the front page, click the Admin button. On the administration page, click Parameters link. Change the parameter IndexRedirectUrl to be the URI of the desired application. For a default weblogger installation, this would be weblogger/. Note the trailing slash. Every page within an OpenACS site is part of a subsite More information). The home page of the entire site is the front page is a special, default instance of a subsite, served from /var/lib/aolserver/$OPENACS_SERVICE_NAME/www. If an index page is not found there, the default index page for all subsites is used. To customize the code on the front page, copy the default index page from the Subsite package to the Main site and edit it: Edit the new index.adp to change the text; you shouldn't need to edit index.tcl unless you are adding new functionality. Almost all pages on an OpenACS site use ACS Templating, and so their appearance is driven by a layer of different files. Let's examine how this works:
+
+ The easiest way is to install the Edit-This-Page package. Log in to the web site as an administrator. Click on Admin > Install Software > Install from OpenACS Repository / Install new application Choose Edit This Page and install Follow the instructions within Edit This Page (the link will only work after Edit This Page is installed). Go to Suppose you install a new site and install Weblogger, and you want all visitors to see weblogger automatically. On the front page, click the On the administration page, click Change the parameter Every page within an OpenACS site is part of a subsite More information). The home page of the entire site is the front page is a special, default instance of a subsite, served from Edit the new Almost all pages on an OpenACS site use ACS Templating, and so their appearance is driven by a layer of different files. Let's examine how this works:
A templated page uses an ADP/TCL pair. The first line in the ADP file is usually:
- If it appears exactly like this, without any arguments, the template processer uses default-master for that subsite. For pages in /var/lib/aolserver/$OPENACS_SERVICE_NAME/www, this is /var/lib/aolserver/$OPENACS_SERVICE_NAME/www/default-master.adp and the associated .tcl file.
- The default-master is itself a normal ADP page. It draws the subsite navigation elements and invokes site-master (/var/lib/aolserver/$OPENACS_SERVICE_NAME/www/site-master.adp and .tcl) The site-master draws site-wide navigation elements and invokes blank-master (/var/lib/aolserver/$OPENACS_SERVICE_NAME/www/blank-master.adp and .tcl). Blank-master does HTML housekeeping and provides a framework for special sitewide navigation "meta" elements such as Translator widgets and Admin widgets. Steps to Reproduce. The events package does not allow users to register for new events. Go to the http://yourserver.net/events as a visitor (ie, log out and, if necessary, clear cookies). This in on a 4.6.3 site with events version 0.1d3. Select an available event A link such as Registration: Deadline is 03/15/2004 10:00am.
-» Login or sign up to register for this event. is visible. Click on "Login or sign up"
- Complete a new registration. Afterwards, you should be redirected back to the same page. Actual Results: The page says "You do not have permission to register for this event." Expected results: A link or form to sign up for the event is shown. Finding the problem. We start with the page that has the error. In the URL it's http://myserver.net/events/event-info.tcl, so open the file /var/lib/aolserver/$OPENACS_SERVICE_NAME/packages/events/www/event-info.tcl. It contains this line: We need to know what that procedure does, so go to /api-doc, paste events::security::can_register_for_event_p into the ACS Tcl API Search box, and click Feeling Lucky. The next pages shows the proc, and we click "show source" to see more information. The body of the proc is simply This means that a given user must have the write privilige on the event in order to register. Let's assume that the priviliges inherit, so that if a user has the write privilige on the whole package, they will have the write privilege on the event. Setting Permissions. A permission has three parts: the privilige, the object of the privilige, and the subject being granted the privilige. In this case the privilige is "write," the object is the Events package, and the subject is all Registered Users. To grant permissions on a package, start at the site map. Find the event package and click "Set permissions". Click "Grant Permission" Grant the write permission to Registered Users. OpenACS 5.0 offers a prettier version at /admin/applications. If it appears exactly like this, without any arguments, the template processer uses The The Steps to Reproduce. The events package does not allow users to register for new events. Go to the http://yourserver.net/events as a visitor (ie, log out and, if necessary, clear cookies). This in on a 4.6.3 site with events version 0.1d3. Select an available event A link such as Complete a new registration. Afterwards, you should be redirected back to the same page. Actual Results: The page says Expected results: A link or form to sign up for the event is shown. Finding the problem. We start with the page that has the error. In the URL it's We need to know what that procedure does, so go to /api-doc, paste events::security::can_register_for_event_p into the ACS Tcl API Search box, and click Feeling Lucky. The next pages shows the proc, and we click "show source" to see more information. The body of the proc is simply This means that a given user must have the write privilige on the event in order to register. Let's assume that the priviliges inherit, so that if a user has the write privilige on the whole package, they will have the write privilege on the event. Setting Permissions. A permission has three parts: the privilige, the object of the privilige, and the subject being granted the privilige. In this case the privilige is "write," the object is the Events package, and the subject is all Registered Users. To grant permissions on a package, start at the site map. Find the event package and click "Set permissions". Click "Grant Permission" Grant the write permission to Registered Users. OpenACS 5.0 offers a prettier version at /admin/applications.
+
+
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
@@ -9,53 +9,53 @@
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
+ Replace all text with temporary message tags. From 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. 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: 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. Replace the temporary message tags in ADP files. From the same 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 ( ... and here is the same file after temporary message tags have been manually added: 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
- Replace the temporary message tags in TCL files. Repeat step 2 for tcl files. Here is the example TCL file after conversion: Note that the message key Replace the temporary message tags in TCL files. Repeat step 2 for tcl files. Here is the example TCL file after conversion: 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 Multilingual APM Parameters
- Internationalize Date and Time queries. Find datetime in .xql files. Use command line tools to find suspect SQL code: 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, becomes 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: 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.
- Use the _pretty version in your ADP page.
-
+ 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 Multilingual APM Parameters
+ Internationalize Date and Time queries. Find datetime in .xql files. Use command line tools to find suspect SQL code: In SQL statements, replace the format string with the ANSI standard format, becomes 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 When a datetime will be written to the database, first convert it from the user's local time to the server's timezone with When a datetime field will be displayed, format it using the localizing function
+ Use the
%c: Long date and time (Mon November 18, 2002 12:00 AM)
-
+
%x: Short date (11/18/02)
-
+
%X: Time (12:00 AM)
-
+
%q: Long date without weekday (November 18, 2002)
-
+
%Q: Long date with weekday (Monday November 18, 2002)
- The "q" format strings are OpenACS additions; the rest follow unix standards (see man
- strftime).
- 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. Checking the Consistency of Catalog Files.
+ The "q" format strings are OpenACS additions; the rest follow unix standards (see Internationalize Numbers.
+ To internationalize numbers, use 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.
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
@@ -64,23 +64,23 @@
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:
-
+
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.
- Replace complicated keys with longer, simpler keys. When writing in one language, it is possible to create clever code to make correct text. In English, for example, you can put an if command at the end of a word which adds "s" if a count is anything but 1. This pluralizes nouns correctly based on the data. However, it is confusing to read and, when internationalized, may result in message keys that are both confusing and impossible to set correctly in some languages. While internationalizing, watch out that the automate converter does not create such keys. Also, refactor compound text as you encounter it. The automated system 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: 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: Replace complicated keys with longer, simpler keys. When writing in one language, it is possible to create clever code to make correct text. In English, for example, you can put an The automated system 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: 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: Complex if statements may produce convoluted message keys that are very hard to localize. Rewrite these if statements. For example: Complex if statements may produce convoluted message keys that are very hard to localize. Rewrite these if statements. For example: ... can be rewritten: ... can be rewritten: Another example, where bugs are concatenated with a number: It would probably be better to do this as something like: Don't combine keys in display text. Converting a phrase from one language to another is usually more complicated than simply replacing each word with an equivalent. When several keys are concatenated, the resulting word order will not be correct for every language. Different languages may use expressions or idioms that don't match the phrase key-for-key. Create complete, distinct keys instead of building text from several keys. For example: Original code: Problematic conversion: Better conversion: ... and include the variable in the key: "New %bug_label%". This gives translators more control over the phrase. In this example of bad i18n, full name is created by concatenating first and last name (admittedly this is pervasive in the toolkit): Avoid unnecessary duplicate keys. When phrases are exactly the same in several places, use a single key. For common words such as
- Yes and No, you can use a library of keys at acs-kernel.
+</if> Don't combine keys in display text. Converting a phrase from one language to another is usually more complicated than simply replacing each word with an equivalent. When several keys are concatenated, the resulting word order will not be correct for every language. Different languages may use expressions or idioms that don't match the phrase key-for-key. Create complete, distinct keys instead of building text from several keys. For example: Original code: Problematic conversion: Better conversion: ... and include the variable in the key: In this example of bad i18n, full name is created by concatenating first and last name (admittedly this is pervasive in the toolkit): Avoid unnecessary duplicate keys. When phrases are exactly the same in several places, use a single key. 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.
+ Additional discussion: Re:
- Bug 961 ("Control Panel" displayed instead of
- "Administer"), Translation
- server upgraded, and Localization questions. Don't internationalize internal code words. Many packages use code words or key words, such as "open" and "closed", which will never be shown to the user. They may match key values in the database, or be used in a switch or if statement. Don't change these. For example, the original code is Additional discussion: Re:
+ Bug 961 ("Control Panel" displayed instead of
+ "Administer"), Translation
+ server upgraded, and Localization questions. Don't internationalize internal code words. Many packages use code words or key words, such as "open" and "closed", which will never be shown to the user. They may match key values in the database, or be used in a switch or if statement. Don't change these. For example, the original code is This is incorrectly internationalized to But resolution is a keyword in a table and in the code, so this breaks the code. It should not have been internationalized at all. Here's another example of text that should not have been internationalized: It is broken if changed to Fix automatic truncated message keys. The automatic converter may create unique but crytic message keys. Watch out for these and replace them with more descriptive keys. For example: But It is broken if changed to Fix automatic truncated message keys. The automatic converter may create unique but crytic message keys. Watch out for these and replace them with more descriptive keys. For example: These would be more useful if they were, "you_can_filter", "you_do_not_have_permission_to_map_this_patch", and "you_do_not_have_permission_to_edit_this_patch". Don't worry about exactly matching the english text, because that might change; instead try to capture the meaning of the phrase. Ask yourself, if I was a translator and didn't know how this application worked, would this key and text make translation easy for me?
- Sometimes the automatic converter creates keys that don't semantically match their text. Fix these: Another example: Bug-tracker component maintainer" was converted to "[_ bug-tracker.Bug-tracker]". Instead, it should be bug_tracker_component_maintainer. Translations in Avoid "clever" message reuse. Translations may need to differ depending on the context in which
+<msg key="You_2">You do not have permission to edit this patch. Only the submitter of the patch
+and users with write permission on the Bug Tracker project (package instance) may do so.</msg> These would be more useful if they were, "you_can_filter", "you_do_not_have_permission_to_map_this_patch", and "you_do_not_have_permission_to_edit_this_patch". Don't worry about exactly matching the english text, because that might change; instead try to capture the meaning of the phrase. Ask yourself, if I was a translator and didn't know how this application worked, would this key and text make translation easy for me?
+ Sometimes the automatic converter creates keys that don't semantically match their text. Fix these: Another example: Translations in Avoid "clever" message reuse. Translations may need to differ depending on the context in which
the message appears.
- Avoid plurals. Different languages create plurals differently. Try to avoid keys which will change based on the value of a number. OpenACS does not currently support internationalization of plurals. If you use two different keys, a plural and a singular form, your application will not localize properly for locales which use different rules or have more than two forms of plurals. Quoting in the message catalog for tcl. Watch out for quoting and escaping when editing text that is also code. For example, the original string breaks if the message text retains all of the escaping that was in the tcl command: When it becomes a key, it should be: Also, some keys had %var;noquote%, which is not needed since those
+ Avoid plurals. Different languages create plurals differently. Try to avoid keys which will change based on the value of a number. OpenACS does not currently support internationalization of plurals. If you use two different keys, a plural and a singular form, your application will not localize properly for locales which use different rules or have more than two forms of plurals. Quoting in the message catalog for tcl. Watch out for quoting and escaping when editing text that is also code. For example, the original string breaks if the message text retains all of the escaping that was in the tcl command: When it becomes a key, it should be: Also, some keys had %var;noquote%, which is not needed since those
variables are not quoted (and in fact the variable won't even be
- recognized so you get the literal %var;noquote% in the output). Be careful with curly brackets. Code within curly brackets isn't evaluated. TCL uses curly brackets as an alternative way to build lists. But TCL also uses curly brackets as an alternative to quotation marks for quoting text. So this original code ... if converted to ... won't work since the _ func will not be called. Instead, it should be Be careful with curly brackets. Code within curly brackets isn't evaluated. TCL uses curly brackets as an alternative way to build lists. But TCL also uses curly brackets as an alternative to quotation marks for quoting text. So this original code ... if converted to ... won't work since the _ func will not be called. Instead, it should be User locale is a property of ad_conn, ad_conn locale. The request processor sets this by calling lang::conn::locale, which looks for the following in order of precedence: Use user preference for this package (stored in ad_locale_user_prefs) Use system preference for the package (stored in apm_packages) Use user's general preference (stored in user_preferences) Use Browser header (Accept-Language HTTP header) Use system locale (an APM parameter for acs_lang) default to en_US For ADP pages, message key lookup occurs in the templating engine. For TCL pages, message key lookup happens with the _ function. In both cases, if the requested locale is not found but a locale which is the default for the language which matches your locale's language is
+
+ User locale is a property of ad_conn, Use user preference for this package (stored in ad_locale_user_prefs) Use system preference for the package (stored in apm_packages) Use user's general preference (stored in user_preferences) Use Browser header ( Use system locale (an APM parameter for acs_lang) default to en_US For ADP pages, message key lookup occurs in the templating engine. For TCL pages, message key lookup happens with the
+
+
This document describes how to develop internationalized OpenACS
packages, including writing new packages with
internationalization and converting old packages. Text that
- users might see is "localizable text"; replacing monolingual text
+ users might see is "localizable text"; replacing monolingual text
and single-locale date/time/money functions with generic
- functions is "internationalization"; translating first
- generation text into a specific language is "localization." At
+ functions is "internationalization"; translating first
+ generation text into a specific language is "localization." At
a minimum, all packages should be internationalized. If you do
not also localize your package for different locales, volunteers
- may use a public "localization server" to submit suggested text.
+ may use a public "localization server" to submit suggested text.
Otherwise, your package will not be usable for all locales.
The main difference between monolingual and internationalized
packages is that all user-visible text in the code of an internationalized
- package are coded as "message keys." The message keys
+ package are coded as "message keys." The message keys
correspond to a message catalog, which contains versions of the
text for each available language. Script files (.adp and .tcl and .vuh), database files (.sql), and APM parameters are affected.
@@ -33,33 +33,33 @@
which are static and mostly text, it may be easier to create a
new ADP page for each language. In this case, the pages are
distinguished by a file naming convention.
- 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. 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.
+ 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. If the request processor finds a file named
Internationalizing templates is about replacing human readable
text in a certain language with internal message keys, which
can then be dynamically replaced with real human language in
the desired locale. Message keys themselves should be in
ASCII English, as should all code. Three different syntaxes
are possible for message keys.
- "Short" syntax is the recommended syntax and should be used
+ "Short" syntax is the recommended syntax and should be used
for new development. When internationalizing an existing
- package, you can use the "temporary" syntax, which the APM can
+ package, you can use the "temporary" syntax, which the APM can
use to auto-generate missing keys and automatically translate
- to the short syntax. The "verbose" syntax is useful while
+ to the short syntax. The "verbose" syntax is useful while
developing, because it allows default text so that the page is
usable before you have done
- localization.
- The short:
- #package_key.message_key#
+ localization.
+ The short:
+
The advantage of the short syntax is that it's short. It's
as simple as inserting the value of a variable. Example:
#forum.title#
-
- The verbose: <trn
- key="package_key.message_key"
- locale="locale">default
- text</trn>
+
+ The verbose:
The verbose syntax allows you to specify a default text in
a certain language. This syntax is not recommended
@@ -68,11 +68,11 @@
in the message catalog yet, because what it'll do is
create the message key with the default text from the tag
as the localized message. Example: <trn
- key="forum.title" locale="en_US">Title</trn>
-
- The temporary:
- <#message_key
- original text#>
+ key="forum.title" locale="en_US">Title</trn>
+
+ The temporary:
+
This syntax has been designed to make it easy to
internationalize existing pages. This is not a syntax that
@@ -83,21 +83,21 @@
auto-generated by the APM. Example: <_ Title>
We recommend the short notation for new package development.
-
In adp files message lookups are typically done with the syntax
- \#package_key.message_key\#. In Tcl
+
- 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.
- 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 {
+ Typical static key lookup:
+ Static key lookup with non-default locale:
+ Dynamic key lookup:
Translatable texts in page TCL scripts are often found in page titles,
@@ -106,16 +106,16 @@
that can be used on Linux to highlight translatable text in TCL files:
You may mark up translatable text in TCL library files and TCL pages
@@ -124,82 +124,82 @@
variables and or procedure calls in it you should in most cases
try to turn the whole text into one
message in the catalog (remember that translators is made easier the longer the phrases to translate are). In those cases, follow these steps:
-
+
For each message call in the text, decide on a variable name and replace
the procedure call with a variable lookup on the syntax %var_name%. Remember
- to initialize a tcl variable with the same name on some line above the text. If the text is in a tcl file you must replace variable lookups
- (occurences of $var_name or ${var_name}) with %var_name% You are now ready to follow the normal procedure and mark up the text using a
+ to initialize a tcl variable with the same name on some line above the text. If the text is in a tcl file you must replace variable lookups
+ (occurences of $var_name or ${var_name}) with %var_name% You are now ready to follow the normal procedure and mark up the text using a
tempoarary message tag (<#_ text_with_percentage_vars#>) and run the action
replace tags with keys in the APM.
The variable values in the message are usually fetched with upvar, here is an example from dotlrn:
-
- ad_return_complaint 1 "Error: A [parameter::get -parameter classes_pretty_name]
- must have <em>no</em>[parameter::get -parameter class_instances_pretty_plural] to be deleted"
-
+
This kind of interpolation also works in adp files where adp variable values will be inserted into the message.
Alternatively, you may pass in an array list of the variable values to be interpolated into the message so that
our example becomes:
When we were done going through the tcl files we ran the following
commands to check for mistakes:
When you feel ready you may vist your package in the
- package manager
- and run the action "Replace tags with keys
- and insert into catalog" on the TCL files that you've edited to
+ package manager
+ and run the action "Replace tags with keys
+ and insert into catalog" on the TCL files that you've edited to
replace the temporary tags with calls to the message lookup
procedure.
-
+
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
+
Some parameters contain text that need to be localized. In
this case, instead of storing the real text in the parameter,
you should use message keys using the short notation above,
- i.e. #package_key.message_key#.
+ i.e. #package_key.message_key#.
In order to avoid clashes with other uses of the hash
character, you need to tell the APM that the parameter value
needs to be localized when retrieving it. You do that by saying:
- parameter::get -localize.
+ parameter::get -localize.
Here are a couple of examples. Say we have the following two
parameters, taken directly from the dotlrn package.
-
+
Then, depending on how we retrieve the value, here's what we get:
-
+
The value in the rightmost column in the table above is the
value returned by an invocation of parameter::get. Note that
for localization to happen you must use the -localize flag.
@@ -209,5 +209,5 @@
locale.
Developers are responsible for creating the keys in the message
- catalog, which is available at /acs-lang/admin/
+ catalog, which is available at Table 12.1. Internationalization and Localization Overview Table 14.1. Internationalization and Localization Overview by Henry Minsky,
- Yon Feldman,
- Lars Pind,
- Peter Marklund,
- Christian Hvid,
+
+ by Henry Minsky,
+ Yon Feldman,
+ Lars Pind,
+ Peter Marklund,
+ Christian Hvid,
and others.
This document describes the requirements for functionality in
the OpenACS platform to support globalization of the core and optional
modules. The goal is to make it possible to support delivery of
applications which work properly in multiple locales with the
lowest development and maintenance cost.
-
+
The provision within a computer program of the
capability of making itself adaptable to the requirements of different
native languages, local customs and coded character sets.
@@ -28,8 +28,8 @@
A product development approach which ensures that software products
are usable in the worldwide markets through a combination of
internationalization and localization.
- The Mozilla project suggests keeping two catchy phrases in
+mind when thinking about globalization: One code base for the world English is just another language Building an application often involves making a number of
assumptions on the part of the developers which depend on their own
culture. These include constant strings in the user interface and
system error messages, names of countries, cities, order of given
@@ -44,21 +44,21 @@
kind of globalization support would be large and ongoing, since
without a mechanism to incorporate the locale-specific changes
cleanly back into the code base, it would require making a new fork
-of the source code for each locale. A globalized application will perform some or all of the
+of the source code for each locale. A globalized application will perform some or all of the
following steps to handle a page request for a specific
-locale: Decide what the target locale is for an incoming page
-request Decide which character set encoding the output should be
-delivered in If a script file to handle the request needs to be loaded
+locale: Decide what the target locale is for an incoming page
+request Decide which character set encoding the output should be
+delivered in If a script file to handle the request needs to be loaded
from disk, determine if a character set conversion needs to be
-performed when loading the script If needed, locale-specific resources are fetched. These can
+performed when loading the script If needed, locale-specific resources are fetched. These can
include text, graphics, or other resources that would vary with the
-target locale. If content data is fetched from the database, check for
-locale-specific versions of the data (e.g. country names). Source code should use a message catalog API to translate
-constant strings in the code to the target locale Perform locale-specific linguistic sorting on data if
-needed If the user submitted form input data, decide what character
+target locale. If content data is fetched from the database, check for
+locale-specific versions of the data (e.g. country names). Source code should use a message catalog API to translate
+constant strings in the code to the target locale Perform locale-specific linguistic sorting on data if
+needed If the user submitted form input data, decide what character
set encoding conversion if any is needed. Parse locale-specific
-quantities if needed (number formats, date formats). If templating is being used, select correct locale-specific
-template to merge with content Format output data quantities in locale-specific manner
+quantities if needed (number formats, date formats). If templating is being used, select correct locale-specific
+template to merge with content Format output data quantities in locale-specific manner
(date, time, numeric, currency). If templating is being used, this
may be done either before and/or after merging the data with a
template. Since the internationalization APIs may potentially be used
@@ -69,68 +69,68 @@
Java which we will want to move to. So the design to meet the
requirements will tend to rely on these capabilities, or close
approximations to them where possible, in order to make it easier
-to maintain Tcl and Java OpenACS versions. Here are the cases that we need to be able to handle
-efficiently: A developer needs to author a web site/application in a
+to maintain Tcl and Java OpenACS versions. Here are the cases that we need to be able to handle
+efficiently: A developer needs to author a web site/application in a
language besides English, and possibly a character set besides
ISO-8859-1. This includes the operation of the OpenACS itself, i.e.,
navigation, admin pages for modules, error messages, as well as
additional modules or content supplied by the web site
developer. What do they need to modify to make this work? Can their
localization work be easily folded in to future releases of
-OpenACS? A developer needs to author a web site which operates in
+OpenACS? A developer needs to author a web site which operates in
multiple languages simultaneously. For example, www.un.org with
content and navigation in multiple languages. The site would have an end-user visible UI to support these
languages, and the content management system must allow articles to
be posted in these languages. In some cases it may be necessary to
make the modules' admin UI's operate in more than one
supported language, while in other cases the backend admin
-interface can operate in a single language. A developer is writing a new module, and wants to make it
+interface can operate in a single language. A developer is writing a new module, and wants to make it
easy for someone to localize it. There should be a clear path to
author the module so that future developers can easily add support
for other locales. This would include support for creating
resources such as message catalogs, non-text assets such as
graphics, and use of templates which help to separate application
-logic from presentation. Other application servers: ATG Dyanmo, Broadvision, Vignette,
-... ? Anyone know how they deal with i18n ? System/Package "coversheet" - where all
-documentation for this software is linked off of User's guide Other-cool-system-related-to-this-one
-document Other application servers: ATG Dyanmo, Broadvision, Vignette,
+... ? Anyone know how they deal with i18n ? System/Package "coversheet" - where all
+documentation for this software is linked off of User's guide Other-cool-system-related-to-this-one
+document LI18NUX
2000 Globalization Specification:
-http://www.li18nux.net/ Mozilla
+http://www.li18nux.net/ Mozilla
i18N Guidelines:
-http://www.mozilla.org/docs/refList/i18n/l12yGuidelines.html ISO
+http://www.mozilla.org/docs/refList/i18n/l12yGuidelines.html ISO 3166-1:1997
+http://sunsite.berkeley.edu/amher/iso_639.html Test plan Competitive system(s) Because the requirements for globalization affect many areas
+http://www.niso.org/3166.html IANA
+Registry of Character Sets Test plan Competitive system(s) Because the requirements for globalization affect many areas
of the system, we will break up the requirements into phases, with
a base required set of features, and then stages of increasing
-functionality. 10.0 A standard representation of locale will be used throughout
the system. A locale refers to a language and territory, and is
uniquely identified by a combination of ISO language and ISO
country abbreviations. See
-Content
+Content
Repository Requirement 100.20 10.10 Provide a consistent
representation and API for creating and referencing a locale 10.20 There will be a Tcl library of
locale-aware formatting and parsing functions for numbers, dates
and times. Note that Java has builtin support for these
already. 10.30 For each locale there will be
-default date, number and currency formats. Currency i18n is
-NOT IMPLEMENTED for 5.0.0. 10.40Administrators can upgrade their
-servers to use new locales via the APM. NOT IMPLEMENTED in
+default date, number and currency formats. Currency i18n is
+NOT IMPLEMENTED for 5.0.0. 10.40Administrators can upgrade their
+servers to use new locales via the APM. NOT IMPLEMENTED in
5.0.0; current workaround is to get an xml file and load it
-manually. 20.0 The request processor must have a mechanism for associating a
locale with each request. This locale is then used to select the
appropriate template for a request, and will also be passed as the
locale argument to the message catalog or locale-specific
formatting functions. 20.10 The locale for a request should be
computed by the following method, in descending order of
-priority: get locale associated with subsite or package id get locale from user preference get locale from site wide default 20.20 An API will be provided for
+priority: get locale associated with subsite or package id get locale from user preference get locale from site wide default 20.20 An API will be provided for
getting the current request locale from the
-ad_conn structure. 30.0 A mechanism must be provided for a developer to group a set
of arbitrary content resources together, keyed by a unique
identifier and a locale. For example, what approaches could be used to implement a
localizable nav-bar mechanism for a site? A navigation bar might be
@@ -142,7 +142,7 @@
functionality might include using templates, Java ResourceBundles,
content-item containers in the Content Repository, or some
convention assigning a common prefix to key strings in the message
-catalog. 40.0 A message catalog facility will provide a database of
+catalog. 40.0 A message catalog facility will provide a database of
translations for constant strings for multilingual applications. It
must support the following: 40.10 Each message will referenced via
unique a key. 40.20 The key for a message will have
@@ -167,7 +167,7 @@
is modified, the other translations of that string can be flagged
as needing update. 40.90 The message lookup must be as
efficient as possible so as not to slow down the delivery of
-pages. Character Sets 50.0 A locale will have a primary
associated character set which is used to encode text in the
language. When given a locale, we can query the system for the
associated character set to use. The assumption is that we are going to use Unicode in our
@@ -177,12 +177,12 @@
browsers and authoring tools, the system must be able to read and
write other character sets. In particular, conversions to and from
Unicode will need to be explicitly performed at the following
-times: Loading source files (.tcl or .adp) or content files from the
-filesystem Accepting form input data from users Delivering text output to a browser Composing an email message Writing data to the filesystem Acs-templating does the following. When the acs-templating package opens an an ADP or TCL file, it assumes the file is iso-8859-1. If the output charset (OutputCharset) in the AOLserver config file is set, then acs-templating assumes it's that charset.
-Writing Files When the acs-templating package writes an an ADP or
+times: Loading source files (.tcl or .adp) or content files from the
+filesystem Accepting form input data from users Delivering text output to a browser Composing an email message Writing data to the filesystem Acs-templating does the following. When the acs-templating package opens an an ADP or TCL file, it assumes the file is iso-8859-1. If the output charset (OutputCharset) in the AOLserver config file is set, then acs-templating assumes it's that charset.
+Writing Files When the acs-templating package writes an an ADP or
TCL file, it assumes the file is iso-8859-1. If the output
charset (OutputCharset) in the AOLserver config file is set,
- then acs-templating assumes it's that charset. There are two classes of Tcl files loaded by the system;
+ then acs-templating assumes it's that charset. There are two classes of Tcl files loaded by the system;
library files loaded at server startup, and page script files,
which are run on each page request. Should we require all Tcl files be stored as UTF8?
That seems too much of a burden on developers. 50.10 Tcl library files can be authored
@@ -191,31 +191,31 @@
filename. 50.20 Tcl page script files can be
authored in any character set. The system must have a way to
determine the character set before loading the files, probably from
- the filename. 50.30 Data which is submitted with a
HTTP request using a GET or POST method may be in any character
set. The system must be able to determine the encoding of the form
data and convert it to Unicode on demand. 50.35 The developer must be able to
override the default system choice of character set when parsing
- and validating user form data. INCOMPLETE - form
+ and validating user form data. INCOMPLETE - form
widgets in acs-templating/tcl/date-procs.tcl are not
internationalized. Also, acs-templating's UI needs to be
internationalized by replacing all user-visible strings with
- message keys. 50.30.10In Japan and some
+ message keys. 50.30.10In Japan and some
other Asian languages where there are multiple character set
encodings in common use, the server may need to attempt to do an
auto-detection of the character set, because buggy browsers may
- submit form data in an unexpected alternate encoding. 50.40 The output character set for a
+ submit form data in an unexpected alternate encoding. 50.40 The output character set for a
page request will be determined by default by the locale associated
with the request (see requirement 20.0). 50.50 It must be possible for a
developer to manually override the output character set encoding
for a request using an API function.
- 60.10 All OpenACS error messages must use
the message catalog and the request locale to generate error
-message for the appropriate locale.NOT IMPLEMENTED for 5.0.0. 60.20 Web server error messages such as
+message for the appropriate locale.NOT IMPLEMENTED for 5.0.0. 60.20 Web server error messages such as
404, 500, etc must also be delivered in the appropriate
locale. 60.30 Where files are written or read
from disk, their filenames must use a character set and character
-values which are safe for the underlying operating system. 70.0 For a given abstract URL, the
+values which are safe for the underlying operating system. 70.0 For a given abstract URL, the
designer may create multiple locale-specific template files may be
created (one per locale or language) 70.10 For a given page request, the
system must be able to select an approprate locale-specific
@@ -226,28 +226,28 @@
current request locale. 70.30 A template file may be created in
any character set. The system must have a way to know which
character set a template file contains, so it can properly process
-it. 70.50 The properties of a datasource
column may include a datatype so that the templating system can
format the output for the current locale. The datatype is defined
by a standard OpenACS datatype plus a format token or format string,
for example: a date column might be specified as
'current_date:date LONG,' or 'current_date:date
-"YYYY-Mon-DD"' 70.60 The forms API must support
+"YYYY-Mon-DD"' 70.60 The forms API must support
construction of locale-specific HTML form widgets, such as date
entry widgets, and form validation of user input data for
locale-specific data, such as dates or numbers. NOT
IMPLEMENTED in 5.0.0. 70.70 For forms which allow users to
upload files, a standard method for a user to indicate the charset
of a text file being uploaded must be provided. Design note: this presumably applies to uploading
-data to the content repository as well 80.10 Support API for correct collation
(sorting order) on lists of strings in locale-dependent way. 80.20 For the Tcl API, we will say that
locale-dependent sorting will use Oracle SQL operations (i.e., we
won't provide a Tcl API for this). We require a Tcl API
function to return the correct incantation of NLS_SORT to use for a
-given locale with ORDER BY clauses in
+given locale with 80.40 The system must handle full-text
-search in any supported language. 90.10 Provide API support for specifying
a time zone 90.20 Provide an API for computing time
and date operations which are aware of timezones. So for example a
calendar module can properly synchronize items inserted into a
@@ -258,29 +258,29 @@
zone preference should be attached via a session or else UTC should
be used to display every date and time. 90.60 The default if we can't
determine a time zone is to display all dates and times in some
-universal time zone such as GMT. 100.10 Since UTF8 strings can use up to
three (UCS2) or six (UCS4) bytes per character, make sure that
column size declarations in the schema are large enough to
accomodate required data (such as email addresses in
-Japanese). Since 5.0.0, this is covered in the database
-install instructions for both PostgreSQL and Oracle. When sending an email message, just as when delivering the
content in web page over an HTTP connection, it is necessary to be
able to specify what character set encoding to use, defaulting to UTF-8. 110.10 The email message sending API
will allow for a character set encoding to be specified. 110.20 The email accepting API
allows for character set to be parsed correctly (the message has a MIME
- character set content type header) Mail is not internationalized. The following issues must be addressed.
+ character set content type header) Mail is not internationalized. The following issues must be addressed.
Many functions still call ns_sendmail. This
means that there are different end points for sending
mail. This should be changed to use the acs-mail-lite API instead.
-
+
Consumers of email services must do
the following: Determine the appropriate language or
languages to use for the message subject and message body
and localize them (as in notifications).
- Extreme Use case: Web site has a default language of Danish. A forum is set up for Swedes, so the forum has a package_id and a language setting of Swedish. A poster posts to the forum in Russian (is this possible?). A user is subscribed to the forum and has a language preference of Chinese. What should be in the message body and message subject? Incoming mail should be localized.
+ Extreme Use case: Web site has a default language of Danish. A forum is set up for Swedes, so the forum has a package_id and a language setting of Swedish. A poster posts to the forum in Russian (is this possible?). A user is subscribed to the forum and has a language preference of Chinese. What should be in the message body and message subject? Incoming mail should be localized.
Because globalization touches many different parts of the system,
we want to reduce the implementation risk by breaking the
implementation into phases.
- -d:pserver:anonymous@cvs.openacs.org:/cvsroot
immediately after cvs
in a cvs command to check out or export code.
-d:ext:cvs.openacs.org:/cvsroot
+ immediately after cvs
in
checkout commands. This will create a local checkout directory
that uses cvs.openacs.org but does not specify the user. By
default, it will use your local account name as the user, so if
- you are logged in as "foobar" it will try to check out and
+ you are logged in as "foobar" it will try to check out and
commit as if you had specified
- :ext:foobar@cvs.openacs.org:/cvsroot. The advantage of not specifying a user in the checkout command is that other users can work in the directory using their own accounts.
+ :ext:foobar@cvs.openacs.org:/cvsroot
. The advantage of not specifying a user in the checkout command is that other users can work in the directory using their own accounts.
CVS_RSH=ssh
in your
environment. (Typically this is accomplished by putting
- export CVS_RSH=ssh into
- ~/.bash_profile.). If your local
+ export CVS_RSH=ssh
into
+ ~/.bash_profile
.). If your local
account name does not match your cvs.openacs.org account name, create a
- file ~/.ssh/config with an entry
+ file ~/.ssh/config
with an entry
like:
Host cvs.openacs.org
User joel
~/.cvsrc
with the contents:
cvs -z6
-cvs -q
sudo bash
-/usr/sbin/useradd -c "Real Name" -G cvs -p passwd username
+cvs -q
-z6
speeds up cvs access over the network quite a bit by enabling compressed
+ connection by default. -q
suppresses some verbose output from commands. For example, it makes the output of cvs up
much easier to read.sudo bash
+/usr/sbin/useradd -c "Real Name" -G cvs -p passwd username
/usr/sbin/usermod -G cvs,username username
-
cvs -d :ext:cvs.openacs.org:/cvsroot co CVSROOT
+
cvs -d :ext:cvs.openacs.org:/cvsroot co CVSROOT
cd CVSROOT
-emacs avail
avail|username|openacs-4
cvs commit -m "added commit on X for username" avail
Host cvs-server
+emacs avail
avail|username|openacs-4
cvs commit -m "added commit on X for username" avail
Host cvs-server
HostName cvs.openacs.org
- User yournamehere
~/.ssh/config
file, then you can use -d :ext:cvs-server:/cvsroot
instead of -d :ext:cvs.openacs.org:/cvsroot
. You can then change the definition of cvs-server
by changing one file instead of editing hundreds of CVSROOT/Repository
files.cvs -d:ext:cvs.openacs.org:/cvsroot -r oacs-5-7 checkout acs-core
cd /var/lib/aolserver/service0/packages
cvs up -d packagename
cvs -d:ext:cvs.openacs.org:/cvsroot checkout acs-core
cvs -d:pserver:anonymous@cvs.openacs.org:/cvsroot checkout acs-core
-r
tag.cvs -d:ext:cvs.openacs.org:/cvsroot checkout acs-core
cvs -d:pserver:anonymous@cvs.openacs.org:/cvsroot checkout acs-core
dotlrn
:
cvs -d :pserver:anonymous@cvs.openacs.org:/cvsroot checkout -r oacs-5-7 acs-core
mv openacs-4 dotlrn
cd dotlrn/packages
cvs -d :pserver:anonymous@cvs.openacs.org:/cvsroot checkout -r oacs-5-7 dotlrn-all
-mv dotlrn/install.xml ..
cvs -n update
does not change any files, but reports which changes have been updated or locally modified, or are not present in CVS.
+ cvs update
. This will merge changes from the repository with your local files. It has no effect on the cvs.openacs.org repository.openacs-4
. (The openacs-4 directory contains code for all versions of OpenACS 4 and later, and .LRN 1 and later.) Checking out this module retrieves all openacs code of any type. For convenience, subsets of openacs-4
are repackaged as smaller modules.acs-core
contains only critical common
packages. It does not have any user applications, such as forums,
bug-tracker, calendar, or ecommerce. These can be added at
any time.
@@ -112,29 +110,29 @@
acs-tcl
acs-templating
ref-timezones searchdotlrn-all
contains the packages required, in combination with acs-core, to run the .LRN system.
project-manager-all
contains the packages required, in combination with acs-core, to run the project-manager package.
openacs-x-y-z-final
+ tags mark final releases of OpenACS. This tag is applied to the acs-core files for an OpenACS core release, and to the latest released versions of all other packages at the time of release. Example: openacs-5-0-4-final
.
+ dotlrn-x-y-z-final
+ tags mark final releases of .LRN. These tags apply only to .LRN packages. Example: dotlrn-2-0-1-final
+ packagename-x-y-z-final
+ tags apply to releases of individual packages. For example, calendar-2-0-0-final
is a tag that will retrieve only the files in the calendar 2.0.0 release. It applies only to the
calendar package. All non-core, non-dotlrn packages should have a
tag of this style, based on the package name. Many packages have
not been re-released since the new naming convention was adopted
and so don't have a tag of this type.
- openacs-x-y-compat
tags point to the most recent released version of OpenACS X.Y.
It is similar to openacs-x-y-z-compat, except that it will
always get the most recent dot-release of Core and the
most recent compatible, released version of all other
@@ -148,51 +146,51 @@
package, etc. If you update the checkout two months later, you
might get version 5.0.5 of all OpenACS core packages and version
2.1 of calendar.
- cvs commit -m "what I did and why" filename
HEAD
is a branch used
+ for development of core packages.cvs commit -m "what I did and why" filename
cd /tmp
cvs -d:ext:cvs.openacs.org:/cvsroot checkout acs-core
cp -r /var/lib/aolserver/service0/packages/newpackage /tmp/openacs-4/packages
cd /tmp/openacs-4/packages/newpackage
-cvs import -m "Initial import of newpackage" openacs-4/packages/newpackage myname newpackage-0-1d
cvs -d :ext:cvs.openacs.org:/cvsroot co CVSROOT
+cvs import -m "Initial import of newpackage" openacs-4/packages/newpackage myname newpackage-0-1d
cvs -d :ext:cvs.openacs.org:/cvsroot co CVSROOT
cd CVSROOT
-emacs modules
photo-album-portlet openacs-4/packages/photo-album-portlet
cvs commit -m "added alias for package newpackage" modules
+emacs modulesphoto-album-portlet openacs-4/packages/photo-album-portlet
cvs commit -m "added alias for package newpackage" modules
**** Access allowed: Personal Karma exceeds Environmental Karma.
Checking in modules;
/cvsroot/CVSROOT/modules,v <-- modules
new revision: 1.94; previous revision: 1.93
done
-cvs commit: Rebuilding administrative file databasecd /var/lib/aolserver/service0/packages/newpackage
-cvs tag -b oacs-5-1
Note
cp -r /cvsroot/openacs-4/contrib/packages/package0 /cvsroot/openacs-4/packages
cd /var/lib/aolserver/service0/packages/newpackage
+cvs tag -b oacs-5-1
Note
openacs-4/contrib/packages
. Starting with OpenACS 5.1, we have a Maturity mechanism in the APM which makes the contrib
directory un-necessary. If you are working on a contrib
package, you should move it to /packages
. This must be done by an OpenACS administrator. On cvs.openacs.org:cp -r /cvsroot/openacs-4/contrib/packages/package0 /cvsroot/openacs-4/packages
cvs rm
. One approach for file in `find | grep -v CVS`; do rm $file; cvs remove $file; done
/packages
-
+
directory
and the maturity flag in the .info file should be zero. This is a change from
previous policy, where new packages went to /contrib/packages)
- [root root]# mkdir /cvsroot/$OPENACS_SERVICE_NAME
-[root root]# chown $OPENACS_SERVICE_NAME.$OPENACS_SERVICE_NAME /cvsroot/$OPENACS_SERVICE_NAME
+
[root root]#
mkdir /cvsroot/$OPENACS_SERVICE_NAME
+[root root]# chown $OPENACS_SERVICE_NAME.$OPENACS_SERVICE_NAME /cvsroot/$OPENACS_SERVICE_NAME
[root root]#
mkdir /cvsroot/$OPENACS_SERVICE_NAME
-chown $OPENACS_SERVICE_NAME.$OPENACS_SERVICE_NAME /cvsroot/$OPENACS_SERVICE_NAME[root root]# su - $OPENACS_SERVICE_NAME
-[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ emacs .bashrc
export CVSROOT=/cvsroot
[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ exit
+chown $OPENACS_SERVICE_NAME.$OPENACS_SERVICE_NAME /cvsroot/$OPENACS_SERVICE_NAME
[root root]#
su - $OPENACS_SERVICE_NAME
+[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ emacs .bashrc
/home/$OPENACS_SERVICE_NAME/.bashrc
:export CVSROOT=/cvsroot
[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$
exit
logout
-[root root]#$OPENACS_SERVICE_NAME
refers to the cvs repository to use; it uses the CVSROOT
plus this string,
i.e.
- /cvsroot/$OPENACS_SERVICE_NAME.
- "OpenACS" is the vendor tag, and "oacs-5-7-0-final" is the
+ /cvsroot/$OPENACS_SERVICE_NAME
.
+ "OpenACS" is the vendor tag, and "oacs-5-7-0-final" is the
release tag. These tags will be useful in upgrading and
- branching. -m sets the version comment.[root root]# su - $OPENACS_SERVICE_NAME
-[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ cd /var/lib/aolserver/$OPENACS_SERVICE_NAME
-[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ cvs import -m "initial install" $OPENACS_SERVICE_NAME OpenACS oacs-5-7-0-final
+ branching. -m sets the version comment.
[root root]#
su - $OPENACS_SERVICE_NAME
+[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ cd /var/lib/aolserver/$OPENACS_SERVICE_NAME
+[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ cvs import -m "initial install" $OPENACS_SERVICE_NAME OpenACS oacs-5-7-0-final
N $OPENACS_SERVICE_NAME/license.txt
N $OPENACS_SERVICE_NAME/readme.txt
(many lines omitted)
@@ -37,19 +37,19 @@
[root root]#
su - $OPENACS_SERVICE_NAME
cd /var/lib/aolserver/$OPENACS_SERVICE_NAME
-cvs import -m "initial install" $OPENACS_SERVICE_NAME OpenACS oacs-5-7-0-final
-exit[root root]# mv /var/lib/aolserver/$OPENACS_SERVICE_NAME /var/tmp
-[root root]# mkdir /var/lib/aolserver/$OPENACS_SERVICE_NAME
-[root root]# chown $OPENACS_SERVICE_NAME.$OPENACS_SERVICE_NAME /var/lib/aolserver/$OPENACS_SERVICE_NAME
-[root root]# su - $OPENACS_SERVICE_NAME
-[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ cd /var/lib/aolserver
-[$OPENACS_SERVICE_NAME aolserver]$ cvs checkout $OPENACS_SERVICE_NAME
+cvs import -m "initial install" $OPENACS_SERVICE_NAME OpenACS oacs-5-7-0-final
+exit
[root root]#
mv /var/lib/aolserver/$OPENACS_SERVICE_NAME /var/tmp
+[root root]# mkdir /var/lib/aolserver/$OPENACS_SERVICE_NAME
+[root root]# chown $OPENACS_SERVICE_NAME.$OPENACS_SERVICE_NAME /var/lib/aolserver/$OPENACS_SERVICE_NAME
+[root root]# su - $OPENACS_SERVICE_NAME
+[$OPENACS_SERVICE_NAME $OPENACS_SERVICE_NAME]$ cd /var/lib/aolserver
+[$OPENACS_SERVICE_NAME aolserver]$ cvs checkout $OPENACS_SERVICE_NAME
cvs checkout: Updating $OPENACS_SERVICE_NAME
U $OPENACS_SERVICE_NAME/license.txt
(many lines omitted)
U $OPENACS_SERVICE_NAME/www/SYSTEM/dbtest.tcl
U $OPENACS_SERVICE_NAME/www/SYSTEM/flush-memoized-statement.tcl
-[$OPENACS_SERVICE_NAME aolserver]$ exit
+[$OPENACS_SERVICE_NAME aolserver]$ exit
logout
[root root]#
@@ -60,4 +60,4 @@
su - $OPENACS_SERVICE_NAME
cd /var/lib/aolserver
cvs checkout $OPENACS_SERVICE_NAME
-exitPrev Home Next Upgrading Platform components Up Running a PostgreSQL database on another server
docs@openacs.orgPrev Home Next Diagnosing Performance Problems Up Running a PostgreSQL database on another server
docs@openacs.orgns_db
interface):begin
+transaction
really means "turn auto-commit mode off" and
+end transaction
means "commit the current transaction and
+turn auto-commit mode on." Thus if transactional code needed to call a
routine which needed to operate transactionally, the semantics were
non-obvious. Consider:
@@ -29,47 +29,47 @@
}
db_transaction {
-db_dml unused "insert into greeble(bork) values(33)"
+db_dml unused "insert into greeble(bork) values(33)"
foo $db
-db_dml unused "insert into greeble(bork) values(50)"
+db_dml unused "insert into greeble(bork) values(50)"
}
foo
+transactionally, but the end transaction
in foo
would actually cause a commit, and greeble #50 would later be inserted in
auto-commit mode. This could cause subtle bugs: e.g., in the case that the
-insert for greeble #50 failed, part of the "transaction" would have
+insert for greeble #50 failed, part of the "transaction" would have
already have been committed!. This is not a good thing.
-set_variables_after_query
routine, which relies on an uplevel
+variable named selection
(likewise for
+set_variables_after_subquery
and subselection
).
-DECODE
on Oracle and CASE ... WHEN
on
Postgres).WHERE
clause criteria dynamicallyORDER BY
clause (Ben Adida has a
+proposed solution for this)SELECT
clause must
contain if it's a query) without actually implementing the statement in a
specific SQL dialectset_variables_after_query
is gone! (Well, it's still there,
but you'll never need to use it.) The new API routines set local
variables automatically. For instance:
-db_1row select_names "select first_names, last_name from users where user_id = [ad_get_user_id]"
-doc_body_append "Hello, $first_names $last_name!"
+db_1row select_names "select first_names, last_name from users where user_id = [ad_get_user_id]"
+doc_body_append "Hello, $first_names $last_name!"
ns_db 1row
, this will bomb if the query doesn't return
any rows (no such user exists). If this isn't what you want, you can
write:
-if { [db_0or1row select_names "select first_names, last_name from users where user_id = [ad_get_user_id]"] } {
- doc_body_append "Hello, $first_names $last_name!"
+if { [db_0or1row select_names "select first_names, last_name from users where user_id = [ad_get_user_id]"] } {
+ doc_body_append "Hello, $first_names $last_name!"
} else {
# Executed if the query returns no rows.
- doc_body_append "There's no such user!"
+ doc_body_append "There's no such user!"
}
-db_foreach select_names "select first_names, last_name from users" {
- doc_body_append "Say hi to $first_names $last_name for me!<br>"
+db_foreach select_names "select first_names, last_name from users" {
+ doc_body_append "Say hi to $first_names $last_name for me!<br>"
}
db_foreach
is now like ns_db
+select
plus a while
loop plus
+set_variables_after_query
plus an if
statement
(containing code to be executed if no rows are returned).
-db_foreach select_names "select first_names, last_name from users where last_name like 'S%'" {
- doc_body_append "Say hi to $first_names $last_name for me!<br>"
+db_foreach select_names "select first_names, last_name from users where last_name like 'S%'" {
+ doc_body_append "Say hi to $first_names $last_name for me!<br>"
} if_no_rows {
- doc_body_append "There aren't any users with last names beginnings with S!"
+ doc_body_append "There aren't any users with last names beginnings with S!"
}
-
-doc_body_append "<ul>"
-db_foreach select_names "select first_names, last_name, user_id from users" {
+doc_body_append "<ul>"
+db_foreach select_names "select first_names, last_name, user_id from users" {
# Automatically allocated a database handle from the main pool.
- doc_body_append "<li>User $first_names $last_name\n<ul>"
+ doc_body_append "<li>User $first_names $last_name\n<ul>"
- db_foreach select_groups "select group_id from user_group_map where user_id = $user_id" {
+ db_foreach select_groups "select group_id from user_group_map where user_id = $user_id" {
# There's a selection in progress, so we allocated a database handle
# from the subquery pool for this selection.
- doc_body_append "<li>Member of group #$group_id.\n"
+ doc_body_append "<li>Member of group #$group_id.\n"
} if_no_rows {
# Not a member of any groups.
- doc_body_append "<li>Not a member of any group.\n"
+ doc_body_append "<li>Not a member of any group.\n"
}
}
-doc_body_append "</ul>"
+doc_body_append "</ul>"
db_release_unused_handles
db_release_unused_handles
is invoked (or the script
terminates).
-ns_db gethandle
- the
+handle is always automatically allocated the first time it's needed.some_presentation_id
is a number which is a valid
presentation ID of the presentation I want to delete. It's easy to write
code handling situations like this since SQL statements can include
-bind variables, which represent placeholders for actual
+bind variables, which represent placeholders for actual
data. A bind variable is specified as a colon followed by an identifier, so
the statement above can be coded as:
@@ -176,43 +176,43 @@
:some_presentation_id
is pulled from the Tcl variable
+$some_presentation_id
(in the caller's environment). Note
that bind variables are not limited to one per statement; you can use an
arbitrary number, and each will pull from the correspondingly named Tcl
-variable. (Alternatively, you can also specify an list or ns_set
+variable. (Alternatively, you can also specify an list or ns_set
providing bind variables' values; see Usage.)
db_quote
to escape single-quotes contained
in the value. The following works fine, despite the apostrophe:
-set exclamation "That's all, folks!"
+set exclamation "That's all, folks!"
db_dml exclamation_insert { insert into exclamations(exclamation) values(:exclamation) }
$table_name
is set
properly:
select * from :table_name
-
-db_dml presentation_delete "
+db_dml presentation_delete "
delete from wp_presentations where presentation_id = $some_presentation_id
-"
+"
$some_presentation_id
to be interpolated in.) This will work,
but consider the case where some devious user causes
-some_presentation_id to be set to something like '3 or
-1 = 1', which would result in the following statement being
+some_presentation_id
to be set to something like '3 or
+1 = 1'
, which would result in the following statement being
executed:
@@ -222,24 +222,24 @@
This deletes every presentation in the database! Using bind variables
eliminates this gaping security hole: since bind variable values are taken
literally. Oracle will attempt to delete presentations whose presentation ID
-is literally '3 or 1 = 1' (i.e., no presentations, since
-'3 or 1 = 1' can't possibly be a valid integer
-primary key for wp_presentations. In general, since Oracle
+is literally
'3 or 1 = 1'
(i.e., no presentations, since
+'3 or 1 = 1'
can't possibly be a valid integer
+primary key for wp_presentations
. In general, since Oracle
always considers the values of bind variables to be literals, it becomes more
difficult for users to perform URL surgery to trick scripts into running
dangerous queries and DML.
-db_*
command accepting a SQL command as an argument
+supports bind variables. You can either-bind
switch to provide a set with bind variable
+values, or-bind
switch to explicitly provide a list of
+bind variable names and values, or-bind
switch is omitted) is
that these procedures expect to find local variables that correspond in name
to the referenced bind variables, e.g.:
set user_id 123456
-set role "administrator"
+set role "administrator"
db_foreach user_group_memberships_by_role {
select g.group_id, g.group_name
@@ -249,18 +249,18 @@
and map.role = :role
} {
# do something for each group of which user 123456 is in the role
- # of "administrator"
+ # of "administrator"
}
user_id
(123456) is bound to
+the user_id
bind variable.
+-bind
switch can takes the name of an ns_set
containing keys for each bind variable named in the query, e.g.:
set bind_vars [ns_set create]
ns_set put $bind_vars user_id 123456
-ns_set put $bind_vars role "administrator"
+ns_set put $bind_vars role "administrator"
db_foreach user_group_memberships_by_role {
select g.group_id, g.group_name
@@ -270,11 +270,11 @@
and map.role = :role
} -bind $bind_vars {
# do something for each group in which user 123456 has the role
- # of "administrator"
+ # of "administrator"
}
-bind
you can specify a list of
alternating name/value pairs for bind variables:
@@ -284,22 +284,22 @@
where g.group_id = map.user_id
and map.user_id = :user_id
and map.role = :role
-} -bind [list user_id 123456 role "administrator"] {
+} -bind [list user_id 123456 role "administrator"] {
# do something for each group in which user 123456 has the role
- # of "administrator"
+ # of "administrator"
}
-
null
. (This coercion does not occur in the
+WHERE
clause of a query, i.e.
+col = ''
and
+col is null
are not equivalent.)
null
is to set the corresponding bind variable
to the empty string, since a bind variable whose value is the string
-"null" will be interpreted as the literal string
-"null".
#
@@ -311,259 +311,259 @@
# );
#
-set bar ""
-set baz ""
+set bar ""
+set baz ""
-db_dml foo_create "insert into foo(bar, baz) values(:bar, :baz)"
+db_dml foo_create "insert into foo(bar, baz) values(:bar, :baz)"
#
-# the values of the "bar" and "baz" columns in the new row are both
+# the values of the "bar" and "baz" columns in the new row are both
# null, because Oracle has coerced the empty string (even for the
-# numeric column "bar") into null in both cases
+# numeric column "bar") into null in both cases
null
, this code has different semantics depending on the
underlying database (i.e., the row that gets inserted may not have null as
its column values), which defeats the purpose of SQL abstraction.
+represent
null
(instead of the Oracle-specific idiom of the
+empty string): db_null
.null
, e.g.:
set bar [db_null]
set baz [db_null]
-db_dml foo_create "insert into foo(bar, baz) values(:bar, :baz)"
+db_dml foo_create "insert into foo(bar, baz) values(:bar, :baz)"
#
-# sets the values for both the "bar" and "baz" columns to null
+# sets the values for both the "bar" and "baz" columns to null
-
db_foreach
, db_0or1row
, and
+db_1row
places the results of queries in Tcl variables, so you
can say:
-db_foreach users_select "select first_names, last_name from users" {
- doc_body_append "<li>$first_names $last_name\n"
+db_foreach users_select "select first_names, last_name from users" {
+ doc_body_append "<li>$first_names $last_name\n"
}
-column_array
and -column_set
switches to
+db_foreach
, db_0or1row
, and db_1row
to
instruct the database routines to place the results in a Tcl array or
-ns_set, respectively, where the keys are the column names and
+ns_set
, respectively, where the keys are the column names and
the values are the column values. For example:
-db_foreach users_select "select first_names, last_name from users" -column_set columns {
+db_foreach users_select "select first_names, last_name from users" -column_set columns {
# Now $columns is an ns_set.
- doc_body_append "<li>"
+ doc_body_append "<li>"
for { set i 0 } { $i < [ns_set size $columns] } { incr i } {
- doc_body_append "[ns_set key $columns $i] is [ns_set value $columns $i]. \n"
+ doc_body_append "[ns_set key $columns $i] is [ns_set value $columns $i]. \n"
}
}
ns_db
anymore (including
+ns_db gethandle
)! Just start doing stuff, and (if you want) call
+db_release_unused_handles
when you're done as a hint to
release the database handle.
-db_null
-db_null
+
db_null
null
. See Nulls and Bind Variables
above.db_foreach
-db_foreach statement-name sql [ -bind bind_set_id | -bind bind_value_list ] \
+db_foreach statement-name sql [ -bind bind_set_id | -bind bind_value_list ] \
[ -column_array array_name | -column_set set_name ] \
code_block [ if_no_rows if_no_rows_block ]
-
+
sql
, executing
+code_block
once for each row with variables set to
+column values (or a set or array populated if -column_array
or
+column_set
is specified). If the query returns no rows, executes
+if_no_rows_block
(if provided).
-db_foreach select_foo "select foo, bar from greeble" {
- doc_body_append "<li>foo=$foo; bar=$bar\n"
+db_foreach select_foo "select foo, bar from greeble" {
+ doc_body_append "<li>foo=$foo; bar=$bar\n"
} if_no_rows {
- doc_body_append "<li>There are no greebles in the database.\n"
+ doc_body_append "<li>There are no greebles in the database.\n"
}
-db_1row statement-name sql [ -bind bind_set_id | -bind bind_value_list ] \
+The code block may contain
break
statements (which terminate the
+loop and flush the database handle) and continue
statements
+(which continue to the next row of the loop). db_1row
+db_1row statement-name sql [ -bind bind_set_id | -bind bind_value_list ] \
[ -column_array array_name | -column_set set_name ]
-
sql
, setting variables to
column values. Raises an error if the query does not return exactly 1 row.
-db_1row select_foo "select foo, bar from greeble where greeble_id = $greeble_id"
+db_1row select_foo "select foo, bar from greeble where greeble_id = $greeble_id"
# Bombs if there's no such greeble!
# Now $foo and $bar are set.
-
-db_0or1row statement-name sql [ -bind bind_set_id | -bind bind_value_list ] \
+
db_0or1row
+db_0or1row statement-name sql [ -bind bind_set_id | -bind bind_value_list ] \
[ -column_array array_name | -column_set set_name ]
-
sql
. If a row is returned,
sets variables to column values and returns 1. If no rows are returned,
-returns 0. If more than one row is returned, throws an error.
-db_string statement-name sql [ -default default ] [ -bind bind_set_id | -bind bind_value_list ]
+returns 0. If more than one row is returned, throws an error.
db_string
+db_string statement-name sql [ -default default ] [ -bind bind_set_id | -bind bind_value_list ]
sql
. If sql
doesn't return a
+row, returns default
(or throws an error if
+default
is unspecified). Analogous to
+database_to_tcl_string
and
+database_to_tcl_string_or_null
.
-
-db_nextval sequence-name
+
db_nextval
+db_nextval sequence-name
SELECT
sequence-name
.nextval FROM
+DUAL
). If sequence pooling is enabled for the sequence, transparently
uses a value from the pool if available to save a round-trip to the database.
-
-db_list statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
+
db_list
+db_list statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
sql
. If sql
doesn't
return any rows, returns an empty list. Analogous to
-database_to_tcl_list.
+database_to_tcl_list
.
-
-db_list_of_lists statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
+
db_list_of_lists
+db_list_of_lists statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
sql
. If
+sql
doesn't return any rows, returns an empty list.
+(Analogous to database_to_tcl_list_list
.)
-
-db_list_of_ns_sets statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
+
db_list_of_ns_sets
+db_list_of_ns_sets statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
-db_dml statement-name sql \
+ returned by the
sql
query specified.
+ db_dml
+db_dml statement-name sql \
[ -bind bind_set_id | -bind bind_value_list ] \
[ -blobs blob_list | -clobs clob_list |
-blob_files blob_file_list | -clob_files clob_file_list ]
-
sql
. :1
, :2
, ... :n
.
+blobs
or clobs
, if specified,
should be a list of individual BLOBs or CLOBs to insert;
-blob_files or clob_files, if
+blob_files
or clob_files
, if
specified, should be a list of paths to files containing the data to
-insert. Only one of -blobs, -clobs,
--blob_files, and -clob_files may be provided.
+insert. Only one of
-blobs
, -clobs
,
+-blob_files
, and -clob_files
may be provided.
-db_dml insert_photos "
+db_dml insert_photos "
insert photos(photo_id, image, thumbnail_image)
values(photo_id_seq.nextval, empty_blob(), empty_blob())
returning image, thumbnail_image into :1, :2
- " -blob_files [list "/var/tmp/the_photo" "/var/tmp/the_thumbnail"]
+ " -blob_files [list "/var/tmp/the_photo" "/var/tmp/the_thumbnail"]
photos
table, with the contents
+of the files /var/tmp/the_photo
and
+/var/tmp/the_thumbnail
in the image
and
+thumbnail
columns, respectively.
db_write_clob
,
+db_write_blob
,
+db_blob_get_file
-db_write_clob statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
+db_write_clob statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
-db_write_blob statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
+db_write_blob statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
-db_blob_get_file statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
-
ns_ora write_clob/write_blob/blob_get_file
.
-
-db_release_unused_handles
-
-db_transaction code_block [ on_error { code_block } ]
-
db_release_unused_handles
+db_release_unused_handles
+
db_transaction
+db_transaction code_block [ on_error { code_block } ]
+
code_block
transactionally. Nested
+transactions are supported (end transaction
is transparently
+ns_db dml
'ed when the outermost transaction completes). The
+db_abort_transaction
command can be used to abort all levels of
+transactions. It is possible to specify an optional on_error
code block that will be executed if some code in code_block throws
-an exception. The variable errmsg will be bound in that scope.
-If there is no on_error code, any errors will be propagated.
+an exception. The variable
errmsg
will be bound in that scope.
+If there is no on_error
code, any errors will be propagated.
proc replace_the_foo { col } {
db_transaction {
- db_dml "delete from foo"
- db_dml "insert into foo(col) values($col)"
+ db_dml "delete from foo"
+ db_dml "insert into foo(col) values($col)"
}
}
proc print_the_foo {} {
- doc_body_append "foo is [db_string "select col from foo"]<br>\n"
+ doc_body_append "foo is [db_string "select col from foo"]<br>\n"
}
replace_the_foo 8
-print_the_foo ; # Writes out "foo is 8"
+print_the_foo ; # Writes out "foo is 8"
db_transaction {
replace_the_foo 14
- print_the_foo ; # Writes out "foo is 14"
- db_dml "insert into some_other_table(col) values(999)"
+ print_the_foo ; # Writes out "foo is 14"
+ db_dml "insert into some_other_table(col) values(999)"
...
db_abort_transaction
} on_error {
- doc_body_append "Error in transaction: $errmsg"
+ doc_body_append "Error in transaction: $errmsg"
}
-print_the_foo ; # Writes out "foo is 8"
+print_the_foo ; # Writes out "foo is 8"
-
db_abort_transaction
-db_abort_transaction
+db_abort_transaction
db_dml "abort" "abort transaction"
.
-
-db_multirow [ -local ] [ -append ] [ -extend column_list ] \
+
db_multirow
+db_multirow [ -local ] [ -append ] [ -extend column_list ] \
var-name statement-name sql \
[ -bind bind_set_id | -bind bind_value_list ] \
code_block [ if_no_rows if_no_rows_block ]
sql
, saving results in variables
of the form
- var_name:1, var_name:2, etc,
- setting var_name:rowcount to the total number
- of rows, and setting var_name:columns to a
+ var_name:1
, var_name:2
, etc,
+ setting var_name:rowcount
to the total number
+ of rows, and setting var_name:columns
to a
list of column names.
-local
is passed, the variables defined
by db_multirow will be set locally (useful if you're compiling dynamic templates
in a function or similar situations).
-extend { col_1 col_2 ... }
switch. This is
useful for things like constructing a URL for the object retrieved by
the query.
-append
switch. This causes the rows returned by this query
to be appended to the rows already in the multirow, instead of starting
a clean multirow, as is the normal behavior. The columns must match the
columns in the original multirow, or an error will be thrown.
continue
in order to skip a row
+ and not include it in the multirow. Or you can call break
to skip this row and quit looping.
-db_resultrows
+
db_resultrows
+db_resultrows
-db_with_handle var code_block
-
+
db_with_handle
+db_with_handle var code_block
+
var
and
+executes code_block
. This is useful when you don't
+want to have to use the new API (db_foreach
,
+db_1row
, etc.), but need to use database handles explicitly.
proc lookup_the_foo { foo } {
db_with_handle db {
- return [db_string unused "select ..."]
+ return [db_string unused "select ..."]
}
}
db_with_handle db {
# Now there's a database handle in $db.
- set selection [ns_db select $db "select foo from bar"]
+ set selection [ns_db select $db "select foo from bar"]
while { [ns_db getrow $db $selection] } {
set_variables_after_query
@@ -633,96 +633,96 @@
}
db_name
-
-
+
+
-
- db_name
-
+
+
db_name
+
db_type
-
-
+
+
-
- db_type
-
+
+
db_type
+
db_compatible_rdbms_p
-
-
+
+
- db_compatible_rdbms_p db_type
+ db_compatible_rdbms_p db_type
db_package_supports_rdbms_p
-
-
+
+
- db_package_supports_rdbms_p db_type_list
+ db_package_supports_rdbms_p db_type_list
db_legacy_package_p
-
-
+
+
- db_legacy_package_p db_type_list
+ db_legacy_package_p db_type_list
db_version
-
-
+
+
- db_version
+ db_version
db_current_rdbms
-
-
+
+
- db_current_rdbms
+ db_current_rdbms
db_known_database_types
-
-
+
+
- db_known_database_types
+ db_known_database_types
set count 0
-set tcl_var "foo"
+set tcl_var "foo"
set sql {
SELECT foo, bar, baz
FROM some_table, some_other_table
@@ -35,30 +35,30 @@
}
db_transaction
command
makes the scope of a transaction
- clear; db_transaction takes the
+ clear; db_transaction
takes the
code block argument and automatically runs it in the context of a
transaction. If you use something like db_foreach though, you need to
make sure that there are no calls in the code block which would take
a second db handle since the transaction is only valid for
one handle (thats why we build up a list of returned values and call
a second proc outside the db_foreach loop).
- db_foreach
writes
our old while loop for us.
-
-set table "baz"
-set condition "where foo = bar"
+set table "baz"
+set condition "where foo = bar"
db_foreach my_query { select :table from some_table where :condition }
db_*
command accepting a SQL command as an argument
+ supports bind variables. You can either-bind
switch to provide a set with bind variable
values, or
- -bind
switch to explicitly provide a list of
bind variable names and values, or
- -bind
switch is omitted) is
that these procedures expect to find local variables that correspond in name
to the referenced bind variables, e.g.:
set user_id 123456
-set role "administrator"
+set role "administrator"
db_foreach user_group_memberships_by_role {
select g.group_id, g.group_name
@@ -169,18 +169,18 @@
and map.role = :role
} {
# do something for each group of which user 123456 is in the role
- # of "administrator"
+ # of "administrator"
}
user_id
(123456) is bound to
+ the user_id
bind variable.
+ -bind
switch can takes the name of an ns_set
containing keys for each bind variable named in the query, e.g.:
set bind_vars [ns_set create]
ns_set put $bind_vars user_id 123456
-ns_set put $bind_vars role "administrator"
+ns_set put $bind_vars role "administrator"
db_foreach user_group_memberships_by_role {
select g.group_id, g.group_name
@@ -190,11 +190,11 @@
and map.role = :role
} -bind $bind_vars {
# do something for each group in which user 123456 has the role
- # of "administrator"
+ # of "administrator"
}
-bind
you can specify a list of
alternating name/value pairs for bind variables:
@@ -204,22 +204,22 @@
where g.group_id = map.user_id
and map.user_id = :user_id
and map.role = :role
-} -bind [list user_id 123456 role "administrator"] {
+} -bind [list user_id 123456 role "administrator"] {
# do something for each group in which user 123456 has the role
- # of "administrator"
+ # of "administrator"
}
-
null
. (This coercion does not occur in the
+ WHERE
clause of a query, i.e.
+ col = ''
and
+ col is null
are not equivalent.)
null
is to set the corresponding bind variable
to the empty string, since a bind variable whose value is the string
- "null" will be interpreted as the literal string
- "null".
#
@@ -231,43 +231,43 @@
# );
#
-set bar ""
-set baz ""
+set bar ""
+set baz ""
-db_dml foo_create "insert into foo(bar, baz) values(:bar, :baz)"
+db_dml foo_create "insert into foo(bar, baz) values(:bar, :baz)"
#
-# the values of the "bar" and "baz" columns in the new row are both
+# the values of the "bar" and "baz" columns in the new row are both
# null, because Oracle has coerced the empty string (even for the
-# numeric column "bar") into null in both cases
+# numeric column "bar") into null in both cases
null
, this code has different semantics depending on the
underlying database (i.e., the row that gets inserted may not have null as
its column values), which defeats the purpose of SQL abstraction.
set bar [db_null]
+ represent
null
(instead of the Oracle-specific idiom of the
+ empty string): db_null
.null
, e.g.:set bar [db_null]
set baz [db_null]
-db_dml foo_create "insert into foo(bar, baz) values(:bar, :baz)"
+db_dml foo_create "insert into foo(bar, baz) values(:bar, :baz)"
#
-# sets the values for both the "bar" and "baz" columns to null
db_nextval
)
does not incur a roundtrip to the server. For instance, this functionality is
very useful in the security/sessions library, which very frequently allocates
- values from the sec_id_seq sequence. To utilize this
+ values from the sec_id_seq
sequence. To utilize this
functionality for a particular sequence, register the sequence to be pooled,
- either using the db_register_pooled_sequence procedure at server
+ either using the db_register_pooled_sequence
procedure at server
startup time, or by including a configuration parameter of the form
PoolSequence.sequence_name_seq=count
yourservername.ini
file, e.g.,
@@ -279,49 +279,49 @@
startup. It will periodically scan pools and allocate new values for
sequences which are less than half-full. (This normally occurs every 60
seconds, and is configurable via the
- PooledSequenceUpdateInterval parameter in the
- [ns/server/
- yourservername
- /acs/database] configuration
+
PooledSequenceUpdateInterval
parameter in the
+ [ns/server/
+ yourservername
+ /acs/database]
configuration
section.)
- ns_db
anymore (including
+ ns_db gethandle
)! Just start doing stuff, and (if you want) call
+ db_release_unused_handles
when you're done as a hint to
release the database handle.
-
db_abort_transaction
-
+
db_abort_transaction
db_dml "abort" "abort transaction"
.
-
-db_multirow [ -local ] [ -append ] [ -extend column_list ] \
+
db_multirow
+db_multirow [ -local ] [ -append ] [ -extend column_list ] \
var-name statement-name sql \
[ -bind bind_set_id | -bind bind_value_list ] \
code_block [ if_no_rows if_no_rows_block ]
sql
, saving results in variables
of the form
- var_name:1, var_name:2, etc,
- setting var_name:rowcount to the total number
- of rows, and setting var_name:columns to a
+ var_name:1
, var_name:2
, etc,
+ setting var_name:rowcount
to the total number
+ of rows, and setting var_name:columns
to a
list of column names.
-local
is passed, the variables defined
by db_multirow will be set locally (useful if you're compiling dynamic templates
in a function or similar situations).
-extend { col_1 col_2 ... }
switch. This is
useful for things like constructing a URL for the object retrieved by
the query.
-append
switch. This causes the rows returned by this query
to be appended to the rows already in the multirow, instead of starting
a clean multirow, as is the normal behavior. The columns must match the
columns in the original multirow, or an error will be thrown.
continue
in order to skip a row
+ and not include it in the multirow. Or you can call break
to skip this row and quit looping.
db_null
-
+
-db_null
+
db_null
null
.
+ See Nulls and
Bind Variables above.
db_foreach
-
+
db_foreach statement-name sql [ -bind bind_set_id | -bind bind_value_list ] \
[ -column_array array_name | -column_set set_name ] \
code_block [ if_no_rows if_no_rows_block ]
sql
, executing
- code_block
- once for each row
+ code_block
+
once for each row
with variables set to column values (or a set or array
populated if
- -column_array or
- column_set is
+ -column_array
or
+ column_set
is
specified). If the query returns no rows, executes
- if_no_rows_block
- (if provided).
+ if_no_rows_block
+
(if provided).
-db_foreach select_foo "select foo, bar from greeble" {
- doc_body_append "<li>foo=$foo; bar=$bar\n"
+db_foreach select_foo "select foo, bar from greeble" {
+ doc_body_append "<li>foo=$foo; bar=$bar\n"
} if_no_rows {
- doc_body_append "<li>There are no greebles in the database.\n"
+ doc_body_append "<li>There are no greebles in the database.\n"
}
break
statements (which terminate the
+ loop and flush the database handle) and continue
statements
(which continue to the next row of the loop).
db_1row
-
+
db_1row statement-name sql [ -bind bind_set_id | -bind bind_value_list ] \
[ -column_array array_name | -column_set set_name ]
sql
,
setting variables to column values. Raises an error if the
query does not return exactly 1 row.
-db_1row select_foo "select foo, bar from greeble where greeble_id = $greeble_id"
+db_1row select_foo "select foo, bar from greeble where greeble_id = $greeble_id"
# Bombs if there's no such greeble!
# Now $foo and $bar are set.
db_0or1row
-
+
db_0or1row statement-name sql [ -bind bind_set_id | -bind bind_value_list ] \
[ -column_array array_name | -column_set set_name ]
sql
.
If a row is returned, sets variables to column values and
returns 1. If no rows are returned, returns 0. If more
than one row is returned, throws an error.
-
+
db_nextval
db_nextval sequence-name
SELECT
+ sequence-name
.nextval FROM
+ DUAL
). If sequence pooling is enabled for the sequence, transparently
uses a value from the pool if available to save a round-trip to the database
- (see Sequence Pooling).
+ (see Sequence Pooling).
db_register_pooled_sequence
-
+
db_register_pooled_sequence sequence-name pool-size
+
db_string
db_string statement-name sql [ -default default ] [ -bind bind_set_id | -bind bind_value_list ]
sql
.
+ If sql
doesn't return a
row, returns
- default
+ default
(or throws an error if
- default is unspecified). Analogous to
- database_to_tcl_string and
- database_to_tcl_string_or_null.
+ default
is unspecified). Analogous to
+ database_to_tcl_string
and
+ database_to_tcl_string_or_null
.
-
+
db_list
db_list statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
sql
.
+ If sql
doesn't
return any rows, returns an empty list. Analogous to
- database_to_tcl_list.
+ database_to_tcl_list
.
-
+
db_list_of_lists
db_list_of_lists statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
sql
. If
+ sql
doesn't return any rows, returns an empty list.
+ (Analogous to database_to_tcl_list_list
.)
-
+
db_dml
db_dml statement-name sql \
[ -bind bind_set_id | -bind bind_value_list ] \
[ -blobs blob_list | -clobs clob_list |
-blob_files blob_file_list | -clob_files clob_file_list ]
-
sql
. :1
, :2
, ... :n
.
+ blobs
or clobs
, if specified,
should be a list of individual BLOBs or CLOBs to insert;
- blob_files or clob_files, if
+ blob_files
or clob_files
, if
specified, should be a list of paths to files containing the data to
- insert. Only one of -blobs, -clobs,
- -blob_files, and -clob_files may be provided.
+ insert. Only one of
-blobs
, -clobs
,
+ -blob_files
, and -clob_files
may be provided.
-db_dml insert_photos "
+db_dml insert_photos "
insert photos(photo_id, image, thumbnail_image)
values(photo_id_seq.nextval, empty_blob(), empty_blob())
returning image, thumbnail_image into :1, :2
- " -blob_files [list "/var/tmp/the_photo" "/var/tmp/the_thumbnail"]
+ " -blob_files [list "/var/tmp/the_photo" "/var/tmp/the_thumbnail"]
photos
table, with the contents
+ of the files /var/tmp/the_photo
and
+ /var/tmp/the_thumbnail
in the image
and
+ thumbnail
columns, respectively.
db_write_clob
,
+ db_write_blob
,
+ db_blob_get_file
db_write_clob statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
db_write_blob statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
db_blob_get_file statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
-
ns_ora write_clob/write_blob/blob_get_file
.
-
+
db_release_unused_handles
db_release_unused_handles
-
+
db_transaction
db_transaction code_block [ on_error { code_block } ]
-
code_block
transactionally. Nested
+ transactions are supported (end transaction
is transparently
+ ns_db dml
'ed when the outermost transaction completes). The
+ db_abort_transaction
command can be used to abort all levels of
+ transactions. It is possible to specify an optional on_error
code block that will be executed if some code in code_block throws
- an exception. The variable errmsg will be bound in that scope.
- If there is no on_error code, any errors will be propagated.
+ an exception. The variable
errmsg
will be bound in that scope.
+ If there is no on_error
code, any errors will be propagated.
proc replace_the_foo { col } {
db_transaction {
- db_dml "delete from foo"
- db_dml "insert into foo(col) values($col)"
+ db_dml "delete from foo"
+ db_dml "insert into foo(col) values($col)"
}
}
proc print_the_foo {} {
- doc_body_append "foo is [db_string "select col from foo"]<br>\n"
+ doc_body_append "foo is [db_string "select col from foo"]<br>\n"
}
replace_the_foo 8
-print_the_foo ; # Writes out "foo is 8"
+print_the_foo ; # Writes out "foo is 8"
db_transaction {
replace_the_foo 14
- print_the_foo ; # Writes out "foo is 14"
- db_dml "insert into some_other_table(col) values(999)"
+ print_the_foo ; # Writes out "foo is 14"
+ db_dml "insert into some_other_table(col) values(999)"
...
db_abort_transaction
} on_error {
- doc_body_append "Error in transaction: $errmsg"
+ doc_body_append "Error in transaction: $errmsg"
}
-print_the_foo ; # Writes out "foo is 8"
+print_the_foo ; # Writes out "foo is 8"
-
+
db_resultrows
db_resultrows
+
db_with_handle
db_with_handle var code_block
-
+
var
and
+ executes code_block
. This is useful when you don't
+ want to have to use the new API (db_foreach
,
+ db_1row
, etc.), but need to use database handles explicitly.
proc lookup_the_foo { foo } {
db_with_handle db {
- return [db_string unused "select ..."]
+ return [db_string unused "select ..."]
}
}
db_with_handle db {
# Now there's a database handle in $db.
- set selection [ns_db select $db "select foo from bar"]
+ set selection [ns_db select $db "select foo from bar"]
while { [ns_db getrow $db $selection] } {
set_variables_after_query
@@ -623,51 +623,51 @@
db_nullify_empty_string
-
+
db_nullify_empty_string string
db_nullify_empty_string
, which returns
+ [db_null] if its string
argument is the empty string
and can be used to encapsulate another Oracle quirk:
-set baz ""
+set baz ""
# Clean out the foo table
#
-db_dml unused "delete from foo"
+db_dml unused "delete from foo"
-db_dml unused "insert into foo(baz) values('$baz')"
+db_dml unused "insert into foo(baz) values('$baz')"
-set n_rows [db_string unused "select count(*) from foo where baz is null"]
+set n_rows [db_string unused "select count(*) from foo where baz is null"]
#
-# $n_rows is 1; in effect, the "baz is null" criterion is matching
+# $n_rows is 1; in effect, the "baz is null" criterion is matching
# the empty string we just inserted (because of Oracle's coercion
# quirk)
baz
to
+ null
by writing:
-db_dml foo_insert "insert into foo(baz) values(:1)" {[db_nullify_empty_string $baz]}
+db_dml foo_insert "insert into foo(baz) values(:1)" {[db_nullify_empty_string $baz]}
-# Query to return the elements of a page as a list. The prefix "page_" is used to denote
+# Query to return the elements of a page as a list. The prefix "page_" is used to denote
# that this is a page-related query, page_id is used to uniquely identify the query
# by object, and the suffix uniquely defines the operation being performed on the
# page object.
Index: openacs-4/packages/acs-core-docs/www/dev-guide.html
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/dev-guide.html,v
diff -u -r1.35 -r1.35.2.1
--- openacs-4/packages/acs-core-docs/www/dev-guide.html 31 Jul 2011 23:11:45 -0000 1.35
+++ openacs-4/packages/acs-core-docs/www/dev-guide.html 21 Aug 2013 10:19:21 -0000 1.35.2.1
@@ -1,2 +1,2 @@
-
-
- <book><title><part label="Part 1"><etc...>
+ <book><title><part label="Part 1"><etc...>
bibliocoverage
,
+ bibliorelation
, and
+ bibliosource
. DocBook:
The Definitive Guide is a good start for learning how
to represent paper-based books online.
xsltproc
- The processor that
will take an XML document and, given a xsl stylesheet, convert
it to HTML. It needs libxml2 and libxslt (available in RPM and
- DEB formats or from xmlsoft.org.
-
- book : Docs for one package - templating
+ book : Docs for one package - templating
|
- +--chapter : One section - for developers
+ +--chapter : One section - for developers
|
---------+------------------------------------------------------
|
- +--sect1 : Single document - requirements
+ +--sect1 : Single document - requirements
|
- +--sect2 : Sections - functional requirements
+ +--sect2 : Sections - functional requirements
|
- +--sect3 : Subsections - Programmer's API
+ +--sect3 : Subsections - Programmer's API
|
- ... : ...
+ ... : ...
sect1
-level. These are then tied together in a top-level document that
contains all the information above the line. This will be explained in more detail in a later document,
and we will provide a set of templates for documenting an entire package. sect1
-level, all your documents should open with a
+ <sect1>
-tag and end
+ with the corresponding </sect1>
.
<sect1>
two attributes. The first attribute,
+ id
, is standard and can be used with all elements. It comes in very
+ handy when interlinking between documents (more about this when talking about links in the section called “Links”).
+ The value of id
has to be unique
+ throughout the book you're making since the id
's in your
+ sect1
's will turn into filenames when the book is parsed into HTML.
xreflabel
. The value of this is the text that will appear
+ as the link when referring to this sect1
.
xreflabel
-attribute. E.g. the top level of the document you're
reading right now looks like this:
-<sect1 id="docbook-primer" xreflabel="DocBook Primer">
+<sect1 id="docbook-primer" xreflabel="DocBook Primer">
<title>DocBook Primer</title>
...
</sect1>
<sect2>
's,
+ each with the same requirements - id
and xreflabel
+ attributes, and a <title>
-tag inside. Actually, the xreflabel
is never required in sections, but it makes linking to that section a lot easier.
sect2
's and below, prefix them with some abbreviation of the id
in the sect1
such as requirements-overview
.
+ <computeroutput>
+ and <code>
tags.
- These replace the HTML-tag <code><code></code> tag,
+ These replace the HTML-tag <code>
tag,
depending on whether the tag is describing computer output or
computer code.
<programlisting>
is used. Just wrap your code block in it; mono-spacing, indents and all that stuff is taken care of
automatically.
<screen>
+ tag around text that has been wrapped by combinations of <computeroutput>
+ and <userinput>
+id
's you can cross-reference any part of your book
with a simple tag, regardless of where that part is.
-
+
- Find information about creating a package in
-<xref linkend="packages-making-a-package"></xref>.
+<xref linkend="packages-making-a-package"></xref>.
- Find information about creating a package in
-Making a Package.
+Making a Package.
</xref>
, or
+ <xref linkend="blahblah"/>
+ xreflabel
-attribute,
the link is going to look like this:
-Find information about what a package looks like in
-<xref linkend="packages-looks"></xref>.
+<xref linkend="packages-looks"></xref>.
- Find information about what a package looks like in
-Section , “What a Package Looks Like”.
+the section called “What a Package Looks Like”.
xreflabel
for the subsection,
+ packages-looks
, the
parser will try its best to explain where the link takes you.
- <ulink>
):
- <ulink url="http://www.oracle.com/">Oracle Corporation</ulink>
<ulink url="http://www.oracle.com/">Oracle Corporation</ulink>
&
- <mediaobject>
,
+ <imageobject>
,
+ <imagedata>
,
and
- <textobject>.
+ <textobject>
.
Two versions of all graphics are required. One for the Web
(usually a JPEG or GIF), and a brief text description. The
description becomes the ALT text. You can also supply a version for print (EPS).
<mediaobject>
<imageobject>
- <imagedata fileref="images/rp-flow.gif" format="GIF" align="center"/>
+ <imagedata fileref="images/rp-flow.gif" format="GIF" align="center"/>
</imageobject>
<imageobject>
- <imagedata fileref="images/rp-flow.eps" format="EPS" align="center"/>
+ <imagedata fileref="images/rp-flow.eps" format="EPS" align="center"/>
</imageobject>
<textobject>
<phrase>This is an image of the flow in the Request Processor</phrase>
</textobject>
</mediaobject>
<li>
, that is. The only differences are that each list item has to be wrapped in something more, such as
+ <para>
, and that the tags are called
+ <itemizedlist>
and
- <listitem>:
+ <listitem>
:
<itemizedlist>
<listitem><para>Stuff goes here</para></listitem>
<listitem><para>More stuff goes here</para></listitem>
</itemizedlist>
-
+
<orderedlist>
instead:
<orderedlist>
<listitem><para>Stuff goes here</para></listitem>
<listitem><para>More stuff goes here</para></listitem>
</orderedlist>
-
variablelist
and these are the tags you'll need to
make it happen:
- <variablelist>,
- <varlistentry>,
- <term> and
- <listitem>:
+
<variablelist>
,
+ <varlistentry>
,
+ <term>
and
+ <listitem>
:
<variablelist>
<varlistentry>
@@ -889,14 +889,14 @@
</varlistentry>
</variablelist>
-
<informaltable>
is enough:
-<informaltable frame="all">
- <tgroup cols="3">
+<informaltable frame="all">
+ <tgroup cols="3">
<tbody>
<row>
@@ -924,26 +924,26 @@
With our current XSL-style-sheet, the output of the markup above will be a simple HTML-table:
a1 b1 c1 a2 b2 c2 a3 b3 c3 <table>
for an example.
- <emphasis>
.
<emphasis>
tag defaults to italics when parsed. If you're looking for
+ emphasizing with bold type, use <emphasis role="strong">
.
+ <indexterm>
,
+ <primary>
and
+ <secondary>
for this. See these links for an explanation.
- Note
Note
-bash$ xsltproc -o outputfilename.xml /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/html/html.xsl filename.xml
+
bash$
xsltproc -o outputfilename.xml /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/html/html.xsl filename.xml
Note
-bash$ xsltproc /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/html/chunk.xsl filename.xml
+
bash$
xsltproc /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/html/chunk.xsl filename.xml
Constraint type Abbreviation references (foreign key) fk unique un primary key pk check ck not null nn Constraint type Abbreviation references (foreign key) fk unique un primary key pk check ck not null nn
+
create table example_topics (
topic_id integer
constraint example_topics_topic_id_pk
@@ -52,7 +52,7 @@
constraint cne_example_id_one_line_unq unique(example_id, one_line_description)
);
-
object-verb.extension
/admin/users/portrait-erase.tcl
.
+/bookmarks/
+directory, and so there is no need to name the bookmark editing page with a redundant url: /bookmarks/bookmark-edit.tcl
. Instead, we omit the object type, and use this convention:
verb.extension
/bookmarks/edit.tcl
.
+one.
extension
/bookmarks/one.tcl
. Note that no verb is necessary for display-type files.
+object.extension
/ecommerce/product.tcl
.
+foobar.extension
(Step 1)foobar-2.extension
(Step 2)foobar-N.extension
(Step N)foobar
is determined by the above
rules.
/www/doc/sql
, and name them
for the modules towards which they are used:
module
.sql
module
-procs.tcl
+user-delete
instead of
+user-delete.tcl
), because they enhance maintainability.
index.tcl
,
+index.adp
, index.html
, etc.). Instead, use
just the directory name, for both relative links
-(subdir/) and absolute links
-(/top-level-dir/). If linking to the directory in which
-the page is located, use the empty string (""), which
+(subdir/
) and absolute links
+(/top-level-dir/
). If linking to the directory in which
+the page is located, use the empty string (""
), which
browsers will resolve correctly.
-
# /www/index.tcl
-
# /tcl/module-defs.tcl
-
@@ -95,7 +95,7 @@
This can be at the top or bottom of the file.
ad_page_contract
after the file path comment (this supersedes set_the_usual_form_variables and
ad_return_complaint). Here is an example of using
ad_page_contract, which serves both documentation and page input
@@ -119,32 +119,32 @@
{persistent_cookie_p f}
}
ad_page_contract
:
+foo:integer,multiple,trim
. In particular, multiple
and
+array
are the flags that correspond to the old
+ad_page_variables
flags.trim
, notnull
and
+optional
. They do what you'd expect; values will not be
trimmed, unless you mark them for it; empty strings are valid input, unless
you specify notnull; and a specified variable will be considered required,
-unless you declare it optional.ad_page_contract
can do validation for you: the flags integer
+and sql_identifier
will make sure that the values
+supplied are integers/sql_identifiers. The integer
flag
will also trim leading zeros. Note that unless you specify
-notnull, both will accept the empty string.
-notnull
, both will accept the empty string.
+ad_page_contract
does not generate
QQvariables, which were automatically created by ad_page_variables and
set_the_usual_form_variables. The use of bind variables makes such
previous variable syntax obsolete.
ad_library
after
the file path comment. Its only argument is a doc_string in the
standard (javadoc-style) format, like
-ad_page_contract. Don't forget to put the @cvs-id in
+ad_page_contract
. Don't forget to put the @cvs-id in
there. Here is an example of using ad_library:
# tcl/wp-defs.tcl
@@ -165,56 +165,56 @@
-- author
-- created
--
--- $Id$
+-- $Id$
--
" with the comment delimiter
appropriate for the language in which you are programming.
-page_content
), and then send it back to the browser with
+one call to doc_return
, which will call
db_release_unused_handles prior to executing ns_return, effectively
combining the two operations.
-set page_content "[ad_header "Page Title"]
+set page_content "[ad_header "Page Title"]
<h2>Page Title</h2>
<hr>
<ul>
-"
+"
db_foreach get_row_info {
select row_information
from bar
} {
- append page_content "<li>row_information\n"
+ append page_content "<li>row_information\n"
}
-append page_content "</ul>
+append page_content "</ul>
-[ad_footer]"
+[ad_footer]"
doc_return 200 text/html $page_content
ReturnHeaders
and
+then ns_write
for each distinct chunk of the page. This
approach has the disadvantage of tying up a scarce and valuable
resource (namely, a database handle) for an unpredictable amount of
time while sending packets back to the browser, and so it should be
avoided in most cases. (On the other hand, for a page that requires an
expensive database query, it's better to call
-ad_return_top_of_page
+ad_return_top_of_page
first, so that the user is not left to stare at an empty page while
the query is running.)
module_
" and
should be used rarely, only when they are exceedingly useful.
create or replace procedure|function
+ <proc_or_func_name>
. It makes reloading packages much
easier and painless to someone who is upgrading or fixing a bug.
- end
statements, i.e., the
+ end
statement for a package should be end
+ <package_name>;
, not just end;
; same
goes for procedures, functions, package bodies, and triggers.
-
-
+
acs_user.create(first_names => 'Jane', last_name => 'Doe', etc.)
-
+
instead of
-
+
acs_user.create(first_names_in => 'Jane', last_name_in => 'Doe', etc.)
-
+
new
functions (e.g., acs_object.new,
+ party.new,
etc.) should optionally accept an ID:
-
+
create or replace package acs_object
as
function new (
@@ -134,22 +134,22 @@
creation_ip in acs_objects.creation_ip%TYPE default null,
context_id in acs_objects.context_id%TYPE default null
) return acs_objects.object_id%TYPE;
-
+
object_id
. Do this to
allow people to use the same API call when they are doing double
click protection, that is, tehy have already gotten an
- object_id and now they want to create the object with
- that object_id.
- 5.0.0
5.0.0rc2
5.0.0rc1
@@ -24,7 +22,7 @@
Version numbers are also recorded in the CVS repository so that the
code tree can be restored to the exact state it was in for a
particular release. To translate between a distribution tar file
-(acs-3.2.2.tar.gz) and a CVS tag, just swap '.' for '-'.The entire release history of the toolkit is recorded in the tags for the top-level readme.txt file:
+(acs-3.2.2.tar.gz) and a CVS tag, just swap '.' for '-'.The entire release history of the toolkit is recorded in the tags for the top-level
readme.txt
file:
> cvs log readme.txt
RCS file: /usr/local/cvsroot/acs/readme.txt,v
@@ -60,10 +58,10 @@
@@ -73,24 +71,24 @@
<maturity>1</maturity>
<callbacks>
...
-
/packages/myfirstpackage/sql/postgresql/upgrade/upgrade-OLDVERSION-NEWVERSION.sql
/packages/myfirstpackage/myfirstpackage.info
. So if forums is at 2.0.1, OLDVERSION should be 2.0.1d1. Note that this means that new version development that includes an upgrade must start at d2, not d1.
+ upgrade-2.0.1d3-2.0.1d4.sql
.upgrade-5.1.0d1-5.1.0d2.sql
Prev Home Next Using Form Builder: building html forms dynamically Up OpenACS Style Guide
docs@openacs.orgPrev Home Next Using Form Builder: building html forms dynamically Up OpenACS Style Guide
docs@openacs.orgFeature Status Description New API EXT-AUTH-01 A Extend Authentication/Acct Status API EXT-AUTH-03 A Account Creation API EXT-AUTH-05 A Password Management API EXT-AUTH-30 A Authority Management API Feature Status Description Login EXT-AUTH-04 A Rewrite login, register, and admin pages to use APIs EXT-AUTH-38 A ad_form complain feature EXT-AUTH-19 A Rewrite password recovery to use API EXT-AUTH-21 A Rewrite email verification with API EXT-AUTH-28 A Username is email switch Feature Status Description New API EXT-AUTH-01 A Extend Authentication/Acct Status API EXT-AUTH-03 A Account Creation API EXT-AUTH-05 A Password Management API EXT-AUTH-30 A Authority Management API Feature Status Description Login EXT-AUTH-04 A Rewrite login, register, and admin pages to use APIs EXT-AUTH-38 A ad_form complain feature EXT-AUTH-19 A Rewrite password recovery to use API EXT-AUTH-21 A Rewrite email verification with API EXT-AUTH-28 A Username is email switch Feature Status Description Configuration EXT-AUTH-07 A Admin pages to control Ext-Auth parameters Feature Status Description Configuration EXT-AUTH-07 A Admin pages to control Ext-Auth parameters Feature Status Description create service contract EXT-AUTH-16 A Create service contract for Authentication EXT-AUTH-17 A Create service contract for Acct. Creation EXT-AUTH-29 A Create service contract for Passwd Management Feature Status Description EXT-AUTH-18 A Authority configuration data model Feature Status Description create service contract EXT-AUTH-16 A Create service contract for Authentication EXT-AUTH-17 A Create service contract for Acct. Creation EXT-AUTH-29 A Create service contract for Passwd Management Feature Status Description EXT-AUTH-18 A Authority configuration data model Feature Status Description Synchronizing and linking users EXT-AUTH-28 A Create service contract for Batch Sync. EXT-AUTH-38 A Batch User Synchronization API EXT-AUTH-38 A IMS Synchronization driver EXT-AUTH-08 A Automation of batch Synchronization EXT-AUTH-15 B On-demand syncronization Feature Status Description Synchronizing and linking users EXT-AUTH-28 A Create service contract for Batch Sync. EXT-AUTH-38 A Batch User Synchronization API EXT-AUTH-38 A IMS Synchronization driver EXT-AUTH-08 A Automation of batch Synchronization EXT-AUTH-15 B On-demand syncronization Feature Status Description EXT-AUTH-31 EXT-AUTH-31 A Upgrade user data model for ext-auth Feature Status Description EXT-AUTH-31 EXT-AUTH-31 A Upgrade user data model for ext-auth Feature Status Description EXT-AUTH-20 EXT-AUTH-20 A Login over HTTPS Feature Status Description EXT-AUTH-20 EXT-AUTH-20 A Login over HTTPS Feature Status Description EXT-AUTH-33 EXT-AUTH-33 A Untrusted Logins Feature Status Description EXT-AUTH-33 EXT-AUTH-33 A Untrusted Logins auth::require_login
would
bounce to the login page if the user is only logged in at the
untrusted level. Only if you explicitly say
-auth::require_login -untrusted will we give you
+auth::require_login -untrusted
will we give you
the user_id of a user who's only logged in in untrusted
-mode.ad_conn user_id
will continue
to return 0 (not logged in) when the user is only logged in
-untrusted, and we'll supply another variable, ad_conn
-untrusted_user_id, which wlll be set to the user_id for
+untrusted, and we'll supply another variable, ad_conn
+untrusted_user_id
, which wlll be set to the user_id for
all login levels.Feature Status Description EXT-AUTH-34 EXT-AUTH-34 A Expire Logins Feature Status Description EXT-AUTH-34 EXT-AUTH-34 A Expire Logins Feature Status Description EXT-AUTH-23 EXT-AUTH-23 Single sign-on Feature Status Description EXT-AUTH-23 EXT-AUTH-23 Single sign-on Feature Status Description EXT-AUTH-22 EXT-AUTH-22 B rewrite cookie handling Feature Status Description EXT-AUTH-22 EXT-AUTH-22 B rewrite cookie handling Feature Status Description EXT-AUTH-24 EXT-AUTH-24 A Email on password change Feature Status Description EXT-AUTH-24 EXT-AUTH-24 A Email on password change Feature Status Description EXT-AUTH-25 EXT-AUTH-25 A Implement password policy Feature Status Description EXT-AUTH-25 EXT-AUTH-25 A Implement password policy Feature Status Description EXT-AUTH-26 EXT-AUTH-26 B Login without explicit domain Feature Status Description EXT-AUTH-26 EXT-AUTH-26 B Login without explicit domain
if { ![auth::split_username -username_var username -authority_var authority] } {
@@ -305,7 +305,7 @@
# username will now contain username
# authority will now contain authority
-
Feature Status Description EXT-AUTH-27 EXT-AUTH-27 B Who's online list Feature Status Description EXT-AUTH-27 EXT-AUTH-27 B Who's online list Feature Status Description EXT-AUTH-28 EXT-AUTH-28 implement subsite-level config Feature Status Description EXT-AUTH-28 EXT-AUTH-28 implement subsite-level config Feature Status Description EXT-AUTH-32 EXT-AUTH-32 A Parameters for Service Contract Implementation EXT-AUTH-35 A Make the Authentication API a service contract Feature Status Description EXT-AUTH-32 EXT-AUTH-32 A Parameters for Service Contract Implementation EXT-AUTH-35 A Make the Authentication API a service contract Feature Status Description EXT-AUTH-36 EXT-AUTH-36 A Authenticate against multiple servers auth::require_login
+and auth::authenticate
) be implemented through a
+service contract.Feature Status Description EXT-AUTH-36 EXT-AUTH-36 A Authenticate against multiple servers Feature Status Description Implement specific drivers EXT-AUTH-09 A Create Auth. drivers for Local Authority EXT-AUTH-10 A Create Acct. Creation driver for Local Authority EXT-AUTH-11 A Create Auth. driver for PAM EXT-AUTH-12 X Create Acct. Creation driver for PAM - this
- functionality is explicitly excluded from PAM EXT-AUTH-13 A Create Acct. Creation driver for LDAP EXT-AUTH-14 A Create Auth. driver for LDAP Feature Status Description Implement specific drivers EXT-AUTH-09 A Create Auth. drivers for Local Authority EXT-AUTH-10 A Create Acct. Creation driver for Local Authority EXT-AUTH-11 A Create Auth. driver for PAM EXT-AUTH-12 X Create Acct. Creation driver for PAM - this
+ functionality is explicitly excluded from PAM EXT-AUTH-13 A Create Acct. Creation driver for LDAP EXT-AUTH-14 A Create Auth. driver for LDAP Document Revision # Action Taken, Notes When? By Whom? 0.3 Edited further, incorporated feedback from Michael Yoon 9/05/2000 Kai Wu 0.2 Edited 8/22/2000 Kai Wu 0.1 Creation 8/21/2000 Josh Finkler, Audrey McLoghlin Prev Home Next OpenACS Core Documentation Up Chapter 1. High level information: What is OpenACS?
docs@openacs.orgPrev Home Next OpenACS Core Documentation Up Chapter 1. High level information: What is OpenACS?
docs@openacs.orgset foo_options [db_list_of_lists foo_option_list "
+ the ad_form api
+ documentation is helpful.
set foo_options [db_list_of_lists foo_option_list "
select foo,
foo_id
from foos
-"]
-
{foo:text(select)
- {label "Which Foo"}
+"]
+
foo_options
should resemble {{first foo} 1234} {{second foo} 1235}
+
{foo:text(select)
+ {label "Which Foo"}
{options $foo_options}
- }
-new_data
and -edit_data
. In the example, it is available as $foo
{pm_task_id:integer(select),optional
- {label "Subject"}
+ {label "Subject"}
{options {$task_options}}
- {html {onChange "document.form_name.__refreshing_p.value='1';submit()"}}
+ {html {onChange "document.form_name.__refreshing_p.value='1';submit()"}}
{value $pm_task_id}
}
db_1row get_task_values { }
template::element set_value form_name estimated_hours_work $estimated_hours_work
-
ns_log notice it's my page!
set mypage [ns_getform]
-if {[string equal "" $mypage]} {
+if {[string equal "" $mypage]} {
ns_log notice no form was submitted on my page
} else {
ns_log notice the following form was submitted on my page
ns_set print $mypage
}
-
user_groups
table may contain the
+group_id
of a parent group, but parent-child relationship
support is limited because it only allows one kind of relationship between
groups to be represented. Moreover, the Oracle database's limited support
for tree-like structures makes the queries over these relationships
expensive.scope
, user_id
, and group_id
columns
was used to identify the party. One disadvantage of this design convention is
that it increases a data model's complexity by requiring the programmer
-to:scope
value of "group" but a null
+group_id
)Tcl
and PL/SQL
+functions and procedures to check both the user_id
and
+group_id
valuesparties
persons
first_names
and
+last_name
.users
user_preferences
-groups
-group_types
membership_rels
group_member_index
-rel_id
+from the membership_rels
table.composition_rels
group_component_index
-rel_id
from the composition_rels
table.group.new
constructor.
When a specialized type of group is required, the group type can be extended
by an application developer. Membership constraints can be specified at
-creation time by passing a parent group to the constructor.membership_rels
and composition_rels
tables indicate
a group's direct members and direct components; these tables do not
provide a record of the members or components that are in the group by virtue
of being a member or component of one of the group's component groups.
@@ -85,60 +85,60 @@
queries responsive, the data model includes triggers (described in the next
paragraph) which watch for changes in membership or composition and update
tables that maintain the group party mappings, i.e.,
-group_member_index and group_component_index. One can think
-of these tables as a manually maintained index.group_member_index
and group_component_index
. One can think
+of these tables as a manually maintained index.group_*_index
tables up to
+date:membership_rels_in_tr
membership_rels
)membership_rels_del_tr
membership_rels
)composition_rels_in_tr
composition_rels
)composition_rels_del_tr
composition_rels
)group_member_index
and group_component_index
tables. No
+code outside of Groups System should modify the group_*_index
+tables.group_member_map
rel_id
+from the membership_rels
table.group_approved_member_map
member_state
is 'approved'); this mapping includes the type
+of relationship by including the appropriaterel_id
from the
+membership_rels
table.group_distinct_member_map
group_component_map
-rel_id
from the composition_rels
table.party_member_map
-party_approved_member_map
-group_types
table is used to create new types of groups.group_member_map
, group_approved_member_map
,
+group_distinct_member_map
, group_component_map
,
+party_member_map
, and party_approved_member_map
views are
+used to query group membership and composition.person.new
creates a new person and returns the
+person_id
. The function must be given the full name of the person in
+two pieces: first_names
and last_name
. All other fields are
+optional and default to null except for object_type
which defaults
+to person and creation_date
which defaults to sysdate
. The
interface for this function is:
function person.new (
person_id persons.person_id%TYPE,
@@ -151,19 +151,19 @@
first_names persons.first_names%TYPE,
last_name persons.last_name%TYPE
) return persons.person_id%TYPE;
-
person.delete
deletes the person whose person_id
is
passed to it. The interface for this procedure is:
procedure person.delete (
person_id persons.person_id%TYPE
);
-
+
person.name
returns the name of the person whose
+person_id
is passed to it. The interface for this function is:
function person.name (
person_id persons.person_id%TYPE
) return varchar;
-
acs_user.new
creates a new user and returns the user_id
.
The function must be given the user's email address and the full name of
-the user in two pieces: first_names and last_name. All
+the user in two pieces: first_names
and last_name
. All
other fields are optional. The interface for this function is:
function acs_user.new (
user_id users.user_id%TYPE,
@@ -182,19 +182,19 @@
screen_name users.screen_name%TYPE,
email_verified_p users.email_verified_p%TYPE
) return users.user_id%TYPE;
-
acs_user.delete
deletes the user whose user_id
is passed
to it. The interface for this procedure is:
procedure acs_user.delete (
user_id users.user_id%TYPE
);
-
acs_user.receives_alerts_p
returns 't' if the user should
receive email alerts and 'f' otherwise. The interface for this
function is:
function acs_user.receives_alerts_p (
user_id users.user_id%TYPE
) return varchar;
-
acs_user.approve_email
and
+acs_user.unapprove_email
to specify whether the user's email
address is valid. The interface for these procedures are:
procedure acs_user.approve_email (
user_id users.user_id%TYPE
@@ -203,11 +203,11 @@
procedure acs_user.unapprove_email (
user_id users.user_id%TYPE
);
-
acs_group.new
creates a new group and returns the
+group_id
. All fields are optional and default to null except for
+object_type
which defaults to 'group',
+creation_date
which defaults to sysdate
, and
+group_name
which is required. The interface for
this function is:
function acs_group.new (
group_id groups.group_id%TYPE,
@@ -219,21 +219,21 @@
url parties.url%TYPE,
group_name groups.group_name%TYPE
) return groups.group_id%TYPE;
-
+
acs_group.name
returns the name of the group whose
+group_id
is passed to it. The interface for this function is:
function acs_group.name (
group_id groups.group_id%TYPE
) return varchar;
-
acs_group.member_p
returns 't' if the specified party is
a member of the specified group. Returns 'f' otherwise. The interface
for this function is:
function acs_group.member_p (
group_id groups.group_id%TYPE,
party_id parties.party_id%TYPE,
) return char;
-
membership_rel.new
creates a new membership relationship type
+between two parties and returns the relationship type's rel_id
.
+All fields are optional and default to null except for rel_type
which defaults to membership_rel. The interface for this function is:
function membership_rel.new (
rel_id membership_rels.rel_id%TYPE,
@@ -244,42 +244,42 @@
creation_user acs_objects.creation_user%TYPE,
creation_ip acs_objects.creation_ip%TYPE,
) return membership_rels.rel_id%TYPE;
-
+
membership_rel.ban
sets the member_state
of the given
+rel_id
to 'banned'. The interface for this procedure is:
procedure membership_rel.ban (
rel_id membership_rels.rel_id%TYPE
);
-
membership_rel.approve
sets the member_state
of the
+given rel_id
to 'approved'. The interface for this procedure
is:
procedure membership_rel.approve (
rel_id membership_rels.rel_id%TYPE
);
-
+
membership_rel.reject
sets the member_state
of the given
+rel_id
to 'rejected. The interface for this procedure is:
procedure membership_rel.reject (
rel_id membership_rels.rel_id%TYPE
);
-
membership_rel.unapprove
sets the member_state
of the
+given rel_id
to an empty string ''. The interface for this
procedure is:
procedure membership_rel.unapprove (
rel_id membership_rels.rel_id%TYPE
);
-
membership_rel.deleted
sets the member_state
of the
+given rel_id
to 'deleted'. The interface for this procedure
is:
procedure membership_rel.deleted (
rel_id membership_rels.rel_id%TYPE
);
-
membership_rel.delete
deletes the given rel_id
. The
interface for this procedure is:
procedure membership_rel.delete (
rel_id membership_rels.rel_id%TYPE
);
-
composition_rel.new
creates a new composition relationship type
+and returns the relationship's rel_id
. All fields are optional
+and default to null except for rel_type
which defaults to
composition_rel. The interface for this function is:
function membership_rel.new (
rel_id composition_rels.rel_id%TYPE,
@@ -289,18 +289,18 @@
creation_user acs_objects.creation_user%TYPE,
creation_ip acs_objects.creation_ip%TYPE,
) return composition_rels.rel_id%TYPE;
-
composition_rel.delete
deletes the given rel_id
. The
interface for this procedure is:
procedure membership_rel.delete (
rel_id composition_rels.rel_id%TYPE
);
-
Document Revision # Action Taken, Notes When? By Whom? 0.1 Creation 08/22/2000 Rafael H. Schloming 0.2 Initial Revision 08/30/2000
+ Document Revision # Action Taken, Notes When? By Whom? 0.1 Creation 08/22/2000 Rafael H. Schloming 0.2 Initial Revision 08/30/2000
Mark Thomas
0.3 Additional revisions; tried to clarify membership/compostion 09/08/2000
Mark Thomas
Index: openacs-4/packages/acs-core-docs/www/groups-requirements.html
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/groups-requirements.html,v
diff -u -r1.33 -r1.33.2.1
--- openacs-4/packages/acs-core-docs/www/groups-requirements.html 31 Jul 2011 23:11:45 -0000 1.33
+++ openacs-4/packages/acs-core-docs/www/groups-requirements.html 21 Aug 2013 10:19:22 -0000 1.33.2.1
@@ -1,60 +1,60 @@
-
- user_groups
table may contain the
+ group_id
of a parent group, but parent-child relationship
support is limited because it only allows one kind of relationship between
groups to be represented. Moreover, the Oracle database's limited support
for tree-like structures makes the queries over these relationships
expensive.scope
, user_id
, and group_id
columns
was used to identify the party. One disadvantage of this design convention is
that it increases a data model's complexity by requiring the programmer
- to:scope
value of "group" but a null
+ group_id
)Tcl
and PL/SQL
+ functions and procedures to check both the user_id
and
+ group_id
valuesDocument Revision # Action Taken, Notes When? By Whom? 0.1 Creation 08/16/2000 Rafael Schloming 0.2 Initial revision 08/19/2000 Mark Thomas 0.3 Edited and reviewed, conforms to requirements template 08/23/2000 Kai Wu 0.4 Further revised, added UI requirements 08/24/2000 Mark Thomas 0.5 Final edits, pending freeze 08/24/2000 Kai Wu 0.6 More revisions, added composition requirements 08/30/2000 Mark Thomas 0.7 More revisions, added composition requirements 09/08/2000 Mark Thomas where
clause, whatever mechanism is used to check membership in SQL
+ should be fairly small and simple.Document Revision # Action Taken, Notes When? By Whom? 0.1 Creation 08/16/2000 Rafael Schloming 0.2 Initial revision 08/19/2000 Mark Thomas 0.3 Edited and reviewed, conforms to requirements template 08/23/2000 Kai Wu 0.4 Further revised, added UI requirements 08/24/2000 Mark Thomas 0.5 Final edits, pending freeze 08/24/2000 Kai Wu 0.6 More revisions, added composition requirements 08/30/2000 Mark Thomas 0.7 More revisions, added composition requirements 09/08/2000 Mark Thomas Prev Home Next Running multiple services on one machine Up Staged Deployment for Production Networks
docs@openacs.orgPrev Home Next Running multiple services on one machine Up Staged Deployment for Production Networks
docs@openacs.orgcp /var/lib/aolserver/$OPENACS_SERVICE_NAME/packages/acs-subsite/www/index* /var/lib/aolserver/$OPENACS_SERVICE_NAME/www
/admin/permissions
and grant Create to Registered UsersAdmin
button.Parameters
link.IndexRedirectUrl
to be the URI of the desired application. For a default weblogger installation, this would be
. Note the trailing slash.weblogger/
/var/lib/aolserver/$OPENACS_SERVICE_NAME/www
. If an index page is not found there, the default index page for all subsites is used. To customize the code on the front page, copy the default index page from the Subsite package to the Main site and edit it:cp
/var/lib/aolserver/$OPENACS_SERVICE_NAME/packages/acs-subsite/www/index*
/var/lib/aolserver/$OPENACS_SERVICE_NAME/www
index.adp
to change the text; you shouldn't need to edit index.tcl
unless you are adding new functionality.<master>
set can_register_p [events::security::can_register_for_event_p -event_id $event_id]
return [permission::permission_p -party_id $user_id -object_id $event_id -privilege write]
<master>
default-master
for that subsite. For pages in /var/lib/aolserver/$OPENACS_SERVICE_NAME/www
, this is /var/lib/aolserver/$OPENACS_SERVICE_NAME/www/default-master.adp
and the associated .tcl file.
+ default-master
is itself a normal ADP page. It draws the subsite navigation elements and invokes site-master
(/var/lib/aolserver/$OPENACS_SERVICE_NAME/www/site-master.adp
and .tcl)site-master
draws site-wide navigation elements and invokes blank-master
(/var/lib/aolserver/$OPENACS_SERVICE_NAME/www/blank-master.adp
and .tcl). Blank-master
does HTML housekeeping and provides a framework for special sitewide navigation "meta" elements such as Translator widgets and Admin widgets.Registration: Deadline is 03/15/2004 10:00am.
+» Login or sign up to register for this event.
is visible. Click on "Login or sign up"
+ "You do not have permission to register for this event."
http://myserver.net/events/event-info.tcl
, so open the file /var/lib/aolserver/$OPENACS_SERVICE_NAME/packages/events/www/event-info.tcl
. It contains this line:set can_register_p [events::security::can_register_for_event_p -event_id $event_id]
return [permission::permission_p -party_id $user_id -object_id $event_id -privilege write]
Tip
Tip
/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.
-set title "Messages for $a(name) in $b(label)"
-set context [list [list . "SimPlay"] \
+
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.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._
), 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)"]
+ "Administer $a(name)"] \
+ "Messages for $a(name)"]
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%#>]
-
+
case_admin_page_title
was manually selected, because an autogenerated key for this text, with its substitute variables, would have been very confusing
+
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]]
-
grep -r "to_char.*H" *
-grep -r "to_date.*H" *
-
to_char(timestamp,'MM/DD/YYYY HH:MI:SS') as foo_date_pretty
to_char(timestamp,'YYYY-MM-DD HH24:MI:SS') as foo_date_ansi
-set foo_date_ansi [lc_time_system_to_conn $foo_date_ansi]
set foo_date_pretty [lc_time_fmt $foo_date_ansi "%x %X"]
grep -r "to_char.*H" *
+grep -r "to_date.*H" *
+
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
to_char(timestamp,'YYYY-MM-DD HH24:MI:SS') as foo_date_ansi
lc_time_system_to_conn
:
+set foo_date_ansi [lc_time_system_to_conn $foo_date_ansi]
lc_time_conn_to_system
.
+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"]
_pretty
version in your ADP page.
+ man
+ strftime
).
+ lc_numeric $value
, which formats the number using the appropriate decimal point and thousand separator for the locale.
+
acs-lang/bin/check-catalog.sh package_key
-
+
<p class="form-help-text"><b>Invitations</b> are sent,
- when this wizard is completed and casting begins.</p>
<p class="form-help-text"> <#Invitations_are_sent <b>Invitations</b> are sent,
+
if
command at the end of a word which adds "s" if a count is anything but 1. This pluralizes nouns correctly based on the data. However, it is confusing to read and, when internationalized, may result in message keys that are both confusing and impossible to set correctly in some languages. While internationalizing, watch out that the automate converter does not create such keys. Also, refactor compound text as you encounter it. <p class="form-help-text"><b>Invitations</b> are sent,
+ when this wizard is completed and casting begins.</p>
<p class="form-help-text"> <#Invitations_are_sent <b>Invitations</b> are sent,
when this wizard is completed and casting begins.#>
- </p>
Select which case <if @simulation.casting_type@ eq "open">and
+ </p>
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>
+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.
<if @simulation.casting_type@ eq "open">
+@simulation.casting_type@ eq "open">and role</if> when the
+simulation begins.
<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
@@ -96,7 +96,7 @@
begins.
</else>
<if @components.view_bugs_url@ not nil>
- <a href="@components.view_bugs_url@" title="View the @pretty_names.bugs@ for this component">
+ <a href="@components.view_bugs_url@" title="View the @pretty_names.bugs@ for this component">
</if>
@components.num_bugs@
<if @components.num_bugs@ eq 1>
@@ -110,7 +110,7 @@
</if>
<if @components.view_bugs_url@ not nil>
-<a href="@components.view_bugs_url@" title="#bug-tracker.View_the_bug_fo_component#">
+<a href="@components.view_bugs_url@" title="#bug-tracker.View_the_bug_fo_component#">
</if>
@components.num_bugs@
<if @components.num_bugs@ eq 1>
@@ -124,39 +124,39 @@
</if>
<if @components.view_bugs_url@ not nil>
<if @components.num_bugs@ eq 1>
- <a href="@components.view_bugs_url@" title="#bug-tracker.View_the_bug_fo_component#">#bug-tracker.one_bug#</a>
+ <a href="@components.view_bugs_url@" title="#bug-tracker.View_the_bug_fo_component#">#bug-tracker.one_bug#</a>
</if><else>
- <a href="@components.view_bugs_url@" title="#bug-tracker.View_the_bug_fo_component#">#bug-tracker.N_bugs#</a>
+ <a href="@components.view_bugs_url@" title="#bug-tracker.View_the_bug_fo_component#">#bug-tracker.N_bugs#</a>
</else>
-</if>
multirow append links "New [bug_tracker::conn Bug]"
multirow append links "[_ bug-tracker.New] [bug_tracker::conn Bug]"
set bug_label [bug_tracker::conn Bug]
-multirow append links "[_ bug-tracker.New_Bug]" "${url_prefix}bug-add"
<a href="@past_version.maintainer_url@" title="#bug-tracker.Email# @past_version.maintainer_email@">
-@past_version.maintainer_first_names@ @past_version.maintainer_last_name@</a>
multirow append links "New [bug_tracker::conn Bug]"
multirow append links "[_ bug-tracker.New] [bug_tracker::conn Bug]"
set bug_label [bug_tracker::conn Bug]
+multirow append links "[_ bug-tracker.New_Bug]" "${url_prefix}bug-add"
"New %bug_label%"
. This gives translators more control over the phrase.<a href="@past_version.maintainer_url@" title="#bug-tracker.Email# @past_version.maintainer_email@">
+@past_version.maintainer_first_names@ @past_version.maintainer_last_name@</a>
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.workflow::case::add_log_data \
+ across different locales.
workflow::case::add_log_data \
-entry_id $entry_id \
- -key "resolution" \
+ -key "resolution" \
-value [db_string select_resolution_code {}]
workflow::case::add_log_data \
-entry_id $entry_id \
- -key "[_ bug-tracker.resolution]" \
- -value [db_string select_resolution_code {}]
{show_patch_status "open"}
{show_patch_status "[_ bug-tracker.open]"}
-<msg key="You">You can filter by this %component_name% by viisting %filter_url_string%</msg>
-<msg key="You_1">You do not have permission to map this patch to a bug. Only the submitter of the patch
+ -key "[_ bug-tracker.resolution]" \
+ -value [db_string select_resolution_code {}]
resolution
is a keyword in a table and in the code, so this breaks the code. It should not have been internationalized at all. Here's another example of text that should not have been internationalized:{show_patch_status "open"}
{show_patch_status "[_ bug-tracker.open]"}
+<msg key="You">You can filter by this %component_name% by viisting %filter_url_string%</msg>
+<msg key="You_1">You do not have permission to map this patch to a bug. Only the submitter of the patch
and users with write permission on this Bug Tracker project (package instance) may do so.</msg>
-<msg key="You_2">You do not have permission to edit this patch. Only the submitter of the patch
-and users with write permission on the Bug Tracker project (package instance) may do so.</msg>
<msg key="Fix">for version</msg>
-<msg key="Fix_1">for</msg>
-<msg key="Fix_2">for Bugs</msg>
<msg key="Fix">for version</msg>
+<msg key="Fix_1">for</msg>
+<msg key="Fix_2">for Bugs</msg>
Bug-tracker component maintainer"
was converted to "[_ bug-tracker.Bug-tracker]"
. Instead, it should be bug_tracker_component_maintainer
.set title "Patch \"$patch_summary\" is nice."
<msg>Patch \"$patch_summary\" is nice.</msg>
<msg>Patch "$patch_summary" is nice.</msg>
set title "Patch \"$patch_summary\" is nice."
<msg>Patch \"$patch_summary\" is nice.</msg>
<msg>Patch "$patch_summary" is nice.</msg>
array set names { key "Pretty" ...}
array set names { key "[_bug-tracker.Pretty]" ...}
array set names [list key [_bug-tracker.Pretty] ...]
Prev Home Next How Internationalization/Localization works in OpenACS Up Design Notes
docs@openacs.orgarray set names { key "Pretty" ...}
array set names { key "[_bug-tracker.Pretty]" ...}
array set names [list key [_bug-tracker.Pretty] ...]
Prev Home Next How Internationalization/Localization works in OpenACS Up Design Notes
docs@openacs.orgad_conn locale
. The request processor sets this by calling lang::conn::locale
, which looks for the following in order of precedence:Accept-Language
HTTP header)_
function. In both cases, if the requested locale is not found but a locale which is the default for the language which matches your locale's language is
found, then that locale is offered instead.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.#package_key.message_key#
<trn
+ key="package_key.message_key"
+ locale="locale">default
+ text</trn>
<#message_key
+ original text#>
\#package_key.message_key\#
. In Tcl
files all message lookups *must* be on either of the following formats:
[_ package_key.message_key]
- The message key and package key used here must be string literals, they can't result from variable evaluation.[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.[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])]
-
+
# Find text in double quotes
-find -iname '*.tcl'|xargs egrep -i '"[a-z]'
+
find -iname '*.tcl'|xargs egrep -i '"[a-z]'
# Find untranslated text in form labels, options and values
-find -iname '*.tcl'|xargs egrep -i '\-(options|label|value)'|egrep -v '<#'|egrep -v '\-(value|label|options)[[:space:]]+\$[a-zA-Z_]+[[:space:]]*\\?[[:space:]]*$'
+find -iname '*.tcl'|xargs egrep -i '\-(options|label|value)'|egrep -v '<#'|egrep -v '\-(value|label|options)[[:space:]]+\$[a-zA-Z_]+[[:space:]]*\\?[[:space:]]*$'
# Find text in page titles and context bars
-find -iname '*.tcl'|xargs egrep -i 'set (title|page_title|context_bar) '|egrep -v '<#'
+find -iname '*.tcl'|xargs egrep -i 'set (title|page_title|context_bar) '|egrep -v '<#'
# Find text in error messages
-find -iname '*.tcl'|xargs egrep -i '(ad_complain|ad_return_error)'|egrep -v '<#'
+find -iname '*.tcl'|xargs egrep -i '(ad_complain|ad_return_error)'|egrep -v '<#'
+ ad_return_complaint 1 "Error: A [parameter::get -parameter classes_pretty_name]
+ must have <em>no</em>[parameter::get -parameter class_instances_pretty_plural] to be deleted"
+
was replaced by:
-
+
set subject [parameter::get -localize -parameter classes_pretty_name]
set class_instances [parameter::get -localize -parameter class_instances_pretty_plural]
ad_return_complaint 1 [_ dotlrn.class_may_not_be_deleted]
-
+
-set msg_subst_list [list subject [parameter::get -localize -parameter classes_pretty_name] class_instances [parameter::get -localize -parameter class_instances_pretty_plural]]
+
set msg_subst_list [list subject [parameter::get -localize -parameter classes_pretty_name] class_instances [parameter::get -localize -parameter class_instances_pretty_plural]]
ad_return_complaint 1 [_ dotlrn.class_may_not_be_deleted $msg_subst_list]
-
+
# Message tags should usually not be in curly braces since then the message lookup may not be
# executed then (you can usually replace curly braces with the list command). Find message tags
# in curly braces (should return nothing, or possibly a few lines for inspection)
-find -iname '*.tcl'|xargs egrep -i '\{.*<#'
+
find -iname '*.tcl'|xargs egrep -i '\{.*<#'
# Check if you've forgotten space between default key and text in message tags (should return nothing)
-find -iname '*.tcl'|xargs egrep -i '<#_[^ ]'
+find -iname '*.tcl'|xargs egrep -i '<#_[^ ]'
# Review the list of tcl files with no message lookups
-for tcl_file in $(find -iname '*.tcl'); do egrep -L '(<#|\[_)' $tcl_file; done
+for tcl_file in $(find -iname '*.tcl'); do egrep -L '(<#|\[_)' $tcl_file; done
/acs-lang/admin/set-system-timezone
and readable at
- lang::system::timezone.. When
+ lang::system::timezone.
. When
retrieved from the database and displayed, dates and times must
be localized to the user's locale.
- Parameter Name Parameter Value class_instance_pages_csv #dotlrn.class_page_home_title#,Simple 2-Column;#dotlrn.class_page_calendar_title#,Simple 1-Column;#dotlrn.class_page_file_storage_title#,Simple 1-Column departments_pretty_name #departments_pretty_name# Parameter Name Parameter Value class_instance_pages_csv #dotlrn.class_page_home_title#,Simple 2-Column;#dotlrn.class_page_calendar_title#,Simple 1-Column;#dotlrn.class_page_file_storage_title#,Simple 1-Column departments_pretty_name #departments_pretty_name# Command used to retrieve Value Retrieved Value parameter::get -localize -parameter class_instances_pages_csv Kurs Startseite,Simple 2-Column;Kalender,Simple 1-Column;Dateien,Simple 1-Column parameter::get -localize -parameter departments_pretty_name Abteilung parameter::get -parameter departments_pretty_name #departments_pretty_name# Command used to retrieve Value Retrieved Value parameter::get -localize -parameter class_instances_pages_csv Kurs Startseite,Simple 2-Column;Kalender,Simple 1-Column;Dateien,Simple 1-Column parameter::get -localize -parameter departments_pretty_name Abteilung parameter::get -parameter departments_pretty_name #departments_pretty_name# /acs-lang/admin/
Prev Home Next Internationalization and Localization Overview Up How to Internationalize a Package
docs@openacs.orgStage Task Who Internationalization Package Developer uses the acs-lang tools to replace all visible text in a package with message keys. (More information) Package Developer Release Management The newly internationalized package is released. Package Developer The translation server is updated with the new package. Translation server maintainers Localization Translators work in their respective locales to write text for each message key. (More information) Translators Release Management The translated text in the database of the translation server is compared to the current translations in the OpenACS code base, conflicts are resolved, and the new text is written to catalog files on the translation server. Translation server maintainers The catalog files are committed to the OpenACS code base. Translation server maintainers A new version of OpenACS core and/or affected packages is released and published in the OpenACS.org repository. Release Manager Upgrading Site Administrators upgrade their OpenACS sites, either via the automatic upgrade from the Repository or via tarball or CVS Site Administrators Site Administrators import the new translations. Existing local translations, if they exist, are not overwritten. Site Administrators Prev Home Next Chapter 12. Internationalization Up How Internationalization/Localization works in OpenACS
docs@openacs.orgStage Task Who Internationalization Package Developer uses the acs-lang tools to replace all visible text in a package with message keys. (More information) Package Developer Release Management The newly internationalized package is released. Package Developer The translation server is updated with the new package. Translation server maintainers Localization Translators work in their respective locales to write text for each message key. (More information) Translators Release Management The translated text in the database of the translation server is compared to the current translations in the OpenACS code base, conflicts are resolved, and the new text is written to catalog files on the translation server. Translation server maintainers The catalog files are committed to the OpenACS code base. Translation server maintainers A new version of OpenACS core and/or affected packages is released and published in the OpenACS.org repository. Release Manager Upgrading Site Administrators upgrade their OpenACS sites, either via the automatic upgrade from the Repository or via tarball or CVS Site Administrators Site Administrators import the new translations. Existing local translations, if they exist, are not overwritten. Site Administrators Prev Home Next Chapter 14. Internationalization Up How Internationalization/Localization works in OpenACS
docs@openacs.orgORDER BY
clauses in
queries.