ad_new_stuff_module_list
Let's take faq module (Frequently Asked Questions) as an example. Its files are stored in three directories: /faq, /faq/admin and /admin/faq. We need these three separate directories in order to support three levels of access to the module data: public, module administrator and site-wide administrator. Pages in /faq are public pages showing questions and answers. Pages in /faq/admin are used by module admistrator to add, edit or remove faq questions and answers. Pages in /admin/faq are provided for site-wide administrator who may need to add or delete whole faqs, collect faq module statistics (e.g, how many people used the faq module in the previous month) and be able to do other operations refering to the whole faq module and not just to an instance of it.
Data model for the module should reside in /doc/sql directory (e.g. /doc/sql/faq.sql for faq module). Data modeling is the hardest and most important part of any module. If you get the data model wrong, your module might not do what users need, it might be unreliable, and it might fill up the database with garbage. In order to support module customization and module scoping, your data model needs to conform with ACS standards (see Module Customization and Scoping sections bellow for the changes you need to make to your data model). All tables, sequences, functions, triggers, views, etc. should be prefixed with the module name or its abbreviation in order to avoid naming conflicts (e.g. faq_q_and_a for faq questions and answers).
All the Tcl functions you write for your module should go to your private tcl directory (e.g. faq module has its Tcl functions stored in faq-defs.tcl). Procedures should be prefixed with the module name or its abbreviation (e.g. faq_maintainer_p), in order to avoid naming conflicts. If you think you wrote a generic Tcl function that everybody can use, then you can send e-mail to jsc@mit.edu and suggest that your function becomes a part of ArsDigita Toolkit utility functions.
Module customization includes parameters that are used by the whole module.
These parameters should be put in configuration file your_server_name.ini
in the parameters directory.
For download module, parameters in configuration file look like this:
These parameters can be accessed from within the code using the
[ns/server/yourservername/acs/download]
; root directory of the downloadable files
DownloadRoot=/web/photonet-dev/download/
ad_parameter
function.
An ACS module is a collection of sql table definitions supported by HTML interface. An instance of a module uses this table definitions and HTML interface to present a module functionality to the user. For example, an instance of chat module is a chat room, an instance of a bulletin board is a bulletin board for a certain topic and an instance of faq module is a faq collection, such as, AOL Server FAQ or Novice Photographers FAQ. Note that not all modules support multiple instances (e.g. eccomerce module has only one instance). Modules supporting multiple instances should have parameters kept in columns of the table where module instances are defined. For chat module, instances are chat rooms and parameters are columns in the chat_rooms table. For example, parameter that determines whether chat room should be moderated is kept in the moderated_p column of the chat_rooms table. Parameter moderated_p configures an instance of the chat module and not the whole chat module. When using parameters, you should make decision whether parameter should be associated with module and be put in parameters file or associated with a particular instance of the module and be stored in the database.
ArsDigita standard defines three scopes: public, group and user.
create table faqs (
faq_id integer primary key,
-- name of the FAQ.
faq_name varchar(250) not null,
-- group the viewing may be restricted to
group_id integer references user_groups,
-- permissions can be expanded to be more complex later
scope varchar(20),
-- insure consistant state
constraint faq_scope_check check ((scope='group' and group_id is not null)
or (scope='public' and group_id null))
);
Notice that faqs don't support user scope, so user_id is ommited and faq_scope_check
restricts scope to public and group only.
insert into acs_modules
(module_key, pretty_name, public_directory, admin_directory, site_wide_admin_directory, module_type, supports_scoping_p, documentation_url, data_model_url)
values
('news', 'News', '/news', '/news/admin', '/admin/news', 'system', 't', '/doc/news.html', '/doc/sql/news.sql');
ad_scope_header
, ad_scope_footer
and
ad_scope_context_bar
instead of
ad_header
, ad_footer
and
ad_context_bar
. ad-scope.tcl also defines a powerful
security procedure ad_scope_authorize
, which
authorizes a user for specified action and specified scope. If you
don't understand this scope stuff, take a look at files in /faq
and /faq/admin directories for examples of files implementing
embedding interface.