Need some help with your project? Contact me

Showing private Webform fields to anonymous users based on URL query strings

I’m sure everybody knows the Webform module as the go-to module for creating surveys and gathering all sorts of information from people. It is indeed a great module that provides a lot of flexibility and can be used very well for event registration forms as well. In this tutorial I am going to show you a way in which you can filter the visibility of webform components based on query strings passed in the URL.

I recently needed to create a registration form for a conference with multiple events - some private, some public. People should be able to register to multiple events at once but only some people are able to register for the private events. What that means in practice is that I needed a single registration form but which allowed me to filter some of the events based on the URL or something. Out of the box, you cannot do this with Webform.

So what did I do? After pondering on possible solutions, I figured out an acceptable one. Since all the people who will register will be anonymous users, private webform components (fieldsets primarily) would be hidden from them. So this took care of making the difference between the public and private events. But how to make the private events visible to those anonymous users they should be visible for? No, no user registration. A bit of simple code in a custom module that would remove the private status of some components based on some query parameters:

/*
 * Implements hook_node_load().
 */
function my_module_node_load($nodes, $types) {
  if($nodes[111]) {
    $params = drupal_get_query_parameters();

    foreach ($params as $key => $value) {
      foreach ($nodes[111]->webform['components'] as &$component) {
        if ($component['form_key'] == check_plain($key)) {
          $component['extra']['private'] = check_plain($value);
        }
      }
    }
  }
}

So what happens here? I implement hook_node_load() to act on a node being loaded and hard code the ID of the node (111) for which I want to do this. Here you can play around and add more flexibility, maybe even create something in the UI to select for which webform you’d like this to happen.

Next, I gather the query parameters from the URL into an array. Inside a foreach() iteration of this array, I also iterate through all the webform components on this node and check if the form key (the machine name of the field) is equal to any of the query parameter names passed in the URL. If any do, then I set the private status of that component to the value of that query parameter. Simple. So what does this mean in practice?

All information regarding each event gets put within a fieldset in the webform (for the sake of being able to control multiple fields related to one event at once). For the private events, this fieldset becomes private and gets a specific machine name (let’s say privateEvent). Then when I go to the URL of the registration form, I pass that machine name as a parameter and assign it to 0 (example.com/registration?privateEvent=0). This means that the private status of the fieldset with the machine name privateEvent (which is currently private) gets set to 0 (not private). This way it becomes visible to that anonymous user who goes to the registration form with this URL.

So as long as you are not super duper paranoid about people guessing the parameters for the private events, this can work. And you can name those fieldsets as secretive as you want so you make sure only the people who receive the right URL get the private event.

Hope this helps someone.

Comments

I think the check_plain()'s are unnecessary as you're not outputting the values. It might make sense to validate the values in some way, however.

Hey there :)

Probably, but I usually add it there for good measure :)

D

Add new comment

You can post comments in Markdown and basic HTML tags.
For code blocks, wrap your code within '~~~'. For example:
~~~
$var = 'my variable';
~~~