This problem was found while working on a drush issue: http://drupal.org/node/756228

I was trying to do a drush pm-enable/disable on a theme (drush 3). These commands handle both module and theme enabling/disabling. The drush pm-enable/disable calls drush_theme_enable, which directly sets the theme status in the database. Subsequent to that, pm-enable does a drush_get_projects(), which calls drush_get_themes, which calls system_theme_data, which calls system_get_files_database.

system_theme_data deletes the theme information from the database and replaces it with information it got from system_get_files_database.

from system.module, in system_get_files_database (v6.16)
750 function system_get_files_database(&$files, $type) {
751 // Extract current files from database.
752 $result = db_query("SELECT filename, name, type, status, throttle, schema_version FROM {system} WHERE type = '%s'", $type);
753 while ($file = db_fetch_object($result)) {
754 if (isset($files[$file->name]) && is_object($files[$file->name])) {
755 $file->old_filename = $file->filename;
756 foreach ($file as $key => $value) {
757 if (!isset($files[$file->name]) || !isset($files[$file->name]->$key)) {
758 $files[$file->name]->$key = $value;
759 }
760 }
761 }
762 }
763 }

With line 757, it only adds new keys and does nothing with existing keys. The drush pm-enable command calls (indirectly) this function twice. The first time it goes through, the status key is created. Then, the drush command changes the status in the database. When this is invoked the second time, the correct information is read from the database with the select on line 752. However, as the status key exists in the in-memory object, so nothing is done. When you return to the system_theme_data, you then delete the updated information in the database and write out the object using the old, in-memory key that contains old status information.

I don't know what other things end up using this call. So, I am not sure if it should be as currently exists, or if it should create if not there and update if it does exist.

The other 'odd' thing about 757 is the check for !isset($files[$file->name]). On line 754, you check isset($files[$file->name]). By virtue of that, the first condition on 757 will always yield false. As it is or'd with the second condition, it does not impact it, but is unnecessary.

This is my first time to report a core problem, so if I don't have all the information you need, or if what I've presented is unclear, just let me know.

Comments

jonhattan’s picture

Summarizing, this bug can be reproduced this way:

system_theme_data();
db_query("UPDATE {system} SET status = 1 WHERE type = 'theme' AND name = 'garland'"); # garland is a disabled theme for our test
system_theme_data();

Despite the bug in line 757 of system_get_files_database() with the never matching condition, the problem here is the cache used in _system_theme_data(), that is modified outside this function.

This issue is a duplicate of #305653: Themes disabled during update (see comment #99). #305653 has been commited to D7 but not backported to D6. Another duplicate or alternative solution is at #632080: _system_theme_data() should clone the returned objects..

Status: Active » Closed (outdated)

Automatically closed because Drupal 6 is no longer supported. If the issue verifiably applies to later versions, please reopen with details and update the version.