Solstice::Controller - A virtual superclass for constructing Solstice controllers.


Solstice documentation Contained in the Solstice distribution.

Index


Code Index:

NAME

Top

Solstice::Controller - A virtual superclass for constructing Solstice controllers.

SYNOPSIS

Top

  package MyApp::Controller;

  use Solstice::Controller;

  our @ISA = qw(Solstice::Controller);

DESCRIPTION

Top

This is a virtual class for creating Solstice controller classes. This class should never be instantiated as an object, rather, it should always be sub-classed. This particular implementation uses Solstice::CGI to handle events by the user.

Export

No symbols exported.

Methods

new()

Creates a new Solstice::Controller object.

build
validPreConditions()
freshen()
update()
validate()
commit()
revert()
setModel($model)

Set the data model that this controller controls.

getModel()

Get the data model that this controller controls.

setSuccessView($view)

Set the success view that this controller controls.

getStartingView()

This gets the first view that a controller produces, like the form that the controller will then manage. Must by subclassed.

setErrorView($view)

Set the error view for this controller.

getErrorView()

Get the error view for this controller.

getChildView($key)

Returns a view object for the child controller of a given key.

getChildViews($key)

Returns an array ref of view objects for all of the child controllers of a given key.

setError($error)

Sets an error object for placement into the views

getError()

Gets the error object for this controller.

getErrMsgs()

Get the error messages for this controller.

checkForm($profile)

This method takes a form profile to be passed to Data::FormValidator, and returns a Data::FormValidator::Results object.

createParam('param_name')

Adds a new param to be validated. This is required by default.

createRequiredParam('param_name')

Adds a new param to be validated. Requires user input.

createOptionalParam('param_name');

Adds a new param to be validated. Does not require user input.

createGroupDependency({ dependency_name => 'name', require => $count, fields => [ $field1, $field2] });

Allows the use of require_some...

processConstraints()

Takes all of the constraints added to a controller, transforms them into a hash for Data::FormValidator.

setInputName($location_name)
getInputName()
setOutputName($location_name)
getOutputName()
getInputObject()
getOutputObject()
setInputObject($object)
setOutputObject($object)
createChildControllerList( 'loop_name', 'var_name' )
addChildController($key,( $controller || \@controllers) )
getChildController($key)
getChildControllers($key)

returns a reference to an array of 'em.

clearChildControllers($key)
validateChildren($key)
updateChildren($key)
revertChildren($key)
commitChildren($key)
validPreConditionsChildren($key)
freshenChildren($key)
getDateTimeController($model)

Return the preferred Solstice datetime controller, or a fallback.

getRichTextController($model)

Return the preferred Solstice rich-text controller, or a fallback.

Private Methods

_initErrMsgs()

Initialize the error messages for this controller.

Modules Used

Solstice::Service, Solstice::LogService, Solstice::UserService, Solstice::ValidationParam, Solstice::CGI, Solstice::CGI::FormError, Data::FormValidator.

AUTHOR

Top

Catalyst Group, <catalyst@u.washington.edu>

VERSION

Top

Version $Revision: 3365 $

COPYRIGHT

Top


Solstice documentation Contained in the Solstice distribution.
package Solstice::Controller;

# $Id: Controller.pm 3365 2006-05-05 07:52:21Z pmichaud $

use 5.006_000;
use strict;
use warnings;

use base qw(Solstice);

use Solstice::CGI;
use Solstice::CGI::FormError;

use Solstice::Service;
use Solstice::LogService;
use Solstice::UserService;
use Solstice::NavigationService;
use Solstice::IconService;

use Solstice::ValidationParam;

use Data::FormValidator;

use Solstice::Controller::FormInput::DateTime;
use Solstice::Controller::FormInput::DateTime::YahooUI;
use Solstice::Controller::FormInput::TextArea;

use constant TRUE  => 1;
use constant FALSE => 0;
use constant GLOBAL_FORM_ERROR_KEY => 'form_error';

our ($VERSION) = ('$Revision: 3365 $' =~ /^\$Revision:\s*([\d.]*)/);

sub new {
    my $class = shift;
    my $model = shift;

    my $self = $class->SUPER::new(@_);
    $self->setModel($model) if defined $model;
    $self->{'_constraints'} = [];
    $self->{'_group_dependencies'} = [];

    return $self;
}

sub build {
    return TRUE;
}

sub initialize {
    return TRUE;
}

sub finalize {
    return TRUE;
}

sub validPreConditions{
    return TRUE;
}

sub freshen{
    return TRUE;
}

sub update{
    return TRUE;
}

sub validate{
    return TRUE;
}

sub commit{
    return TRUE;
}

sub revert {
    return TRUE;
}

sub setModel {
    my $self = shift;
    $self->{'_model'} = shift;
}

sub getModel {
    my $self = shift;
    return $self->{'_model'};
}

sub setSuccessView {
    my $self = shift;
    $self->{'_success_view'} = shift;
}

sub getStartingView {
    my $self = shift;
    return $self->{'_success_view'};
}

sub setErrorView {
    my $self = shift;
    $self->{'_error_view'} = shift;
}

sub getErrorView {
    my $self = shift;
    return $self->{'_error_view'};
}


sub getChildView {
    my $self = shift;
    my $key = shift;

    my $controllers = $self->getChildControllers($key);
    if (defined $controllers and defined $$controllers[0]) {
        my $view = ${$controllers}[0]->getView();
        $view->setError($controllers->[0]->getError());
        return $view;
    }
    return;
}

sub getChildViews {
    my $self = shift;
    my $key = shift;

    my $controllers = $self->getChildControllers($key);
    return () unless defined $controllers;
    my @views;
    foreach (@$controllers) {
        my $view = $_->getView();
        $view->setError($_->getError());
        push @views, $view;
    }
    return \@views;
}

sub setError {
    my $self = shift;
    $self->{'_error'} = shift;
}

sub getError {
    my $self = shift;
    return $self->{'_error'};
}

sub getErrMsgs {
    my $self = shift;

    return $self->{'_msgs'} if exists $self->{'_msgs'};

    $self->_initErrMsgs();
    return $self->{'_msgs'};
}

sub checkForm {
    my $self = shift;
    my $profile = shift;

    die "checkForm: missing required profile\n" unless $profile;

    my $dfv = Data::FormValidator->new();
    my $form_results = $dfv->check(Solstice::CGI->new(), $profile);

    my $error = undef;
    if ($form_results->has_missing or $form_results->has_invalid) {
        $error = Solstice::CGI::FormError->new();
        $error->setFormMessages($form_results->msgs);
    }
    return $error;
}

sub createParam {
    my $self = shift;
    return $self->createRequiredParam(@_);
}

sub createRequiredParam {
    my $self = shift;
    my $param_name = shift;
    
    my $param = Solstice::ValidationParam->new($param_name);
    $param->setRequired();
    $param->addTrimmedLengthConstraint('input_required', {min => 1});
    
    push @{$self->{'_constraints'}}, $param;

    return $param;
}

sub createOptionalParam {
    my $self = shift;
    my $param_name = shift;

    my $param = Solstice::ValidationParam->new($param_name);
    $param->setOptional();
    
    push @{$self->{'_constraints'}}, $param;

    return $param;
}

sub createGroupDependency {
    my $self = shift;
    my $input = shift;

    push @{$self->{'_group_dependencies'}}, $input;

    return TRUE;
}

sub processConstraints {
    my $self = shift;
    my $global_error_key = shift;
    if (!defined $global_error_key) {
        $global_error_key = GLOBAL_FORM_ERROR_KEY;
    }
    
    # Start by pulling all of the data out of the constraint objects, and into a mungable form
    my @params = @{$self->{'_constraints'}};

    my (%required, %optional);
    my $constraints = {};
    my $require_some = {};
    
    for my $param (@params) {
        my $name = $param->getFieldName();
        if ($param->isRequired()) {
            $required{$name} = 1;
        } else {
            $optional{$name} = 1;
        }

        my $constraint_iterator = $param->getConstraints()->iterator();
        while (my $constraint = $constraint_iterator->next()) {
            push @{$constraints->{$name}}, { 
                name       => $constraint->{'error_key'},
                constraint => $constraint->{'constraint'},
            };
        }
    }
    
    # Go through the group dependencies...
    for my $dependency (@{$self->{'_group_dependencies'}}) {
        my $name = $dependency->{'dependency_name'};
        my $count = $dependency->{'require'};
        my @fields = @{$dependency->{'fields'}};
        for my $field (@fields) {
            delete $required{$field};
        }
        $require_some->{$name} = [$count, @fields];
    }

    # Create the form profile out of the intermediate data
    my $form_profile = {
        msgs         => $self->getErrMsgs(),
        optional     => [keys %optional],
        required     => [keys %required],
        require_some => $require_some,
        constraints  => $constraints,
    };

    my $valid = TRUE;
    if (my $error = $self->checkForm($form_profile)) {
        $valid = FALSE;

        $self->setError($error);
        
        ref($self) =~ m/^(\w+):.*$/;
        my $ns = $1;
        $self->getMessageService()->addErrorMessage(
            $self->getLangService($ns)->getMessage($global_error_key)
        );
    }
    return $valid;
}

sub setInputName {
    my $self = shift;
    $self->{'_input_name'} = shift;
}

sub getInputName {
    my $self = shift;
    return $self->{'_input_name'};
}

sub setOutputName {
    my $self = shift;
    $self->{'_output_name'} = shift;
}

sub getOutputName {
    my $self = shift;
    return $self->{'_output_name'};
}

sub getInputObject {
    my $self = shift;

    my $service = Solstice::Service->new;
    return $service->get($self->getInputName());
}

sub getOutputObject {
    my $self = shift;

    my $service = Solstice::Service->new;
    return $service->get($self->getOutputName());
}

sub setInputObject {
    my $self = shift;
    my $object = shift;

    my $service = Solstice::Service->new;
    $service->set($self->getInputName(), $object);
}

sub setOutputObject {
    my $self = shift;
    my $object = shift;

    my $service = Solstice::Service->new;
    $service->set($self->getOutputName(), $object);
}

sub createChildControllerList {
    my ($self, $name) = @_;

    return undef unless ($name);

    my $list = Solstice::List->new();

    ${$self->{'_child_controllers'}}{$name} = $list->getAll();

    return $list;
}


sub addChildController {
    my $self = shift;
    my $key = shift;
    my $arg = shift;

    unless (defined $self->{'_child_controllers'}){
        $self->{'_child_controllers'}{$key} = [];
    }
    if (!defined $arg){ 
        $self->warn('Tried to add an undefined child controller');
        return FALSE;
    }

    if (ref $arg eq 'ARRAY'){
        push @{$self->{'_child_controllers'}{$key}}, @$arg;
    }else{
        push @{$self->{'_child_controllers'}{$key}}, $arg;
    }
    return TRUE;
}

sub getChildController {
    my $self = shift;
    my $key = shift;

    my $controllers = $self->getChildControllers($key);
    if (defined $controllers and defined $$controllers[0]) {
        return $$controllers[0];
    }
    return;
}
    
sub getChildControllers{
    my $self = shift;
    my $key = shift;

    # Make sure we always return an array ref...
    return $self->{'_child_controllers'}{$key} || [];
}

sub clearChildControllers {
    my $self = shift;
    my $key = shift;

    $self->{'_child_controllers'}{$key} = [];
}

sub validateChildren {
    my $self = shift;
    my $key  = shift;

    my $retval = TRUE;
    for my $controller ( @{$self->getChildControllers($key)} ) {
        if (!defined $controller) {
            $self->warn('Tried to call validateChildren with an undefined controller');
            return FALSE;
        }
        $retval &= $controller->validate(@_);
    }
    return $retval;
}

sub updateChildren {
    my $self = shift;
    my $key  = shift;

    my $retval = TRUE;
    for my $controller ( @{$self->getChildControllers($key)} ) {
        if (!defined $controller) {
            $self->warn('Tried to call updateChildren with an undefined controller');
            return FALSE;
        }
        $retval &= $controller->update(@_);
    }
    return $retval;
}

sub revertChildren {
    my $self = shift;
    my $key  = shift;

    my $retval = TRUE;
    for my $controller ( @{$self->getChildControllers($key)} ) {
        if (!defined $controller) {
            $self->warn('Tried to call revertChildren with an undefined controller');
            return FALSE;
        }
        $retval &= $controller->revert(@_);
    }
    return $retval;
}

sub commitChildren {
    my $self = shift;
    my $key  = shift;

    my $retval = TRUE;
    for my $controller ( @{$self->getChildControllers($key)} ) {
        if (!defined $controller) {
            $self->warn('Tried to call commitChildren with an undefined controller');
            return FALSE;
        }
        $retval &= $controller->commit(@_);
    }
    return $retval;
}

sub validPreConditionsChildren {
    my $self = shift;
    my $key  = shift;

    my $retval = TRUE;
    for my $controller ( @{$self->getChildControllers($key)} ) {
        if (!defined $controller) {
            $self->warn('Tried to call validPreConditionsChildren with an undefined controller');
            return FALSE;
        }
        $retval &= $controller->validPreConditions(@_);
    }
    return $retval;
}


sub freshenChildren{
    my $self = shift;
    my $key = shift;

    my $retval = TRUE;
    for my $controller ( @{$self->getChildControllers($key)} ) {
        if (!defined $controller) {
            $self->warn('Tried to call freshenChildren with an undefined controller');
            return FALSE;
        }
        $retval &= $controller->freshen(@_);
    }
    return $retval;
}

sub getDateTimeController {
    my $self = shift;
    my $model = shift;
    return Solstice::Controller::FormInput::DateTime::YahooUI->new($model);
}

sub getRichTextController {
    my $self = shift;
    my $model = shift;

    my $service = Solstice::Service::Memory->new();

    my $has_fckeditor = $service->getValue('has_fckeditor');
    unless (defined $has_fckeditor ) {
        eval {
            $self->loadModule('FCKEditor::Controller::Editor');
        };
        $has_fckeditor = ($@) ? FALSE : TRUE;
        $service->setValue('has_fckeditor', $has_fckeditor);
    }
    
    my $controller;
    if ($has_fckeditor) {    
        $controller = FCKEditor::Controller::Editor->new($model);
    } else {
        $controller = Solstice::Controller::FormInput::TextArea->new($model);
    }
    return $controller;
}

sub _initErrMsgs {
    my $self = shift;

    ref($self) =~ m/^(\w+):.*$/;
    my $lang_service = $self->getLangService($1);

    $self->{'_msgs'} = {
        any_errors        => 'err',
        prefix            => 'err_',
        format            => '<span class="sol_error_notification_text">&nbsp;%s</span>',
        invalid_seperator => '<span class="sol_error_notification_text">, </span>',
        missing           => $lang_service->getError('input_required'),
        constraints       => $lang_service->getErrors(),
    };
    return TRUE;
}


1;
__END__