Drupal的註冊表是指registry和registry_file兩個數據表。前一個表保存全部可用的類和接口以及它們所對應的文件,後一個表保存每一個文件的hash碼。
1. 將全部須要更新的文件都彙總的$files數組:css
// 須要更新的文件有兩部分:一是系統includes目錄下全部的.inc文件,二是模塊描述文件中經過files屬性聲明的文件。 $files = array(); $modules = db_query("SELECT * FROM {system} WHERE type = 'module'")->fetchAll(); foreach ($modules as &$module) { $module->info = unserialize($module->info); $dir = dirname($module->filename); $module->dir = $dir; if ($module->status) { foreach ($module->info['files'] as $file) { $files["$dir/$file"] = array('module' => $module->name, 'weight' => $module->weight); } } } foreach (file_scan_directory('includes', '/\.inc$/') as $filename => $file) { $files["$filename"] = array('module' => '', 'weight' => 0); }
2. 更新$files數組的hash屬性:數組
foreach (db_query("SELECT * FROM {registry_file}")->fetchAllAssoc('filename', PDO::FETCH_ASSOC) as $filename => $file) { // Add the hash for those files we have already parsed. if (isset($files[$filename])) { $files[$filename]['hash'] = $file['hash']; } else { // Flush the registry of resources in files that are no longer on disc // or are in files that no installed modules require to be parsed. db_delete('registry') ->condition('filename', $filename) ->execute(); db_delete('registry_file') ->condition('filename', $filename) ->execute(); } }
3. 更新registry和registry_file表:fetch
$parsed_files = array(); // 從新計算每一個文件的Hash碼 foreach ($files as $filename => $file) { if (file_exists($filename)) { $hash = hash_file('sha256', $filename); if (empty($file['hash']) || $file['hash'] != $hash) { $file['hash'] = $hash; $parsed_files[$filename] = $file; } } } foreach ($parsed_files as $filename => $file) { // 搜索文件中的類和接口 if (preg_match_all('/^\s*(?:abstract|final)?\s*(class|interface)\s+([a-zA-Z0-9_]+)/m', file_get_contents($filename), $matches)) { foreach ($matches[2] as $key => $name) { // 將類和接口名稱更新到registry表 db_merge('registry') ->key(array( 'name' => $name, 'type' => $matches[1][$key], )) ->fields(array( 'filename' => $filename, 'module' => $module, 'weight' => $weight, )) ->execute(); } // Delete any resources for this file where the name is not in the list // we just merged in. db_delete('registry') ->condition('filename', $filename) ->condition('name', $matches[2], 'NOT IN') ->execute(); } // 更新registry_file表 db_merge('registry_file') ->key(array('filename' => $filename)) ->fields(array( 'hash' => $file['hash'], )) ->execute(); }
因此,模塊安裝時,讓Drupal自動更新註冊表的關鍵是要在.info文件中註明files屬性。例如,comment模塊的.info文件就是這樣寫的:ui
name = Comment description = Allows users to comment on and discuss published content. package = Core version = VERSION core = 7.x dependencies[] = text files[] = comment.module files[] = comment.test configure = admin/content/comment stylesheets[all][] = comment.css