The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

OpenInteract2::Observer - Initialize and manage observers to OpenInteract components

SYNOPSIS

 # Declare an observer 'allcaps' in the server-wide file for
 # registering observers, referring to a class somewhere in @INC
 #
 # File: $WEBSITE_DIR/conf/observer.ini
 
 [observer]
 allcaps = OpenInteract2::Filter::AllCaps
 
 # Associate the filter with an action in the same file
 
 [map]
 allcaps = news
 
 # You can also declare the observer in your package's package.conf
 # file; it's mapped the same no matter where it's declared
 # File: pkg/mypackage-2.00/package.conf
 
 name           mypackage
 version        2.00
 author         Kilroy (kilroy@washere.com)
 observer       allcaps   OpenInteract2::Filter::AllCaps
 
 # Create the filter -- see OpenInteract2::Filter::AllCaps shipped
 # with the distribution:
 
 package OpenInteract2::Filter::AllCaps;
 
 use strict;
 
 sub update {
     my ( $class, $action, $type, $content ) = @_;
     return unless ( $type eq 'filter' );
     $$content =~ tr/a-z/A-Z/;
 }
 
 # Elsewhere, programmatically add a new observer
 
 CTX->add_observer( foobar => 'OpenInteract2::Observer::Foobar' );

DESCRIPTION

This class provides methods for initializing observers and attaching them to action objects or action classes.

Observers are registered at server startup and sit around waiting for actions to post events. When an action posts an event the data is passed around to all the observers watching that action. The observer can react to the data if it wants or it can pass.

Most observers react to one or two types of events. For instance, if you're using the delicious_tags package there's an observer that looks like this:

 sub update {
     my ( $class, $action, $type ) = @_;
     return unless ( $type =~ /^post (add|update)$/ );
     # ... tag the object ...
 }

This observer only reacts to 'post add' and 'post update' observations and ignores all others.

Observation Types

Actions can independently declare their own observation types. However, there are a few built-in to OpenInteract classes:

  • filter: Issued after an action has generated its content but before that content is cached and returned.

    Signature: $action, 'filter', \$content

  • cache hit: Issued after an action has successfully loaded data from the cache but before that content is returned.

    Signature: $action, 'cache hit', \$content

  • pre add/post add: Issued before/after an object is added by the action to long-term storage. Currently used by OpenInteract2::Action::CommonAdd, but you can use it as well.

    Signature: $action, 'pre add', $object, \%save_options

    Signature: $action, 'post add', $object

  • pre update/post update: Issued before/after an object is updated by the action to long-term storage. Currently used by OpenInteract2::Action::CommonUpdate, but you can use it as well.

    Signature: $action, 'pre update', $object, \%old_data, \%save_options

    Signature: $action, 'post update', $object, \%old_data

  • pre remove/post remove: Issued before/after an object is remove by the action from long-term storage. Currently used by OpenInteract2::Action::CommonRemove, but you can use it as well.

    Signature: $action, 'pre remove', $object

    Signature: $action, 'post remove', $object

METHODS

All methods are class methods (for now). Note that when we discuss a 'observer' it could mean a class name, instantiated object or subroutine reference. (A filter is just an observer, see Class::Observable for what constitutes an observer.)

create_observer_filename()

Returns the full path to the server observer file, normally $WEBSITE_DIR/conf/observer.ini.

add_observer_to_action( $observer_name, $action | $action_name )

Registers the observer referenced by $observer_name to the action $action or the action class referenced by $action_name. If you pass in $action the observer will go away when the object is disposed at the end of the request; with $action_name the observer will persist until the server is shutdown.

Returns: assigned observer

register_observer( $observer_name, \%observer_info, \%observer_registry )

Creates a observer with the name $observer_name and saves the information in \%observer_registry. If the observer cannot be created (due to a library not being available or an object not being instantiable) an error is logged but no exception thrown.

Returns: created observer, undef if an error encountered

initialize()

Reads observers declared in packages and in the server conf/observer.ini file, brings in the libraries referenced by the observers, creates a observer name-to-observer registry and saves it to the context.

Note that observers declared at the server will override observers declared in a package if they share the same name.

You will likely never call this as it is called from OpenInteract2::Setup on the observers declared in packages or in the global observer file.

Returns: nothing

CONFIGURATION

Configuration is split into two parts: declaring the observer and mapping the observer to one or more actions for it to watch.

Both parts are typically done in the $WEBSITE_DIR/conf/observer.ini, although you can also do the observer declaration from a package.

Configuration: Declaring the Observer

Most of the time you'll register an observer name with a class. The following registers two observers to classes under the names 'wiki' and 'delicious_tag':

 [observer]
 wiki          = OpenInteract2::Observer::Wikify
 delicious_tag = OpenInteract2::Observer::AddDeliciousTags

This standard usage is actually a shortcut for:

 [observer wiki]
 class = OpenInteract2::Observer::Wikify
 
 [observer delicious_tag]
 class = OpenInteract2::Observer::AddDeliciousTags

Or more generically:

 [observer observer-name]
 observation-type = value

In addition to assigning class observers register a particular subroutine or object instance. The three observation types are 'class', 'object' and 'sub' (see Class::Observable for what these mean and how they are setup), so you could have:

 [observer myobject]
 object = OpenInteract2::FooFilter
 
 [observer myroutine]
 sub    = OpenInteract2::FooFilter::other_sub

Using the object is fairly rare and you should probably use the class observer for its simplicity.

Configuration: Mapping the Observer to an Action

Mapping an observer to an action is exclusively done in $WEBSITE_DIR/conf/observer.ini. Under the 'map' section you assign an observer to one or more actions. Here as assign the observer 'wiki' to 'news' and 'page' and 'delicious_tag' to 'news':

 [map]
 wiki = news
 wiki = page
 delicious_tag = news

Note that the mapping is ignorant of:

  • Observer type: The mapping doesn't care if 'wiki' is a class, object or subroutine.

  • Observer declaration: The mapping also doesn't care where 'wiki' was declared.

SEE ALSO

Class::Observable

COPYRIGHT

Copyright (c) 2004-2005 Chris Winters. All rights reserved.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

AUTHORS

Chris Winters <chris@cwinters.com>