Update to drupal 8.0.0-rc1. For more information, see https://www.drupal.org/node/2582663

This commit is contained in:
Greg Anderson 2015-10-08 11:40:12 -07:00
parent eb34d130a8
commit f32e58e4b1
8476 changed files with 211648 additions and 170042 deletions

View file

@ -23,12 +23,12 @@ function content_translation_install() {
function content_translation_enable() {
// Translation works when at least two languages are added.
if (count(\Drupal::languageManager()->getLanguages()) < 2) {
$t_args = array('!language_url' => \Drupal::url('entity.configurable_language.collection'));
$message = t('Be sure to <a href="!language_url">add at least two languages</a> to translate content.', $t_args);
$t_args = array(':language_url' => \Drupal::url('entity.configurable_language.collection'));
$message = t('Be sure to <a href=":language_url">add at least two languages</a> to translate content.', $t_args);
drupal_set_message($message, 'warning');
}
// Point the user to the content translation settings.
$t_args = array('!settings_url' => \Drupal::url('language.content_settings_page'));
$message = t('<a href="!settings_url">Enable translation</a> for <em>content types</em>, <em>taxonomy vocabularies</em>, <em>accounts</em>, or any other element you wish to translate.', $t_args);
$t_args = array(':settings_url' => \Drupal::url('language.content_settings_page'));
$message = t('<a href=":settings_url">Enable translation</a> for <em>content types</em>, <em>taxonomy vocabularies</em>, <em>accounts</em>, or any other element you wish to translate.', $t_args);
drupal_set_message($message, 'warning');
}

View file

@ -13,7 +13,7 @@ use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\StringTranslation\TranslationWrapper;
use Drupal\Core\StringTranslation\TranslatableMarkup;
/**
* Implements hook_help().
@ -23,11 +23,11 @@ function content_translation_help($route_name, RouteMatchInterface $route_match)
case 'help.page.content_translation':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('The Content Translation module allows you to translate content, comments, custom blocks, taxonomy terms, users and other <a href="!field_help" title="Field module help, with background on content entities">content entities</a>. Together with the modules <a href="!language">Language</a>, <a href="!config-trans">Configuration Translation</a>, and <a href="!locale">Interface Translation</a>, it allows you to build multilingual websites. For more information, see <a href="!translation-entity">the online documentation for the Content Translation module</a>.', array('!locale' => (\Drupal::moduleHandler()->moduleExists('locale')) ? \Drupal::url('help.page', array('name' => 'locale')) : '#', '!config-trans' => (\Drupal::moduleHandler()->moduleExists('config_translation')) ? \Drupal::url('help.page', array('name' => 'config_translation')) : '#', '!language' => \Drupal::url('help.page', array('name' => 'language')), '!translation-entity' => 'https://www.drupal.org/documentation/modules/translation', '!field_help' => \Drupal::url('help.page', array('name' => 'field')))) . '</p>';
$output .= '<p>' . t('The Content Translation module allows you to translate content, comments, custom blocks, taxonomy terms, users and other <a href=":field_help" title="Field module help, with background on content entities">content entities</a>. Together with the modules <a href=":language">Language</a>, <a href=":config-trans">Configuration Translation</a>, and <a href=":locale">Interface Translation</a>, it allows you to build multilingual websites. For more information, see the <a href=":translation-entity">online documentation for the Content Translation module</a>.', array(':locale' => (\Drupal::moduleHandler()->moduleExists('locale')) ? \Drupal::url('help.page', array('name' => 'locale')) : '#', ':config-trans' => (\Drupal::moduleHandler()->moduleExists('config_translation')) ? \Drupal::url('help.page', array('name' => 'config_translation')) : '#', ':language' => \Drupal::url('help.page', array('name' => 'language')), ':translation-entity' => 'https://www.drupal.org/documentation/modules/translation', ':field_help' => \Drupal::url('help.page', array('name' => 'field')))) . '</p>';
$output .= '<h3>' . t('Uses') . '</h3>';
$output .= '<dl>';
$output .= '<dt>' . t('Enabling translation') . '</dt>';
$output .= '<dd>' . t('In order to translate content, the website must have at least two <a href="!url">languages</a>. When that is the case, you can enable translation for the desired content entities on the <a href="!translation-entity">Content language</a> page. When enabling translation you can choose the default language for content and decide whether to show the language selection field on the content editing forms.', array('!url' => \Drupal::url('entity.configurable_language.collection'), '!translation-entity' => \Drupal::url('language.content_settings_page'), '!language-help' => \Drupal::url('help.page', array('name' => 'language')))) . '</dd>';
$output .= '<dd>' . t('In order to translate content, the website must have at least two <a href=":url">languages</a>. When that is the case, you can enable translation for the desired content entities on the <a href=":translation-entity">Content language</a> page. When enabling translation you can choose the default language for content and decide whether to show the language selection field on the content editing forms.', array(':url' => \Drupal::url('entity.configurable_language.collection'), ':translation-entity' => \Drupal::url('language.content_settings_page'), ':language-help' => \Drupal::url('help.page', array('name' => 'language')))) . '</dd>';
$output .= '<dt>' . t('Enabling field translation') . '</dt>';
$output .= '<dd>' . t('You can define which fields of a content entity can be translated. For example, you might want to translate the title and body field while leaving the image field untranslated. If you exclude a field from being translated, it will still show up in the content editing form, but any changes made to that field will be applied to <em>all</em> translations of that content.') . '</dd>';
$output .= '<dt>' . t('Translating content') . '</dt>';
@ -42,7 +42,7 @@ function content_translation_help($route_name, RouteMatchInterface $route_match)
case 'language.content_settings_page':
$output = '';
if (!\Drupal::languageManager()->isMultilingual()) {
$output .= '<br/>' . t('Before you can translate content, there must be at least two languages added on the <a href="!url">languages administration</a> page.', array('!url' => \Drupal::url('entity.configurable_language.collection')));
$output .= '<br/>' . t('Before you can translate content, there must be at least two languages added on the <a href=":url">languages administration</a> page.', array(':url' => \Drupal::url('entity.configurable_language.collection')));
}
return $output;
}
@ -252,8 +252,8 @@ function content_translation_views_data_alter(array &$data) {
*/
function content_translation_menu_links_discovered_alter(array &$links) {
// Clarify where translation settings are located.
$links['language.content_settings_page']['title'] = new TranslationWrapper('Content language and translation');
$links['language.content_settings_page']['description'] = new TranslationWrapper('Configure language and translation support for content.');
$links['language.content_settings_page']['title'] = new TranslatableMarkup('Content language and translation');
$links['language.content_settings_page']['description'] = new TranslatableMarkup('Configure language and translation support for content.');
}
/**
@ -376,8 +376,8 @@ function content_translation_form_field_config_edit_form_alter(array &$form, For
$toggle_url = \Drupal::url('language.content_settings_page', array(), array(
'query' => \Drupal::destination()->getAsArray(),
));
$form['translatable']['#description'] = t('To configure translation for this field, <a href="@language-settings-url">enable language support</a> for this type.', array(
'@language-settings-url' => $toggle_url,
$form['translatable']['#description'] = t('To configure translation for this field, <a href=":language-settings-url">enable language support</a> for this type.', array(
':language-settings-url' => $toggle_url,
));
}
@ -471,7 +471,14 @@ function content_translation_language_configuration_element_process(array $eleme
);
$submit_name = isset($form['actions']['save_continue']) ? 'save_continue' : 'submit';
$form['actions'][$submit_name]['#submit'][] = 'content_translation_language_configuration_element_submit';
// Only add the submit handler on the submit button if the #submit property
// is already available, otherwise this breaks the form submit function.
if (isset($form['actions'][$submit_name]['#submit'])) {
$form['actions'][$submit_name]['#submit'][] = 'content_translation_language_configuration_element_submit';
}
else {
$form['#submit'][] = 'content_translation_language_configuration_element_submit';
}
}
return $element;
}

View file

@ -479,6 +479,13 @@ class ContentTranslationHandler implements ContentTranslationHandlerInterface, E
if (isset($form['actions']['delete'])) {
$form['actions']['delete']['#submit'][] = array($this, 'entityFormDelete');
}
// Handle entity form submission before the entity has been saved.
foreach (Element::children($form['actions']) as $action) {
if (isset($form['actions'][$action]['#type']) && $form['actions'][$action]['#type'] == 'submit') {
array_unshift($form['actions'][$action]['#submit'], [$this, 'entityFormSubmit']);
}
}
}
/**
@ -579,7 +586,6 @@ class ContentTranslationHandler implements ContentTranslationHandlerInterface, E
$metadata->setAuthor(!empty($values['uid']) ? User::load($values['uid']) : User::load(0));
$metadata->setPublished(!empty($values['status']));
$metadata->setCreatedTime(!empty($values['created']) ? strtotime($values['created']) : REQUEST_TIME);
$metadata->setChangedTime(REQUEST_TIME);
$source_langcode = $this->getSourceLangcode($form_state);
if ($source_langcode) {
@ -611,6 +617,30 @@ class ContentTranslationHandler implements ContentTranslationHandlerInterface, E
}
}
/**
* Form submission handler for ContentTranslationHandler::entityFormAlter().
*
* Updates metadata fields, which should be updated only after the validation
* has run and before the entity is saved.
*/
function entityFormSubmit($form, FormStateInterface $form_state) {
/** @var \Drupal\Core\Entity\ContentEntityFormInterface $form_object */
$form_object = $form_state->getFormObject();
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity = $form_object->getEntity();
// ContentEntityForm::submit will update the changed timestamp on submit
// after the entity has been validated, so that it does not break the
// EntityChanged constraint validator. The content translation metadata
// field for the changed timestamp does not have such a constraint defined
// at the moment, but it is correct to update it's value in a submission
// handler as well and have the same logic like in the Form API.
if ($entity->hasField('content_translation_changed')) {
$metadata = $this->manager->getTranslationMetadata($entity);
$metadata->setChangedTime(REQUEST_TIME);
}
}
/**
* Form submission handler for ContentTranslationHandler::entityFormAlter().
*

View file

@ -31,6 +31,7 @@ class ContentTestTranslationUITest extends ContentTranslationUITestBase {
*/
protected $defaultCacheContexts = [
'languages:language_interface',
'session',
'theme',
'url.path',
'url.query_args',

View file

@ -39,11 +39,11 @@ class ContentTranslationConfigImportTest extends KernelTestBase {
parent::setUp();
$this->installEntitySchema('entity_test_mul');
$this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.staging'));
$this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.sync'));
// Set up the ConfigImporter object for testing.
$storage_comparer = new StorageComparer(
$this->container->get('config.storage.staging'),
$this->container->get('config.storage.sync'),
$this->container->get('config.storage'),
$this->container->get('config.manager')
);
@ -68,7 +68,7 @@ class ContentTranslationConfigImportTest extends KernelTestBase {
$config_id = $entity_type_id . '.' . $entity_type_id;
$config_name = 'language.content_settings.' . $config_id;
$storage = $this->container->get('config.storage');
$staging = $this->container->get('config.storage.staging');
$sync = $this->container->get('config.storage.sync');
// Verify the configuration to create does not exist yet.
$this->assertIdentical($storage->exists($config_name), FALSE, $config_name . ' not found.');
@ -90,8 +90,8 @@ class ContentTranslationConfigImportTest extends KernelTestBase {
'content_translation' => array('enabled' => TRUE),
),
);
$staging->write($config_name, $data);
$this->assertIdentical($staging->exists($config_name), TRUE, $config_name . ' found.');
$sync->write($config_name, $data);
$this->assertIdentical($sync->exists($config_name), TRUE, $config_name . ' found.');
// Import.
$this->configImporter->reset()->import();

View file

@ -217,6 +217,11 @@ class ContentTranslationSettingsTest extends WebTestBase {
$this->drupalPostForm('admin/config/people/accounts', $edit, t('Save configuration'));
$this->drupalGet('admin/config/people/accounts');
$this->assertFieldChecked('edit-language-content-translation');
// Make sure account settings can be saved.
$this->drupalPostForm('admin/config/people/accounts', array('anonymous' => 'Save me please!'), 'Save configuration');
$this->assertFieldByName('anonymous', 'Save me please!', 'Anonymous name has been changed.');
$this->assertText('The configuration options have been saved.');
}
/**

View file

@ -77,4 +77,13 @@ class ContentTranslationStandardFieldsTest extends WebTestBase {
$this->assertFieldByXPath("//input[@id='edit-settings-user-user-fields-user-picture' and @checked='checked']");
}
/**
* Test that revision_log is not translatable.
*/
public function testRevisionLogNotTranslatable() {
$path = 'admin/config/regional/content-language';
$this->drupalGet($path);
$this->assertNoFieldByXPath("//input[@id='edit-settings-node-article-fields-revision-log']");
}
}

View file

@ -160,7 +160,7 @@ class ContentTranslationSyncImageTest extends ContentTranslationTestBase {
// items will be one less than the original values to check that only the
// translated ones will be preserved. In fact we want the same fids and
// items order for both languages.
$translation = $entity->getTranslation($langcode);
$translation = $entity->addTranslation($langcode);
for ($delta = 0; $delta < $this->cardinality - 1; $delta++) {
// Simulate a field reordering: items are shifted of one position ahead.
// The modulo operator ensures we start from the beginning after reaching

View file

@ -65,6 +65,7 @@ abstract class ContentTranslationUITestBase extends ContentTranslationTestBase {
$this->doTestAuthoringInfo();
$this->doTestTranslationEdit();
$this->doTestTranslationChanged();
$this->doTestChangedTimeAfterSaveWithoutChanges();
$this->doTestTranslationDeletion();
}
@ -316,7 +317,7 @@ abstract class ContentTranslationUITestBase extends ContentTranslationTestBase {
'content_translation[created]' => '19/11/1978',
);
$this->drupalPostForm($entity->urlInfo('edit-form'), $edit, $this->getFormSubmitAction($entity, $langcode));
$this->assertTrue($this->xpath('//div[contains(concat(" ", normalize-space(@class), " "), :class)]', array(':class' => ' messages--error ')), 'Invalid values generate a form error message.');
$this->assertTrue($this->xpath('//div[contains(@class, "error")]//ul'), 'Invalid values generate a list of form errors.');
$metadata = $this->manager->getTranslationMetadata($entity->getTranslation($langcode));
$this->assertEqual($metadata->getAuthor()->id(), $values[$langcode]['uid'], 'Translation author correctly kept.');
$this->assertEqual($metadata->getCreatedTime(), $values[$langcode]['created'], 'Translation date correctly kept.');
@ -546,4 +547,30 @@ abstract class ContentTranslationUITestBase extends ContentTranslationTestBase {
}
}
/**
* Test the changed time after API and FORM save without changes.
*/
public function doTestChangedTimeAfterSaveWithoutChanges() {
$entity = entity_load($this->entityTypeId, $this->entityId, TRUE);
// Test only entities, which implement the EntityChangedInterface.
if ($entity->getEntityType()->isSubclassOf('Drupal\Core\Entity\EntityChangedInterface')) {
$changed_timestamp = $entity->getChangedTime();
$entity->save();
$entity = entity_load($this->entityTypeId, $this->entityId, TRUE);
$this->assertEqual($changed_timestamp, $entity->getChangedTime(), 'The entity\'s changed time wasn\'t updated after API save without changes.');
// Ensure different save timestamps.
sleep(1);
// Save the entity on the regular edit form.
$language = $entity->language();
$edit_path = $entity->urlInfo('edit-form', array('language' => $language));
$this->drupalPostForm($edit_path, [], $this->getFormSubmitAction($entity, $language->getId()));
$entity = entity_load($this->entityTypeId, $this->entityId, TRUE);
$this->assertNotEqual($changed_timestamp, $entity->getChangedTime(), 'The entity\'s changed time was updated after form save without changes.');
}
}
}

View file

@ -40,6 +40,7 @@ class ContentTranslationManageAccessCheckTest extends UnitTestCase {
$this->cacheContextsManager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
->disableOriginalConstructor()
->getMock();
$this->cacheContextsManager->method('assertValidTokens')->willReturn(TRUE);
$container = new ContainerBuilder();
$container->set('cache_contexts_manager', $this->cacheContextsManager);