Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.1013 diff -u -p -r1.1013 common.inc --- includes/common.inc 11 Oct 2009 06:05:53 -0000 1.1013 +++ includes/common.inc 12 Oct 2009 22:14:03 -0000 @@ -2578,13 +2578,98 @@ function drupal_attributes(array $attrib * an HTML string containing a link to the given path. */ function l($text, $path, array $options = array()) { + global $theme; + static $theme_functions = array('theme_link'); + static $theme_system_ready = FALSE; + static $just_theme_link = TRUE; + + $variables = array( + 'text' => $text, + 'path' => $path, + 'options' => $options, + ); + + // If the theme system is not initialized yet, then theme('link') cannot be + // called and theme_link() needs to be called directly. Also, since l() is + // called very often during a single page request, we statically cache + // preprocess and process functions to directly invoke them in subsequent + // calls. + if (!$theme_system_ready && isset($theme)) { + // Theme hooks can define include files, but those only need to be loaded + // once per request. A single call to theme() is fine, but subsequent + // invocations of l() will avoid this overhead. + $return = theme('link', $variables); + + // Retrieve preprocess, process, and theme functions. + $hooks = theme_get_registry(); + if (isset($hooks) && isset($hooks['link']) && isset($hooks['link']['function'])) { + $theme_functions = array(); + foreach (array('preprocess functions', 'process functions') as $phase) { + if (isset($hooks['link'][$phase])) { + foreach ($hooks['link'][$phase] as $function) { + if (function_exists($function)) { + $theme_functions[] = $function; + } + } + } + } + // A void function is needed to handle the edge case of the theme function + // overridden, but not existing. We emulate what theme() would do, which + // is return NULL. + $theme_functions[] = function_exists($hooks['link']['function']) ? $hooks['link']['function'] : create_function('', ''); + $theme_system_ready = TRUE; + if ((count($theme_functions) > 1) || ($theme_functions[0] != 'theme_link')) { + $just_theme_link = FALSE; + } + } + } + // Before the theme system is ready, or after it is, but if there are no + // preprocess or process functions and the theme function isn't overridden, + // just call theme_link(). + elseif ($just_theme_link) { + $return = theme_link($variables, 'link'); + } + // Once the theme system is ready and we've called theme('link') once, + // for subsequent calls to l(), mimic theme('link') using the cached data. + else { + foreach ($theme_functions as $function) { + $return = $function($variables, 'link'); + } + } + + return $return; +} + +/** + * Format an internal Drupal link. + * + * @param $variables + * An associative array containing: + * - text: The link text to output. + * - path: The URL path component to link to. + * - options: (optional) An array of options to pass to url(). + * See l() for more information. + * + * @return + * A HTML string containing a link to the given path. + * + * @ingroup themeable + * + * @todo If it is impossible to call l() before the theme system is initialized, + * then move this function into theme.inc. + */ +function theme_link($variables) { global $language_url; + $text = $variables['text']; + $path = $variables['path']; + $options = $variables['options']; + // Merge in defaults. $options += array( - 'attributes' => array(), - 'html' => FALSE, - ); + 'attributes' => array(), + 'html' => FALSE, + ); // Append active class. if (($path == $_GET['q'] || ($path == '' && drupal_is_front_page())) && @@ -4857,6 +4942,9 @@ function drupal_common_theme() { 'status_messages' => array( 'arguments' => array('display' => NULL), ), + 'link' => array( + 'arguments' => array('text' => NULL, 'path' => NULL, 'options' => array()), + ), 'links' => array( 'arguments' => array('links' => NULL, 'attributes' => array('class' => array('links')), 'heading' => array()), ), Index: modules/simpletest/tests/common.test =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/common.test,v retrieving revision 1.83 diff -u -p -r1.83 common.test --- modules/simpletest/tests/common.test 11 Oct 2009 02:14:43 -0000 1.83 +++ modules/simpletest/tests/common.test 12 Oct 2009 22:14:04 -0000 @@ -4,7 +4,7 @@ /** * Tests for URL generation functions. */ -class CommonURLUnitTest extends DrupalUnitTestCase { +class CommonURLUnitTest extends DrupalWebTestCase { public static function getInfo() { return array( 'name' => 'URL generation tests',