In addition to mapping an entire tree to an object, admins have the option
of mapping only a subtree of an existing tree. To do that, they have to click on
a "Map subtree" link, after which they will see a list of tree nodes.
The mapped subtree will consist of all subcategories of the category
the user selected - the category itself will not be included.
Note that the mapped subtree will not be a new tree. Therefore,
this option should be used only if an admin plans to use the subtree
as-is and has no intention of making changes to it.
An alternative solution is available for admins who want to
create a tree by copying one of the existing trees and subsequently
playing around with it (moving/adding/deleting categories).
To accomplish that, they would have to create a new tree,
go to the admin page for this tree and click on a "Copy existing
tree" link. They will see a list of available trees to copy. Clicking on the "Copy this one" link will result
in creating copies of the categories from the source
trees and placing them in the new tree.
This operation
can be performed several times, each time the copied
categories will be placed as toplevel categories of the tree.
As far as unmapping is concerned, this operation doesn't delete the mapping between categories and objects.
Permissions
The creator of the category tree is granted the category_tree_read, category_tree_write
and category_tree_grant_permissions privileges.
The operations one can perform on categories are:
ad (d) You cannot delete a category that has children.
Also, you cannot delete a category that has objects mapped to it (do we want it or not?)
ad (e) The effect of phasing out a category is that users no longer will be able to associate objects
with it, but existing associations will still be visible
Deletions and phasing it/out can be performed as bulk operations.
ad (f) sort key is used to order children of the same parent category,
that is the elements of the tree are sorted first by parent, then
by the sort key.
This table actually stores the information whether the tree is side-wide or not.
create table category_trees ( tree_id integer primary key constraint cat_trees_tree_id_fk references acs_objects on delete cascade, site_wide_p char(1) default 't' constraint cat_trees_site_wide_p_ck check (site_wide_p in ('t','f')) );
Here the tree's name and description is stored in different translations.
create table category_tree_translations ( tree_id integer constraint cat_tree_trans_tree_id_fk references category_trees on delete cascade, locale varchar2(5) not null constraint cat_tree_trans_locale_fk references ad_locales, name varchar2(50) not null, description varchar2(1000), primary key (tree_id, locale) );
This table stores the tree hierarchy by holding the information about the parent category. The tree is ordered by a nested index (left_ind, right_ind). Sorting is thus accomplished by means of a nested set. You can read a description of how nested sets work. This also describes how to write queries that sort correctly when using categories.
create table categories ( category_id integer primary key constraint cat_category_id_fk references acs_objects on delete cascade, tree_id integer constraint cat_tree_id_fk references category_trees on delete cascade, parent_id integer constraint cat_parent_id_fk references categories, deprecated_p char(1) default 'f' constraint cat_deprecated_p_ck check (deprecated_p in ('t','f')), left_ind integer, right_ind integer );
Here the actual categories are stored together with different translations.
create table category_translations ( category_id integer constraint cat_trans_category_id_fk references categories on delete cascade, locale varchar2(5) not null constraint cat_trans_locale_fk references ad_locales, name varchar2(200), description varchar2(4000), primary key (category_id, locale) );
This table contains mapping between categories and objects
create table category_object_map ( category_id integer constraint cat_object_map_category_id_fk references categories on delete cascade, object_id integer constraint cat_object_map_object_id_fk references acs_objects on delete cascade, primary key (object_id, category_id) ) organization index;
This is the table for the relation of trees and objects. subtree_category_id comes to play in situations when you map a subtree of an existing tree to an object.
create table category_tree_map ( tree_id integer constraint cat_tree_map_tree_id_fk references category_trees on delete cascade, object_id integer constraint cat_tree_map_object_id_fk references acs_objects on delete cascade, subtree_category_id integer default null constraint cat_tree_map_subtree_id_fk references categories, primary key (object_id, tree_id) ) organization index;
Known Limitations
Integration with other packages
Here are the changes needed to be made to integrate with other packages.
index.adp
Provide an admin-link to
/categories/cadmin/one-object?object_id=@package_id@ to let admins
map trees to the package instance.
form-page.tcl
Use this in ad_form to display all mapped category trees and
selected categories (if editing an object):
{category_ids:integer(category),multiple,optional {label "Categories"} {html {size 4}} {value {$object_id $package_id}}}Alternatively, you can include the following in your adp:
<include src="/packages/categories/www/include/widget" object_id=@object_id@ package_id=@package_id@>In the processing part of ad_form use:
category::map_object -remove_old -object_id $object_id $category_ids