Drupal 7 "Sample Request" feature using Flag, Views, Webform, and a few hooks
Today @welly in #drupal-support asked about how to have Druapl 7 "users to be able to flag a bunch of nodes and then submit their list of flagged nodes to an admin user some how."
I just happened to do that exact thing for a client project just a few weeks ago.
So here's my approach.
Using Flag (and Session API for anonymous flagging) with Views, Webform, and a few webform hooks, I was able to allow users to flag items for which they could request samples in a webform.
There are four components:
- Flagging
- Requesting
- Unflagging
- Rendering
Flagging
The flagging component should be self-explanatory to anyone who has used Flag -- a flag link is provided. In my case, I provided a link to the Request (Step 2) within the Flag's confirmation message, to allow the user to quickly jump to their request (list) after flagging (or unflagging) any item.


Requesting
I created a webform with a few fields, one of them being a select list. Webform now supports select list options to be populated from pre built lists. These are implementations of hook_webform_select_options(). Webform provides a few for US states, etc.
My implementation just used a view. (See @mconnerton's webform_views_select sandbox for the Views plugin that can provide the options implementation without writing the hook manually.).

Here is the code for this feature:
/** * Implements hook_webform_select_options_info(). */ function MODULE_webform_select_options_info() { 'title' => t("Sample Requests (User Flag list)"), 'options callback' => '_MODULE_user_flag_sample_requests', ); } return $items; } function _MODULE_user_flag_sample_requests() { $view = views_get_view('user_flag_sample_request', TRUE); $view->set_display('webform_options'); $view->execute(); if ($view->result) { $row_class = $view->style_options['row_class']; $attributes = $row_class ? " class='$row_class'" : ''; foreach($view->result as $item) { $options[$item->nid] = '<a' . $attributes . '>' . render($item->field_field_img[0]['rendered']) . ' ' . $item->field_ref_colorway_node_title . ' (' . $item->node_title . ')' . '</a>'; } } else { $options[0] = t("Nothing"); } return $options; }
Here the hook registers a callback; the callback builds a one-dimensional array with keys of node ids and values of HTML strings including a few of the view fields -- image, title, and in my case the title of the node's "owner" (a node reference field)
Then, after choosing this source of options for my webform component, I have a list of any items which the active user of the site has flagged.

Now that the flagged items are options in a webform select list, I need to unflag them once the webform is submitted.
Unflagging
To unflag each item requested in a webform submission, I implement a second webform hook -- hook_webform_submission_insert():
/** * Respond to a Webform submission being inserted. * * Note that this hook is called after a submission has already been saved to * the database. If needing to modify the submission prior to insertion, use * hook_webform_submission_presave(). * * @param $node * The Webform node on which this submission was made. * @param $submission * The Webform submission that was just inserted into the database. */ function MODULE_webform_submission_insert($node, $submission) { global $user; // Unflag selected items foreach ($submission->data[1]['value'] as $k => $nid) { flag_flag('unflag', 'sample_request', $nid, $user); $flag->flag('unflag', $nid, $user); } }
Rendering
And since the submitted webform will hold the values of each flagged node id, I used a third hook to display a little more about the node than just its id -- hook_webform_submission_render_alter():
/** * Implementation of hook_webform_submission_render_alter(). * * Displays links to nodes in place of their nids. */ // dpm / drupal_set_message here to discover $renderable array. foreach ($nodes as $node) { $renderable['requested_items']['#value'][$node->nid] = l('[' . $node->type . '] ' . $node->title, 'node/' . $node->nid); } }
This prints a text link in both the webform results displayed on the site and returned in the webform submission email(s).

....That's about it. Comment with questions or ideas on how you approach a problem like this.
-Steve
- Steve Oliver's blog
- Login to post comments
