You are here

phptemplate.engine in Drupal 5

Handles integration of templates written in pure php with the Drupal theme system.

File

themes/engines/phptemplate/phptemplate.engine
View source
<?php

// $Id$

/**
 * @file
 * Handles integration of templates written in pure php with the Drupal theme system.
 */
function phptemplate_init($template) {
  $file = dirname($template->filename) . '/template.php';
  if (file_exists($file)) {
    include_once "./{$file}";
  }
}
function phptemplate_templates($directory = 'themes') {
  return drupal_system_listing('^page\\.tpl\\.php$', $directory, 'filename');
}

/**
 * Declare the available regions implemented by this engine.
 *
 * @return
 *  An array of regions. The first array element will be used as the default region for themes.
 */
function phptemplate_regions() {
  return array(
    'left' => t('left sidebar'),
    'right' => t('right sidebar'),
    'content' => t('content'),
    'header' => t('header'),
    'footer' => t('footer'),
  );
}

/**
 * Execute a template engine call.
 *
 * Each call to the template engine has two parts. Namely preparing
 * the variables, and then doing something with them.
 *
 * The first step is done by all template engines / themes, the second
 * step is dependent on the engine used.
 *
 * @param $hook
 *   The name of the theme function being executed.
 * @param $variables
 *   A sequential array of variables passed to the theme function.
 * @param $suggestions
 *   An array of suggested template files to use. If none of the files are found, the
 *   default $hook.tpl.php will be used.
 * @return
 *  The HTML generated by the template system.
 */
function _phptemplate_callback($hook, $variables = array(), $suggestions = array()) {
  global $theme_engine;
  $variables = array_merge($variables, _phptemplate_default_variables($hook, $variables));

  // Allow specified variables to be overridden
  $variables_function = '_' . $theme_engine . '_variables';
  if (function_exists($variables_function)) {
    $variables = array_merge($variables, call_user_func($variables_function, $hook, $variables));
  }
  if (isset($variables['template_files'])) {
    $suggestions = array_merge($suggestions, $variables['template_files']);
  }
  if (isset($variables['template_file'])) {
    $suggestions[] = $variables['template_file'];
  }
  $hook_function = '_' . $theme_engine . '_' . $hook;
  $default_function = '_' . $theme_engine . '_default';
  if (function_exists($hook_function)) {
    return call_user_func($hook_function, $variables, $suggestions);
  }
  elseif (function_exists($default_function)) {
    return call_user_func($default_function, $hook, $variables, $suggestions);
  }
}

/**
 * Adds additional helper variables to all templates.
 *
 * Counts how many times certain hooks have been called. Sidebar left / right are special cases.
 *
 * @param $hook
 *   The name of the theme function being executed.
 * @param $variables
 *   A sequential array of variables passed to the theme function.
 */
function _phptemplate_default_variables($hook, $variables) {
  global $theme, $sidebar_indicator;
  static $count = array();
  $count[$hook] = isset($count[$hook]) && is_int($count[$hook]) ? $count[$hook] : 1;
  $variables['zebra'] = $count[$hook] % 2 ? 'odd' : 'even';
  $variables['id'] = $count[$hook]++;
  if ($hook == 'block') {
    $count['block_counter'][$sidebar_indicator] = isset($count['block_counter'][$sidebar_indicator]) && is_int($count['block_counter'][$sidebar_indicator]) ? $count['block_counter'][$sidebar_indicator] : 1;
    $variables['block_zebra'] = $count['block_counter'][$sidebar_indicator] % 2 ? 'odd' : 'even';
    $variables['block_id'] = $count['block_counter'][$sidebar_indicator]++;
  }
  elseif ($hook == 'page') {
    $regions = system_region_list($theme);

    // Load all region content assigned via blocks.
    foreach (array_keys($regions) as $region) {

      // Skip blocks in this region that have already been loaded.
      // This pre-loading is necessary because phptemplate uses variable names different from
      // the region names, e.g., 'sidebar_left' instead of 'left'.
      if (!in_array($region, array(
        'left',
        'right',
        'footer',
      ))) {
        $normal_blocks = isset($variables['regions']) ? $variables['regions'][$region] : theme('blocks', $region);
        isset($variables[$region]) ? $variables[$region] .= $normal_blocks : ($variables[$region] = $normal_blocks);
      }
    }
  }

  // Tell all templates where they are located.
  $variables['directory'] = path_to_theme();
  $variables['is_front'] = drupal_is_front_page();
  return $variables;
}

/**
 * @return
 *  Array of template features
 */
function phptemplate_features() {
  return array(
    'toggle_logo',
    'toggle_comment_user_picture',
    'toggle_favicon',
    'toggle_mission',
    'toggle_name',
    'toggle_node_user_picture',
    'toggle_search',
    'toggle_slogan',
  );
}

/**
 * Prepare the values passed to the theme_page function to be passed
 * into a pluggable template engine. Uses the arg() function to
 * generate a series of page template files suggestions based on the
 * current path. If none are found, the default page.tpl.php is used.
 */
function phptemplate_page($content, $show_blocks = TRUE) {
  global $theme;
  $regions = array_keys(system_region_list($theme));
  $variables = array(
    'regions' => array(),
  );

  /* Set title and breadcrumb to declared values */
  if (drupal_is_front_page()) {
    $mission = filter_xss_admin(theme_get_setting('mission'));
  }

  /* Add favicon */
  if (theme_get_setting('toggle_favicon')) {
    drupal_set_html_head('<link rel="shortcut icon" href="' . check_url(theme_get_setting('favicon')) . '" type="image/x-icon" />');
  }

  // Populate sidebars
  $layout = 'none';
  if ($show_blocks) {
    global $sidebar_indicator;

    // Load blocks early for adding header info
    foreach ($regions as $region) {

      // Sidebar_indicator tells the block counting code
      // to count sidebars separately.
      if ($region == 'left' || $region == 'right') {
        $sidebar_indicator = $region;
      }
      else {
        $sidebar_indicator = NULL;
      }
      $variables['regions'][$region] = theme('blocks', $region);
    }
    $sidebar_indicator = NULL;
    $sidebar_left = $variables['regions']['left'];
    if ($sidebar_left != '') {
      $layout = 'left';
    }
    $sidebar_right = $variables['regions']['right'];
    if ($sidebar_right != '') {
      $layout = $layout == 'left' ? 'both' : 'right';
    }
  }
  else {

    // Add empty strings as default
    foreach ($regions as $region) {
      $variables['regions'][$region] = '';
    }
  }

  // Construct page title
  if (drupal_get_title()) {
    $head_title = array(
      strip_tags(drupal_get_title()),
      variable_get('site_name', 'Drupal'),
    );
  }
  else {
    $head_title = array(
      variable_get('site_name', 'Drupal'),
    );
    if (variable_get('site_slogan', '')) {
      $head_title[] = variable_get('site_slogan', '');
    }
  }
  $variables = array_merge($variables, array(
    'base_path' => base_path(),
    'breadcrumb' => theme('breadcrumb', drupal_get_breadcrumb()),
    'closure' => theme('closure'),
    'content' => $content,
    'feed_icons' => drupal_get_feeds(),
    'footer_message' => filter_xss_admin(variable_get('site_footer', FALSE)) . "\n" . $variables['regions']['footer'],
    'head' => drupal_get_html_head(),
    'head_title' => implode(' | ', $head_title),
    'help' => theme('help'),
    'language' => $GLOBALS['locale'],
    'layout' => $layout,
    'logo' => theme_get_setting('logo'),
    'messages' => theme('status_messages'),
    'mission' => isset($mission) ? $mission : '',
    'primary_links' => menu_primary_links(),
    'search_box' => theme_get_setting('toggle_search') ? drupal_get_form('search_theme_form') : '',
    'secondary_links' => menu_secondary_links(),
    'sidebar_left' => $sidebar_left,
    'sidebar_right' => $sidebar_right,
    'site_name' => theme_get_setting('toggle_name') ? variable_get('site_name', 'Drupal') : '',
    'site_slogan' => theme_get_setting('toggle_slogan') ? variable_get('site_slogan', '') : '',
    'css' => drupal_add_css(),
    'styles' => drupal_get_css(),
    'scripts' => drupal_get_js(),
    'tabs' => theme('menu_local_tasks'),
    'title' => drupal_get_title(),
  ));
  if (arg(0) == 'node' && is_numeric(arg(1))) {
    $variables['node'] = node_load(arg(1));
  }

  // Build a list of suggested template files in order of specificity. One
  // suggestion is made for every element of the current path, though
  // numeric elements are not carried to subsequent suggestions. For example,
  // http://www.example.com/node/1/edit would result in the following
  // suggestions:
  //
  // page-node-edit.tpl.php
  // page-node-1.tpl.php
  // page-node.tpl.php
  // page.tpl.php
  $i = 0;
  $suggestion = 'page';
  $suggestions = array(
    $suggestion,
  );
  while ($arg = arg($i++)) {
    $arg = str_replace(array(
      "/",
      "\\",
      "\0",
    ), '', $arg);
    $suggestions[] = $suggestion . '-' . $arg;
    if (!is_numeric($arg)) {
      $suggestion .= '-' . $arg;
    }
  }
  if (drupal_is_front_page()) {
    $suggestions[] = 'page-front';
  }
  return _phptemplate_callback('page', $variables, $suggestions);
}

/**
 * Prepare the values passed to the theme_node function to be passed
 * into a pluggable template engine.
 */
function phptemplate_node($node, $teaser = 0, $page = 0) {
  if (module_exists('taxonomy')) {
    $taxonomy = taxonomy_link('taxonomy terms', $node);
  }
  else {
    $taxonomy = array();
  }
  $variables = array(
    'content' => $teaser && $node->teaser ? $node->teaser : $node->body,
    'date' => format_date($node->created),
    'links' => $node->links ? theme('links', $node->links, array(
      'class' => 'links inline',
    )) : '',
    'name' => theme('username', $node),
    'node' => $node,
    // we pass the actual node to allow more customization
    'node_url' => url('node/' . $node->nid),
    'page' => $page,
    'taxonomy' => $taxonomy,
    'teaser' => $teaser,
    'terms' => theme('links', $taxonomy, array(
      'class' => 'links inline',
    )),
    'title' => check_plain($node->title),
  );

  // Flatten the node object's member fields.
  $variables = array_merge((array) $node, $variables);

  // Display info only on certain node types.
  if (theme_get_setting('toggle_node_info_' . $node->type)) {
    $variables['submitted'] = t('Submitted by !a on @b.', array(
      '!a' => theme('username', $node),
      '@b' => format_date($node->created),
    ));
    $variables['picture'] = theme_get_setting('toggle_node_user_picture') ? theme('user_picture', $node) : '';
  }
  else {
    $variables['submitted'] = '';
    $variables['picture'] = '';
  }
  return _phptemplate_callback('node', $variables, array(
    'node-' . $node->type,
  ));
}

/**
 * Prepare the values passed to the theme_comment function to be passed
 * into a pluggable template engine.
 */
function phptemplate_comment($comment, $links = 0) {
  return _phptemplate_callback('comment', array(
    'author' => theme('username', $comment),
    'comment' => $comment,
    'content' => $comment->comment,
    'date' => format_date($comment->timestamp),
    'links' => isset($links) ? theme('links', $links) : '',
    'new' => $comment->new ? t('new') : '',
    'picture' => theme_get_setting('toggle_comment_user_picture') ? theme('user_picture', $comment) : '',
    'submitted' => t('Submitted by !a on @b.', array(
      '!a' => theme('username', $comment),
      '@b' => format_date($comment->timestamp),
    )),
    'title' => l($comment->subject, $_GET['q'], NULL, NULL, "comment-{$comment->cid}"),
  ));
}

/**
 * Prepare the values passed to the theme_block function to be passed
 * into a pluggable template engine. Uses block properties to generate a
 * series of template file suggestions. If none are found, the default
 * block.tpl.php is used.
 */
function phptemplate_block($block) {
  $suggestions[] = 'block';
  $suggestions[] = 'block-' . $block->region;
  $suggestions[] = 'block-' . $block->module;
  $suggestions[] = 'block-' . $block->module . '-' . $block->delta;
  return _phptemplate_callback('block', array(
    'block' => $block,
  ), $suggestions);
}

/**
 * Prepare the values passed to the theme_box function to be passed
 * into a pluggable template engine.
 */
function phptemplate_box($title, $content, $region = 'main') {
  return _phptemplate_callback('box', array(
    'content' => $content,
    'region' => $region,
    'title' => $title,
  ));
}

/**
 * Default callback for PHPTemplate.
 *
 * Load a template file, and pass the variable array to it.
 * If the suggested file is not found, PHPTemplate will attempt to use
 * a $hook.tpl.php file in the template directory, and failing that a
 * $hook.tpl.php in the PHPTemplate directory.
 *
 * @param $hook
 *   The name of the theme function being executed.
 * @param $variables
 *   A sequential array of variables passed to the theme function.
 * @param $suggestions
 *   An array of suggested template files to use. This may include a path when
 *   the suggested template is contained within a sub-directory of the theme.
 *   They are set from _phptemplate_variables() or the theming hook invoking
 *   _phptemplate_callback().
 */
function _phptemplate_default($hook, $variables, $suggestions = array(), $extension = '.tpl.php') {
  global $theme_engine;

  // Loop through any suggestions in FIFO order.
  $suggestions = array_reverse($suggestions);
  foreach ($suggestions as $suggestion) {
    if (!empty($suggestion) && file_exists(path_to_theme() . '/' . $suggestion . $extension)) {
      $file = path_to_theme() . '/' . $suggestion . $extension;
      break;
    }
  }
  if (!isset($file)) {
    if (file_exists(path_to_theme() . "/{$hook}{$extension}")) {
      $file = path_to_theme() . "/{$hook}{$extension}";
    }
    else {
      if (in_array($hook, array(
        'node',
        'block',
        'box',
        'comment',
      ))) {
        $file = path_to_engine() . '/' . $hook . $extension;
      }
      else {
        $variables['hook'] = $hook;
        watchdog('error', t('%engine.engine was instructed to override the %name theme function, but no valid template file was found.', array(
          '%engine' => $theme_engine,
          '%name' => $hook,
        )));
        $file = path_to_engine() . '/default' . $extension;
      }
    }
  }
  if (isset($file)) {
    return call_user_func('_' . $theme_engine . '_render', $file, $variables);
  }
}
function _phptemplate_render($file, $variables) {
  extract($variables, EXTR_SKIP);

  // Extract the variables to a local namespace
  ob_start();

  // Start output buffering
  include "./{$file}";

  // Include the file
  $contents = ob_get_contents();

  // Get the contents of the buffer
  ob_end_clean();

  // End buffering and discard
  return $contents;

  // Return the contents
}

Functions

Namesort descending Description
phptemplate_block Prepare the values passed to the theme_block function to be passed into a pluggable template engine. Uses block properties to generate a series of template file suggestions. If none are found, the default block.tpl.php is used.
phptemplate_box Prepare the values passed to the theme_box function to be passed into a pluggable template engine.
phptemplate_comment Prepare the values passed to the theme_comment function to be passed into a pluggable template engine.
phptemplate_features
phptemplate_init @file Handles integration of templates written in pure php with the Drupal theme system.
phptemplate_node Prepare the values passed to the theme_node function to be passed into a pluggable template engine.
phptemplate_page Prepare the values passed to the theme_page function to be passed into a pluggable template engine. Uses the arg() function to generate a series of page template files suggestions based on the current path. If none are found, the default page.tpl.php…
phptemplate_regions Declare the available regions implemented by this engine.
phptemplate_templates
_phptemplate_callback Execute a template engine call.
_phptemplate_default Default callback for PHPTemplate.
_phptemplate_default_variables Adds additional helper variables to all templates.
_phptemplate_render