Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.1013 diff -u -r1.1013 common.inc --- includes/common.inc 11 Oct 2009 06:05:53 -0000 1.1013 +++ includes/common.inc 12 Oct 2009 13:52:13 -0000 @@ -2578,6 +2578,91 @@ * an HTML string containing a link to the given path. */ function l($text, $path, array $options = array()) { + global $theme; + static $theme_function; + static $processor_functions = array(); + + $variables = array( + 'text' => $text, + 'path' => $path, + 'options' => $options, + ); + + // Basically, we want to call theme('link', $variables). But we can't do that + // until the theme system is fully loaded and operational, and even when it + // is, it has too much overhead (l() is called a lot!). So instead, we use + // static variables to cache the theme function to call (yes, we're assuming + // a function, because a template implementation of 'link' would be needlessly + // slow) and its preprocess and process functions. In a sense, we're + // duplicating what theme() does in order to shave a few microseconds. + if (!isset($theme_function)) { + if (isset($theme)) { + // Theme hooks can have include files, but those only need to be loaded + // once per page request. No need to duplicate that part of theme(). + // One more call to theme() per page request is fine. Additional calls + // to l() per page request will avoid this overhead. + $return = theme('link', $variables); + + $hooks = theme_get_registry(); + if (isset($hooks) && isset($hooks['link']) && isset($hooks['link']['function'])) { + $theme_function = $hooks['link']['function']; + foreach (array('preprocess functions', 'process functions') as $phase) { + if (isset($hooks['link'][$phase])) { + $processor_functions = array_merge($processor_functions, $hooks['link'][$phase]); + } + } + } + // Now that everything is loaded, cleanup our data to minimize overhead. + foreach ($processor_functions as $key => $function) { + if (!function_exists($function)) { + unset($processor_functions[$key]); + } + } + if (!function_exists($theme_function)) { + $theme_function = 'theme_link'; + } + + return $return; + } + } + + // Here we've already called theme('link') once for the page request and + // are on a subsequent call to l(). So we emulate what theme() would do + // with respect to preprocess and process functions. + foreach ($processor_functions as $function) { + $function($variables, 'link'); + } + // Now, call the actual function. Chances are, it's not overridden by the + // theme, and if so, save the overhead of a function_exists() and calling + // a variable function. + if (!isset($theme_function) || $theme_function == 'theme_link') { + return theme_link($variables); + } + else { + return $theme_function($variables); + } +} + +/** + * Format an internal Drupal link. + * + * @param $variables + * A keyed array with 'text', 'path', and 'options'. + * @see l() for documentation about these. + * + * @return + * an HTML string containing a link to the given path. + * + * @ingroup themeable + * + * @todo + * If it's never possible for l() to be called without theme.inc loaded, + * then move this function to theme.inc. + */ +function theme_link($variables) { + $text = $variables['text']; + $path = $variables['path']; + $options = $variables['options']; global $language_url; // Merge in defaults. @@ -4857,6 +4942,9 @@ '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 -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 13:52:13 -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',