NAME

Contentment::Content::Nodelet - Helper class for building node modules

DESCRIPTION

By using this class, most of the work of making your class into a node module is done for you. This class defines a number of SPOPS rules and other methods that automatically create and update the parent node and revision records associated with this record. This module is also helpful because node objects are a bit atypical in the way operations work:

  1. The primary key/ID-field for nodelet objects is the node_id from the node record.

  2. Node creation involes the creation of two related records other than the main object: the node and the revision.

  3. There are two ways to update a node record:

    Simple

    The simple way to update is simply to change the current record in place, which should result in updates to the revision and node records as well (i.e., new dates and users for certain fields).

    New Revision

    The alternative is to create a new revision of the object. This causes the object to be cloned, the old record to be updated and disabled (thus, modifying certain fields in node and revision for that record), the new record is then created with the alterations and the old object keeps the old values (except for a few dates and users that are updated).

  4. Deletion of a record can also happen in two ways. One is to disable all revisions associated with the record. The other is to actually remove the records from the database altogether. Both are possible.

  5. Searching for records has to be done a bit more carefully to ensure that only the current revision of each record is returned on a normal search. Records that have been "deleted" but are still stored in the database should also be ignored.

  6. However, it wouldn't be of much value if there wasn't some way to search for old revisions and "deleted" records.

See each of the methods below to see details on how the solution to these issues are implemented.

SPOPS CONFIGURATION

In general, a nodelet is configured in exactly the same way as a regular SPOPS DBI class, but there are a couple additions. Here's the definition of the additional fields and their meaning:

id_field

This has no meaning for nodelets. This field is ignored. You will need a primary key (of course) for your table, but you don't need to bother setting it in here. Nodelets are primarily identified by their node_id. This is done through a bit of trickery.

rev_id_field (default: "node_rev_id")

You need a field in your table which links your table to the "node_rev_id" field of the node and revision. The name of this field goes in the "ref_id_field" setting (which defaults to "node_rev_id" if not set explicitly). You may link this table to the table named "revision" by this field, if you want the database to enforce the constraint.

create_revision (default: 0)

Whenever you save you can pass an optional parameter named "create_revision" to specify whether or not this save should create a new revision. If true, then the object is cloned and the new revision is modified and dates are set on both the new and old object. The current object becomes the new object.

This option sets the default behavior. If you normally want revisions, you can set this to a true value. The default is to not create revisions every time as this is a more expensive operation.

disable (default: 0)

Whenever you delete a record, you can pass an optional parameter named "disable" to specify whether or not this delete should just set the disabled flag for the revision. If true, then the object is disabled and not actually removed from the table, but won't be returned on typical queries. Otherwise, the object is completely removed from the database.

This option sets the default behavior. If you normally want to disable rather than to delete records, you can set this to a true value. The default is not to disable records.

SPOPS API

$nodelet = Nodelet->fetch($id, \%params)

Fetches the record associated with the given $id. By default, this will return the latest revision for the requested nodelet. If a record has been disabled, then this method will normally return undef. These latter behaviors can be modified with special parameters in %params:

include_disabled

If this is set to a true value, then a disabled record can be returned. Without this option, undef would be returned if the current record associated with a nodelet is disabled.

revision_id

If this parameter is set, then the "include_disabled" option is implied. This allows you to retrieve a different revision for the nodelet than the head revision.

$nodelets = Nodelet->fetch_group(\%params)

This method returns all of the nodelet records for enabled head revisions. That is, only currently enabled records are returned and only the head revision of the nodelet is returned (under normal circumstances).

The behavior of this method can be altered by through the use of parameters in %params:

all_revisions

This option implies "include_disabled". This causes every revision matching the given criteria to be returned in the query, so multiple records with the same node_id can be returned (use revision_id to differentiate them).

include_disabled

This option (when "all_revisions" isn't present) causes the head revisions from both enabled and disabled records to be returned. Thus, one of each node will be returned, but the node_id for each record will still be unique within the returned set (unless "all_revisions" is set).

$iter = Nodelet->fetch_iterator(\%params)

This method is identical to fetch_group, except that an iterator is returned rather than an array reference.

$num = Nodelet->fetch_count(\%params)

This method is identical to fetch_group, except that it returns the number of records that would be returned rather than any actual records.

$nodelet->save(\%params)

This method saves changes to the record. On create, this method is pretty much identical to the SPOPS::DBI implementation. On update, this method may create a revision, if this has been set as the default behavior or if the "create_revision" option is set to true in %params.

If this method creates a revision, the following steps are taken:

  1. Begin a transaction.

  2. The nodelet record is cloned and a new revision record is created. Modifications are set on the clone and these two records are saved.

  3. The original revision record is disabled and saved.

  4. The node record is touched.

  5. This object becomes a pointer to the new revision.

  6. The transaction is committed.

$nodelet->field_update($fields, \%params)

This has essentially the same effect as the SPOPS::DBI object, but uses the "create_revision" parameter (or default value set at configuration time) to possibly create a new revision in the way that save does.

Nodelet->field_update($fields, \%params)

Again, this is the same as SPOPS::DBI, but takes the additional "create_parameter" or uses the default configuration value to possibly create a new revision for each change in the way that save does. I imagine that creating revisions for bunches of records is an extremely expensive process.

$nodelet->remove(\%params)

This method will delete or disable a nodelet record. The operation performed depends upon the "disable" parameter passed to %params (or the default given in the configuration).

Some of the behavior of this method varies depending on the state of the database. If "disable" is false and this nodelet record represents the only revision in the database for this node_id, then the nodelet, revision, and node records are all deleted.

If "disable" is false and there are multiple revisions for this node_id besides this one, only this nodelet and associated revision are deleted (see "cascade_delete" for a slightly different behavior). If this nodelet also happens to be the head revision, then the nodelet with the highest revision_id is then selected to replace this one as head (i.e., the record is now effectively disabled, with this particular nodelet revision completely purged from the table). If this behavior doesn't suit your needs (i.e., a different revision should become the head), then you should change the head before deleting the revision.

The behavior of the behavior of this method is further determined by other parameters:

cascade_delete

This option has no meaning when the "disable" option is true.

Normally, the remove action will only affect the current revision. Thus, if there exists another revision in the database, the node won't be deleted, just this particular record.

However, if this option is set, then every revision and nodelet record for this node_id will be purged from the table as well as the node record.

disable

If true, no record is purged from any table. Rather, the "enabled" flag on the revision record is set to a false value and saved.

AUTHOR

Andrew Sterling Hanenkamp, <hanenkamp@users.sourceforge.net>

COPYRIGHT AND LICENSE

Copyright 2005 Andrew Sterling Hanenkamp. All Rights Reserved.

Contentment is distributed and licensed under the same terms as Perl itself.

5 POD Errors

The following errors were encountered while parsing the POD:

Around line 25:

You have '=item 1' instead of the expected '=item 2'

Around line 29:

You have '=item 2' instead of the expected '=item 3'

Around line 45:

You have '=item 3' instead of the expected '=item 4'

Around line 49:

You have '=item 4' instead of the expected '=item 5'

Around line 53:

You have '=item 4' instead of the expected '=item 6'