| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 <?php 2 3 define('SCHEMA_UNINSTALLED', -1); 4 define('SCHEMA_INSTALLED', 0); 5 6 define('REQUIREMENT_INFO', -1); 7 define('REQUIREMENT_OK', 0); 8 define('REQUIREMENT_WARNING', 1); 9 define('REQUIREMENT_ERROR', 2); 10 11 define('FILE_EXIST', 1); 12 define('FILE_READABLE', 2); 13 define('FILE_WRITABLE', 4); 14 define('FILE_EXECUTABLE', 8); 15 define('FILE_NOT_EXIST', 16); 16 define('FILE_NOT_READABLE', 32); 17 define('FILE_NOT_WRITABLE', 64); 18 define('FILE_NOT_EXECUTABLE', 128); 19 20 /** 21 * Initialize the update system by loading all installed module's .install files. 22 */ 23 function drupal_load_updates() { 24 foreach (drupal_get_installed_schema_version(NULL, FALSE, TRUE) as $module => $schema_version) { 25 if ($schema_version > -1) { 26 module_load_install($module); 27 } 28 } 29 } 30 31 /** 32 * Returns an array of available schema versions for a module. 33 * 34 * @param $module 35 * A module name. 36 * @return 37 * If the module has updates, an array of available updates sorted by version. 38 * Otherwise, FALSE. 39 */ 40 function drupal_get_schema_versions($module) { 41 $updates = array(); 42 $functions = get_defined_functions(); 43 foreach ($functions['user'] as $function) { 44 if (strpos($function, $module .'_update_') === 0) { 45 $version = substr($function, strlen($module .'_update_')); 46 if (is_numeric($version)) { 47 $updates[] = $version; 48 } 49 } 50 } 51 if (count($updates) == 0) { 52 return FALSE; 53 } 54 sort($updates, SORT_NUMERIC); 55 return $updates; 56 } 57 58 /** 59 * Returns the currently installed schema version for a module. 60 * 61 * @param $module 62 * A module name. 63 * @param $reset 64 * Set to TRUE after modifying the system table. 65 * @param $array 66 * Set to TRUE if you want to get information about all modules in the 67 * system. 68 * @return 69 * The currently installed schema version. 70 */ 71 function drupal_get_installed_schema_version($module, $reset = FALSE, $array = FALSE) { 72 static $versions = array(); 73 74 if ($reset) { 75 $versions = array(); 76 } 77 78 if (!$versions) { 79 $versions = array(); 80 $result = db_query("SELECT name, schema_version FROM {system} WHERE type = '%s'", 'module'); 81 while ($row = db_fetch_object($result)) { 82 $versions[$row->name] = $row->schema_version; 83 } 84 } 85 86 return $array ? $versions : $versions[$module]; 87 } 88 89 /** 90 * Update the installed version information for a module. 91 * 92 * @param $module 93 * A module name. 94 * @param $version 95 * The new schema version. 96 */ 97 function drupal_set_installed_schema_version($module, $version) { 98 db_query("UPDATE {system} SET schema_version = %d WHERE name = '%s'", $version, $module); 99 } 100 101 /** 102 * Loads the profile definition, extracting the profile's defined name. 103 * 104 * @return 105 * The name defined in the profile's _profile_details() hook. 106 */ 107 function drupal_install_profile_name() { 108 global $profile; 109 static $name = NULL; 110 111 if (!isset($name)) { 112 // Load profile details. 113 $function = $profile .'_profile_details'; 114 if (function_exists($function)) { 115 $details = $function(); 116 } 117 $name = isset($details['name']) ? $details['name'] : 'Drupal'; 118 } 119 120 return $name; 121 } 122 123 /** 124 * Auto detect the base_url with PHP predefined variables. 125 * 126 * @param $file 127 * The name of the file calling this function so we can strip it out of 128 * the URI when generating the base_url. 129 * 130 * @return 131 * The auto-detected $base_url that should be configured in settings.php 132 */ 133 function drupal_detect_baseurl($file = 'install.php') { 134 global $profile; 135 $proto = $_SERVER['HTTPS'] ? 'https://' : 'http://'; 136 $host = $_SERVER['SERVER_NAME']; 137 $port = ($_SERVER['SERVER_PORT'] == 80 ? '' : ':'. $_SERVER['SERVER_PORT']); 138 $uri = preg_replace("/\?.*/", '', $_SERVER['REQUEST_URI']); 139 $dir = str_replace("/$file", '', $uri); 140 141 return "$proto$host$port$dir"; 142 } 143 144 /** 145 * Detect all databases supported by Drupal that are compiled into the current 146 * PHP installation. 147 * 148 * @return 149 * An array of database types compiled into PHP. 150 */ 151 function drupal_detect_database_types() { 152 $databases = array(); 153 154 foreach (array('mysql', 'mysqli', 'pgsql') as $type) { 155 if (file_exists('./includes/install.'. $type .'.inc')) { 156 include_once './includes/install.'. $type .'.inc'; 157 $function = $type .'_is_available'; 158 if ($function()) { 159 $databases[$type] = $type; 160 } 161 } 162 } 163 164 return $databases; 165 } 166 167 /** 168 * Read settings.php into a buffer line by line, changing values specified in 169 * $settings array, then over-writing the old settings.php file. 170 * 171 * @param $settings 172 * An array of settings that need to be updated. 173 */ 174 function drupal_rewrite_settings($settings = array(), $prefix = '') { 175 $default_settings = './sites/default/default.settings.php'; 176 $settings_file = './'. conf_path(FALSE, TRUE) .'/'. $prefix .'settings.php'; 177 178 // Build list of setting names and insert the values into the global namespace. 179 $keys = array(); 180 foreach ($settings as $setting => $data) { 181 $GLOBALS[$setting] = $data['value']; 182 $keys[] = $setting; 183 } 184 185 $buffer = NULL; 186 $first = TRUE; 187 if ($fp = fopen($default_settings, 'r')) { 188 // Step line by line through settings.php. 189 while (!feof($fp)) { 190 $line = fgets($fp); 191 if ($first && substr($line, 0, 5) != '<?php') { 192 $buffer = "<?php\n\n"; 193 } 194 $first = FALSE; 195 // Check for constants. 196 if (substr($line, 0, 7) == 'define(') { 197 preg_match('/define\(\s*[\'"]([A-Z_-]+)[\'"]\s*,(.*?)\);/', $line, $variable); 198 if (in_array($variable[1], $keys)) { 199 $setting = $settings[$variable[1]]; 200 $buffer .= str_replace($variable[2], " '". $setting['value'] ."'", $line); 201 unset($settings[$variable[1]]); 202 unset($settings[$variable[2]]); 203 } 204 else { 205 $buffer .= $line; 206 } 207 } 208 // Check for variables. 209 elseif (substr($line, 0, 1) == '$') { 210 preg_match('/\$([^ ]*) /', $line, $variable); 211 if (in_array($variable[1], $keys)) { 212 // Write new value to settings.php in the following format: 213 // $'setting' = 'value'; // 'comment' 214 $setting = $settings[$variable[1]]; 215 $buffer .= '$'. $variable[1] ." = '". $setting['value'] ."';". (!empty($setting['comment']) ? ' // '. $setting['comment'] ."\n" : "\n"); 216 unset($settings[$variable[1]]); 217 } 218 else { 219 $buffer .= $line; 220 } 221 } 222 else { 223 $buffer .= $line; 224 } 225 } 226 fclose($fp); 227 228 // Add required settings that were missing from settings.php. 229 foreach ($settings as $setting => $data) { 230 if ($data['required']) { 231 $buffer .= "\$$setting = '". $data['value'] ."';\n"; 232 } 233 } 234 235 $fp = fopen($settings_file, 'w'); 236 if ($fp && fwrite($fp, $buffer) === FALSE) { 237 drupal_set_message(st('Failed to modify %settings, please verify the file permissions.', array('%settings' => $settings_file)), 'error'); 238 } 239 } 240 else { 241 drupal_set_message(st('Failed to open %settings, please verify the file permissions.', array('%settings' => $default_settings)), 'error'); 242 } 243 } 244 245 /** 246 * Get list of all .install files. 247 * 248 * @param $module_list 249 * An array of modules to search for their .install files. 250 */ 251 function drupal_get_install_files($module_list = array()) { 252 $installs = array(); 253 foreach ($module_list as $module) { 254 $installs = array_merge($installs, drupal_system_listing($module .'.install$', 'modules')); 255 } 256 return $installs; 257 } 258 259 /** 260 * Verify a profile for installation. 261 * 262 * @param profile 263 * Name of profile to verify. 264 * @param locale 265 * Name of locale used (if any). 266 * @return 267 * The list of modules to install. 268 */ 269 function drupal_verify_profile($profile, $locale) { 270 include_once './includes/file.inc'; 271 include_once './includes/common.inc'; 272 273 $profile_file = "./profiles/$profile/$profile.profile"; 274 275 if (!isset($profile) || !file_exists($profile_file)) { 276 install_no_profile_error(); 277 } 278 279 require_once($profile_file); 280 281 // Get a list of modules required by this profile. 282 $function = $profile .'_profile_modules'; 283 $module_list = array_merge(drupal_required_modules(), $function(), ($locale != 'en' && !empty($locale) ? array('locale') : array())); 284 285 // Get a list of modules that exist in Drupal's assorted subdirectories. 286 $present_modules = array(); 287 foreach (drupal_system_listing('\.module$', 'modules', 'name', 0) as $present_module) { 288 $present_modules[] = $present_module->name; 289 } 290 291 // Verify that all of the profile's required modules are present. 292 $missing_modules = array_diff($module_list, $present_modules); 293 if (count($missing_modules)) { 294 foreach ($missing_modules as $module) { 295 drupal_set_message(st('The %module module is required but was not found. Please move it into the <em>modules</em> subdirectory.', array('%module' => $module)), 'error'); 296 } 297 } 298 else { 299 return $module_list; 300 } 301 } 302 303 /** 304 * Calls the install function and updates the system table for a given list of 305 * modules. 306 * 307 * @param module_list 308 * The modules to install. 309 */ 310 function drupal_install_modules($module_list = array()) { 311 $files = module_rebuild_cache(); 312 $module_list = array_flip(array_values($module_list)); 313 do { 314 $moved = FALSE; 315 foreach ($module_list as $module => $weight) { 316 $file = $files[$module]; 317 if (isset($file->info['dependencies']) && is_array($file->info['dependencies'])) { 318 foreach ($file->info['dependencies'] as $dependency) { 319 if (isset($module_list[$dependency]) && $module_list[$module] < $module_list[$dependency] +1) { 320 $module_list[$module] = $module_list[$dependency] +1; 321 $moved = TRUE; 322 } 323 } 324 } 325 } 326 } while ($moved); 327 asort($module_list); 328 $module_list = array_keys($module_list); 329 array_filter($module_list, '_drupal_install_module'); 330 module_enable($module_list); 331 } 332 333 /** 334 * Callback to install an individual profile module. 335 * 336 * Used during installation to install modules one at a time and then 337 * enable them, or to install a number of modules at one time 338 * from admin/build/modules. 339 */ 340 function _drupal_install_module($module) { 341 if (drupal_get_installed_schema_version($module, TRUE) == SCHEMA_UNINSTALLED) { 342 module_load_install($module); 343 module_invoke($module, 'install'); 344 $versions = drupal_get_schema_versions($module); 345 drupal_set_installed_schema_version($module, $versions ? max($versions) : SCHEMA_INSTALLED); 346 return TRUE; 347 } 348 } 349 350 /** 351 * Callback to install the system module. 352 * 353 * Separated from the installation of other modules so core system 354 * functions can be made available while other modules are installed. 355 */ 356 function drupal_install_system() { 357 $system_path = dirname(drupal_get_filename('module', 'system', NULL)); 358 require_once './'. $system_path .'/system.install'; 359 module_invoke('system', 'install'); 360 $system_versions = drupal_get_schema_versions('system'); 361 $system_version = $system_versions ? max($system_versions) : SCHEMA_INSTALLED; 362 db_query("INSERT INTO {system} (filename, name, type, owner, status, throttle, bootstrap, schema_version) VALUES('%s', '%s', '%s', '%s', %d, %d, %d, %d)", $system_path .'/system.module', 'system', 'module', '', 1, 0, 0, $system_version); 363 // Now that we've installed things properly, bootstrap the full Drupal environment 364 drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); 365 module_rebuild_cache(); 366 } 367 368 369 /** 370 * Calls the uninstall function and updates the system table for a given module. 371 * 372 * @param $module 373 * The module to uninstall. 374 */ 375 function drupal_uninstall_module($module) { 376 // First, retrieve all the module's menu paths from db. 377 drupal_load('module', $module); 378 $paths = module_invoke($module, 'menu'); 379 380 // Uninstall the module(s). 381 module_load_install($module); 382 module_invoke($module, 'uninstall'); 383 384 // Now remove the menu links for all paths declared by this module. 385 if (!empty($paths)) { 386 $paths = array_keys($paths); 387 // Clean out the names of load functions. 388 foreach ($paths as $index => $path) { 389 $parts = explode('/', $path, MENU_MAX_PARTS); 390 foreach ($parts as $k => $part) { 391 if (preg_match('/^%[a-z_]*$/', $part)) { 392 $parts[$k] = '%'; 393 } 394 } 395 $paths[$index] = implode('/', $parts); 396 } 397 $placeholders = implode(', ', array_fill(0, count($paths), "'%s'")); 398 399 $result = db_query('SELECT * FROM {menu_links} WHERE router_path IN ('. $placeholders .') AND external = 0 ORDER BY depth DESC', $paths); 400 // Remove all such items. Starting from those with the greatest depth will 401 // minimize the amount of re-parenting done by menu_link_delete(). 402 while ($item = db_fetch_array($result)) { 403 _menu_delete_item($item, TRUE); 404 } 405 } 406 407 drupal_set_installed_schema_version($module, SCHEMA_UNINSTALLED); 408 } 409 410 /** 411 * Verify the state of the specified file. 412 * 413 * @param $file 414 * The file to check for. 415 * @param $mask 416 * An optional bitmask created from various FILE_* constants. 417 * @param $type 418 * The type of file. Can be file (default), dir, or link. 419 * @return 420 * TRUE on success or FALSE on failure. A message is set for the latter. 421 */ 422 function drupal_verify_install_file($file, $mask = NULL, $type = 'file') { 423 $return = TRUE; 424 // Check for files that shouldn't be there. 425 if (isset($mask) && ($mask & FILE_NOT_EXIST) && file_exists($file)) { 426 return FALSE; 427 } 428 // Verify that the file is the type of file it is supposed to be. 429 if (isset($type) && file_exists($file)) { 430 $check = 'is_'. $type; 431 if (!function_exists($check) || !$check($file)) { 432 $return = FALSE; 433 } 434 } 435 436 // Verify file permissions. 437 if (isset($mask)) { 438 $masks = array(FILE_EXIST, FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE, FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE); 439 foreach ($masks as $current_mask) { 440 if ($mask & $current_mask) { 441 switch ($current_mask) { 442 case FILE_EXIST: 443 if (!file_exists($file)) { 444 if ($type == 'dir') { 445 drupal_install_mkdir($file, $mask); 446 } 447 if (!file_exists($file)) { 448 $return = FALSE; 449 } 450 } 451 break; 452 case FILE_READABLE: 453 if (!is_readable($file) && !drupal_install_fix_file($file, $mask)) { 454 $return = FALSE; 455 } 456 break; 457 case FILE_WRITABLE: 458 if (!is_writable($file) && !drupal_install_fix_file($file, $mask)) { 459 $return = FALSE; 460 } 461 break; 462 case FILE_EXECUTABLE: 463 if (!is_executable($file) && !drupal_install_fix_file($file, $mask)) { 464 $return = FALSE; 465 } 466 break; 467 case FILE_NOT_READABLE: 468 if (is_readable($file) && !drupal_install_fix_file($file, $mask)) { 469 $return = FALSE; 470 } 471 break; 472 case FILE_NOT_WRITABLE: 473 if (is_writable($file) && !drupal_install_fix_file($file, $mask)) { 474 $return = FALSE; 475 } 476 break; 477 case FILE_NOT_EXECUTABLE: 478 if (is_executable($file) && !drupal_install_fix_file($file, $mask)) { 479 $return = FALSE; 480 } 481 break; 482 } 483 } 484 } 485 } 486 return $return; 487 } 488 489 /** 490 * Create a directory with specified permissions. 491 * 492 * @param file 493 * The name of the directory to create; 494 * @param mask 495 * The permissions of the directory to create. 496 * @param $message 497 * (optional) Whether to output messages. Defaults to TRUE. 498 * 499 * @return 500 * TRUE/FALSE whether or not the directory was successfully created. 501 */ 502 function drupal_install_mkdir($file, $mask, $message = TRUE) { 503 $mod = 0; 504 $masks = array(FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE, FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE); 505 foreach ($masks as $m) { 506 if ($mask & $m) { 507 switch ($m) { 508 case FILE_READABLE: 509 $mod += 444; 510 break; 511 case FILE_WRITABLE: 512 $mod += 222; 513 break; 514 case FILE_EXECUTABLE: 515 $mod += 111; 516 break; 517 } 518 } 519 } 520 521 if (@mkdir($file, intval("0$mod", 8))) { 522 return TRUE; 523 } 524 else { 525 return FALSE; 526 } 527 } 528 529 /** 530 * Attempt to fix file permissions. 531 * 532 * The general approach here is that, because we do not know the security 533 * setup of the webserver, we apply our permission changes to all three 534 * digits of the file permission (i.e. user, group and all). 535 * 536 * To ensure that the values behave as expected (and numbers don't carry 537 * from one digit to the next) we do the calculation on the octal value 538 * using bitwise operations. This lets us remove, for example, 0222 from 539 * 0700 and get the correct value of 0500. 540 * 541 * @param $file 542 * The name of the file with permissions to fix. 543 * @param $mask 544 * The desired permissions for the file. 545 * @param $message 546 * (optional) Whether to output messages. Defaults to TRUE. 547 * 548 * @return 549 * TRUE/FALSE whether or not we were able to fix the file's permissions. 550 */ 551 function drupal_install_fix_file($file, $mask, $message = TRUE) { 552 $mod = fileperms($file) & 0777; 553 $masks = array(FILE_READABLE, FILE_WRITABLE, FILE_EXECUTABLE, FILE_NOT_READABLE, FILE_NOT_WRITABLE, FILE_NOT_EXECUTABLE); 554 555 // FILE_READABLE, FILE_WRITABLE, and FILE_EXECUTABLE permission strings 556 // can theoretically be 0400, 0200, and 0100 respectively, but to be safe 557 // we set all three access types in case the administrator intends to 558 // change the owner of settings.php after installation. 559 foreach ($masks as $m) { 560 if ($mask & $m) { 561 switch ($m) { 562 case FILE_READABLE: 563 if (!is_readable($file)) { 564 $mod |= 0444; 565 } 566 break; 567 case FILE_WRITABLE: 568 if (!is_writable($file)) { 569 $mod |= 0222; 570 } 571 break; 572 case FILE_EXECUTABLE: 573 if (!is_executable($file)) { 574 $mod |= 0111; 575 } 576 break; 577 case FILE_NOT_READABLE: 578 if (is_readable($file)) { 579 $mod &= ~0444; 580 } 581 break; 582 case FILE_NOT_WRITABLE: 583 if (is_writable($file)) { 584 $mod &= ~0222; 585 } 586 break; 587 case FILE_NOT_EXECUTABLE: 588 if (is_executable($file)) { 589 $mod &= ~0111; 590 } 591 break; 592 } 593 } 594 } 595 596 // chmod() will work if the web server is running as owner of the file. 597 // If PHP safe_mode is enabled the currently executing script must also 598 // have the same owner. 599 if (@chmod($file, $mod)) { 600 return TRUE; 601 } 602 else { 603 return FALSE; 604 } 605 } 606 607 608 /** 609 * Send the user to a different installer page. This issues an on-site HTTP 610 * redirect. Messages (and errors) are erased. 611 * 612 * @param $path 613 * An installer path. 614 */ 615 function install_goto($path) { 616 global $base_url; 617 header('Location: '. $base_url .'/'. $path); 618 header('Cache-Control: no-cache'); // Not a permanent redirect. 619 exit(); 620 } 621 622 /** 623 * Hardcoded function for doing the equivalent of t() during 624 * the install process, when database, theme, and localization 625 * system is possibly not yet available. 626 */ 627 function st($string, $args = array()) { 628 static $locale_strings = NULL; 629 global $profile, $install_locale; 630 631 if (!isset($locale_strings)) { 632 $locale_strings = array(); 633 $filename = './profiles/'. $profile .'/translations/'. $install_locale .'.po'; 634 if (file_exists($filename)) { 635 require_once './includes/locale.inc'; 636 $file = (object) array('filepath' => $filename); 637 _locale_import_read_po('mem-store', $file); 638 $locale_strings = _locale_import_one_string('mem-report'); 639 } 640 } 641 642 require_once './includes/theme.inc'; 643 // Transform arguments before inserting them 644 foreach ($args as $key => $value) { 645 switch ($key[0]) { 646 // Escaped only 647 case '@': 648 $args[$key] = check_plain($value); 649 break; 650 // Escaped and placeholder 651 case '%': 652 default: 653 $args[$key] = '<em>'. check_plain($value) .'</em>'; 654 break; 655 // Pass-through 656 case '!': 657 } 658 } 659 return strtr((!empty($locale_strings[$string]) ? $locale_strings[$string] : $string), $args); 660 } 661 662 /** 663 * Check a profile's requirements. 664 * 665 * @param profile 666 * Name of profile to check. 667 */ 668 function drupal_check_profile($profile) { 669 include_once './includes/file.inc'; 670 671 $profile_file = "./profiles/$profile/$profile.profile"; 672 673 if (!isset($profile) || !file_exists($profile_file)) { 674 install_no_profile_error(); 675 } 676 677 require_once($profile_file); 678 679 // Get a list of modules required by this profile. 680 $function = $profile .'_profile_modules'; 681 $module_list = array_unique(array_merge(drupal_required_modules(), $function())); 682 683 // Get a list of all .install files. 684 $installs = drupal_get_install_files($module_list); 685 686 // Collect requirement testing results 687 $requirements = array(); 688 foreach ($installs as $install) { 689 require_once $install->filename; 690 if (module_hook($install->name, 'requirements')) { 691 $requirements = array_merge($requirements, module_invoke($install->name, 'requirements', 'install')); 692 } 693 } 694 return $requirements; 695 } 696 697 /** 698 * Extract highest severity from requirements array. 699 */ 700 function drupal_requirements_severity(&$requirements) { 701 $severity = REQUIREMENT_OK; 702 foreach ($requirements as $requirement) { 703 if (isset($requirement['severity'])) { 704 $severity = max($severity, $requirement['severity']); 705 } 706 } 707 return $severity; 708 } 709 710 /** 711 * Check a module's requirements. 712 */ 713 function drupal_check_module($module) { 714 // Include install file 715 $install = drupal_get_install_files(array($module)); 716 if (isset($install[$module])) { 717 require_once $install[$module]->filename; 718 719 // Check requirements 720 $requirements = module_invoke($module, 'requirements', 'install'); 721 if (is_array($requirements) && drupal_requirements_severity($requirements) == REQUIREMENT_ERROR) { 722 // Print any error messages 723 foreach ($requirements as $requirement) { 724 if (isset($requirement['severity']) && $requirement['severity'] == REQUIREMENT_ERROR) { 725 $message = $requirement['description']; 726 if (isset($requirement['value']) && $requirement['value']) { 727 $message .= ' ('. t('Currently using !item !version', array('!item' => $requirement['title'], '!version' => $requirement['value'])) .')'; 728 } 729 drupal_set_message($message, 'error'); 730 } 731 } 732 return FALSE; 733 } 734 } 735 return TRUE; 736 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Jul 9 18:01:44 2012 | Cross-referenced by PHPXref 0.7 |