3

Does anyone know a way to programmatically render a view from a module using the default theme after editing a node?

I'm basically trying to create a static html page of a view.

I have the following code in a custom module:

function MODULENAME_node_update($node) {
  unset($node->is_new);
  unset($node->original);    
  entity_get_controller('node')->resetCache(array($node->nid));
  $view = views_get_view('references');
  $view->set_display('block');
  $output = $view->render();
  file_put_contents('references.html', $output);
}

The code works but for obvious reasons it renders the view using the admin theme.

I have tried several things to no avail:

variable_set

function MODULENAME_node_update($node) {
  variable_set('admin_theme', 'DEFAULT THEME HERE');
  [...]
  variable_set('admin_theme', 'ADMIN THEME HERE');
}

This hook is probably not the right place to switch themes as it is invoked too late for this.

global $custom_theme

function MODULENAME_node_update($node) {
  global $custom_theme;
  $custom_theme = 'DEFAULT THEME HERE';
  [...]
  $custom_theme = 'ADMIN THEME HERE';
}

custom menu item

function MODULE_NAME_menu(){
  $items = array();

  $items['outputview'] = array(
    'title' => 'Test',
    'type' => MENU_CALLBACK,
    'page callback' => 'MODULE_NAME_output_view',
    'access callback' => TRUE,
    'theme callback' => 'DEFAULT THEME HERE'
  );

  return $items;
}

function MODULE_NAME_output_view() {
  $view = views_get_view('references');
  $view->set_display('block');
  $output = $view->render();
  file_put_contents('references.html', $output);
}

function MODULE_NAME_node_update($node) {
    unset($node->is_new);
    unset($node->original);
    entity_get_controller('node')->resetCache(array($node->nid));
    menu_execute_active_handler('outputview', FALSE); // or via curl
}

This works as the view gets rendered correctly but still uses the admin theme.

hook_custom_theme

function MODULENAME_custom_theme(){
  return 'DEFAULT THEME HERE';
}
David
  • 201
  • 2
  • 8

2 Answers2

1

I am looking for something similar. I found some code doing this (see patch #3 https://drupal.org/node/1813350), but it did not help with our implementation of the Shortcode contrib module. Hopefully it works for you or help you in the right direction.

This is our attempt derived from the patch:

$custom_theme_bu = drupal_static('menu_get_custom_theme');
$custom_theme = &drupal_static('menu_get_custom_theme');

$custom_theme = variable_get('theme_default', 'bartik');
unset($GLOBALS['theme']);
drupal_theme_initialize();

$embed_view = views_embed_view('YOUR_VIEW_ID', 'YOUR_VIEW_DISPLAY_ID');

$custom_theme = $custom_theme_bu;
unset($GLOBALS['theme']);
drupal_theme_initialize();
lmeurs
  • 16,111
  • 4
  • 27
  • 30
  • The patch actually works. Add two functions to your code and call the first one for switching theme and then after the job done call the second one to revert the default theme. I used it in a cron email and it worked fine. – sumanchalki May 12 '16 at 08:24
0

Here is some self-documenting code based on the answer by lmeurs:

/**
 * Switch to or from an alternative theme in the middle of a request.
 *
 * This is useful if you need to render something (like a node) in a different
 * theme without changing the theme of the entire page. An example use case is
 * when you need to render something for a front end user from an admin page.
 *
 * Usage example:
 *     my_module_switch_theme('bartik');
 *     $node = node_load(1);
 *     $renderable = node_view($node);
 *     $rendered = render($renderable);
 *     my_module_switch_theme();
 *
 * @param string|null $to
 *   The name of the theme to switch to. If NULL, it switches back to the
 *   original theme.
 */
function my_module_switch_theme(string $to = NULL) {
  // Backup the original theme.
  static $original_theme;
  if (empty($original_theme)) {
    $original_theme = drupal_static('menu_get_custom_theme');
  }

  // Get a reference to the current theme value.
  $custom_theme = &drupal_static('menu_get_custom_theme');

  // Perform the switch.
  $custom_theme = $to ?? $original_theme;
  unset($GLOBALS['theme']);
  drupal_theme_initialize();
}
rudolfbyker
  • 2,034
  • 1
  • 20
  • 25
  • This only works if a custom theme is set (see https://api.drupal.org/api/drupal/includes%21menu.inc/function/menu_get_custom_theme/7.x on how that is determined). Also, it doesn't seem to properly work without also clearing the cache. – berliner Nov 06 '21 at 19:28