eXtropia WebDB Documentation

WebDB Code Walkthrough


Table of Contents:

[ TOC ]
[ TOC ]

Overview

Finally, let's take a look at how WebDB actually works.

As we mentioned in the introduction, the core WebDB is not contained in the CGI script. The script itself is simply a collection of configuration variables which are passed to the application object. This application object, WebDB.pm, is the actual workhorse.

With that in mind, we'll focus primarily in walking through WebDB.pm. WebDB.pm has several methods through which it does its work.

[ TOC ]


The Application Preamble

Like all eXtropia application objects, WebDB.pm opens with the standard eXtropia application preamble that is documented in the eXtropia Applications Guide. But to refresh your memory, here is what the preamble contains:

The application has several standard Perl module dependencies including the following:

The application also has the following standard eXtropia module dependencies:

[ TOC ]


The new() Method

Like every eXtropia application object, this application also defines a new() method that is called by webdb.cgi to construct the application object. The method is public and returns the application object.

Essentially the method performs four steps:

  1. Check incoming variables

  2. Create a Log object and AuthManager object

  3. Check that optional parameters make sense

  4. Return object

[ TOC ]


Step 1: Check Incoming Variables

The new() method uses the _rearrangeAsHash() method from Extropia::Base to order the incoming parameters and to check that all required parameters have been submitted. It then used the _dieIfRemainingParamsExist() method, also from Extropia::Base, to make sure that no other parameters were submitted. This protects users who make typos in configuring the application.

The newly ordered and checked parameters are then added to the $params hash.

Next, where appropriate, optional parameters are assigned default values using the _assignDefaults() method in Extropia::Base.

Finally, defaults are overridden by incoming variables where appropriate. In particular, we allow the view, max_records_per_page, sort_field1, and sort_field2 parameters to be overridden by user-defined values. We also assign values for administrative pagination variables.

 
    sub new {
        my $package = shift;
        my $self;
        ($self, @_) = _rearrangeAsHash([
            -CGI_OBJECT,
            -SESSION_OBJECT,
            -DATASOURCE_CONFIG_PARAMS,
            -AUTH_MANAGER_CONFIG_PARAMS,
            -ADD_FORM_DH_MANAGER_CONFIG_PARAMS,
            -MODIFY_FORM_DH_MANAGER_CONFIG_PARAMS,
            -DELETE_FORM_DH_MANAGER_CONFIG_PARAMS,
            -LOG_CONFIG_PARAMS,
            -DEFAULT_SORT_FIELD1,
            -DEFAULT_SORT_FIELD2,
            -DEFAULT_VIEW_NAME,
            -DEFAULT_MAX_RECORDS_PER_PAGE,
            -REQUIRE_AUTH_FOR_SEARCHING_FLAG,
            -ALLOW_ADDITIONS_FLAG,
            -ALLOW_MODIFICATIONS_FLAG,
            -ALLOW_DELETIONS_FLAG,
            -VIEW_FILTERS_CONFIG_PARAMS,
            -VIEW_LOADER,
            -VALID_VIEWS,
            -VIEW_DISPLAY_PARAMS,
            -BASIC_DATA_VIEW_NAME,
            -MODIFY_FORM_VIEW_NAME,
            -DELETE_FORM_VIEW_NAME,
            -ADD_FORM_VIEW_NAME,
            -MAIL_CONFIG_PARAMS,
            -SEND_EMAIL_ON_DELETE_FLAG,
            -SEND_EMAIL_ON_MODIFY_FLAG,
            -SEND_EMAIL_ON_ADD_FLAG,
            -DELETE_EVENT_MAIL_SEND_PARAMS, 
            -MODIFY_EVENT_MAIL_SEND_PARAMS, 
            -ADD_EVENT_MAIL_SEND_PARAMS, 
            -DELETE_EMAIL_BODY_VIEW,
            -ADD_EMAIL_BODY_VIEW,
            -MODIFY_EMAIL_BODY_VIEW
                ],
                [
            -CGI_OBJECT,
            -DATASOURCE_CONFIG_PARAMS,  
            -DEFAULT_VIEW_NAME,
            -BASIC_DATA_VIEW_NAME,
            -MODIFY_FORM_VIEW_NAME,
            -DELETE_FORM_VIEW_NAME,
            -ADD_FORM_VIEW_NAME,
            -VALID_VIEWS,
            -VIEW_DISPLAY_PARAMS,
            -VIEW_LOADER
                ],
            @_);
    
        _dieIfRemainingParamsExist(@_);
    
        $self = _assignDefaults($self, {
            -SEND_EMAIL_ON_DELETE_FLAG         => 0,
            -SEND_EMAIL_ON_ADD_FLAG            => 0,
            -SEND_EMAIL_ON_MODIFY_FLAG         => 0,
            -ALLOW_ADDITIONS_FLAG              => 0,
            -ALLOW_MODIFICATIONS_FLAG          => 0,
            -ALLOW_DELETIONS_FLAG              => 0,
            -REQUIRE_AUTH_FOR_SEARCHING_FLAG   => 1,
            -DEFAULT_MAX_RECORDS_PER_PAGE      => 10
        });
    
        $self->{'_view_name'} = $self->{'-DEFAULT_VIEW_NAME'};
        my $cgi = $self->{'-CGI_OBJECT'};
    
        $self->{'_sort_field1'} = $cgi->param('sort_field1') ||
                               $self->{'-DEFAULT_SORT_FIELD1'};

 
        $self->{'_sort_field2'} = $cgi->param('sort_field2') ||
                               $self->{'-DEFAULT_SORT_FIELD2'};
    
        $self->{'_max_records_per_page'} = $cgi->param('records_per_page') || 
                                     $self->{'-DEFAULT_MAX_RECORDS_PER_PAGE'};

 
        $self->{'_last_record_retrieved'} = 
            $cgi->param('first_record_to_display') ||
                                            0;
        $self->{'_first_record_on_page'}  = 
            $cgi->param('first_record_to_display') ||
                                            0;
        $self->{'_simple_search_string'}  = 
            $cgi->param('simple_search_string') || "";

[ TOC ]


Step 2: Create a Log Object and AuthManager Object

Next, Extropia::Log and Extropia::AuthManger objects are created and added to the $self hash.

 
    $self->{'_auth_manager_object'} =  Extropia::AuthManager->create(
        @{$self->{'-AUTH_MANAGER_CONFIG_PARAMS'}}
    ) or die("Whoopsy!  I was unable to construct the " .
             "Authentication object in the new() method of MLM.pm. Please ".
             "contact the webmaster.");
    
    $self->{'_log'} = 
        Extropia::Log->create(@{$self->{'-LOG_CONFIG_PARAMS'}})
        or die("Whoopsy!  I was unable to construct the " .
               "Log object in the new() method of MLM.pm. Please " .
               "contact the webmaster.");

[ TOC ]


Step 3: Check that optional parameters make sense

Then, the method checks to make sure that all optional parameters that have dependencies on other optional parameters are checked.

For example, if the optional -SEND_EMAIL_ON_ADD_FLAG is set to 1, the application will require that the optional -MAIL_CONFIG_PARAMS and -ADD_EVENT_MAIL_SEND_PARAMS parameters are defined as well.

 
    if ($self->{'-SEND_EMAIL_ON_MODIFY_FLAG'}) {
        if (!$self->{'-MAIL_CONFIG_PARAMS'} || 
            !$self->{'-MODIFY_EVENT_MAIL_SEND_PARAMS'}) {
            die("Whoopsy! In order to send mail, you must specify " .
                "-MAIL_CONFIG_PARAMS and -MODIFY_EVENT_MAIL_SEND_PARAMS");
        }
    }
    
    if ($self->{'-SEND_EMAIL_ON_ADD_FLAG'}) {
        if (!$self->{'-MAIL_CONFIG_PARAMS'} || 
            !$self->{'-ADD_EVENT_MAIL_SEND_PARAMS'}) {
            die("Whoopsy! In order to send mail, you must specify " .
                "-MAIL_CONFIG_PARAMS and -ADD_EVENT_MAIL_SEND_PARAMS");
        }
    }
    
    if ($self->{'-SEND_EMAIL_ON_DELETE_FLAG'}) {
        if (!$self->{'-MAIL_CONFIG_PARAMS'} || 
            !$self->{'-DELETE_EVENT_MAIL_SEND_PARAMS'}) {
            die("Whoopsy! In order to send mail, you must specify " .
                "-MAIL_CONFIG_PARAMS and -DELETE_EVENT_MAIL_SEND_PARAMS");
        }
    } 

[ TOC ]


Step 4: Return the object

Finally the object itself is returned to the caller.

 
    return bless $self, $package;

[ TOC ]


The do() Method

Like every eXtropia application object, this application defines a do() method. The method is public and returns whatever view is required based upon the results of processing. It is called from the last line of webdb.cgi.

The do() method handles eight cases.

  1. User submits an Add request.

  2. User submits a Modify request.

  3. User submits a Delete request.

  4. User requests to see the Add form

  5. User requests to see the Modify form

  6. user requests to see the Basic Data view.

  7. User requests to see another view (such as BottomFrameView).

[ TOC ]


Case 1: User Is Submitting An Add Request

If the user had just been on the Add form and submitted an add request, the value of the submit button named submit_add_record will have some value. As was discussed in the eXtropia Applications Guide, the following if control statement tests to see if the submit button has been clicked:

 
    if ($cgi->param('submit_add_record') && 
           $self->{'-ALLOW_ADDITIONS_FLAG'}) {

If the tests succeed, the do() method processes the addition using the _processAddRequest() method discussed later.

If the processing is successful, it calls the _displayView() method to display the Basic Data view. If, on the other hand, the processing is unsuccessful ( most likely due to data handling errors), the do() method redisplays the Add Form view using the _displayView() method.

 
    if ($cgi->param('submit_add_record') && 
           $self->{'-ALLOW_ADDITIONS_FLAG'}) {

 
        if ($auth_manager) {
            $auth_manager->authenticate();
        }
    
        my $add_request_success = $self->_processAddRequest(
            -CGI_OBJECT                 => $self->{'-CGI_OBJECT'},
            -LOG_OBJECT                 => $self->{'_log_object'},
            -DATASOURCE_CONFIG_PARAMS   => 
                $self->{'-DATASOURCE_CONFIG_PARAMS'},
            -MAIL_CONFIG_PARAMS         => $self->{'-MAIL_CONFIG_PARAMS'},
            -DATA_HANDLER_CONFIG_PARAMS => 
                $self->{'-ADD_FORM_DH_MANAGER_CONFIG_PARAMS'},
            -EMAIL_BODY_VIEW            => $self->{'-ADD_EMAIL_BODY_VIEW'},
            -MAIL_SEND_PARAMS           => 
                $self->{'-ADD_EVENT_MAIL_SEND_PARAMS'},
            -SEND_EMAIL_FLAG            => 
                $self->{'-SEND_EMAIL_ON_ADD_FLAG'},
            -VIEW_DISPLAY_PARAMS        => $self->{'-VIEW_DISPLAY_PARAMS'},
            -VIEW_LOADER                => $self->{'-VIEW_LOADER'}
        );
    
        if (!$add_request_success) {
            $self->{'_view_name'} = $self->{'-ADD_FORM_VIEW_NAME'};
        }
        else {
            $self->{'_view_name'} = $self->{'-BASIC_DATA_VIEW_NAME'};
        }
    
       return $self->_displayView(
            -VIEW_NAME                  => $self->{'_view_name'},
            -LOAD_DATA_FLAG             => 1,
            @default_view_display_params
        );
    }

[ TOC ]


Case 2: User Is Submitting A Modify Request

If you look at the code used to modify a record, you will see that it is almost identical to the code used for additions.

 
    elsif ($cgi->param('submit_modify_record') &&
        $self->{'-ALLOW_MODIFICATIONS_FLAG'}) {
    
        if ($auth_manager) {
            $auth_manager->authenticate();
        }
    
        my $modify_request_success = $self->_processModifyRequest(
            -CGI_OBJECT                 => $self->{'-CGI_OBJECT'},
            -LOG_OBJECT                 => $self->{'_log_object'},
            -DATASOURCE_CONFIG_PARAMS   => 
                $self->{'-DATASOURCE_CONFIG_PARAMS'},
            -MAIL_CONFIG_PARAMS         => $self->{'-MAIL_CONFIG_PARAMS'},
            -DATA_HANDLER_CONFIG_PARAMS => 
                $self->{'-MODIFY_FORM_DH_MANAGER_CONFIG_PARAMS'},
            -EMAIL_BODY_VIEW            => 
                $self->{'-MODIFY_EMAIL_BODY_VIEW'},
            -MAIL_SEND_PARAMS           => 
                $self->{'-MODIFY_EVENT_MAIL_SEND_PARAMS'},
            -SEND_EMAIL_FLAG            => 
                $self->{'-SEND_EMAIL_ON_MODIFY_FLAG'},
            -VIEW_DISPLAY_PARAMS        => $self->{'-VIEW_DISPLAY_PARAMS'},
            -VIEW_LOADER                => $self->{'-VIEW_LOADER'}
        );
    
        if (!$modify_request_success) {
            $self->{'_view_name'} = $self->{'-MODIFY_FORM_VIEW_NAME'};
        }
        else {
            $self->{'_view_name'} = $self->{'-BASIC_DATA_VIEW_NAME'};
        }
    
        return $self->_displayView(
            -VIEW_NAME                  => $self->{'_view_name'},
            -LOAD_DATA_FLAG             => 1,
            @default_view_display_params
        );
    }

[ TOC ]


Case 3: User Is Submitting A Delete Request

If you look at the code used to modify a record, you will see that it is almost identical to the code used for additions.

 
    elsif ($cgi->param('submit_delete_record') && 
        $self->{'-ALLOW_DELETIONS_FLAG'}) {

 
        if ($auth_manager) {
            $auth_manager->authenticate();
        }
    
        my $delete_request_success = $self->_processDeleteRequest(
            -CGI_OBJECT                 => $self->{'-CGI_OBJECT'},
            -LOG_OBJECT                 => $self->{'_log_object'},
            -DATASOURCE_CONFIG_PARAMS   => 
                $self->{'-DATASOURCE_CONFIG_PARAMS'},
            -MAIL_CONFIG_PARAMS         => $self->{'-MAIL_CONFIG_PARAMS'},
            -DATA_HANDLER_CONFIG_PARAMS => 
                $self->{'-DELETE_FORM_DH_MANAGER_CONFIG_PARAMS'},
            -EMAIL_BODY_VIEW            => 
                $self->{'-DELETE_EMAIL_BODY_VIEW'},
            -MAIL_SEND_PARAMS           => 
                $self->{'-DELETE_EVENT_MAIL_SEND_PARAMS'},
            -SEND_EMAIL_FLAG            => 
                $self->{'-SEND_EMAIL_ON_DELETE_FLAG'},
            -VIEW_DISPLAY_PARAMS        => $self->{'-VIEW_DISPLAY_PARAMS'},
            -VIEW_LOADER                => $self->{'-VIEW_LOADER'}
        );
    
        if (!$delete_request_success) {
            $self->{'_view_name'} = $self->{'-DELETE_FORM_VIEW_NAME'};
        }
        else {
            $self->{'_view_name'} = $self->{'-BASIC_DATA_VIEW_NAME'};
        }
    
       return $self->_displayView(
            -VIEW_NAME                  => $self->{'_view_name'},
            -LOAD_DATA_FLAG             => 1,
            @default_view_display_params
        );
    }

[ TOC ]


Case 4: User Requests To see The Add Form

If the user has requested to see the Add form, the method uses the _displayView() method to display the view.

 
    elsif ($cgi->param('display_add_form') &&
           $self->{'-ALLOW_ADDITIONS_FLAG'}) {
        
        if ($auth_manager) {
            $auth_manager->authenticate();
        }
    
        return $self->_displayView(
            -VIEW_NAME                  => $self->{'-ADD_FORM_VIEW_NAME'},
            @default_view_display_params
        );
    }

[ TOC ]


Case 5: User Requests To See The Modify Form

If the user has requested to see the Modify form, the method uses the _displayView() method to display the view.

 
    elsif ($cgi->param('display_modification_form') &&
           $self->{'-ALLOW_MODIFICATIONS_FLAG'}) {
    
        if ($auth_manager) {
            $auth_manager->authenticate();
        }
    
        return $self->_displayView(
            -VIEW_NAME                  => $self->{'-MODIFY_FORM_VIEW_NAME'},
            -LOAD_DATA_FLAG             => 1,
            @default_view_display_params
        );
    }

[ TOC ]


Case 6: User Requests To See The Basic Data View

If the user has requested to see the Basic data view, the method will use the _displayView() method to display the view

 
    elsif ($cgi->param('display_data_view') ||
           ($self->{'_view_name'} eq $self->{'-BASIC_DATA_VIEW_NAME'})) {
        
        if ($self->{'-REQUIRE_AUTH_FOR_SEARCHING_FLAG'}) {
            if ($auth_manager) {
                $auth_manager->authenticate();
            }
        }
    
       return $self->_displayView(
            -VIEW_NAME                  => $self->{'-BASIC_DATA_VIEW_NAME'},
            -LOAD_DATA_FLAG             => 1,
            @default_view_display_params
        );
    }

[ TOC ]


Case 7: User Requests To See Another View

If the user has requested to see another view, the method will use the _displayView() method to display the view.

 
    else { 
        return $self->_displayView(
            -VIEW_NAME  => $cgi->param('view') ||
                           $self->{'_view_name'},
            @default_view_display_params
        );
    }

There are several possible views that can be displayed. Which view is actually displayed depends on the rules explained in the following list:

[ TOC ]


The _displayView() Method

This method is used to display the requested view. Essentially, the method performs four functions:

  1. Check incoming variables.

  2. Load data if required to do so.

  3. Check for errors.

  4. Display view.

[ TOC ]


Step 1: Check Incoming Variables

The method uses the _rearrangeAsHash() method from Extropia::Base to order the incoming parameters and to check that all required parameters have been submitted. It then uses the _dieIfRemainingParamsExist() method, also from Extropia::Base, to check that no other parameters were submitted. This is protects users who make typos in configuring the application.

The newly ordered and checked parameters are then added to the $params hash.

Finally, where appropriate, optional parameters are assigned default values using the _assignDefaults() method in Extropia::Base.

 
    sub _displayView {
        my $self = shift;
        my ($params) = _rearrangeAsHash([
            -AUTH_MANAGER,
            -SESSION_OBJECT,
            -LOG_OBJECT,
            -MAX_RECORDS_PER_PAGE,
            -FIRST_RECORD_ON_PAGE,
            -SORT_FIELD1,
            -SORT_FIELD2,
            -SIMPLE_SEARCH_STRING,
            -VIEW_NAME,
            -VALID_VIEWS,
            -VIEW_LOADER,
            -VIEW_FILTERS_CONFIG_PARAMS,
            -VIEW_DISPLAY_PARAMS,
            -DATASOURCE_CONFIG_PARAMS,
            -LAST_RECORD_RETRIEVED,
            -CGI_OBJECT,
            -LOAD_DATA_FLAG
                ],
                [
            -MAX_RECORDS_PER_PAGE,
            -FIRST_RECORD_ON_PAGE,
            -SORT_FIELD1,
            -SORT_FIELD2,
            -SIMPLE_SEARCH_STRING,
            -VIEW_NAME,
            -VALID_VIEWS,
            -VIEW_LOADER,
            -VIEW_DISPLAY_PARAMS,
                ],
            @_
        );
    
        my $record_set;
    
        $params = _assignDefaults($params, {
            -LOAD_DATA_FLAG          => 0,
            -SIMPLE_SEARCH_STRING    => "",
            -SORT_FIELD1             => "",
            -SORT_FIELD2             => "",
            -MAX_RECORDS_PER_PAGE    => 10,
            -LAST_RECORD_RETRIEVED   => 0
        });
    
        if ($params->{'-LOAD_DATA_FLAG'}) {
            if (!$params->{'-DATASOURCE_CONFIG_PARAMS'} ||
                !$params->{'-CGI_OBJECT'}) {
                die("Whoopsy! -DATASOURCE_CONFIG_PARAMS and " .
                    "-CGI_OBJECT are required by _displayView(), " .
                    "but have not been supplied.");
        }

[ TOC ]


Step 2: Load Data If Required

Next, the method loads the data source entries if it is required to do so.

 
    if ($params->{'-LOAD_DATA_FLAG'}) {
        if (!$params->{'-DATASOURCE_CONFIG_PARAMS'} ||
            !$params->{'-CGI_OBJECT'}) {
            die("Whoopsy! -DATASOURCE_CONFIG_PARAMS and " .
                "-CGI_OBJECT are required by _displayView(), " .
                "but have not been supplied.");
        }
    
        $record_set = $self->_loadData((
            -DATASOURCE_CONFIG_PARAMS  => 
                 $params->{'-DATASOURCE_CONFIG_PARAMS'},
            -SORT_FIELD1               => $params->{'-SORT_FIELD1'},
            -SORT_FIELD2               => $params->{'-SORT_FIELD2'},
            -MAX_RECORDS_PER_PAGE      => $params->{'-MAX_RECORDS_PER_PAGE'},
            -LAST_RECORD_RETRIEVED     => 
                 $params->{'-LAST_RECORD_RETRIEVED'},
            -SIMPLE_SEARCH_STRING      => $params->{'-SIMPLE_SEARCH_STRING'},
            -CGI_OBJECT                => $params->{'-CGI_OBJECT'}
        ));
    }

[ TOC ]


Step 3: Check For Errors

Next the method checks to see if any errors have been built up in the processing of user input. To do so, it accesses the error object provided by Extropia::Base and goes through each error extracting the message that it will then pass to all views.

 
    my $errors_ref = $self->getErrors();
    
    my @errors;
    my $error;
    foreach $error (@$errors_ref) {
        push (@errors, $error->getMessage());
    }

[ TOC ]


Step 4: Display View

Finally, the method uses the _loadViewAndDisplay() method from Extropia::App to return the requested view.

 
    my $view_display_params = $params->{'-VIEW_DISPLAY_PARAMS'};
    
    return $self->_loadViewAndDisplay((
        -RECORD_SET                 => $record_set,
        -ERROR_MESSAGES             => \@errors,
        -AUTH_MANAGER               => $params->{'-AUTH_MANAGER'},
        -SESSION_OBJECT             => $params->{'-SESSION_OBJECT'},
        -LOG_OBJECT                 => $params->{'-LOG_OBJECT'},
        -MAX_RECORDS_PER_PAGE       => $params->{'-MAX_RECORDS_PER_PAGE'},
        -FIRST_RECORD_ON_PAGE       => $params->{'-FIRST_RECORD_ON_PAGE'},
        -SORT_FIELD1                => $params->{'-SORT_FIELD1'},
        -SORT_FIELD2                => $params->{'-SORT_FIELD2'},
        -SIMPLE_SEARCH_STRING       => $params->{'-SIMPLE_SEARCH_STRING'},
        -VIEW_NAME                  => $params->{'-VIEW_NAME'},
        -VALID_VIEWS                => $params->{'-VALID_VIEWS'},
        -VIEW_LOADER                => $params->{'-VIEW_LOADER'},
        -VIEW_FILTERS_CONFIG_PARAMS => 
            $params->{'-VIEW_FILTERS_CONFIG_PARAMS'},
        @$view_display_params
        ));
    }

[ TOC ]


The _processAddRequest() Method

There are four steps involved with processing an addition:

  1. Check incoming variables

  2. Handle Data

  3. Add the record

  4. Send Mail

[ TOC ]


Step 1: Check Incoming Variables

The method uses the _rearrangeAsHash() method from Extropia::Base to order the incoming parameters and to check that all required parameters have been submitted. It then uses the _dieIfRemainingParamsExist() method, also from Extropia::Base, to check that no other parameters were submitted. This is protects users who make typos in configuring the application.

The newly ordered and checked parameters are then added to the $params hash.

 
    sub _processAddRequest {
        my $self = shift;
    
        my ($params) = _rearrangeAsHash([
            -CGI_OBJECT,
            -LOG_OBJECT,
            -DATASOURCE_CONFIG_PARAMS,
            -MAIL_CONFIG_PARAMS,
            -DATA_HANDLER_CONFIG_PARAMS,
            -EMAIL_BODY_VIEW,
            -MAIL_SEND_PARAMS,
            -SEND_EMAIL_FLAG,
            -VIEW_DISPLAY_PARAMS,
            -VIEW_LOADER
                ],
                [
            -CGI_OBJECT,
            -DATASOURCE_CONFIG_PARAMS,
            -VIEW_DISPLAY_PARAMS,
            -VIEW_LOADER
                ],
            @_
        );

[ TOC ]


Step 2: Handle the Data

The next step in processing a form is to submit the incoming data to the data handling rules contained in the data handler manager. To handle the incoming data, we use the _handleIncomingData() method in Extropia::App. This method checks that incoming data conforms to the rules specified in the data handler manager defined in mlm.cgi. The method is discussed in detail in the eXtropia Applications Guide referenced in Appendix A: Further References.

If the incoming form data passes inspection, the method returns a 1 (true).

If, on the other hand, the data does not pass, the method returns an undef and logs the error using an Extropia::Log object if one has been supplied.

In the case of a data handling error, we also populate the local error variable given to us by Extropia::Base using the addError() method also inherited from Extropia::Base. The errors added are returned from the _getDataHandlerErrors() method defined in Extropia::App. Finally, we return undef to the do() method to let it know that the form data was bad.

 
        my $data_handler_success = $self->_handleIncomingData(
            -CGI_OBJECT                 => $cgi,
            -LOG_OBJECT                 => $log,
            -DATA_HANDLER_CONFIG_PARAMS =>
                $delete_form_dhm_config_params
        );
                              
        if (!$data_handler_success) {
            my $error;
            foreach $error ($self->_getDataHandlerErrors()) {
                $self->addError($error);
            }
            $self->{’-VIEW’}           = $add_form_view_name;
        }

[ TOC ]


Step 3: Adding the Record

If the data handler manager reports success, the method continues to process the request. The act of adding a new record is performed in the _addRecord() method that is discussed later in this chapter.

The _addRecord() method returns a 1 (true) if it is successful. If it is not successful, it returns an undef and logs the problem. If the addition is unsuccessful, the method sets the -VIEW configuration parameter to the Add form so that the form will be redisplayed with errors so that the user can try again.

 
    my $addition_success = $self->_addRecord((
        -CGI_OBJECT               => $params->{'-CGI_OBJECT'},
        -LOG_OBJECT               => $params->{'-LOG_OBJECT'},
        -DATASOURCE_CONFIG_PARAMS => $params->{'-DATASOURCE_CONFIG_PARAMS'}
    ));
      
    if (!$addition_success) {
        return undef;
    }

[ TOC ]


Step 4: Sending Mail

If, on the other hand, the record addition was successful, the method continues to process the request. Recall that in the application executable we specified a set of -MAIL_SEND_PARAMS that corresponded to the parameters that should be used in email sent out for different circumstances.

Here is where those configuration parameters are used.

The method begins by dealing with the admin receipt. Initially, it checks to see if the administrator has configured the application to send email receipts at all. Recall that we defined -SEND_MAIL_ON_DELETE_FLAG in the application executable. If set to 1, the method knows to send the user a receipt.

Mailing involves three steps:

Once the email receipt has been sent (or not depending on how you have configured the application), the method sends the user a notification. Of course, as was the case with the administrator receipt, whether or not the method sends the user notification will depend on the -SEND_USER_RECEIPT_FLAG_ON_DELETE configuration parameter.

The process of emailing the administrator notification is exactly the same as for emailing the user receipt so rather than bore you, we’ll just present the code in the following example:

 
    my $view_loader = $params->{'-VIEW_LOADER'};
    
    if ($params->{'-SEND_EMAIL_FLAG'}) {
        my $view = $view_loader->create(
            $params->{'-EMAIL_BODY_VIEW'}
        );

 
        my $body = $view->display(
            @{$params->{'-VIEW_DISPLAY_PARAMS'}}
        );
    
        $self->_sendReceipt((
            -MAIL_CONFIG_PARAMS => $params->{'-MAIL_CONFIG_PARAMS'},
            -BODY               => $body,
            @{$params->{'-MAIL_SEND_PARAMS'}}
        ));
    }

[ TOC ]


The _processModifyRequest() Method

This method does exactly the same thing as the _processAddRequest() method except that it is specific to modifications rather than additions. Because it works exactly the same, we won’t bother listing the code here.

[ TOC ]


The _processDeleteRequest() Method

This method does exactly the same thing as the _processAddRequest() method except that it is specific to deletions rather than additions. Because it works exactly the same, we won’t bother listing the code here.

[ TOC ]


The _sendReceipt() Method

This protected method is called from within each of the three _processXXXRequest() methods and is used to perform mailings. The method performs the following functions:

  1. Define variables.

  2. Instantiate an Extropia::Mail mailer.

  3. Attempt to send the requested mail.

[ TOC ]


Step 1: Define Variables

The method begins by using the _rearrange() method from Extropia::Base to order incoming parameters and check to make sure that all the required parameters have values. It then shifts the ordered variables off the parameter list.

 
    sub _sendReceipt {
        my $self = shift;
        @_ = _rearrange([
            -MAIL_CONFIG_PARAMS,   
            -FROM,
            -TO,
            -SUBJECT,
            -BODY,
                ],
                [
            -MAIL_CONFIG_PARAMS,
            -FROM,
            -TO,
            -SUBJECT,
            -BODY
                ],
            @_
        );  
    
        my $mail_config_params_ref = shift;
        my $from                   = shift;
        my $to_list_ref            = shift;
        my $subject                = shift;
        my $body                   = shift;

[ TOC ]


Step 2: Instantiate An Extropia::Mail Mailer.

The mail configuration parameters are then used to instantiate a mailer object.

 
    my $mailer = Extropia::Mail->create(@$mail_config_params_ref)
       or confess("Whoopsy!  I was unable to construct the Mail " . 
                  "object in the _sendMail() method of MLM.pm. " .
                  "Please contact the webmaster.");

[ TOC ]


Step 3: Attempt to send the requested mail.

The mail is then sent using the send() method in the mailer object.

 
    return $mailer->send((
        -FROM    => $from,
        -TO      => $to_list_ref,
        -SUBJECT => $subject,
        -BODY    => $body
    ));

[ TOC ]


The _loadData() Method

This protected method is called from within the do() method and is used to load guestbook entries for display. The method performs the following functions:

  1. Define variables.

  2. Refine search parameters based upon the simple_search_string and the display_without_admin_review variables.

  3. Instantiate an Extropia::DataSource object.

  4. Perform a search on the data source.

  5. Populate the internal error parameter if the search returned nothing and return undef, or return the record set returned from the search.

[ TOC ]


Step 1: Define The Variables

The method begins by using the _rearrange() method from Extropia::Base to order incoming parameters and check to make sure that all the required parameters have values.

 
    sub _loadData {
        my $self = shift;
        @_ = _rearrange([
            -DATASOURCE_CONFIG_PARAMS,  
            -SORT_FIELD1,  
            -SORT_FIELD2,  
            -MAX_RECORDS_PER_PAGE,
            -LAST_RECORD_RETRIEVED,
            -SIMPLE_SEARCH_STRING
                ],
                [
            -DATASOURCE_CONFIG_PARAMS,  
            -SORT_FIELD1,  
            -SORT_FIELD2,  
            -MAX_RECORDS_PER_PAGE,
            -LAST_RECORD_RETRIEVED,
            -SIMPLE_SEARCH_STRING
                ],
            @_);
    
        my $datasource_config_params_ref = shift;
        my $sort_field1                  = shift;
        my $sort_field2                  = shift;
        my $max_records_to_retrieve      = shift;
        my $last_record_retrieved        = shift;
        my $simple_search_string         = shift;

[ TOC ]


Step 2: Refine Search Parameters

Next, the method refines the search string.

 
    if ($simple_search_string) {
        $simple_search_string = "* =i '*" . $simple_search_string . "*'";
    }
    else {
        $simple_search_string = "* =i '*'";
    }

[ TOC ]


Step 3: Instantiate an Extropia::DataSource object.

The data source configuration parameters are then used to instantiate a data source object.

 
    my $search_ds = Extropia::DataSource->create(@$datasource_config_params_ref)
       or confess("Whoopsy!  I was unable to construct the " .
                  "DataSource object in the _loadData() method of " .
                  "WebDB.pm. Please contact the webmaster."); 

[ TOC ]


Step 4: Perform a search on the data source.

Then, the data source is searched.

 
    return $search_ds->search(
        -ORDER                   => "$sort_field1, $sort_field2",
        -MAX_RECORDS_TO_RETRIEVE => $max_records_to_retrieve,
        -LAST_RECORD_RETRIEVED   => $last_record_retrieved,
        -SEARCH                  => $simple_search_string
   );

[ TOC ]


The _addRecord() Method

This protected method is called from the _processAddRequest() method and is used to add a new entry to the mailing list. The method performs the following functions:

  1. Define variables.

  2. Instantiate an Extropia::DataSource object.

  3. Add the record.

  4. Log and report results.

[ TOC ]


Step 1: Define variables

The method begins by using the _rearrange() method from Extropia::Base to order incoming parameters and check to make sure that all the required parameters have values.

 
    sub _addRecord {
        my $self = shift;
        @_ = _rearrange([
            -CGI_OBJECT,
            -LOG_OBJECT,
            -DATASOURCE_CONFIG_PARAMS
                ],
                [
            -CGI_OBJECT,
            -DATASOURCE_CONFIG_PARAMS
                ],
            @_);
    
        my $cgi                          = shift;
        my $log                          = shift;
        my $datasource_config_params_ref = shift;

[ TOC ]


Step 2: Instantiate an Extropia::DataSource object.

The data source configuration parameters are then used to instantiate a data source object.

 
    my $add_ds = Extropia::DataSource->create(@$datasource_config_params_ref)
       or confess("Whoopsy!  I was unable to construct the " .
                  "DataSource object in the _addRecord() method " .
                  "of WebDB.pm. Please contact the webmaster.");

[ TOC ]


Step 3: Add the record

Then a hash of name/value pairs is created to use to add the record.

 
    my @params = $cgi->param();
    my (%add_hash, $param);
    
    foreach $param (@params) {
        $add_hash{$param} = $cgi->param($param);
    }
    
    my $rows_added = $add_ds->add(-ADD => \%add_hash);

[ TOC ]


Step 4: Log and report results.

Finally, if there were any problems adding the record, the errors are logged and the method returns undef to report the problem to the caller. Otherwise, the success is logged and a true value (1) is returned to the caller to report success.

 
    if ($add_ds->getErrorCount()) {
        $self->addError($add_ds->getLastError());
        if ($log) {
            $log->log(   
                 -SEVERITY =>  Extropia::Log::WARN,
                 -EVENT    => "FAILED_ADDITION|" . 
                              $add_ds->getLastError()->getMessage()
            );
            return undef;
        }
    }
                 
    else {
        if ($log) {
            my $key;
            my @add_array;
            foreach $key (keys %add_hash) {
               push (@add_array, "$key=" . $add_hash{$key});
            } 
            my $add_string = join("\|", @add_array);
            $log->log(
                 -SEVERITY =>  Extropia::Log::INFO,
                 -EVENT    => "ADDITION PERFORMED\|" . 
                              "ADD_DEFINITION: $add_string"
            );
        }       
    }
    return 1;

[ TOC ]


The _deleteRecord() Method

This protected method is called from the _processDeleteRequest() method and is used to delete an entry from the mailing list. The method is almost identical to the _addRecord() method so we won’t list the code here. Instead we will outline its functions:

[ TOC ]


The _modifyRecord() Method

This protected method is called from the _processModifyRequest() method and is used to delete an entry from the mailing list. The method is almost identical to the _addRecord() method so we won't list the code here. Instead we will outline its functions:

[ TOC ]


Code Walkthrough in Review

Hopefully that was not too much to take in. The code the makes the mailing list manager application work is actually not all that difficult. In summary, what you learned is that:

  1. The new() method instantiates the object.

  2. The do() method handles the workflow.

    In the case of this application, the workflow boils down to three cases including:

    1. Allow a user to add a new entry

    2. Allow the user to delete an entry

    3. Allow an administrator to send a mailing to all list members

  3. The _sendMail() method helps the do() method by sending the various mails the application needs to send.

  4. The _addRecord() method helps the do() method by actually performing the new entry addition using Extropia::DataSource.

  5. The _deleteRecord() method helps the do() method by actually performing deletions using Extropia::DataSource.

  6. The _modifyRecord() method helps the do() method by actually performing modifications using Extropia::DataSource.
[ TOC ]

[ TOC ]


[ TOC ]
Master Copy URL: http://www.extropia.com/support/docs/webdb/
Copyright © 2000-2001 Extropia. All rights reserved.
[ TOC ]
Written by eXtropia.
Last Modified at 09/20/2001