Modifying submitted data

Our demonstration Speaker Registration form requires potential speakers to supply a title for their presentation in the Presentation title textfield. The Fictitious Conference organizers have requested us to ensure that data entered into this field is properly formatted in title case (for example, This Is A Sentence In Title Case), as opposed to the conventional sentence case.

Rather than attempting to enforce this requirement as a validation rule, we have decided to merely apply formatting to the input without informing the registering speakers, since we are not making a material change to their submitted data. Thankfully Webform provides a hook for us to make changes to submitted data rather easily via a plugin custom module.

Getting ready

Let us quickly handle the preliminary steps to creating our module so that we may focus on the actual coding in the exercise that follows. We have been through these steps before in the recipe Changing Webform results defaults discussed in Chapter 3, Working with Submissions, and Defining custom option lists discussed in Chapter 6, Extending Webform, so there is no need to spend much time now explaining the familiar pattern of steps:

  1. Create a custom module folder called webform_custom_format in sites/all/modules so that we have the folder path sites/all/modules/webform_custom_format.
  2. Next we add our module info a file called webform_custom_format.info into the sites/all/modules/webform_custom_format folder we just created. Edit the file to add the following text and save the changes:
    name = Webform Custom Format
    description = Custom formatting rules for Webforms.
    core = 7.x
    package = Webform
    dependencies[] = webform
    
  3. Now we can add our module file by creating an empty file called webform_custom_format.module in our new module folder. We add the following lines of code to our module file and save the changes:
    <?php
    /**
    * @file
    * Webform Custom Format.
    */
    
  4. Finally, we navigate to our Drupal Modules administration page, check the box to enable our bare-bones module and click on Save configuration (even though the module does not actually do anything yet).
    Getting ready

The coding with which we will apply the required formatting rule will be placed into our webform_custom_format.module file. Since we have already enabled the module, we should find that any changes we make to the code in our module file become immediately effective. If it happens that a coding change does not appear to be taking effect immediately, we may return to the Modules administration page and merely click on the Save configuration button to refresh Drupal's modules cache.

How to do it...

We are about to code three functions that will help us achieve the required title case formatting of the Presentation title field input. The first function we code will implement the hook_webform_submission_presave() hook required to change submitted data prior to storing it in the database. The second function is a helper function to assist us in obtaining the internal Webform component identifiers of those components whose values we wish to affect. The final function will apply the required title case formatting to the submitted values.

  1. Implementing hook_webform_submission_presave() is where we specify the driving logic in our webform_custom_format.module file, so let's get it coded in there underneath the last bit of code:
    /**
    * Implements hook_webform_submission_presave().
    */
    function webform_custom_format_webform_submission_presave($node, &$submission) {
    switch ($node->title) {
    case "Speaker Registration":
    $field_keys = array('presentation_title'),
    $cids = webform_custom_format_get_cids($node->nid, $field_keys);
    foreach ($cids as $cid) {
    $value = $submission->data[$cid]['value'][0];
    $value = webform_custom_format_title_case($value);
    $submission->data[$cid]['value'][0] = $value;
    }
    break;
    }
    }
    
  2. Obtaining the required component identifiers is handled by the webform_custom_format_get_cids() function which we also code into our webform_custom_format.module file:
    /**
    * Retrieve Webform component id's for specified field keys from the
    * webform_component database table.
    *
    * @param int $node_id
    * The node id of the Webform node on which this submission was made.
    * @param array $field_keys
    * An array of form field keys for which we need component id's.
    * @return array
    * A list of component id's in cid sequence.
    */
    function webform_custom_format_get_cids($node_id, $field_keys) {
    $cids = db_select('webform_component', 'wc')
    ->fields('wc', array('cid'))
    ->condition('nid', $node_id)
    ->condition('form_key', $field_keys, 'IN')
    ->orderBy('cid')
    ->execute()
    ->fetchCol();
    return $cids;
    }
    
  3. The application of title case formatting will be performed by the webform_custom_format_title_case() function code that we add in next:
    /**
    * Reformat user input to title case and allow for hyphenated words.
    * See http://www.php.net/manual/en/function.ucwords.php#106598
    *
    * @param string $value
    * The submitted value we wish to transform to title case.
    * @param string $delimiter
    * Optional inter-word delimiter - defaults to hyphen.
    * @return string
    * The formatted string value.
    */
    function webform_custom_format_title_case($value, $delimiter = '-') {
    $delimiter_space = $delimiter . ' ';
    $value = str_replace($delimiter, $delimiter_space, $value);
    $value = ucwords($value);
    $value = str_replace($delimiter_space, $delimiter, $value);
    return $value;
    }
    

We can now save these changes to the webform_custom_format.module file and return to our Speaker Registration form. To test our module we want to enter a new submission, taking care to submit a Presentation title that will adequately test our code. For our test we shall enter the text this was a lower-case title. Let's fill out the remaining required values, submit the form and navigate to our Speaker Registration form's Results page, and click on view to see how our module has transformed the new submission in the PRESENTATION DETAILS fieldset.

How to do it...

How it works...

To implement a hook that has been exposed by another module, we need to create a module and place a function within that module that is built on the hook name. We implement a hook, such as hook_webform_submission_presave(), by substituting the word hook with our full module name, thus giving rise to the function name we created previously, webform_custom_format_webform_submission_presave().

After Webform is done with processing our submitted form and found no validation errors, control gets passed to any modules that implement the hook_webform_submission_presave() hook.

Our custom hook function has a PHP switch construct which ensures that the formatting code will only execute when a submission is made to our Speaker Registration form. This is to prevent the possibility of formatting being attempted when a different Webform on our site is submitted. Assuming the submission is from our form, we then call the webform_custom_format_get_cids() helper function.

The helper function uses the supplied array of component field keys to retrieve the respective component identifiers from the webform_component database table using the Drupal Database API db_select() function. Whereas it is easier for computers to reference array items by number, we find that our coding is far more readable when we can make use of descriptive labels. The Webform system builds an array of our submitted values which is indexed by the numeric component identifier. This function purely serves to translate the descriptive labels into the numeric indexes used by the internal system.

To find out what the field key for a specific component is we need to navigate to our Speaker Registration form's Webform link and click on Form components. Once there, we click on Edit next to the respective component name and we will see the Field Key value appearing underneath the Label textfield on the component edit page.

How it works...

Armed with the component identifier numbers, our module now sends the required submitted values from the $submission->data array to the webform_custom_format_title_case() function for formatting. The submitted values are then subsequently replaced by the newly formatted values.

When our custom module processing finishes, control passes back to the Webform module which writes the submitted data, complete with changes, into the database.

This cycle of processing will occur every time a form is submitted, whether that be from a site visitor to the form itself, or when a website administrator saves an edited submission.

There's more...

As we browse about in the various forums and issue queues on the drupal.org website, we will see that folks sometimes object to the idea of having to create a custom plugin module. As we have now seen, it does not need to take more than a few short minutes to create such a module and the potential rewards make the effort well worthwhile.

Granted, there is a learning curve involved for those of us new to Drupal programming, but it is by no means an insurmountable obstacle. It just requires a bit of application and practice.

Deciding on direction

As is so often the case, there is another way we might have achieved the objective of applying title case formatting. In Chapter 7, Theming Webform, we learned that theming functions will enable us to change the way our submitted data is output. Clearly, then, we could have opted for that route instead.

The chief drawback of solving this formatting issue via theming is the necessary processing every time the field data is output. In other words, the same processing would occur on every submission view, every time an e-mail is sent, and every time the data is downloaded. In this case it makes more sense to have this module which converts the data at submission time and is done with it, rather than unnecessarily repeating the same processing.

Solve specific problems generally

This heading may sound like an oxymoron, but it is not. As developers, we should attempt, as far as possible, to create a general solution to a specific problem, so that we are able to solve more than one problem with our solution if the need arises.

Should our Fictitious Conference organizers now request that we also apply title case formatting to the First name and Last name fields of the Speaker Registration form, we can quickly and easily meet their demands. Having taken the time to structure our solution in a manner that solves the formatting problem generally, all we need to do is change one line of code by adding the additional field's keys to our $field_keys array like so:

$field_keys = array('presentation_title', 'first_name', 'last_name'),

Now title case formatting will be applied to three fields, instead of just the one we originally had. An added bonus stemming from our generalized approach is that this formatting ability is also available for any number of fields on any number of Webforms across our site by simply including the relevant case blocks.

In contrast, our preceding example did not, strictly speaking, require the two functions that are called from within our webform_custom_format_webform_submission_presave() hook function originally. We could have looked at the URL of our Presentation title component edit form, made a note of the component identifier, and hardcoded the formatting requirement directly into webform_custom_format_webform_submission_presave(). The downside of doing things that way is that we would need to repeat the formatting code for every additional field we wish to format and we would need to repeat it yet again for every Webform on our site that requires similar functionality. Clearly it is more rewarding to structure our code such that it is reusable.

Drupal coding standards and best practices

Those of us new to the inner workings of the Drupal CMS should invest some time learning how Drupal developers go about things. Apart from the obvious benefits of writing self-documenting code, we will find that more people on the forums are willing to assist with problems we may encounter when our code looks like we made an effort to comply with the norms. In fact, problems often come about exactly because one or more standards were ignored.

An excellent resource for information regarding coding and other standards is to be found on the drupal.org website at http://drupal.org/documentation/develop.

Also, at our disposal are automated tools which can assist us in our bid to adhere to the stringent Drupal coding requirements. The Coder project is located at http://drupal.org/project/coder and Drupal Code Sniffer at http://drupal.org/project/drupalcs.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset