Update to Drupal 8.0.5. For more information, see https://www.drupal.org/node/2679347

This commit is contained in:
Pantheon Automation 2016-03-02 12:40:24 -08:00 committed by Greg Anderson
parent 2a9f1f148d
commit fd3b12cf27
251 changed files with 5439 additions and 957 deletions

View file

@ -18,7 +18,7 @@
}
.progress__bar {
background-color: #000;
height: 1.5em;
height: 16px;
width: 3%;
min-width: 3%;
max-width: 100%;

View file

@ -245,8 +245,8 @@ class SystemController extends ControllerBase {
// content has a common place in all themes.
$theme->incompatible_region = !isset($theme->info['regions']['content']);
$theme->incompatible_php = version_compare(phpversion(), $theme->info['php']) < 0;
// Confirmed that the base theme is available.
$theme->incompatible_base = isset($theme->info['base theme']) && !isset($themes[$theme->info['base theme']]);
// Confirm that all base themes are available.
$theme->incompatible_base = (isset($theme->info['base theme']) && !($theme->base_themes === array_filter($theme->base_themes)));
// Confirm that the theme engine is available.
$theme->incompatible_engine = isset($theme->info['engine']) && !isset($theme->owner);
}

View file

@ -0,0 +1,38 @@
<?php
/**
* @file
* Contains \Drupal\system\Tests\Ajax\AjaxInGroupTest.
*/
namespace Drupal\system\Tests\Ajax;
use Drupal\Core\Ajax\DataCommand;
/**
* Tests that form elements in groups work correctly with AJAX.
*
* @group Ajax
*/
class AjaxInGroupTest extends AjaxTestBase {
protected function setUp() {
parent::setUp();
$this->drupalLogin($this->drupalCreateUser(array('access content')));
}
/**
* Submits forms with select and checkbox elements via Ajax.
*/
function testSimpleAjaxFormValue() {
$this->drupalGet('/ajax_forms_test_get_form');
$this->assertText('Test group');
$this->assertText('AJAX checkbox in a group');
$this->drupalPostAjaxForm(NULL, ['checkbox_in_group' => TRUE], 'checkbox_in_group');
$this->assertText('Test group');
$this->assertText('AJAX checkbox in a group');
$this->assertText('AJAX checkbox in a nested group');
$this->assertText('Another AJAX checkbox in a nested group');
}
}

View file

@ -492,5 +492,124 @@ class TransactionTest extends DatabaseTestBase {
$this->assertRowAbsent('inner');
$this->assertRowAbsent('inner2');
}
}
/**
* Tests that transactions can continue to be used if a query fails.
*/
public function testQueryFailureInTransaction() {
$connection = Database::getConnection();
$transaction = $connection->startTransaction('test_transaction');
$connection->schema()->dropTable('test');
// Test a failed query using the query() method.
try {
$connection->query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'David'))->fetchField();
$this->fail('Using the query method failed.');
}
catch (\Exception $e) {
$this->pass('Using the query method failed.');
}
// Test a failed select query.
try {
$connection->select('test')
->fields('test', ['name'])
->execute();
$this->fail('Select query failed.');
}
catch (\Exception $e) {
$this->pass('Select query failed.');
}
// Test a failed insert query.
try {
$connection->insert('test')
->fields([
'name' => 'David',
'age' => '24',
])
->execute();
$this->fail('Insert query failed.');
}
catch (\Exception $e) {
$this->pass('Insert query failed.');
}
// Test a failed update query.
try {
$connection->update('test')
->fields(['name' => 'Tiffany'])
->condition('id', 1)
->execute();
$this->fail('Update query failed.');
}
catch (\Exception $e) {
$this->pass('Update query failed.');
}
// Test a failed delete query.
try {
$connection->delete('test')
->condition('id', 1)
->execute();
$this->fail('Delete query failed.');
}
catch (\Exception $e) {
$this->pass('Delete query failed.');
}
// Test a failed merge query.
try {
$connection->merge('test')
->key('job', 'Presenter')
->fields([
'age' => '31',
'name' => 'Tiffany',
])
->execute();
$this->fail('Merge query failed.');
}
catch (\Exception $e) {
$this->pass('Merge query failed.');
}
// Test a failed upsert query.
try {
$connection->upsert('test')
->key('job')
->fields(['job', 'age', 'name'])
->values([
'job' => 'Presenter',
'age' => 31,
'name' => 'Tiffany',
])
->execute();
$this->fail('Upset query failed.');
}
catch (\Exception $e) {
$this->pass('Upset query failed.');
}
// Create the missing schema and insert a row.
$this->installSchema('database_test', ['test']);
$connection->insert('test')
->fields(array(
'name' => 'David',
'age' => '24',
))
->execute();
// Commit the transaction.
unset($transaction);
$saved_age = $connection->query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'David'))->fetchField();
$this->assertEqual('24', $saved_age);
}
}

View file

@ -123,7 +123,7 @@ class EntityQueryTest extends EntityUnitTestBase {
// decimal 13 is binary 1101 so unit 3,2 and 0 will be added to the
// entity.
for ($i = 1; $i <= 15; $i++) {
$entity = entity_create('entity_test_mulrev', array(
$entity = EntityTestMulRev::create(array(
'type' => $bundles[$i & 1],
'name' => $this->randomMachineName(),
'langcode' => 'en',

View file

@ -371,6 +371,10 @@ class EntityTranslationTest extends EntityLanguageTestBase {
// Save the translation and check that the expected hooks are fired.
$translation->save();
$hooks = $this->getHooksInfo();
$this->assertEqual($hooks['entity_translation_create'], $langcode, 'The generic entity translation creation hook has fired.');
$this->assertEqual($hooks[$entity_type . '_translation_create'], $langcode, 'The entity-type-specific entity translation creation hook has fired.');
$this->assertEqual($hooks['entity_translation_insert'], $langcode, 'The generic entity translation insertion hook has fired.');
$this->assertEqual($hooks[$entity_type . '_translation_insert'], $langcode, 'The entity-type-specific entity translation insertion hook has fired.');
@ -436,6 +440,10 @@ class EntityTranslationTest extends EntityLanguageTestBase {
$this->assertEqual($entity->language()->getId(), $default_langcode, 'The original language has been preserved.');
$translation->save();
$hooks = $this->getHooksInfo();
$this->assertEqual($hooks['entity_translation_create'], $langcode2, 'The generic entity translation creation hook has fired.');
$this->assertEqual($hooks[$entity_type . '_translation_create'], $langcode2, 'The entity-type-specific entity translation creation hook has fired.');
$this->assertEqual($hooks['entity_translation_insert'], $langcode2, 'The generic entity translation insertion hook has fired.');
$this->assertEqual($hooks[$entity_type . '_translation_insert'], $langcode2, 'The entity-type-specific entity translation insertion hook has fired.');
@ -483,7 +491,13 @@ class EntityTranslationTest extends EntityLanguageTestBase {
$entity->removeTranslation($langcode2);
$entity->save();
$hooks = $this->getHooksInfo();
$this->assertFalse($hooks, 'No hooks are run when adding and removing a translation without storing it.');
$this->assertTrue(isset($hooks['entity_translation_create']), 'The generic entity translation creation hook is run when adding and removing a translation without storing it.');
unset($hooks['entity_translation_create']);
$this->assertTrue(isset($hooks[$entity_type . '_translation_create']), 'The entity-type-specific entity translation creation hook is run when adding and removing a translation without storing it.');
unset($hooks[$entity_type . '_translation_create']);
$this->assertFalse($hooks, 'No other hooks beyond the entity translation creation hooks are run when adding and removing a translation without storing it.');
// Check that hooks are fired only when actually storing data.
$entity = $this->reloadEntity($entity);
@ -554,6 +568,9 @@ class EntityTranslationTest extends EntityLanguageTestBase {
);
$this->assertEqual($translation->description->getValue(), $expected, 'Language-aware default values correctly populated.');
$this->assertEqual($translation->description->getLangcode(), $langcode2, 'Field object has the expected langcode.');
// Reset hook firing information.
$this->getHooksInfo();
}
/**

View file

@ -27,7 +27,7 @@ class UrlRewritingTest extends FileTestBase {
* Tests the rewriting of shipped file URLs by hook_file_url_alter().
*/
function testShippedFileURL() {
// Test generating an URL to a shipped file (i.e. a file that is part of
// Test generating a URL to a shipped file (i.e. a file that is part of
// Drupal core, a module or a theme, for example a JavaScript file).
// Test alteration of file URLs to use a CDN.
@ -74,7 +74,7 @@ class UrlRewritingTest extends FileTestBase {
* Tests the rewriting of public managed file URLs by hook_file_url_alter().
*/
function testPublicManagedFileURL() {
// Test generating an URL to a managed file.
// Test generating a URL to a managed file.
// Test alteration of file URLs to use a CDN.
\Drupal::state()->set('file_test.hook_file_url_alter', 'cdn');

View file

@ -319,6 +319,9 @@ class ThemeTest extends WebTestBase {
/**
* Test themes can't be installed when the base theme or engine is missing.
*
* Include test for themes that have a missing base theme somewhere further up
* the chain than the immediate base theme.
*/
function testInvalidTheme() {
// theme_page_test_system_info_alter() un-hides all hidden themes.
@ -327,6 +330,7 @@ class ThemeTest extends WebTestBase {
$this->container->get('theme_handler')->reset();
$this->drupalGet('admin/appearance');
$this->assertText(t('This theme requires the base theme @base_theme to operate correctly.', array('@base_theme' => 'not_real_test_basetheme')));
$this->assertText(t('This theme requires the base theme @base_theme to operate correctly.', array('@base_theme' => 'test_invalid_basetheme')));
$this->assertText(t('This theme requires the theme engine @theme_engine to operate correctly.', array('@theme_engine' => 'not_real_engine')));
// Check for the error text of a theme with the wrong core version.
$this->assertText("This theme is not compatible with Drupal 8.x. Check that the .info.yml file contains the correct 'core' value.");

View file

@ -82,6 +82,17 @@ class UpdatePathTestBaseTest extends UpdatePathTestBase {
// Increment the schema version.
\Drupal::state()->set('update_test_schema_version', 8001);
$this->runUpdates();
$select = \Drupal::database()->select('watchdog');
$select->orderBy('wid', 'DESC');
$select->range(0, 5);
$select->fields('watchdog', ['message']);
$container_cannot_be_saved_messages = array_filter(iterator_to_array($select->execute()), function($row) {
return strpos($row->message, 'Container cannot be saved to cache.') !== FALSE;
});
$this->assertEqual([], $container_cannot_be_saved_messages);
// Ensure schema has changed.
$this->assertEqual(drupal_get_installed_schema_version('update_test_schema', TRUE), 8001);
// Ensure the index was added for column a.

View file

@ -8,6 +8,7 @@
namespace Drupal\system\Tests\Update;
use Drupal\Core\Url;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\simpletest\WebTestBase;
/**
@ -22,7 +23,7 @@ class UpdateScriptTest extends WebTestBase {
*
* @var array
*/
public static $modules = array('update_script_test', 'dblog');
public static $modules = array('update_script_test', 'dblog', 'language');
/**
* {@inheritdoc}
@ -218,6 +219,57 @@ class UpdateScriptTest extends WebTestBase {
$this->assertEqual($final_maintenance_mode, $initial_maintenance_mode, 'Maintenance mode should not have changed after database updates.');
}
/**
* Tests perfoming updates with update.php in a multilingual environment.
*/
function testSuccessfulMultilingualUpdateFunctionality() {
// Add some custom languages.
foreach (array('aa', 'bb') as $language_code) {
ConfigurableLanguage::create(array(
'id' => $language_code,
'label' => $this->randomMachineName(),
))->save();
}
$config = \Drupal::service('config.factory')->getEditable('language.negotiation');
// Ensure path prefix is used to determine the language.
$config->set('url.source', 'path_prefix');
// Ensure that there's a path prefix set for english as well.
$config->set('url.prefixes.en', 'en');
$config->save();
// Reset the static cache to ensure we have the most current setting.
$schema_version = drupal_get_installed_schema_version('update_script_test', TRUE);
$this->assertEqual($schema_version, 8001, 'update_script_test schema version is 8001 after updating.');
// Set the installed schema version to one less than the current update.
drupal_set_installed_schema_version('update_script_test', $schema_version - 1);
$schema_version = drupal_get_installed_schema_version('update_script_test', TRUE);
$this->assertEqual($schema_version, 8000, 'update_script_test schema version overridden to 8000.');
// Create admin user.
$admin_user = $this->drupalCreateUser(array('administer software updates', 'access administration pages', 'access site reports', 'access site in maintenance mode', 'administer site configuration'));
$this->drupalLogin($admin_user);
// Visit status report page and ensure, that link to update.php has no path prefix set.
$this->drupalGet('en/admin/reports/status', array('external' => TRUE));
$this->assertResponse(200);
$this->assertLinkByHref('/update.php');
$this->assertNoLinkByHref('en/update.php');
// Click through update.php with 'access administration pages' and
// 'access site reports' permissions.
$this->drupalGet($this->updateUrl, array('external' => TRUE));
$this->clickLink(t('Continue'));
$this->clickLink(t('Apply pending updates'));
$this->assertText('Updates were attempted.');
$this->assertLink('logged');
$this->assertLink('Administration pages');
$this->assertNoLinkByHrefInMainRegion('update.php', 1);
$this->clickLink('Administration pages');
$this->assertResponse(200);
}
/**
* Helper function to run updates via the browser.
*/

View file

@ -1412,22 +1412,24 @@ function system_block_view_system_main_block_alter(array &$build, BlockPluginInt
/**
* Implements hook_path_update().
*/
function system_path_update() {
\Drupal::service('path.alias_manager')->cacheClear();
function system_path_update($path) {
$alias_manager = \Drupal::service('path.alias_manager');
$alias_manager->cacheClear($path['source']);
$alias_manager->cacheClear($path['original']['source']);
}
/**
* Implements hook_path_insert().
*/
function system_path_insert() {
\Drupal::service('path.alias_manager')->cacheClear();
function system_path_insert($path) {
\Drupal::service('path.alias_manager')->cacheClear($path['source']);
}
/**
* Implements hook_path_delete().
*/
function system_path_delete($path) {
\Drupal::service('path.alias_manager')->cacheClear();
\Drupal::service('path.alias_manager')->cacheClear($path['source']);
}
/**

View file

@ -456,6 +456,9 @@ system.db_update:
op: 'info'
requirements:
_access: 'TRUE'
options:
default_url_options:
path_processing: FALSE
system.admin_content:
path: '/admin/content'

View file

@ -5,7 +5,7 @@
*
* Available variables
* - attributes: A list of HTML attributes for the wrapper element.
* - children: The rendered checkboxes.
* - children: The rendered tabs.
*
* @see template_preprocess_vertical_tabs()
*

View file

@ -36,4 +36,12 @@ class Callbacks {
$response->addCommand(new DataCommand('#ajax_checkbox_value', 'form_state_value_select', (int) $form_state->getValue('checkbox')));
return $response;
}
/**
* Ajax callback triggered by the checkbox in a #group.
*/
function checkboxGroupCallback($form, FormStateInterface $form_state) {
return $form['checkbox_in_group_wrapper'];
}
}

View file

@ -72,6 +72,48 @@ class AjaxFormsTestSimpleForm extends FormBase {
);
}
$form['test_group'] = [
'#type' => 'details',
'#title' => $this->t('Test group'),
'#open' => TRUE,
];
// Test ajax element in a #group.
$form['checkbox_in_group_wrapper'] = [
'#type' => 'container',
'#attributes' => ['id' => 'checkbox-wrapper'],
'#group' => 'test_group',
'checkbox_in_group' => [
'#type' => 'checkbox',
'#title' => $this->t('AJAX checkbox in a group'),
'#ajax' => [
'callback' => [$object, 'checkboxGroupCallback'],
'wrapper' => 'checkbox-wrapper',
],
],
'nested_group' => [
'#type' => 'details',
'#title' => $this->t('Nested group'),
'#open' => TRUE,
],
'checkbox_in_nested' => [
'#type' => 'checkbox',
'#group' => 'nested_group',
'#title' => $this->t('AJAX checkbox in a nested group'),
'#ajax' => [
'callback' => [$object, 'checkboxGroupCallback'],
'wrapper' => 'checkbox-wrapper',
],
],
];
$form['another_checkbox_in_nested'] = [
'#type' => 'checkbox',
'#group' => 'nested_group',
'#title' => $this->t('Another AJAX checkbox in a nested group'),
];
return $form;
}

View file

@ -384,10 +384,13 @@ function entity_test_entity_field_access($operation, FieldDefinitionInterface $f
if ($field_definition->getName() == 'field_test_text') {
if ($items) {
if ($items->value == 'no access value') {
return AccessResult::forbidden()->cacheUntilEntityChanges($items->getEntity());
return AccessResult::forbidden()->addCacheableDependency($items->getEntity());
}
elseif ($items->value == 'custom cache tag value') {
return AccessResult::allowed()->addCacheableDependency($items->getEntity())->addCacheTags(['entity_test_access:field_test_text']);
}
elseif ($operation == 'edit' && $items->value == 'no edit access value') {
return AccessResult::forbidden()->cacheUntilEntityChanges($items->getEntity());
return AccessResult::forbidden()->addCacheableDependency($items->getEntity());
}
}
}
@ -471,6 +474,13 @@ function entity_test_entity_operation_alter(array &$operations, EntityInterface
}
}
/**
* Implements hook_entity_translation_create().
*/
function entity_test_entity_translation_create(EntityInterface $translation) {
_entity_test_record_hooks('entity_translation_create', $translation->language()->getId());
}
/**
* Implements hook_entity_translation_insert().
*/
@ -485,6 +495,13 @@ function entity_test_entity_translation_delete(EntityInterface $translation) {
_entity_test_record_hooks('entity_translation_delete', $translation->language()->getId());
}
/**
* Implements hook_ENTITY_TYPE_translation_create() for 'entity_test_mul'.
*/
function entity_test_entity_test_mul_translation_create(EntityInterface $translation) {
_entity_test_record_hooks('entity_test_mul_translation_create', $translation->language()->getId());
}
/**
* Implements hook_ENTITY_TYPE_translation_insert() for 'entity_test_mul'.
*/
@ -500,7 +517,14 @@ function entity_test_entity_test_mul_translation_delete(EntityInterface $transla
}
/**
* Implements hook_ENTITY_TYPE_translation_insert() for 'entity_test_mulrev'.
* Implements hook_ENTITY_TYPE_translation_create() for 'entity_test_mul_changed'.
*/
function entity_test_entity_test_mul_changed_translation_create(EntityInterface $translation) {
_entity_test_record_hooks('entity_test_mul_changed_translation_create', $translation->language()->getId());
}
/**
* Implements hook_ENTITY_TYPE_translation_insert() for 'entity_test_mul_changed'.
*/
function entity_test_entity_test_mul_changed_translation_insert(EntityInterface $translation) {
_entity_test_record_hooks('entity_test_mul_changed_translation_insert', $translation->language()->getId());
@ -513,6 +537,13 @@ function entity_test_entity_test_mul_changed_translation_delete(EntityInterface
_entity_test_record_hooks('entity_test_mul_changed_translation_delete', $translation->language()->getId());
}
/**
* Implements hook_ENTITY_TYPE_translation_create().
*/
function entity_test_entity_test_mulrev_translation_create(EntityInterface $translation) {
_entity_test_record_hooks('entity_test_mulrev_translation_create', $translation->language()->getId());
}
/**
* Implements hook_ENTITY_TYPE_translation_insert().
*/
@ -527,6 +558,13 @@ function entity_test_entity_test_mulrev_translation_delete(EntityInterface $tran
_entity_test_record_hooks('entity_test_mulrev_translation_delete', $translation->language()->getId());
}
/**
* Implements hook_ENTITY_TYPE_translation_create() for 'entity_test_mulrev_changed'.
*/
function entity_test_entity_test_mulrev_changed_translation_create(EntityInterface $translation) {
_entity_test_record_hooks('entity_test_mulrev_changed_translation_create', $translation->language()->getId());
}
/**
* Implements hook_ENTITY_TYPE_translation_insert() for 'entity_test_mulrev'.
*/
@ -541,6 +579,13 @@ function entity_test_entity_test_mulrev_changed_translation_delete(EntityInterfa
_entity_test_record_hooks('entity_test_mulrev_changed_translation_delete', $translation->language()->getId());
}
/**
* Implements hook_ENTITY_TYPE_translation_create() for 'entity_test_mul_langcode_key'.
*/
function entity_test_entity_test_mul_langcode_key_translation_create(EntityInterface $translation) {
_entity_test_record_hooks('entity_test_mul_langcode_key_translation_create', $translation->language()->getId());
}
/**
* Implements hook_ENTITY_TYPE_translation_insert() for 'entity_test_mul_langcode_key'.
*/

View file

@ -2,7 +2,7 @@
/**
* @file
* Contains \Drupal\system\Tests\Extension\ModuleHandlerTest.
* Contains \Drupal\Tests\system\Kernel\Extension\ModuleHandlerTest.
*/
namespace Drupal\Tests\system\Kernel\Extension;

View file

@ -0,0 +1,62 @@
<?php
/**
* @file
* Contains \Drupal\Tests\system\Kernel\PathHooksTest.
*/
namespace Drupal\Tests\system\Kernel;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Path\AliasManagerInterface;
use Drupal\KernelTests\KernelTestBase;
use Prophecy\Argument;
/**
* @group Drupal
*/
class PathHooksTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
static public $modules = ['system'];
/**
* Test system_path_*() correctly clears caches.
*/
public function testPathHooks() {
$this->installSchema('system', ['url_alias']);
$source = '/' . $this->randomMachineName();
$alias = '/' . $this->randomMachineName();
// Check system_path_insert();
$alias_manager = $this->prophesize(AliasManagerInterface::class);
$alias_manager->cacheClear(Argument::any())->shouldBeCalledTimes(1);
$alias_manager->cacheClear($source)->shouldBeCalledTimes(1);
\Drupal::getContainer()->set('path.alias_manager', $alias_manager->reveal());
$alias_storage = \Drupal::service('path.alias_storage');
$alias_storage->save($source, $alias);
$new_source = '/' . $this->randomMachineName();
$path = $alias_storage->load(['source' => $source]);
// Check system_path_update();
$alias_manager = $this->prophesize(AliasManagerInterface::class);
$alias_manager->cacheClear(Argument::any())->shouldBeCalledTimes(2);
$alias_manager->cacheClear($source)->shouldBeCalledTimes(1);
$alias_manager->cacheClear($new_source)->shouldBeCalledTimes(1);
\Drupal::getContainer()->set('path.alias_manager', $alias_manager->reveal());
$alias_storage->save($new_source, $alias, LanguageInterface::LANGCODE_NOT_SPECIFIED, $path['pid']);
// Check system_path_delete();
$alias_manager = $this->prophesize(AliasManagerInterface::class);
$alias_manager->cacheClear(Argument::any())->shouldBeCalledTimes(1);
$alias_manager->cacheClear($new_source)->shouldBeCalledTimes(1);
\Drupal::getContainer()->set('path.alias_manager', $alias_manager->reveal());
$alias_storage->delete(['pid' => $path['pid']]);
}
}

View file

@ -2,7 +2,7 @@
/**
* @file
* Contains \Drupal\system\Tests\PhpStorage\PhpStorageFactoryTest.
* Contains \Drupal\Tests\system\Kernel\PhpStorage\PhpStorageFactoryTest.
*/
namespace Drupal\Tests\system\Kernel\PhpStorage;

View file

@ -57,6 +57,7 @@ class DbDumpCommandTest extends KernelTestBase {
$this->assertContains("'name' => 'test", $output, 'Insert name field found');
$this->assertContains("'path' => 'test", $output, 'Insert path field found');
$this->assertContains("'pattern_outline' => 'test", $output, 'Insert pattern_outline field found');
$this->assertContains("// @codingStandardsIgnoreFile", $output);
}
/**

View file

@ -0,0 +1,6 @@
name: 'Theme test with valid base theme but no grandparent base theme'
type: theme
description: 'Test theme which has a non-existent base theme in the base chain.'
version: VERSION
core: 8.x
base theme: test_invalid_basetheme

View file

@ -0,0 +1,13 @@
<?php
/**
* @file
* Test preprocess functions for theme test_stable.
*/
/**
* Implements hook_preprocess_theme_test_render_element().
*/
function test_stable_preprocess_theme_test_render_element($variables) {
// This is used for Drupal\Tests\Core\Theme\RegistryTest.
}