Same name and namespace in other branches
  1. 7.x includes/theme.inc \_theme_process_registry()

Process a single invocation of the theme hook. $type will be one of 'module', 'theme_engine', 'base_theme_engine', 'theme', or 'base_theme' and it tells us some important information.

Because $cache is a reference, the cache will be continually expanded upon; new entries will replace old entries in the array_merge, but we are careful to ensure some data is carried forward, such as the arguments a theme hook needs.

An override flag can be set for preprocess functions. When detected the cached preprocessors for the hook will not be merged with the newly set. This can be useful to themes and theme engines by giving them more control over how and when the preprocess functions are run.

1 call to _theme_process_registry()
_theme_build_registry in includes/theme.inc
Rebuild the hook theme_registry cache.

File

includes/theme.inc, line 274
The theme system, which controls the output of Drupal.

Code

function _theme_process_registry(&$cache, $name, $type, $theme, $path) {
  $result = array();
  $function = $name . '_theme';
  if (function_exists($function)) {
    $result = $function($cache, $type, $theme, $path);
    foreach ($result as $hook => $info) {
      $result[$hook]['type'] = $type;
      $result[$hook]['theme path'] = $path;

      // if function and file are left out, default to standard naming
      // conventions.
      if (!isset($info['template']) && !isset($info['function'])) {
        $result[$hook]['function'] = ($type == 'module' ? 'theme_' : $name . '_') . $hook;
      }

      // Make sure include files is set so we don't generate notices later.
      if (!isset($info['include files'])) {
        $result[$hook]['include files'] = array();
      }

      // If a path is set in the info, use what was set. Otherwise use the
      // default path. This is mostly so system.module can declare theme
      // functions on behalf of core .include files.
      // All files are included to be safe. Conditionally included
      // files can prevent them from getting registered.
      if (isset($info['file']) && !isset($info['path'])) {

        // First, check to see if the fully qualified file exists.
        $filename = './' . $path . '/' . $info['file'];
        if (file_exists($filename)) {
          require_once $filename;
          $result[$hook]['include files'][] = $filename;
        }
        else {
          $filename = './' . $info['file'];
          if (file_exists($filename)) {
            require_once $filename;
            $result[$hook]['include files'][] = $filename;
          }
        }
      }
      elseif (isset($info['file']) && isset($info['path'])) {
        $filename = './' . $info['path'] . '/' . $info['file'];
        if (file_exists($filename)) {
          require_once $filename;
          $result[$hook]['include files'][] = $filename;
        }
      }
      if (isset($info['template']) && !isset($info['path'])) {
        $result[$hook]['template'] = $path . '/' . $info['template'];
      }

      // If 'arguments' have been defined previously, carry them forward.
      // This should happen if a theme overrides a Drupal defined theme
      // function, for example.
      if (!isset($info['arguments']) && isset($cache[$hook])) {
        $result[$hook]['arguments'] = $cache[$hook]['arguments'];
      }

      // Likewise with theme paths. These are used for template naming suggestions.
      // Theme implementations can occur in multiple paths. Suggestions should follow.
      if (!isset($info['theme paths']) && isset($cache[$hook])) {
        $result[$hook]['theme paths'] = $cache[$hook]['theme paths'];
      }

      // Check for sub-directories.
      $result[$hook]['theme paths'][] = isset($info['path']) ? $info['path'] : $path;

      // Check for default _preprocess_ functions. Ensure arrayness.
      if (!isset($info['preprocess functions']) || !is_array($info['preprocess functions'])) {
        $info['preprocess functions'] = array();
        $prefixes = array();
        if ($type == 'module') {

          // Default preprocessor prefix.
          $prefixes[] = 'template';

          // Add all modules so they can intervene with their own preprocessors. This allows them
          // to provide preprocess functions even if they are not the owner of the current hook.
          $prefixes += module_list();
        }
        elseif ($type == 'theme_engine' || $type == 'base_theme_engine') {

          // Theme engines get an extra set that come before the normally named preprocessors.
          $prefixes[] = $name . '_engine';

          // The theme engine also registers on behalf of the theme. The theme or engine name can be used.
          $prefixes[] = $name;
          $prefixes[] = $theme;
        }
        else {

          // This applies when the theme manually registers their own preprocessors.
          $prefixes[] = $name;
        }
        foreach ($prefixes as $prefix) {
          if (function_exists($prefix . '_preprocess')) {
            $info['preprocess functions'][] = $prefix . '_preprocess';
          }
          if (function_exists($prefix . '_preprocess_' . $hook)) {
            $info['preprocess functions'][] = $prefix . '_preprocess_' . $hook;
          }
          if (!empty($info['original hook']) && function_exists($prefix . '_preprocess_' . $info['original hook'])) {
            $info['preprocess functions'][] = $prefix . '_preprocess_' . $info['original hook'];
          }
        }
      }

      // Check for the override flag and prevent the cached preprocess functions from being used.
      // This allows themes or theme engines to remove preprocessors set earlier in the registry build.
      if (!empty($info['override preprocess functions'])) {

        // Flag not needed inside the registry.
        unset($result[$hook]['override preprocess functions']);
      }
      elseif (isset($cache[$hook]['preprocess functions']) && is_array($cache[$hook]['preprocess functions'])) {
        $info['preprocess functions'] = array_merge($cache[$hook]['preprocess functions'], $info['preprocess functions']);
      }
      elseif (isset($info['original hook']) && isset($cache[$info['original hook']]['preprocess functions']) && is_array($cache[$info['original hook']]['preprocess functions'])) {
        $info['preprocess functions'] = array_merge($cache[$info['original hook']]['preprocess functions'], $info['preprocess functions']);
      }
      $result[$hook]['preprocess functions'] = $info['preprocess functions'];
    }

    // Merge the newly created theme hooks into the existing cache.
    $cache = array_merge($cache, $result);
  }

  // Let themes have preprocess functions even if they didn't register a template.
  if ($type == 'theme' || $type == 'base_theme') {
    foreach ($cache as $hook => $info) {

      // Check only if it's a template and not registered by the theme or engine.
      if (!empty($info['template']) && empty($result[$hook])) {
        if (!isset($info['preprocess functions'])) {
          $cache[$hook]['preprocess functions'] = array();
        }
        if (function_exists($name . '_preprocess')) {
          $cache[$hook]['preprocess functions'][] = $name . '_preprocess';
        }
        if (function_exists($name . '_preprocess_' . $hook)) {
          $cache[$hook]['preprocess functions'][] = $name . '_preprocess_' . $hook;
        }

        // Ensure uniqueness.
        $cache[$hook]['preprocess functions'] = array_unique($cache[$hook]['preprocess functions']);
      }
    }
  }
}