2005-12-08 08:40:10 +00:00
< ? php
2014-04-24 13:06:35 +00:00
/**
2012-08-31 15:56:36 +00:00
* @ file
* API functions for installing modules and themes .
*/
2014-03-31 09:58:12 +00:00
use Drupal\Component\Utility\OpCodeCache ;
Issue #3035312 by kim.pepper, andypost, martin107, yogeshmpawar, naveenvalecha, pguillard, Berdir, dww, claudiu.cristea, jibran, Mile23: Move file_scan_directory() to file_system service
2019-07-24 10:29:08 +00:00
use Drupal\Component\Utility\Unicode ;
2014-04-16 10:07:11 +00:00
use Drupal\Component\Utility\UrlHelper ;
2021-01-18 21:43:55 +00:00
use Drupal\Core\Database\Database ;
Issue #3035312 by kim.pepper, andypost, martin107, yogeshmpawar, naveenvalecha, pguillard, Berdir, dww, claudiu.cristea, jibran, Mile23: Move file_scan_directory() to file_system service
2019-07-24 10:29:08 +00:00
use Drupal\Core\Extension\Dependency ;
2014-02-28 11:51:38 +00:00
use Drupal\Core\Extension\ExtensionDiscovery ;
2019-10-03 23:50:26 +00:00
use Drupal\Core\Installer\InstallerKernel ;
2014-04-25 19:13:44 +00:00
use Drupal\Core\Site\Settings ;
Issue #3035312 by kim.pepper, andypost, martin107, yogeshmpawar, naveenvalecha, pguillard, Berdir, dww, claudiu.cristea, jibran, Mile23: Move file_scan_directory() to file_system service
2019-07-24 10:29:08 +00:00
use Symfony\Component\HttpFoundation\RedirectResponse ;
2011-12-27 21:17:19 +00:00
2008-05-26 17:12:55 +00:00
/**
* Requirement severity -- Informational message only .
*/
2011-11-29 09:56:53 +00:00
const REQUIREMENT_INFO = - 1 ;
2008-05-26 17:12:55 +00:00
/**
* Requirement severity -- Requirement successfully met .
*/
2011-11-29 09:56:53 +00:00
const REQUIREMENT_OK = 0 ;
2008-05-26 17:12:55 +00:00
/**
* Requirement severity -- Warning condition ; proceed but flag warning .
*/
2011-11-29 09:56:53 +00:00
const REQUIREMENT_WARNING = 1 ;
2008-05-26 17:12:55 +00:00
/**
* Requirement severity -- Error condition ; abort installation .
*/
2011-11-29 09:56:53 +00:00
const REQUIREMENT_ERROR = 2 ;
2005-12-08 08:40:10 +00:00
2008-05-26 17:12:55 +00:00
/**
* File permission check -- File exists .
*/
2011-11-29 09:56:53 +00:00
const FILE_EXIST = 1 ;
2008-05-26 17:12:55 +00:00
/**
* File permission check -- File is readable .
*/
2011-11-29 09:56:53 +00:00
const FILE_READABLE = 2 ;
2008-05-26 17:12:55 +00:00
/**
* File permission check -- File is writable .
*/
2011-11-29 09:56:53 +00:00
const FILE_WRITABLE = 4 ;
2008-05-26 17:12:55 +00:00
/**
* File permission check -- File is executable .
*/
2011-11-29 09:56:53 +00:00
const FILE_EXECUTABLE = 8 ;
2008-05-26 17:12:55 +00:00
/**
* File permission check -- File does not exist .
*/
2011-11-29 09:56:53 +00:00
const FILE_NOT_EXIST = 16 ;
2008-05-26 17:12:55 +00:00
/**
* File permission check -- File is not readable .
*/
2011-11-29 09:56:53 +00:00
const FILE_NOT_READABLE = 32 ;
2008-05-26 17:12:55 +00:00
/**
* File permission check -- File is not writable .
*/
2011-11-29 09:56:53 +00:00
const FILE_NOT_WRITABLE = 64 ;
2008-05-26 17:12:55 +00:00
/**
* File permission check -- File is not executable .
*/
2011-11-29 09:56:53 +00:00
const FILE_NOT_EXECUTABLE = 128 ;
2005-12-08 08:40:10 +00:00
2006-07-31 19:24:16 +00:00
/**
2012-08-31 15:56:36 +00:00
* Loads . install files for installed modules to initialize the update system .
2006-07-31 19:24:16 +00:00
*/
function drupal_load_updates () {
2020-03-10 21:32:33 +00:00
/** @var \Drupal\Core\Extension\ModuleExtensionList $extension_list_module */
$extension_list_module = \Drupal :: service ( 'extension.list.module' );
Issue #2124069 by voleger, andypost, martin107, damiankloip, cburschka, dawehner, kim.pepper, daffie, pcambra, ParisLiakos, Xano, longwave, MerryHamster, vacho, kostyashupenko, catch, alexpott, amateescu, Mile23, claudiu.cristea, larowlan, almaudoh, Berdir, zviryatko: Convert schema.inc to the update.update_hook_registry service (UpdateHookRegistry)
2021-06-23 15:55:26 +00:00
foreach ( \Drupal :: service ( 'update.update_hook_registry' ) -> getAllInstalledVersions () as $module => $schema_version ) {
2020-03-10 21:32:33 +00:00
if ( $extension_list_module -> exists ( $module ) && ! $extension_list_module -> checkIncompatibility ( $module )) {
if ( $schema_version > - 1 ) {
module_load_install ( $module );
}
2007-12-17 12:23:01 +00:00
}
2005-12-08 08:40:10 +00:00
}
}
2006-07-13 13:14:25 +00:00
/**
2012-10-05 16:11:15 +00:00
* Loads the installation profile , extracting its defined distribution name .
2006-07-13 13:14:25 +00:00
*
* @ return
2013-03-06 22:51:39 +00:00
* The distribution name defined in the profile ' s . info . yml file . Defaults to
2012-10-05 16:11:15 +00:00
* " Drupal " if none is explicitly provided by the installation profile .
2009-12-07 06:19:20 +00:00
*
* @ see install_profile_info ()
2006-07-13 13:14:25 +00:00
*/
2009-12-07 06:19:20 +00:00
function drupal_install_profile_distribution_name () {
2010-06-21 02:27:47 +00:00
// During installation, the profile information is stored in the global
// installation state (it might not be saved anywhere yet).
2017-03-04 01:20:24 +00:00
$info = [];
2019-10-03 23:50:26 +00:00
if ( InstallerKernel :: installationAttempted ()) {
2010-06-21 02:27:47 +00:00
global $install_state ;
2014-03-14 10:49:27 +00:00
if ( isset ( $install_state [ 'profile_info' ])) {
$info = $install_state [ 'profile_info' ];
}
2010-06-21 02:27:47 +00:00
}
// At all other times, we load the profile via standard methods.
else {
2019-07-22 08:31:06 +00:00
$profile = \Drupal :: installProfile ();
2019-10-07 13:46:33 +00:00
$info = \Drupal :: service ( 'extension.list.profile' ) -> getExtensionInfo ( $profile );
2010-06-21 02:27:47 +00:00
}
2021-11-15 02:19:43 +00:00
return $info [ 'distribution' ][ 'name' ] ? ? 'Drupal' ;
2006-07-13 13:14:25 +00:00
}
2015-10-05 05:30:28 +00:00
/**
* Loads the installation profile , extracting its defined version .
*
2017-08-22 07:16:08 +00:00
* @ return string
* Distribution version defined in the profile ' s . info . yml file .
* Defaults to \Drupal :: VERSION if no version is explicitly provided by the
* installation profile .
2015-10-05 05:30:28 +00:00
*
* @ see install_profile_info ()
*/
function drupal_install_profile_distribution_version () {
// During installation, the profile information is stored in the global
// installation state (it might not be saved anywhere yet).
2019-10-03 23:50:26 +00:00
if ( InstallerKernel :: installationAttempted ()) {
2015-10-05 05:30:28 +00:00
global $install_state ;
2021-11-15 02:19:43 +00:00
return $install_state [ 'profile_info' ][ 'version' ] ? ? \Drupal :: VERSION ;
2015-10-05 05:30:28 +00:00
}
// At all other times, we load the profile via standard methods.
else {
2019-07-22 08:31:06 +00:00
$profile = \Drupal :: installProfile ();
2019-10-07 13:46:33 +00:00
$info = \Drupal :: service ( 'extension.list.profile' ) -> getExtensionInfo ( $profile );
2015-10-05 05:30:28 +00:00
return $info [ 'version' ];
}
}
2006-07-13 13:14:25 +00:00
/**
2012-08-31 15:56:36 +00:00
* Detects all supported databases that are compiled into PHP .
2006-07-13 13:14:25 +00:00
*
* @ return
2016-06-02 14:20:55 +00:00
* An array of database types compiled into PHP .
2006-07-13 13:14:25 +00:00
*/
function drupal_detect_database_types () {
2010-11-29 02:55:57 +00:00
$databases = drupal_get_database_types ();
foreach ( $databases as $driver => $installer ) {
$databases [ $driver ] = $installer -> name ();
}
return $databases ;
}
/**
2014-02-28 11:51:38 +00:00
* Returns all supported database driver installer objects .
2010-11-29 02:55:57 +00:00
*
2014-02-28 11:51:38 +00:00
* @ return \Drupal\Core\Database\Install\Tasks []
* An array of available database driver installer objects .
2010-11-29 02:55:57 +00:00
*/
function drupal_get_database_types () {
2017-03-04 01:20:24 +00:00
$databases = [];
$drivers = [];
2006-07-13 13:14:25 +00:00
2014-02-28 11:51:38 +00:00
// The internal database driver name is any valid PHP identifier.
2020-01-01 18:03:21 +00:00
$mask = ExtensionDiscovery :: PHP_FUNCTION_PATTERN ;
2020-04-07 20:00:31 +00:00
// Find drivers in the Drupal\Core and Drupal\Driver namespaces.
Issue #3035312 by kim.pepper, andypost, martin107, yogeshmpawar, naveenvalecha, pguillard, Berdir, dww, claudiu.cristea, jibran, Mile23: Move file_scan_directory() to file_system service
2019-07-24 10:29:08 +00:00
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
$file_system = \Drupal :: service ( 'file_system' );
$files = $file_system -> scanDirectory ( DRUPAL_ROOT . '/core/lib/Drupal/Core/Database/Driver' , $mask , [ 'recurse' => FALSE ]);
2013-02-15 19:08:38 +00:00
if ( is_dir ( DRUPAL_ROOT . '/drivers/lib/Drupal/Driver/Database' )) {
Issue #3035312 by kim.pepper, andypost, martin107, yogeshmpawar, naveenvalecha, pguillard, Berdir, dww, claudiu.cristea, jibran, Mile23: Move file_scan_directory() to file_system service
2019-07-24 10:29:08 +00:00
$files += $file_system -> scanDirectory ( DRUPAL_ROOT . '/drivers/lib/Drupal/Driver/Database/' , $mask , [ 'recurse' => FALSE ]);
2013-02-15 19:08:38 +00:00
}
foreach ( $files as $file ) {
2011-12-28 01:06:42 +00:00
if ( file_exists ( $file -> uri . '/Install/Tasks.php' )) {
2020-04-07 20:00:31 +00:00
// The namespace doesn't need to be added here, because
// db_installer_object() will find it.
$drivers [ $file -> filename ] = NULL ;
}
}
// Find drivers in Drupal module namespaces.
/** @var \Composer\Autoload\ClassLoader $class_loader */
$class_loader = \Drupal :: service ( 'class_loader' );
// We cannot use the file cache because it does not always exist.
$extension_discovery = new ExtensionDiscovery ( DRUPAL_ROOT , FALSE , []);
$modules = $extension_discovery -> scan ( 'module' );
foreach ( $modules as $module ) {
$module_driver_path = DRUPAL_ROOT . '/' . $module -> getPath () . '/src/Driver/Database' ;
if ( is_dir ( $module_driver_path )) {
$driver_files = $file_system -> scanDirectory ( $module_driver_path , $mask , [ 'recurse' => FALSE ]);
foreach ( $driver_files as $driver_file ) {
$tasks_file = $module_driver_path . '/' . $driver_file -> filename . '/Install/Tasks.php' ;
if ( file_exists ( $tasks_file )) {
$namespace = 'Drupal\\' . $module -> getName () . '\\Driver\\Database\\' . $driver_file -> filename ;
// The namespace needs to be added for db_installer_object() to find
// it.
$drivers [ $driver_file -> filename ] = $namespace ;
// The directory needs to be added to the autoloader, because this is
// early in the installation process: the module hasn't been enabled
// yet and the database connection info array (including its 'autoload'
// key) hasn't been created yet.
$class_loader -> addPsr4 ( $namespace . '\\' , $module -> getPath () . '/src/Driver/Database/' . $driver_file -> filename );
}
}
2010-07-31 12:29:31 +00:00
}
2008-08-22 12:43:53 +00:00
}
2020-04-07 20:00:31 +00:00
foreach ( $drivers as $driver => $namespace ) {
$installer = db_installer_object ( $driver , $namespace );
2008-08-21 19:36:39 +00:00
if ( $installer -> installable ()) {
2010-11-29 02:55:57 +00:00
$databases [ $driver ] = $installer ;
2008-08-21 19:36:39 +00:00
}
}
2008-08-22 12:43:53 +00:00
2008-12-30 16:43:20 +00:00
// Usability: unconditionally put the MySQL driver on top.
2008-08-28 08:40:33 +00:00
if ( isset ( $databases [ 'mysql' ])) {
$mysql_database = $databases [ 'mysql' ];
unset ( $databases [ 'mysql' ]);
2017-03-04 01:20:24 +00:00
$databases = [ 'mysql' => $mysql_database ] + $databases ;
2008-08-28 08:40:33 +00:00
}
2008-11-11 16:49:38 +00:00
2008-08-21 19:36:39 +00:00
return $databases ;
}
2006-07-13 13:14:25 +00:00
/**
2012-08-31 15:56:36 +00:00
* Replaces values in settings . php with values in the submitted array .
2006-07-13 13:14:25 +00:00
*
2013-03-10 02:58:05 +00:00
* This function replaces values in place if possible , even for
* multidimensional arrays . This way the old settings do not linger ,
* overridden and also the doxygen on a value remains where it should be .
*
2006-07-13 13:14:25 +00:00
* @ param $settings
2013-03-10 02:58:05 +00:00
* An array of settings that need to be updated . Multidimensional arrays
* are dumped up to a stdClass object . The object can have value , required
* and comment properties .
* @ code
2019-06-24 13:04:44 +00:00
* $settings [ 'settings' ][ 'config_sync_directory' ] = ( object ) array (
* 'value' => 'config_hash/sync' ,
* 'required' => TRUE ,
2013-03-10 02:58:05 +00:00
* );
* @ endcode
* gets dumped as :
* @ code
2019-06-24 13:04:44 +00:00
* $settings [ 'config_sync_directory' ] = 'config_hash/sync'
2013-03-10 02:58:05 +00:00
* @ endcode
2006-07-13 13:14:25 +00:00
*/
2017-03-04 01:20:24 +00:00
function drupal_rewrite_settings ( $settings = [], $settings_file = NULL ) {
2013-03-10 02:58:05 +00:00
if ( ! isset ( $settings_file )) {
2020-03-05 11:22:39 +00:00
$settings_file = \Drupal :: getContainer () -> getParameter ( 'site.path' ) . '/settings.php' ;
2013-03-10 02:58:05 +00:00
}
2006-07-13 13:14:25 +00:00
// Build list of setting names and insert the values into the global namespace.
2017-03-04 01:20:24 +00:00
$variable_names = [];
$settings_settings = [];
2006-07-13 13:14:25 +00:00
foreach ( $settings as $setting => $data ) {
2014-02-20 12:29:03 +00:00
if ( $setting != 'settings' ) {
_drupal_rewrite_settings_global ( $GLOBALS [ $setting ], $data );
}
else {
_drupal_rewrite_settings_global ( $settings_settings , $data );
}
2016-05-05 11:07:19 +00:00
$variable_names [ '$' . $setting ] = $setting ;
2006-07-13 13:14:25 +00:00
}
Issue #2304461 by dawehner, neclimdul, naveenvalecha, jibran, tim.plunkett, phenaproxima, Xano, hussainweb, sun, hitesh-jain, amateescu, alexpott, daffie, Mile23, Wim Leers, larowlan: KernelTestBaseTNG™
2015-08-18 00:25:27 +00:00
$contents = file_get_contents ( $settings_file );
2012-06-14 02:48:09 +00:00
if ( $contents !== FALSE ) {
2014-03-24 17:07:44 +00:00
// Initialize the contents for the settings.php file if it is empty.
if ( trim ( $contents ) === '' ) {
$contents = " <?php \n " ;
}
2012-06-14 02:48:09 +00:00
// Step through each token in settings.php and replace any variables that
// are in the passed-in array.
2013-03-10 02:58:05 +00:00
$buffer = '' ;
$state = 'default' ;
2012-06-14 02:48:09 +00:00
foreach ( token_get_all ( $contents ) as $token ) {
2013-03-10 02:58:05 +00:00
if ( is_array ( $token )) {
2021-11-15 02:35:55 +00:00
[ $type , $value ] = $token ;
2006-07-13 13:14:25 +00:00
}
2012-06-14 02:48:09 +00:00
else {
2013-03-10 02:58:05 +00:00
$type = - 1 ;
$value = $token ;
}
// Do not operate on whitespace.
2017-03-04 01:20:24 +00:00
if ( ! in_array ( $type , [ T_WHITESPACE , T_COMMENT , T_DOC_COMMENT ])) {
2013-03-10 02:58:05 +00:00
switch ( $state ) {
case 'default' :
if ( $type === T_VARIABLE && isset ( $variable_names [ $value ])) {
// This will be necessary to unset the dumped variable.
$parent = & $settings ;
// This is the current index in parent.
$index = $variable_names [ $value ];
// This will be necessary for descending into the array.
$current = & $parent [ $index ];
$state = 'candidate_left' ;
}
break ;
2020-06-02 08:46:52 +00:00
2013-03-10 02:58:05 +00:00
case 'candidate_left' :
if ( $value == '[' ) {
$state = 'array_index' ;
}
if ( $value == '=' ) {
$state = 'candidate_right' ;
}
break ;
2020-06-02 08:46:52 +00:00
2013-03-10 02:58:05 +00:00
case 'array_index' :
if ( _drupal_rewrite_settings_is_array_index ( $type , $value )) {
$index = trim ( $value , '\'"' );
$state = 'right_bracket' ;
}
else {
// $a[foo()] or $a[$bar] or something like that.
throw new Exception ( 'invalid array index' );
}
break ;
2020-06-02 08:46:52 +00:00
2013-03-10 02:58:05 +00:00
case 'right_bracket' :
if ( $value == ']' ) {
if ( isset ( $current [ $index ])) {
// If the new settings has this index, descend into it.
$parent = & $current ;
$current = & $parent [ $index ];
$state = 'candidate_left' ;
}
else {
// Otherwise, jump back to the default state.
$state = 'wait_for_semicolon' ;
}
}
else {
// $a[1 + 2].
throw new Exception ( '] expected' );
}
break ;
2020-06-02 08:46:52 +00:00
2013-03-10 02:58:05 +00:00
case 'candidate_right' :
if ( _drupal_rewrite_settings_is_simple ( $type , $value )) {
$value = _drupal_rewrite_settings_dump_one ( $current );
// Unsetting $current would not affect $settings at all.
unset ( $parent [ $index ]);
// Skip the semicolon because _drupal_rewrite_settings_dump_one() added one.
$state = 'semicolon_skip' ;
}
else {
$state = 'wait_for_semicolon' ;
}
break ;
2020-06-02 08:46:52 +00:00
2013-03-10 02:58:05 +00:00
case 'wait_for_semicolon' :
if ( $value == ';' ) {
$state = 'default' ;
}
break ;
2020-06-02 08:46:52 +00:00
2013-03-10 02:58:05 +00:00
case 'semicolon_skip' :
if ( $value == ';' ) {
$value = '' ;
$state = 'default' ;
}
else {
// If the expression was $a = 1 + 2; then we replaced 1 and
// the + is unexpected.
2014-04-03 08:57:54 +00:00
throw new Exception ( 'Unexpected token after replacing value.' );
2013-03-10 02:58:05 +00:00
}
break ;
2006-07-13 13:14:25 +00:00
}
}
2013-03-10 02:58:05 +00:00
$buffer .= $value ;
2006-07-13 13:14:25 +00:00
}
2013-03-10 02:58:05 +00:00
foreach ( $settings as $name => $setting ) {
$buffer .= _drupal_rewrite_settings_dump ( $setting , '$' . $name );
2006-07-13 13:14:25 +00:00
}
2012-06-14 02:48:09 +00:00
// Write the new settings file.
Issue #2304461 by dawehner, neclimdul, naveenvalecha, jibran, tim.plunkett, phenaproxima, Xano, hussainweb, sun, hitesh-jain, amateescu, alexpott, daffie, Mile23, Wim Leers, larowlan: KernelTestBaseTNG™
2015-08-18 00:25:27 +00:00
if ( file_put_contents ( $settings_file , $buffer ) === FALSE ) {
Issue #2055851 by andypost, jungle, dawehner, Mac_Weber, sja112, borisson_, fietserwin, init90, Gábor Hojtsy, xjm, effulgentsia, tim.plunkett: Remove translation of exception messages
2020-05-19 00:21:21 +00:00
throw new Exception ( " Failed to modify ' $settings_file '. Verify the file permissions. " );
2006-07-13 13:14:25 +00:00
}
2014-02-20 12:29:03 +00:00
else {
// In case any $settings variables were written, import them into the
// Settings singleton.
if ( ! empty ( $settings_settings )) {
2014-03-24 08:51:28 +00:00
$old_settings = Settings :: getAll ();
2014-02-20 12:29:03 +00:00
new Settings ( $settings_settings + $old_settings );
}
2014-03-31 09:58:12 +00:00
// The existing settings.php file might have been included already. In
// case an opcode cache is enabled, the rewritten contents of the file
// will not be reflected in this process. Ensure to invalidate the file
// in case an opcode cache is enabled.
OpCodeCache :: invalidate ( DRUPAL_ROOT . '/' . $settings_file );
2014-02-20 12:29:03 +00:00
}
2006-07-13 13:14:25 +00:00
}
else {
Issue #2055851 by andypost, jungle, dawehner, Mac_Weber, sja112, borisson_, fietserwin, init90, Gábor Hojtsy, xjm, effulgentsia, tim.plunkett: Remove translation of exception messages
2020-05-19 00:21:21 +00:00
throw new Exception ( " Failed to open ' $settings_file '. Verify the file permissions. " );
2006-07-13 13:14:25 +00:00
}
}
2013-03-10 02:58:05 +00:00
/**
* Helper for drupal_rewrite_settings () .
*
* Checks whether this token represents a scalar or NULL .
*
* @ param int $type
2016-05-08 22:42:30 +00:00
* The token type .
2013-03-10 02:58:05 +00:00
* @ param string $value
* The value of the token .
*
* @ return bool
* TRUE if this token represents a scalar or NULL .
2016-05-08 22:42:30 +00:00
*
* @ see token_name ()
2013-03-10 02:58:05 +00:00
*/
function _drupal_rewrite_settings_is_simple ( $type , $value ) {
$is_integer = $type == T_LNUMBER ;
$is_float = $type == T_DNUMBER ;
$is_string = $type == T_CONSTANT_ENCAPSED_STRING ;
2017-03-04 01:20:24 +00:00
$is_boolean_or_null = $type == T_STRING && in_array ( strtoupper ( $value ), [ 'TRUE' , 'FALSE' , 'NULL' ]);
2013-03-10 02:58:05 +00:00
return $is_integer || $is_float || $is_string || $is_boolean_or_null ;
}
/**
* Helper for drupal_rewrite_settings () .
*
* Checks whether this token represents a valid array index : a number or a
2014-09-18 14:21:39 +00:00
* string .
2013-03-10 02:58:05 +00:00
*
* @ param int $type
2016-05-08 22:42:30 +00:00
* The token type .
2013-03-10 02:58:05 +00:00
*
* @ return bool
* TRUE if this token represents a number or a string .
2016-05-08 22:42:30 +00:00
*
* @ see token_name ()
2013-03-10 02:58:05 +00:00
*/
function _drupal_rewrite_settings_is_array_index ( $type ) {
$is_integer = $type == T_LNUMBER ;
$is_float = $type == T_DNUMBER ;
$is_string = $type == T_CONSTANT_ENCAPSED_STRING ;
return $is_integer || $is_float || $is_string ;
}
/**
* Helper for drupal_rewrite_settings () .
*
* Makes the new settings global .
*
2013-10-15 16:48:37 +00:00
* @ param array | null $ref
2013-03-10 02:58:05 +00:00
* A reference to a nested index in $GLOBALS .
* @ param array | object $variable
* The nested value of the setting being copied .
*/
function _drupal_rewrite_settings_global ( & $ref , $variable ) {
if ( is_object ( $variable )) {
$ref = $variable -> value ;
}
else {
foreach ( $variable as $k => $v ) {
_drupal_rewrite_settings_global ( $ref [ $k ], $v );
}
}
}
/**
* Helper for drupal_rewrite_settings () .
*
* Dump the relevant value properties .
*
* @ param array | object $variable
* The container for variable values .
* @ param string $variable_name
* Name of variable .
2020-05-20 22:11:54 +00:00
*
2013-03-10 02:58:05 +00:00
* @ return string
* A string containing valid PHP code of the variable suitable for placing
* into settings . php .
*/
function _drupal_rewrite_settings_dump ( $variable , $variable_name ) {
$return = '' ;
if ( is_object ( $variable )) {
if ( ! empty ( $variable -> required )) {
$return .= _drupal_rewrite_settings_dump_one ( $variable , " $variable_name = " , " \n " );
}
}
else {
foreach ( $variable as $k => $v ) {
$return .= _drupal_rewrite_settings_dump ( $v , $variable_name . " [' " . $k . " '] " );
}
}
return $return ;
}
/**
* Helper for drupal_rewrite_settings () .
*
* Dump the value of a value property and adds the comment if it exists .
*
2013-10-04 13:24:54 +00:00
* @ param object $variable
2013-03-10 02:58:05 +00:00
* A stdClass object with at least a value property .
* @ param string $prefix
* A string to prepend to the variable ' s value .
* @ param string $suffix
* A string to append to the variable ' s value .
2020-05-20 22:11:54 +00:00
*
2013-03-10 02:58:05 +00:00
* @ return string
* A string containing valid PHP code of the variable suitable for placing
* into settings . php .
*/
function _drupal_rewrite_settings_dump_one ( \stdClass $variable , $prefix = '' , $suffix = '' ) {
$return = $prefix . var_export ( $variable -> value , TRUE ) . ';' ;
if ( ! empty ( $variable -> comment )) {
$return .= ' // ' . $variable -> comment ;
}
$return .= $suffix ;
return $return ;
}
2006-07-13 13:14:25 +00:00
/**
2012-10-05 16:11:15 +00:00
* Verifies that all dependencies are met for a given installation profile .
2006-07-13 13:14:25 +00:00
*
2009-07-28 12:13:47 +00:00
* @ param $install_state
* An array of information about the current installation state .
2012-08-31 15:56:36 +00:00
*
2006-08-03 01:02:51 +00:00
* @ return
* The list of modules to install .
2006-07-13 13:14:25 +00:00
*/
2009-07-28 12:13:47 +00:00
function drupal_verify_profile ( $install_state ) {
2012-08-10 09:18:18 +00:00
$profile = $install_state [ 'parameters' ][ 'profile' ];
2009-07-28 12:13:47 +00:00
$info = $install_state [ 'profile_info' ];
2006-08-03 07:06:36 +00:00
2014-02-28 11:51:38 +00:00
// Get the list of available modules for the selected installation profile.
2015-05-08 14:33:16 +00:00
$listing = new ExtensionDiscovery ( \Drupal :: root ());
2017-03-04 01:20:24 +00:00
$present_modules = [];
2014-02-28 11:51:38 +00:00
foreach ( $listing -> scan ( 'module' ) as $present_module ) {
2014-03-11 17:19:24 +00:00
$present_modules [] = $present_module -> getName ();
2006-10-23 06:45:17 +00:00
}
2012-10-05 16:11:15 +00:00
// The installation profile is also a module, which needs to be installed
// after all the other dependencies have been installed.
2014-02-28 11:51:38 +00:00
$present_modules [] = $profile ;
2009-08-21 07:50:08 +00:00
2006-10-23 06:45:17 +00:00
// Verify that all of the profile's required modules are present.
2018-05-03 22:16:58 +00:00
$missing_modules = array_diff ( $info [ 'install' ], $present_modules );
2008-10-01 00:27:29 +00:00
2017-03-04 01:20:24 +00:00
$requirements = [];
2008-11-11 16:49:38 +00:00
2015-09-22 20:29:51 +00:00
if ( $missing_modules ) {
$build = [
'#theme' => 'item_list' ,
'#context' => [ 'list_style' => 'comma-list' ],
];
2007-01-02 05:05:38 +00:00
foreach ( $missing_modules as $module ) {
2017-03-04 01:20:24 +00:00
$build [ '#items' ][] = [ '#markup' => '<span class="admin-missing">' . Unicode :: ucfirst ( $module ) . '</span>' ];
2006-08-03 01:02:51 +00:00
}
2015-09-22 20:29:51 +00:00
$modules_list = \Drupal :: service ( 'renderer' ) -> renderPlain ( $build );
2017-03-04 01:20:24 +00:00
$requirements [ 'required_modules' ] = [
2015-09-22 20:29:51 +00:00
'title' => t ( 'Required modules' ),
'value' => t ( 'Required modules not found.' ),
'severity' => REQUIREMENT_ERROR ,
2017-03-04 01:20:24 +00:00
'description' => t ( 'The following modules are required but were not found. Move them into the appropriate modules subdirectory, such as <em>/modules</em>. Missing modules: @modules' , [ '@modules' => $modules_list ]),
];
2006-08-03 01:02:51 +00:00
}
2008-10-01 00:27:29 +00:00
return $requirements ;
2006-08-03 01:02:51 +00:00
}
2006-07-29 17:56:41 +00:00
2007-12-08 15:15:25 +00:00
/**
2012-08-31 15:56:36 +00:00
* Installs the system module .
2007-12-08 15:15:25 +00:00
*
* Separated from the installation of other modules so core system
* functions can be made available while other modules are installed .
2014-01-25 22:00:48 +00:00
*
* @ param array $install_state
* An array of information about the current installation state . This is used
* to set the default language .
2007-12-08 15:15:25 +00:00
*/
2014-01-25 22:00:48 +00:00
function drupal_install_system ( $install_state ) {
2014-06-26 10:47:01 +00:00
// Remove the service provider of the early installer.
2014-03-09 15:08:57 +00:00
unset ( $GLOBALS [ 'conf' ][ 'container_service_providers' ][ 'InstallerServiceProvider' ]);
Issue #2208429 by dawehner, almaudoh, alexpott, jibran, Xano, donquixote, amitgoyal, bircher, stefan.r, Mile23, alvar0hurtad0, Berdir, andypost, larowlan: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList
2018-01-24 15:21:31 +00:00
// Add the normal installer service provider.
$GLOBALS [ 'conf' ][ 'container_service_providers' ][ 'InstallerServiceProvider' ] = 'Drupal\Core\Installer\NormalInstallerServiceProvider' ;
2013-11-19 16:21:35 +00:00
2019-08-12 21:45:20 +00:00
// Get the existing request.
2014-06-26 10:47:01 +00:00
$request = \Drupal :: request ();
// Reboot into a full production environment to continue the installation.
/** @var \Drupal\Core\Installer\InstallerKernel $kernel */
$kernel = \Drupal :: service ( 'kernel' );
$kernel -> shutdown ();
// Have installer rebuild from the disk, rather then building from scratch.
$kernel -> rebuildContainer ( FALSE );
2019-08-12 21:45:20 +00:00
// Reboot the kernel with new container.
$kernel -> boot ();
$kernel -> preHandle ( $request );
// Ensure our request includes the session if appropriate.
if ( PHP_SAPI !== 'cli' ) {
$request -> setSession ( $kernel -> getContainer () -> get ( 'session' ));
}
2012-07-21 19:16:31 +00:00
Issue #2208429 by dawehner, almaudoh, alexpott, jibran, Xano, donquixote, amitgoyal, bircher, stefan.r, Mile23, alvar0hurtad0, Berdir, andypost, larowlan: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList
2018-01-24 15:21:31 +00:00
// Before having installed the system module and being able to do a module
// rebuild, prime the \Drupal\Core\Extension\ModuleExtensionList static cache
// with the module's location.
// @todo Try to install system as any other module, see
// https://www.drupal.org/node/2719315.
\Drupal :: service ( 'extension.list.module' ) -> setPathname ( 'system' , 'core/modules/system/system.info.yml' );
2014-04-02 07:05:28 +00:00
// Install base system configuration.
\Drupal :: service ( 'config.installer' ) -> installDefaultConfig ( 'core' , 'core' );
2013-01-21 19:21:34 +00:00
Issue #2156401 by alexpott, moshe weitzman, tedbow, dawehner, greg.1.anderson, phenaproxima, chris.smith, heddn, balsama, xjm, Mile23, izus, Manuel Garcia, sun, pwolanin, Berdir: Write install_profile value to configuration and only to settings.php if it is writeable
2017-01-31 10:32:31 +00:00
// Store the installation profile in configuration to populate the
// 'install_profile' container parameter.
\Drupal :: configFactory () -> getEditable ( 'core.extension' )
-> set ( 'profile' , $install_state [ 'parameters' ][ 'profile' ])
-> save ();
2021-01-18 21:43:55 +00:00
$connection = Database :: getConnection ();
$provider = $connection -> getProvider ();
// When the database driver is provided by a module, then install that module.
// This module must be installed before any other module, as it must be able
// to override any call to hook_schema() or any "backend_overridable" service.
if ( $provider !== 'core' ) {
$autoload = $connection -> getConnectionOptions ()[ 'autoload' ] ? ? '' ;
if (( $pos = strpos ( $autoload , 'src/Driver/Database/' )) !== FALSE ) {
$kernel -> getContainer () -> get ( 'module_installer' ) -> install ([ $provider ], FALSE );
}
}
2020-07-21 11:38:45 +00:00
// Install System module.
2017-03-04 01:20:24 +00:00
$kernel -> getContainer () -> get ( 'module_installer' ) -> install ([ 'system' ], FALSE );
2014-06-26 10:47:01 +00:00
2014-01-25 22:00:48 +00:00
// Ensure default language is saved.
if ( isset ( $install_state [ 'parameters' ][ 'langcode' ])) {
2015-01-16 10:43:35 +00:00
\Drupal :: configFactory () -> getEditable ( 'system.site' )
2015-05-05 10:47:16 +00:00
-> set ( 'langcode' , ( string ) $install_state [ 'parameters' ][ 'langcode' ])
-> set ( 'default_langcode' , ( string ) $install_state [ 'parameters' ][ 'langcode' ])
-> save ( TRUE );
2014-01-25 22:00:48 +00:00
}
2006-07-19 07:45:35 +00:00
}
2006-07-13 13:14:25 +00:00
/**
2012-08-31 15:56:36 +00:00
* Verifies the state of the specified file .
2006-07-13 13:14:25 +00:00
*
* @ param $file
* The file to check for .
* @ param $mask
* An optional bitmask created from various FILE_ * constants .
* @ param $type
* The type of file . Can be file ( default ), dir , or link .
2018-06-15 12:51:03 +00:00
* @ param bool $autofix
* ( optional ) Determines whether to attempt fixing the permissions according
* to the provided $mask . Defaults to TRUE .
2012-08-31 15:56:36 +00:00
*
2006-07-13 13:14:25 +00:00
* @ return
2006-12-05 05:47:37 +00:00
* TRUE on success or FALSE on failure . A message is set for the latter .
2006-07-13 13:14:25 +00:00
*/
2018-06-15 12:51:03 +00:00
function drupal_verify_install_file ( $file , $mask = NULL , $type = 'file' , $autofix = TRUE ) {
2006-07-13 13:14:25 +00:00
$return = TRUE ;
// Check for files that shouldn't be there.
if ( isset ( $mask ) && ( $mask & FILE_NOT_EXIST ) && file_exists ( $file )) {
return FALSE ;
}
// Verify that the file is the type of file it is supposed to be.
if ( isset ( $type ) && file_exists ( $file )) {
2008-04-14 17:48:46 +00:00
$check = 'is_' . $type ;
2006-07-13 13:14:25 +00:00
if ( ! function_exists ( $check ) || ! $check ( $file )) {
$return = FALSE ;
}
}
// Verify file permissions.
if ( isset ( $mask )) {
2017-03-04 01:20:24 +00:00
$masks = [ FILE_EXIST , FILE_READABLE , FILE_WRITABLE , FILE_EXECUTABLE , FILE_NOT_READABLE , FILE_NOT_WRITABLE , FILE_NOT_EXECUTABLE ];
2006-07-13 13:14:25 +00:00
foreach ( $masks as $current_mask ) {
if ( $mask & $current_mask ) {
switch ( $current_mask ) {
case FILE_EXIST :
if ( ! file_exists ( $file )) {
2018-06-15 12:51:03 +00:00
if ( $type == 'dir' && $autofix ) {
2006-07-13 13:14:25 +00:00
drupal_install_mkdir ( $file , $mask );
}
if ( ! file_exists ( $file )) {
$return = FALSE ;
}
}
break ;
2020-06-02 08:46:52 +00:00
2006-07-13 13:14:25 +00:00
case FILE_READABLE :
2018-06-15 12:51:03 +00:00
if ( ! is_readable ( $file )) {
2006-07-13 13:14:25 +00:00
$return = FALSE ;
}
break ;
2020-06-02 08:46:52 +00:00
2006-07-13 13:14:25 +00:00
case FILE_WRITABLE :
2018-06-15 12:51:03 +00:00
if ( ! is_writable ( $file )) {
2006-07-13 13:14:25 +00:00
$return = FALSE ;
}
break ;
2020-06-02 08:46:52 +00:00
2006-07-13 13:14:25 +00:00
case FILE_EXECUTABLE :
2018-06-15 12:51:03 +00:00
if ( ! is_executable ( $file )) {
2006-07-13 13:14:25 +00:00
$return = FALSE ;
}
break ;
2020-06-02 08:46:52 +00:00
2006-07-13 13:14:25 +00:00
case FILE_NOT_READABLE :
2018-06-15 12:51:03 +00:00
if ( is_readable ( $file )) {
2006-07-13 13:14:25 +00:00
$return = FALSE ;
}
break ;
2020-06-02 08:46:52 +00:00
2006-07-13 13:14:25 +00:00
case FILE_NOT_WRITABLE :
2018-06-15 12:51:03 +00:00
if ( is_writable ( $file )) {
2006-07-13 13:14:25 +00:00
$return = FALSE ;
}
break ;
2020-06-02 08:46:52 +00:00
2006-07-13 13:14:25 +00:00
case FILE_NOT_EXECUTABLE :
2018-06-15 12:51:03 +00:00
if ( is_executable ( $file )) {
2006-07-13 13:14:25 +00:00
$return = FALSE ;
}
break ;
}
}
}
}
2018-06-15 12:51:03 +00:00
if ( ! $return && $autofix ) {
return drupal_install_fix_file ( $file , $mask );
}
2006-07-13 13:14:25 +00:00
return $return ;
}
/**
2012-08-31 15:56:36 +00:00
* Creates a directory with the specified permissions .
2006-07-13 13:14:25 +00:00
*
2008-09-14 01:58:17 +00:00
* @ param $file
2016-04-16 12:17:32 +00:00
* The name of the directory to create ;
2008-09-14 01:58:17 +00:00
* @ param $mask
2016-04-16 12:17:32 +00:00
* The permissions of the directory to create .
2006-07-13 13:14:25 +00:00
* @ param $message
2016-04-16 12:17:32 +00:00
* ( optional ) Whether to output messages . Defaults to TRUE .
2012-08-31 15:56:36 +00:00
*
2006-07-13 13:14:25 +00:00
* @ return
2016-06-02 14:20:55 +00:00
* TRUE / FALSE whether or not the directory was successfully created .
2006-07-13 13:14:25 +00:00
*/
function drupal_install_mkdir ( $file , $mask , $message = TRUE ) {
$mod = 0 ;
2017-03-04 01:20:24 +00:00
$masks = [ FILE_READABLE , FILE_WRITABLE , FILE_EXECUTABLE , FILE_NOT_READABLE , FILE_NOT_WRITABLE , FILE_NOT_EXECUTABLE ];
2006-07-13 13:14:25 +00:00
foreach ( $masks as $m ) {
if ( $mask & $m ) {
switch ( $m ) {
case FILE_READABLE :
2010-07-26 13:20:01 +00:00
$mod |= 0444 ;
2006-07-13 13:14:25 +00:00
break ;
2020-06-02 08:46:52 +00:00
2006-07-13 13:14:25 +00:00
case FILE_WRITABLE :
2010-07-26 13:20:01 +00:00
$mod |= 0222 ;
2006-07-13 13:14:25 +00:00
break ;
2020-06-02 08:46:52 +00:00
2006-07-13 13:14:25 +00:00
case FILE_EXECUTABLE :
2010-07-26 13:20:01 +00:00
$mod |= 0111 ;
2006-07-13 13:14:25 +00:00
break ;
}
}
}
2019-03-07 09:12:01 +00:00
if ( @ \Drupal :: service ( 'file_system' ) -> mkdir ( $file , $mod )) {
2006-07-13 13:14:25 +00:00
return TRUE ;
}
else {
return FALSE ;
}
}
/**
2012-08-31 15:56:36 +00:00
* Attempts to fix file permissions .
2006-07-13 13:14:25 +00:00
*
2006-12-08 11:54:04 +00:00
* The general approach here is that , because we do not know the security
* setup of the webserver , we apply our permission changes to all three
* digits of the file permission ( i . e . user , group and all ) .
*
* To ensure that the values behave as expected ( and numbers don ' t carry
* from one digit to the next ) we do the calculation on the octal value
* using bitwise operations . This lets us remove , for example , 0222 from
* 0700 and get the correct value of 0500.
*
2006-07-13 13:14:25 +00:00
* @ param $file
2016-04-16 12:17:32 +00:00
* The name of the file with permissions to fix .
2006-07-13 13:14:25 +00:00
* @ param $mask
2016-04-16 12:17:32 +00:00
* The desired permissions for the file .
2006-07-13 13:14:25 +00:00
* @ param $message
2016-04-16 12:17:32 +00:00
* ( optional ) Whether to output messages . Defaults to TRUE .
2012-08-31 15:56:36 +00:00
*
2006-07-13 13:14:25 +00:00
* @ return
2016-06-02 14:20:55 +00:00
* TRUE / FALSE whether or not we were able to fix the file ' s permissions .
2006-07-13 13:14:25 +00:00
*/
function drupal_install_fix_file ( $file , $mask , $message = TRUE ) {
2008-09-27 20:03:35 +00:00
// If $file does not exist, fileperms() issues a PHP warning.
if ( ! file_exists ( $file )) {
return FALSE ;
}
2006-12-08 11:54:04 +00:00
$mod = fileperms ( $file ) & 0777 ;
2017-03-04 01:20:24 +00:00
$masks = [ FILE_READABLE , FILE_WRITABLE , FILE_EXECUTABLE , FILE_NOT_READABLE , FILE_NOT_WRITABLE , FILE_NOT_EXECUTABLE ];
2006-12-08 11:54:04 +00:00
// FILE_READABLE, FILE_WRITABLE, and FILE_EXECUTABLE permission strings
// can theoretically be 0400, 0200, and 0100 respectively, but to be safe
// we set all three access types in case the administrator intends to
// change the owner of settings.php after installation.
2006-07-13 13:14:25 +00:00
foreach ( $masks as $m ) {
if ( $mask & $m ) {
switch ( $m ) {
case FILE_READABLE :
if ( ! is_readable ( $file )) {
2006-12-08 11:54:04 +00:00
$mod |= 0444 ;
2006-07-13 13:14:25 +00:00
}
break ;
2020-06-02 08:46:52 +00:00
2006-07-13 13:14:25 +00:00
case FILE_WRITABLE :
if ( ! is_writable ( $file )) {
2006-12-08 11:54:04 +00:00
$mod |= 0222 ;
2006-07-13 13:14:25 +00:00
}
break ;
2020-06-02 08:46:52 +00:00
2006-07-13 13:14:25 +00:00
case FILE_EXECUTABLE :
if ( ! is_executable ( $file )) {
2006-12-08 11:54:04 +00:00
$mod |= 0111 ;
2006-07-13 13:14:25 +00:00
}
break ;
2020-06-02 08:46:52 +00:00
2006-07-13 13:14:25 +00:00
case FILE_NOT_READABLE :
if ( is_readable ( $file )) {
2006-12-08 11:54:04 +00:00
$mod &= ~ 0444 ;
2006-07-13 13:14:25 +00:00
}
break ;
2020-06-02 08:46:52 +00:00
2006-07-13 13:14:25 +00:00
case FILE_NOT_WRITABLE :
if ( is_writable ( $file )) {
2006-12-08 11:54:04 +00:00
$mod &= ~ 0222 ;
2006-07-13 13:14:25 +00:00
}
break ;
2020-06-02 08:46:52 +00:00
2006-07-13 13:14:25 +00:00
case FILE_NOT_EXECUTABLE :
if ( is_executable ( $file )) {
2006-12-08 11:54:04 +00:00
$mod &= ~ 0111 ;
2006-07-13 13:14:25 +00:00
}
break ;
}
}
}
2006-12-08 11:54:04 +00:00
// chmod() will work if the web server is running as owner of the file.
if ( @ chmod ( $file , $mod )) {
2006-07-13 13:14:25 +00:00
return TRUE ;
}
else {
return FALSE ;
}
}
2006-07-31 19:24:16 +00:00
/**
2012-08-31 15:56:36 +00:00
* Sends the user to a different installer page .
2008-09-14 01:58:17 +00:00
*
* This issues an on - site HTTP redirect . Messages ( and errors ) are erased .
2006-07-31 19:24:16 +00:00
*
* @ param $path
* An installer path .
*/
function install_goto ( $path ) {
2006-10-12 15:20:08 +00:00
global $base_url ;
2017-03-04 01:20:24 +00:00
$headers = [
2013-06-11 21:12:01 +00:00
// Not a permanent redirect.
'Cache-Control' => 'no-cache' ,
2017-03-04 01:20:24 +00:00
];
2013-06-11 21:12:01 +00:00
$response = new RedirectResponse ( $base_url . '/' . $path , 302 , $headers );
$response -> send ();
2006-07-31 19:24:16 +00:00
}
2011-10-01 16:11:43 +00:00
/**
* Returns the URL of the current script , with modified query parameters .
*
* This function can be called by low - level scripts ( such as install . php and
* update . php ) and returns the URL of the current script . Existing query
* parameters are preserved by default , but new ones can optionally be merged
* in .
*
* This function is used when the script must maintain certain query parameters
* over multiple page requests in order to work correctly . In such cases ( for
* example , update . php , which requires the 'continue=1' parameter to remain in
* the URL throughout the update process if there are any requirement warnings
* that need to be bypassed ), using this function to generate the URL for links
* to the next steps of the script ensures that the links will work correctly .
*
* @ param $query
* ( optional ) An array of query parameters to merge in to the existing ones .
*
* @ return
* The URL of the current script , with query parameters modified by the
* passed - in $query . The URL is not sanitized , so it still needs to be run
2015-08-31 07:51:38 +00:00
* through \Drupal\Component\Utility\UrlHelper :: filterBadProtocol () if it will be
* used as an HTML attribute value .
2011-10-01 16:11:43 +00:00
*
* @ see drupal_requirements_url ()
2015-08-31 07:51:38 +00:00
* @ see Drupal\Component\Utility\UrlHelper :: filterBadProtocol ()
2011-10-01 16:11:43 +00:00
*/
2017-03-04 01:20:24 +00:00
function drupal_current_script_url ( $query = []) {
2011-10-01 16:11:43 +00:00
$uri = $_SERVER [ 'SCRIPT_NAME' ];
2014-05-08 15:27:12 +00:00
$query = array_merge ( UrlHelper :: filterQueryParameters ( \Drupal :: request () -> query -> all ()), $query );
2011-10-01 16:11:43 +00:00
if ( ! empty ( $query )) {
2014-04-16 10:07:11 +00:00
$uri .= '?' . UrlHelper :: buildQuery ( $query );
2011-10-01 16:11:43 +00:00
}
return $uri ;
}
/**
* Returns a URL for proceeding to the next page after a requirements problem .
*
* This function can be called by low - level scripts ( such as install . php and
* update . php ) and returns a URL that can be used to attempt to proceed to the
* next step of the script .
*
* @ param $severity
* The severity of the requirements problem , as returned by
* drupal_requirements_severity () .
*
* @ return
* A URL for attempting to proceed to the next step of the script . The URL is
2015-08-31 07:51:38 +00:00
* not sanitized , so it still needs to be run through
* \Drupal\Component\Utility\UrlHelper :: filterBadProtocol () if it will be used
* as an HTML attribute value .
2011-10-01 16:11:43 +00:00
*
* @ see drupal_current_script_url ()
2015-08-31 07:51:38 +00:00
* @ see \Drupal\Component\Utility\UrlHelper :: filterBadProtocol ()
2011-10-01 16:11:43 +00:00
*/
function drupal_requirements_url ( $severity ) {
2017-03-04 01:20:24 +00:00
$query = [];
2011-10-01 16:11:43 +00:00
// If there are no errors, only warnings, append 'continue=1' to the URL so
// the user can bypass this screen on the next page load.
if ( $severity == REQUIREMENT_WARNING ) {
$query [ 'continue' ] = 1 ;
}
return drupal_current_script_url ( $query );
}
2006-09-01 08:44:53 +00:00
/**
2012-10-05 16:11:15 +00:00
* Checks an installation profile ' s requirements .
2006-09-01 08:44:53 +00:00
*
2012-08-10 09:18:18 +00:00
* @ param string $profile
2012-10-05 16:11:15 +00:00
* Name of installation profile to check .
2012-08-10 09:18:18 +00:00
*
* @ return array
2012-10-05 16:11:15 +00:00
* Array of the installation profile ' s requirements .
2006-09-01 08:44:53 +00:00
*/
2016-01-19 14:08:12 +00:00
function drupal_check_profile ( $profile ) {
2009-07-15 02:08:41 +00:00
$info = install_profile_info ( $profile );
2009-12-27 03:37:54 +00:00
// Collect requirement testing results.
2017-03-04 01:20:24 +00:00
$requirements = [];
2015-05-08 14:33:16 +00:00
// Performs an ExtensionDiscovery scan as the system module is unavailable and
// we don't yet know where all the modules are located.
// @todo Remove as part of https://www.drupal.org/node/2186491
2016-09-27 15:00:36 +00:00
$drupal_root = \Drupal :: root ();
$module_list = ( new ExtensionDiscovery ( $drupal_root )) -> scan ( 'module' );
2018-05-03 22:16:58 +00:00
foreach ( $info [ 'install' ] as $module ) {
2016-09-27 15:00:36 +00:00
// If the module is in the module list we know it exists and we can continue
// including and registering it.
// @see \Drupal\Core\Extension\ExtensionDiscovery::scanDirectory()
if ( isset ( $module_list [ $module ])) {
$function = $module . '_requirements' ;
$module_path = $module_list [ $module ] -> getPath ();
$install_file = " $drupal_root / $module_path / $module .install " ;
if ( is_file ( $install_file )) {
require_once $install_file ;
}
2019-04-11 03:08:45 +00:00
\Drupal :: service ( 'class_loader' ) -> addPsr4 ( 'Drupal\\' . $module . '\\' , \Drupal :: root () . " / $module_path /src " );
2015-04-01 09:11:54 +00:00
2016-09-27 15:00:36 +00:00
if ( function_exists ( $function )) {
$requirements = array_merge ( $requirements , $function ( 'install' ));
}
2006-09-05 02:28:11 +00:00
}
2006-09-01 08:44:53 +00:00
}
2016-09-27 15:00:36 +00:00
2018-10-19 21:51:28 +00:00
// Add the profile requirements.
$function = $profile . '_requirements' ;
if ( function_exists ( $function )) {
$requirements = array_merge ( $requirements , $function ( 'install' ));
}
2006-09-01 08:44:53 +00:00
return $requirements ;
}
/**
2012-08-31 15:56:36 +00:00
* Extracts the highest severity from the requirements array .
2008-09-14 01:58:17 +00:00
*
* @ param $requirements
2008-11-11 16:49:38 +00:00
* An array of requirements , in the same format as is returned by
2008-09-14 01:58:17 +00:00
* hook_requirements () .
2012-08-31 15:56:36 +00:00
*
2008-09-14 01:58:17 +00:00
* @ return
* The highest severity in the array .
2006-09-01 08:44:53 +00:00
*/
function drupal_requirements_severity ( & $requirements ) {
$severity = REQUIREMENT_OK ;
foreach ( $requirements as $requirement ) {
if ( isset ( $requirement [ 'severity' ])) {
$severity = max ( $severity , $requirement [ 'severity' ]);
}
}
return $severity ;
}
/**
2012-08-31 15:56:36 +00:00
* Checks a module ' s requirements .
2008-09-14 01:58:17 +00:00
*
* @ param $module
* Machine name of module to check .
2012-08-31 15:56:36 +00:00
*
2008-09-14 01:58:17 +00:00
* @ return
2012-08-31 15:56:36 +00:00
* TRUE or FALSE , depending on whether the requirements are met .
2006-09-01 08:44:53 +00:00
*/
function drupal_check_module ( $module ) {
2009-12-27 03:37:54 +00:00
module_load_install ( $module );
2013-08-01 13:42:18 +00:00
// Check requirements
2017-03-04 01:20:24 +00:00
$requirements = \Drupal :: moduleHandler () -> invoke ( $module , 'requirements' , [ 'install' ]);
2013-08-01 13:42:18 +00:00
if ( is_array ( $requirements ) && drupal_requirements_severity ( $requirements ) == REQUIREMENT_ERROR ) {
// Print any error messages
foreach ( $requirements as $requirement ) {
if ( isset ( $requirement [ 'severity' ]) && $requirement [ 'severity' ] == REQUIREMENT_ERROR ) {
2015-06-15 20:47:27 +00:00
$message = $requirement [ 'description' ];
2013-08-01 13:42:18 +00:00
if ( isset ( $requirement [ 'value' ]) && $requirement [ 'value' ]) {
2017-03-04 01:20:24 +00:00
$message = t ( '@requirements_message (Currently using @item version @version)' , [ '@requirements_message' => $requirement [ 'description' ], '@item' => $requirement [ 'title' ], '@version' => $requirement [ 'value' ]]);
2006-09-01 08:44:53 +00:00
}
2018-01-22 15:28:16 +00:00
\Drupal :: messenger () -> addError ( $message );
2006-09-01 08:44:53 +00:00
}
}
2013-08-01 13:42:18 +00:00
return FALSE ;
2006-09-01 08:44:53 +00:00
}
return TRUE ;
}
2009-07-15 02:08:41 +00:00
/**
2013-03-06 22:51:39 +00:00
* Retrieves information about an installation profile from its . info . yml file .
2009-07-19 04:48:10 +00:00
*
2013-03-06 22:51:39 +00:00
* The information stored in a profile . info . yml file is similar to that stored
* in a normal Drupal module . info . yml file . For example :
2012-10-05 16:11:15 +00:00
* - name : The real name of the installation profile for display purposes .
2009-07-19 04:48:10 +00:00
* - description : A brief description of the profile .
2012-08-31 15:56:36 +00:00
* - dependencies : An array of shortnames of other modules that this install
* profile requires .
2018-05-03 22:16:58 +00:00
* - install : An array of shortname of other modules to install that are not
* required by this install profile .
2009-07-19 04:48:10 +00:00
*
2013-03-06 22:51:39 +00:00
* Additional , less commonly - used information that can appear in a
* profile . info . yml file but not in a normal Drupal module . info . yml file
* includes :
2014-03-14 10:49:27 +00:00
*
* - distribution : Existence of this key denotes that the installation profile
* is intended to be the only eligible choice in a distribution and will be
* auto - selected during installation , whereas the installation profile
* selection screen will be skipped . If more than one distribution profile is
* found then the first one discovered will be selected .
* The following subproperties may be set :
* - name : The name of the distribution that is being installed , to be shown
* throughout the installation process . If omitted ,
* drupal_install_profile_distribution_name () defaults to 'Drupal' .
* - install : Optional parameters to override the installer :
* - theme : The machine name of a theme to use in the installer instead of
* Drupal ' s default installer theme .
2018-04-26 12:54:48 +00:00
* - finish_url : A destination to visit after the installation of the
* distribution is finished
2009-12-07 06:19:20 +00:00
*
2011-02-19 00:50:43 +00:00
* Note that this function does an expensive file system scan to get info file
* information for dependencies . If you only need information from the info
2019-10-07 13:46:33 +00:00
* file itself , use
* \Drupal :: service ( 'extension.list.profile' ) -> getExtensionInfo () .
2011-02-19 00:50:43 +00:00
*
2013-03-06 22:51:39 +00:00
* Example of . info . yml file :
2010-01-04 16:20:20 +00:00
* @ code
2017-01-05 15:41:49 +00:00
* name : Minimal
* description : Start fresh , with only a few modules enabled .
2018-05-03 22:16:58 +00:00
* install :
2017-01-05 15:41:49 +00:00
* - block
* - dblog
2010-01-04 16:20:20 +00:00
* @ endcode
2009-07-19 04:48:10 +00:00
*
2011-10-05 15:43:58 +00:00
* @ param $profile
2009-07-19 04:48:10 +00:00
* Name of profile .
2011-11-25 06:22:29 +00:00
* @ param $langcode
* Language code ( if any ) .
2011-10-05 15:43:58 +00:00
*
2009-07-19 04:48:10 +00:00
* @ return
* The info array .
2009-07-15 02:08:41 +00:00
*/
2011-11-25 06:22:29 +00:00
function install_profile_info ( $profile , $langcode = 'en' ) {
2019-03-29 05:02:13 +00:00
static $cache = [];
2009-07-19 04:48:10 +00:00
2015-05-18 05:03:27 +00:00
if ( ! isset ( $cache [ $profile ][ $langcode ])) {
2009-07-19 04:48:10 +00:00
// Set defaults for module info.
2017-03-04 01:20:24 +00:00
$defaults = [
'dependencies' => [],
2018-05-03 22:16:58 +00:00
'install' => [],
2017-03-04 01:20:24 +00:00
'themes' => [ 'stark' ],
2009-07-19 04:48:10 +00:00
'description' => '' ,
'version' => NULL ,
2010-08-22 15:31:18 +00:00
'hidden' => FALSE ,
Issue #2908079 by jungle, voleger, mpdonadio, zahord, andypost, RoSk0, Mile23, claudiu.cristea, alexpott, xjm, Krzysztof Domański, naveenvalecha, piggito, Suresh Prabhu Parkala, daffie, dawehner, gumanist: Move some of the bootstrap.inc PHP-related constants to \Drupal and deprecate the old versions
2020-06-21 18:55:29 +00:00
'php' => \Drupal :: MINIMUM_PHP ,
Issue #2788777 by alexpott, bircher, jribeiro, Eli-T, mpotter, douggreen, GoZ, DamienMcKenna, Dane Powell, jibran, szeidler, Alumei, andypost, dawehner, johndevman: Allow a site-specific profile to be installed from existing config
2018-06-20 18:03:54 +00:00
'config_install_path' => NULL ,
2017-03-04 01:20:24 +00:00
];
Issue #2347783 by kim.pepper, andypost, almaudoh, gumanist, aleevas, rodrigoaguilera, Berdir, saurabh-2k17, Spokje, dhirendra.mishra, alexpott, paulocs, izus, Wim Leers, KapilV, naveenvalecha, anmolgoyal74, subson, yo30, harsha012, mrinalini9, daffie, voleger, dww, fietserwin, tim.plunkett, joachim, larowlan: Deprecate drupal_get_path() and drupal_get_filename() and replace with ExtensionList::getPath() and ExtensionList::getPathname()
2021-07-15 10:20:33 +00:00
$profile_path = \Drupal :: service ( 'extension.list.profile' ) -> getPath ( $profile );
Issue #2788777 by alexpott, bircher, jribeiro, Eli-T, mpotter, douggreen, GoZ, DamienMcKenna, Dane Powell, jibran, szeidler, Alumei, andypost, dawehner, johndevman: Allow a site-specific profile to be installed from existing config
2018-06-20 18:03:54 +00:00
$info = \Drupal :: service ( 'info_parser' ) -> parse ( " $profile_path / $profile .info.yml " );
2012-08-10 09:18:18 +00:00
$info += $defaults ;
2009-08-21 07:50:08 +00:00
Issue #2677532 by alexpott, Mile23, kim.pepper, dawehner, andypost, Eric_A, xjm, Mixologic, larowlan, phenaproxima, markcarver, borisson_: Move drupal_check_incompatibility() functionality to a new Dependency class and Version component
2018-10-22 05:21:49 +00:00
$dependency_name_function = function ( $dependency ) {
return Dependency :: createFromString ( $dependency ) -> getName ();
};
Issue #2855026 by phenaproxima, trobey, HaiNguyen007, alexpott, Taran2L, -enzo-, Jo Fitzgerald, tucho, DamienMcKenna, andypost, tobiasb, dawehner, larowlan: Installation profiles do not support project:module format for dependencies
2018-10-08 16:44:23 +00:00
// Convert dependencies in [project:module] format.
Issue #2677532 by alexpott, Mile23, kim.pepper, dawehner, andypost, Eric_A, xjm, Mixologic, larowlan, phenaproxima, markcarver, borisson_: Move drupal_check_incompatibility() functionality to a new Dependency class and Version component
2018-10-22 05:21:49 +00:00
$info [ 'dependencies' ] = array_map ( $dependency_name_function , $info [ 'dependencies' ]);
Issue #2855026 by phenaproxima, trobey, HaiNguyen007, alexpott, Taran2L, -enzo-, Jo Fitzgerald, tucho, DamienMcKenna, andypost, tobiasb, dawehner, larowlan: Installation profiles do not support project:module format for dependencies
2018-10-08 16:44:23 +00:00
// Convert install key in [project:module] format.
Issue #2677532 by alexpott, Mile23, kim.pepper, dawehner, andypost, Eric_A, xjm, Mixologic, larowlan, phenaproxima, markcarver, borisson_: Move drupal_check_incompatibility() functionality to a new Dependency class and Version component
2018-10-22 05:21:49 +00:00
$info [ 'install' ] = array_map ( $dependency_name_function , $info [ 'install' ]);
Issue #2855026 by phenaproxima, trobey, HaiNguyen007, alexpott, Taran2L, -enzo-, Jo Fitzgerald, tucho, DamienMcKenna, andypost, tobiasb, dawehner, larowlan: Installation profiles do not support project:module format for dependencies
2018-10-08 16:44:23 +00:00
2009-08-21 07:50:08 +00:00
// drupal_required_modules() includes the current profile as a dependency.
2014-03-24 15:31:12 +00:00
// Remove that dependency, since a module cannot depend on itself.
2017-03-04 01:20:24 +00:00
$required = array_diff ( drupal_required_modules (), [ $profile ]);
2014-03-24 15:31:12 +00:00
2017-03-04 01:20:24 +00:00
$locale = ! empty ( $langcode ) && $langcode != 'en' ? [ 'locale' ] : [];
2014-03-24 15:31:12 +00:00
2018-05-03 22:16:58 +00:00
// Merge dependencies, required modules and locale into install list and
// remove any duplicates.
$info [ 'install' ] = array_unique ( array_merge ( $info [ 'install' ], $required , $info [ 'dependencies' ], $locale ));
2009-08-21 07:50:08 +00:00
Issue #2788777 by alexpott, bircher, jribeiro, Eli-T, mpotter, douggreen, GoZ, DamienMcKenna, Dane Powell, jibran, szeidler, Alumei, andypost, dawehner, johndevman: Allow a site-specific profile to be installed from existing config
2018-06-20 18:03:54 +00:00
// If the profile has a config/sync directory use that to install drupal.
if ( is_dir ( $profile_path . '/config/sync' )) {
$info [ 'config_install_path' ] = $profile_path . '/config/sync' ;
}
2015-05-18 05:03:27 +00:00
$cache [ $profile ][ $langcode ] = $info ;
2009-07-19 04:48:10 +00:00
}
2015-05-18 05:03:27 +00:00
return $cache [ $profile ][ $langcode ];
2009-07-15 02:08:41 +00:00
}
2010-11-29 04:45:11 +00:00
/**
* Returns a database installer object .
*
2020-04-07 20:00:31 +00:00
* Before calling this function it is important the database installer object
* is autoloadable . Database drivers provided by contributed modules are added
* to the autoloader in drupal_get_database_types () and Settings :: initialize () .
*
2010-11-29 04:45:11 +00:00
* @ param $driver
* The name of the driver .
2020-04-07 20:00:31 +00:00
* @ param string $namespace
* ( optional ) The database driver namespace .
2013-09-27 12:53:59 +00:00
*
* @ return \Drupal\Core\Database\Install\Tasks
2013-10-04 15:29:43 +00:00
* A class defining the requirements and tasks for installing the database .
2020-04-07 20:00:31 +00:00
*
* @ see drupal_get_database_types ()
* @ see \Drupal\Core\Site\Settings :: initialize ()
2010-11-29 04:45:11 +00:00
*/
2020-04-07 20:00:31 +00:00
function db_installer_object ( $driver , $namespace = NULL ) {
2011-12-28 19:24:46 +00:00
// We cannot use Database::getConnection->getDriverClass() here, because
// the connection object is not yet functional.
2020-04-07 20:00:31 +00:00
if ( $namespace ) {
$task_class = $namespace . " \\ Install \\ Tasks " ;
return new $task_class ();
}
// Old Drupal 8 style contrib namespace.
2020-03-17 10:08:29 +00:00
$task_class = " Drupal \\ Driver \\ Database \\ { $driver } \\ Install \\ Tasks " ;
2013-02-15 19:08:38 +00:00
if ( class_exists ( $task_class )) {
return new $task_class ();
}
else {
2020-04-07 20:00:31 +00:00
// Core provided driver.
2020-03-17 10:08:29 +00:00
$task_class = " Drupal \\ Core \\ Database \\ Driver \\ { $driver } \\ Install \\ Tasks " ;
2013-02-15 19:08:38 +00:00
return new $task_class ();
}
2010-11-29 04:45:11 +00:00
}