Issue #1808200 by sun: Fixed Unit test performance significantly decreased since system list config conversion.

8.0.x
webchick 2012-11-06 00:51:18 -08:00
parent a41da4e30f
commit 7b88ea7ccf
11 changed files with 88 additions and 44 deletions

View File

@ -938,7 +938,7 @@ function drupal_get_filename($type, $name, $filename = NULL) {
// extension, not just the file we are currently looking for. This // extension, not just the file we are currently looking for. This
// prevents unnecessary scans from being repeated when this function is // prevents unnecessary scans from being repeated when this function is
// called more than once in the same page request. // called more than once in the same page request.
$matches = drupal_system_listing("/^" . DRUPAL_PHP_FUNCTION_PATTERN . "\.$extension$/", $dir, 'name', 0); $matches = drupal_system_listing("/^" . DRUPAL_PHP_FUNCTION_PATTERN . "\.$extension$/", $dir);
foreach ($matches as $matched_name => $file) { foreach ($matches as $matched_name => $file) {
$files[$type][$matched_name] = $file->uri; $files[$type][$matched_name] = $file->uri;
} }

View File

@ -5119,17 +5119,17 @@ function drupal_cron_cleanup() {
* depending on what type of object you are looking for. For instance, if you * depending on what type of object you are looking for. For instance, if you
* are looking for modules and call: * are looking for modules and call:
* @code * @code
* drupal_system_listing("/\.module$/", "modules", 'name', 0); * drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.module$/', 'modules');
* @endcode * @endcode
* the function will search the following directories in this order: * this function will search:
* - /core/modules. * - the core modules directory; i.e., /core/modules
* - /core/profiles/testing/modules (only if a test is being run). * - the testing profile directory; e.g., /profiles/testing/modules
* - /core/profiles/active_profile/modules or /profiles/active_profile/modules. * - your installation profile's directory; e.g., /profiles/standard/modules
* - /modules (standard directory for your contrib/custom modules). * - the site-wide modules directory; i.e., /modules
* - /sites/all/modules (legacy contrib/custom modules directory, see above). * - the all-sites directory; i.e., /sites/all/modules
* - /sites/your_site_dir/modules (for multisite installations). * - the site-specific directory; i.e., /sites/example.com/modules
* and return information about all of the files ending in .module in those * in that order, and return information about all of the files ending in
* directories. * .module in those directories.
* *
* The information is returned in an associative array, which can be keyed on * The information is returned in an associative array, which can be keyed on
* the file name ($key = 'filename'), the file name without the extension ($key * the file name ($key = 'filename'), the file name without the extension ($key
@ -5140,21 +5140,28 @@ function drupal_cron_cleanup() {
* files found. * files found.
* *
* @param string $mask * @param string $mask
* The preg_match() regular expression for the files to find. * The preg_match() regular expression for the files to find. The expression
* must be anchored and use DRUPAL_PHP_FUNCTION_PATTERN for the file name part
* before the extension, since the results could contain matches that do not
* present valid Drupal extensions otherwise.
* @param string $directory * @param string $directory
* The subdirectory name in which the files are found. For example, * The subdirectory name in which the files are found. For example,
* 'core/modules' will search in sub-directories of the /core/modules * 'modules' will search all 'modules' directories and their sub-directories
* directory, sub-directories of /modules/, etc. * as explained above.
* @param string $key * @param string $key
* The key to be used for the associative array returned. Possible values are * (optional) The key to be used for the associative array returned. Possible
* 'uri', for the file's URI; 'filename', for the basename of the file; and * values are:
* 'name' for the name of the file without the extension. If you choose 'name' * - 'uri' for the file's URI.
* or 'filename', only the highest-precedence file will be returned. * - 'filename' for the basename of the file.
* - 'name' for the name of the file without the extension.
* For 'name' and 'filename' only the highest-precedence file is returned.
* Defaults to 'name'.
* @param int $min_depth * @param int $min_depth
* Minimum depth of directories to return files from, relative to each * (optional) Minimum depth of directories to return files from, relative to
* directory searched. For instance, a minimum depth of 2 would find modules * each directory searched. For instance, a directory of 'modules' and a
* inside /core/modules/node/tests, but not modules directly in * minimum depth of 2 would find modules inside /modules/node/tests, but not
* /core/modules/node. * modules directly in /modules/node. Defaults to 1. The default is sufficient
* and suitable for all extension types known by Drupal core.
* *
* @return array * @return array
* An associative array of file objects, keyed on the chosen key. Each element * An associative array of file objects, keyed on the chosen key. Each element
@ -5204,7 +5211,14 @@ function drupal_system_listing($mask, $directory, $key = 'name', $min_depth = 1)
require_once DRUPAL_ROOT . '/core/includes/file.inc'; require_once DRUPAL_ROOT . '/core/includes/file.inc';
} }
foreach ($searchdir as $dir) { foreach ($searchdir as $dir) {
$files_to_add = file_scan_directory($dir, $mask, array('key' => $key, 'min_depth' => $min_depth)); $files_to_add = file_scan_directory($dir, $mask, array(
'key' => $key,
'min_depth' => $min_depth,
// Do not recurse into ./lib directories; they cannot contain extensions.
// We also skip templates, css, and js directories.
// @todo Find a way to skip ./config directories (but not modules/config).
'nomask' => '/^(CVS|lib|templates|css|js)$/',
));
// Duplicate files found in later search directories take precedence over // Duplicate files found in later search directories take precedence over
// earlier ones, so we want them to overwrite keys in our resulting // earlier ones, so we want them to overwrite keys in our resulting
@ -5216,7 +5230,7 @@ function drupal_system_listing($mask, $directory, $key = 'name', $min_depth = 1)
foreach (array_intersect_key($files_to_add, $files) as $file_key => $file) { foreach (array_intersect_key($files_to_add, $files) as $file_key => $file) {
// If it has no info file, then we just behave liberally and accept the // If it has no info file, then we just behave liberally and accept the
// new resource on the list for merging. // new resource on the list for merging.
if (file_exists($info_file = dirname($file->uri) . '/' . $file->name . '.info')) { if (file_exists($info_file = DRUPAL_ROOT . '/' . dirname($file->uri) . '/' . $file->name . '.info')) {
// Get the .info file for the module or theme this file belongs to. // Get the .info file for the module or theme this file belongs to.
$info = drupal_parse_info_file($info_file); $info = drupal_parse_info_file($info_file);

View File

@ -1432,12 +1432,17 @@ function file_download() {
function file_scan_directory($dir, $mask, $options = array(), $depth = 0) { function file_scan_directory($dir, $mask, $options = array(), $depth = 0) {
// Merge in defaults. // Merge in defaults.
$options += array( $options += array(
'nomask' => '/(\.\.?|CVS)$/', 'nomask' => '/^CVS$/',
'callback' => 0, 'callback' => 0,
'recurse' => TRUE, 'recurse' => TRUE,
'key' => 'uri', 'key' => 'uri',
'min_depth' => 0, 'min_depth' => 0,
); );
// Normalize $dir only once.
if ($depth == 0) {
$dir = file_stream_wrapper_uri_normalize($dir);
$dir_has_slash = (substr($dir, -1) === '/');
}
$options['key'] = in_array($options['key'], array('uri', 'filename', 'name')) ? $options['key'] : 'uri'; $options['key'] = in_array($options['key'], array('uri', 'filename', 'name')) ? $options['key'] : 'uri';
$files = array(); $files = array();
@ -1446,10 +1451,15 @@ function file_scan_directory($dir, $mask, $options = array(), $depth = 0) {
if (is_dir($dir)) { if (is_dir($dir)) {
if($handle = @opendir($dir)) { if($handle = @opendir($dir)) {
while (FALSE !== ($filename = readdir($handle))) { while (FALSE !== ($filename = readdir($handle))) {
if (!preg_match($options['nomask'], $filename) && $filename[0] != '.') { // Skip this file if it matches the nomask or starts with a dot.
if ($filename[0] != '.' && !preg_match($options['nomask'], $filename)) {
if ($depth == 0 && $dir_has_slash) {
$uri = "$dir$filename";
}
else {
$uri = "$dir/$filename"; $uri = "$dir/$filename";
$uri = file_stream_wrapper_uri_normalize($uri); }
if (is_dir($uri) && $options['recurse']) { if ($options['recurse'] && is_dir($uri)) {
// Give priority to files in this folder by merging them in after // Give priority to files in this folder by merging them in after
// any subdirectory files. // any subdirectory files.
$files = array_merge(file_scan_directory($uri, $mask, $options, $depth + 1), $files); $files = array_merge(file_scan_directory($uri, $mask, $options, $depth + 1), $files);

View File

@ -384,7 +384,7 @@ function drupal_verify_profile($install_state) {
// Get a list of modules that exist in Drupal's assorted subdirectories. // Get a list of modules that exist in Drupal's assorted subdirectories.
$present_modules = array(); $present_modules = array();
foreach (drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.module$/', 'modules', 'name', 0) as $present_module) { foreach (drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.module$/', 'modules') as $present_module) {
$present_modules[] = $present_module->name; $present_modules[] = $present_module->name;
} }

View File

@ -1006,7 +1006,7 @@ function module_invoke_all($hook) {
* Returns an array of modules required by core. * Returns an array of modules required by core.
*/ */
function drupal_required_modules() { function drupal_required_modules() {
$files = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.info$/', 'modules', 'name', 0); $files = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.info$/', 'modules');
$required = array(); $required = array();
// An installation profile is required and one must always be loaded. // An installation profile is required and one must always be loaded.

View File

@ -385,10 +385,20 @@ function simpletest_test_get_all() {
* Registers namespaces for disabled modules. * Registers namespaces for disabled modules.
*/ */
function simpletest_classloader_register() { function simpletest_classloader_register() {
$all_data = system_rebuild_module_data(); // @see drupal_get_filename()
$all_data += system_rebuild_theme_data(); $types = array(
foreach ($all_data as $name => $data) { 'theme_engine' => array('dir' => 'themes/engines', 'extension' => 'engine'),
drupal_classloader_register($name, dirname($data->filename)); 'module' => array('dir' => 'modules', 'extension' => 'module'),
'theme' => array('dir' => 'themes', 'extension' => 'info'),
'profile' => array('dir' => 'profiles', 'extension' => 'profile'),
);
foreach ($types as $type => $info) {
$matches = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.' . $info['extension'] . '$/', $info['dir']);
foreach ($matches as $name => $file) {
drupal_classloader_register($name, dirname($file->uri));
// While being there, prime drupal_get_filename().
drupal_get_filename($type, $name, $file->uri);
}
} }
} }

View File

@ -22,14 +22,24 @@ class GetFilenameUnitTest extends UnitTestBase {
); );
} }
function setUp() {
parent::setUp();
// Remove the keyvalue service definition, since this test wants to verify
// the filesystem scan fallback of drupal_get_filename().
$this->keyvalue_definition = $this->container->getDefinition('keyvalue');
$this->container->removeDefinition('keyvalue');
}
function tearDown() {
$this->container->setDefinition('keyvalue', $this->keyvalue_definition);
parent::tearDown();
}
/** /**
* Tests that drupal_get_filename() works when the file is not in database. * Tests that drupal_get_filename() works when the file is not in database.
*/ */
function testDrupalGetFilename() { function testDrupalGetFilename() {
// Reset the static cache so we can test the "db is not active" code of
// drupal_get_filename().
drupal_static_reset('drupal_get_filename');
// Retrieving the location of a module. // Retrieving the location of a module.
$this->assertIdentical(drupal_get_filename('module', 'php'), 'core/modules/php/php.module', 'Retrieve module location.'); $this->assertIdentical(drupal_get_filename('module', 'php'), 'core/modules/php/php.module', 'Retrieve module location.');
@ -50,6 +60,6 @@ class GetFilenameUnitTest extends UnitTestBase {
// Since there is already a core/scripts directory, drupal_get_filename() // Since there is already a core/scripts directory, drupal_get_filename()
// will automatically check there for 'script' files, just as it does // will automatically check there for 'script' files, just as it does
// for (e.g.) 'module' files in core/modules. // for (e.g.) 'module' files in core/modules.
$this->assertIdentical(drupal_get_filename('script', 'test'), 'core/scripts/test.script', 'Retrieve test script location.'); $this->assertIdentical(drupal_get_filename('script', 'test'), 'core/scripts/test/test.script');
} }
} }

View File

@ -55,7 +55,7 @@ class SystemListingTest extends WebTestBase {
// Now scan the directories and check that the files take precedence as // Now scan the directories and check that the files take precedence as
// expected. // expected.
$files = drupal_system_listing('/\.module$/', 'modules', 'name', 1); $files = drupal_system_listing('/\.module$/', 'modules');
foreach ($expected_directories as $module => $directories) { foreach ($expected_directories as $module => $directories) {
$expected_directory = array_shift($directories); $expected_directory = array_shift($directories);
$expected_filename = "$expected_directory/$module/$module.module"; $expected_filename = "$expected_directory/$module/$module.module";

View File

@ -2776,10 +2776,10 @@ function system_get_module_info($property) {
*/ */
function _system_rebuild_module_data() { function _system_rebuild_module_data() {
// Find modules // Find modules
$modules = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.module$/', 'modules', 'name', 0); $modules = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.module$/', 'modules');
// Find installation profiles. // Find installation profiles.
$profiles = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.profile$/', 'profiles', 'name', 0); $profiles = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.profile$/', 'profiles');
// Include the installation profile in modules that are loaded. // Include the installation profile in modules that are loaded.
$profile = drupal_get_profile(); $profile = drupal_get_profile();

View File

@ -28,7 +28,7 @@ else {
} }
// Bootstrap to perform initial validation or other operations. // Bootstrap to perform initial validation or other operations.
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE);
if (!module_exists('simpletest')) { if (!module_exists('simpletest')) {
simpletest_script_print_error("The simpletest module must be enabled before this script can run."); simpletest_script_print_error("The simpletest module must be enabled before this script can run.");
exit; exit;