Index: openacs-4/packages/acs-core-docs/www/tutorial-advanced.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/tutorial-advanced.html,v diff -u -N -r1.14.2.12 -r1.14.2.13 --- openacs-4/packages/acs-core-docs/www/tutorial-advanced.html 2 Feb 2004 18:10:57 -0000 1.14.2.12 +++ openacs-4/packages/acs-core-docs/www/tutorial-advanced.html 10 Feb 2004 13:19:06 -0000 1.14.2.13 @@ -1,10 +1,10 @@ -Advanced Topics

Advanced Topics

by Joel Aufrecht

+Advanced Topics

Advanced Topics

by Joel Aufrecht

OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff.

This tutorial covers topics which are not essential to creating a minimal working package. Each section can be used independently of all of the others; all sections assume that - you've completed the basic tutorial.

Write the Requirements and Design Specs

It's time to document. For the tutorial we'll use + you've completed the basic tutorial.

Write the Requirements and Design Specs

It's time to document. For the tutorial we'll use pre-written documentation. When creating a package from scratch, start by copying the documentation template from /var/lib/aolserver/openacs-dev/packages/acs-core-docs/xml/docs/xml/package-documentation-template.xml @@ -54,7 +54,7 @@ Writing bi01.html for bibliography Writing index.html for book [service0 xml]$

Verify that the documentation was generated and reflects - your changes by browsing to http://yoursite:8000/myfirstpackage/doc

Add the new package to CVS

Before you do any more work, make sure that your work is + your changes by browsing to http://yoursite:8000/myfirstpackage/doc

Add the new package to CVS

Before you do any more work, make sure that your work is protected by putting it all into cvs. The cvs add command is not recursive, so you'll have to traverse the directory tree manually and add as you go. (More on @@ -114,7 +114,7 @@ initial revision: 1.1 done (many lines omitted) -[service0 myfirstpackage]$

Adding Comments

You can track comments for any ACS Object. Here we'll track +[service0 myfirstpackage]$

Adding Comments

You can track comments for any ACS Object. Here we'll track comments for notes. On the note-edit.tcl/adp pair, which is used to display individual notes, we want to put a link to add comments at the bottom of the screen. If there are any comments, we want to @@ -135,7 +135,7 @@ there are comments. Then you pass the note id, which is also the acs_object id.

We put our two new variables in the note-edit.adp page.

<a href="@comment_add_url@">Add a comment</a>
- @comments_html@

Admin Pages

+ @comments_html@

Admin Pages

There are at least two flavors of admin user interface:

  • Admins use same pages as all other users, except that they are offered admin links and buttons where appropriate. @@ -212,7 +212,7 @@ <if @admin_p@ ne nil> <a href="@admin_url@">@admin_title@</a> </if> -

Categories

You can associate any ACS Object with one or more categories. +

Categories

You can associate any ACS Object with one or more categories. In this tutorial we'll show how to equip your application with user interface to take advantage of the Categories service.

@@ -237,23 +237,18 @@ way for administrators of your application to choose which category trees are applicable for the application.

-

-

The way to achieve this is is to provide a link to the Category Management pages. Add the following snippet to your /var/lib/aolserver/service0/packages/myfirstpackage/www/admin/index.tcl file: -

 set category_map_url [export_vars -base \
     "[site_node::get_package_url -package_key categories]cadmin/one-object" \
         { { object_id $package_id } }]
           

-

and the following snippet to your /var/lib/aolserver/service0/packages/myfirstpackage/www/admin/index.adp file: -

 <li><a href="@category_map_url@"
       class="action_link">Site-Wide Categories</a>
@@ -325,16 +320,22 @@
     ad_script_abort
 }
           

-

Prepare the package for distribution.

Browse to the package manager. Click on +

Profile your code

There are several facilities for profiling your code in + OpenACS. The first thing to do is to install the + developer-support package and play around with it. But there + is also support in the API for profiling your code: + profiling + your code using ds_profile +

Prepare the package for distribution.

Browse to the package manager. Click on tutorialapp.

Click on Generate a distribution file for this package from the filesystem. -

Click on the file size +

Click on the file size (37.1KB) after the label Distribution File: and save the file to - /tmp.

-

Notifications

by David Bell and Simon Carstensen

+ /tmp.

+

Notifications

by David Bell and Simon Carstensen

OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff.

The notifications package allows you to send notifications through any @@ -441,7 +442,85 @@ parameter is what appears at the end of the text returned (i.e. "... request notification</a> for pretty_name"), The url parameter should be set to the address we want the user to be redirected to after they have finished the subscription process.

This should be all you need to implement a notification system. For more examples - look at the forums package.

Future Topics:

  • How to enforce security so that users can't + look at the forums package.

Hierarchical data

by Jade Rubick + with help from many people in the OpenACS community

+ OpenACS docs are written by the named authors, and may be edited + by OpenACS documentation staff. +

One of the nice things about using the OpenACS object system + is that it has a built-in facility for tracking hierarchical data + in an efficient way. The algorithm behind this is called + tree_sortkey.

Any time your tables are subclasses of the acs_objects + table, then you automatically get the ability to structure them + hierarchically. The way you do this is currently via the + context_id column of + acs_objects (Note that there is talk of adding in a + parent_id column instead, because + the use of context_id has been + ambiguous in the past). So when you want to build your hierarchy, + simply set the context_id values. Then, when you want to make + hierarchical queries, you can do them as follows:

+      db_multirow categories blog_categories "
+      SELECT
+      c.*,
+      o.context_id,
+      tree_level(o.tree_sortkey)
+      FROM
+      blog_categories c,
+      acs_objects o
+      WHERE
+      c.category_id = o.object_id
+      ORDER BY
+      o.tree_sortkey"
+    

Note the use of the + tree_level() function, which + gives you the level, starting from 1, 2, 3...

Here's an example, pulling all of the children for a given + parent:

+      SELECT 
+      children.*,
+      tree_level(children.tree_sortkey) -
+        tree_level(parent.tree_sortkey) as level
+      FROM 
+      some_table parent, 
+      some_table children
+      WHERE 
+      children.tree_sorktey between parent.tree_sortkey and tree_right(parent.tree_sortkey)
+      and parent.tree_sortkey <> children.tree_sortkey
+      and parent.key = :the_parent_key;
+      

The reason we substract the parent's tree_level from the + child's tree_level is that the tree_levels are global, so if you + want the parent's tree_level to start with 0, you'll want the + subtraction in there. This is a reason you'll commonly see magic + numbers in tree_sortkey SQL queries, like + tree_level(children.tree_sortkey) - + 4. That is basically an incorrect way to do it, + and subtracting the parent's tree_level is the preferred method.

This example does not include the parent. To return the entire subtree including the parent, leave out the non-equals clause:

+      SELECT
+      subtree.*,
+      tree_level(children.tree_sortkey) -
+        tree_level(parent.tree_sortkey) as level
+      FROM some_table parent, some_table subtree
+      WHERE 
+      subtree.tree_sorktey between parent.tree_sortkey and tree_right(parent.tree_sortkey)
+      and parent.key = :the_parent_key;
+    

If you are using the Content Repository, you get a similar + facility, but the parent_id + column is already there. Note you can do joins with + tree_sortkey:

+      SELECT
+      p.item_id,
+      repeat(:indent_pattern, (tree_level(p.tree_sortkey) - 5)* :indent_factor) as indent,
+      p.parent_id as folder_id,
+      p.project_name
+      FROM pm_projectsx p, cr_items i
+      WHERE p.project_id = i.live_revision
+      ORDER BY i.tree_sortkey
+    

This rather long thread explains How + tree_sortkeys work and this paper describes + the technique for tree_sortkeys, although the OpenACS + implementation has a few differences in the + implementation, to make it work for many languages and the + LIKE construct in Postgres. +

Future Topics:

  • How to enforce security so that users can't change other users records

  • How to use the content management tables so that ... what?

  • How to change the default stylesheets for Form Builder HTML forms.

  • How to make your package searchable with OpenFTS/Oracle

  • How to prepare pagelets for inclusion in other pages

  • How and when to put procedures in a tcl procedure library

  • More on ad_form - data validation, other stuff.