Serving content is a basic function of any web site. +Common types of content include:
Note that the definition of content is not limited to what is +produced by the publisher. User-contributed content such as +reviews, comments, or message board postings may come to dominate +active community sites.
Regardless of its type or origin, it is often useful for +developers, publishers and users to handle all content in a +consistent fashion. Developers benefit because they can base all +their content-driven applications on a single core API, thereby +reducing the need for custom (and often redundant) development. +Publishers benefit because they can subject all types of content to +the same management and production practices, including access +control, workflow, categorization and syndication. Users benefit +because they can enjoy a single interface for searching, browsing +and managing their own contributions.
The content repository itself is intended only as a +common substrate for developing content-driven applications. It +provides the developer with a core set of content-related +services:
As a substrate layer, the content repository is not intended to +ever have its own administrative or user interface. ACS modules and +custom applications built on the repository remain responsible for +implementing an appropriate interface. (Note that the ACS Content +Management System provides a general interface for interacting with +the content repository).
The content repository was originally developed in the Spring of +2000 as a standalone data model. It was based on an earlier custom +system developed for an ArsDigita client. Many of the principle +design features of the original data model were also reflected in +the ACS Objects system implemented in the ACS 4.0 core. The content +repository was subsequently rewritten as an extension of ACS +Objects.
The content repository is a direct extension of the core ACS +Object Model. As such the same design tradeoffs apply.
The content repository stores all revisions of all content items +in a single table, rather than maintaining separate tables for +"live" and other revisions. The single-table approach dramatically +simplifies most operations on the repository, including adding +revisions, marking a "live" revision, and maintaining a full +version history. The drawback of this approach is that accessing +live content is less efficient. Given the ID of a content item, it +is not possible to directly access the live content associated with +that item. Instead, an extra join to the revisions table is +required. Depending on the production habits of the publisher, the +amount of live content in the repository may be eclipsed by large +numbers of infrequently accessed working drafts. The impact of this +arrangement is minimized by storing the actual content data in a +separate tablespace (preferably on a separate disk) from the actual +revisions table, reducing its size and allows the database server +to scan and read it more efficiently.
The Object Model provides a +graphic overview of the the how the content repository is designed. +The model links to pages of the API Guide that describe individual +objects. The Developer Guide describes how to address common +development tasks using the content repository.
Developer Guide
Object Reference
The content repository is a part of the core data model of ACS +4.0 and greater, and is loaded automatically as part of the ACS +installation process.
If you wish to install the content repository in a database +schema outside the context of ACS, the following instructions +apply.
First install the data model and PL/SQL API:
In additional to SQL and PL/SQL, the content repository +implements a limited set of key methods in Java. The XML import and +export methods are dependent on Oracle's XML Parser for Java v2, +available from the Oracle Technology Network:
http://technet.us.oracle.com/tech/xml/parser_java2/index.htmTo load the XML parser, download and untar the distribution. +Load the class package lib/xmlparserv2.jar into Oracle +from a shell prompt:
+$ loadjava -user user/password xmlparserv2.jar +
Finally, load the SQLJ files in +packages/acs-content-repository/java:
+$ loadjava -user user/password -resolve *.sqlj +
Installation of the data model and API should now be +complete.
The content repository relies on an Intermedia with the INSO +filtering option to search text within a wide variety of file +formats, including PDF and Microsoft Word. When the index on the +content column of cr_revisions is built, the INSO +filter automatically detects the file type of each entry and +extracts all available text for indexing.
If your searches are not returning any results even after +rebuilding the index, INSO filtering may be silently failing. You +can verifying this by checking for entries in the +ctx_user_index_errors view following an alter +index statement.
If you experience errors on a UNIX system, check the +following:
+ (SID_DESC = + (SID_NAME = PLSExtProc) + (ORACLE_HOME = /ora8/m01/app/oracle/product/8.1.6) + (ENVS = LD_LIBRARY_PATH=/ora8/m01/app/oracle/product/8.1.6/lib:/usr/lib:/lib:/usr/openwin/lib:/ora8/m01/app/oracle/product/8.1.6/ctx/lib) + (PROGRAM = extproc) + ) +
If your searches are still failing even after following these +instructions, try a simple test case +to determine whether the problem has something to do with the +content repository data model itself.
Even if you follow the instructions in the installation notes, content searches may +inexplicably fail to work. This document describes how to create a +simple test case independent of the content repository to verify +that Intermedia is indeed functioning properly.
Create a simple table to hold some test documents:
+create table cr_test_documents ( + doc_id integer primary key, + author varchar2(30), + format varchar2(30), + title varchar2(256), + doc blob +); +
Create an Intermedia preference to specify INSO filtering:
+begin + ctx_ddl.create_preference + ( + preference_name => 'CONTENT_FILTER_PREF', + object_name => 'INSO_FILTER' + ); +
If this preference has already been created, this step will +cause an error that you can ignore.
Create an Intermedia index on the test table with INSO +filtering:
+create index cr_test_documents_idx on cr_test_documents ( doc ) + indextype is ctxsys.context + parameters ('FILTER content_filter_pref' ); +
You can use SQL*Loader to load some documents into the test +table. First create a control file named +cr-test-docs.ctl:
+load data +INFILE 'cr-test-docs.data' +INTO TABLE cr_test_documents +APPEND +FIELDS TERMINATED BY ',' +(doc_id SEQUENCE (MAX,1), + format, + title, + ext_fname FILLER CHAR(80), + doc LOBFILE(ext_fname) TERMINATED BY EOF) +
Copy any number of documents (Microsoft Word, PDF, text, HTML, +etc.) to the file system of your database server. Create a data +file with an entry for each document you would like to load. This +is simply a comma-separated text file:
+word, Simple Story,sample-docs/simple.doc, +excel, Simple Spreadsheet,sample-docs/simple.xls +
Load the documents from the command line:
+$ sqlldr userid=cms/cms control=cr-test-docs.ctl log=cr-test-docs.log + +SQL*Loader: Release 8.1.6.2.0 - Production on Thu Nov 9 13:36:56 2000 + +(c) Copyright 1999 Oracle Corporation. All rights reserved. + +Commit point reached - logical record count 2 +
Once the documents have been loaded, rebuild the index and run +some test queries:
+SQL> alter index cr_test_documents_index rebuild online parameters ('sync'); +SQL> select score(1), doc_id from cr_test_documents + where contains(doc, 'cars', 1) > 0; + + SCORE(1) DOC_ID +---------- ---------- + 4 1 +
The content repository is an extension of the ACS Object Model. +The following diagram illustrates the relationship among the +standard object types defined by the content repository (click on a +box to view a description and API summary for a particular object +type):
Note that content revisions and content items inherit separately +from the root of the object model. Each item may be related to one +or more revisions, but they are fundamentally different types of +objects.
Also important to note is the relationship between custom +content types and the rest of the object model. You define new +content types as subtypes of Content Revision, not of Content Item. +This is because new content types are characterized by their +attributes, which are stored at the revision level to make changes +easy to audit. Custom content types typically do not require +additional unaudited attributes or methods beyond those already +provided by the Content Item type. It is thereful almost never +necessary to create a custom subtype of Content Item itself.
The content repository must be able to store objects in any +format, both text and binary. MIME types provide a standard set of +codes for identifying the file format of each content item. For the +purpose of data integrity, the repository must have a canonical +list of MIME types that may be assigned to content items.
A content type is characterized by a set of attributes +that may be associated with a text or binary content object. +Attributes are stored separately from their associated content +object, and as such may be indexed, searched, sorted and retrieved +independently. For example, attributes of a press release may +include a title, byline, and publication date.
The data model must support storage of descriptive information +for each content type:
++10.10 Content types must be associated with unique +keyword identifiers, such as press_release, so they can be +referenced in data tables, queries and procedural code.
+10.20 Content types must be associated with singular and +plural descriptive labels, such as Press Release and +Press Releases, to simplify user recognition.
+10.20 Content types may specify any number of +attributes. Attribute values are simple strings or +numbers.
+10.30 Content types may inherit attributes from any other +other content type. For example, a regional press release may be a +subtype of the press release type. Regional press releases have a +region attribute in addition to the characteristics of a +regular press release.
+10.40 Part of the definition of a content type may +include a description of the parent-child relationships allowed for +items of this type. For example, a Press Release may contain +one or more items of type Image, but it should not contain +any items of type Internal Financial Status Report.
+10.60 A content type definition may include a list of +allowed file MIME types for items of this type.
+10.70 A content type definition may include a list of +tokens to identify or flag relationships with other items. For +example, the content type definition for a chapter of a reference +manual may include the tokens next, previous and +see_also. Each type of relationship may include a minimum +and/or maximum number of relationships of this type that are +required for an item to be published.
+
Items are the fundamental building blocks of the content +repository. Each item represents a distinct text or binary content +object that is publishable to the web, such as an article, report, +message or photograph. An item my also include any number of +attributes with more structured data, such as title, source, byline +and publication date.
Content items have the following persistent characteristics +which the data model must support:
++20.10 Content items must have a simple unique identifier +so they can be related to other objects in the system.
+20.20 Each content item consists of a set of attributes +and a single text or binary object.
+20.25 All content items are associated with a few basic +attributes to facilitate searching and development of browser +interfaces to the content repository:
+
- A title
- A brief description or summary
- An author or contributor
- A publication or posting date
- A distinguished URL at which an item may be +accessed.
- A MIME type
++20.30 Each content item must be an instance of a +particular content type. The content type +defines the attributes associated with the content item, in +addition to the basic ones described above.
+20.40 A content item must have a unique, persistent URL +(Uniform Resource Locator) by which it is publicly accessible, such +as /press-releases/products/widget. To facilitate moving +of items within the repository, the item itself should only be +associated with the "tail" of the url, such as widget. The +absolute URL of the item is determined by its location within the +repository (See Content +Organization).
+20.50 It must be possible to specify the language of each +item.
+20.60 It must be possible to maintain a revision history +for both the attributes and the text or binary object associated +with a content item.
+20.70. There must be a flexible mechanism for +implementing access control on individual items, based on granting +of permissions to groups or individual users.
+20.80. A content item may be associated with any number +of workflows.
+20.90. Content items may themselves be "containers" or +"parents" for other content items. For example, an Article +may contain multiple Sections.
+20.95 Each item may be associated with any number of +related objects. The type and number of relationships must be +constrained by the content type of the item (See 10.70 above).
+
As mentioned above, each content item may be associated with any +number of revisions. The data model for revisions must support the +following:
++30.10. A revision consists of the complete state of the +item as it existed at a certain point in time. This includes the +main text or binary object associated with the item, as well as all +attributes.
+30.20. The data model must be extensible so that +revisions for all content types (with any number of attributes) may +be stored and retrieved efficiently.
+
40.0 Organization of +the Repository
++40.10. The data model must support the hierarchical +organization of content items in a manner similar to a file +system.
+40.20. The URL of a content item should reflect its +location in the hierarchy. For example, a press release with the +URL /press-releases/products/new-widget is located at the +third level down from the root of the hierarchy.
A folder is analogous to a folder or directory in a +file system. It represents a level in the content item hierarchy. +In the previous example, press-releases is a folder under +the repository root, and products is folder within that. +The description of a folder may include the following +information:
++40.20.5.10. A URL-encoded name for building the path to +folders and individual items within the folder.
+40.20.5.20. A pointer to a content item that may serve as +the "index" for the folder (i.e. the item that is served when the +URL of the folder itself is accessed).
+40.20.5.30. A set of constraints on the number and type +of content items that may be stored in the folder.
++40.30. It must be possible to create symbolic links or +shortcuts to content items, so they may be presented at more than +one URL or branch of the hierarchy.
+++40.30.5 Content Symbolic +Link.
+40.30.5.20. A pointer to a +target item which the symbolic link references..
+40.30.5.30. A title or +label, which may be different from the title or label of the target +item.
+
The content repository should provide a means of storing and +managing the templates that are merged with content items to render +output in HTML or other formats. Templates are assumed to be text +files containing static markup with embedded tags or code to +incorporate dynamic content in appropriate places. The data model +requirements for templates are a subset of those for content +items.
Because they typically need to reference a specific attributes, +a template is typically specific to a particular content types and +its subtypes.
100.10 MIME Types
Since a MIME type is a required attribute of each content item, +the repository must be capable of managing a list of recognized +MIME types for ensuring appropriate delivery and storage of +content.
++100.10.10. Register a MIME type
+100.10.20. Set the description of a MIME type
+100.10.30. Get the description of a MIME type
+100.10.40. Determine whether a MIME type is text or +binary
+100.10.50. Get a list of registered MIME types
+100.10.60. Unregister a MIME type
+
It is important to note that the role of MIME types in the +content repository is simply to describe the general file format of +each content item. Neither the data model nor the API support the +full range of allowed parameters for the general MIME types such as +text/plain.
100.20 Locales
The repository must have access to a list of recognized locales +for the purpose of publishing content items in multiple languages +and character sets.
All content in the repository is stored in UTF-8 to facilitate +searching and uniform handling of content. Locales may be specified +as user preferences to configure the user interface in the +following ways:
Functional requirements for locales include:
++100.20.10. Register a locale, including language, +territory and character set.
+100.20.20. Get the language of a specified locale.
+100.20.10. Get the character set code of a specified +locale using either Oracle or WETF/ISO/ANSI codes.
+100.20.30. Get the number, date and currency format of a +specified locale.
+100.20.40. Convert a text content item to a specified +locale (character set).
+100.20.50. Get a list of registered locales.
+100.20.60. Unregister a locale.
+
100.30 Content Types
++100.30.10. Create a content type, optionally specifying +that it inherits the attributes of another content type. Multiple +inheritance is not supported.
+100.30.20. Get and set the singular and plural proper +names for a content type.
+100.30.30. Create an attribute for a content type.
+100.30.40. Register a content type as a container for +another content type, optionally specifying a minimum and maximum +count of live items.
+100.30.50. Register a content type as a container for +another content type, optionally specifying a minimum and maximum +count of live items.
+100.30.60. Register a set of tags or tokens for labeling +child items of an item of a particular content type.
+100.30.70. Register a template +for use with a content type, optionally specifying a use context +("intranet", "extranet") which the template is appropriate to +use.
+100.30.80. Register a particular type of workflow to +associate with items of this content type by default.
+100.30.90. Register a MIME type as valid for a content +type. For example, the Image content type may only allow GIF +and JPEG file formats.
+100.30.95 Register a relationship with another type of +object, specifying a token or name for the relationship type as +well as a minimum and/or maximum number of relationships of this +type that are required for the item to be published.
+
100.40 Content Items
++100.40.10. Create a new item, specifying a parent context +or the root of the repository by default.
+100.40.15. Rename an item.
+100.40.17. Copy an item to another location in the +repository.
+100.40.20. Move an item to another location in the +repository.
+100.40.30. Get the full path (ancestry of an item) up to +the root.
+100.40.35. Get the parent of an item.
+100.40.40. Determine whether an item may have a child of +a particular content type, based on the existing children of the +item and the constraints on the content type.
+100.40.45. Label a child item with a tag or token, based +on the set of tags registered for the content type of the container +item.
+100.40.50. Get the children of an item.
+100.40.55. Get the children of an item by type or +tag.
+100.40.60. Establish a generic relationship between any +object and a content item, optionally specifying a relationship +type.
+100.40.70. Create a revision.
+100.40.80. Mark a particular revision of an item as +"live".
+100.40.83. Specify a start and end time when an item +should be available.
+100.40.85. Clear the live revision attribute of an item, +effectively removing it from public view.
+100.40.90. Get a list of revisions for an item, including +modifying user, date modified and comments.
+100.40.95. Revert to an older revision (create a new +revision based on an older revision).
+
100.50 Content Folders
The repository should allow for hierarchical arrangement of +content items in a manner similar to a file system. The API to meet +this general requirement focuses primarily on content folders:
++100.50.10. Create a folder for logical groups of +content items and other folders. The folder name becomes part of +the distinguished URL of any items it contains. Folders may be +created at the "root" or may be nested within other folders.
+100.50.20. Set a label and description for a folder.
+100.50.30. Get the label and description for a +folder.
+100.50.40. Get a list of folders contained within a +folder.
+100.50.50. Move a folder to another folder.
+100.50.60. Copy a folder to another folder.
+100.50.70. Create a symbolic link to a folder from +within another folder. The contents of the folder should be +accessible via the symbolic link as well as the regular path.
+100.50.80. Tag all live item revisions within a folder +with a common version descriptor (i.e. 'Version 1.0' or 'August 1 +release'), for the purpose of versioning an entire branch of the +site. Folder objects themselves are not eligible for +versioning, since they are solely containers and do not have any +content other than the items they contain.
+100.50.90. Delete a folder if it is empty.
+
Note that folders are simply a special type of content item, and +as such may receive the same object services as items, (namely +access control and workflow). In addition to the file-system +analogy afforded by folders, any type of content item may serve as +a contain for other content items (see below).
The repository must offer integration with a workflow package +for managing the content production process.
100.60 Categorization
The repository must support a common hierarchical taxonomy of +subject classifications that may be applied to content items.
++100.60.10. Create a new subject category.
+100.60.20. Create a new subject category as the child of +another subject category.
+100.60.30. Assign a subject category to a content +item.
+100.60.40. Remove a subject category from an item.
+100.60.50. Get the subject categories assigned to a +content item.
+
The repository must have a standard means of indexing and +searching all content.
The repository must have a means of restricting access on an +item-by-item basis.
The presentation layer must have access to a subset of the +stored procedure API in order to search and retrieve content +directly from the repository if desired.
Author | Date | Description | +
---|---|---|
Karl Goldstein | 9 August 2000 | Initial draft. | +
Karl Goldstein | 22 August 2000 | Added to API section. | +
Karl Goldstein | 19 September 2000 | Added data model requirements, revised API requirements, +numbered all items. | +
Karl Goldstein | 21 September 2000 | Add requirements for relationships among content items and +other objects. | +
+ +Documentation + +Write ASAP. + +Sign In/Out + +--Eventually need to use regular acs40 API (maintain existing interface) + +Work Items 3 + +--Display deadlines highlighted depending on whether the deadline has + passed +--Add ability to check items in and out in addition to simply finishing + enabled tasks. + +Site Map + +--Tree widget is buggy (not updating correctly on delete, not showing blue + arrows in proper context, etc.) 1-Stas +--Improve design of folder listing (sortable by name, date, size, mod_time) Michael +--Symlink title is confusing (Stas) +--Ideally bookmark graphics show change to show items that are currently + marked. + +Items + +--UI around each item needs polishing (better display of revisions etc.) +--support for display and editing of additional simple attributes 2 +--for now just allow assignment of one template. 1-Karl +--We currently have no way of setting access controls (also applies to + folders). 1 + +Content Types + +--Not much to do here, seems OK. +--Need UI for creating content types, adding attributes, etc. (3) + +Subject Categories + +--Need to reintegrate simple category table (depends on message catalog) + Previous UI was functional, should be reusable. +-- 1 + +Message Catalog + +--Remove as a module for now. + +Users + +--Should display the party hierarchy here, with tools for adding/removing + users. Parties and usersshould be markable to the clipboard so they can + be used in building workflow contexts and access control lists. +-- 2 + +Workflows + +--index.tcl: Display a list of available workflows, add/remove users from +the eligible list for each transition, etc. +--reintegration with notifications! + +Clipboard + +--think about improving UI for this. 2 + +
Last Modified: $Id: todo.html,v 1.1.1.1 2001/03/13 22:59:26 ben +Exp $
+ Index: openacs-4/packages/acs-content-repository/www/doc/tutorial.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/www/doc/tutorial.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-content-repository/www/doc/tutorial.adp 16 Sep 2014 20:51:11 -0000 1.1.2.1 @@ -0,0 +1,715 @@ + +Let's say you're a developer making a package for OpenACS. +You've heard statements like, "every package should use the content +repository", or maybe a developer has suggested that you use it. Or +maybe you just stumbled across it. Why would you want to spend your +time reading this document and wasting a good afternoon when you +could get started coding right away?
The simple answer is that the content repository (CR) gives you +many different things for free:
For the sake of an example, I'm going to use a Tasks +application. This application will keep track of all the tasks of +an organization, deadlines for those tasks, and who needs to work +on them.
The reason I might be interested in using the content repository +(CR) in this case is that I can keep track of all the changes to a +particular Task, so that if someone changes the deadline on an +item, I can see what the original deadline was. In addition, I as a +developer would like to have sub-tasks, and sub-sub-tasks, so I can +have a whole hierarchy of things that need to be accomplished. Big +tasks can be sub-divided so that several people can each do their +particular parts.
So I decide to create a Tasks table. Each of these Tasks has +various information associated with it, such as deadlines, +descriptions of what needs to be accomplished, and so on:
+Task + Title + Description + Task Number + +
First of all, let's get some terminology out of the way. Columns +of a table are referred to as attributes in content +repository-speak.
+The steps to set up your data model are as follows: +The first step is to decide on what part of a Task you'd you'd +like to have under revision control, and what portion you'd like to +have just one version of. In our case, the only thing we wouldn't +want under version control is the Task Number. This will be a +unique identifier for the task, and we don't want that changing +every time someone edits it.
For our simple example:
+ Title - want versions + Description - want versions + Task Number - do NOT want versions + +
You will have two tables: one with versioned attributes, and one +without versioned attributes.
+Convention: often, developers will name the first table +by what it is (in my case pm_tasks), and the second, +versioned table by the same name, but with _revisions at the end. +Thus, I'll name my second table pm_tasks_revisions.
+This is actually very easy: +Versioned portion:
+ create table pm_tasks_revisions ( + task_revision_id + integer + constraint pm_tasks_revisions_id_pk + primary key + constraint pm_tasks_revisions_id_fk + references cr_revisions(revision_id) + on delete cascade, + title + varchar(100), + description + varchar(4000) + ); + +
Unversioned portion:
+ create table pm_tasks ( + task_id + integer + constraint pm_tasks_id_pk + primary key + constraint pm_tasks_id_fk + references cr_items(item_id) + on delete cascade, + task_number + integer + ) + +
One thing you have to be careful of when creating these tables
+is that there are no columns that have the same names as any of the
+columns in the cr_items
and cr_revisions
+tables. For example, you can't call you key on the
+pm_tasks_revisions table revision_id
. Why? There are
+some views that are automatically generated that combine these
+tables for you, but they won't be created if the names conflict.
+I'll describe what these views are later, but they are useful. You
+were warned.
Notice that each table uses as its primary key a reference to
+either the cr_revisions
table or the
+cr_items
table. A content item is basically
+just some content: either text or binary data. The contents
+revisions table keeps track of which version from the
+tasks_revisions table is the most current, and which one is
+live.
All this is going inside the
+sql/postgresql/project-manager-create.sql
file. Your
+name will be different of course.
After we've created the two tables, we need to let the content +repository know that we have a new type of structured data that we +are storing in the content repository. Tasks are a "content type", +because they have data associated with them, such as when they are +due, and what needs to be done.
I thus need to to
+ --create the content type + select content_type__create_type ( + 'pm_task', -- content_type + 'content_revision', -- not sure what this is + 'Task', -- pretty_name + 'Tasks', -- pretty_plural + 'pm_tasks_revisions', -- table name + 'task_id', -- id_column + 'content_revision.revision_name' + ); + +
You then need to add in all the attributes, so that the content +repository can do some magic things behind the scenes. The content +repository doesn't know about what's inside of the pm_tasks +and pm_tasks_revisions tables, so we teach it:
+ -- add in attributes + + select content_type__create_attribute ( + 'pm_task', -- content_type + 'start_date', -- attribute_name + 'date', -- datatype (string, number, boolean, date, keyword, integer) + 'Start date', -- pretty_name + 'Start dates', -- pretty_plural + null, -- sort_order + null, -- default value + 'timestamptz' -- column_spec + ); + + select content_type__create_attribute ( + 'pm_task', -- content_type + 'end_date', -- attribute_name + 'date', -- datatype + 'End date', -- pretty_name + 'End dates', -- pretty_plural + null, -- sort_order + null, -- default value + 'timestamptz' -- column_spec + ); + + select content_type__create_attribute ( + 'pm_task', -- content_type + 'percent_complete', -- attribute_name + 'number', -- datatype + 'Percent complete', -- pretty_name + 'Percents complete', -- pretty_plural + null, -- sort_order + null, -- default value + 'numeric' -- column_spec + ); + +
+Side effect: once you've created the content type, the
+content repository creates a view for you called
+pm_tasks_revisionsx
. Note the x at the end of the
+name. If you're using Postgres, I believe it will also create a
+view for you called pm_tasks_revisionsi
+
Why are these two views created? the x view is created for +selection, and the i view is created for inserts. They join the +acs_objects, cr_revisions, and our pm_tasks_revisions tables +together. Try viewing them to get an idea of how they might be +useful.
It is also possible to dynamically create tables, and extend
+them with extra columns. You could do this by using create
+table
or alter table add column
statements in
+SQL, but this also adds in some meta-data that will be useful to
+you. The disadvantage is that you have to call the content
+repository API. The advantage is that someday you'll be able to do
+really cool stuff with it, like automatically generate interfaces
+that take advantage of the new columns and tables you've added.
+Another nice thing is that all that messy business of defining your
+attributes through the API is taken care of.
+Types is the content repository are another term for
+tables, although that doesn't explain it completely. Types are also
+kept track of within OpenACS, in the acs_object_types
+table, so the system knows about the tables you create, and can do
+some intelligent things with them.
A lot of the intelligent things you can do with this +information is still being built. But imagine for example that you +are using the project manager package I've written. You work at an +ice cream company, and every task that is done also has an +associated ice cream flavor with it (yeah, this isn't a good +example, but pay attention anyway). If I've written the project +manager to take advantage of it, when you add in this extra +attribute to the pm_tasks_revisions table, the UI aspects will be +automatically taken care of. You'll be able to select a flavor when +you edit a task, and it will be shown on the task view page. This +is the direction OpenACS development is going, and it will be +really really cool!
First, I'm going to describe how to extend other content +repository tables using the CR API. Then, I'll describe how to set +up your own tables as well:
As you recall from earlier in this page, attributes are just
+another term for columns in a table. The Content Repository has a
+mechanism for adding and removing columns via the pl/sql API. If
+you check your /api-doc:
+/api-doc/plsql-subprogram-one?type=FUNCTION&name=content%5ftype%5f%5fcreate%5fattribute
+, you'll see that there is a way to extend the columns
+programmatically.
Why would you want to do this? For project manager, I decided to +do this because I wanted to customize my local version of the +projects table, to account for company-specific information. That +way, I can have a separate edit page for those types, but not have +a separate table to join against.
+. Instead of doing this: ++I can do this: ++alter table pm_projects add column + target_date date; +
+A very important advantage of this method is that it recreates all +the views associated with the pm_projects table, like pm_projectsx. +If I did an alter table statement, all the views would not contain +the new column. Note that I believe you CAN create foreign key +constraints, by putting them in the column spec (the last column): ++select content_type__create_attribute( + 'pm_project', + 'target_date', + 'date', + 'Target date', + 'Target dates', + null, + null, + 'date' +); +
+I have no idea of whether or not that is supposed to be legal, but +I believe it works. Jun was the one who originally talked about +the +possibility of storing all the revisioned columns in a generic +table. ++select content_type__create_attribute( + 'pm_project', + 'company_id', + 'integer', + 'Company', + 'Companies', + null, + null, + 'integer constraint pm_project_comp_fk references organizations' +); +
pm_task__new_task_item
function (which we'll
+write in a little bit). This function creates both a new content
+item, and a new content revision. Information is actually stored in
+four tables, believe it or not: cr_revisions
,
+cr_items
, pm_tasks
, and
+pm_tasks_revisions
. The task number is stored in
+pm_tasks, the title and description are stored in
+pm_tasks_revisions, and some additional information like who
+entered the information is stored in cr_revisions and cr_items.
+Whenever you make a change to this item, you don't change the table
+yourself, but add a revision, using your
+pm_task__new_task_revision
function (which we'll write
+in a little bit). This function adds another revision, but
+not another item or cr_item. After you've added another
+revision, you'll have two revisions and one item. Two entries in
+cr_revisions (and pm_tasks_revisions), and one item in cr_items and
+pm_tasks. The cr_revisions table keeps track of which item is the
+most recent, and which item is "live". For the edit-this-page
+application, for example, this is used to keep track of which
+revision to a page is actually being served to users. In your code,
+you'll use your pm_tasks_revisionsx view, which joins the
+pm_tasks_revisions table with the cr_revisions table (and it might
+even join in cr_items -- I forget at the moment).
++select define_function_args('pm_task__new_task_item', 'task_id, project_id, title, description, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, creation_date, creation_user, creation_ip, package_id'); + +create function pm_task__new_task_item ( + p_task_id integer, + p_project_id integer, + p_title varchar, + p_description varchar, + p_end_date timestamptz, + p_percent_complete numeric, + p_estimated_hours_work numeric, + p_estimated_hours_work_min numeric, + p_estimated_hours_work_max numeric, + p_creation_date timestamptz, + p_creation_user integer, + p_creation_ip varchar, + p_package_id integer +) returns integer +as $$ +declare + v_item_id cr_items.item_id%TYPE; + v_revision_id cr_revisions.revision_id%TYPE; + v_id cr_items.item_id%TYPE; + v_task_number integer; +begin + select acs_object_id_seq.nextval into v_id from dual; + + -- We want to put the task under the project item + + -- create the task_number + + v_item_id := content_item__new ( + v_id::varchar, -- name + p_project_id, -- parent_id + v_id, -- item_id + null, -- locale + now(), -- creation_date + p_creation_user, -- creation_user + p_package_id, -- context_id + p_creation_ip, -- creation_ip + 'content_item', -- item_subtype + 'pm_task', -- content_type + p_title, -- title + p_description, -- description + 'text/plain', -- mime_type + null, -- nls_language + null -- data + ); + + v_revision_id := content_revision__new ( + p_title, -- title + p_description, -- description + now(), -- publish_date + 'text/plain', -- mime_type + NULL, -- nls_language + NULL, -- data + v_item_id, -- item_id + NULL, -- revision_id + now(), -- creation_date + p_creation_user, -- creation_user + p_creation_ip -- creation_ip + ); + + PERFORM content_item__set_live_revision (v_revision_id); + + insert into pm_tasks ( + task_id, task_number) + values ( + v_item_id, v_task_number); + + insert into pm_tasks_revisions ( + task_revision_id, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, actual_hours_worked) + values ( + v_revision_id, p_end_date, p_percent_complete, p_estimated_hours_work, p_estimated_hours_work_min, p_estimated_hours_work_max, '0'); + + PERFORM acs_permission__grant_permission( + v_revision_id, + p_creation_user, + 'admin' + ); + + return v_revision_id; +end; +$$ language plpgsql; + + +select define_function_args('pm_task__new_task_revision', 'task_id, project_id, title, description, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, actual_hours_worked, creation_date, creation_user, creation_ip, package_id'); + +create function pm_task__new_task_revision ( + p_task_id integer, -- the item_id + p_project_id integer, + p_title varchar, + p_description varchar, + p_end_date timestamptz, + p_percent_complete numeric, + p_estimated_hours_work numeric, + p_estimated_hours_work_min numeric, + p_estimated_hours_work_max numeric, + p_actual_hours_worked numeric, + p_creation_date timestamptz, + p_creation_user integer, + p_creation_ip varchar, + p_package_id integer +) returns integer +as $$ +declare + v_revision_id cr_revisions.revision_id%TYPE; + v_id cr_items.item_id%TYPE; +begin + select acs_object_id_seq.nextval into v_id from dual; + + -- We want to put the task under the project item + + v_revision_id := content_revision__new ( + p_title, -- title + p_description, -- description + now(), -- publish_date + 'text/plain', -- mime_type + NULL, -- nls_language + NULL, -- data + p_task_id, -- item_id + NULL, -- revision_id + now(), -- creation_date + p_creation_user, -- creation_user + p_creation_ip -- creation_ip + ); + + PERFORM content_item__set_live_revision (v_revision_id); + + insert into pm_tasks_revisions ( + task_revision_id, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, actual_hours_worked) + values ( + v_revision_id, p_end_date, p_percent_complete, p_estimated_hours_work, p_estimated_hours_work_min, p_estimated_hours_work_max, p_actual_hours_worked); + + PERFORM acs_permission__grant_permission( + v_revision_id, + p_creation_user, + 'admin' + ); + + return v_revision_id; +end; +$$ language plpgsql; + + +-- The delete function deletes a record and all related overhead. + +select define_function_args('pm_task__delete_task_item', 'task_id'); + +create or replace function pm_task__delete_task_item (p_task_id integer) +returns integer as $$ +declare +begin + delete from pm_tasks_revisions + where task_revision_id in (select revision_id from pm_tasks_revisionsx where item_id = p_task_id); + + delete from pm_tasks + where task_id = p_task_id; + + raise NOTICE 'Deleting pm_task...'; + + PERFORM content_item__delete(p_task_id); + return 0; +end; +$$ language plpgsql; +
+item_id - unique id for this item, will be +different than the revision_id+cr_revisions: +
parent_id - used to group items into a hierarchy (see +below)
name - this is used to make a URL by the content repository. +It must be unique per content folder. You can use a number, or +something like project_231. One way to do this is to set it equal +to a title plus the item_id.
locale - not sure, probably for internationalization +support
live_revision - this is equal to the cr_revision table's +revision_id that is the live version
latest_revision - this is equal to the cr_revision table's +revision_id that is the latest version
publish_status - not sure
content_type - not sure
storage_type - not sure, probably text or binary?
storage_area_key - not sure
tree_sortkey - a utility column used in hierarchical +queries.
+
+revision_id - a unique id for this revision.
item_id - a reference to the item_id for this revision
title - you can use this for your application. For example, +My Big Project
description - you can use this for your application, as a +longer description.
publish_date - the date this was published. Not sure if this +is for your use, or internal
mime_type - the mime type.
nls_language - I believe this is for +internationalization
lob - the binary content.
content - the text content.
content_length - the length of the text or binary +content?
+
Using this structure is optional, but useful in many +circumstances.
The facility for this is built into the cr_items
+data model. This makes sense, because you wouldn't want your
+hierarchy associated with each revision. Here's how Postgres
+describes the cr_items
table:
+The+ Table "public.cr_items" + Column | Type | Modifiers +------------------+------------------------+----------------------------- + item_id | integer | not null + parent_id | integer | not null + name | character varying(400) | not null + locale | character varying(4) | + live_revision | integer | + latest_revision | integer | + publish_status | character varying(40) | + content_type | character varying(100) | + storage_type | character varying(10) | not null default 'text' + storage_area_key | character varying(100) | not null default 'CR_FILES' + tree_sortkey | bit varying | +
parent_id
refers to either a content item
+(cr_items
), or a subclass of a content_item (such as
+cr_folders
). I'll explain more later about
+cr_folders
.
+One thing that you might want to do for your application is to +give the application its own root directory. Because the content +repository is shared among applications, this separates it off from +other applications. They can still use the items in your +application, but it must be a more deliberate process. If you don't +create your own root directory, you may see strange-looking data +from other applications in your application, or see your +application's data in other applications. There are times when +you'll want to do this, but probably not until you're much more +familiar with the content repository. Another reason for creating +your own root repository is that you application may be mounted +several times. If you want to separate the directory structure +between instances of your application, you need to create your own +root directory:
+Note that this example is for projects rather than tasks. This is +because for the application I'm writing, projects are what tasks +are stored inside of. A project has many component tasks. If you +were writing another application, or if I wasn't doing anythign +with projects, then this would be creating a folder for just tasks. ++-- Creates and returns a unique name for new project folders + +select define_function_args('pm_project__new_unique_name', 'package_id'); + +create function pm_project__new_unique_name (p_package_id integer) +returns text as $$ +declare + v_name cr_items.name%TYPE; + v_package_key apm_packages.package_key%TYPE; + v_id integer; +begin + select package_key into v_package_key from apm_packages + where package_id = p_package_id; + + select acs_object_id_seq.nextval into v_id from dual; + + -- Set the name + select v_package_key || '_' || + to_char(current_timestamp, 'YYYYMMDD') || '_' || + v_id into v_name; + + return v_name; +end; +$$ language plpgsql; + + +select define_function_args('pm_project__new_root_folder', 'package_id'); + +create function pm_project__new_root_folder (p_package_id integer) +returns integer as $$ +declare + v_folder_id cr_folders.folder_id%TYPE; + v_folder_name cr_items.name%TYPE; +begin + -- Set the folder name + v_folder_name := pm_project__new_unique_name (p_package_id); + + v_folder_id := content_folder__new ( + v_folder_name, -- name + 'Projects', -- label + 'Project Repository', -- description + p_package_id -- parent_id + ); + + -- Register the standard content types + PERFORM content_folder__register_content_type ( + v_folder_id, -- folder_id + 'pm_project', -- content_type + 'f' -- include_subtypes + ); + + -- TODO: Handle Permissions here for this folder. + + return v_folder_id; +end; +$$ language plpgsql; +
Typically, this definition would go in your
+sql/postgresql/project-manager-create.sql
file. If
+this file is broken in several parts, this would go in the
+project-manager-create-functions.sql portion.
Once you've created your root directory, you will set the
+parent_id
of your items to the id for the new root
+repository (in our case, it's returned from the
+pm_project__new_root_folder function
)
In the project-manager application, we'll create a root
+repository, and make all projects under that root repository. That
+means they'll all have a parent_id
set to the root
+repository. However, we also want to make projects that are
+sub-projects of other projects. In that case, we will set the
+parent_id
of the sub-project to the
+item_id
of the parent.
cr_items
, and the only real difference is that they
+contain no data, except for a label and description.
+If you create folders for your application, then you'll need to +make sure you manage them along with your other objects. For +example, if you were to add a folder for each of your objects, then +you would probably want to make sure you delete the folder when you +delete the object.
However, in many cases you are not creating more than one +folder. In fact, the only folder you might have will be the root +folder you create for each instance of your application (if you +install the project-manager in two parts of your web server, for +example, it should have two different root folders). When your +application is running, it can determine the root folder by +searching the cr_folders table. Here's the definition of that +table:
+Note that there is a+ Table "public.cr_folders" + Column | Type | Modifiers +--------------------+-------------------------+------------- + folder_id | integer | not null + label | character varying(1000) | + description | text | + has_child_folders | boolean | default 'f' + has_child_symlinks | boolean | default 'f' + package_id | integer | +
package_id
column. The nice thing
+about this column is that you can use it to find the root
+repository, if you only have one folder per instance of your
+application. You can get your package_id using this call within
+your .tcl file:
++Then you can find the root repository by using a query like this: ++set package_id [ad_conn package_id] +
+select folder_id from cr_folders where package_id = :package_id; +
Get latest revision (Tcl) | set live_revision_id [db_exec_plsql get_live_revision "select +content_item__get_live_revision(:item_id)"] | +
---|---|
Get latest revision (pl/sql) | live_revision_id := +content_item__get_live_revision(:item_id); | +
The item_id identifies the content item with which the revision +is associated.
Likewise, the most recent revision of a content item can be +obtained with the content_item__get_latest_revision function
cr_revisions
table, and a table that
+you set up to store specialized data. In this case, the title (I
+think), byline, and publication date would be stored in a
+specialized table.+The problem seems to be that there were still items in the ++Referential Integrity: attempting to delete live_revision: 658 +
cr_items
table. You can remove them using select
+content_item__delete(648);
in psql. You get the codes by
+doing a query like this:
++Really, however, what you need to do is make sure your __delete and +drop scripts first go through and delete all children of those +items. I'm not sure if you need to delete the items themselves -- I +believe they may be dropped by themselves when the tables are +dropped, because of the+select i.item_id, r.revision_id, r.title, i.content_type from cr_items i, cr_revisions r where i.item_id = r.item_id order by i.item_id, r.revision_id; +
cascade
portion of the SQL
+data model.
+When I was troubleshooting folders, I found this query +useful:
+select f.folder_id,f.label,f.description,i.content_type from cr_folders f, cr_items i where f.folder_id = i.item_id; +
Once again, thanks to daveb for help in tracking this down (he +rocks!).
+ Index: openacs-4/packages/acs-content-repository/www/doc/uninstall.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/www/doc/uninstall.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-content-repository/www/doc/uninstall.adp 16 Sep 2014 20:51:11 -0000 1.1.2.1 @@ -0,0 +1,27 @@ + +The content repository includes an uninstall script, +sql/content-drop.sql. This script does two things:
The uninstall script does not do the following:
Because of what the uninstall script does not do, it is +only appropriate for removing the content repository in +preparation for removing the entire ACS Objects data model. If +you wish to upgrade an existing installation and cannot afford to +lose your data, you must run an upgrade script rather than +uninstalling the entire data model.
+Content Repository : content
Parameters: | |
---|---|
Not yet documented | |
Declaration: | |
+function blob_to_string( + blob_loc blob) return varchar2 +as language + java +name + 'com.arsdigita.content.Util.blobToString( + oracle.sql.BLOB + ) return java.lang.String'; + + |
Parameters: | |
---|---|
Not yet documented | |
Declaration: | |
+procedure blob_to_file( +s varchar2, blob_loc blob) +as language + java +name + 'com.arsdigita.content.Util.blobToFile( + java.lang.String, oracle.sql.BLOB + )'; + + |
Parameters: | |
---|---|
Not yet documented | |
Declaration: | |
+procedure string_to_blob( + s varchar2, blob_loc blob) +as language + java +name + 'com.arsdigita.content.Util.stringToBlob( + java.lang.String, oracle.sql.BLOB + )'; + + |
Parameters: | |
---|---|
Not yet documented | |
Declaration: | |
+procedure string_to_blob_size( + s varchar2, blob_loc blob, blob_size number) +as language + java +name + 'com.arsdigita.content.Util.stringToBlob( + java.lang.String, oracle.sql.BLOB, int + )'; + + |
Last Modified: $Id: content.html,v 1.1.1.1 2001/03/13 22:59:26 +ben Exp $
+ Index: openacs-4/packages/acs-content-repository/www/doc/api/extlink.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/www/doc/api/extlink.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-content-repository/www/doc/api/extlink.adp 16 Sep 2014 20:51:11 -0000 1.1.2.1 @@ -0,0 +1,102 @@ + ++Content Repository : +content_extlink
External links are references to content pages on other web +sites. They provide the basis for maintaining a hierarchy of +"bookmarks" that may be managed in a manner analogous to other +content items. In particular, external links may be tagged with +keywords and related to the site's own content items.
Determines if the item is a extlink
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Returns: | 't' if the item is a extlink, 'f' otherwise | +|||
Parameters: | ||||
| ||||
Declaration: | ||||
+function is_extlink ( + item_id in cr_items.item_id%TYPE +) return char; + + | ||||
See Also: | content_extlink.new, content_extlink.resolve | +
Create a new extlink, an item pointing to an off-site +resource
Author: | Karl Goldstein | +|||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Returns: | The id of the newly created extlink | +|||||||||||||||||||||||||||
Parameters: | ||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||
Declaration: | ||||||||||||||||||||||||||||
+function new ( + name in cr_items.name%TYPE default null, + url in cr_extlinks.url%TYPE, + label in cr_extlinks.label%TYPE default null, + description in cr_extlinks.description%TYPE default null, + parent_id in acs_objects.context_id%TYPE, + extlink_id in cr_extlinks.extlink_id%TYPE default null, + creation_date in acs_objects.creation_date%TYPE + default sysdate, + creation_user in acs_objects.creation_user%TYPE + default null, + creation_ip in acs_objects.creation_ip%TYPE default null +) return cr_extlinks.extlink_id%TYPE; + + | ||||||||||||||||||||||||||||
See Also: | acs_object.new, content_item.new, content_extlink.resolve | +
Deletes the extlink
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Parameters: | ||||
| ||||
Declaration: | ||||
+procedure delete ( + extlink_id in cr_extlinks.extlink_id%TYPE +); + + | ||||
See Also: | content_extlink.new, acs_object.delete | +
+Last Modified: $Id: extlink.html,v 1.1.1.1 2001/03/13 22:59:26 ben +Exp $ + Index: openacs-4/packages/acs-content-repository/www/doc/api/folder.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/www/doc/api/folder.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-content-repository/www/doc/api/folder.adp 16 Sep 2014 20:51:12 -0000 1.1.2.1 @@ -0,0 +1,331 @@ + +
+Content Repository : +content_folder
Content folders contain related content items and allow content +managers to group content as they see fit. Within a content folder, +content items must have unique names since this is where they will +be served from. For example within the folder "movies" (served from +"/movies") all items must have unique names, such as: "terminator," +"terminator2" (served from "/movies/terminator, +"/movies/terminator2" respectively).
Returns the item ID of the index page of the folder, null +otherwise
Author: | Michael Pih | +|||
---|---|---|---|---|
Returns: | The item ID of the index page | +|||
Parameters: | ||||
| ||||
Declaration: | ||||
+function get_index_page ( + folder_id in cr_folders.folder_id%TYPE +) return cr_items.item_id%TYPE; + + |
Returns the label for the folder. This function is the default +name method for the folder object.
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Returns: | The folder's label | +|||
Parameters: | ||||
| ||||
Declaration: | ||||
+function get_label ( + folder_id in cr_folders.folder_id%TYPE +) return cr_folders.label%TYPE; + + | ||||
See Also: | acs_object_type.create_type, the docs for the name_method +parameter | +
Determine if the folder is empty
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Returns: | 't' if the folder contains no subfolders or items, +'f' otherwise | +|||
Parameters: | ||||
| ||||
Declaration: | ||||
+function is_empty ( + folder_id in cr_folders.folder_id%TYPE +) return varchar2; + + | ||||
See Also: | content_folder.is_folder | +
Determine if the item is a folder
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Returns: | 't' if the item is a folder, 'f' otherwise | +|||
Parameters: | ||||
| ||||
Declaration: | ||||
+function is_folder ( + item_id in cr_items.item_id%TYPE +) return char; + + | ||||
See Also: | content_folder.new, content_folder.is_sub_folder | +
change this to is_type_registered Determines if a content type +is registered to the folder Only items of the registered type(s) +may be added to the folder.
Author: | Karl Goldstein | +|||||||||
---|---|---|---|---|---|---|---|---|---|---|
Returns: | 't' if the type is registered to this folder, 'f' +otherwise | +|||||||||
Parameters: | ||||||||||
| ||||||||||
Declaration: | ||||||||||
+function is_registered ( + folder_id in cr_folders.folder_id%TYPE, + content_type in cr_folder_type_map.content_type%TYPE, + include_subtypes in varchar2 default 'f' +) return varchar2; + + | ||||||||||
See Also: | content_folder.register_content_type, +content_folder.unregister_content_type, | +
Determine if the item target_folder_id is a subfolder +of the item folder_id +
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Returns: | 't' if the item target_folder_id is a +subfolder of the item folder_id, 'f' otherwise | +||||||
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+function is_sub_folder ( + folder_id in cr_folders.folder_id%TYPE, + target_folder_id in cr_folders.folder_id%TYPE +) return char; + + | |||||||
See Also: | content_folder.is_folder | +
Create a new folder
Author: | Karl Goldstein | +||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Returns: | The id of the newly created folder | +||||||||||||||||||||||||
Parameters: | |||||||||||||||||||||||||
| |||||||||||||||||||||||||
Declaration: | |||||||||||||||||||||||||
+function new ( + name in cr_items.name%TYPE, + label in cr_folders.label%TYPE, + description in cr_folders.description%TYPE default null, + parent_id in acs_objects.context_id%TYPE default null, + folder_id in cr_folders.folder_id%TYPE default null, + creation_date in acs_objects.creation_date%TYPE + default sysdate, + creation_user in acs_objects.creation_user%TYPE + default null, + creation_ip in acs_objects.creation_ip%TYPE default null +) return cr_folders.folder_id%TYPE; + + | |||||||||||||||||||||||||
See Also: | acs_object.new, content_item.new | +
Recursively copy the folder and all items in into a new +location. An error is thrown if either of the parameters is not a +folder. The root folder of the sitemap and the root folder of the +templates cannot be copied
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+procedure copy ( + folder_id in cr_folders.folder_id%TYPE, + target_folder_id in cr_folders.folder_id%TYPE +); + + | |||||||
See Also: | content_folder.new, content_folder.copy | +
Delete a folder. An error is thrown if the folder is not +empty
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Parameters: | ||||
| ||||
Declaration: | ||||
+procedure delete ( + folder_id in cr_folders.folder_id%TYPE +); + + | ||||
See Also: | acs_object.delete, content_item.delete | +
Recursively move the folder and all items in into a new +location. An error is thrown if either of the parameters is not a +folder. The root folder of the sitemap and the root folder of the +templates cannot be moved.
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+procedure move ( + folder_id in cr_folders.folder_id%TYPE, + target_folder_id in cr_folders.folder_id%TYPE +); + + | |||||||
See Also: | content_folder.new, content_folder.copy | +
Register a content type to the folder, if it is not already +registered. Only items of the registered type(s) may be added to +the folder.
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+procedure register_content_type ( + folder_id in cr_folders.folder_id%TYPE, + content_type in cr_folder_type_map.content_type%TYPE, + include_subtypes in varchar2 default 'f' +); + + | |||||||
See Also: | content_folder.unregister_content_type, +content_folder.is_registered | +
Change the name, label and/or description of the folder
Author: | Karl Goldstein | +||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Parameters: | |||||||||||||
| |||||||||||||
Declaration: | |||||||||||||
+procedure rename ( + folder_id in cr_folders.folder_id%TYPE, + name in cr_items.name%TYPE default null, + label in cr_folders.label%TYPE default null, + description in cr_folders.description%TYPE default null +); + + | |||||||||||||
See Also: | content_folder.new | +
Unregister a content type from the folder, if it has been +registered. Only items of the registered type(s) may be added to +the folder. If the folder already contains items of the type to be +unregistered, the items remain in the folder.
Author: | Karl Goldstein | +|||||||||
---|---|---|---|---|---|---|---|---|---|---|
Parameters: | ||||||||||
| ||||||||||
Declaration: | ||||||||||
+procedure unregister_content_type ( + folder_id in cr_folders.folder_id%TYPE, + content_type in cr_folder_type_map.content_type%TYPE, + include_subtypes in varchar2 default 'f' +); + + | ||||||||||
See Also: | content_folder.register_content_type, +content_folder.is_registered | +
+Last Modified: $Id: folder.html,v 1.2 2004/06/01 22:54:18 donb Exp +$ + Index: openacs-4/packages/acs-content-repository/www/doc/api/item.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/www/doc/api/item.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-content-repository/www/doc/api/item.adp 16 Sep 2014 20:51:12 -0000 1.1.2.1 @@ -0,0 +1,682 @@ + +
+Content Repository : +content_item
Content items store the overview of the content published on a +website. The actual content is stored in content revisions. It is +implemented this way so that there can be mulitple versions of the +actual content while the main idea remains constant. For example: +If there is a review for the movie "Terminator," there will exist a +content item by the name "terminator" with all the right parameters +(supertype, parent, etc), there will also exist at least one +content revision pointing to this item with the actual review +content.
Retrieve the content type of this item. Only objects of this +type may be used as revisions for the item.
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Returns: | The content type of the item | +|||
Parameters: | ||||
| ||||
Declaration: | ||||
+function get_content_type ( + item_id in cr_items.item_id%TYPE +) return cr_items.content_type%TYPE; + + |
Retrieve the parent of the given item
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Returns: | The id of the parent for this item | +|||
Parameters: | ||||
| ||||
Declaration: | ||||
+function get_context ( + item_id in cr_items.item_id%TYPE +) return acs_objects.context_id%TYPE; + + |
Takes in a path, such as "/tv/programs/star_trek/episode_203" +and returns the id of the item with this path. Note: URLs are +abstract (no extensions are allowed in content item names and +extensions are stripped when looking up content items)
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Returns: | The id of the item with the given path, or null if +no such item exists | +||||||
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+function get_id ( + item_path in varchar2, + root_folder_id in cr_items.item_id%TYPE default c_root_folder_id +) return cr_items.item_id%TYPE; + + | |||||||
See Also: | content_item.get_path | +
Retrieves the id of the latest revision for the item (as opposed +to the live revision)
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Returns: | The id of the latest revision for this item, or +null if no revisions exist | +|||
Parameters: | ||||
| ||||
Declaration: | ||||
+function get_latest_revision ( + item_id in cr_items.item_id%TYPE +) return cr_revisions.revision_id%TYPE; + + | ||||
See Also: | content_item.get_live_revision | +
Retrieves the id of the live revision for the item
Note that this function does nothing else besides retrieving the
+value of the column cr_items.live_revision
. It is thus
+more efficient in many cases to join against cr_items
+and retrieve the value directly.
Returns: | The id of the live revision for this item, or null +if no live revision exists | +|||
---|---|---|---|---|
Parameters: | ||||
| ||||
Declaration: | ||||
+function get_live_revision ( + item_id in cr_items.item_id%TYPE +) return cr_revisions.revision_id%TYPE; + + | ||||
See Also: | content_item.set_live_revision, +content_item.get_latest_revision | +
Get the parent folder.
Author: | Michael Pih | +|||
---|---|---|---|---|
Returns: | the folder_id of the parent folder, null +otherwise | +|||
Parameters: | ||||
| ||||
Declaration: | ||||
+function get_parent_folder ( + item_id in cr_items.item_id%TYPE +) return cr_folders.folder_id%TYPE; + + |
Retrieves the full path to an item, in the form of +"/tv/programs/star_trek/episode_203"
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Returns: | The path to the item | +||||||
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+function get_path ( + item_id in cr_items.item_id%TYPE, + root_folder_id in cr_items.item_id%TYPE default c_root_folder_id +) return varchar2; + + | |||||||
See Also: | content_item.get_id, content_item.write_to_file | +
Retrieves the publish date for the item
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Returns: | The publish date for the item, or null if the item +has no revisions | +||||||
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+function get_publish_date ( + item_id in cr_items.item_id%TYPE, + is_live in char default 'f' +) return cr_revisions.publish_date%TYPE; + + | |||||||
See Also: | content_item.get_live_revision, +content_item.get_latest_revision, | +
Return the total count of revisions for this item
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Returns: | The number of revisions for this item | +|||
Parameters: | ||||
| ||||
Declaration: | ||||
+function get_revision_count ( + item_id in cr_items.item_id%TYPE +) return number; + + | ||||
See Also: | content_revision.new | +
Parameters: | |
---|---|
Not yet documented | |
Declaration: | |
+function get_root_folder return cr_folders.folder_id%TYPE; + + |
Retrieves the template which should be used to render this item. +If no template is registered to specifically render the item in the +given context, the default template for the item's type is +returned.
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Returns: | The id of the registered template, or null if no +template could be found | +||||||
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+function get_template ( + item_id in cr_items.item_id%TYPE, + use_context in cr_item_template_map.use_context%TYPE +) return cr_templates.template_id%TYPE; + + | |||||||
See Also: | content_type.register_template, +content_item.register_template, | +
Retrieves the title for the item, using either the latest or the +live revision. If the specified item is in fact a folder, return +the folder's label. In addition, this function will automatically +resolve symlinks.
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Returns: | The title of the item | +||||||
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+function get_title ( + item_id in cr_items.item_id%TYPE, + is_live in char default 'f' +) return cr_revisions.title%TYPE; + + | |||||||
See Also: | content_item.get_live_revision, +content_item.get_latest_revision, content_symlink.resolve | +
Retrieves the virtual path to an item, in the form of +"/tv/programs/star_trek/episode_203"
Author: | Michael Pih | +||||||
---|---|---|---|---|---|---|---|
Returns: | The virtual path to the item | +||||||
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+function get_virtual_path ( + item_id in cr_items.item_id%TYPE, + root_folder_id in cr_items.item_id%TYPE default c_root_folder_id +) return varchar2; + + | |||||||
See Also: | content_item.get_id, content_item.write_to_file, +content_item.get_path | +
Determine if the item is an index page for the specified folder. +The item is an index page for the folder if it exists in the folder +and its item name is "index".
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Returns: | 't' if the item is an index page for the specified +folder, 'f' otherwise | +||||||
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+function is_index_page ( + item_id in cr_items.item_id%TYPE, + folder_id in cr_folders.folder_id%TYPE +) return varchar2; + + | |||||||
See Also: | content_folder.get_index_page | +
Determines if an item is publishable. Publishable items must +meet the following criteria: 1) for each child type, the item has n +children, min_n < n < max_n 2) for each relation type, the +item has n relations, min_n < n < max_n 3) any +'publishing_wf' workflows are finished
Author: | Michael Pih | +|||
---|---|---|---|---|
Returns: | 't' if the item is publishable in it's present +state, Otherwise, returns 'f' | +|||
Parameters: | ||||
| ||||
Declaration: | ||||
+function is_publishable ( + item_id in cr_items.item_id%TYPE +) return char; + + |
Determines if one type is a subclass of another. A class is +always a subclass of itself.
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Returns: | 't' if the child class is a subclass of the +superclass, 'f' otherwise | +||||||
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+function is_subclass ( + object_type in acs_object_types.object_type%TYPE, + supertype in acs_object_types.supertype%TYPE +) return char; + + | |||||||
See Also: | acs_object_type.create_type | +
Determines if an item would be a valid child of another item by +checking if the parent allows children of the would-be child's +content type and if the parent already has n_max children of that +content type.
Author: | Michael Pih | +||||||
---|---|---|---|---|---|---|---|
Returns: | 't' if the item would be a valid child, 'f' +otherwise | +||||||
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+function is_valid_child ( + item_id in cr_items.item_id%TYPE, + content_type in acs_object_types.object_type%TYPE +) return char; + + |
Creates a new content item. If the data, title +or text parameters are specified, also creates a revision +for the item.
Author: | Karl Goldstein | +|||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Returns: | The id of the newly created item | +|||||||||||||||||||||||||||||||||||||||||||||||||||
Parameters: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||||||
Declaration: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
+function new ( + name in cr_items.name%TYPE, + parent_id in acs_objects.context_id%TYPE default null, + item_id in acs_objects.object_id%TYPE default null, + locale in cr_items.locale%TYPE default null, + creation_date in acs_objects.creation_date%TYPE + default sysdate, + creation_user in acs_objects.creation_user%TYPE + default null, + creation_ip in acs_objects.creation_ip%TYPE default null, + item_subtype in acs_object_types.object_type%TYPE + default 'content_item', + content_type in acs_object_types.object_type%TYPE + default 'content_revision', + title in cr_revisions.title%TYPE default null, + description in cr_revisions.description%TYPE default null, + mime_type in cr_revisions.mime_type%TYPE default 'text/plain', + nls_language in cr_revisions.nls_language%TYPE default null, + text in varchar2 default null, + data in cr_revisions.content%TYPE default null, + relation_tag in cr_child_rels.relation_tag%TYPE default null, + is_live in char default 'f' +) return cr_items.item_id%TYPE; + + | ||||||||||||||||||||||||||||||||||||||||||||||||||||
See Also: | acs_object.new | +
Parameters: | |
---|---|
Not yet documented | |
Declaration: | |
+function relate ( + item_id in cr_items.item_id%TYPE, + object_id in acs_objects.object_id%TYPE, + relation_tag in cr_type_relations.relation_tag%TYPE default 'generic', + order_n in cr_item_rels.order_n%TYPE default null, + relation_type in acs_object_types.object_type%TYPE default 'cr_item_rel' +) return cr_item_rels.rel_id%TYPE; + + |
Copies the item to a new location, creating an identical item +with no revisions or associated workflow. If the target folder does +not exist, or if the folder already contains an item with the same +name as the given item, an error will be thrown.
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+procedure copy ( + item_id in cr_items.item_id%TYPE, + target_folder_id in cr_folders.folder_id%TYPE +); + + | |||||||
See Also: | content_item.new, content_folder.new, content_item.move | +
Deletes the specified content item, along with any revisions, +symlinks, workflows, and template relations for the item. Use with +caution - this operation cannot be undone.
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Parameters: | ||||
| ||||
Declaration: | ||||
+procedure delete ( + item_id in cr_items.item_id%TYPE +); + + | ||||
See Also: | acs_object.delete | +
Move the specified item to a different folder. If the target +folder does not exist, or if the folder already contains an item +with the same name as the given item, an error will be thrown.
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+procedure move ( + item_id in cr_items.item_id%TYPE, + target_folder_id in cr_folders.folder_id%TYPE +); + + | |||||||
See Also: | content_item.new, content_folder.new, content_item.copy | +
Registers a template which will be used to render this item.
Author: | Karl Goldstein | +|||||||||
---|---|---|---|---|---|---|---|---|---|---|
Parameters: | ||||||||||
| ||||||||||
Declaration: | ||||||||||
+procedure register_template ( + item_id in cr_items.item_id%TYPE, + template_id in cr_templates.template_id%TYPE, + use_context in cr_item_template_map.use_context%TYPE +); + + | ||||||||||
See Also: | content_type.register_template, +content_item.unregister_template, content_item.get_template | +
Renames the item. If an item with the specified name already +exists under this item's parent, an error is thrown
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+procedure rename ( + item_id in cr_items.item_id%TYPE, + name in cr_items.name%TYPE +); + + | |||||||
See Also: | content_item.new | +
Make the specified revision the live revision for the item
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Parameters: | ||||
| ||||
Declaration: | ||||
+procedure set_live_revision ( + revision_id in cr_revisions.revision_id%TYPE, + publish_status in cr_items.publish_status%TYPE default 'ready' +); + + | ||||
See Also: | content_item.get_live_revision | +
Sets the release period for the item. This information may be +used by applications to update the publishing status of items at +periodic intervals.
Author: | Karl Goldstein | +|||||||||
---|---|---|---|---|---|---|---|---|---|---|
Parameters: | ||||||||||
| ||||||||||
Declaration: | ||||||||||
+procedure set_release_period ( + item_id in cr_items.item_id%TYPE, + start_when date default null, + end_when date default null +); + + |
Unregisters a template which will be used to render this +item.
Author: | Karl Goldstein | +|||||||||
---|---|---|---|---|---|---|---|---|---|---|
Parameters: | ||||||||||
| ||||||||||
Declaration: | ||||||||||
+procedure unregister_template ( + item_id in cr_items.item_id%TYPE, + template_id in cr_templates.template_id%TYPE default null, + use_context in cr_item_template_map.use_context%TYPE default null +); + + | ||||||||||
See Also: | content_type.register_template, content_item.register_template, +content_item.get_template | +
Parameters: | |
---|---|
Not yet documented | |
Declaration: | |
+procedure unset_live_revision ( + --/** Set the live revision to null for the item + -- @author Michael Pih + -- @param item_id The id of the item for which to unset the live revision + -- @see {content_item.set_live_revision} + item_id in cr_items.item_id%TYPE +); + + |
Writes the content of the live revision of this item to a file, +creating all the neccessary directories in the process
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+procedure write_to_file ( + item_id in cr_items.item_id%TYPE, + root_path in varchar2 +); + + | |||||||
See Also: | content_item.get_path | +
+Last Modified: $Id: item.adp,v 1.1.2.1 2014/09/16 20:51:12 gustafn Exp $ + Index: openacs-4/packages/acs-content-repository/www/doc/api/keyword.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/www/doc/api/keyword.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-content-repository/www/doc/api/keyword.adp 16 Sep 2014 20:51:12 -0000 1.1.2.1 @@ -0,0 +1,285 @@ + +
+Content Repository : +content_keyword
Keyword cassify a content_item. For example: If you have some +press releases about dogs. You might want assigning the Keyword dog +to every single content_item.
Retrieves the description of the content keyword
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Returns: | The description for the specified keyword | +|||
Parameters: | ||||
| ||||
Declaration: | ||||
+function get_description ( + keyword_id in cr_keywords.keyword_id%TYPE +) return varchar2; + + | ||||
See Also: | content_keyword.get_heading, +content_keyword.set_description | +
Retrieves the heading of the content keyword
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Returns: | The heading for the specified keyword | +|||
Parameters: | ||||
| ||||
Declaration: | ||||
+function get_heading ( + keyword_id in cr_keywords.keyword_id%TYPE +) return varchar2; + + | ||||
See Also: | content_keyword.set_heading, +content_keyword.get_description | +
Retreives a path to the keyword/subject category, with the most +general category at the root of the path
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Returns: | The path to the keyword, or null if no such +keyword exists | +|||
Parameters: | ||||
| ||||
Declaration: | ||||
+function get_path ( + keyword_id in cr_keywords.keyword_id%TYPE +) return varchar2; + + | ||||
See Also: | content_keyword.new | +
Determines if the keyword is assigned to the item
Author: | Karl Goldstein | +|||||||||
---|---|---|---|---|---|---|---|---|---|---|
Returns: | 't' if the keyword may be matched to an item, 'f' +otherwise | +|||||||||
Parameters: | ||||||||||
| ||||||||||
Declaration: | ||||||||||
+function is_assigned ( + item_id in cr_items.item_id%TYPE, + keyword_id in cr_keywords.keyword_id%TYPE, + recurse in varchar2 default 'none' +) return varchar2; + + | ||||||||||
See Also: | content_keyword.item_assign | +
Determines if the keyword has no sub-keywords associated with +it
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Returns: | 't' if the keyword has no descendants, 'f' +otherwise | +|||
Parameters: | ||||
| ||||
Declaration: | ||||
+function is_leaf ( + keyword_id in cr_keywords.keyword_id%TYPE +) return varchar2; + + | ||||
See Also: | content_keyword.new | +
Creates a new keyword (also known as "subject category").
Author: | Karl Goldstein | +||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Returns: | The id of the newly created keyword | +||||||||||||||||||||||||
Parameters: | |||||||||||||||||||||||||
| |||||||||||||||||||||||||
Declaration: | |||||||||||||||||||||||||
+function new ( + heading in cr_keywords.heading%TYPE, + description in cr_keywords.description%TYPE default null, + parent_id in cr_keywords.parent_id%TYPE default null, + keyword_id in cr_keywords.keyword_id%TYPE default null, + creation_date in acs_objects.creation_date%TYPE + default sysdate, + creation_user in acs_objects.creation_user%TYPE + default null, + creation_ip in acs_objects.creation_ip%TYPE default null, + object_type in acs_object_types.object_type%TYPE default 'content_keyword' +) return cr_keywords.keyword_id%TYPE; + + | |||||||||||||||||||||||||
See Also: | acs_object.new, content_item.new, content_keyword.item_assign, +content_keyword.delete | +
Deletes the specified keyword, which must be a leaf. Unassigns +the keyword from all content items. Use with caution - this +operation cannot be undone.
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Parameters: | ||||
| ||||
Declaration: | ||||
+procedure delete ( + keyword_id in cr_keywords.keyword_id%TYPE +); + + | ||||
See Also: | acs_object.delete, content_keyword.item_unassign | +
Assigns this keyword to a content item, creating a relationship +between them
Author: | Karl Goldstein | +|||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Parameters: | ||||||||||||||||
| ||||||||||||||||
Declaration: | ||||||||||||||||
+procedure item_assign ( + item_id in cr_items.item_id%TYPE, + keyword_id in cr_keywords.keyword_id%TYPE, + context_id in acs_objects.context_id%TYPE default null, + creation_user in acs_objects.creation_user%TYPE default null, + creation_ip in acs_objects.creation_ip%TYPE default null +); + + | ||||||||||||||||
See Also: | acs_rel.new, content_keyword.item_unassign | +
Unassigns this keyword to a content item, removing a +relationship between them
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+procedure item_unassign ( + item_id in cr_items.item_id%TYPE, + keyword_id in cr_keywords.keyword_id%TYPE +); + + | |||||||
See Also: | acs_rel.delete, content_keyword.item_assign | +
Sets a new description for the keyword
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+procedure set_description ( + keyword_id in cr_keywords.keyword_id%TYPE, + description in cr_keywords.description%TYPE +); + + | |||||||
See Also: | content_keyword.set_heading, +content_keyword.get_description | +
Sets a new heading for the keyword
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+procedure set_heading ( + keyword_id in cr_keywords.keyword_id%TYPE, + heading in cr_keywords.heading%TYPE +); + + | |||||||
See Also: | content_keyword.get_heading, +content_keyword.set_description | +
+Last Modified: $Id: keyword.html,v 1.1.1.1 2001/03/13 22:59:26 ben +Exp $ + Index: openacs-4/packages/acs-content-repository/www/doc/api/permission.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/www/doc/api/permission.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-content-repository/www/doc/api/permission.adp 16 Sep 2014 20:51:12 -0000 1.1.2.1 @@ -0,0 +1,242 @@ + +
+Content Repository : +content_permission
Permissions can be set to allow certain users certain things. - +They can be compared with the Unix filesystem permission: read, +write ...
Determine if the user may grant a certain permission to another +user. The permission may only be granted if the user has the +permission himself and posesses the cm_perm access, or if the user +posesses the cm_perm_admin access.
Author: | Karl Goldstein | +|||||||||
---|---|---|---|---|---|---|---|---|---|---|
Returns: | 't' if the donation is possible, 'f' +otherwise | +|||||||||
Parameters: | ||||||||||
| ||||||||||
Declaration: | ||||||||||
+ function has_grant_authority ( + object_id in acs_objects.object_id%TYPE, + holder_id in parties.party_id%TYPE, + privilege in acs_privileges.privilege%TYPE + ) return varchar2; + + | ||||||||||
See Also: | content_permission.grant_permission, +content_permission.is_has_revoke_authority, +acs_permission.grant_permission | +
Determine if the user may take a certain permission away from +another user. The permission may only be revoked if the user has +the permission himself and posesses the cm_perm access, while the +other user does not, or if the user posesses the cm_perm_admin +access.
Author: | Karl Goldstein | +||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Returns: | 't' if it is possible to revoke the privilege, 'f' +otherwise | +||||||||||||
Parameters: | |||||||||||||
| |||||||||||||
Declaration: | |||||||||||||
+ function has_revoke_authority ( + object_id in acs_objects.object_id%TYPE, + holder_id in parties.party_id%TYPE, + privilege in acs_privileges.privilege%TYPE, + revokee_id in parties.party_id%TYPE + ) return varchar2; + + | |||||||||||||
See Also: | content_permission.has_grant_authority, +content_permission.revoke_permission, +acs_permission.revoke_permission | +
Determine if the user has the specified permission on the +specified object. Does NOT check objects recursively: that is, if +the user has the permission on the parent object, he does not +automatically gain the permission on all the child objects.
Author: | Karl Goldstein | +|||||||||
---|---|---|---|---|---|---|---|---|---|---|
Returns: | 't' if the user has the specified permission on +the object, 'f' otherwise | +|||||||||
Parameters: | ||||||||||
| ||||||||||
Declaration: | ||||||||||
+ function permission_p ( + object_id in acs_objects.object_id%TYPE, + holder_id in parties.party_id%TYPE, + privilege in acs_privileges.privilege%TYPE + ) return varchar2; + + | ||||||||||
See Also: | content_permission.grant_permission, +content_permission.revoke_permission, +acs_permission.permission_p | +
This is a helper function for +content_permission.grant_permission and should not be called +individually.
Grants a permission and revokes all descendants of the +permission, since they are no longer relevant.
Author: | Karl Goldstein | +|||||||||
---|---|---|---|---|---|---|---|---|---|---|
Parameters: | ||||||||||
| ||||||||||
Declaration: | ||||||||||
+ procedure grant_permission_h ( + object_id in acs_objects.object_id%TYPE, + grantee_id in parties.party_id%TYPE, + privilege in acs_privileges.privilege%TYPE + ); + + | ||||||||||
See Also: | content_permission.grant_permission | +
This is a helper function for +content_permission.grant_permission and should not be called +individually.
Grants a permission and revokes all descendants of the +permission, since they are no longer relevant.
Author: | Karl Goldstein | +|||||||||
---|---|---|---|---|---|---|---|---|---|---|
Parameters: | ||||||||||
| ||||||||||
Declaration: | ||||||||||
+ procedure grant_permission_h ( + object_id in acs_objects.object_id%TYPE, + grantee_id in parties.party_id%TYPE, + privilege in acs_privileges.privilege%TYPE + ); + + | ||||||||||
See Also: | content_permission.grant_permission | +
Make the child object inherit all of the permissions of the +parent object. Typically, this function is called whenever a new +object is created under a given parent
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+ procedure inherit_permissions ( + parent_object_id in acs_objects.object_id%TYPE, + child_object_id in acs_objects.object_id%TYPE, + child_creator_id in parties.party_id%TYPE default null + ); + + | |||||||
See Also: | content_permission.grant, acs_permission.grant_permission | +
This is a helper function for +content_permission.revoke_permission and should not be called +individually.
Revokes a permission but grants all child permissions to the +holder, to ensure that the permission is not permanently lost
Author: | Karl Goldstein | +|||||||||
---|---|---|---|---|---|---|---|---|---|---|
Parameters: | ||||||||||
| ||||||||||
Declaration: | ||||||||||
+ procedure revoke_permission_h ( + object_id in acs_objects.object_id%TYPE, + revokee_id in parties.party_id%TYPE, + privilege in acs_privileges.privilege%TYPE + ); + + | ||||||||||
See Also: | content_permission.revoke_permission | +
This is a helper function for +content_permission.revoke_permission and should not be called +individually.
Revokes a permission but grants all child permissions to the +holder, to ensure that the permission is not permanently lost
Author: | Karl Goldstein | +|||||||||
---|---|---|---|---|---|---|---|---|---|---|
Parameters: | ||||||||||
| ||||||||||
Declaration: | ||||||||||
+ procedure revoke_permission_h ( + object_id in acs_objects.object_id%TYPE, + revokee_id in parties.party_id%TYPE, + privilege in acs_privileges.privilege%TYPE + ); + + | ||||||||||
See Also: | content_permission.revoke_permission | +
+Last Modified: $Id: permission.html,v 1.1.1.1 2001/03/13 22:59:26 +ben Exp $ + Index: openacs-4/packages/acs-content-repository/www/doc/api/revision.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/www/doc/api/revision.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-content-repository/www/doc/api/revision.adp 16 Sep 2014 20:51:12 -0000 1.1.2.1 @@ -0,0 +1,218 @@ + +
+Content Repository : +content_revision
Content revisions contain the data for content items. There is a +many to one relationship between content revisions and content +items. There is at most one "live" revision for every content item +though. For example, there may be 5 revisions of the review for the +movie "Terminator," yet only one of these may be live on the +website at a given time.
Creates a new copy of an attribute, including all attributes
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Parameters: | ||||
| ||||
Declaration: | ||||
+function copy ( + revision_id in cr_revisions.revision_id%TYPE, + copy_id in cr_revisions.revision_id%TYPE default null +) return cr_revisions.revision_id%TYPE; + + | ||||
See Also: | content_revision.new | +
Parameters: | |
---|---|
Not yet documented | |
Declaration: | |
+function export_xml ( + revision_id IN cr_revisions.revision_id%TYPE +) return cr_xml_docs.doc_id%TYPE; + + |
Return the revision number of the specified revision, according +to the chronological order in which revisions have been added for +this item.
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Returns: | The number of the revision | +|||
Parameters: | ||||
| ||||
Declaration: | ||||
+function get_number ( + revision_id in cr_revisions.revision_id%TYPE +) return number; + + | ||||
See Also: | content_revision.new | +
Parameters: | |
---|---|
Not yet documented | |
Declaration: | |
+function import_xml ( + item_id IN cr_items.item_id%TYPE, + revision_id IN cr_revisions.revision_id%TYPE, + doc_id IN number +) return cr_revisions.revision_id%TYPE; + + |
Create a new revision for an item.
Author: | Karl Goldstein | +|||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Returns: | The id of the newly created revision | +|||||||||||||||||||||||||||||||||
Parameters: | ||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||
Declaration: | ||||||||||||||||||||||||||||||||||
+function new ( + title in cr_revisions.title%TYPE, + description in cr_revisions.description%TYPE default null, + publish_date in cr_revisions.publish_date%TYPE default sysdate, + mime_type in cr_revisions.mime_type%TYPE default 'text/plain', + nls_language in cr_revisions.nls_language%TYPE default null, + data in cr_revisions.content%TYPE, + item_id in cr_items.item_id%TYPE, + revision_id in cr_revisions.revision_id%TYPE default null, + creation_date in acs_objects.creation_date%TYPE + default sysdate, + creation_user in acs_objects.creation_user%TYPE + default null, + creation_ip in acs_objects.creation_ip%TYPE default null +) return cr_revisions.revision_id%TYPE; + + | ||||||||||||||||||||||||||||||||||
See Also: | acs_object.new, content_item.new | +
Parameters: | |
---|---|
Not yet documented | |
Declaration: | |
+function read_xml ( + item_id IN number, + revision_id IN number, + clob_loc IN clob +) return number as language + java +name + 'com.arsdigita.content.XMLExchange.importRevision( + java.lang.Integer, java.lang.Integer, oracle.sql.CLOB + ) return int'; + + |
Parameters: | |
---|---|
Not yet documented | |
Declaration: | |
+function write_xml ( + revision_id IN number, + clob_loc IN clob +) return number as language + java +name + 'com.arsdigita.content.XMLExchange.exportRevision( + java.lang.Integer, oracle.sql.CLOB + ) return int'; + + |
Deletes the revision.
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Parameters: | ||||
| ||||
Declaration: | ||||
+procedure delete ( + revision_id in cr_revisions.revision_id%TYPE +); + + | ||||
See Also: | content_revision.new, acs_object.delete | +
Generates an XML document for insertion into +cr_revision_attributes, which is indexed by Intermedia for +searching attributes.
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Parameters: | ||||
| ||||
Declaration: | ||||
+procedure index_attributes( + revision_id IN cr_revisions.revision_id%TYPE +); + + | ||||
See Also: | content_revision.new | +
Parameters: | |
---|---|
Not yet documented | |
Declaration: | |
+procedure replace( + revision_id number, search varchar2, replace varchar2) +as language + java +name + 'com.arsdigita.content.Regexp.replace( + int, java.lang.String, java.lang.String + )'; + + |
Converts a revision uploaded as a binary document to html
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Parameters: | ||||
| ||||
Declaration: | ||||
+procedure to_html ( + revision_id IN cr_revisions.revision_id%TYPE +); + + |
+Last Modified: $Id: revision.html,v 1.1.1.1 2001/03/13 22:59:26 ben +Exp $ + Index: openacs-4/packages/acs-content-repository/www/doc/api/symlink.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/www/doc/api/symlink.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-content-repository/www/doc/api/symlink.adp 16 Sep 2014 20:51:12 -0000 1.1.2.1 @@ -0,0 +1,151 @@ + +
+Content Repository : +content_symlink
Symlinks are pointers to items within the content repository. +They are simply used to create links between content items.
Determines if the item is a symlink
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Returns: | 't' if the item is a symlink, 'f' otherwise | +|||
Parameters: | ||||
| ||||
Declaration: | ||||
+function is_symlink ( + item_id in cr_items.item_id%TYPE +) return char; + + | ||||
See Also: | content_symlink.new, content_symlink.resolve | +
Create a new symlink, linking two items
Author: | Karl Goldstein | +||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Returns: | The id of the newly created symlink | +||||||||||||||||||||||||
Parameters: | |||||||||||||||||||||||||
| |||||||||||||||||||||||||
Declaration: | |||||||||||||||||||||||||
+function new ( + name in cr_items.name%TYPE default null, + label in cr_symlinks.label%TYPE default null, + target_id in cr_items.item_id%TYPE, + parent_id in acs_objects.context_id%TYPE, + symlink_id in cr_symlinks.symlink_id%TYPE default null, + creation_date in acs_objects.creation_date%TYPE + default sysdate, + creation_user in acs_objects.creation_user%TYPE + default null, + creation_ip in acs_objects.creation_ip%TYPE default null +) return cr_symlinks.symlink_id%TYPE; + + | |||||||||||||||||||||||||
See Also: | acs_object.new, content_item.new, content_symlink.resolve | +
Resolves the symlink and returns the target item id.
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Returns: | The target item of the symlink, or the original +item id if the item is not in fact a symlink | +|||
Parameters: | ||||
| ||||
Declaration: | ||||
+function resolve ( + item_id in cr_items.item_id%TYPE +) return cr_items.item_id%TYPE; + + | ||||
See Also: | content_symlink.new, content_symlink.is_symlink | +
Gets the content type of the target item.
Author: | Michael Pih | +|||
---|---|---|---|---|
Returns: | The content type of the symlink target, otherwise +null. the item is not in fact a symlink | +|||
Parameters: | ||||
| ||||
Declaration: | ||||
+function resolve_content_type ( + item_id in cr_items.item_id%TYPE +) return cr_items.content_type%TYPE; + + | ||||
See Also: | content_symlink.resolve | +
Copies the symlink itself to another folder, without resolving +the symlink
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+procedure copy ( + symlink_id in cr_symlinks.symlink_id%TYPE, + target_folder_id in cr_folders.folder_id%TYPE +); + + | |||||||
See Also: | content_symlink.new, content_item.copy | +
Deletes the symlink
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Parameters: | ||||
| ||||
Declaration: | ||||
+procedure delete ( + symlink_id in cr_symlinks.symlink_id%TYPE +); + + | ||||
See Also: | content_symlink.new, acs_object.delete | +
+Last Modified: $Id: symlink.html,v 1.1.1.1.28.1 2014/09/16 20:43:09 +gustafn Exp $ + Index: openacs-4/packages/acs-content-repository/www/doc/api/template.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/www/doc/api/template.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-content-repository/www/doc/api/template.adp 16 Sep 2014 20:51:12 -0000 1.1.2.1 @@ -0,0 +1,128 @@ + +
+Content Repository : +content_template
Templates are a special class of text objects that are used for +specifying the layout of a content item. They may be mapped to +content types, meaning that every item of that type will display +using that template unless a specific item overrides the default by +mapping to a template itself.
Retrieves the full path to the template, as described in +content_item.get_path
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Returns: | The path to the template, starting with the +specified root folder | +||||||
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+function get_path ( + template_id in cr_templates.template_id%TYPE, + root_folder_id in cr_folders.folder_id%TYPE default c_root_folder_id +) return varchar2; + + | |||||||
See Also: | content_item.get_path | +
Parameters: | |
---|---|
Not yet documented | |
Declaration: | |
+function get_root_folder return cr_folders.folder_id%TYPE; + + |
Determine if an item is a template.
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Returns: | 't' if the item is a template, 'f' otherwise | +|||
Parameters: | ||||
| ||||
Declaration: | ||||
+function is_template ( + template_id in cr_templates.template_id%TYPE +) return varchar2; + + | ||||
See Also: | content_template.new | +
Creates a new content template which can be used to render +content items.
Author: | Karl Goldstein | +||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Returns: | The id of the newly created template | +||||||||||||||||||
Parameters: | |||||||||||||||||||
| |||||||||||||||||||
Declaration: | |||||||||||||||||||
+function new ( + name in cr_items.name%TYPE, + parent_id in acs_objects.context_id%TYPE default null, + template_id in cr_templates.template_id%TYPE default null, + creation_date in acs_objects.creation_date%TYPE + default sysdate, + creation_user in acs_objects.creation_user%TYPE + default null, + creation_ip in acs_objects.creation_ip%TYPE default null +) return cr_templates.template_id%TYPE; + + | |||||||||||||||||||
See Also: | acs_object.new, content_item.new, +content_item.register_template, content_type.register_template | +
Deletes the specified template, and unregisters the template +from all content types and content items. Use with caution - this +operation cannot be undone.
Author: | Karl Goldstein | +|||
---|---|---|---|---|
Parameters: | ||||
| ||||
Declaration: | ||||
+procedure delete ( + template_id in cr_templates.template_id%TYPE +); + + | ||||
See Also: | acs_object.delete, content_item.unregister_template, +content_type.unregister_template, | +
+Last Modified: $Id: template.html,v 1.1.1.1 2001/03/13 22:59:26 ben +Exp $ + Index: openacs-4/packages/acs-content-repository/www/doc/api/type.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/www/doc/api/type.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-content-repository/www/doc/api/type.adp 16 Sep 2014 20:51:13 -0000 1.1.2.1 @@ -0,0 +1,406 @@ + +
+Content Repository : +content_type
This package is used to manipulate content types and attributes +Content types represent the different kind of content displayed on +a website. All content items should subclass a content type.
Create a new attribute for the specified type. Automatically +create the column for the attribute if the column does not already +exist.
Author: | Karl Goldstein | +|||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Returns: | The id of the newly created attribute | +|||||||||||||||
Parameters: | ||||||||||||||||
| ||||||||||||||||
Declaration: | ||||||||||||||||
+function create_attribute ( + content_type in acs_attributes.object_type%TYPE, + attribute_name in acs_attributes.attribute_name%TYPE, + datatype in acs_attributes.datatype%TYPE, + pretty_name in acs_attributes.pretty_name%TYPE, + pretty_plural in acs_attributes.pretty_plural%TYPE default null, + default_value in acs_attributes.default_value%TYPE default null, + column_spec in varchar2 default 'varchar2(4000)' +) return acs_attributes.attribute_id%TYPE; + + | ||||||||||||||||
See Also: | acs_object_type.create_attribute, content_type.create_type | +
Retrieve the appropriate template for rendering items of the +specified type.
Author: | Karl Goldstein | +||||||
---|---|---|---|---|---|---|---|
Returns: | The ID of the template to use | +||||||
Parameters: | |||||||
| |||||||
Declaration: | |||||||
+function get_template ( + content_type in cr_type_template_map.content_type%TYPE, + use_context in cr_type_template_map.use_context%TYPE +) return cr_templates.template_id%TYPE; + + | |||||||
See Also: | content_item.register_template, +content_item.unregister_template, content_item.get_template, +content_type.unregister_template, content_type.register_template, +content_type.set_default_template | +
Parameters: | |
---|---|
Not yet documented | |
Declaration: | |
+function is_content_type ( + object_type in acs_object_types.object_type%TYPE +) return char; + + |
Create a new content type. Automatically create the attribute +table for the type if the table does not already exist.
Author: | Karl Goldstein | +|||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Parameters: | ||||||||||||||||||||||
| ||||||||||||||||||||||
Declaration: | ||||||||||||||||||||||
+procedure create_type ( + content_type in acs_object_types.object_type%TYPE, + supertype in acs_object_types.object_type%TYPE + default 'content_revision', + pretty_name in acs_object_types.pretty_name%TYPE, + pretty_plural in acs_object_types.pretty_plural%TYPE, + table_name in acs_object_types.table_name%TYPE default null, + id_column in acs_object_types.id_column%TYPE default 'XXX', + name_method in acs_object_types.name_method%TYPE default null +); + + | ||||||||||||||||||||||
See Also: | acs_object_type.create_type | +
Drop an existing attribute. If you are using CMS, make sure to +call cm_form_widget.unregister_attribute_widget before +calling this function.
Author: | Karl Goldstein | +|||||||||
---|---|---|---|---|---|---|---|---|---|---|
Parameters: | ||||||||||
| ||||||||||
Declaration: | ||||||||||
+procedure drop_attribute ( + content_type in acs_attributes.object_type%TYPE, + attribute_name in acs_attributes.attribute_name%TYPE, + drop_column in varchar2 default 'f' +); + + | ||||||||||
See Also: | acs_object.drop_attribute, content_type.create_attribute, +cm_form_widget.unregister_attribute_widget | +
Create a view for the type which joins all attributes of the +type, including the inherited attributes. The view is named "
+X" Called by create_attribute and create_type. +Author: | Karl Goldstein | +|||
---|---|---|---|---|
Parameters: | ||||
| ||||
Declaration: | ||||
+procedure refresh_view ( + content_type in cr_type_template_map.content_type%TYPE +); + + | ||||
See Also: | content_type.create_type | +
Register a parent-child relationship between a content type and +another object type. This may then be used by the +content_item.is_valid_relation function to validate the +relationship between an item and a potential child.
Author: | Karl Goldstein | +|||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Parameters: | ||||||||||||||||
| ||||||||||||||||
Declaration: | ||||||||||||||||
+procedure register_child_type ( + parent_type in cr_type_children.parent_type%TYPE, + child_type in cr_type_children.child_type%TYPE, + relation_tag in cr_type_children.relation_tag%TYPE default 'generic', + min_n in integer default 0, + max_n in integer default null +); + + | ||||||||||||||||
See Also: | content_type.register_relation_type, +content_type.register_child_type | +
Parameters: | |
---|---|
Not yet documented | |
Declaration: | |
+procedure register_mime_type ( + content_type in cr_content_mime_type_map.content_type%TYPE, + mime_type in cr_content_mime_type_map.mime_type%TYPE +); + + |
Register a relationship between a content type and another +object type. This may then be used by the +content_item.is_valid_relation function to validate any +relationship between an item and another object.
Author: | Karl Goldstein | +|||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Parameters: | ||||||||||||||||
| ||||||||||||||||
Declaration: | ||||||||||||||||
+procedure register_relation_type ( + content_type in cr_type_relations.content_type%TYPE, + target_type in cr_type_relations.target_type%TYPE, + relation_tag in cr_type_relations.relation_tag%TYPE default 'generic', + min_n in integer default 0, + max_n in integer default null +); + + | ||||||||||||||||
See Also: | content_type.unregister_relation_type | +
Register a template for the content type. This template may be +used to render all items of that type.
Author: | Karl Goldstein | +||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Parameters: | |||||||||||||
| |||||||||||||
Declaration: | |||||||||||||
+procedure register_template ( + content_type in cr_type_template_map.content_type%TYPE, + template_id in cr_templates.template_id%TYPE, + use_context in cr_type_template_map.use_context%TYPE, + is_default in cr_type_template_map.is_default%TYPE default 'f' +); + + | |||||||||||||
See Also: | content_item.register_template, +content_item.unregister_template, content_item.get_template, +content_type.unregister_template, +content_type.set_default_template, content_type.get_template | +
Make the registered template a default template. The default +template will be used to render all items of the type for which no +individual template is registered.
Author: | Karl Goldstein | +|||||||||
---|---|---|---|---|---|---|---|---|---|---|
Parameters: | ||||||||||
| ||||||||||
Declaration: | ||||||||||
+procedure set_default_template ( + content_type in cr_type_template_map.content_type%TYPE, + template_id in cr_templates.template_id%TYPE, + use_context in cr_type_template_map.use_context%TYPE +); + + | ||||||||||
See Also: | content_item.register_template, +content_item.unregister_template, content_item.get_template, +content_type.unregister_template, content_type.register_template, +content_type.get_template | +
Register a parent-child relationship between a content type and +another object type. This may then be used by the +content_item.is_valid_relation function to validate the +relationship between an item and a potential child.
Author: | Karl Goldstein | +|||||||||
---|---|---|---|---|---|---|---|---|---|---|
Parameters: | ||||||||||
| ||||||||||
Declaration: | ||||||||||
+procedure unregister_child_type ( + parent_type in cr_type_children.parent_type%TYPE, + child_type in cr_type_children.child_type%TYPE, + relation_tag in cr_type_children.relation_tag%TYPE default null +); + + | ||||||||||
See Also: | content_type.register_relation_type, +content_type.register_child_type | +
Parameters: | |
---|---|
Not yet documented | |
Declaration: | |
+procedure unregister_mime_type ( + content_type in cr_content_mime_type_map.content_type%TYPE, + mime_type in cr_content_mime_type_map.mime_type%TYPE +); + + |
Unregister a relationship between a content type and another +object type.
Author: | Karl Goldstein | +|||||||||
---|---|---|---|---|---|---|---|---|---|---|
Parameters: | ||||||||||
| ||||||||||
Declaration: | ||||||||||
+procedure unregister_relation_type ( + content_type in cr_type_relations.content_type%TYPE, + target_type in cr_type_relations.target_type%TYPE, + relation_tag in cr_type_relations.relation_tag%TYPE default null +); + + | ||||||||||
See Also: | content_type.register_relation_type | +
Unregister a template. If the unregistered template was the +default template, the content_type can no longer be rendered in the +use_context,
Author: | Karl Goldstein | +|||||||||
---|---|---|---|---|---|---|---|---|---|---|
Parameters: | ||||||||||
| ||||||||||
Declaration: | ||||||||||
+procedure unregister_template ( + content_type in cr_type_template_map.content_type%TYPE default null, + template_id in cr_templates.template_id%TYPE, + use_context in cr_type_template_map.use_context%TYPE default null +); + + | ||||||||||
See Also: | content_item.register_template, +content_item.unregister_template, content_item.get_template, +content_type.set_default_template, content_type.register_template, +content_type.get_template | +
+Last Modified: $Id: type.html,v 1.1.1.1 2001/03/13 22:59:26 ben Exp +$ + Index: openacs-4/packages/acs-content-repository/www/doc/guide/access-control.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/www/doc/guide/access-control.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-content-repository/www/doc/guide/access-control.adp 16 Sep 2014 20:51:13 -0000 1.1.2.1 @@ -0,0 +1,7 @@ + +
Last Modified: $Id: access-control.html,v 1.1.1.1 2001/03/13 +22:59:26 ben Exp $
Index: openacs-4/packages/acs-content-repository/www/doc/guide/convert.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/www/doc/guide/convert.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-content-repository/www/doc/guide/convert.adp 16 Sep 2014 20:51:13 -0000 1.1.2.1 @@ -0,0 +1,42 @@ + +The content repository uses the INSO libraries included with +Intermedia to support conversion of binary files such as Microsoft +Word documents to HTML. This document describes how to make this +conversion be part of the item creation or editing process, such +that the content is always stored in the repository as HTML.
+Note: Because temporary tables and LOB storage are used +during the conversion process, the entire process described here +must be performed within the context of a single transaction.
The first step is to create the revision that will be associated +with the converted document, and obtain the corresponding ID. The +content column for the revision must be initialized with +an empty blob object:
+revision_id := content_revision.new(item_id => :item_id, + revision_id => :revision_id, + data => empty_blob(), + title => 'My Word Document', + ...); +
The next step in the process is to upload the binary file into +the temporary table cr_doc_filter. This may be done using +any standard technique for uploading a binary file, such as an +image. The temporary table has only two columns; one is a BLOB to +store the document itself, and one is the revision ID.
Once the revision has been created and the file has been +uploaded, the file may be converted to HTML and written into the +empty blob associated with the revision. This is done with the +to_html procedure in the content_revision +package:
+begin + content_revision.to_html(:revision_id); +end; +/ +
Once the transaction is committed, the uploaded document is +automatically deleted from the cr_doc_filter table.
The content repository organizes content items in a hierarchical +structure similar to a file system. You manage content items in the +repository using the same basic operations as in a file system:
The content repository adds an additional twist to a traditional +filesystem: any content item, not just a folder, may serve +as a container for any number of other content items. For example, +imagine a book consisting of a preface, a number of chapters and a +bibliography (which in turn may have any number of entries). The +book itself is a content item, in that it has attributes +(publisher, ISBN number, publication date, synopsis, etc.) +associated with it. It also is the logical container for all its +components.
It is important to note that folders are simply a special +subtype of content item. The content repository's representation of +a parent-child relationship between a folder and the items it +contains is no different from the relationship between a book and +its chapters. Folders may be thought of simply as generic +containers for grouping items that are not necessarily part of a +greater whole.
Consider a simple repository structure with the following +contents:
Note the following:
Note that the same effective organization could have been +achieved by creating the "Press Index" item under the root, and +having press releases as its children. Using the folder approach +may have the following advantages:
By default, the content repository has one root folder for +content items and one for templates. In some situations, that is +not enough. For example, a package that can be instantiated several +times might wish to store the content for each instance in its own +content root. Creating your own content (and template) root also +has the advantage that you will not accidentally access another +package's content nor will another package access your content. Not +that that could do any harm, because you have secured all your +content through appropriate permissions.
We only talk about creating content roots from here on — +creating template roots is completely analogous. You create your +own content root by calling content_folder.new in +PL/SQL:
+declare + v_my_content_root integer; +begin + v_my_content_root := content_folder.new( + name => 'my_root', + label => 'My Root', + parent_id => 0 + ); + -- Store v_my_content_root in a safe place +end; +/ +
The important point is that you have to pass in 0 for +the parent_id. This parent_id is special in that +it indicates folders with no parent.
The content repository does not keep track of who created what +root folders. You have to do that yourself. In the above example, +you need to store the value v_my_content_root somewhere, +for example a table that is specific for your package, otherwise +you won't have a reliable way of accessing your new content +root.
With multiple content roots, there can be many items with +item_path'/news/article' and you need to tell +the content repository which root you are talking about. For +example, to retrieve content through content_item.get_id, +you pass the id of your content root as the root_folder_id +parameter to specify the content root under which the +item_path should be resolved.
Content items are initialized using the +content_item.new function. A name is the only parameter +required to create an item:
+item_id := content_item.new( name => 'my_item' ); +
The name represents the tail of the URL for that content item. +In most cases you will want to create items in a particular context +with the repository hierarchy:
+item_id := content_item.new( + name => 'my_item', + parent_id => :parent_id +); +
The parent ID must be another content item, or a subclass of +content item such as a folder.
The content_item.new function accepts a number of other +optional parameters. The standard creation_date, +creation_user and creation_ip should be specified +for auditing purposes. You can also create the initial revision and +publish text items in a single step:
+item_id := content_item.new( + name => 'my_item', + parent_id => :parent_id, + title => 'My Item', + text => 'Once upon a time Goldilocks crossed the street. + Here comes a car...uh oh! The End', + is_live => 't' +); +
If either the title or text are not null, the function will +create the first revision of the item. It will also mark the item +as live if the is_live parameter is true. The alternative +to this one step method is to create a content item and then add a +revision using the Content Revision API.
If a content item has at least one revision, then it can be +published by calling the content_item.set_live_revision +procedure, which takes as input a revision_id:
+content_item.set_live_revision( revision_id => :revision_id ); +
Last Modified: $Id: items.html,v 1.1.1.1 2001/03/13 22:59:26 ben +Exp $
+ Index: openacs-4/packages/acs-content-repository/www/doc/guide/keywords.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/www/doc/guide/keywords.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-content-repository/www/doc/guide/keywords.adp 16 Sep 2014 20:51:13 -0000 1.1.2.1 @@ -0,0 +1,132 @@ + ++Subject Keywords are used to implement categorization +for the Content Management system. A Subject Keyword is a small +label, such as "Oracle Documentation" or "My Favorite Foods", which +can be associated with any number of content items. Thus, content +items may be grouped by arbitrary categories. For example, +assigning the Subject Keyword "My Favorite Foods" to the content +items "Potstickers", "Strawberries" and "Ice Cream" would indicate +that all the three items belong in the same category - namely, the +category of the user's favorite foods. The actual physical location +of these items within the repository is irrelevant.
Subject Keywords may be nested to provide more detailed control +over categorization; for example, "My Favorite Foods" may be +further subdivided into "Healthy" and "Unhealthy". Subject Keywords +which have descendants are referred to as "Subject +Categories".
The content_keyword object type is used to represent +Subject Keywords (see content_keyword.sql) The +content_keyword type inherits from +acs_object:
+ acs_object_type.create_type ( supertype => 'acs_object', object_type + => 'content_keyword', pretty_name => 'Content Keyword', + pretty_plural => 'Content Keywords', table_name => 'cr_keywords', + id_column => 'keyword_id', name_method => 'acs_object.default_name' + ); ++In addition, the cr_keywords table (see +content-create.sql) contains extended attributes of +Subject Keywords: +
+create table cr_keywords ( + keyword_id integer + constraint cr_keywords_pk + primary key, + heading varchar2(600) + constraint cr_keywords_name_nil + not null, + description varchar2(4000) +); ++In content-keyword.sql: +
+attr_id := acs_attribute.create_attribute ( + object_type => 'acs_object', + attribute_name => 'heading', + datatype => 'string', + pretty_name => 'Heading', + pretty_plural => 'Headings' +); + +attr_id := acs_attribute.create_attribute ( + object_type => 'content_keyword', + attribute_name => 'description', + datatype => 'string', + pretty_name => 'Description', + pretty_plural => 'Descriptions' +); +
Thus, each Subject Keyword has a heading, which is a +user-readable heading for the keyword, and a description, +which is a somewhat longer description of the keyword.
The cr_item_keyword_map table (see +content-create.sql) is used to relate content items to +keywords:
+create table cr_item_keyword_map ( + item_id integer + constraint cr_item_keyword_map_item_fk + references cr_items + constraint cr_item_keyword_map_item_nil + not null, + keyword_id integer + constraint cr_item_keyword_map_kw_fk + references cr_keywords + constraint cr_item_keyword_map_kw_nil + not null + constraint cr_item_keyword_map_pk + primary key (item_id, keyword_id) +); +
The API used to access and modify content keywords are outlined +below. The function names are links that will take you to a more +detailed description of the function and its parameters.
Function/Procedure | Purpose | Description | +
---|---|---|
new | Create a new Subject Keyword | This is a standard new function, used to create a new +Subject Keyword. If the parent id is specified, the new keword +becomes a child of the parent keyword (which may now be called a +Subject Category) | +
delete | Delete a Subject Keyword | This is a standard delete function, used to delete a +Subject Keyword | +
+get_heading set_heading get_description set_description + | Manipulate properties of the Keyword | You must use these functions to manipulate the properties of a +keyword. In the future, the data model will be updated to handle +internatiolization, but the API will not change. | +
+item_assign item_unassign is_assigned + | Assign Keywords to Items | These functions should be used to assign Subject Keywords to
+content items, to unassign keywords from items, and to determine
+whether a particular keyword is assigned to an item.
+ The is_assigned function can be used to determine if a +keyword matches a content item, based on the recurse +parameter:
|
+
Many applications of the content repository require that content +items be related to each other as well as to other classes of +objects. Examples include:
The ACS kernel provides a standard, highly flexible data model +and API for relating objects to other objects. If you have a highly +specific problem and are developing your own user interface on the +content repository, you can use the ACS relationships framework +directly. The relationship framework in the content repository +itself is simply intended as a convenience for handling common +relationship situations involving content items.
In many cases one content item may serve as a natural container +for another item. An article divided into sections, or a news story +with an associated photo are one example of this. These +"parent-child" relationships are handled by the basic hierarchical +organization of the content repository. Every item has a parent +item, represented internally by the parent_id column in +the cr_items table.
It is often desirable to constrain the number and content type +of child items. For example, the specifications for a news story +may only allow for a single photo. A structured report may have +exactly three sections. Furthermore, it may be necessary to +classify or identify child items of the same type. Clearly the +sections of a report would have a logical order in which they would +need to be presented to the user. The layout for a photo album may +have a special position for a "featured" photo.
+ |
The content repository accomodates these situations in the +following ways:
Note that there is no currently no explicit API to "add a +child." You specify the parent of an item upon creating it. You can +use the API procedure content_item.move to change the +parent of an item.
In addition to the relationships to their parents and children +in the content repository hierarchy, content items may be linked to +any number of other objects in the system. This may include +products, users or content items on related subjects.
The same need to constrain the possibilities for an item-object +relationship, as described above for parents and children, also +apply to items and objects in general. The content repository +provides a data model and API for managing these constraints that +parallels what is provided for parent-child relationships:
The simple relation mechanisms described above may not be +sufficient for some applications. However, because both +relationships defined by the content repository are +themselves objects, you have the option to extend their +types as you would for any other ACS object.
The content repository does not place any restrictions on the +methods employed for delivering content via a public server +infrastructure. Applications are free to query the repository and +process the data in any way desired.
Although there are no restrictions on publishing methodology, +the repository API is intended to facilitate generic template-based +publication, regardless of the specific presentation layer used. +The following diagram illustrates the steps typically involved in +such a publication process:
In general, there is an initial resolution step in +which the server must identify the appropriate content item and +then decide which template to actually parse. Following that is an +execution step, during which setup tasks associated with +the template are performed. Finally, the merging step +combines the data and layout into a rendered page.
The primary mechanism for matching URLs to Content Items are +virtual URL handlers, .vuh files. An explanation +of virtual URL handlers can be found in the tutorial on the +Request Processor.
Here is an example index.vuh file that you can adapt to +your own purposes:
+# Get the paths + +set the_url [ad_conn path_info] +set the_root $::acs::pageroot + +# Get the IDs +set content_root \ + [db_string content_root "select content_item.get_root_folder from dual"] +set template_root \ + [db_string template_root "select content_template.get_root_folder from dual"] + +# Serve the page +# DRB: Note that content::init modifies the local variable the_root, which is treated +# as though it's been passed by reference. This requires that the redirect treat the +# path as an absolute path within the filesystem. +if { [content::init the_url the_root $content_root $template_root] } { + set file "$the_root/$the_url" + rp_internal_redirect -absolute_path $file +} else { + ns_returnnotfound +} +
The content_root and template_root parameters +select the content and template root folders. In the example, they +are just the default roots that the content repository initializes +on installation. If you want to store your content completely +independent from that of other packages, you can initialize your +own content root and pass that folder's ID on to +content::init.
To publish content through URLs that are underneath +/mycontent you need to do the following:
If you use the example index.vuh file above unaltered +for requests to my_content, a request for +http://yourserver/mycontent/news/articles/42 would request +the content item /news/articles/42 from the content +repository on the default content root folder.
When you create a new content type or add an attribute to an +existing content type, a view is created (or recreated) that joins +the attribute tables for the entire chain of inheritance for that +content type. The view always has the same name as the attribute +table for the content table, with an "x" appended to distinguish it +from the table itself (for example, if the attribute table for +Press Releases is press_releases, then the view +will be named press_releasesx. Querying this view is a +convenient means of accessing any attribute associated with a +content item.
As a shortcut, the item's template may call +content::get_content in its Tcl file in order to +automatically retrieve the current item's attributes. The +attributes will be placed in a onerow datasource called +content . The template may then call +template::util::array_to_vars content in order to convert +the onerow datasource to local variables.
In addition to the "x" view, the Content Repository creates an +"i" view, which simplifies the creation of new revisions. The "i" +view has the same name as the content table, with "i" appended at +the end. You may insert into the view as if it was a normal table; +the insert trigger on the view takes care of inserting the actual +values into the content tables.
Templates often display more than simple content attributes. +Additional queries may be necessary to obtain data about related +objects not described directly in attribute tables. The setup code +associated with a template typically performs these queries after +the initial query for any needed attributes.
At a basic level, creating a new revision of a content item +involves the following steps:
Content revisions are initialized using the +content_revision.new function. The only parameters +required to create the revision are a title, a content item ID, and +some text:
+revision_id := content_revision.new( + title => 'A Revision', + item_id => :item_id, + text => 'Once upon a time Goldilocks crossed the street. + Here comes a car...uh oh! The End' +); +
The item_id parameter is ID of the content item with +which the revision is associated.
The content_item.new function accepts a number of other +optional parameters: description, mime_type, and +publish_date. The standard creation_date, +creation_user, and creation_ip should be +specified for auditing purposes. Instead of the text +parameter, this function can be called with a data +parameter, in which data is a blob:
+revision_id := content_revision.new( + title => 'A Revision', + description => 'A Description of a revision', + mime_type => 'text/html', + publish_date => to_date('Jan 22, 2000','Mon DD, YYYY'), + item_id => :item_id, + data => :blob_of_content, + creation_date => sysdate, + creation_user => :user_id, + creation_ip => :ip_address +); +
Given that there is no way (AFAIK) to pass variable parameters +to a PL/SQL function, there is no way to make +content_revision.new generic enough to support submission +of the attributes for all different content types. This leaves you +with three alternatives:
The last option is made possible by an instead of +insert trigger on the attribute view for each content type. +(An attribute view joins together the storage tables for +the ancestors of each content type, including acs_objects +and cr_revisions). Normally it is not possible to insert +into a view. Oracle allows you to create an instead of +trigger for a view, however, which intercepts the DML statement and +allows you to execute an arbitrary block of PL/SQL instead. The +code to create or replace the trigger is automatically generated +and executed with each call to +content_type.create_attribute. The trigger makes it +possible to create complete revisions with a single insert +statement:
+insert into cr_revisionsx ( + item_id, revision_id, title +) values ( + 18, 19, 'All About Revisions' +); +
Because a special trigger is generated for each content type +that includes insert statements for all inherited tables, revisions +with extended attributes may be created in the same fashion:
+insert into cr_imagesx ( + item_id, revision_id, title, height, width +) values ( + 18, 19, 'A Nice Drawing', 300, 400 +); +
The live revision of a content item can be obtained with the +content_item.get_live_revision function:
+live_revision_id := content_item.get_live_revision( + item_id => :item_id +); +
The item_id identifies the content item with which the +revision is associated.
Likewise, the most recent revision of a content item can be +obtained with the content_item.get_latest_revision +function:
+latest_revision_id := content_item.get_latest_revision( + item_id => :item_id +); +
Last Modified: $Id: revisions.html,v 1.1.1.1 2001/03/13 22:59:26 +ben Exp $
+ Index: openacs-4/packages/acs-content-repository/www/doc/guide/search.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/www/doc/guide/search.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-content-repository/www/doc/guide/search.adp 16 Sep 2014 20:51:13 -0000 1.1.2.1 @@ -0,0 +1,94 @@ + +The content repository provides a consistent sitewide interface +for searching content. It uses Intermedia to index the +content column of cr_revisions) as well as all +the attribute columns for each content type.
The content column in cr_revisions may contain +data in any text or binary format. To accomodate searches across +multiple file types, the content repository uses an Intermedia +index with the INSO filtering option. The INSO filter automatically +detects the the file type of a binary object, and extracts text +from it for indexing. Most common file types are supported, +including PDF and Microsoft Word, and Excel and PowerPoint.
Searching for content requires the same syntax as any text +index:
+select + score(1), revision_id, item_id +from + cr_revisions r +where + contains(content, 'company', 1) > 0 +
The above query may be useful for an administrative interface +where you wish to search across all revisions, but in most cases +you only want to search live revisions:
+select + score(1), revision_id, item_id, content_item.get_path(item_id) url, title +from + cr_revisions +where + contains(content, 'company', 1) > 0 +and + revision_id = content_item.get_live_revision(item_id) +
The URL and title may be used to construct a hyperlink directly +to the item.
You may implement any number of variants on this basic query to +place additional constraints on the results, such as publication +date, content type, subject heading or a particular attribute (see +below).
Some limitations of the current implementation include:
This task is primarily handled to two Intermedia indices:
Providing a generic mechanism for searching attributes is +complicated by the fact that the attributes for each content type +are different. The content repository takes advantage of the XML +features in Oracle 8.1.6 to address this:
After creating a new revision and inserting attributes into the +storage table for the content type and all its ancestors, you must +execute the content_revision.index_attributes procedure. +(Note that this cannot be called automatically by +content_revision.new, since the attributes in all extended +storage tables must be inserted first).
This procedure creates a row in the +cr_revision_attributes table, and writes an XML document +including all attributes into this row. A Java stored procedure +using the Oracle XML Parser for Java v2 is used to actually +generate the XML document.
A special Intermedia index configured to parse XML documents is +built on the column containing the XML documents for all +revisions.
The Intermedia index allows you to use the WITHIN operator to +search on individual attributes if desired.
+select + revision_id,score(1) +from + cr_revisions +where + contains(attributes, 'company WITHIN title', 1) > 0 +
Some limitations of the current implementation include:
This document provides an introduction to using the content +repository for storing data (binary or text files) and associated +attributes. It describes how to store user portraits as an +example.
The first step towards using the content repository is to define +one or more content types for the data you wish to +manage.
The basic content item includes the following attributes:
Most types of content require additional attributes. For a +photo, we probably also want to store the pixel width and height at +the very least:
+ create table images ( + image_id integer + constraint images_image_id_fk + references cr_revisions + constraint images_pk + primary key, + width integer, + height integer + ); +
Content types are nothing more than standard ACS Objects that +inherit from content_revision:
+begin + + acs_object_type.create_type ( + supertype => 'content_revision', + object_type => 'image', + pretty_name => 'Image', + pretty_plural => 'Images', + table_name => 'images', + id_column => 'image_id', + name_method => 'acs_object.default_name' + ); + + acs_attribute.create_attribute ( + object_type => 'image', + attribute_name => 'width', + datatype => 'number', + pretty_name => 'Width', + pretty_plural => 'Widths' + ); + + acs_attribute.create_attribute ( + object_type => 'image', + attribute_name => 'height', + datatype => 'number', + pretty_name => 'Height', + pretty_plural => 'Heights' + ); + +end; +/ +show errors +
Note that content types always extend content_revision, +rather than content_item. This is because we want to store +multiple revisions of both the actual data (in this case the image) +as well as associated attributes (the width and height of the image +may vary among revisions).
The content repository implements a flexible mechanism for +organizing data in a hierarchical fashion in a manner similar to a +file system. This would be useful if we ever decided to allow each +user to manage an entire personal photo gallery rather than a +single portrait.
In the simple case where each user is allowed a single portrait, +we can simply define a relationship between user and image as ACS +Objects:
+ acs_rel_type.create_role('user'); + acs_rel_type.create_role('portrait'); + + acs_rel_type.create_type( rel_type => 'user_portrait_rel', + pretty_name => 'User Portrait', + pretty_plural => 'User Portraits', + object_type_one => 'user', + role_one => 'user', + min_n_rels_one => 1, + max_n_rels_one => 1, + object_type_two => 'content_item', + min_n_rels_two => 0, + max_n_rels_two => 1 + ); +
Note that the user object is related to a +content_item object rather than an image object +directly. Each image object represents only a single +revision of a portrait. Revisions always exist in the context of an +item.
Now we have defined both a content type and relationship type, +we can start storing portraits. The DML for processing a new +portrait upload form would look like this:
+ begin transaction + :item_id := content_item.new(:name, :item_id, sysdate, NULL, '[ns_conn peeraddr]'); + # maybe have content_revision return the LOB locator so that it can + # be used directly with blob_dml_file + :revision_id := content_revision.new(:title, :description, $publish_date, :mime_type, NULL, :text, 'content_revision', + :item_id, :revision_id); + blob_dml_file update cr_revisions set content = empty_blob() ... + :rel_id := acs_rel.new(...) +
+ ns_ora write_blob ... +
Last Modified: $Id: storage.html,v 1.1.1.1 2001/03/13 22:59:26 +ben Exp $
+ Index: openacs-4/packages/acs-content-repository/www/doc/guide/template.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/www/doc/guide/template.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-content-repository/www/doc/guide/template.adp 16 Sep 2014 20:51:14 -0000 1.1.2.1 @@ -0,0 +1,112 @@ + +The content repository allows you to associate templates with +both content types and individual content items. A template +determines how a content item is rendered when exported to the file +system or served directly to a client.
The content repository does not make any assumptions about the +type of templating system used by the application server with which +it is being used. Templates are simply made available to the +application server as text objects. The server is responsible for +merging the template with the actual content.
The content repository handle templates as a special class of +text object. The interface for handling templates builds on that of +simple content items:
+template_id := content_template.new( + name => 'image_template', + parent_id => :parent_id +); +
The name represents the tail of the location for that content +template. The parent ID must be another content item, or a subclass +of content item such as a folder.
+The content_template.new function accepts the standard +creation_date, creation_user, and +creation_ip auditing parameters.
Content items and templates are organized in two separate +hierarchies within the content repository. For example, you may +place all your press releases in the press folder under +the item root (having the ID returned by +content_item.get_root_folder). You may have 5 different +templates used to render press releases. These my be stored in the +press folder under the template root (having the +ID returned by content_template.get_root_folder).
Templates are placed under their own root to ensures that bare +templates are never accessible via a public URL. This is also done +because the relationship with the file system may be different for +templates than for content items. For example, templates may be +associated with additional code or resource files that developers +maintain under separate source control.
You use the content_type.register_template procedure to +associate a template with a particular content type:
+content_type.register_template( + content_type => 'content_revision', + template_id => :template_id, + use_context => 'public', + is_default => 't' +); +
The use_context is a simple keyword that specifies the +situation in which the template is appropriate. One general +context, public, is loaded when the content repository is +installed. Templates in this context are for presenting content to +users of the site. Some sites may wish to distinguish this further, +for example using intranet, extranet and +public contexts.
The is_default flag specifies that this template will +serve as the default template in the case that no template is +registered to a content item of this content type and this use +context. Any content type/context pair may have any number of +templates registered to it, but there can be only one default +template per pair.
To make a template the default template for a content +type/context pair:
+content_type.set_default_template( + content_type => 'content_revision', + template_id => :template_id, + use_context => 'public' +); +
Individual items may also be associated with templates using the +content_item.register_template procedure:
+content_item.register_template( + item_id => :item_id, + template_id => :template_id, + use_context => 'intranet' +); +
Unlike the case with content types, only one template may be +registered with a content item for a particular context.
The content management system uses this functionality to allow +publishers to choose templates for each content they create. For +example, a company may have three different templates for +presenting press releases. Depending on the subject, geographic +region or any other criterion, a different template may be used for +each press release.
The application server (AOLserver or servlet container) may use +the content_item.get_template function to determine the +proper template to use for rendering a page in any particular +context:
+template_id := content_item.get_template( + item_id => :item_id, + use_context => 'public' +); + +template_path := content_template.get_path( + template_id => :template_id +); +
In the case that no template is registered to given item/context +pair, content_item.get_template will return the default +template (if it exists) for the related content type/context +pair.
The procedure for disassociating templates with content types is +as follows:
+content_type.unregister_template( + content_type => 'content_revision', + template_id => :template_id, + use_context => 'intranet' +); +
The corresponding procedure to disassociate templates with +content items is:
+content_item.unregister_template( + item_id => :item_id, + template_id => :template_id, + use_context => 'admin' +); +
Last Modified: $Id: template.html,v 1.1.1.1 2001/03/13 22:59:26 +ben Exp $
+ Index: openacs-4/packages/acs-content-repository/www/doc/guide/types.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/www/doc/guide/types.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-content-repository/www/doc/guide/types.adp 16 Sep 2014 20:51:14 -0000 1.1.2.1 @@ -0,0 +1,99 @@ + +The content repository requires you to define each type of +content supported by your supplication. Content types are defined +as ACS Object Types, and may be created in the same +fashion as any other object type. This page provides some specific +examples and details related to defining ACS object types in the +context of the content repository.
A content item typically consists of two components:
Note that a content type does not have to store its +primary content in the BLOB column of the +cr_revisions table. There is some additional overhead +associated with retrieving small passages of text from the BLOB +column compared to an attribute column. In most cases the +difference is trivial (fewer than about 10 microseconds), but if +many items must be queried at the same time the difference may +become significant. If the primary content will always be small, it +is perfectly acceptable to store the content in an attribute column +instead.
Basic attributes for all content types are stored in the +cr_revisions (note that they are stored in the revisions +table so that attributes may be updated for each new revision of +the actual data). Most types of content require more than the basic +attributes. For example, when storing images you will usually want +to store the pixel height and width so that images can be selected +and sorted by size, as well as displayed efficiently.
Extended attributes associated with ACS object types may be +stored as key-value pairs in a central table (generic storage), or +in a custom table whose primary key references the associated ACS +object ID (specific storage). To ensure efficient access to +attributes, the content repository API requires you to use specific +storage. Your table should have the form:
+create table cr_content_type ( + content_type_id integer + constraint cr_content_type_id_fk + references cr_revisions + constraint cr_content_type_pk + primary key, + attributes... +); +
Note that your extended attribute table must reference the +cr_revisions table, notcr_items. As +mentioned above, this allows you to maintain multiple revisions of +the attribute data in tandem with revisions of the content object +itself.
To define a content type, you should write an SQL script to +create the content type and then add attributes to it:
+declare + attr_id acs_attributes.attribute_id%TYPE; +begin + + -- create the content type + content_type.create_type ( + content_type => 'cr_press_release', + pretty_name => 'Press Release', + pretty_plural => 'Press Releases', + table_name => 'cr_press_releases', + id_column => 'release_id' + ); + + -- create content type attributes + attr_id := content_type.create_attribute ( + content_type => 'cr_press_release', + attribute_name => 'location', + datatype => 'text', + pretty_name => 'Location', + pretty_plural => 'Location', + column_spec => 'varchar2(1000)' + ); + + ... +
The content_type methods use the core ACS Object Type +API to create an object type for each content type, and to add +attributes to the object type. In addition, +content_type.create_type will create the extended +attribute table with an appropriately defined primary key column +(referencing its supertype) if the table does not already exist. +Likewise, content_type.create_attribute will add a column +to the table if the column does not already exist.
Most importantly, the content_type methods call +content_type.refresh_view after each change to the content +type definition. Each content type must have an associated +attribute view named +table_namex, where +table_name is the name of the extended attribute +table for a particular content type. The view joins the +acs_objects, cr_revisions, and all extended +attribute tables in the class hierarchy of a particular content +type. This view may be used to query attributes when serving +content.
In many cases your content items will serve as containers for +other items. You can include the set of allowable components as +part of a content type definition. See Object Relationships for +details.
Last Modified: $Id: types.html,v 1.1.1.1 2001/03/13 22:59:26 ben +Exp $
+ Index: openacs-4/packages/acs-content-repository/www/doc/guide/workflow.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-content-repository/www/doc/guide/workflow.adp,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-content-repository/www/doc/guide/workflow.adp 16 Sep 2014 20:51:14 -0000 1.1.2.1 @@ -0,0 +1,161 @@ + +This document describes the workflow API calls necessary to +apply a simple workflow to a content item.
Most publishers wish to follow some variation of the following +workflow:
State | Task | Description | +
---|---|---|
Created | Authoring | The publisher has created the item. | +
Authored | Editing | The author has written the item. | +
Edited | Publishing | The editor has approved the item. | +
Published | None | The publisher has approved the item. | +
At any point in the workflow, an assigned user should be able to +check out an item, such that other users are advised that someone +is working on it. When checking an item in, a user should have up +to three options:
This simple workflow is defined in +sql/workflows/author-edit-publish.sql.
Production of a content item frequently begins with a concept +which is initiated by the publisher and then executed by the staff. +In this scenario, the publisher creates the workflow and then +assigns each task in the workflow to one or more people. The API +calls to initialize a new workflow are as follows:
+declare + v_case_id integer; + sample_object_id integer := 9; + sample_user_id integer := 10; +begin + + v_case_id := workflow_case.new( workflow_key => 'publishing_wf', + context_key => NULL, + object_id => sample_object_id); + + workflow_case.add_manual_assignment(v_case_id, 'authoring', sample_user_id); + workflow_case.add_manual_assignment(v_case_id, 'editing', sample_user_id); + workflow_case.add_manual_assignment(v_case_id,'approval', sample_user_id); + + workflow_case.start_case(case_id => v_case_id, msg => 'Here we go.'); + +end; +/ +
In this case, only one assignment is made per task. You can make +as many assignments per task as desired. There is currently no +workflow API to set deadlines, so you must write your own DML to +insert a row into wf_case_deadlines if you wish to allow +the publisher to set deadlines ahead of time.
The above workflow is created in the Default context. In +practice, you may wish to create one or more contexts in which to +create your workflows. Contexts may be used to represent different +departments within an organization.
The start_case enables the first task in the workflow, +in this case Authoring.
If multiple persons are assigned to the same task, it is useful +to allow a single person to "check out" or lock an item while they +are working. This is accomplished with the following API calls:
+declare + v_journal_id integer; + sample_task_id := 1000; + sample_user_id := 10; + sample_ip := '127.0.0.1'; +begin + + v_journal_id := workflow_case.begin_task_action(sample_task_id, 'start', + sample_ip, sample_user_id, 'Checking it out'); + workflow_case.end_task_action(v_journal_id, 'start', sample_task_id); + +end; +/ +
A mininum of two calls are required to perform any action +related to a task. In this case we are simply notifying the +workflow engine that someone has started the task. You may specify +NULL for the journal message if the user does not wish to comment +on the check out.
Unless given a timeout period, a lock on a content item will +persist until the holding user checks the item back in. This +involves notifying the workflow engine that the user has finished +the task:
+declare + v_journal_id integer; + sample_task_id integer := 1000; + sample_user_id integer := 10; + sample_ip := '127.0.0.1'; +begin + + v_journal_id := workflow_case.begin_task_action(sample_task_id, 'finish', + sample_ip, sample_user_id, 'Done for now'); + workflow_case.set_attribute_value(v_journal_id, 'next_place', 'start'); + workflow_case.end_task_action(v_journal_id, 'finish', sample_task_id); + +end; +/ +
Upon finishing a task, you must notify the workflow engine where +to go next. In this case, an author wishes to simply check an item +back in without actually completing the authoring task. The +set_attribute_value procedure must thus be used to set +next_place to the starting place of the workflow.
The process to finish a task varies slightly depending on +whether the user has previously checked out the item out or not. If +the user has not already checked it out (has been working on the +item without locking it, the code looks like this:
+declare + v_journal_id integer; + sample_task_id integer := 1002; + sample_user_id integer := 10; + sample_ip := '127.0.0.1'; +begin + + -- start the task + v_journal_id := workflow_case.begin_task_action(sample_task_id, 'start', + sample_ip, sample_user_id, NULL); + workflow_case.end_task_action(v_journal_id, 'start', sample_task_id); + + -- finish the task + v_journal_id := workflow_case.begin_task_action(sample_task_id, 'finish', + sample_ip, sample_user_id, 'Authoring complete'); + workflow_case.set_attribute_value(v_journal_id, 'next_place', 'authored'); + workflow_case.end_task_action(v_journal_id, 'finish', sample_task_id); + +end; +/ +
In this case an author is finishing the Authoring task, +upon which the workflow engine will move the workflow to the +Authored state (as indicated by the next_place +attribute). If the author had previously checked out the item, then +only the second step is required.
Approval steps more commonly do not involve an explicit +check-out process. The code is thus virtually identical to that +above:
+declare + v_journal_id integer; + sample_task_id integer := 1003; + sample_user_id integer := 10; + sample_ip := '127.0.0.1'; +begin + + v_journal_id := workflow_case.begin_task_action(sample_task_id, 'start', + sample_ip, sample_user_id, NULL); + workflow_case.end_task_action(v_journal_id, 'start', sample_task_id); + + v_journal_id := workflow_case.begin_task_action(sample_task_id, 'finish', + sample_ip, sample_user_id, 'Authoring complete'); + workflow_case.set_attribute_value(v_journal_id, 'next_place', 'edited'); + workflow_case.end_task_action(v_journal_id, 'finish', sample_task_id); + +end; +/ +
Note the distinction between approval or rejection is determined +solely by the value of the next_place attribute.