diff --git a/core/includes/mail.inc b/core/includes/mail.inc index c4ba3566b463d74bea3b64be81dd49e4c4e29bcb..c9ff601952fa481ff58b5b735850fa1a673e8b84 100644 --- a/core/includes/mail.inc +++ b/core/includes/mail.inc @@ -8,7 +8,7 @@ /** * Auto-detect appropriate line endings for e-mails. * - * $conf['mail_line_endings'] will override this setting. + * $settings['mail_line_endings'] will override this setting. */ define('MAIL_LINE_ENDINGS', isset($_SERVER['WINDIR']) || strpos($_SERVER['SERVER_SOFTWARE'], 'Win32') !== FALSE ? "\r\n" : "\n"); @@ -216,14 +216,14 @@ function drupal_mail($module, $key, $to, $langcode, $params = array(), $from = N * By default, all messages are sent via PHP's mail() function by the * Drupal\Core\Mail\PhpMail implementation. * - * The selection of a particular implementation is controlled via the variable - * 'mail_system', which is a keyed array. The default implementation - * is the class whose name is the value of 'default-system' key. A more specific - * match first to key and then to module will be used in preference to the - * default. To specify a different class for all mail sent by one module, set - * the class name as the value for the key corresponding to the module name. To - * specify a class for a particular message sent by one module, set the class - * name as the value for the array key that is the message id, which is + * The selection of a particular implementation is controlled via the config + * 'system.mail.interface', which is a keyed array. The default implementation + * is the class whose name is the value of 'default' key. A more specific match + * first to key and then to module will be used in preference to the default. To + * specify a different class for all mail sent by one module, set the class + * name as the value for the key corresponding to the module name. To specify + * a class for a particular message sent by one module, set the class name as + * the value for the array key that is the message id, which is * "${module}_${key}". * * For example to debug all mail sent by the user module by logging it to a @@ -231,7 +231,7 @@ function drupal_mail($module, $key, $to, $langcode, $params = array(), $from = N * * @code * array( - * 'default-system' => 'Drupal\Core\Mail\PhpMail', + * 'default' => 'Drupal\Core\Mail\PhpMail', * 'user' => 'DevelMailLog', * ); * @endcode @@ -241,7 +241,7 @@ function drupal_mail($module, $key, $to, $langcode, $params = array(), $from = N * * @code * array( - * 'default-system' => 'Drupal\Core\Mail\PhpMail', + * 'default' => 'Drupal\Core\Mail\PhpMail', * 'user' => 'DevelMailLog', * 'contact_page_autoreply' => 'DrupalDevNullMailSend', * ); @@ -260,13 +260,15 @@ function drupal_mail($module, $key, $to, $langcode, $params = array(), $from = N * alter hook in drupal_mail() would have been {$module}_{$key}. * * @return Drupal\Core\Mail\MailInterface + * + * @throws \Exception */ function drupal_mail_system($module, $key) { $instances = &drupal_static(__FUNCTION__, array()); $id = $module . '_' . $key; - $configuration = variable_get('mail_system', array('default-system' => 'Drupal\Core\Mail\PhpMail')); + $configuration = config('system.mail')->get('interface'); // Look for overrides for the default class, starting from the most specific // id, and falling back to the module name. @@ -277,7 +279,7 @@ function drupal_mail_system($module, $key) { $class = $configuration[$module]; } else { - $class = $configuration['default-system']; + $class = $configuration['default']; } if (empty($instances[$class])) { @@ -506,8 +508,9 @@ function drupal_html_to_text($string, $allowed_tags = NULL) { if (isset($casing)) { $chunk = $casing($chunk); } + $line_endings = settings()->get('mail_line_endings', MAIL_LINE_ENDINGS); // Format it and apply the current indentation. - $output .= drupal_wrap_mail($chunk, implode('', $indent)) . MAIL_LINE_ENDINGS; + $output .= drupal_wrap_mail($chunk, implode('', $indent)) . $line_endings; // Remove non-quotation markers from indentation. $indent = array_map('_drupal_html_to_text_clean', $indent); } diff --git a/core/lib/Drupal/Core/Mail/PhpMail.php b/core/lib/Drupal/Core/Mail/PhpMail.php index f5ec995609e368f0079f07d10d030dd21f26f571..580a82415a31e3ed98a8c8919cef139c354d3762 100644 --- a/core/lib/Drupal/Core/Mail/PhpMail.php +++ b/core/lib/Drupal/Core/Mail/PhpMail.php @@ -59,13 +59,13 @@ public function mail(array $message) { foreach ($message['headers'] as $name => $value) { $mimeheaders[] = $name . ': ' . mime_header_encode($value); } - $line_endings = variable_get('mail_line_endings', MAIL_LINE_ENDINGS); + $line_endings = settings()->get('mail_line_endings', MAIL_LINE_ENDINGS); // Prepare mail commands. $mail_subject = mime_header_encode($message['subject']); // Note: e-mail uses CRLF for line-endings. PHP's API requires LF // on Unix and CRLF on Windows. Drupal automatically guesses the // line-ending format appropriate for your system. If you need to - // override this, adjust $conf['mail_line_endings'] in settings.php. + // override this, adjust $settings['mail_line_endings'] in settings.php. $mail_body = preg_replace('@\r?\n@', $line_endings, $message['body']); // For headers, PHP's API suggests that we use CRLF normally, // but some MTAs incorrectly replace LF with CRLF. See #234403. diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php index 7626952f80c397117b320fb0c99225a1a5276b57..44e29c2a7a0e179d9ad9f7a1dd2d28a5c63bee82 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php @@ -854,7 +854,7 @@ protected function setUp() { variable_set('file_public_path', $this->public_files_directory); // Use the test mail class instead of the default mail handler class. - variable_set('mail_system', array('default-system' => 'Drupal\Core\Mail\VariableLog')); + config('system.mail')->set('interface.default', 'Drupal\Core\Mail\VariableLog')->save(); drupal_set_time_limit($this->timeLimit); // Temporary fix so that when running from run-tests.sh we don't get an diff --git a/core/modules/system/config/system.mail.yml b/core/modules/system/config/system.mail.yml new file mode 100644 index 0000000000000000000000000000000000000000..e3eb7685187a5da626b48739485d144e84e45c8c --- /dev/null +++ b/core/modules/system/config/system.mail.yml @@ -0,0 +1,2 @@ +interface: + default: 'Drupal\Core\Mail\PhpMail' diff --git a/core/modules/system/lib/Drupal/system/Tests/Mail/HtmlToTextTest.php b/core/modules/system/lib/Drupal/system/Tests/Mail/HtmlToTextTest.php index 5302c8dbd4f26fb00832c2ec2fea3db03ccfa6e9..f93b40fef5b9bbbed08211e84557d891e7b5702e 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Mail/HtmlToTextTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Mail/HtmlToTextTest.php @@ -348,11 +348,8 @@ public function testDrupalHtmlToTextParagraphs() { public function testVeryLongLineWrap() { $input = 'Drupal

' . str_repeat('x', 2100) . '
Drupal'; $output = drupal_html_to_text($input); - // This awkward construct comes from includes/mail.inc lines 8-13. - $eol = variable_get('mail_line_endings', MAIL_LINE_ENDINGS); - // We must use strlen() rather than drupal_strlen() in order to count - // octets rather than characters. - $line_length_limit = 1000 - drupal_strlen($eol); + $eol = settings()->get('mail_line_endings', MAIL_LINE_ENDINGS); + $maximum_line_length = 0; foreach (explode($eol, $output) as $line) { // We must use strlen() rather than drupal_strlen() in order to count diff --git a/core/modules/system/lib/Drupal/system/Tests/Mail/MailTest.php b/core/modules/system/lib/Drupal/system/Tests/Mail/MailTest.php index bb72d293075ea1634b3d9850612482d2f3fa9033..155fdb859accc01999a070175bde4c2ecb520b1f 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Mail/MailTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Mail/MailTest.php @@ -42,7 +42,7 @@ function setUp() { parent::setUp(); // Set MailTestCase (i.e. this class) as the SMTP library - variable_set('mail_system', array('default-system' => 'Drupal\system\Tests\Mail\MailTest')); + config('system.mail')->set('interface.default', 'Drupal\system\Tests\Mail\MailTest')->save(); } /** @@ -119,4 +119,3 @@ public function mail(array $message) { self::$sent_message = $message; } } - diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/BareMinimalUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/BareMinimalUpgradePathTest.php index f6784b93a7e9436c8eab978f8a4daa5edc75aaa5..9c51bee19953a000bab4ef3d7e819d7a38ff068d 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/BareMinimalUpgradePathTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/BareMinimalUpgradePathTest.php @@ -90,6 +90,9 @@ public function testBasicMinimalUpgrade() { // Verify that image.module was correctly installed. $this->assertEqual('thumbnail', config('image.style.thumbnail')->get('name')); + + // Make sure that the default mail configuration has been converted. + $this->assertEqual(array('default' => 'Drupal\Core\Mail\PhpMail'), config('system.mail')->get('interface'), 'Default mail configuration set.'); } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/MailUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/MailUpgradePathTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a77c6b7141b0b7654dac50dfa0abe525016d3dbd --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/MailUpgradePathTest.php @@ -0,0 +1,55 @@ + 'Mail upgrade test', + 'description' => 'Tests upgrade of Mail backend configuration.', + 'group' => 'Upgrade path', + ); + } + + public function setUp() { + $this->databaseDumpFiles = array( + drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.bare.standard_all.database.php.gz', + drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.system.database.php', + ); + parent::setUp(); + } + + /** + * Tests that mail backends are upgraded to their Drupal 8 equivalents. + */ + public function testMailSystemUpgrade() { + $this->performUpgrade(TRUE); + + // Get the new mailer definitions. + $mail_system = config('system.mail')->get('interface'); + + // Check that the default mailer has been changed to a PSR-0 definition. + $this->assertEqual($mail_system['default'], 'Drupal\Core\Mail\PhpMail', 'Default mailer upgraded to Drupal 8 syntax.'); + + // Check that a custom mailer has been preserved through the upgrade. + $this->assertEqual($mail_system['maillog'], 'MaillogMailSystem', 'Custom mail backend preserved during upgrade.'); + } + + /** + * Overrides UpgradePathTestBase::checkCompletionPage(). + */ + protected function checkCompletionPage() { + // Ensure the user is informed about mail backends that need updating. + $this->assertText('The following mail backends need to be re-configured: MaillogMailSystem.', 'User notified about outdated mail backends.'); + } + +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php index 3ee5a9302fce59d44749bc387d8df863f354bf27..74c9923000774e9fad7c727b8f751a5d7cb1f961 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php @@ -264,6 +264,9 @@ protected function performUpgrade($register_errors = TRUE) { throw new Exception('Errors during update process.'); } + // Allow tests to check the completion page. + $this->checkCompletionPage(); + // Check if there still are pending updates. $this->getUpdatePhp(); $this->drupalPost(NULL, array(), t('Continue')); @@ -316,4 +319,11 @@ protected function getUpdatePhp() { return $out; } + /** + * Checks the update.php completion page. + * + * Invoked by UpgradePathTestBase::performUpgrade() to allow upgrade tests to + * check messages and other output on the final confirmation page. + */ + protected function checkCompletionPage() { } } diff --git a/core/modules/system/system.install b/core/modules/system/system.install index c21d62a5019ee58b02562b9a89748a58a8cabe47..9d986789c14e60f6e9342ec39b511c70948e6812 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -2140,6 +2140,45 @@ function system_update_8049() { db_create_table('config_snapshot', $table); } +/** + * Converts mail settings to config. + * + * @ingroup config_upgrade + */ +function system_update_8050() { + // Update any mail interfaces to their Drupal 8 equivalents. + $old_mail_system_settings = update_variable_get('mail_system'); + + if ($old_mail_system_settings) { + $new_mail_system_settings = array(); + + foreach ($old_mail_system_settings as $key => $mailer_class) { + // Update old class name to PSR-0. + if ($mailer_class == 'DefaultMailSystem') { + $mailer_class = 'Drupal\Core\Mail\PhpMail'; + } + // New default key. + if ($key == 'default-system') { + $new_mail_system_settings['default'] = $mailer_class; + unset($old_mail_system_settings[$key]); + } + } + if (count($old_mail_system_settings)) { + // Warn about non-core classes which may need to be updated. + drupal_set_message(format_string('The following mail backends need to be re-configured: @list.', array('@list' => implode(', ', $old_mail_system_settings))), 'warning'); + } + + $new_mail_system_settings += $old_mail_system_settings; + // Save the updated variable, and let update_variables_to_config convert it. + if ($new_mail_system_settings) { + update_variable_set('mail_system', $new_mail_system_settings); + } + } + update_variables_to_config('system.mail', array( + 'mail_system' => 'interface', + )); +} + /** * @} End of "defgroup updates-7.x-to-8.x". * The next series of updates should start at 9000. diff --git a/core/modules/system/tests/upgrade/drupal-7.system.database.php b/core/modules/system/tests/upgrade/drupal-7.system.database.php index be9f54cd9e2e1f289e1163bac6dd004fbc57b891..5bf6f296d0c524236769291bf43c15689c440a9f 100644 --- a/core/modules/system/tests/upgrade/drupal-7.system.database.php +++ b/core/modules/system/tests/upgrade/drupal-7.system.database.php @@ -12,123 +12,127 @@ // Add non-default system settings. db_insert('variable')->fields(array( - 'name', - 'value', -)) -->values(array( - 'name' => 'cache', - 'value'=> 'i:1;', -)) -->values(array( + 'name', + 'value', + )) + ->values(array( + 'name' => 'cache', + 'value'=> 'i:1;', + )) + ->values(array( 'name' => 'cache_lifetime', 'value' => 's:5:"10800";', )) -->values(array( + ->values(array( 'name' => 'page_cache_maximum_age', 'value' => 's:4:"1800";', )) -->values(array( + ->values(array( 'name' => 'page_compression', 'value' => 'i:1;', )) -->values(array( + ->values(array( 'name' => 'preprocess_css', 'value' => 'i:1;', )) -->values(array( + ->values(array( 'name' => 'preprocess_js', 'value' => 'i:1;', )) -->values(array( + ->values(array( 'name' => 'cron_safe_threshold', 'value' => 's:5:"86400";', )) -->values(array( + ->values(array( 'name' => 'cron_threshold_warning', 'value' => 's:5:"86400";', )) -->values(array( + ->values(array( 'name' => 'cron_threshold_error', 'value' => 's:6:"172800";', )) -->values(array( + ->values(array( 'name' => 'error_level', 'value' => 's:1:"1";', )) -->values(array( + ->values(array( 'name' => 'maintenance_mode', 'value' => 'i:1;', )) -->values(array( + ->values(array( 'name' => 'maintenance_mode_message', 'value' => 's:22:"Testing config upgrade"', )) -->values(array( + ->values(array( 'name' => 'feed_default_items', 'value' => 's:2:"20";', )) -->values(array( + ->values(array( 'name' => 'feed_description', 'value' => 's:22:"Testing config upgrade";', )) -->values(array( + ->values(array( 'name' => 'feed_item_length', 'value' => 's:6:"teaser";', )) -->values(array( + ->values(array( 'name' => 'site_403', 'value' => 's:3:"403";', )) -->values(array( + ->values(array( 'name' => 'site_404', 'value' => 's:3:"404";', )) -->values(array( + ->values(array( 'name' => 'site_frontpage', 'value' => 's:4:"node";', )) -->values(array( + ->values(array( 'name' => 'site_slogan', 'value' => 's:31:"CMI makes Drupal 8 drush cex -y";', )) -->values(array( - 'name' => 'user_cancel_method', - 'value' => 's:20:"user_cancel_reassign"', + ->values(array( + 'name' => 'user_cancel_method', + 'value' => 's:20:"user_cancel_reassign"', )) -->values(array( + ->values(array( 'name' => 'taxonomy_override_selector', 'value' => 'i:1;', )) -->values(array( + ->values(array( 'name' => 'taxonomy_terms_per_page_admin', 'value' => 'i:32;', )) -->values(array( + ->values(array( 'name' => 'taxonomy_maintain_index_table', 'value' => 'i:0;', - )) -->values(array( - 'name' => 'filter_allowed_protocols', - 'value' => 'a:4:{i:0;s:4:"http";i:1;s:5:"https";i:2;s:3:"ftp";i:3;s:6:"mailto";}', )) -->values(array( + ->values(array( + 'name' => 'filter_allowed_protocols', + 'value' => 'a:4:{i:0;s:4:"http";i:1;s:5:"https";i:2;s:3:"ftp";i:3;s:6:"mailto";}', + )) + ->values(array( 'name' => 'password_count_log2', 'value' => 'i:42;', -)) -->values(array( + )) + ->values(array( 'name' => 'actions_max_stack', 'value' => 'i:42;', )) -->execute(); + ->values(array( + 'name' => 'mail_system', + 'value' => 'a:2:{s:14:"default-system";s:17:"DefaultMailSystem";s:7:"maillog";s:17:"MaillogMailSystem";}', + )) + ->execute(); db_update('variable') ->fields(array('value' => 's:18:"config@example.com";')) ->condition('name', 'site_mail') ->execute(); db_update('variable') - ->fields(array('value' => 's:22:"Testing config upgrade";')) - ->condition('name', 'site_name') - ->execute(); + ->fields(array('value' => 's:22:"Testing config upgrade";')) + ->condition('name', 'site_name') + ->execute(); db_update('variable') ->fields(array('value' => 's:10:"plain_text";')) ->condition('name', 'filter_fallback_format') @@ -152,50 +156,50 @@ ); db_insert('variable')->fields(array( - 'name', - 'value', -)) + 'name', + 'value', + )) ->values(array( - 'name' => 'color_bartik_files', - 'value' => serialize(array('public://color/bartik-09696463/logo.png', 'public://color/bartik-09696463/colors.css')), -)) + 'name' => 'color_bartik_files', + 'value' => serialize(array('public://color/bartik-09696463/logo.png', 'public://color/bartik-09696463/colors.css')), + )) ->values(array( - 'name' => 'color_bartik_logo', - 'value' => serialize('public://color/bartik-09696463/logo.png'), -)) + 'name' => 'color_bartik_logo', + 'value' => serialize('public://color/bartik-09696463/logo.png'), + )) ->values(array( - 'name' => 'color_bartik_palette', - 'value' => serialize($palette), -)) + 'name' => 'color_bartik_palette', + 'value' => serialize($palette), + )) ->values(array( - 'name' => 'color_bartik_stylesheets', - 'value' => serialize('public://color/bartik-09696463/colors.css'), -)) + 'name' => 'color_bartik_stylesheets', + 'value' => serialize('public://color/bartik-09696463/colors.css'), + )) ->execute(); // color module with faked seven upgrade path to test screenshot option db_insert('variable')->fields(array( - 'name', - 'value', -)) + 'name', + 'value', + )) ->values(array( - 'name' => 'color_seven_files', - 'value' => serialize(array('public://color/seven-09696463/logo.png', 'public://color/seven-09696463/colors.css')), -)) + 'name' => 'color_seven_files', + 'value' => serialize(array('public://color/seven-09696463/logo.png', 'public://color/seven-09696463/colors.css')), + )) ->values(array( - 'name' => 'color_seven_logo', - 'value' => serialize('public://color/seven-09696463/logo.png'), -)) + 'name' => 'color_seven_logo', + 'value' => serialize('public://color/seven-09696463/logo.png'), + )) ->values(array( - 'name' => 'color_seven_palette', - 'value' => serialize($palette), -)) + 'name' => 'color_seven_palette', + 'value' => serialize($palette), + )) ->values(array( - 'name' => 'color_seven_stylesheets', - 'value' => serialize('public://color/seven-09696463/colors.css'), -)) + 'name' => 'color_seven_stylesheets', + 'value' => serialize('public://color/seven-09696463/colors.css'), + )) ->values(array( - 'name' => 'color_seven_screenshot', - 'value' => serialize('public://color/seven-09696463/dummy-screenshot.png'), -)) + 'name' => 'color_seven_screenshot', + 'value' => serialize('public://color/seven-09696463/dummy-screenshot.png'), + )) ->execute();