source: sipes/cord/includes/module.inc @ b354002

stableversion-3.0
Last change on this file since b354002 was b354002, checked in by José Gregorio Puentes <jpuentes@…>, 8 años ago

se agrego el directorio del cord

  • Propiedad mode establecida a 100755
File size: 16.3 KB
Línea 
1<?php
2
3/**
4 * @file
5 * API for loading and interacting with Drupal modules.
6 */
7
8/**
9 * Load all the modules that have been enabled in the system table.
10 */
11function module_load_all() {
12  foreach (module_list(TRUE, FALSE) as $module) {
13    drupal_load('module', $module);
14  }
15}
16
17/**
18 * Call a function repeatedly with each module in turn as an argument.
19 */
20function module_iterate($function, $argument = '') {
21  foreach (module_list() as $name) {
22    $function($name, $argument);
23  }
24}
25
26/**
27 * Collect a list of all loaded modules. During the bootstrap, return only
28 * vital modules. See bootstrap.inc
29 *
30 * @param $refresh
31 *   Whether to force the module list to be regenerated (such as after the
32 *   administrator has changed the system settings).
33 * @param $bootstrap
34 *   Whether to return the reduced set of modules loaded in "bootstrap mode"
35 *   for cached pages. See bootstrap.inc.
36 * @param $sort
37 *   By default, modules are ordered by weight and filename, settings this option
38 *   to TRUE, module list will be ordered by module name.
39 * @param $fixed_list
40 *   (Optional) Override the module list with the given modules. Stays until the
41 *   next call with $refresh = TRUE.
42 * @return
43 *   An associative array whose keys and values are the names of all loaded
44 *   modules.
45 */
46function module_list($refresh = FALSE, $bootstrap = TRUE, $sort = FALSE, $fixed_list = NULL) {
47  static $list, $sorted_list;
48
49  if ($refresh || $fixed_list) {
50    $list = array();
51    $sorted_list = NULL;
52    if ($fixed_list) {
53      foreach ($fixed_list as $name => $module) {
54        drupal_get_filename('module', $name, $module['filename']);
55        $list[$name] = $name;
56      }
57    }
58    else {
59      if ($bootstrap) {
60        $result = db_query("SELECT name, filename, throttle FROM {system} WHERE type = 'module' AND status = 1 AND bootstrap = 1 ORDER BY weight ASC, filename ASC");
61      }
62      else {
63        $result = db_query("SELECT name, filename, throttle FROM {system} WHERE type = 'module' AND status = 1 ORDER BY weight ASC, filename ASC");
64      }
65      while ($module = db_fetch_object($result)) {
66        if (file_exists($module->filename)) {
67          // Determine the current throttle status and see if the module should be
68          // loaded based on server load. We have to directly access the throttle
69          // variables, since throttle.module may not be loaded yet.
70          $throttle = ($module->throttle && variable_get('throttle_level', 0) > 0);
71          if (!$throttle) {
72            drupal_get_filename('module', $module->name, $module->filename);
73            $list[$module->name] = $module->name;
74          }
75        }
76      }
77    }
78  }
79  if ($sort) {
80    if (!isset($sorted_list)) {
81      $sorted_list = $list;
82      ksort($sorted_list);
83    }
84    return $sorted_list;
85  }
86  return $list;
87}
88
89/**
90 * Rebuild the database cache of module files.
91 *
92 * @return
93 *   The array of filesystem objects used to rebuild the cache.
94 */
95function module_rebuild_cache() {
96  // Get current list of modules
97  $files = drupal_system_listing('\.module$', 'modules', 'name', 0);
98
99  // Extract current files from database.
100  system_get_files_database($files, 'module');
101
102  ksort($files);
103
104  // Set defaults for module info
105  $defaults = array(
106    'dependencies' => array(),
107    'dependents' => array(),
108    'description' => '',
109    'version' => NULL,
110    'php' => DRUPAL_MINIMUM_PHP,
111  );
112
113  foreach ($files as $filename => $file) {
114    // Look for the info file.
115    $file->info = drupal_parse_info_file(dirname($file->filename) .'/'. $file->name .'.info');
116
117    // Skip modules that don't provide info.
118    if (empty($file->info)) {
119      unset($files[$filename]);
120      continue;
121    }
122    // Merge in defaults and save.
123    $files[$filename]->info = $file->info + $defaults;
124
125    // Invoke hook_system_info_alter() to give installed modules a chance to
126    // modify the data in the .info files if necessary.
127    drupal_alter('system_info', $files[$filename]->info, $files[$filename]);
128
129    // Log the critical hooks implemented by this module.
130    $bootstrap = 0;
131    foreach (bootstrap_hooks() as $hook) {
132      if (module_hook($file->name, $hook)) {
133        $bootstrap = 1;
134        break;
135      }
136    }
137
138    // Update the contents of the system table:
139    if (isset($file->status) || (isset($file->old_filename) && $file->old_filename != $file->filename)) {
140      db_query("UPDATE {system} SET info = '%s', name = '%s', filename = '%s', bootstrap = %d WHERE filename = '%s'", serialize($files[$filename]->info), $file->name, $file->filename, $bootstrap, $file->old_filename);
141    }
142    else {
143      // This is a new module.
144      $files[$filename]->status = 0;
145      $files[$filename]->throttle = 0;
146      db_query("INSERT INTO {system} (name, info, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', %d, %d, %d)", $file->name, serialize($files[$filename]->info), 'module', $file->filename, 0, 0, $bootstrap);
147    }
148  }
149  $files = _module_build_dependencies($files);
150  return $files;
151}
152
153/**
154 * Find dependencies any level deep and fill in dependents information too.
155 *
156 * If module A depends on B which in turn depends on C then this function will
157 * add C to the list of modules A depends on. This will be repeated until
158 * module A has a list of all modules it depends on. If it depends on itself,
159 * called a circular dependency, that's marked by adding a nonexistent module,
160 * called -circular- to this list of modules. Because this does not exist,
161 * it'll be impossible to switch module A on.
162 *
163 * Also we fill in a dependents array in $file->info. Using the names above,
164 * the dependents array of module B lists A.
165 *
166 * @param $files
167 *   The array of filesystem objects used to rebuild the cache.
168 * @return
169 *   The same array with dependencies and dependents added where applicable.
170 */
171function _module_build_dependencies($files) {
172  do {
173    $new_dependency = FALSE;
174    foreach ($files as $filename => $file) {
175      // We will modify this object (module A, see doxygen for module A, B, C).
176      $file = &$files[$filename];
177      if (isset($file->info['dependencies']) && is_array($file->info['dependencies'])) {
178        foreach ($file->info['dependencies'] as $dependency_name) {
179          // This is a nonexistent module.
180          if ($dependency_name == '-circular-' || !isset($files[$dependency_name])) {
181            continue;
182          }
183          // $dependency_name is module B (again, see doxygen).
184          $files[$dependency_name]->info['dependents'][$filename] = $filename;
185          $dependency = $files[$dependency_name];
186          if (isset($dependency->info['dependencies']) && is_array($dependency->info['dependencies'])) {
187            // Let's find possible C modules.
188            foreach ($dependency->info['dependencies'] as $candidate) {
189              if (array_search($candidate, $file->info['dependencies']) === FALSE) {
190                // Is this a circular dependency?
191                if ($candidate == $filename) {
192                  // As a module name can not contain dashes, this makes
193                  // impossible to switch on the module.
194                  $candidate = '-circular-';
195                  // Do not display the message or add -circular- more than once.
196                  if (array_search($candidate, $file->info['dependencies']) !== FALSE) {
197                    continue;
198                  }
199                  drupal_set_message(t('%module is part of a circular dependency. This is not supported and you will not be able to switch it on.', array('%module' => $file->info['name'])), 'error');
200                }
201                else {
202                  // We added a new dependency to module A. The next loop will
203                  // be able to use this as "B module" thus finding even
204                  // deeper dependencies.
205                  $new_dependency = TRUE;
206                }
207                $file->info['dependencies'][] = $candidate;
208              }
209            }
210          }
211        }
212      }
213      // Don't forget to break the reference.
214      unset($file);
215    }
216  } while ($new_dependency);
217  return $files;
218}
219
220/**
221 * Determine whether a given module exists.
222 *
223 * @param $module
224 *   The name of the module (without the .module extension).
225 * @return
226 *   TRUE if the module is both installed and enabled.
227 */
228function module_exists($module) {
229  $list = module_list();
230  return array_key_exists($module, $list);
231}
232
233/**
234 * Load a module's installation hooks.
235 */
236function module_load_install($module) {
237  // Make sure the installation API is available
238  include_once './includes/install.inc';
239
240  module_load_include('install', $module);
241}
242
243/**
244 * Load a module include file.
245 *
246 * Examples:
247 * @code
248 *   // Load node.admin.inc from the node module.
249 *   module_load_include('inc', 'node', 'node.admin');
250 *   // Load content_types.inc from the node module.
251 *   module_load_include('inc', 'node', 'content_types'); 
252 * @endcode
253 *
254 * Do not use this function to load an install file. Use module_load_install()
255 * instead.
256 *
257 * @param $type
258 *   The include file's type (file extension).
259 * @param $module
260 *   The module to which the include file belongs.
261 * @param $name
262 *   Optionally, specify the base file name (without the $type extension).
263 *   If not set, $module is used.
264 */
265function module_load_include($type, $module, $name = NULL) {
266  if (empty($name)) {
267    $name = $module;
268  }
269
270  $file = './'. drupal_get_path('module', $module) ."/$name.$type";
271
272  if (is_file($file)) {
273    require_once $file;
274  }
275  else {
276    return FALSE;
277  }
278}
279
280/**
281 * Load an include file for each of the modules that have been enabled in
282 * the system table.
283 */
284function module_load_all_includes($type, $name = NULL) {
285  $modules = module_list();
286  foreach ($modules as $module) {
287    module_load_include($type, $module, $name);
288  }
289}
290
291/**
292 * Enable a given list of modules.
293 *
294 * @param $module_list
295 *   An array of module names.
296 */
297function module_enable($module_list) {
298  $invoke_modules = array();
299  foreach ($module_list as $module) {
300    $existing = db_fetch_object(db_query("SELECT status FROM {system} WHERE type = '%s' AND name = '%s'", 'module', $module));
301    if ($existing->status == 0) {
302      module_load_install($module);
303      db_query("UPDATE {system} SET status = %d, throttle = %d WHERE type = '%s' AND name = '%s'", 1, 0, 'module', $module);
304      drupal_load('module', $module);
305      $invoke_modules[] = $module;
306    }
307  }
308
309  if (!empty($invoke_modules)) {
310    // Refresh the module list to include the new enabled module.
311    module_list(TRUE, FALSE);
312    // Force to regenerate the stored list of hook implementations.
313    module_implements('', FALSE, TRUE);
314  }
315
316  foreach ($invoke_modules as $module) {
317    module_invoke($module, 'enable');
318    // Check if node_access table needs rebuilding.
319    // We check for the existence of node_access_needs_rebuild() since
320    // at install time, module_enable() could be called while node.module
321    // is not enabled yet.
322    if (function_exists('node_access_needs_rebuild') && !node_access_needs_rebuild() && module_hook($module, 'node_grants')) {
323      node_access_needs_rebuild(TRUE);
324    }
325  }
326}
327
328/**
329 * Disable a given set of modules.
330 *
331 * @param $module_list
332 *   An array of module names.
333 */
334function module_disable($module_list) {
335  $invoke_modules = array();
336  foreach ($module_list as $module) {
337    if (module_exists($module)) {
338      // Check if node_access table needs rebuilding.
339      if (!node_access_needs_rebuild() && module_hook($module, 'node_grants')) {
340        node_access_needs_rebuild(TRUE);
341      }
342
343      module_load_install($module);
344      module_invoke($module, 'disable');
345      db_query("UPDATE {system} SET status = %d, throttle = %d WHERE type = '%s' AND name = '%s'", 0, 0, 'module', $module);
346      $invoke_modules[] = $module;
347    }
348  }
349
350  if (!empty($invoke_modules)) {
351    // Refresh the module list to exclude the disabled modules.
352    module_list(TRUE, FALSE);
353    // Force to regenerate the stored list of hook implementations.
354    module_implements('', FALSE, TRUE);
355  }
356
357  // If there remains no more node_access module, rebuilding will be
358  // straightforward, we can do it right now.
359  if (node_access_needs_rebuild() && count(module_implements('node_grants')) == 0) {
360    node_access_rebuild();
361  }
362}
363
364/**
365 * @defgroup hooks Hooks
366 * @{
367 * Allow modules to interact with the Drupal core.
368 *
369 * Drupal's module system is based on the concept of "hooks". A hook is a PHP
370 * function that is named foo_bar(), where "foo" is the name of the module
371 * (whose filename is thus foo.module) and "bar" is the name of the hook. Each
372 * hook has a defined set of parameters and a specified result type.
373 *
374 * To extend Drupal, a module need simply implement a hook. When Drupal wishes
375 * to allow intervention from modules, it determines which modules implement a
376 * hook and calls that hook in all enabled modules that implement it.
377 *
378 * The available hooks to implement are explained here in the Hooks section of
379 * the developer documentation. The string "hook" is used as a placeholder for
380 * the module name in the hook definitions. For example, if the module file is
381 * called example.module, then hook_help() as implemented by that module would
382 * be defined as example_help().
383 */
384
385/**
386 * Determine whether a module implements a hook.
387 *
388 * @param $module
389 *   The name of the module (without the .module extension).
390 * @param $hook
391 *   The name of the hook (e.g. "help" or "menu").
392 * @return
393 *   TRUE if the module is both installed and enabled, and the hook is
394 *   implemented in that module.
395 */
396function module_hook($module, $hook) {
397  return function_exists($module .'_'. $hook);
398}
399
400/**
401 * Determine which modules are implementing a hook.
402 *
403 * @param $hook
404 *   The name of the hook (e.g. "help" or "menu").
405 * @param $sort
406 *   By default, modules are ordered by weight and filename, settings this option
407 *   to TRUE, module list will be ordered by module name.
408 * @param $refresh
409 *   For internal use only: Whether to force the stored list of hook
410 *   implementations to be regenerated (such as after enabling a new module,
411 *   before processing hook_enable).
412 * @return
413 *   An array with the names of the modules which are implementing this hook.
414 */
415function module_implements($hook, $sort = FALSE, $refresh = FALSE) {
416  static $implementations;
417
418  if ($refresh) {
419    $implementations = array();
420    return;
421  }
422
423  if (!isset($implementations[$hook])) {
424    $implementations[$hook] = array();
425    $list = module_list(FALSE, TRUE, $sort);
426    foreach ($list as $module) {
427      if (module_hook($module, $hook)) {
428        $implementations[$hook][] = $module;
429      }
430    }
431  }
432
433  // The explicit cast forces a copy to be made. This is needed because
434  // $implementations[$hook] is only a reference to an element of
435  // $implementations and if there are nested foreaches (due to nested node
436  // API calls, for example), they would both manipulate the same array's
437  // references, which causes some modules' hooks not to be called.
438  // See also http://www.zend.com/zend/art/ref-count.php.
439  return (array)$implementations[$hook];
440}
441
442/**
443 * Invoke a hook in a particular module.
444 *
445 * @param $module
446 *   The name of the module (without the .module extension).
447 * @param $hook
448 *   The name of the hook to invoke.
449 * @param ...
450 *   Arguments to pass to the hook implementation.
451 * @return
452 *   The return value of the hook implementation.
453 */
454function module_invoke() {
455  $args = func_get_args();
456  $module = $args[0];
457  $hook = $args[1];
458  unset($args[0], $args[1]);
459  $function = $module .'_'. $hook;
460  if (module_hook($module, $hook)) {
461    return call_user_func_array($function, $args);
462  }
463}
464/**
465 * Invoke a hook in all enabled modules that implement it.
466 *
467 * @param $hook
468 *   The name of the hook to invoke.
469 * @param ...
470 *   Arguments to pass to the hook.
471 * @return
472 *   An array of return values of the hook implementations. If modules return
473 *   arrays from their implementations, those are merged into one array.
474 */
475function module_invoke_all() {
476  $args = func_get_args();
477  $hook = $args[0];
478  unset($args[0]);
479  $return = array();
480  foreach (module_implements($hook) as $module) {
481    $function = $module .'_'. $hook;
482    $result = call_user_func_array($function, $args);
483    if (isset($result) && is_array($result)) {
484      $return = array_merge_recursive($return, $result);
485    }
486    else if (isset($result)) {
487      $return[] = $result;
488    }
489  }
490
491  return $return;
492}
493
494/**
495 * @} End of "defgroup hooks".
496 */
497
498/**
499 * Array of modules required by core.
500 */
501function drupal_required_modules() {
502  return array('block', 'filter', 'node', 'system', 'user');
503}
Nota: Vea TracBrowser para ayuda de uso del navegador del repositorio.