phptemplate.engine 12 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
<?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)) {
12
   include_once "./$file";
13 14 15 16 17 18 19
  }
}

function phptemplate_templates($directory = 'themes') {
  return system_listing('^page\.tpl\.php$', $directory, 'filename');
}

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
/**
 * 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')
  );
}

36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
/**
 * 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 $file
 *   A suggested template file to use. If the file is not found, the default $hook.tpl.php will be used.
 * @return
 *  The HTML generated by the template system.
 */
54
function _phptemplate_callback($hook, $variables = array(), $file = NULL) {
55
  global $theme_engine;
56 57 58 59

  $variables = array_merge($variables, _phptemplate_default_variables($hook, $variables));

  // Allow specified variables to be overridden
60 61 62
  $variables_function = '_'. $theme_engine .'_variables';
  if (function_exists($variables_function)) {
    $variables = array_merge($variables, call_user_func($variables_function, $hook, $variables));
63 64
  }

65
  if (isset($variables['template_file'])) {
66 67 68
    $file = $variables['template_file'];
  }

69 70 71 72
  $hook_function = '_'. $theme_engine .'_'. $hook;
  $default_function = '_'. $theme_engine .'_default';
  if (function_exists($hook_function)) {
    return call_user_func($hook_function, $variables, $file);
73
  }
74 75
  elseif (function_exists($default_function)) {
    return call_user_func($default_function, $hook, $variables, $file);
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
  }

}

/**
 * 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) {
91
  global $theme, $sidebar_indicator;
92
  static $count = array();
93

94
  $count[$hook] = isset($count[$hook]) && is_int($count[$hook]) ? $count[$hook] : 1;
95 96 97 98
  $variables['zebra'] = ($count[$hook] % 2) ? 'odd' : 'even';
  $variables['id'] = $count[$hook]++;

  if ($hook == 'block') {
99
    $count['block_counter'][$sidebar_indicator] = isset($count['block_counter'][$sidebar_indicator]) && is_int($count['block_counter'][$sidebar_indicator]) ? $count['block_counter'][$sidebar_indicator] : 1;
100 101 102
    $variables['block_zebra'] = ($count['block_counter'][$sidebar_indicator] % 2) ? 'odd' : 'even';
    $variables['block_id'] = $count['block_counter'][$sidebar_indicator]++;
  }
103 104 105 106 107 108 109 110
  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'))) {
111
        isset($variables[$region]) ? $variables[$region] .= theme('blocks', $region) : $variables[$region] = theme('blocks', $region);
112 113 114
      }
    }
  }
115 116
  // Tell all templates where they are located.
  $variables['directory'] = path_to_theme();
117
  $variables['is_front'] = drupal_is_front_page();
118 119 120 121

  return $variables;
}

122 123 124 125
/**
 * @return
 *  Array of template features
 */
126 127
function phptemplate_features() {
  return array(
128
    'toggle_logo',
129 130 131 132 133 134 135 136
    'toggle_comment_user_picture',
    'toggle_favicon',
    'toggle_mission',
    'toggle_name',
    'toggle_node_user_picture',
    'toggle_search',
    'toggle_slogan'
  );
137 138 139 140 141 142 143 144
}

/**
 * Prepare the values passed to the theme_page function to be passed
 * into a pluggable template engine.
 */
function phptemplate_page($content) {

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

150 151 152 153 154
  /* 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" />');
  }

155 156 157
  /**
  * Populate sidebars.
  */
158
  $layout = 'none';
159 160
  global $sidebar_indicator;
  /**
161
   * Sidebar_indicator tells the block counting code to count sidebars separately.
162 163
   */
  $sidebar_indicator = 'left';
164 165 166
  $sidebar_left = theme('blocks', 'left');
  if ($sidebar_left != '') {
    $layout = 'left';
167 168 169
  }

  $sidebar_indicator = 'right';
170 171 172
  $sidebar_right = theme('blocks', 'right');
  if ($sidebar_right != '') {
    $layout = ($layout == 'left') ? 'both' : 'right';
173
  }
174
  $sidebar_indicator = NULL;
175

176 177 178 179 180 181 182 183 184 185 186
  // 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', '');
    }
  }

187
  $variables = array(
188
    'base_path'           => base_path(),
189 190 191
    'breadcrumb'          => theme('breadcrumb', drupal_get_breadcrumb()),
    'closure'             => theme('closure'),
    'content'             => '<!-- begin content -->' . $content . '<!-- end content -->',
192
    'footer_message'      => filter_xss_admin(variable_get('site_footer', FALSE)) . "\n" . theme('blocks', 'footer'),
193
    'head'                => drupal_get_html_head(),
194
    'head_title'          => implode(' | ', $head_title),
195
    'help'                => theme('help'),
196
    'language'            => $GLOBALS['locale'],
197
    'layout'              => $layout,
198
    'logo'                => theme_get_setting('logo'),
199
    'messages'            => theme('status_messages'),
200
    'mission'             => isset($mission) ? $mission : '',
201
    'primary_links'       => menu_primary_links(),
202
    'search_box'          => (theme_get_setting('toggle_search') ? search_box() : ''),
203
    'secondary_links'     => menu_secondary_links(),
204 205
    'sidebar_left'        => $sidebar_left,
    'sidebar_right'       => $sidebar_right,
206 207
    'site_name'           => (theme_get_setting('toggle_name') ? variable_get('site_name', 'Drupal') : ''),
    'site_slogan'         => (theme_get_setting('toggle_slogan') ? variable_get('site_slogan', '') : ''),
208 209 210
    'styles'              => theme_get_styles(),
    'tabs'                => theme('menu_local_tasks'),
    'title'               => drupal_get_title()
211
  );
212 213

  if ((arg(0) == 'node') && is_numeric(arg(1))) {
214
    $variables['node'] = node_load(arg(1));
215 216 217 218 219
  }

  return _phptemplate_callback('page', $variables);
}

220
/*
221 222 223
 * Prepare the values passed to the theme_node function to be passed
 * into a pluggable template engine.
 */
224
function phptemplate_node($node, $teaser = 0, $page = 0) {
225 226 227 228 229 230 231 232
  if (module_exist('taxonomy')) {
    $taxonomy = taxonomy_link('taxonomy terms', $node);
  }
  else {
    $taxonomy = array();
  }

  $variables = array(
233
    'content'        => ($teaser && $node->teaser) ? $node->teaser : $node->body,
234 235
    'date'           => format_date($node->created),
    'links'          => $node->links ? theme('links', $node->links) : '',
236
    'name'           => theme('username', $node),
237 238 239 240
    'node'           => $node,  // we pass the actual node to allow more customization
    'node_url'       => url('node/'. $node->nid),
    'page'           => $page,
    'taxonomy'       => $taxonomy,
241
    'teaser'         => $teaser,
242 243 244
    'terms'          => theme('links', $taxonomy),
    'title'          => check_plain($node->title)
  );
245

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

249 250
  // Display info only on certain node types.
  if (theme_get_setting('toggle_node_info_' . $node->type)) {
251
    $variables['submitted'] =  t('Submitted by %a on %b.', array('%a' => theme('username', $node), '%b' => format_date($node->created)));
252
    $variables['picture'] = theme_get_setting('toggle_node_user_picture') ? theme('user_picture', $node) : '';
253
  }
254 255 256
  else {
    $variables['picture'] = '';
  }
257 258 259 260 261 262 263 264 265 266

  return _phptemplate_callback('node', $variables, '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(
267
    'author'    => theme('username', $comment),
268 269
    'comment'   => $comment,
    'content'   => $comment->comment,
270
    'date'      => format_date($comment->timestamp),
271
    'links'     => isset($links) ? theme('links', $links) : '',
272 273 274
    'new'       => $comment->new ? t('new') : '',
    'picture'   => theme_get_setting('toggle_comment_user_picture') ? theme('user_picture', $comment) : '',
    'submitted' => t('Submitted by %a on %b.',
275
                      array('%a' => theme('username', $comment),
Steven Wittens's avatar
Steven Wittens committed
276
                            '%b' => format_date($comment->timestamp))),
277
    'title'     => l($comment->subject, $_GET['q'], NULL, NULL, "comment-$comment->cid")
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
  ));
}

/**
 * Prepare the values passed to the theme_block function to be passed
 * into a pluggable template engine.
 */
function phptemplate_block($block) {
  return _phptemplate_callback('block', array('block' => $block));
}

/**
 * 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,
296 297
    'region'  =>   $region,
    'title'   =>   $title
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
  ));
}

/**
 * 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 $file
 *   A suggested template file to use.
 */
316 317 318 319 320
function _phptemplate_default($hook, $variables, $file = NULL, $extension = '.tpl.php') {
  global $theme_engine;

  if (!empty($file) && file_exists(path_to_theme() ."/$file$extension")) {
    $file = path_to_theme() ."/$file$extension";
321 322
  }
  else {
323 324
    if (file_exists(path_to_theme() ."/$hook$extension")) {
      $file = path_to_theme() ."/$hook$extension";
325 326 327
    }
    else {
      if (in_array($hook, array('node', 'block', 'box', 'comment'))) {
328
        $file = "themes/engines/$theme_engine/$hook$extension";
329 330 331
      }
      else {
        $variables['hook'] = $hook;
332 333
        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' => theme('placeholder', $hook))));
        $file = "themes/engines/$theme_engine/default$extension";
334 335 336 337
      }
    }
  }

338
  if (isset($file)) {
339
    return call_user_func('_'. $theme_engine .'_render', $file, $variables);
340
  }
341
}
342

343 344 345 346 347 348 349
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
350 351 352
}

?>