A user can be a member of more than one subcommunity (an employee is located at an office, works on one or more projects, and is a member of a team, within a department), so subsites provide an intuitive partitioning of information (to find out when a project is scheduled to launch, go to the project subsite; to learn about benefits, go to the HR department subsite; etc), improving the usability of the site as a whole.
This does not imply that navigating subsites is the only way for users to get information from subcommunities. Rather, the ACS also provides a user-centric portal (along the lines of My Yahoo!) that integrates relevant content from all subcommunities to which the user belongs. The real challenge is figuring out what is actually relevant to the user; doing this is what's known, in industry terms, as personalization. (New Stuff is a simple example of personalization, based on the assumption that most users will be interested in new content.) User profiling provides the foundation for really effective personalization.
create table subsites (
subsite_id constraint subsites_subsite_id_fk
references acs_objects (object_id),
owner constraint subsites_owner_fk
references acs_objects (object_id)
constraint subsites_owner_un
unique,
constraint subsites_pk
primary key (subsite_id)
);
For each type of subcommunity (i.e., acs_object_type),
you can define a subsite specification to designate packages that you
believe any subcommunity of that type will find useful. For example,
to build a family collaboration service along the lines of MyFamily.com, you (as the site
administrator) would:
acs_object_type
acs_object_type
The data model for subsite specifications is a simple table that
contains a row for each enabled (acs_object_type ,
package_id) pair:
create table subsite_specifications (
object_type constraint subsite_specs_object_type_fk
references acs_object_types (object_type),
package_id constraint subsite_specs_package_id_fk
references acs_packages (package_id),
constraint subsite_specs_pk
primary key (object_type, package_id)
);
subsite_package_instances for each package instance.
create table subsite_package_instances (
instance_id integer primary key,
subsite_id constraint subsite_pckg_inst_object_id_fk
references subsites (subsite_id),
package_id constraint subsite_pckg_inst_pckg_id_fk
references acs_packages (package_id),
constraint subsite_pckg_inst_un
unique (subsite_id, package_id)
);
subsite_specifications) is modified, e.g., a module is
added or removed. While it would be possible to provide automatic
propagation to subsites at the data model level, it is an overly
complex solution and not necessarily the most desirable one. The
simpler model is to have subsites branch irrevocably from their
templates upon creation. Then, when a template is changed, the
template administrator is given the ability to selectively propagate
the changes to child subsites. This is what the ACS implements.
party and
corresponding subsite. In this way, packages can be installed for the
site as a whole just as they are for subsites.
On the opposite extreme is the subcommunity of one, i.e., the individual user. By allowing for personal subsites, we can use standard packages to provide a Yahoo!-like suite of integrated services:
Although a degenerate case, personal subsites are handled in a standard manner within the data model (i.e. the owner of each personal subsite is an
Calendar - Yahoo! Calendar Address Book - Yahoo! Address Book Webmail - Yahoo! Mail Homepage - Yahoo! GeoCities
acs_object of acs_object_type "user".
general_permissions
row granting "administer" permission on the appropriate row in the
subsites table.
Responsibility can be delegated at either the subsite level (by
granting the "administrator" role to other group members) or the
package level (by inserting general_permissions rows
granting "administer" permission on the appropriate row in the
subsite_package_instance table).
This model of administration by itself does easily support the concept
of Site-Wide Administration as it has been known in ACS. The reason
for this is that administrators of the all_users subsite
woud by default only be able to administer the top-level site, but no
subsites. To achieve true Site-Wide Administration (i.e being able to
administer everything on a site), we add the special case
that administrators of the all_users subsite can also
administer any subsite. This method has the benefit of simple
implementation with the drawback that we can no longer support
top-level administration separate from site-wide administration.
/<object_type_plural>/<object_name>/
with subsite-wide administration pages at:
/<object_type_plural>/<object_name>/admin/
The path for a given subsite package is:
/<object_type_plural>/<object_name>/<package_url_stub>/
with package-level administration pages at:
/<object_type_plural>/<object_name>/<package_url_stub>/admin/
So, for instance, the URL for the Boston office's subsite on our
hypothetical corporate website would be:
http://www.company.com/offices/boston/
and news specific to the Boston office would be found at:
http://www.company.com/offices/boston/news/
Since the virtual directories that correspond to
acs_object_types appear directly under the actual page
root, there is the possibility of name collision with directories in
the filesystem. To address this, we log an error for each collision
detected when the server starts (which Watchdog will
then report to the site administrators) and give precedence to the
real directories.
The public site, being a special case, is served from directly under the page root. Continuing our example from above, company-wide news would appear at:
http://www.company.com/news/
/news/
should be served only public news (i.e., news items for the
all_users pseudo-subcommunity), while a visitor to
/offices/boston/news/ should be served only news items
specific to the Boston office subcommunity.
In order to make this work, we need to be able to relate entities to their enclosing subcommunities, which should be a straightforward process:
ad_conn API (to be determined)
to identify the enclosing subsite_id. This subsite_id will serve
as the "context" for the page.
acs_objects the
corresponding context_id is included. For top-level
items within a package, the context_id will be the subsite. For
other items the context_id will be another acs_object within the
subsite.
bboard_topics) will join with acs_objects
and include the corresponding subsite_id as a
criterion.
/offices/boston/bboard/ will do the following to display
a list of posts ot the Boston office bboard:
ad_conn to grab the subsite_id (which
references the subsite that is owned by the boston office party
object).
select t.topic, b.one-line, b.message
from bboard_topics t, bboard b, acs_objects o
where o.context_id = :subsite_id
and t.topic_id = o.object_id
and b.topic_id = t.topic_id
Note how the acs_objects table and
subsite_id are used to filter
the bboard topics to display.
For instance, an employee's contact information should be available both in the company directory (i.e., Address Book) and (at least, in part) on the subsites of her project(s), for access by the customer. Another example is Calendar: calendar events should "cascade" down, so that an employee's calendar is comprised of events from every level up the organizational hierarchy.
We make the simplifying assumption that each entity has exactly one
owning context (given by the context_id in acs_objects). However, we
represent relationships other than owning context between entities and
subsites by using the acs_rels table. In this manner, a
package can use acs_rels to grab content that is
"related" to a subsite but not actually a part of it.
For example, ...
In ACS, the relationships between these objects (department, team,
etc) are maintained in acs_rels which allows us to
express this rich hierarchy. However, the subsites for these objects
are not contained in that hierarchy. Instead they exists in a flat
plane parallel to that hierarchy such that no subsite is a parent or
child of another subsite.
Subsites for related objects can still share data using the method
described before. For example, the subsite for
the Operations department may share certain info with subsites for
teams within that department and vice-versa. However, this sharing of
information is explicit and outside of the object hierarchy. In the
future, implicit sharing between subsites based on object relationship
rules may be warranted.
API
subsites
create table subsites (
subsite_id constraint subsites_subsite_id_fk
references acs_objects (object_id)
constraint subsites_pk primary key
);
subsites_obj
create or replace view subsites_obj as select s.*, o.* from subsites s, acs_objects o where s.subsite_id = o.object_id;
subsite_specifications
create table subsite_specifications ( object_type constraint subsite_spec_object_type_fk references acs_object_types, package_id constraint subsite_spec_package_id_pk references apm_packages on delete cascade, constraint subsite_specifications_pk primary key(object_type, package_id) );
subsite_package_map
create table subsite_package_map ( subsite_id constraint spm_subsite_id_fk references subsites on delete cascade, package_id constraint spm_package_id_pk references apm_packages on delete cascade, constraint subsite_package_map_pk primary key(subsite_id, package_id) );
subsite.new(subsite_id, object_type, context_id)
(optional) subsite_id: ID of new subsite object
(optional) object_type: Object Type of new subsite
context_id: ID of acs_object that the new subsite is
for
context_id
subsite.delete(subsite_id)
subsite_id: ID of subsite to delete
subsite.for_object(object_id)
object_id: acs_object who's subsite we are looking for
subsite.url(subsite_id)
subsite_id: ID of the subsite whose url we want
acs_object_subsite
subsite.for_object(object_id)
acs_main_subsite
acs_subsite_url
subsite.url(subsite_id)
Last Modified: subsites.html,v 1.1 2001/01/21 01:39:50 bquinn Exp