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

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