From: Chris W. <la...@us...> - 2004-09-27 12:53:37
|
Update of /cvsroot/openinteract/OpenInteract2/lib/OpenInteract2 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27617 Added Files: Observer.pm Removed Files: Filter.pm Log Message: OIN-83: delete Filter.pm and add Observer.pm since filters are just a more specific form of observers --- NEW FILE: Observer.pm --- package OpenInteract2::Observer; # $Id: Observer.pm,v 1.1 2004/09/27 12:53:27 lachoy Exp $ use strict; use Log::Log4perl qw( get_logger ); use OpenInteract2::Constants qw( :log ); use OpenInteract2::Context qw( CTX ); use OpenInteract2::Config::IniFile; $OpenInteract2::Observer::VERSION = sprintf("%d.%02d", q$Revision: 1.1 $ =~ /(\d+)\.(\d+)/); my ( $log ); sub register_observer { my ( $class, $observer_name, $observer_info, $registry ) = @_; $log ||= get_logger( LOG_OI ); $log->is_info && $log->info( "Trying to register observer '$observer_name'" ); my ( $observer, $observer_type ); my $observer_class = ( ref $observer_info ) ? $observer_info->{class} : $observer_info; if ( $observer_class ) { my $error = $class->_require_module( $observer_class ); unless ( $error ) { $observer = $observer_class; $observer_type = 'class'; } } elsif ( my $observer_obj = $observer_info->{object} ) { my $error = $class->_require_module( $observer_obj ); unless ( $error ) { $observer = eval { $observer_obj->new }; if ( $@ ) { $log->error( "Failed to instantiate observer ", "object '$observer_obj'" ); } else { $log->is_info && $log->info( "Created object '$observer_obj' ok" ); $observer_type = 'object'; } } } elsif ( my $observer_sub = $observer_info->{sub} ) { $observer_sub =~ /^(.*)::(.*)$/; my ( $name_class, $name_sub ) = ( $1, $2 ); my $error = $class->_require_module( $name_class ); unless ( $error ) { no strict 'refs'; $observer = *{ $name_class . '::' . $name_sub }; $log->is_info && $log->info( "Seemed to assign anonymous sub ok" ); $observer_type = 'sub'; } } else { $log->error( "No observer registered for '$observer_name': must specify", " 'class', 'object' or 'sub' in observer information. ", "(See docs for OpenInteract2::Action under ", "'OBSERVABLE ACTIONS')" ); } if ( $observer ) { $registry->{ $observer_name } = $observer; } return $observer; } # Note: $action_item can be a name or an object sub add_observer_to_action { my ( $class, $observer_name, $action_item ) = @_; my $observer = CTX->lookup_observer( $observer_name ); return unless ( $observer ); if ( ref $observer and ref $observer ne 'CODE' ) { $observer = $observer->new; # create a new object } my $observed = $action_item; unless ( ref $observed ) { my $action_info = eval { CTX->lookup_action_info( $action_item ) }; return if ( $@ or ref $action_info ne 'HASH' ); $observed = $action_info->{class}; } $observed->add_observer( $observer ); $log->is_info && $log->info( "Added observer '$observer' to '$observed' ok" ); return $observer; } sub initialize { my ( $class ) = @_; my $li = get_logger( LOG_INIT ); my $observer_file = $class->create_observer_filename; return unless ( -f $observer_file ); my $observer_ini = OpenInteract2::Config::IniFile->read_config({ filename => $observer_file }); if ( $@ ) { $li->error( "Failed to read '$observer_file': $@" ); return; } $li->is_info && $li->info( "Read in '$observer_file' ok" ); my $observer_registry = $class->_register_initial_observers( $observer_ini->{observer}, CTX->packages ); $li->is_info && $li->info( "Registered internal observers ok" ); CTX->set_observer_registry( $observer_registry ); my $mappings = $observer_ini->{map}; if ( ref $mappings eq 'HASH' ) { while ( my ( $observer_name, $action_info ) = each %{ $mappings } ) { my @actions = ( ref $action_info ) ? @{ $action_info } : ( $action_info ); foreach my $action_name ( @actions ) { $li->is_info && $li->info( "Trying to add observer '$observer_name' to ", "action '$action_name'" ); $class->add_observer_to_action( $observer_name, $action_name ); } } } return; } sub create_observer_filename { my ( $class ) = @_; my $conf_dir = CTX->lookup_directory( 'config' ); return File::Spec->catfile( $conf_dir, 'observer.ini' ); } sub _register_initial_observers { my ( $class, $ini_observers, $packages ) = @_; my $li = get_logger( LOG_INIT ); my %observer_map = (); # First register observers in packages; entries in 'observer.ini' will # override packages since it's assumed people editing it know what # they're doing... foreach my $pkg ( @{ $packages } ) { my $pkg_observers = $pkg->config->observer; next unless ( ref $pkg_observers eq 'HASH' ); while ( my ( $observer_name, $observer_class ) = each %{ $pkg_observers } ) { $li->is_info && $li->info( "Registering observer '$observer_name' as ", "'$observer_class' from package ", $pkg->full_name ); $observer_map{ $observer_name } = $observer_class; } } # Now cycle through the INI and pull the info for each observer # (usually just a class name) while ( my ( $observer_name, $observer_info ) = each %{ $ini_observers } ) { $li->is_info && $li->info( "Registering observer '$observer_name' from ", "server config" ); if ( $observer_map{ $observer_name } ) { $li->warn( "WARNING: Overwriting observer '$observer_name', ", "previously '$observer_map{ $observer_name }'" ); } $observer_map{ $observer_name } = $observer_info; } my %observer_registry = (); # Now that they're collected, be sure we can # require/reference/instantiate each while ( my ( $observer_name, $observer_info ) = each %observer_map ) { $class->register_observer( $observer_name, $observer_info, \%observer_registry ); } return \%observer_registry; } sub _require_module { my ( $class, $to_require ) = @_; $log ||= get_logger( LOG_OI ); eval "require $to_require"; my $error = $@; if ( $error ) { $log->error( "Failed to require '$to_require': $error" ); } else { $log->is_info && $log->info( "Required module '$to_require' ok'" ); } return ( $error ) ? $error : undef; } 1; __END__ =head1 NAME OpenInteract2::Observer - Initialize and manage observers to OpenInteract components =head1 SYNOPSIS # Declare a filter '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 # You can also declare it in your package's package.conf file # File: pkg/mypackage-2.00/package.conf name mypackage version 2.00 author Kilroy (ki...@wa...) observer allcaps OpenInteract2::Filter::AllCaps # Associate the filter with an action in the same file [map] allcaps = news # 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' ); =head1 DESCRIPTION This class provides methods for initializing observers and attaching them to action objects or action classes. =head1 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 L<Class::Observable|Class::Observable> for what constitutes an observer.) B<create_observer_filename()> Returns the full path to the server observer file, normally C<$WEBSITE_DIR/conf/observer.ini>. B<add_observer_to_action( $observer_name, $action | $action_name )> Registers the observer referenced by C<$observer_name> to the action C<$action> or the action class referenced by C<$action_name>. If you pass in C<$action> the observer will go away when the object is disposed at the end of the request; with C<$action_name> the observer will persist until the server is shutdown. Returns: assigned observer B<register_observer( $observer_name, \%observer_info, \%observer_registry )> Creates a observer with the name C<$observer_name> and saves the information in C<\%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 B<initialize()> Reads observers declared in packages and in the server C<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 L<OpenInteract2::Setup|OpenInteract2::Setup> on the observers declared in packages or in the global observer file. Returns: nothing =head2 Configuring You can also register a particular subroutine or object instance The general configuration to declare a observer is: [observer filtername] observation-type = value The observation types are 'class', 'object' and 'sub' (see L<Class::Observable|Class::Observable> for what these mean and how they are setup), so you could have: [observer foo_obj] object = OpenInteract2::FooFilter [observer foo_sub] sub = OpenInteract2::FooFilter::other_sub [observer action] foo_obj = news foo_sub = page Most of the time you will use the class shortcut since it is the easiest. =head1 SEE ALSO L<Class::Observable> =head1 COPYRIGHT Copyright (c) 2004 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. =head1 AUTHORS Chris Winters E<lt>ch...@cw...E<gt> --- Filter.pm DELETED --- |