|
From: clayton c. <cc...@ca...> - 2001-04-10 16:07:33
|
One of the greatest benefits of modular code is incremental utility, i.e. i
can add what i need, when i need it, with minimum impact to the base system.
An issue this raises is how newer features integrate into the base in a way
that other parts of the system can benefit from the new functionality.
Suppose, for example, we're running a site that allows users to create
communities. We currently have a calendar module, but later we decide to add
an address book and photoalbum. How do we associate the community user group
with these modules ? The way most people do it, unfortunately, is to modify
the schema of the group and insert foreign keys pointing to the tables
containing the data for the given modules. In my opinion phpWS should be
designed in a way that no end-user (site-operator) should ever have to
manipulate the schema (if they want to is another matter).
ACS (ArsDigita Community System) deals with this issue is through
scoping. Every module which needs to be able to associate itself with
another entity in the system does the following :
1) decide on the level of granularity of association. For instance with a
photo-album, do we want to associate an album with a user group, or single
photos.
2) based on 1, we modify the table representing the entity (album or photo)
being associated to contain the following additional fields :
scope varchar(12) -- [1] can be "user", "group",
"table", "system"
user_id int -- id of user if scope == "user"
group_id int -- id of group if scope == "group"
table varchar(64) -- table name, if scope is "table"
3) every time updates are made, we simply fill in these fields in a manner
appropriate to the scope. So for instance, to add a photoalbum to user #10's
account :
insert into pws_albums(scope,user_id,attr1,attr2) values
('user',10,$value1,$value2)
4) the module table will contain the following extra fields :
is_scoped char - "t" or "f"
item_type_name varchar(200) e.g. Photo Album
type_name_plural varchar(200) e.g. Photo Albums
item_table_name varchar(64) -- table containing the
entity e.g. pws_albums
item_id_field varchar(64) -- name of PK
field
what this allows us to do is to traverse all scoped modules to answer
questions like "what modules can be associated with a user/group etc. "
the last 4 fields are for easy UI and automatic query generation. For
instance consider the following
/* get ids of all groups who use a module */
function getModuleGroups($moduleId) {
$sql = "select * from pws_modules where moduleId=$moduleId";
$result = db_query($sql);
$row = db_fetcharray($result);
db_free_result($result);
$table = $row['item_table_name'];
$field = $row['item_id_field'];
$sql = "select $table.group_id, pws_groups.name from $table, pws_groups
where $table.scope='group' " .
" and pws_groups.group_id = $table.group_id";
$result = db_query($result);
$list = array();
while ($row = db_fetcharray($result)) {
$list[] = $row;
}
db_free_result($result);
return $list;
}
/* get all modules related to a user */
function getUserModule($userId) {
$sql = "select * from pws_modules where is_scoped="t";
$result = db_query($sql);
$list = array();
while ($row = db_fetcharray($result)) {
$item_type = $row['item_name_plural'];
$id_field = $row['item_id_field'];
$table = $row['item_table_name'];
$sql = "select $id_field from $table where $table.scope='user' and
$table.user_id=$userId";
$result1 = db_query($sql);
$sublist = array()
while ($row = db_fetcharray($result1) {
$sublist[] = $row['$id_field'];
}
db_free_result($result1);
$list[] = array($item_type => $sublist)
};
db_free_result($result);
return $list;
}
As you can see, once implemented, there is no need to mess with the schema
as modules are added. And the module metadata makes it possible to have
generic routines for UIs and queries. i also have ideas on metadata
improvement to make this slightly better.
In addition ive semi-translated a file containing routines to support
scoping in PHP scripts (reading the needed variables from GETs and POSTs,
generating hidden vars and urls, etc). if you'd like id ask Todd to post it
to his site.
questions, comments, criticisms ? fire away ...
|