Drupal如何更新註冊表?

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
相關文章
相關標籤/搜索