diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampFormatter.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampFormatter.php
new file mode 100644
index 0000000..6861a00
--- /dev/null
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/TimestampFormatter.php
@@ -0,0 +1,40 @@
+ $item) {
+ $elements[$delta] = array('#markup' => format_date($item->value));
+ }
+
+ return $elements;
+ }
+
+}
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/BooleanItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/BooleanItem.php
index 14d0f83..f2951ac 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/BooleanItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/BooleanItem.php
@@ -18,7 +18,8 @@
* id = "boolean",
* label = @Translation("Boolean"),
* description = @Translation("An entity field containing a boolean value."),
- * no_ui = TRUE
+ * no_ui = TRUE,
+ * default_widget = "boolean",
* )
*/
class BooleanItem extends FieldItemBase {
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/CreatedItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/CreatedItem.php
index 9b2e055..72c0ea9 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/CreatedItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/CreatedItem.php
@@ -14,7 +14,9 @@
* id = "created",
* label = @Translation("Created"),
* description = @Translation("An entity field containing a UNIX timestamp of when the entity has been created."),
- * no_ui = TRUE
+ * no_ui = TRUE,
+ * default_widget = "timestamp",
+ * default_formatter = "timestamp",
* )
*/
class CreatedItem extends TimestampItem {
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/TimestampItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/TimestampItem.php
index ba432e3..72f71a2 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/TimestampItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/TimestampItem.php
@@ -18,7 +18,9 @@
* id = "timestamp",
* label = @Translation("Timestamp"),
* description = @Translation("An entity field containing a UNIX timestamp value."),
- * no_ui = TRUE
+ * no_ui = TRUE,
+ * default_widget = "timestamp",
+ * default_formatter = "timestamp",
* )
*/
class TimestampItem extends FieldItemBase {
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/BooleanWidget.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/BooleanWidget.php
new file mode 100644
index 0000000..66f4d07
--- /dev/null
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/BooleanWidget.php
@@ -0,0 +1,38 @@
+ 'checkbox',
+ '#default_value' => isset($items[$delta]->value) ? $items[$delta]->value : NULL,
+ );
+
+ return $element;
+ }
+
+}
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/RouteBasedAutocompleteWidget.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/RouteBasedAutocompleteWidget.php
new file mode 100644
index 0000000..cf8b2c3
--- /dev/null
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/RouteBasedAutocompleteWidget.php
@@ -0,0 +1,48 @@
+ '',
+ ) + parent::defaultSettings();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, array &$form_state) {
+ $element['target_id'] = $element + array(
+ '#type' => 'textfield',
+ '#default_value' => $items[$delta]->value,
+ '#autocomplete_route_name' => $this->getSetting('route_name'),
+ );
+
+ return $element;
+ }
+
+}
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/TimestampWidget.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/TimestampWidget.php
new file mode 100644
index 0000000..fc487de
--- /dev/null
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/TimestampWidget.php
@@ -0,0 +1,86 @@
+ FALSE
+ ) + parent::defaultSettings();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, array &$form_state) {
+ $default_value = isset($items[$delta]->value) ? format_date($items[$delta]->value, 'custom', 'Y-m-d H:i:s O') : '';
+ $element['value'] = $element + array(
+ '#type' => 'textfield',
+ '#default_value' => $default_value,
+ '#maxlength' => 25,
+ '#element_validate' => array(
+ array($this, 'elementValidate'),
+ ),
+ );
+
+ if (!empty($default_value)) {
+ $example_time = date_format(date_create($default_value), 'Y-m-d H:i:s O');
+ $timezone = date_format(date_create($default_value), 'O');
+ }
+ else {
+ $example_time = format_date(REQUEST_TIME, 'custom', 'Y-m-d H:i:s O');
+ $timezone = format_date(REQUEST_TIME, 'custom', 'O');
+ }
+ $element['value']['#description'] = $this->t('Format: %time. The date format is YYYY-MM-DD and %timezone is the time zone offset from UTC. Leave blank to use the time of form submission.', array('%time' => $example_time, '%timezone' => $timezone));
+
+ return $element;
+ }
+
+ /**
+ * Validates an element.
+ *
+ * @todo Convert to massageFormValues() after https://drupal.org/node/2226723 lands.
+ */
+ public function elementValidate($element, &$form_state, $form) {
+ $value = trim($element['#value']);
+ if (empty($value)) {
+ $value = $this->getSetting('use_request_time_on_empty') ? REQUEST_TIME : 0;
+ }
+ else {
+ $date = new DrupalDateTime($value);
+ if ($date->hasErrors()) {
+ $value = FALSE;
+ }
+ else {
+ $value = $date->getTimestamp();
+ }
+ }
+ form_set_value($element, $value, $form_state);
+ }
+
+}
diff --git a/core/modules/content_translation/src/ContentTranslationHandler.php b/core/modules/content_translation/src/ContentTranslationHandler.php
index 500ae49..d17fa92 100644
--- a/core/modules/content_translation/src/ContentTranslationHandler.php
+++ b/core/modules/content_translation/src/ContentTranslationHandler.php
@@ -416,7 +416,7 @@ function entityFormValidate($form, &$form_state) {
if (!empty($translation['name']) && !($account = user_load_by_name($translation['name']))) {
form_set_error('content_translation][name', $form_state, t('The translation authoring username %name does not exist.', array('%name' => $translation['name'])));
}
- // Validate the "authored on" field.
+ // Validate the "created on" field.
if (!empty($translation['created']) && strtotime($translation['created']) === FALSE) {
form_set_error('content_translation][created', $form_state, t('You have to specify a valid translation authoring date.'));
}
diff --git a/core/modules/datetime/datetime.module b/core/modules/datetime/datetime.module
index b5f98dd..058a027 100644
--- a/core/modules/datetime/datetime.module
+++ b/core/modules/datetime/datetime.module
@@ -999,21 +999,13 @@ function datetime_range_years($string, $date = NULL) {
}
/**
- * Implements hook_form_BASE_FORM_ID_alter() for node forms.
+ * Implements hook_entity_base_field_info_alter().
*/
-function datetime_form_node_form_alter(&$form, &$form_state, $form_id) {
- // Alter the 'Authored on' date to use datetime.
- $form['created']['#type'] = 'datetime';
- $date_format = entity_load('date_format', 'html_date')->getPattern();
- $time_format = entity_load('date_format', 'html_time')->getPattern();
- $form['created']['#description'] = t('Format: %format. Leave blank to use the time of form submission.', array('%format' => datetime_format_example($date_format . ' ' . $time_format)));
- unset($form['created']['#maxlength']);
-}
-
-/**
- * Implements hook_node_prepare_form().
- */
-function datetime_node_prepare_form(NodeInterface $node, $operation, array &$form_state) {
- // Prepare the 'Authored on' date to use datetime.
- $node->date = DrupalDateTime::createFromTimestamp($node->getCreatedTime());
+function datetime_entity_base_field_info_alter(&$fields, \Drupal\Core\Entity\EntityTypeInterface $entity_type) {
+ if ($entity_type->id() == 'node') {
+ $fields['created']->setDisplayOptions('form', array(
+ 'type' => 'datetime_timestamp',
+ 'weight' => 0,
+ ));
+ }
}
diff --git a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeTimestampWidget.php b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeTimestampWidget.php
new file mode 100644
index 0000000..6c50058
--- /dev/null
+++ b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeTimestampWidget.php
@@ -0,0 +1,62 @@
+getPattern();
+ $time_format = entity_load('date_format', 'html_time')->getPattern();
+ $default_value = isset($items[$delta]->value) ? DrupalDateTime::createFromTimestamp($items[$delta]->value) : '';
+ $element['value'] = $element + array(
+ '#type' => 'datetime',
+ '#default_value' => $default_value,
+ '#element_validate' => array(
+ array($this, 'elementValidate'),
+ ),
+ );
+ $element['value']['#description'] = $this->t('Format: %format. Leave blank to use the time of form submission.', array('%format' => datetime_format_example($date_format . ' ' . $time_format)));
+
+ return $element;
+ }
+
+ /**
+ * Validates an element.
+ *
+ * @todo Convert to massageFormValues() after https://drupal.org/node/2226723 lands.
+ */
+ public function elementValidate($element, &$form_state, $form) {
+ $date = $element['#value']['object'];
+ if ($date->hasErrors()) {
+ $value = -1;
+ }
+ else {
+ $value = $date->getTimestamp();
+ }
+ form_set_value($element, $value, $form_state);
+ }
+
+}
diff --git a/core/modules/entity/src/Tests/EntityDisplayTest.php b/core/modules/entity/src/Tests/EntityDisplayTest.php
index f0c8e0c..1fa6341 100644
--- a/core/modules/entity/src/Tests/EntityDisplayTest.php
+++ b/core/modules/entity/src/Tests/EntityDisplayTest.php
@@ -296,7 +296,7 @@ public function testRenameDeleteBundle() {
$expected_dependencies = array(
'entity' => array('field.instance.node.article_rename.body', 'node.type.article_rename'),
- 'module' => array('text')
+ 'module' => array('text', 'user')
);
// Check that the display has dependencies on the bundle, fields and the
// modules that provide the formatters.
diff --git a/core/modules/entity_reference/src/Tests/EntityReferenceIntegrationTest.php b/core/modules/entity_reference/src/Tests/EntityReferenceIntegrationTest.php
index cd6a7b5..bdb45a5 100644
--- a/core/modules/entity_reference/src/Tests/EntityReferenceIntegrationTest.php
+++ b/core/modules/entity_reference/src/Tests/EntityReferenceIntegrationTest.php
@@ -65,6 +65,7 @@ public function setUp() {
* Tests the entity reference field with all its supported field widgets.
*/
public function testSupportedEntityTypesAndWidgets() {
+ $user_id = mt_rand(128, 256);
foreach ($this->getTestEntities() as $referenced_entities) {
$this->fieldName = 'field_test_' . $referenced_entities[0]->getEntityTypeId();
@@ -75,9 +76,14 @@ public function testSupportedEntityTypesAndWidgets() {
entity_get_form_display($this->entityType, $this->bundle, 'default')->setComponent($this->fieldName)->save();
$entity_name = $this->randomName();
+ $user_id++;
+ entity_create('user', array(
+ 'uid' => $user_id,
+ 'name' => $this->randomName(),
+ ))->save();
$edit = array(
'name' => $entity_name,
- 'user_id' => mt_rand(0, 128),
+ 'user_id' => $user_id,
$this->fieldName . '[0][target_id]' => $referenced_entities[0]->label() . ' (' . $referenced_entities[0]->id() . ')',
// Test an input of the entity label without a ' (entity_id)' suffix.
$this->fieldName . '[1][target_id]' => $referenced_entities[1]->label(),
@@ -100,9 +106,14 @@ public function testSupportedEntityTypesAndWidgets() {
$target_id = $referenced_entities[0]->label() . ' (' . $referenced_entities[0]->id() . ')';
// Test an input of the entity label without a ' (entity_id)' suffix.
$target_id .= ', ' . $referenced_entities[1]->label();
+ $user_id++;
+ entity_create('user', array(
+ 'uid' => $user_id,
+ 'name' => $this->randomName(),
+ ))->save();
$edit = array(
'name' => $entity_name,
- 'user_id' => mt_rand(0, 128),
+ 'user_id' => $user_id,
$this->fieldName . '[target_id]' => $target_id,
);
$this->drupalPostForm($this->entityType . '/add', $edit, t('Save'));
@@ -117,9 +128,11 @@ public function testSupportedEntityTypesAndWidgets() {
// Test all the other widgets supported by the entity reference field.
// Since we don't know the form structure for these widgets, just test
// that editing and saving an already created entity works.
+ // Also exclude the special author reference widgets.
+ $exclude = array('entity_reference_autocomplete', 'entity_reference_autocomplete_tags', 'route_based_autocomplete', 'author_autocomplete');
$entity = current(entity_load_multiple_by_properties($this->entityType, array('name' => $entity_name)));
$supported_widgets = \Drupal::service('plugin.manager.field.widget')->getOptions('entity_reference');
- $supported_widget_types = array_diff(array_keys($supported_widgets), array('entity_reference_autocomplete', 'entity_reference_autocomplete_tags'));
+ $supported_widget_types = array_diff(array_keys($supported_widgets), $exclude);
foreach ($supported_widget_types as $widget_type) {
entity_get_form_display($this->entityType, $this->bundle, 'default')->setComponent($this->fieldName, array(
@@ -166,9 +179,9 @@ protected function getTestEntities() {
$config_entity_2 = entity_create('config_test', array('id' => $this->randomName(), 'label' => $this->randomName()));
$config_entity_2->save();
- $content_entity_1 = entity_create('entity_test', array('name' => $this->randomName()));
+ $content_entity_1 = entity_create('entity_test', array('name' => $this->randomName(), 'user_id' => 0));
$content_entity_1->save();
- $content_entity_2 = entity_create('entity_test', array('name' => $this->randomName()));
+ $content_entity_2 = entity_create('entity_test', array('name' => $this->randomName(), 'user_id' => 0));
$content_entity_2->save();
return array(
diff --git a/core/modules/field/config/schema/field.schema.yml b/core/modules/field/config/schema/field.schema.yml
index 7018b5f..ca57b6a 100644
--- a/core/modules/field/config/schema/field.schema.yml
+++ b/core/modules/field/config/schema/field.schema.yml
@@ -291,3 +291,15 @@ entity_form_display.field.number:
placeholder:
type: label
label: 'Placeholder'
+
+entity_form_display.field.timestamp:
+ type: entity_field_form_display_base
+ label: 'Timestamp default display format settings'
+ mapping:
+ settings:
+ type: mapping
+ label: 'Settings'
+ mapping:
+ use_request_time_on_empty:
+ type: boolean
+ label: 'Whether the current request time should be used if an empty value is submitted'
diff --git a/core/modules/forum/config/install/rdf.mapping.node.forum.yml b/core/modules/forum/config/install/rdf.mapping.node.forum.yml
index 7db68c7..be874cd 100644
--- a/core/modules/forum/config/install/rdf.mapping.node.forum.yml
+++ b/core/modules/forum/config/install/rdf.mapping.node.forum.yml
@@ -11,12 +11,12 @@ fieldMappings:
properties:
- 'schema:dateCreated'
datatype_callback:
- callable: 'date_iso8601'
+ callable: 'Drupal\rdf\CommonDataConverter::dateIso8601Value'
changed:
properties:
- 'schema:dateModified'
datatype_callback:
- callable: 'date_iso8601'
+ callable: 'Drupal\rdf\CommonDataConverter::dateIso8601Value'
body:
properties:
- 'schema:text'
diff --git a/core/modules/forum/src/Tests/ForumBlockTest.php b/core/modules/forum/src/Tests/ForumBlockTest.php
index 1295c82..f7c7b05 100644
--- a/core/modules/forum/src/Tests/ForumBlockTest.php
+++ b/core/modules/forum/src/Tests/ForumBlockTest.php
@@ -175,8 +175,8 @@ protected function createForumTopics($count = 5) {
'body[0][value]' => $body,
// Forum posts are ordered by timestamp, so force a unique timestamp by
// adding the index.
- 'created[date]' => $date->format('Y-m-d'),
- 'created[time]' => $date->format('H:i:s'),
+ 'created[0][value][date]' => $date->format('Y-m-d'),
+ 'created[0][value][time]' => $date->format('H:i:s'),
);
// Create the forum topic, preselecting the forum ID via a URL parameter.
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index b9a2325..7673eee 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -181,6 +181,14 @@ function node_theme() {
'base hook' => 'field',
'template' => 'field--node--title',
),
+ 'field__node__uid' => array(
+ 'base hook' => 'field',
+ 'template' => 'field--node--uid',
+ ),
+ 'field__node__created' => array(
+ 'base hook' => 'field',
+ 'template' => 'field--node--created',
+ ),
);
}
@@ -202,15 +210,6 @@ function node_entity_view_display_alter(EntityViewDisplayInterface $display, $co
}
/**
- * Implements hook_entity_form_display_alter().
- */
-function node_entity_form_display_alter(EntityFormDisplayInterface $form_display, $context) {
- if ($context['entity_type'] == 'node') {
- $node_type = node_type_load($context['bundle']);
- }
-}
-
-/**
* Entity URI callback.
*
* @param \Drupal\node\NodeInterface $node
@@ -627,14 +626,10 @@ function template_preprocess_node(&$variables) {
$variables['node'] = $variables['elements']['#node'];
/** @var \Drupal\node\NodeInterface $node */
$node = $variables['node'];
-
- $variables['date'] = format_date($node->getCreatedTime());
- $username = array(
- '#theme' => 'username',
- '#account' => $node->getOwner(),
- '#link_options' => array('attributes' => array('rel' => 'author')),
- );
- $variables['author_name'] = drupal_render($username);
+ $variables['date'] = drupal_render($variables['elements']['created'], TRUE);
+ unset($variables['elements']['created']);
+ $variables['author_name'] = drupal_render($variables['elements']['uid'], TRUE);
+ unset($variables['elements']['uid']);
$variables['url'] = $node->url('canonical', array(
'language' => $node->language(),
diff --git a/core/modules/node/src/Entity/Node.php b/core/modules/node/src/Entity/Node.php
index 90ab790..a3986ab 100644
--- a/core/modules/node/src/Entity/Node.php
+++ b/core/modules/node/src/Entity/Node.php
@@ -372,10 +372,25 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields['uid'] = FieldDefinition::create('entity_reference')
->setLabel(t('Author'))
- ->setDescription(t('The user that is the node author.'))
+ ->setDescription(t('The user ID of the node author.'))
->setRevisionable(TRUE)
- ->setSetting('target_type', 'user')
- ->setTranslatable(TRUE);
+ ->setSettings(array(
+ 'target_type' => 'user',
+ 'default_value' => 0,
+ ))
+ ->setTranslatable(TRUE)
+ ->setDisplayOptions('view', array(
+ 'label' => 'hidden',
+ 'type' => 'author',
+ 'weight' => 0,
+ ))
+ ->setDisplayOptions('form', array(
+ 'type' => 'author_autocomplete',
+ 'weight' => -1,
+ 'settings' => array(
+ 'route_name' => 'user.autocomplete',
+ ),
+ ));
$fields['status'] = FieldDefinition::create('boolean')
->setLabel(t('Publishing status'))
@@ -384,10 +399,23 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
->setTranslatable(TRUE);
$fields['created'] = FieldDefinition::create('created')
- ->setLabel(t('Created'))
+ ->setLabel(t('Publication date'))
->setDescription(t('The time that the node was created.'))
->setRevisionable(TRUE)
- ->setTranslatable(TRUE);
+ ->setTranslatable(TRUE)
+ ->setDisplayOptions('view', array(
+ 'label' => 'hidden',
+ 'type' => 'timestamp',
+ 'weight' => 0,
+ ))
+ ->setDisplayOptions('form', array(
+ 'type' => 'timestamp',
+ 'weight' => 0,
+ 'settings' => array(
+ 'use_request_time_on_empty' => TRUE,
+ ),
+ ))
+ ->setDisplayConfigurable('form', TRUE);
$fields['changed'] = FieldDefinition::create('changed')
->setLabel(t('Changed'))
@@ -396,16 +424,22 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
->setTranslatable(TRUE);
$fields['promote'] = FieldDefinition::create('boolean')
- ->setLabel(t('Promote'))
- ->setDescription(t('A boolean indicating whether the node should be displayed on the front page.'))
+ ->setLabel(t('Promoted to front page'))
->setRevisionable(TRUE)
- ->setTranslatable(TRUE);
+ ->setTranslatable(TRUE)
+ ->setDisplayOptions('form', array(
+ 'type' => 'boolean',
+ 'weight' => -1,
+ ));
$fields['sticky'] = FieldDefinition::create('boolean')
- ->setLabel(t('Sticky'))
- ->setDescription(t('A boolean indicating whether the node should be displayed at the top of lists in which it appears.'))
+ ->setLabel(t('Sticky at top of lists'))
->setRevisionable(TRUE)
- ->setTranslatable(TRUE);
+ ->setTranslatable(TRUE)
+ ->setDisplayOptions('form', array(
+ 'type' => 'boolean',
+ 'weight' => 0,
+ ));
$fields['revision_timestamp'] = FieldDefinition::create('created')
->setLabel(t('Revision timestamp'))
@@ -422,9 +456,16 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields['revision_log'] = FieldDefinition::create('string_long')
->setLabel(t('Revision log message'))
- ->setDescription(t('The log entry explaining the changes in this revision.'))
+ ->setDescription(t('Briefly describe the changes you have made.'))
->setRevisionable(TRUE)
- ->setTranslatable(TRUE);
+ ->setTranslatable(TRUE)
+ ->setDisplayOptions('form', array(
+ 'type' => 'text_textarea',
+ 'weight' => 0,
+ 'settings' => array(
+ 'rows' => 4,
+ ),
+ ));
return $fields;
}
diff --git a/core/modules/node/src/NodeForm.php b/core/modules/node/src/NodeForm.php
index 9e3dafc..85b5de0 100644
--- a/core/modules/node/src/NodeForm.php
+++ b/core/modules/node/src/NodeForm.php
@@ -12,6 +12,8 @@
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Component\Utility\String;
+use Drupal\Core\Cache\Cache;
+use Drupal\Core\Language\Language;
/**
* Form controller for the node edit forms.
@@ -36,8 +38,7 @@ protected function prepareEntity() {
$this->settings = $type->getModuleSettings('node');
if (!$node->isNew()) {
- $node->date = format_date($node->getCreatedTime(), 'custom', 'Y-m-d H:i:s O');
- // Remove the revision log message from the original node entity.
+ // Remove the log message from the original node entity.
$node->revision_log = NULL;
}
}
@@ -49,6 +50,16 @@ public function form(array $form, array &$form_state) {
/** @var \Drupal\node\NodeInterface $node */
$node = $this->entity;
+ // Create the "advanced" vertical tabs before building the form, so that
+ // field widgets may detect its presence and choose to live there.
+ $form['advanced'] = array(
+ '#type' => 'vertical_tabs',
+ '#attributes' => array('class' => array('entity-meta')),
+ '#weight' => 99,
+ );
+
+ $form = parent::form($form, $form_state, $node);
+
if ($this->operation == 'edit') {
$form['#title'] = $this->t('Edit @type @title', array('@type' => node_get_type_label($node), '@title' => $node->label()));
}
@@ -84,14 +95,8 @@ public function form(array $form, array &$form_state) {
'#access' => isset($language_configuration['language_show']) && $language_configuration['language_show'],
);
- $form['advanced'] = array(
- '#type' => 'vertical_tabs',
- '#attributes' => array('class' => array('entity-meta')),
- '#weight' => 99,
- );
-
- // Add a revision log field if the "Create new revision" option is checked,
- // or if the current user has the ability to check that option.
+ // Add a revision_log field if the "Create new revision" option is checked, or if
+ // the current user has the ability to check that option.
$form['revision_information'] = array(
'#type' => 'details',
'#group' => 'advanced',
@@ -114,14 +119,12 @@ public function form(array $form, array &$form_state) {
'#default_value' => !empty($this->settings['options']['revision']),
'#access' => $node->isNewRevision() || user_access('administer nodes'),
'#group' => 'revision_information',
+ // Ensure the 'Create new revision' checkbox sits above the revision log
+ // message.
+ '#weight' => -1,
);
- $form['revision_log'] = array(
- '#type' => 'textarea',
- '#title' => t('Revision log message'),
- '#rows' => 4,
- '#default_value' => !empty($node->revision_log->value) ? $node->revision_log->value : '',
- '#description' => t('Briefly describe the changes you have made.'),
+ $form['revision_log'] += array(
'#states' => array(
'visible' => array(
':input[name="revision"]' => array('checked' => TRUE),
@@ -152,26 +155,17 @@ public function form(array $form, array &$form_state) {
'#optional' => TRUE,
);
- $form['uid'] = array(
- '#type' => 'textfield',
- '#title' => t('Authored by'),
- '#maxlength' => 60,
- '#autocomplete_route_name' => 'user.autocomplete',
- '#default_value' => $node->getOwnerId()? $node->getOwner()->getUsername() : '',
- '#weight' => -1,
- '#description' => t('Leave blank for %anonymous.', array('%anonymous' => $user_config->get('anonymous'))),
+ $form['uid'] += array(
'#group' => 'author',
'#access' => user_access('administer nodes'),
);
- $form['created'] = array(
- '#type' => 'textfield',
- '#title' => t('Authored on'),
- '#maxlength' => 25,
- '#description' => t('Format: %time. The date format is YYYY-MM-DD and %timezone is the time zone offset from UTC. Leave blank to use the time of form submission.', array('%time' => !empty($node->date) ? date_format(date_create($node->date), 'Y-m-d H:i:s O') : format_date($node->getCreatedTime(), 'custom', 'Y-m-d H:i:s O'), '%timezone' => !empty($node->date) ? date_format(date_create($node->date), 'O') : format_date($node->getCreatedTime(), 'custom', 'O'))),
- '#default_value' => !empty($node->date) ? $node->date : '',
+ $form['uid']['widget'][0]['value']['#title'] = $this->t('Authored by');
+
+ $form['created'] += array(
'#group' => 'author',
'#access' => user_access('administer nodes'),
);
+ $form['created']['widget'][0]['value']['#title'] = $this->t('Authored on');
// Node options for administrators.
$form['options'] = array(
@@ -188,23 +182,17 @@ public function form(array $form, array &$form_state) {
'#optional' => TRUE,
);
- $form['promote'] = array(
- '#type' => 'checkbox',
- '#title' => t('Promoted to front page'),
- '#default_value' => $node->isPromoted(),
+ $form['promote'] += array(
'#group' => 'options',
'#access' => user_access('administer nodes'),
);
- $form['sticky'] = array(
- '#type' => 'checkbox',
- '#title' => t('Sticky at top of lists'),
- '#default_value' => $node->isSticky(),
+ $form['sticky'] += array(
'#group' => 'options',
'#access' => user_access('administer nodes'),
);
- return parent::form($form, $form_state, $node);
+ return $form;
}
/**
@@ -298,21 +286,6 @@ public function validate(array $form, array &$form_state) {
$this->setFormError('changed', $form_state, $this->t('The content on this page has either been modified by another user, or you have already submitted modifications using this form. As a result, your changes cannot be saved.'));
}
- // Validate the "authored by" field.
- if (!empty($form_state['values']['uid']) && !user_load_by_name($form_state['values']['uid'])) {
- // The use of empty() is mandatory in the context of usernames
- // as the empty string denotes the anonymous user. In case we
- // are dealing with an anonymous user we set the user ID to 0.
- $this->setFormError('uid', $form_state, $this->t('The username %name does not exist.', array('%name' => $form_state['values']['uid'])));
- }
-
- // Validate the "authored on" field.
- // The date element contains the date object.
- $date = $node->date instanceof DrupalDateTime ? $node->date : new DrupalDateTime($node->date);
- if ($date->hasErrors()) {
- $this->setFormError('date', $form_state, $this->t('You have to specify a valid date.'));
- }
-
// Invoke hook_node_validate() for validation needed by modules.
// Can't use \Drupal::moduleHandler()->invokeAll(), because $form_state must
// be receivable by reference.
@@ -402,31 +375,6 @@ public function unpublish(array $form, array &$form_state) {
}
/**
- * {@inheritdoc}
- */
- public function buildEntity(array $form, array &$form_state) {
- /** @var \Drupal\node\NodeInterface $entity */
- $entity = parent::buildEntity($form, $form_state);
- // A user might assign the node author by entering a user name in the node
- // form, which we then need to translate to a user ID.
- if (!empty($form_state['values']['uid']) && $account = user_load_by_name($form_state['values']['uid'])) {
- $entity->setOwnerId($account->id());
- }
- else {
- $entity->setOwnerId(0);
- }
-
- if (!empty($form_state['values']['created']) && $form_state['values']['created'] instanceOf DrupalDateTime) {
- $entity->setCreatedTime($form_state['values']['created']->getTimestamp());
- }
- else {
- $entity->setCreatedTime(REQUEST_TIME);
- }
- return $entity;
- }
-
-
- /**
* Overrides Drupal\Core\Entity\EntityForm::save().
*/
public function save(array $form, array &$form_state) {
diff --git a/core/modules/node/src/NodeTranslationHandler.php b/core/modules/node/src/NodeTranslationHandler.php
index 21ab7e0..aea2d3b 100644
--- a/core/modules/node/src/NodeTranslationHandler.php
+++ b/core/modules/node/src/NodeTranslationHandler.php
@@ -80,8 +80,9 @@ public function entityFormEntityBuild($entity_type, EntityInterface $entity, arr
$translation['status'] = $form_controller->getEntity()->isPublished();
// $form['content_translation']['name'] is the equivalent field
// for translation author uid.
- $translation['name'] = $form_state['values']['uid'];
- $translation['created'] = $form_state['values']['created'];
+ $account = user_load($form_state['values']['uid'][0]['target_id']);
+ $translation['name'] = $account ? $account->getUsername() : '';
+ $translation['created'] = format_date($form_state['values']['created'][0]['value'], 'custom', 'Y-m-d H:i:s O');
}
parent::entityFormEntityBuild($entity_type, $entity, $form, $form_state);
}
diff --git a/core/modules/node/src/NodeViewBuilder.php b/core/modules/node/src/NodeViewBuilder.php
index 606ef36..5521812 100644
--- a/core/modules/node/src/NodeViewBuilder.php
+++ b/core/modules/node/src/NodeViewBuilder.php
@@ -75,12 +75,6 @@ protected function getBuildDefaults(EntityInterface $entity, $view_mode, $langco
if (isset($defaults['#cache']) && isset($entity->in_preview)) {
unset($defaults['#cache']);
}
- else {
- // The node 'submitted' info is not rendered in a standard way (renderable
- // array) so we have to add a cache tag manually.
- // @todo Delete this once https://drupal.org/node/2226493 lands.
- $defaults['#cache']['tags']['user'][] = $entity->getOwnerId();
- }
return $defaults;
}
diff --git a/core/modules/node/src/Tests/MultiStepNodeFormBasicOptionsTest.php b/core/modules/node/src/Tests/MultiStepNodeFormBasicOptionsTest.php
index 67bdbe3..5620a8f 100644
--- a/core/modules/node/src/Tests/MultiStepNodeFormBasicOptionsTest.php
+++ b/core/modules/node/src/Tests/MultiStepNodeFormBasicOptionsTest.php
@@ -62,13 +62,13 @@ function testMultiStepNodeFormBasicOptions() {
$edit = array(
'title[0][value]' => 'a',
- 'promote' => FALSE,
- 'sticky' => 1,
+ 'promote[0][value]' => FALSE,
+ 'sticky[0][value]' => 1,
"{$this->field_name}[0][value]" => $this->randomString(32),
);
$this->drupalPostForm('node/add/page', $edit, t('Add another item'));
- $this->assertNoFieldChecked('edit-promote', 'promote stayed unchecked');
- $this->assertFieldChecked('edit-sticky', 'sticky stayed checked');
+ $this->assertNoFieldChecked('edit-promote-0-value', 'promote stayed unchecked');
+ $this->assertFieldChecked('edit-sticky-0-value', 'sticky stayed checked');
}
}
diff --git a/core/modules/node/src/Tests/NodeCreationTest.php b/core/modules/node/src/Tests/NodeCreationTest.php
index 62846cf..b48a8af 100644
--- a/core/modules/node/src/Tests/NodeCreationTest.php
+++ b/core/modules/node/src/Tests/NodeCreationTest.php
@@ -62,9 +62,9 @@ function testNodeCreation() {
$this->assertTrue($node, 'Node found in database.');
// Verify that pages do not show submitted information by default.
- $submitted_by = t('Submitted by !username on !datetime', array('!username' => $this->loggedInUser->getUsername(), '!datetime' => format_date($node->getCreatedTime())));
$this->drupalGet('node/' . $node->id());
- $this->assertNoText($submitted_by);
+ $this->assertNoText($node->getOwner()->getUsername());
+ $this->assertNoText(format_date($node->getCreatedTime()));
// Change the node type setting to show submitted by information.
$node_type = entity_load('node_type', 'page');
@@ -72,7 +72,8 @@ function testNodeCreation() {
$node_type->save();
$this->drupalGet('node/' . $node->id());
- $this->assertText($submitted_by);
+ $this->assertText($node->getOwner()->getUsername());
+ $this->assertText(format_date($node->getCreatedTime()));
}
/**
@@ -151,7 +152,7 @@ public function testAuthorAutocomplete() {
$this->drupalGet('node/add/page');
- $result = $this->xpath('//input[@id="edit-uid" and contains(@data-autocomplete-path, "user/autocomplete")]');
+ $result = $this->xpath('//input[@id="edit-uid-0-value" and contains(@data-autocomplete-path, "user/autocomplete")]');
$this->assertEqual(count($result), 0, 'No autocompletion without access user profiles.');
$admin_user = $this->drupalCreateUser(array('administer nodes', 'create page content', 'access user profiles'));
@@ -159,7 +160,7 @@ public function testAuthorAutocomplete() {
$this->drupalGet('node/add/page');
- $result = $this->xpath('//input[@id="edit-uid" and contains(@data-autocomplete-path, "user/autocomplete")]');
+ $result = $this->xpath('//input[@id="edit-uid-0-target-id" and contains(@data-autocomplete-path, "user/autocomplete")]');
$this->assertEqual(count($result), 1, 'Ensure that the user does have access to the autocompletion');
}
diff --git a/core/modules/node/src/Tests/NodeTranslationUITest.php b/core/modules/node/src/Tests/NodeTranslationUITest.php
index dd79a7c..9b34ca8 100644
--- a/core/modules/node/src/Tests/NodeTranslationUITest.php
+++ b/core/modules/node/src/Tests/NodeTranslationUITest.php
@@ -158,11 +158,11 @@ protected function doTestAuthoringInfo() {
'promote' => (bool) mt_rand(0, 1),
);
$edit = array(
- 'uid' => $user->getUsername(),
- 'created[date]' => format_date($values[$langcode]['created'], 'custom', 'Y-m-d'),
- 'created[time]' => format_date($values[$langcode]['created'], 'custom', 'H:i:s'),
- 'sticky' => $values[$langcode]['sticky'],
- 'promote' => $values[$langcode]['promote'],
+ 'uid[0][target_id]' => $user->getUsername(),
+ 'created[0][value][date]' => format_date($values[$langcode]['created'], 'custom', 'Y-m-d'),
+ 'created[0][value][time]' => format_date($values[$langcode]['created'], 'custom', 'H:i:s'),
+ 'sticky[0][value]' => $values[$langcode]['sticky'],
+ 'promote[0][value]' => $values[$langcode]['promote'],
);
$this->drupalPostForm($path, $edit, $this->getFormSubmitAction($entity, $langcode), array('language' => $languages[$langcode]));
}
diff --git a/core/modules/node/src/Tests/PageEditTest.php b/core/modules/node/src/Tests/PageEditTest.php
index 2361d13..4fc20db 100644
--- a/core/modules/node/src/Tests/PageEditTest.php
+++ b/core/modules/node/src/Tests/PageEditTest.php
@@ -7,6 +7,8 @@
namespace Drupal\node\Tests;
+use Drupal\Component\Utility\String;
+
/**
* Tests the node edit functionality.
*/
@@ -114,21 +116,21 @@ function testPageAuthoredBy() {
// Try to change the 'authored by' field to an invalid user name.
$edit = array(
- 'uid' => 'invalid-name',
+ 'uid[0][target_id]' => 'invalid-name',
);
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save and keep published'));
- $this->assertText('The username invalid-name does not exist.');
+ $this->assertRaw(String::format('The username %name does not exist.', array('%name' => 'invalid-name')));
// Change the authored by field to an empty string, which should assign
// authorship to the anonymous user (uid 0).
- $edit['uid'] = '';
+ $edit['uid[0][target_id]'] = '';
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save and keep published'));
$node = node_load($node->id(), TRUE);
$this->assertIdentical($node->getOwnerId(), '0', 'Node authored by anonymous user.');
// Change the authored by field to another user's name (that is not
// logged in).
- $edit['uid'] = $this->web_user->getUsername();
+ $edit['uid[0][target_id]'] = $this->web_user->getUsername();
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save and keep published'));
$node = node_load($node->id(), TRUE);
$this->assertIdentical($node->getOwnerId(), $this->web_user->id(), 'Node authored by normal user.');
@@ -136,6 +138,6 @@ function testPageAuthoredBy() {
// Check that normal users cannot change the authored by information.
$this->drupalLogin($this->web_user);
$this->drupalGet('node/' . $node->id() . '/edit');
- $this->assertNoFieldByName('uid');
+ $this->assertNoFieldByName('uid[0][target_id]');
}
}
diff --git a/core/modules/node/src/Tests/PagePreviewTest.php b/core/modules/node/src/Tests/PagePreviewTest.php
index d1635c5..a567932 100644
--- a/core/modules/node/src/Tests/PagePreviewTest.php
+++ b/core/modules/node/src/Tests/PagePreviewTest.php
@@ -192,7 +192,7 @@ function testPagePreviewWithRevisions() {
$edit[$title_key] = $this->randomName(8);
$edit[$body_key] = $this->randomName(16);
$edit[$term_key] = $this->term->id();
- $edit['revision_log'] = $this->randomName(32);
+ $edit['revision_log[0][value]'] = $this->randomName(32);
$this->drupalPostForm('node/add/page', $edit, t('Preview'));
// Check that the preview is displaying the title, body and term.
@@ -206,8 +206,8 @@ function testPagePreviewWithRevisions() {
$this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.');
$this->assertFieldByName($term_key, $edit[$term_key], 'Term field displayed.');
- // Check that the revision log field has the correct value.
- $this->assertFieldByName('revision_log', $edit['revision_log'], 'Revision log field displayed.');
+ // Check that the log field has the correct value.
+ $this->assertFieldByName('revision_log[0][value]', $edit['revision_log[0][value]'], 'Revision Log field displayed.');
}
}
diff --git a/core/modules/node/templates/field--node--created.html.twig b/core/modules/node/templates/field--node--created.html.twig
new file mode 100644
index 0000000..6c8a687
--- /dev/null
+++ b/core/modules/node/templates/field--node--created.html.twig
@@ -0,0 +1,18 @@
+{#
+/**
+* @file
+* Default theme implementation for the node created field.
+*
+* This is an override of field.html.twig for the node created field. See that
+* template for documentation about its details and overrides.
+*
+* Available variables:
+* - attributes: HTML attributes for the containing span element.
+* - items: List of all the field items.
+*
+* @see field.html.twig
+*
+* @ingroup themeable
+*/
+#}
+{{ items }}
diff --git a/core/modules/node/templates/field--node--uid.html.twig b/core/modules/node/templates/field--node--uid.html.twig
new file mode 100644
index 0000000..1fb0a6d
--- /dev/null
+++ b/core/modules/node/templates/field--node--uid.html.twig
@@ -0,0 +1,18 @@
+{#
+/**
+* @file
+* Default theme implementation for the node user field.
+*
+* This is an override of field.html.twig for the node user field. See that
+* template for documentation about its details and overrides.
+*
+* Available variables:
+* - attributes: HTML attributes for the containing span element.
+* - items: List of all the field items.
+*
+* @see field.html.twig
+*
+* @ingroup themeable
+*/
+#}
+{{ items }}
diff --git a/core/modules/node/templates/node.html.twig b/core/modules/node/templates/node.html.twig
index c80eecb..a0e629e 100644
--- a/core/modules/node/templates/node.html.twig
+++ b/core/modules/node/templates/node.html.twig
@@ -23,10 +23,8 @@
* - author_picture: The node author user entity, rendered using the "compact"
* view mode.
* - metadata: Metadata for this node.
- * - date: Formatted creation date. Preprocess functions can reformat it by
- * calling format_date() with the desired parameters on
- * $variables['created'].
- * - author_name: Themed username of node author output from theme_username().
+ * - date: Themed creation date field.
+ * - author_name: Themed author name field.
* - url: Direct URL of the current node.
* - display_submitted: Whether submission information should be displayed.
* - attributes: HTML attributes for the containing element.
diff --git a/core/modules/rdf/rdf.module b/core/modules/rdf/rdf.module
index 7bfb13c..e56ab9a 100644
--- a/core/modules/rdf/rdf.module
+++ b/core/modules/rdf/rdf.module
@@ -216,7 +216,7 @@ function rdf_entity_prepare_view($entity_type, array $entities, array $displays)
$field_mapping = $mapping->getPreparedFieldMapping($name);
if ($field_mapping) {
foreach ($entity->get($name) as $item) {
- $item->_attributes += rdf_rdfa_attributes($field_mapping, $item->getValue());
+ $item->_attributes += rdf_rdfa_attributes($field_mapping, $item->toArray());
}
}
}
@@ -233,7 +233,7 @@ function rdf_comment_load($comments) {
// to optimize performance for websites that implement an entity cache.
$created_mapping = rdf_get_mapping('comment', $comment->bundle())
->getPreparedFieldMapping('created');
- $comment->rdf_data['date'] = rdf_rdfa_attributes($created_mapping, $comment->getCreatedTime());
+ $comment->rdf_data['date'] = rdf_rdfa_attributes($created_mapping, $comment->get('created')->first()->toArray());
$entity = $comment->getCommentedEntity();
$comment->rdf_data['entity_uri'] = $entity->url();
if ($comment->hasParentComment()) {
@@ -304,7 +304,7 @@ function rdf_preprocess_node(&$variables) {
// Adds RDFa markup for the date.
$created_mapping = $mapping->getPreparedFieldMapping('created');
if (!empty($created_mapping) && $variables['display_submitted']) {
- $date_attributes = rdf_rdfa_attributes($created_mapping, $variables['node']->getCreatedTime());
+ $date_attributes = rdf_rdfa_attributes($created_mapping, $variables['node']->get('created')[0]->getValue());
$rdf_metadata = array(
'#theme' => 'rdf_metadata',
'#metadata' => array($date_attributes),
diff --git a/core/modules/rdf/src/CommonDataConverter.php b/core/modules/rdf/src/CommonDataConverter.php
index e27f48b..c91f947 100644
--- a/core/modules/rdf/src/CommonDataConverter.php
+++ b/core/modules/rdf/src/CommonDataConverter.php
@@ -23,4 +23,18 @@ class CommonDataConverter {
static function rawValue($data) {
return $data;
}
+
+ /**
+ * Converts a date entity field array into an ISO 8601 timestamp string.
+ *
+ * @param array $data
+ * The array containing the 'value' element.
+ *
+ * @return string
+ * Returns the ISO 8601 timestamp.
+ */
+ static function dateIso8601Value($data) {
+ return date_iso8601($data['value']);
+ }
+
}
diff --git a/core/modules/rdf/src/Tests/CommentAttributesTest.php b/core/modules/rdf/src/Tests/CommentAttributesTest.php
index d58e44b..1379425 100644
--- a/core/modules/rdf/src/Tests/CommentAttributesTest.php
+++ b/core/modules/rdf/src/Tests/CommentAttributesTest.php
@@ -77,12 +77,12 @@ public function setUp() {
'created' => array(
'properties' => array('dc:date', 'dc:created'),
'datatype' => 'xsd:dateTime',
- 'datatype_callback' => array('callable' => 'date_iso8601'),
+ 'datatype_callback' => array('callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value'),
),
'changed' => array(
'properties' => array('dc:modified'),
'datatype' => 'xsd:dateTime',
- 'datatype_callback' => array('callable' => 'date_iso8601'),
+ 'datatype_callback' => array('callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value'),
),
'comment_body' => array(
'properties' => array('content:encoded'),
diff --git a/core/modules/rdf/src/Tests/CrudTest.php b/core/modules/rdf/src/Tests/CrudTest.php
index 26f793d..fd0d0a1 100644
--- a/core/modules/rdf/src/Tests/CrudTest.php
+++ b/core/modules/rdf/src/Tests/CrudTest.php
@@ -81,7 +81,7 @@ function testFieldMapping() {
$mapping = array(
'properties' => array('dc:created'),
'datatype' => 'xsd:dateTime',
- 'datatype_callback' => array('callable' => 'date_iso8601'),
+ 'datatype_callback' => array('callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value'),
);
rdf_get_mapping($this->entity_type, $this->bundle)
->setFieldMapping($field_name, $mapping)
@@ -94,7 +94,7 @@ function testFieldMapping() {
$mapping = array(
'properties' => array('dc:date'),
'datatype' => 'foo:bar',
- 'datatype_callback' => array('callable' => 'date_iso8601'),
+ 'datatype_callback' => array('callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value'),
);
rdf_get_mapping($this->entity_type, $this->bundle)
->setFieldMapping($field_name, $mapping)
diff --git a/core/modules/rdf/src/Tests/NodeAttributesTest.php b/core/modules/rdf/src/Tests/NodeAttributesTest.php
index 76e1af6..ff29448 100644
--- a/core/modules/rdf/src/Tests/NodeAttributesTest.php
+++ b/core/modules/rdf/src/Tests/NodeAttributesTest.php
@@ -42,7 +42,7 @@ public function setUp() {
->setFieldMapping('created', array(
'properties' => array('dc:date', 'dc:created'),
'datatype' => 'xsd:dateTime',
- 'datatype_callback' => array('callable' => 'date_iso8601'),
+ 'datatype_callback' => array('callable' => 'Drupal\rdf\CommonDataConverter::dateIso8601Value'),
))
->save();
}
diff --git a/core/modules/system/src/Tests/Entity/EntityTranslationFormTest.php b/core/modules/system/src/Tests/Entity/EntityTranslationFormTest.php
index 41806e3..f7cf2c7 100644
--- a/core/modules/system/src/Tests/Entity/EntityTranslationFormTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityTranslationFormTest.php
@@ -11,6 +11,7 @@
use Drupal\field\Entity\FieldConfig;
use Drupal\simpletest\WebTestBase;
use Drupal\Core\Language\Language;
+use Drupal\node\Entity\Node;
/**
* Tests entity translation form.
@@ -61,27 +62,29 @@ function testEntityFormLanguage() {
$this->drupalLogin($web_user);
// Create a node with language LanguageInterface::LANGCODE_NOT_SPECIFIED.
- $edit = array();
- $edit['title[0][value]'] = $this->randomName(8);
- $edit['body[0][value]'] = $this->randomName(16);
+ $node = Node::create(array(
+ 'type' => 'page',
+ 'title' => $this->randomName(8),
+ 'body' => array(
+ 'value' => $this->randomName(16),
+ ),
+ 'uid' => $web_user->id(),
+ ));
+ $node->save();
- $this->drupalGet('node/add/page');
- $form_langcode = \Drupal::state()->get('entity_test.form_langcode') ?: FALSE;
- $this->drupalPostForm(NULL, $edit, t('Save'));
-
- $node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
+ $form_langcode = \Drupal::state()->get('entity_test.form_langcode') ?: 'und';
$this->assertTrue($node->language()->id == $form_langcode, 'Form language is the same as the entity language.');
// Edit the node and test the form language.
$this->drupalGet($this->langcodes[0] . '/node/' . $node->id() . '/edit');
- $form_langcode = \Drupal::state()->get('entity_test.form_langcode') ?: FALSE;
+ $form_langcode = \Drupal::state()->get('entity_test.form_langcode') ?: 'und';
$this->assertTrue($node->language()->id == $form_langcode, 'Form language is the same as the entity language.');
// Explicitly set form langcode.
$langcode = $this->langcodes[0];
$form_state['langcode'] = $langcode;
\Drupal::service('entity.form_builder')->getForm($node, 'default', $form_state);
- $form_langcode = \Drupal::state()->get('entity_test.form_langcode') ?: FALSE;
+ $form_langcode = \Drupal::state()->get('entity_test.form_langcode') ?: 'und';
$this->assertTrue($langcode == $form_langcode, 'Form language is the same as the language parameter.');
// Enable language selector.
@@ -115,7 +118,7 @@ function testEntityFormLanguage() {
$node->getTranslation($langcode2)->body->value = $this->randomName(16);
$node->save();
$this->drupalGet($langcode2 . '/node/' . $node->id() . '/edit');
- $form_langcode = \Drupal::state()->get('entity_test.form_langcode') ?: FALSE;
+ $form_langcode = \Drupal::state()->get('entity_test.form_langcode') ?: 'und';
$this->assertTrue($langcode2 == $form_langcode, "Node edit form language is $langcode2.");
}
}
diff --git a/core/modules/taxonomy/src/Tests/LegacyTest.php b/core/modules/taxonomy/src/Tests/LegacyTest.php
index bf7ae23..83d4597 100644
--- a/core/modules/taxonomy/src/Tests/LegacyTest.php
+++ b/core/modules/taxonomy/src/Tests/LegacyTest.php
@@ -80,8 +80,8 @@ function testTaxonomyLegacyNode() {
$date = new DrupalDateTime('1969-01-01 00:00:00');
$edit = array();
$edit['title[0][value]'] = $this->randomName();
- $edit['created[date]'] = $date->format('Y-m-d');
- $edit['created[time]'] = $date->format('H:i:s');
+ $edit['created[0][value][date]'] = $date->format('Y-m-d');
+ $edit['created[0][value][time]'] = $date->format('H:i:s');
$edit['body[0][value]'] = $this->randomName();
$edit['field_tags'] = $this->randomName();
$this->drupalPostForm('node/add/article', $edit, t('Save and publish'));
diff --git a/core/modules/text/src/Plugin/Field/FieldWidget/TextareaWidget.php b/core/modules/text/src/Plugin/Field/FieldWidget/TextareaWidget.php
index 3c57008..1b41a93 100644
--- a/core/modules/text/src/Plugin/Field/FieldWidget/TextareaWidget.php
+++ b/core/modules/text/src/Plugin/Field/FieldWidget/TextareaWidget.php
@@ -18,7 +18,8 @@
* id = "text_textarea",
* label = @Translation("Text area (multiple rows)"),
* field_types = {
- * "text_long"
+ * "text_long",
+ * "string_long",
* }
* )
*/
diff --git a/core/modules/user/src/Plugin/Field/FieldFormatter/AuthorFormatter.php b/core/modules/user/src/Plugin/Field/FieldFormatter/AuthorFormatter.php
new file mode 100644
index 0000000..38c7f55
--- /dev/null
+++ b/core/modules/user/src/Plugin/Field/FieldFormatter/AuthorFormatter.php
@@ -0,0 +1,50 @@
+ $item) {
+ /** @var $referenced_user \Drupal\user\UserInterface */
+ if ($referenced_user = $item->entity) {
+ $elements[$delta] = array(
+ '#theme' => 'username',
+ '#account' => $referenced_user,
+ '#link_options' => array('attributes' => array('rel' => 'author')),
+ '#cache' => array(
+ 'tags' => $referenced_user->getCacheTag(),
+ ),
+ );
+ }
+ }
+
+ return $elements;
+ }
+
+}
diff --git a/core/modules/user/src/Plugin/Field/FieldWidget/AuthorAutocompleteWidget.php b/core/modules/user/src/Plugin/Field/FieldWidget/AuthorAutocompleteWidget.php
new file mode 100644
index 0000000..43834df
--- /dev/null
+++ b/core/modules/user/src/Plugin/Field/FieldWidget/AuthorAutocompleteWidget.php
@@ -0,0 +1,74 @@
+entity && $items[$delta]->entity->isAuthenticated() ? $items[$delta]->entity->getUsername() : '';
+
+ $user_config = \Drupal::config('user.settings');
+ $element['target_id']['#description'] = $this->t('Leave blank for %anonymous.', array('%anonymous' => $user_config->get('anonymous')));
+
+ $element['target_id']['#element_validate'] = array(array($this, 'elementValidate'));
+
+ return $element;
+ }
+
+ /**
+ * Validates an element.
+ *
+ * @todo Convert to massageFormValues() after https://drupal.org/node/2226723 lands.
+ */
+ public function elementValidate($element, &$form_state, $form) {
+ $form_builder = \Drupal::formBuilder();
+ $value = $element['#value'];
+ // The use of empty() is mandatory in the context of usernames
+ // as the empty string denotes the anonymous user. In case we
+ // are dealing with an anonymous user we set the user ID to 0.
+ if (empty($value)) {
+ $value = 0;
+ }
+ else {
+ $account = user_load_by_name($value);
+ if ($account !== FALSE) {
+ $value = $account->id();
+ }
+ else {
+ // Edge case: a non-existing numeric username should not be treated as
+ // a user ID (entity reference target_id). The ValidReference constraint
+ // would consider this a valid user ID, therefore we need additional
+ // validation here.
+ $form_builder->setError($element, $form_state, $this->t('The username %name does not exist.', array('%name' => $value)));
+ $value = NULL;
+ }
+ }
+ $form_builder->setValue($element, $value, $form_state);
+ }
+
+}
diff --git a/core/profiles/standard/config/install/rdf.mapping.comment.node__comment.yml b/core/profiles/standard/config/install/rdf.mapping.comment.node__comment.yml
index 00abf0c..d8aa944 100644
--- a/core/profiles/standard/config/install/rdf.mapping.comment.node__comment.yml
+++ b/core/profiles/standard/config/install/rdf.mapping.comment.node__comment.yml
@@ -11,12 +11,12 @@ fieldMappings:
properties:
- 'schema:dateCreated'
datatype_callback:
- callable: 'date_iso8601'
+ callable: 'Drupal\rdf\CommonDataConverter::dateIso8601Value'
changed:
properties:
- 'schema:dateModified'
datatype_callback:
- callable: 'date_iso8601'
+ callable: 'Drupal\rdf\CommonDataConverter::dateIso8601Value'
comment_body:
properties:
- 'schema:text'
diff --git a/core/profiles/standard/config/install/rdf.mapping.node.article.yml b/core/profiles/standard/config/install/rdf.mapping.node.article.yml
index 10147e7..d1b7f80 100644
--- a/core/profiles/standard/config/install/rdf.mapping.node.article.yml
+++ b/core/profiles/standard/config/install/rdf.mapping.node.article.yml
@@ -11,12 +11,12 @@ fieldMappings:
properties:
- 'schema:dateCreated'
datatype_callback:
- callable: 'date_iso8601'
+ callable: 'Drupal\rdf\CommonDataConverter::dateIso8601Value'
changed:
properties:
- 'schema:dateModified'
datatype_callback:
- callable: 'date_iso8601'
+ callable: 'Drupal\rdf\CommonDataConverter::dateIso8601Value'
body:
properties:
- 'schema:text'
diff --git a/core/profiles/standard/config/install/rdf.mapping.node.page.yml b/core/profiles/standard/config/install/rdf.mapping.node.page.yml
index 8a5d377..38120ff 100644
--- a/core/profiles/standard/config/install/rdf.mapping.node.page.yml
+++ b/core/profiles/standard/config/install/rdf.mapping.node.page.yml
@@ -11,12 +11,12 @@ fieldMappings:
properties:
- 'schema:dateCreated'
datatype_callback:
- callable: 'date_iso8601'
+ callable: 'Drupal\rdf\CommonDataConverter::dateIso8601Value'
changed:
properties:
- 'schema:dateModified'
datatype_callback:
- callable: 'date_iso8601'
+ callable: 'Drupal\rdf\CommonDataConverter::dateIso8601Value'
body:
properties:
- 'schema:text'
diff --git a/core/themes/bartik/templates/node.html.twig b/core/themes/bartik/templates/node.html.twig
index d45b0f0..3e0d032 100644
--- a/core/themes/bartik/templates/node.html.twig
+++ b/core/themes/bartik/templates/node.html.twig
@@ -23,10 +23,8 @@
* - author_picture: The node author user entity, rendered using the "compact"
* view mode.
* - metadata: Metadata for this node.
- * - date: Formatted creation date. Preprocess functions can reformat it by
- * calling format_date() with the desired parameters on
- * $variables['created'].
- * - author_name: Themed username of node author output from theme_username().
+ * - date: Themed creation date field.
+ * - author_name: Themed author date field.
* - url: Direct URL of the current node.
* - display_submitted: Whether submission information should be displayed.
* - attributes: HTML attributes for the containing element.