Drupal的system_list()函数解析

system_list()函数的目的是根据传入的资源类型,返回一个数组列表:

function system_list($type) { ... ... }

参数$type支持下面三种类型:

  • bootstrap:返回启动模块列表
  • module_enabled :返回模块列表
  • theme:返回主题列表

三种类型里面bootstrap处理方式有点不同,module_enabled和theme是相同的。

先看看bootstrap是如此处理的。这里的bootstrap指的是系统表system里面标识为bootstrap的模块,是系统的启动模块,在Drupal启动过程中需要先被载入。首先检查是否有缓存:

if ($cached = cache_get('bootstrap_modules', 'cache_bootstrap')) {
  $bootstrap_list = $cached->data;
}

若没有缓存,则直接从系统表system中查询:

$bootstrap_list = db_query("SELECT name, filename FROM {system} WHERE status = 1 AND bootstrap = 1 AND type = 'module' ORDER BY weight ASC, name ASC")->fetchAllAssoc('name');
cache_set('bootstrap_modules', $bootstrap_list, 'cache_bootstrap');

然后透过drupal_get_filename()更新模块主文件路径,目的是用system表的filename字段更新drupal_get_filename()函数中的静态变量:

foreach ($bootstrap_list as $module) {
  drupal_get_filename('module', $module->name, $module->filename);
}

最后,更新system_list()的静态变量$lists,返回列表:

$lists['bootstrap'] = array_keys($bootstrap_list);
... ...
return $list[$type];

注意这里boostrap类型返回的只是启动模块的名称数组,没有其它额外的信息。

下面看看module_enabled和theme是如何处理的。首先还是查看缓存:

if ($cached = cache_get('system_list', 'cache_bootstrap')) {
  $lists = $cached->data;
}

若缓存不存在,则直接读取系统表system:

$lists = array(
  'module_enabled' => array(),
  'theme' => array(),
  'filepaths' => array(),
);

$result = db_query("SELECT * FROM {system} WHERE type = 'theme' OR (type = 'module' AND status = 1) ORDER BY weight ASC, name ASC");
foreach ($result as $record) {
  $record->info = unserialize($record->info); // info字段就是资源的info文件
  
  // Build a list of all enabled modules.
  if ($record->type == 'module') {
    $lists['module_enabled'][$record->name] = $record;
  }
  
  // Build a list of themes.
  if ($record->type == 'theme') {
    $lists['theme'][$record->name] = $record;
  }
  
  // Build a list of filenames so drupal_get_filename can use it.
  if ($record->status) {
    $lists['filepaths'][] = array('type' => $record->type, 'name' => $record->name, 'filepath' => $record->filename);
  }
}

接下来处理主题的继承关系。关于主题的继承关系可以参看《Drupal如何解析主题继承关系?》。

foreach ($lists['theme'] as $key => $theme) {
  if (!empty($theme->info['base theme'])) {
    // Make a list of the theme's base themes.
    require_once DRUPAL_ROOT . '/includes/theme.inc';
    $lists['theme'][$key]->base_themes = drupal_find_base_themes($lists['theme'], $key);
    // Don't proceed if there was a problem with the root base theme.
    if (!current($lists['theme'][$key]->base_themes)) {
      continue;
    }
    
    // Determine the root base theme.
    $base_key = key($lists['theme'][$key]->base_themes);
    // Add to the list of sub-themes for each of the theme's base themes.
    foreach (array_keys($lists['theme'][$key]->base_themes) as $base_theme) {
      $lists['theme'][$base_theme]->sub_themes[$key] = $lists['theme'][$key]->info['name'];
    }
    
    // Add the base theme's theme engine info.
    $lists['theme'][$key]->info['engine'] = isset($lists['theme'][$base_key]->info['engine']) ? $lists['theme'][$base_key]->info['engine'] : 'theme';
  }
  else {
    // A plain theme is its own engine.
    $base_key = $key;
    if (!isset($lists['theme'][$key]->info['engine'])) {
      $lists['theme'][$key]->info['engine'] = 'theme';
    }
  }
  // Set the theme engine prefix.
  $lists['theme'][$key]->prefix = ($lists['theme'][$key]->info['engine'] == 'theme') ? $base_key : $lists['theme'][$key]->info['engine'];
}

最后更新drupal_get_filename()的资源主文件路径,返回列表:

foreach ($lists['filepaths'] as $item) {
  drupal_get_filename($item['type'], $item['name'], $item['filepath']);
}

return $lists[$type];

从代码来看,system_list()也是可以调用filepaths类型的,结果也是数组:

array(
    array('type' => '...', 'name' => '...', 'filepath' => '...'),
    array('type' => '...', 'name' => '...', 'filepath' => '...'),
)
原文地址:https://www.cnblogs.com/eastson/p/3371787.html