Mercurial > hg > cmmr2012-drupal-site
comparison core/includes/install.inc @ 4:a9cd425dd02b
Update, including to Drupal core 8.6.10
author | Chris Cannam |
---|---|
date | Thu, 28 Feb 2019 13:11:55 +0000 |
parents | c75dbcec494b |
children | 12f9dff5fda9 |
comparison
equal
deleted
inserted
replaced
3:307d7a7fd348 | 4:a9cd425dd02b |
---|---|
9 use Symfony\Component\HttpFoundation\RedirectResponse; | 9 use Symfony\Component\HttpFoundation\RedirectResponse; |
10 use Drupal\Component\Utility\Crypt; | 10 use Drupal\Component\Utility\Crypt; |
11 use Drupal\Component\Utility\OpCodeCache; | 11 use Drupal\Component\Utility\OpCodeCache; |
12 use Drupal\Component\Utility\UrlHelper; | 12 use Drupal\Component\Utility\UrlHelper; |
13 use Drupal\Core\Extension\ExtensionDiscovery; | 13 use Drupal\Core\Extension\ExtensionDiscovery; |
14 use Drupal\Core\Extension\ModuleHandler; | |
14 use Drupal\Core\Site\Settings; | 15 use Drupal\Core\Site\Settings; |
15 | 16 |
16 /** | 17 /** |
17 * Requirement severity -- Informational message only. | 18 * Requirement severity -- Informational message only. |
18 */ | 19 */ |
378 $is_string = $type == T_CONSTANT_ENCAPSED_STRING; | 379 $is_string = $type == T_CONSTANT_ENCAPSED_STRING; |
379 $is_boolean_or_null = $type == T_STRING && in_array(strtoupper($value), ['TRUE', 'FALSE', 'NULL']); | 380 $is_boolean_or_null = $type == T_STRING && in_array(strtoupper($value), ['TRUE', 'FALSE', 'NULL']); |
380 return $is_integer || $is_float || $is_string || $is_boolean_or_null; | 381 return $is_integer || $is_float || $is_string || $is_boolean_or_null; |
381 } | 382 } |
382 | 383 |
383 | |
384 /** | 384 /** |
385 * Helper for drupal_rewrite_settings(). | 385 * Helper for drupal_rewrite_settings(). |
386 * | 386 * |
387 * Checks whether this token represents a valid array index: a number or a | 387 * Checks whether this token represents a valid array index: a number or a |
388 * string. | 388 * string. |
448 $return .= _drupal_rewrite_settings_dump($v, $variable_name . "['" . $k . "']"); | 448 $return .= _drupal_rewrite_settings_dump($v, $variable_name . "['" . $k . "']"); |
449 } | 449 } |
450 } | 450 } |
451 return $return; | 451 return $return; |
452 } | 452 } |
453 | |
454 | 453 |
455 /** | 454 /** |
456 * Helper for drupal_rewrite_settings(). | 455 * Helper for drupal_rewrite_settings(). |
457 * | 456 * |
458 * Dump the value of a value property and adds the comment if it exists. | 457 * Dump the value of a value property and adds the comment if it exists. |
481 * | 480 * |
482 * @see install_settings_form_submit() | 481 * @see install_settings_form_submit() |
483 * @see update_prepare_d8_bootstrap() | 482 * @see update_prepare_d8_bootstrap() |
484 */ | 483 */ |
485 function drupal_install_config_directories() { | 484 function drupal_install_config_directories() { |
486 global $config_directories; | 485 global $config_directories, $install_state; |
487 | 486 |
488 // Add a randomized config directory name to settings.php, unless it was | 487 // If settings.php does not contain a config sync directory name we need to |
489 // manually defined in the existing already. | 488 // configure one. |
490 if (empty($config_directories[CONFIG_SYNC_DIRECTORY])) { | 489 if (empty($config_directories[CONFIG_SYNC_DIRECTORY])) { |
491 $config_directories[CONFIG_SYNC_DIRECTORY] = \Drupal::service('site.path') . '/files/config_' . Crypt::randomBytesBase64(55) . '/sync'; | 490 if (empty($install_state['config_install_path'])) { |
491 // Add a randomized config directory name to settings.php | |
492 $config_directories[CONFIG_SYNC_DIRECTORY] = \Drupal::service('site.path') . '/files/config_' . Crypt::randomBytesBase64(55) . '/sync'; | |
493 } | |
494 else { | |
495 // Install profiles can contain a config sync directory. If they do, | |
496 // 'config_install_path' is a path to the directory. | |
497 $config_directories[CONFIG_SYNC_DIRECTORY] = $install_state['config_install_path']; | |
498 } | |
492 $settings['config_directories'][CONFIG_SYNC_DIRECTORY] = (object) [ | 499 $settings['config_directories'][CONFIG_SYNC_DIRECTORY] = (object) [ |
493 'value' => $config_directories[CONFIG_SYNC_DIRECTORY], | 500 'value' => $config_directories[CONFIG_SYNC_DIRECTORY], |
494 'required' => TRUE, | 501 'required' => TRUE, |
495 ]; | 502 ]; |
496 // Rewrite settings.php, which also sets the value as global variable. | 503 // Rewrite settings.php, which also sets the value as global variable. |
572 // The installation profile is also a module, which needs to be installed | 579 // The installation profile is also a module, which needs to be installed |
573 // after all the other dependencies have been installed. | 580 // after all the other dependencies have been installed. |
574 $present_modules[] = $profile; | 581 $present_modules[] = $profile; |
575 | 582 |
576 // Verify that all of the profile's required modules are present. | 583 // Verify that all of the profile's required modules are present. |
577 $missing_modules = array_diff($info['dependencies'], $present_modules); | 584 $missing_modules = array_diff($info['install'], $present_modules); |
578 | 585 |
579 $requirements = []; | 586 $requirements = []; |
580 | 587 |
581 if ($missing_modules) { | 588 if ($missing_modules) { |
582 $build = [ | 589 $build = [ |
610 * to set the default language. | 617 * to set the default language. |
611 */ | 618 */ |
612 function drupal_install_system($install_state) { | 619 function drupal_install_system($install_state) { |
613 // Remove the service provider of the early installer. | 620 // Remove the service provider of the early installer. |
614 unset($GLOBALS['conf']['container_service_providers']['InstallerServiceProvider']); | 621 unset($GLOBALS['conf']['container_service_providers']['InstallerServiceProvider']); |
622 // Add the normal installer service provider. | |
623 $GLOBALS['conf']['container_service_providers']['InstallerServiceProvider'] = 'Drupal\Core\Installer\NormalInstallerServiceProvider'; | |
615 | 624 |
616 $request = \Drupal::request(); | 625 $request = \Drupal::request(); |
617 // Reboot into a full production environment to continue the installation. | 626 // Reboot into a full production environment to continue the installation. |
618 /** @var \Drupal\Core\Installer\InstallerKernel $kernel */ | 627 /** @var \Drupal\Core\Installer\InstallerKernel $kernel */ |
619 $kernel = \Drupal::service('kernel'); | 628 $kernel = \Drupal::service('kernel'); |
620 $kernel->shutdown(); | 629 $kernel->shutdown(); |
621 // Have installer rebuild from the disk, rather then building from scratch. | 630 // Have installer rebuild from the disk, rather then building from scratch. |
622 $kernel->rebuildContainer(FALSE); | 631 $kernel->rebuildContainer(FALSE); |
623 $kernel->prepareLegacyRequest($request); | 632 $kernel->prepareLegacyRequest($request); |
624 | 633 |
634 // Before having installed the system module and being able to do a module | |
635 // rebuild, prime the \Drupal\Core\Extension\ModuleExtensionList static cache | |
636 // with the module's location. | |
637 // @todo Try to install system as any other module, see | |
638 // https://www.drupal.org/node/2719315. | |
639 \Drupal::service('extension.list.module')->setPathname('system', 'core/modules/system/system.info.yml'); | |
640 | |
625 // Install base system configuration. | 641 // Install base system configuration. |
626 \Drupal::service('config.installer')->installDefaultConfig('core', 'core'); | 642 \Drupal::service('config.installer')->installDefaultConfig('core', 'core'); |
627 | 643 |
628 // Store the installation profile in configuration to populate the | 644 // Store the installation profile in configuration to populate the |
629 // 'install_profile' container parameter. | 645 // 'install_profile' container parameter. |
651 * The file to check for. | 667 * The file to check for. |
652 * @param $mask | 668 * @param $mask |
653 * An optional bitmask created from various FILE_* constants. | 669 * An optional bitmask created from various FILE_* constants. |
654 * @param $type | 670 * @param $type |
655 * The type of file. Can be file (default), dir, or link. | 671 * The type of file. Can be file (default), dir, or link. |
672 * @param bool $autofix | |
673 * (optional) Determines whether to attempt fixing the permissions according | |
674 * to the provided $mask. Defaults to TRUE. | |
656 * | 675 * |
657 * @return | 676 * @return |
658 * TRUE on success or FALSE on failure. A message is set for the latter. | 677 * TRUE on success or FALSE on failure. A message is set for the latter. |
659 */ | 678 */ |
660 function drupal_verify_install_file($file, $mask = NULL, $type = 'file') { | 679 function drupal_verify_install_file($file, $mask = NULL, $type = 'file', $autofix = TRUE) { |
661 $return = TRUE; | 680 $return = TRUE; |
662 // Check for files that shouldn't be there. | 681 // Check for files that shouldn't be there. |
663 if (isset($mask) && ($mask & FILE_NOT_EXIST) && file_exists($file)) { | 682 if (isset($mask) && ($mask & FILE_NOT_EXIST) && file_exists($file)) { |
664 return FALSE; | 683 return FALSE; |
665 } | 684 } |
677 foreach ($masks as $current_mask) { | 696 foreach ($masks as $current_mask) { |
678 if ($mask & $current_mask) { | 697 if ($mask & $current_mask) { |
679 switch ($current_mask) { | 698 switch ($current_mask) { |
680 case FILE_EXIST: | 699 case FILE_EXIST: |
681 if (!file_exists($file)) { | 700 if (!file_exists($file)) { |
682 if ($type == 'dir') { | 701 if ($type == 'dir' && $autofix) { |
683 drupal_install_mkdir($file, $mask); | 702 drupal_install_mkdir($file, $mask); |
684 } | 703 } |
685 if (!file_exists($file)) { | 704 if (!file_exists($file)) { |
686 $return = FALSE; | 705 $return = FALSE; |
687 } | 706 } |
688 } | 707 } |
689 break; | 708 break; |
690 case FILE_READABLE: | 709 case FILE_READABLE: |
691 if (!is_readable($file) && !drupal_install_fix_file($file, $mask)) { | 710 if (!is_readable($file)) { |
692 $return = FALSE; | 711 $return = FALSE; |
693 } | 712 } |
694 break; | 713 break; |
695 case FILE_WRITABLE: | 714 case FILE_WRITABLE: |
696 if (!is_writable($file) && !drupal_install_fix_file($file, $mask)) { | 715 if (!is_writable($file)) { |
697 $return = FALSE; | 716 $return = FALSE; |
698 } | 717 } |
699 break; | 718 break; |
700 case FILE_EXECUTABLE: | 719 case FILE_EXECUTABLE: |
701 if (!is_executable($file) && !drupal_install_fix_file($file, $mask)) { | 720 if (!is_executable($file)) { |
702 $return = FALSE; | 721 $return = FALSE; |
703 } | 722 } |
704 break; | 723 break; |
705 case FILE_NOT_READABLE: | 724 case FILE_NOT_READABLE: |
706 if (is_readable($file) && !drupal_install_fix_file($file, $mask)) { | 725 if (is_readable($file)) { |
707 $return = FALSE; | 726 $return = FALSE; |
708 } | 727 } |
709 break; | 728 break; |
710 case FILE_NOT_WRITABLE: | 729 case FILE_NOT_WRITABLE: |
711 if (is_writable($file) && !drupal_install_fix_file($file, $mask)) { | 730 if (is_writable($file)) { |
712 $return = FALSE; | 731 $return = FALSE; |
713 } | 732 } |
714 break; | 733 break; |
715 case FILE_NOT_EXECUTABLE: | 734 case FILE_NOT_EXECUTABLE: |
716 if (is_executable($file) && !drupal_install_fix_file($file, $mask)) { | 735 if (is_executable($file)) { |
717 $return = FALSE; | 736 $return = FALSE; |
718 } | 737 } |
719 break; | 738 break; |
720 } | 739 } |
721 } | 740 } |
722 } | 741 } |
742 } | |
743 if (!$return && $autofix) { | |
744 return drupal_install_fix_file($file, $mask); | |
723 } | 745 } |
724 return $return; | 746 return $return; |
725 } | 747 } |
726 | 748 |
727 /** | 749 /** |
946 // we don't yet know where all the modules are located. | 968 // we don't yet know where all the modules are located. |
947 // @todo Remove as part of https://www.drupal.org/node/2186491 | 969 // @todo Remove as part of https://www.drupal.org/node/2186491 |
948 $drupal_root = \Drupal::root(); | 970 $drupal_root = \Drupal::root(); |
949 $module_list = (new ExtensionDiscovery($drupal_root))->scan('module'); | 971 $module_list = (new ExtensionDiscovery($drupal_root))->scan('module'); |
950 | 972 |
951 foreach ($info['dependencies'] as $module) { | 973 foreach ($info['install'] as $module) { |
952 // If the module is in the module list we know it exists and we can continue | 974 // If the module is in the module list we know it exists and we can continue |
953 // including and registering it. | 975 // including and registering it. |
954 // @see \Drupal\Core\Extension\ExtensionDiscovery::scanDirectory() | 976 // @see \Drupal\Core\Extension\ExtensionDiscovery::scanDirectory() |
955 if (isset($module_list[$module])) { | 977 if (isset($module_list[$module])) { |
956 $function = $module . '_requirements'; | 978 $function = $module . '_requirements'; |
965 | 987 |
966 if (function_exists($function)) { | 988 if (function_exists($function)) { |
967 $requirements = array_merge($requirements, $function('install')); | 989 $requirements = array_merge($requirements, $function('install')); |
968 } | 990 } |
969 } | 991 } |
992 } | |
993 | |
994 // Add the profile requirements. | |
995 $function = $profile . '_requirements'; | |
996 if (function_exists($function)) { | |
997 $requirements = array_merge($requirements, $function('install')); | |
970 } | 998 } |
971 | 999 |
972 return $requirements; | 1000 return $requirements; |
973 } | 1001 } |
974 | 1002 |
1011 if (isset($requirement['severity']) && $requirement['severity'] == REQUIREMENT_ERROR) { | 1039 if (isset($requirement['severity']) && $requirement['severity'] == REQUIREMENT_ERROR) { |
1012 $message = $requirement['description']; | 1040 $message = $requirement['description']; |
1013 if (isset($requirement['value']) && $requirement['value']) { | 1041 if (isset($requirement['value']) && $requirement['value']) { |
1014 $message = t('@requirements_message (Currently using @item version @version)', ['@requirements_message' => $requirement['description'], '@item' => $requirement['title'], '@version' => $requirement['value']]); | 1042 $message = t('@requirements_message (Currently using @item version @version)', ['@requirements_message' => $requirement['description'], '@item' => $requirement['title'], '@version' => $requirement['value']]); |
1015 } | 1043 } |
1016 drupal_set_message($message, 'error'); | 1044 \Drupal::messenger()->addError($message); |
1017 } | 1045 } |
1018 } | 1046 } |
1019 return FALSE; | 1047 return FALSE; |
1020 } | 1048 } |
1021 return TRUE; | 1049 return TRUE; |
1028 * in a normal Drupal module .info.yml file. For example: | 1056 * in a normal Drupal module .info.yml file. For example: |
1029 * - name: The real name of the installation profile for display purposes. | 1057 * - name: The real name of the installation profile for display purposes. |
1030 * - description: A brief description of the profile. | 1058 * - description: A brief description of the profile. |
1031 * - dependencies: An array of shortnames of other modules that this install | 1059 * - dependencies: An array of shortnames of other modules that this install |
1032 * profile requires. | 1060 * profile requires. |
1061 * - install: An array of shortname of other modules to install that are not | |
1062 * required by this install profile. | |
1033 * | 1063 * |
1034 * Additional, less commonly-used information that can appear in a | 1064 * Additional, less commonly-used information that can appear in a |
1035 * profile.info.yml file but not in a normal Drupal module .info.yml file | 1065 * profile.info.yml file but not in a normal Drupal module .info.yml file |
1036 * includes: | 1066 * includes: |
1037 * | 1067 * |
1045 * throughout the installation process. If omitted, | 1075 * throughout the installation process. If omitted, |
1046 * drupal_install_profile_distribution_name() defaults to 'Drupal'. | 1076 * drupal_install_profile_distribution_name() defaults to 'Drupal'. |
1047 * - install: Optional parameters to override the installer: | 1077 * - install: Optional parameters to override the installer: |
1048 * - theme: The machine name of a theme to use in the installer instead of | 1078 * - theme: The machine name of a theme to use in the installer instead of |
1049 * Drupal's default installer theme. | 1079 * Drupal's default installer theme. |
1080 * - finish_url: A destination to visit after the installation of the | |
1081 * distribution is finished | |
1050 * | 1082 * |
1051 * Note that this function does an expensive file system scan to get info file | 1083 * Note that this function does an expensive file system scan to get info file |
1052 * information for dependencies. If you only need information from the info | 1084 * information for dependencies. If you only need information from the info |
1053 * file itself, use system_get_info(). | 1085 * file itself, use system_get_info(). |
1054 * | 1086 * |
1055 * Example of .info.yml file: | 1087 * Example of .info.yml file: |
1056 * @code | 1088 * @code |
1057 * name: Minimal | 1089 * name: Minimal |
1058 * description: Start fresh, with only a few modules enabled. | 1090 * description: Start fresh, with only a few modules enabled. |
1059 * dependencies: | 1091 * install: |
1060 * - block | 1092 * - block |
1061 * - dblog | 1093 * - dblog |
1062 * @endcode | 1094 * @endcode |
1063 * | 1095 * |
1064 * @param $profile | 1096 * @param $profile |
1074 | 1106 |
1075 if (!isset($cache[$profile][$langcode])) { | 1107 if (!isset($cache[$profile][$langcode])) { |
1076 // Set defaults for module info. | 1108 // Set defaults for module info. |
1077 $defaults = [ | 1109 $defaults = [ |
1078 'dependencies' => [], | 1110 'dependencies' => [], |
1111 'install' => [], | |
1079 'themes' => ['stark'], | 1112 'themes' => ['stark'], |
1080 'description' => '', | 1113 'description' => '', |
1081 'version' => NULL, | 1114 'version' => NULL, |
1082 'hidden' => FALSE, | 1115 'hidden' => FALSE, |
1083 'php' => DRUPAL_MINIMUM_PHP, | 1116 'php' => DRUPAL_MINIMUM_PHP, |
1117 'config_install_path' => NULL, | |
1084 ]; | 1118 ]; |
1085 $profile_file = drupal_get_path('profile', $profile) . "/$profile.info.yml"; | 1119 $profile_path = drupal_get_path('profile', $profile); |
1086 $info = \Drupal::service('info_parser')->parse($profile_file); | 1120 $info = \Drupal::service('info_parser')->parse("$profile_path/$profile.info.yml"); |
1087 $info += $defaults; | 1121 $info += $defaults; |
1122 | |
1123 // Convert dependencies in [project:module] format. | |
1124 $info['dependencies'] = array_map(function ($dependency) { | |
1125 return ModuleHandler::parseDependency($dependency)['name']; | |
1126 }, $info['dependencies']); | |
1127 | |
1128 // Convert install key in [project:module] format. | |
1129 $info['install'] = array_map(function ($dependency) { | |
1130 return ModuleHandler::parseDependency($dependency)['name']; | |
1131 }, $info['install']); | |
1088 | 1132 |
1089 // drupal_required_modules() includes the current profile as a dependency. | 1133 // drupal_required_modules() includes the current profile as a dependency. |
1090 // Remove that dependency, since a module cannot depend on itself. | 1134 // Remove that dependency, since a module cannot depend on itself. |
1091 $required = array_diff(drupal_required_modules(), [$profile]); | 1135 $required = array_diff(drupal_required_modules(), [$profile]); |
1092 | 1136 |
1093 $locale = !empty($langcode) && $langcode != 'en' ? ['locale'] : []; | 1137 $locale = !empty($langcode) && $langcode != 'en' ? ['locale'] : []; |
1094 | 1138 |
1095 $info['dependencies'] = array_unique(array_merge($required, $info['dependencies'], $locale)); | 1139 // Merge dependencies, required modules and locale into install list and |
1096 | 1140 // remove any duplicates. |
1141 $info['install'] = array_unique(array_merge($info['install'], $required, $info['dependencies'], $locale)); | |
1142 | |
1143 // If the profile has a config/sync directory use that to install drupal. | |
1144 if (is_dir($profile_path . '/config/sync')) { | |
1145 $info['config_install_path'] = $profile_path . '/config/sync'; | |
1146 } | |
1097 $cache[$profile][$langcode] = $info; | 1147 $cache[$profile][$langcode] = $info; |
1098 } | 1148 } |
1099 return $cache[$profile][$langcode]; | 1149 return $cache[$profile][$langcode]; |
1100 } | 1150 } |
1101 | 1151 |