Gantry

 view release on metacpan or  search on metacpan

lib/Gantry/Plugins/CRUD.pm  view on Meta::CPAN

    my $self = shift;
    return $self->{text_descr}
}

sub use_clean_dates {
    my $self = shift;
    return $self->{use_clean_dates};
}

sub turn_off_clean_params {
    my $self = shift;
    return $self->{turn_off_clean_params};
}

sub validator {
    my $self = shift;
    return $self->{validator}
}

#-----------------------------------------------------------
# Methods users call
#-----------------------------------------------------------

#-------------------------------------------------
# $self->add( $your_self, { put => 'your', data => 'here' } )
#-------------------------------------------------
sub add {
    my ( $self, $your_self, $data ) = @_;

    # Use the specified default template in the config if no
    # template was specified to the crud module and there is a
    # default defined.
    if (
        ( ! $self->{ignore_default_template} ) and
        ( $your_self->fish_config( 'default_form_template' ) )
    ) {
        $your_self->stash->view->template(
            $your_self->fish_config( 'default_form_template' )
        );
    }
    else {
        $your_self->stash->view->template( $self->template );
    }

    $your_self->stash->view->title( 'Add ' . $self->text_descr )
            unless $your_self->stash->view->title;

    my $params   = $your_self->get_param_hash();

    # Redirect if user pressed 'Cancel'
    if ( $params->{cancel} ) {
        my $redirect = $self->_find_redirect(
            {
                gantry_site => $your_self,
                data        => $data,
                user_req    => 'add',
                action      => 'cancel',
            }
        );

        return $your_self->relocate( $redirect );
    }

    # get and hold the form description
    my $form = $self->form->( $your_self, $data );

    # Check form data
    my $show_form = 0;
    my $results;

    if ( $your_self->is_post ) {
        $show_form = 1 if ( keys %{ $params } == 0 );

        if ( $self->validator ) {
            $results = $self->validator->(
                {
                    self      => $your_self,
                    params    => $params,
                    form      => $form,
                    profile   => form_profile( $form->{fields} ),
                    action    => 'add',
                }
            );
        }
        else {
            $results = Data::FormValidator->check(
                $params,
                form_profile( $form->{fields} ),
            );
        }

        $show_form = 1 if ( $results->has_invalid );
        $show_form = 1 if ( $results->has_missing );
        $show_form = 1 if ( $form->{ error_text } );
    }
    else {
        $show_form = 1;
    }

    if ( $show_form ) {
        # order is important, first put in the form...
        $your_self->stash->view->form( $form );

        # ... then add error results
        if ( $your_self->method eq 'POST' ) {
            $your_self->stash->view->form->results( $results );
        }
    }
    else {
        my $redirect;
        my $action =    $params->{submit_add_another}
                        ? 'submit_add_another'
                        : 'submit';
        
        # remove submit button entry
        delete $params->{submit};
        delete $params->{submit_add_another};

        if ( $self->turn_off_clean_params ) {
            if ( $self->use_clean_dates ) {
                clean_dates( $params, $form->{ fields } );
            }
        }
        else {
            clean_params( $params, $form->{ fields } );
        }

        $self->add_action->( $your_self, $params, $data );
        
        # Find redirect.
        $redirect = $self->_find_redirect(
            {
                gantry_site => $your_self,
                data        => $data,
                action      => $action,
                user_req    => 'add'
            }
        );

        return $your_self->relocate( $redirect );
    }
} # END: add

#-------------------------------------------------
# $self->edit( $your_self, { put => 'your', data => 'here' } );
#-------------------------------------------------
sub edit {
    my ( $self, $your_self, $data ) = @_;

    # Use the specified default template in the config if no
    # template was specified to the crud module and there is a
    # default defined.
    if (
        ( ! $self->{ignore_default_template} ) and
        ( $your_self->fish_config( 'default_form_template' ) )
    ) {
        $your_self->stash->view->template(
            $your_self->fish_config( 'default_form_template' )
        );
    }
    else {
        $your_self->stash->view->template( $self->template );
    }

    $your_self->stash->view->title( 'Edit ' . $self->text_descr() )
            unless $your_self->stash->view->title;

    my %params = $your_self->get_param_hash();

    # Redirect if 'Cancel'
    if ( $params{cancel} ) {
        my $redirect = $self->_find_redirect(
            {
                gantry_site => $your_self,
                data        => $data,
                action      => 'cancel',
                user_req    => 'edit',
            }
        );
        return $your_self->relocate( $redirect );
    }

    # get and hold the form description
    my $form = $self->form->( $your_self, $data );

    croak 'Your form callback gave me nothing' unless defined $form and $form;

    my $show_form = 0;
    my $results;

    if ( $your_self->is_post ) {
        $show_form = 1 if ( keys %params == 0 );

        # Check form data
        if ( $self->validator ) {
            $results = $self->validator->(
                {
                    self      => $your_self,
                    params    => \%params,
                    form      => $form,
                    profile   => form_profile( $form->{ fields } ),
                    action    => 'edit',
                }
            );
        }
        else {
            $results = Data::FormValidator->check(
                \%params,
                form_profile( $form->{ fields } ),
            );
        }

        $show_form = 1 if ( $results->has_invalid );
        $show_form = 1 if ( $results->has_missing );
        $show_form = 1 if ( $form->{ error_text } );
    }
    else {
        $show_form = 1;
    }

    # Form has errors
    if ( $show_form ) {
        # order matters, get form data first...
        $your_self->stash->view->form( $form );

        # ... then overlay with results
        if ( $your_self->method eq 'POST' ) {
            $your_self->stash->view->form->results( $results );
        }
    
    }
    # Form looks good, make update
    else {
        my $redirect;
        my $action =    $params{submit_add_another}
                        ? 'submit_add_another'
                        : 'submit';
        
        # remove submit button entry
        delete $params{submit};
        delete $params{submit_add_another};
               
        if ( $self->turn_off_clean_params ) {
            if ( $self->use_clean_dates ) {
                clean_dates( \%params, $form->{ fields } );
            }
        }
        else {
            clean_params( \%params, $form->{ fields } );
        }

        $self->edit_action->( $your_self, \%params, $data );
        
        # Find redirect.
        $redirect = $self->_find_redirect(
            {
                gantry_site => $your_self,
                data        => $data,
                action      => $action,
                user_req    => 'edit'
            }
        );
        
        return $your_self->relocate( $redirect );
    }
} # END: edit

#-------------------------------------------------
# $self->delete( $your_self, $confirm, { other => 'data' } )
#-------------------------------------------------
sub delete {
    my ( $self, $your_self, $yes, $data ) = @_;

    $your_self->stash->view->template( 'delete.tt' )
        unless $your_self->stash->view->template();
    $your_self->stash->view->title( 'Delete' )
            unless $your_self->stash->view->title;

    if ( $your_self->params->{cancel} ) {
        my $redirect = $self->_find_redirect(
            {
                gantry_site => $your_self,
                data        => $data,
                action      => 'cancel',
                user_req    => 'delete'
            }
        );
        return $your_self->relocate( $redirect );
    }

    if ( ( defined $yes ) and ( $yes eq 'yes' ) ) {

        $self->delete_action->( $your_self, $data );

        # Move along, it's already dead
        my $redirect = $self->_find_redirect(
            {
                gantry_site => $your_self,
                data        => $data,
                action      => 'submit',
                user_req    => 'delete'
            }
        );
        return $your_self->relocate( $redirect );
    }
    else {
        $your_self->stash->view->form->message (
            'Delete ' . $self->text_descr() . '?'
        );
    }
}

#-----------------------------------------------------------
# Helpers
#-----------------------------------------------------------

sub _find_redirect {
    my ( $self, $args ) = @_;
    my $your_self = $args->{ gantry_site };
    my $data      = $args->{ data };
    my $action    = $args->{ action };
    my $user_req  = $args->{ user_req };

    my $retval;

    my $redirect_sub = $self->redirect;

    if ( $redirect_sub ) {
        $retval = $redirect_sub->( $your_self, $data, $action, $user_req );
    }
    else {
        $retval = $your_self->location();
    }

    return $retval;
}

#-----------------------------------------------------------
# Helper functions offered for export
#-----------------------------------------------------------

sub select_multiple_closure {
    my $field_name  = shift;
    my $db_selected = shift;

    return sub {
        my $id     = shift;
        my $params = shift;

        my @real_keys = grep ! /^\./, keys %{ $params };

        if ( @real_keys ) {
            return unless $params->{ $field_name };
            my @param_ids = split /\0/, $params->{ $field_name };
            foreach my $param_id ( @param_ids ) {
                return 1 if ( $param_id == $id );
            }
        }
        else {
            return $db_selected->{ $id };
        }
    };
}

lib/Gantry/Plugins/CRUD.pm  view on Meta::CPAN


    your self object
    the data you passed to the add, edit, or delete
    the action: 'submit', 'submit_add_another' or 'cancel'
    the user request: 'add', 'edit' or 'delete'

=item template (optional, defaults to form.tt)

The name of your form template.

=item text_descr

The text string used in the page titles and in the delete confirmation
message.

=item use_clean_dates (optional, defaults to false)

This is ignored unless you turn_off_clean_params, since it is redundant
when clean_params is in use.

Make this true if you want your dates cleaned immediately before your
add and edit callbacks are invoked.

Cleaning sets any false fields marked as dates in the form fields list
to undef.  This allows your ORM to correctly insert them as
nulls instead of trying to insert them as blank strings (which is fatal,
at least in PostgreSQL).

For this to work your form fields must have this key: C<<is => 'date'>>.

=item turn_off_clean_params (optional, defaults to false)

By default, right before an SQL insert or update, the params hash from the
form is passed through the clean_params routine which sets all non-boolean
fields which are false to undef.  This prevents SQL errors with ORMs that
can correctly translate blank strings into nulls for non-string types.

If you really don't want this routine, set turn_off_clean_params.  If you
turn it off, you can use_clean_dates, which only sets false dates to undef.

=back

Note that in all cases the submit key is removed from the params hash
by this module before any callback is made.

=item add

Call this in your do_add on a C<Gantry::Plugins::CRUD> instance:

    sub do_special_add {
        my $self = shift;
        $crud_obj->add( $self, { data => \@_ } );
    }

It will die unless you passed the following to the constructor:

        add_action
        form

You may also pass C<redirect> which must return a location suitable for passing
to $your_self->relocate.

=item edit

Call this in your do_edit on a C<Gantry::Plugins::CRUD> instance:

    sub do_special_edit {
        my $self = shift;
        my $id   = shift;
        my $row  = Data::Model->retrieve( $id );
        $crud_obj->edit( $self, { id => $id, row => $row } );
    }

It will die unless you passed the following to the constructor:

        edit_action
        form

You may also pass C<redirect> which must return a location suitable for passing
to $your_self->relocate.

=item delete

Call this in your do_delete on a C<Gantry::Plugins::CRUD> instance:

    sub do_special_delete {
        my $self    = shift;
        my $id      = shift;
        my $confirm = shift;
        $crud_obj->delete( $self, $confirm, { id => $id } );
    }

The C<$confirm> argument is yes if the delete should go ahead and anything
else otherwise.  This allows our standard practice of having delete
urls like this:

    http://somesite.example.com/item/delete/4

which leads to the confirmation form whose submit action is:

    http://somesite.example.com/item/delete/4/yes

which is taken as confirmation.

It will die unless you passed the following to the constructor:

        delete_action

You may also pass C<redirect> which must return a location suitable for passing
to $your_self->relocate.

=back

You can pick and choose which CRUD help you want from this module.  It is
designed to give you maximum flexibility, while doing the most repetative
things in a reasonable way.  It is perfectly good use of this module to
have only one method which calls edit.  On the other hand, you might have
two methods that call edit on two different instances, two methods
that call add on those same instances and a method that calls delete on
one of the instances.  Mix and match.

=head1 HELPER FUNCTIONS

=over 4

=item select_multiple_closure

If you have a form field of type select_multiple, one of the form.tt keys
is selected.  It wants a sub ref so it can reselect items when the form
fails to validate.  This function will generate the proper sub ref (aka
closure).

Parameters:
    form field name
    hash reference of default selections (usually the ones in the database)

Returns: a closure suitable for immediate use as the selected hash key value
for a form field of type select_multiple.

=back

=head1 SEE ALSO

 Gantry::Plugins::AutoCRUD (for simpler situations)

 Gantry and the other Gantry::Plugins

=head1 LIMITATIONS

Currently only one redirection can be defined.  You can get more control
by ending your action callback like this:

    return $self->relocate( 'http://location.of/your/choice' );

=head1 AUTHOR

Phil Crow <philcrow2000@yahoo.com>

=head1 COPYRIGHT and LICENSE

Copyright (c) 2005, Phil Crow

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.6 or,
at your option, any later version of Perl 5 you may have available.

=cut



( run in 0.547 second using v1.01-cache-2.11-cpan-5511b514fd6 )