[Drupal] How to create a theme switcher module for Drupal 7? - Part 2

| | 4 min read

In this article we will be explaining how an anonymous user can switch the theme of a Drupal site. This is the continuation of my previous article How to create Theme Switcher module for Drupal 7 Part 1? If you want to know how to create a theme switcher module for Drupal 7 then read on to know more.

In this article we will look at how we can display the buttons to switch the themes on the site which includes a button to select a random theme.

Now lets begin our module file named as fdt_theme_switcher.module. We are using the hook hook_page_build(), which will be used to call the other functions like fdt_theme_switcher_generate() which will return the theme switcher form as a string. We will also be adding a js file in the function.

/**
 * Implements hook_page_build().
 */
function fdt_theme_switcher_page_build(&$page) {
  //if(!user_access('administer')){
  if(user_is_anonymous()){
    $page['page_top']['theme_switcher'] = array(
      '#markup' => fdt_theme_switcher_generate());
    drupal_add_js(drupal_get_path('module', 'fdt_theme_switcher').'/js/themeSwitcher.js');  
  }
}

/**
 * themeSwitcher.js
*/

(function ($) {
  Drupal.theme_switcher = Drupal.theme_switcher || {};
  Drupal.behaviors.theme_switcher = {
    attach: function () {
       $('select#edit-theme').change(function() {
          $(this).closest("form").submit();
      });
    }
  };
})(jQuery);

The function fdt_theme_switcher_generate() returns the value of the current theme and displays the theme switcher form.

function fdt_theme_switcher_generate()
{

    global $current_theme;
    $fdtpath="http://www.freedrupalthemes.net/customize-theme?n=$current_theme";
    $output="";
    $output.="<div id='top-bar'>";
    $output.='<h2>Customize this theme</h2>';
    $output.="<div id='top-bar-sub'>";
    $output.=/*"".*/drupal_render(drupal_get_form('fdt_theme_switcher_themeswitcher_form'));
    $output.="</div>";
    $output.="</div>";
    return $output;
}

Now lets call the form fdt_themeswitcher_form. In this form there are three buttons

  • Next -> To goto next theme
  • Previous -> To goto previous theme
  • Random -> To display a random theme

See the form array structure below

function fdt_theme_switcher_themeswitcher_form($form, &$form_state) {
  
  global $current_theme;
  $options = fdt_theme_switcher_options();
  
  $form['themeswitcher']['actions']['previous_theme'] = array(
    '#type' => 'submit',
    '#value' => t('Previous'),
    '#id' => 'previous_theme',
    '#submit' => array('fdt_theme_switcher_themeswitcher_form_previous_theme'),
    '#limit_validation_errors' => array(),
  );
  
  $form['themeswitcher']['actions']['random_theme'] = array(
    '#type' => 'submit',
    '#value' => t('Random'),
    '#id' => 'random_theme',
    '#submit' => array('fdt_theme_switcher_themeswitcher_form_random_theme'),
    '#limit_validation_errors' => array(),
  );
  
  $form['themeswitcher']['actions']['next_theme'] = array(
    '#type' => 'submit',
    '#value' => t('Next'),
    '#id' => 'next_theme',
    '#submit' => array('fdt_theme_switcher_themeswitcher_form_next_theme'),
    '#limit_validation_errors' => array(),
  );
  return $form;
}

We will store the current theme name in a variable $current_theme and then pass it as a global variable. To display all the theme names in a select box we will use the function fdt_theme_switcher_options() and the value is stored in $options.

See the code below

function fdt_theme_switcher_options() {
  $options = array();
  $themes = list_themes();
  foreach ($themes as $name => $theme) {
    if ($theme->status) {
      $options[$name] = $theme->info['name'];
    }
  }
  return $options;
}

Next comes the form submit function. In the submit function, the values passed are the themename and baseurl as a global variable. We will store the theme name to variable $themeurl in format t/<theme_name>. Now the function return will call drupal_goto() with the corresponding theme name and enable it.

See the submit function for each buttons

For the option to select the random theme we will write a query to call a random theme name from the system table and pass this value as $themeurl.

/*
Function Called to display Random theme
*/
function fdt_theme_switcher_themeswitcher_form_random_theme($form, &$form_state) {
  global $base_url,$current_theme;
  $themes = list_themes();
  $result = db_query("SELECT name FROM {system} WHERE type='theme' AND status=1 ORDER BY RAND() LIMIT 1");
  foreach ($result as $record) {
    $build=$record->name;
  }
  $themeurl="t/".$build;
  $options = array(
               //'fragment' => '', 
               'query' => '',
               'absolute' => TRUE, 
               'alias' => FALSE, 
               'prefix' => 'goto',
               'external' => FALSE
  	         );
 	drupal_goto($themeurl,$options);
}

To get the value of the next theme we will try to write a query to select all the themes in descending order. Then we proceed to retrieve the position of each theme and store the corresponding theme name to that location. We will check each theme with the current theme and if it is found we will be able to get the next theme postion and subsequently the theme name from that position. Finally we pass this value as themeurl to the drupal_goto function.

/*
Function Called to display Next theme
*/

function fdt_theme_switcher_themeswitcher_form_next_theme($form, &$form_state) {

  global $base_url,$current_theme;
  $count_elements=0;
  $themes = list_themes();
  $num_themes = count($themes);
  $result = db_query("SELECT name FROM {system} WHERE type='theme' AND status=1 ORDER BY name DESC");
  foreach ($result as $record) {
    $count_elements = $count_elements+1; 
    $build[$count_elements]=$record->name;
    if($build[$count_elements]==$current_theme){
      if($count_elements!=1){
        $themeurl="t/".$build[$count_elements-1];
        $options = array(
                     //'fragment' => '', 
                     'query' => '',
                     'absolute' => TRUE, 
                     'alias' => FALSE, 
                     'prefix' => 'goto',
                     'external' => FALSE
  	               );
        drupal_goto($themeurl,$options);
 	    }
 	  }	 
  }
}

For the 'Next' theme button, we will write a query to select all the themes in the ascending order and the process is repeated as previously.

/*
Function Called to display Previous theme
*/

function fdt_theme_switcher_themeswitcher_form_previous_theme($form, &$form_state) {
  
  global $base_url,$current_theme;
  $themes = list_themes();
  $num_themes = count($themes);
  $theme_count= $num_themes;
  $count_elements = $num_themes - 1;
  $result = db_query("SELECT name FROM {system} WHERE type='theme' AND status=1 ORDER BY name ASC");
  foreach ($result as $record) {
    $count_elements = $count_elements-1; 
    $build[$count_elements]=$record->name;
    if($build[$count_elements]==$current_theme){
      if($count_elements+1!=$theme_count-1){
        $themeurl="t/".$build[$count_elements+1];
        $options = array(
                     //'fragment' => '', 
                     'query' => '',
                     'absolute' => TRUE, 
                     'alias' => FALSE, 
                     'prefix' => 'goto',
                     'external' => FALSE
  	               );
        drupal_goto($themeurl,$options);
 	    }
 	  }	 
  }
}

You can also refer the first part of this article at How to create Theme Switcher module for Drupal 7 Part 1? to see how we have used following hooks to view inner pages of the themes.

  • hook_url_inbound_alter() -> Will strip the "t/<theme_name>" from the urls internally
  • hook_url_outbound_alter() -> Rewriteall urls in the site to include the t/<theme_name>

Feel free to send me your feedback using the comment form below.