annotate includes/registry.inc @ 13:134d4b2e75f6

updated quicktabs and google analytics modules
author danieleb <danielebarchiesi@me.com>
date Tue, 29 Oct 2013 13:48:59 +0000
parents ff03f76ab3fe
children
rev   line source
danielebarchiesi@0 1 <?php
danielebarchiesi@0 2
danielebarchiesi@0 3 /**
danielebarchiesi@0 4 * @file
danielebarchiesi@0 5 * This file contains the code registry parser engine.
danielebarchiesi@0 6 */
danielebarchiesi@0 7
danielebarchiesi@0 8 /**
danielebarchiesi@0 9 * @defgroup registry Code registry
danielebarchiesi@0 10 * @{
danielebarchiesi@0 11 * The code registry engine.
danielebarchiesi@0 12 *
danielebarchiesi@0 13 * Drupal maintains an internal registry of all functions or classes in the
danielebarchiesi@0 14 * system, allowing it to lazy-load code files as needed (reducing the amount
danielebarchiesi@0 15 * of code that must be parsed on each request).
danielebarchiesi@0 16 */
danielebarchiesi@0 17
danielebarchiesi@0 18 /**
danielebarchiesi@0 19 * Does the work for registry_update().
danielebarchiesi@0 20 */
danielebarchiesi@0 21 function _registry_update() {
danielebarchiesi@0 22
danielebarchiesi@0 23 // The registry serves as a central autoloader for all classes, including
danielebarchiesi@0 24 // the database query builders. However, the registry rebuild process
danielebarchiesi@0 25 // requires write ability to the database, which means having access to the
danielebarchiesi@0 26 // query builders that require the registry in order to be loaded. That
danielebarchiesi@0 27 // causes a fatal race condition. Therefore we manually include the
danielebarchiesi@0 28 // appropriate query builders for the currently active database before the
danielebarchiesi@0 29 // registry rebuild process runs.
danielebarchiesi@0 30 $connection_info = Database::getConnectionInfo();
danielebarchiesi@0 31 $driver = $connection_info['default']['driver'];
danielebarchiesi@0 32 require_once DRUPAL_ROOT . '/includes/database/query.inc';
danielebarchiesi@0 33 require_once DRUPAL_ROOT . '/includes/database/select.inc';
danielebarchiesi@0 34 require_once DRUPAL_ROOT . '/includes/database/' . $driver . '/query.inc';
danielebarchiesi@0 35
danielebarchiesi@0 36 // Get current list of modules and their files.
danielebarchiesi@0 37 $modules = db_query("SELECT * FROM {system} WHERE type = 'module'")->fetchAll();
danielebarchiesi@0 38 // Get the list of files we are going to parse.
danielebarchiesi@0 39 $files = array();
danielebarchiesi@0 40 foreach ($modules as &$module) {
danielebarchiesi@0 41 $module->info = unserialize($module->info);
danielebarchiesi@0 42 $dir = dirname($module->filename);
danielebarchiesi@0 43
danielebarchiesi@0 44 // Store the module directory for use in hook_registry_files_alter().
danielebarchiesi@0 45 $module->dir = $dir;
danielebarchiesi@0 46
danielebarchiesi@0 47 if ($module->status) {
danielebarchiesi@0 48 // Add files for enabled modules to the registry.
danielebarchiesi@0 49 foreach ($module->info['files'] as $file) {
danielebarchiesi@0 50 $files["$dir/$file"] = array('module' => $module->name, 'weight' => $module->weight);
danielebarchiesi@0 51 }
danielebarchiesi@0 52 }
danielebarchiesi@0 53 }
danielebarchiesi@0 54 foreach (file_scan_directory('includes', '/\.inc$/') as $filename => $file) {
danielebarchiesi@0 55 $files["$filename"] = array('module' => '', 'weight' => 0);
danielebarchiesi@0 56 }
danielebarchiesi@0 57
danielebarchiesi@0 58 $transaction = db_transaction();
danielebarchiesi@0 59 try {
danielebarchiesi@0 60 // Allow modules to manually modify the list of files before the registry
danielebarchiesi@0 61 // parses them. The $modules array provides the .info file information, which
danielebarchiesi@0 62 // includes the list of files registered to each module. Any files in the
danielebarchiesi@0 63 // list can then be added to the list of files that the registry will parse,
danielebarchiesi@0 64 // or modify attributes of a file.
danielebarchiesi@0 65 drupal_alter('registry_files', $files, $modules);
danielebarchiesi@0 66 foreach (registry_get_parsed_files() as $filename => $file) {
danielebarchiesi@0 67 // Add the hash for those files we have already parsed.
danielebarchiesi@0 68 if (isset($files[$filename])) {
danielebarchiesi@0 69 $files[$filename]['hash'] = $file['hash'];
danielebarchiesi@0 70 }
danielebarchiesi@0 71 else {
danielebarchiesi@0 72 // Flush the registry of resources in files that are no longer on disc
danielebarchiesi@0 73 // or are in files that no installed modules require to be parsed.
danielebarchiesi@0 74 db_delete('registry')
danielebarchiesi@0 75 ->condition('filename', $filename)
danielebarchiesi@0 76 ->execute();
danielebarchiesi@0 77 db_delete('registry_file')
danielebarchiesi@0 78 ->condition('filename', $filename)
danielebarchiesi@0 79 ->execute();
danielebarchiesi@0 80 }
danielebarchiesi@0 81 }
danielebarchiesi@0 82 $parsed_files = _registry_parse_files($files);
danielebarchiesi@0 83
danielebarchiesi@0 84 $unchanged_resources = array();
danielebarchiesi@0 85 $lookup_cache = array();
danielebarchiesi@0 86 if ($cache = cache_get('lookup_cache', 'cache_bootstrap')) {
danielebarchiesi@0 87 $lookup_cache = $cache->data;
danielebarchiesi@0 88 }
danielebarchiesi@0 89 foreach ($lookup_cache as $key => $file) {
danielebarchiesi@0 90 // If the file for this cached resource is carried over unchanged from
danielebarchiesi@0 91 // the last registry build, then we can safely re-cache it.
danielebarchiesi@0 92 if ($file && in_array($file, array_keys($files)) && !in_array($file, $parsed_files)) {
danielebarchiesi@0 93 $unchanged_resources[$key] = $file;
danielebarchiesi@0 94 }
danielebarchiesi@0 95 }
danielebarchiesi@0 96 module_implements('', FALSE, TRUE);
danielebarchiesi@0 97 _registry_check_code(REGISTRY_RESET_LOOKUP_CACHE);
danielebarchiesi@0 98 }
danielebarchiesi@0 99 catch (Exception $e) {
danielebarchiesi@0 100 $transaction->rollback();
danielebarchiesi@0 101 watchdog_exception('registry', $e);
danielebarchiesi@0 102 throw $e;
danielebarchiesi@0 103 }
danielebarchiesi@0 104
danielebarchiesi@0 105 // We have some unchanged resources, warm up the cache - no need to pay
danielebarchiesi@0 106 // for looking them up again.
danielebarchiesi@0 107 if (count($unchanged_resources) > 0) {
danielebarchiesi@0 108 cache_set('lookup_cache', $unchanged_resources, 'cache_bootstrap');
danielebarchiesi@0 109 }
danielebarchiesi@0 110 }
danielebarchiesi@0 111
danielebarchiesi@0 112 /**
danielebarchiesi@0 113 * Return the list of files in registry_file
danielebarchiesi@0 114 */
danielebarchiesi@0 115 function registry_get_parsed_files() {
danielebarchiesi@0 116 $files = array();
danielebarchiesi@0 117 // We want the result as a keyed array.
danielebarchiesi@0 118 $files = db_query("SELECT * FROM {registry_file}")->fetchAllAssoc('filename', PDO::FETCH_ASSOC);
danielebarchiesi@0 119 return $files;
danielebarchiesi@0 120 }
danielebarchiesi@0 121
danielebarchiesi@0 122 /**
danielebarchiesi@0 123 * Parse all files that have changed since the registry was last built, and save their function and class listings.
danielebarchiesi@0 124 *
danielebarchiesi@0 125 * @param $files
danielebarchiesi@0 126 * The list of files to check and parse.
danielebarchiesi@0 127 */
danielebarchiesi@0 128 function _registry_parse_files($files) {
danielebarchiesi@0 129 $parsed_files = array();
danielebarchiesi@0 130 foreach ($files as $filename => $file) {
danielebarchiesi@0 131 if (file_exists($filename)) {
danielebarchiesi@0 132 $hash = hash_file('sha256', $filename);
danielebarchiesi@0 133 if (empty($file['hash']) || $file['hash'] != $hash) {
danielebarchiesi@0 134 $file['hash'] = $hash;
danielebarchiesi@0 135 $parsed_files[$filename] = $file;
danielebarchiesi@0 136 }
danielebarchiesi@0 137 }
danielebarchiesi@0 138 }
danielebarchiesi@0 139 foreach ($parsed_files as $filename => $file) {
danielebarchiesi@0 140 _registry_parse_file($filename, file_get_contents($filename), $file['module'], $file['weight']);
danielebarchiesi@0 141 db_merge('registry_file')
danielebarchiesi@0 142 ->key(array('filename' => $filename))
danielebarchiesi@0 143 ->fields(array(
danielebarchiesi@0 144 'hash' => $file['hash'],
danielebarchiesi@0 145 ))
danielebarchiesi@0 146 ->execute();
danielebarchiesi@0 147 }
danielebarchiesi@0 148 return array_keys($parsed_files);
danielebarchiesi@0 149 }
danielebarchiesi@0 150
danielebarchiesi@0 151 /**
danielebarchiesi@0 152 * Parse a file and save its function and class listings.
danielebarchiesi@0 153 *
danielebarchiesi@0 154 * @param $filename
danielebarchiesi@0 155 * Name of the file we are going to parse.
danielebarchiesi@0 156 * @param $contents
danielebarchiesi@0 157 * Contents of the file we are going to parse as a string.
danielebarchiesi@0 158 * @param $module
danielebarchiesi@0 159 * (optional) Name of the module this file belongs to.
danielebarchiesi@0 160 * @param $weight
danielebarchiesi@0 161 * (optional) Weight of the module.
danielebarchiesi@0 162 */
danielebarchiesi@0 163 function _registry_parse_file($filename, $contents, $module = '', $weight = 0) {
danielebarchiesi@0 164 if (preg_match_all('/^\s*(?:abstract|final)?\s*(class|interface)\s+([a-zA-Z0-9_]+)/m', $contents, $matches)) {
danielebarchiesi@0 165 foreach ($matches[2] as $key => $name) {
danielebarchiesi@0 166 db_merge('registry')
danielebarchiesi@0 167 ->key(array(
danielebarchiesi@0 168 'name' => $name,
danielebarchiesi@0 169 'type' => $matches[1][$key],
danielebarchiesi@0 170 ))
danielebarchiesi@0 171 ->fields(array(
danielebarchiesi@0 172 'filename' => $filename,
danielebarchiesi@0 173 'module' => $module,
danielebarchiesi@0 174 'weight' => $weight,
danielebarchiesi@0 175 ))
danielebarchiesi@0 176 ->execute();
danielebarchiesi@0 177 }
danielebarchiesi@0 178 // Delete any resources for this file where the name is not in the list
danielebarchiesi@0 179 // we just merged in.
danielebarchiesi@0 180 db_delete('registry')
danielebarchiesi@0 181 ->condition('filename', $filename)
danielebarchiesi@0 182 ->condition('name', $matches[2], 'NOT IN')
danielebarchiesi@0 183 ->execute();
danielebarchiesi@0 184 }
danielebarchiesi@0 185 }
danielebarchiesi@0 186
danielebarchiesi@0 187 /**
danielebarchiesi@0 188 * @} End of "defgroup registry".
danielebarchiesi@0 189 */