diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index bab2af5..08464ab 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1845,6 +1845,24 @@ function theme_dropbutton_wrapper($variables) {
}
/**
+ * Returns HTML for wrapping a dropbutton list.
+ *
+ * Use this function if the dropbutton contains submit buttons. These elements
+ * need to have a #prefix and #suffix element that wraps those into an
+ * element.
+ *
+ * @param array $variables
+ * An associative array containing:
+ * - element: An associative array containing the properties and children of
+ * the dropbutton list. Properties used: #children.
+ */
+function theme_dropbutton_list_wrapper($variables) {
+ if (!empty($variables['element']['#children'])) {
+ return '';
+ }
+}
+
+/**
* Returns HTML for an image.
*
* @param $variables
@@ -3155,6 +3173,9 @@ function drupal_common_theme() {
'dropbutton_wrapper' => array(
'render element' => 'element',
),
+ 'dropbutton_list_wrapper' => array(
+ 'render element' => 'element',
+ ),
'image' => array(
// HTML 4 and XHTML 1.0 always require an alt attribute. The HTML 5 draft
// allows the alt attribute to be omitted in some cases. Therefore,
diff --git a/core/modules/file/lib/Drupal/file/Tests/FileFieldDisplayTest.php b/core/modules/file/lib/Drupal/file/Tests/FileFieldDisplayTest.php
index 9d7dd30..9d30a2f 100644
--- a/core/modules/file/lib/Drupal/file/Tests/FileFieldDisplayTest.php
+++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldDisplayTest.php
@@ -64,7 +64,7 @@ function testNodeDisplay() {
// Turn the "display" option off and check that the file is no longer displayed.
$edit = array($field_name . '[' . LANGUAGE_NOT_SPECIFIED . '][0][display]' => FALSE);
- $this->drupalPost('node/' . $nid . '/edit', $edit, t('Save'));
+ $this->drupalPost('node/' . $nid . '/edit', $edit, t('Save and keep published'));
$this->assertNoRaw($default_output, t('Field is hidden when "display" option is unchecked.'));
diff --git a/core/modules/file/lib/Drupal/file/Tests/FileFieldRevisionTest.php b/core/modules/file/lib/Drupal/file/Tests/FileFieldRevisionTest.php
index 480f411..47d19d1 100644
--- a/core/modules/file/lib/Drupal/file/Tests/FileFieldRevisionTest.php
+++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldRevisionTest.php
@@ -71,7 +71,7 @@ function testRevisions() {
// Save a new version of the node without any changes.
// Check that the file is still the same as the previous revision.
- $this->drupalPost('node/' . $nid . '/edit', array('revision' => '1'), t('Save'));
+ $this->drupalPost('node/' . $nid . '/edit', array('revision' => '1'), t('Save and keep published'));
$node = node_load($nid, TRUE);
$node_file_r3 = file_load($node->{$field_name}[LANGUAGE_NOT_SPECIFIED][0]['fid']);
$node_vid_r3 = $node->vid;
diff --git a/core/modules/file/lib/Drupal/file/Tests/FileFieldTestBase.php b/core/modules/file/lib/Drupal/file/Tests/FileFieldTestBase.php
index 458eb4c..60b5f52 100644
--- a/core/modules/file/lib/Drupal/file/Tests/FileFieldTestBase.php
+++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldTestBase.php
@@ -149,7 +149,7 @@ function uploadNodeFile($file, $field_name, $nid_or_type, $new_revision = TRUE,
// Attach a file to the node.
$edit['files[' . $field_name . '_' . $langcode . '_0]'] = drupal_realpath($file->uri);
- $this->drupalPost("node/$nid/edit", $edit, t('Save'));
+ $this->drupalPost("node/$nid/edit", $edit, t('Save and keep published'));
return $nid;
}
@@ -165,7 +165,7 @@ function removeNodeFile($nid, $new_revision = TRUE) {
);
$this->drupalPost('node/' . $nid . '/edit', array(), t('Remove'));
- $this->drupalPost(NULL, $edit, t('Save'));
+ $this->drupalPost(NULL, $edit, t('Save and keep published'));
}
/**
@@ -178,7 +178,7 @@ function replaceNodeFile($file, $field_name, $nid, $new_revision = TRUE) {
);
$this->drupalPost('node/' . $nid . '/edit', array(), t('Remove'));
- $this->drupalPost(NULL, $edit, t('Save'));
+ $this->drupalPost(NULL, $edit, t('Save and keep published'));
}
/**
diff --git a/core/modules/file/lib/Drupal/file/Tests/FileFieldValidateTest.php b/core/modules/file/lib/Drupal/file/Tests/FileFieldValidateTest.php
index 050931b..7a40a1c 100644
--- a/core/modules/file/lib/Drupal/file/Tests/FileFieldValidateTest.php
+++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldValidateTest.php
@@ -37,7 +37,7 @@ function testRequired() {
// Try to post a new node without uploading a file.
$langcode = LANGUAGE_NOT_SPECIFIED;
$edit = array("title" => $this->randomName());
- $this->drupalPost('node/add/' . $type_name, $edit, t('Save'));
+ $this->drupalPost('node/add/' . $type_name, $edit, t('Save and publish'));
$this->assertRaw(t('!title field is required.', array('!title' => $instance['label'])), t('Node save failed when required file field was empty.'));
// Create a new node with the uploaded file.
@@ -56,7 +56,7 @@ function testRequired() {
// Try to post a new node without uploading a file in the multivalue field.
$edit = array('title' => $this->randomName());
- $this->drupalPost('node/add/' . $type_name, $edit, t('Save'));
+ $this->drupalPost('node/add/' . $type_name, $edit, t('Save and publish'));
$this->assertRaw(t('!title field is required.', array('!title' => $instance['label'])), t('Node save failed when required multiple value file field was empty.'));
// Create a new node with the uploaded file into the multivalue field.
diff --git a/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php b/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php
index 7fcf35f..3d5f782 100644
--- a/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php
+++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php
@@ -73,7 +73,7 @@ function testSingleValuedWidget() {
$this->assertTrue(isset($label[0]), 'Label for upload found.');
// Save the node and ensure it does not have the file.
- $this->drupalPost(NULL, array(), t('Save'));
+ $this->drupalPost(NULL, array(), t('Save and keep published'));
$node = node_load($nid, TRUE);
$this->assertTrue(empty($node->{$field_name}[LANGUAGE_NOT_SPECIFIED][0]['fid']), t('File was successfully removed from the node.'));
}
@@ -191,7 +191,7 @@ function testMultiValuedWidget() {
$this->assertNoFieldByXPath('//input[@type="submit"]', t('Remove'), t('After removing all files, there is no "Remove" button displayed (JSMode=%type).', array('%type' => $type)));
// Save the node and ensure it does not have any files.
- $this->drupalPost(NULL, array('title' => $this->randomName()), t('Save'));
+ $this->drupalPost(NULL, array('title' => $this->randomName()), t('Save and publish'));
$matches = array();
preg_match('/node\/([0-9]+)/', $this->getUrl(), $matches);
$nid = $matches[1];
@@ -268,7 +268,7 @@ function testPrivateFileComment() {
$edit = array(
'title' => $this->randomName(),
);
- $this->drupalPost('node/add/article', $edit, t('Save'));
+ $this->drupalPost('node/add/article', $edit, t('Save and publish'));
$node = $this->drupalGetNodeByTitle($edit['title']);
// Add a comment with a file.
@@ -302,10 +302,7 @@ function testPrivateFileComment() {
// Unpublishes node.
$this->drupalLogin($this->admin_user);
- $edit = array(
- 'status' => FALSE,
- );
- $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+ $this->drupalPost('node/' . $node->nid . '/edit', array(), t('Save and unpublish'));
// Ensures normal user can no longer download the file.
$this->drupalLogin($user);
diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterAdminTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterAdminTest.php
index e7b1330..a54a739 100644
--- a/core/modules/filter/lib/Drupal/filter/Tests/FilterAdminTest.php
+++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterAdminTest.php
@@ -219,7 +219,7 @@ function testFilterAdmin() {
$edit["title"] = $this->randomName();
$edit["body[$langcode][0][value]"] = $text;
$edit["body[$langcode][0][format]"] = $filtered;
- $this->drupalPost('node/add/page', $edit, t('Save'));
+ $this->drupalPost('node/add/page', $edit, t('Save and publish'));
$this->assertRaw(t('Basic page %title has been created.', array('%title' => $edit["title"])), 'Filtered node created.');
$node = $this->drupalGetNodeByTitle($edit["title"]);
@@ -231,7 +231,7 @@ function testFilterAdmin() {
// Use plain text and see if it escapes all tags, whether allowed or not.
$edit = array();
$edit["body[$langcode][0][format]"] = $plain;
- $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+ $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save and keep published'));
$this->drupalGet('node/' . $node->nid);
$this->assertText(check_plain($text), 'The "Plain text" text format escapes all HTML tags.');
diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterFormatAccessTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterFormatAccessTest.php
index a71a9e9..ce6372e 100644
--- a/core/modules/filter/lib/Drupal/filter/Tests/FilterFormatAccessTest.php
+++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterFormatAccessTest.php
@@ -207,7 +207,7 @@ function testFormatWidgetPermissions() {
$edit['title'] = $this->randomName(8);
$edit[$body_value_key] = $this->randomName(16);
$edit[$body_format_key] = $this->disallowed_format->format;
- $this->drupalPost('node/add/page', $edit, t('Save'));
+ $this->drupalPost('node/add/page', $edit, t('Save and publish'));
$node = $this->drupalGetNodeByTitle($edit['title']);
// Try to edit with a less privileged user.
diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterHooksTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterHooksTest.php
index 71e89fb..442eff4 100644
--- a/core/modules/filter/lib/Drupal/filter/Tests/FilterHooksTest.php
+++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterHooksTest.php
@@ -71,7 +71,7 @@ function testFilterHooks() {
"body[$language_not_specified][0][value]" => $this->randomName(32),
"body[$language_not_specified][0][format]" => $format_id,
);
- $this->drupalPost("node/add/{$type->type}", $edit, t('Save'));
+ $this->drupalPost("node/add/{$type->type}", $edit, t('Save and publish'));
$this->assertText(t('@type @title has been created.', array('@type' => $type_name, '@title' => $title)));
// Disable the text format.
diff --git a/core/modules/forum/lib/Drupal/forum/Tests/ForumBlockTest.php b/core/modules/forum/lib/Drupal/forum/Tests/ForumBlockTest.php
index f36c5a9..d54e30a 100644
--- a/core/modules/forum/lib/Drupal/forum/Tests/ForumBlockTest.php
+++ b/core/modules/forum/lib/Drupal/forum/Tests/ForumBlockTest.php
@@ -172,7 +172,7 @@ protected function createForumTopics($count = 5) {
);
// Create the forum topic, preselecting the forum ID via a URL parameter.
- $this->drupalPost('node/add/forum/1', $edit, t('Save'));
+ $this->drupalPost('node/add/forum/1', $edit, t('Save and publish'));
$topics[] = $title;
}
diff --git a/core/modules/forum/lib/Drupal/forum/Tests/ForumIndexTest.php b/core/modules/forum/lib/Drupal/forum/Tests/ForumIndexTest.php
index 7ae7d5f..27e4384 100644
--- a/core/modules/forum/lib/Drupal/forum/Tests/ForumIndexTest.php
+++ b/core/modules/forum/lib/Drupal/forum/Tests/ForumIndexTest.php
@@ -55,7 +55,7 @@ function testForumIndexStatus() {
);
// Create the forum topic, preselecting the forum ID via a URL parameter.
- $this->drupalPost('node/add/forum/' . $tid, $edit, t('Save'));
+ $this->drupalPost('node/add/forum/' . $tid, $edit, t('Save and publish'));
// Check that the node exists in the database.
$node = $this->drupalGetNodeByTitle($title);
@@ -66,10 +66,7 @@ function testForumIndexStatus() {
$this->assertText($title, 'Published forum topic appears on index.');
// Unpublish the node.
- $edit = array(
- 'status' => FALSE,
- );
- $this->drupalPost("node/{$node->nid}/edit", $edit, t('Save'));
+ $this->drupalPost("node/{$node->nid}/edit", array(), t('Save and unpublish'));
$this->drupalGet("node/{$node->nid}");
$this->assertText(t('Access denied'), 'Unpublished node is no longer accessible.');
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php
index 1cfda9f..7c42a5b 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php
@@ -187,7 +187,7 @@ function testImageFieldSettings() {
$field_name . '[' . LANGUAGE_NOT_SPECIFIED . '][0][alt]' => $image_info['alt'],
$field_name . '[' . LANGUAGE_NOT_SPECIFIED . '][0][title]' => $image_info['title'],
);
- $this->drupalPost('node/' . $nid . '/edit', $edit, t('Save'));
+ $this->drupalPost('node/' . $nid . '/edit', $edit, t('Save and keep published'));
$default_output = theme('image', $image_info);
$this->assertRaw($default_output, 'Image displayed using user supplied alt and title attributes.');
@@ -197,7 +197,7 @@ function testImageFieldSettings() {
$field_name . '[' . LANGUAGE_NOT_SPECIFIED . '][0][alt]' => $this->randomName($test_size),
$field_name . '[' . LANGUAGE_NOT_SPECIFIED . '][0][title]' => $this->randomName($test_size),
);
- $this->drupalPost('node/' . $nid . '/edit', $edit, t('Save'));
+ $this->drupalPost('node/' . $nid . '/edit', $edit, t('Save and keep published'));
$this->assertRaw(t('Alternate text cannot be longer than %max characters but is currently %length characters long.', array(
'%max' => $schema['fields'][$field_name .'_alt']['length'],
'%length' => $test_size,
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php
index f3f7f86..5a4e20e 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php
@@ -118,7 +118,7 @@ function uploadNodeImage($image, $field_name, $type) {
'title' => $this->randomName(),
);
$edit['files[' . $field_name . '_' . LANGUAGE_NOT_SPECIFIED . '_0]'] = drupal_realpath($image->uri);
- $this->drupalPost('node/add/' . $type, $edit, t('Save'));
+ $this->drupalPost('node/add/' . $type, $edit, t('Save and publish'));
// Retrieve ID of the newly created node from the current URL.
$matches = array();
diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php
index 47e1f30..a7354ee 100644
--- a/core/modules/node/lib/Drupal/node/NodeFormController.php
+++ b/core/modules/node/lib/Drupal/node/NodeFormController.php
@@ -239,7 +239,7 @@ public function form(array $form, array &$form_state, EntityInterface $node) {
$form['options'] = array(
'#type' => 'details',
'#access' => user_access('administer nodes'),
- '#title' => t('Publishing options'),
+ '#title' => t('Promotion options'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#group' => 'advanced',
@@ -252,12 +252,6 @@ public function form(array $form, array &$form_state, EntityInterface $node) {
'#weight' => 95,
);
- $form['options']['status'] = array(
- '#type' => 'checkbox',
- '#title' => t('Published'),
- '#default_value' => $node->status,
- );
-
$form['options']['promote'] = array(
'#type' => 'checkbox',
'#title' => t('Promoted to front page'),
@@ -281,6 +275,89 @@ public function form(array $form, array &$form_state, EntityInterface $node) {
}
/**
+ * Overrides Drupal\entity\EntityFormController::actionsElement().
+ */
+ protected function actionsElement(array $form, array &$form_state) {
+ $element = parent::actionsElement($form, $form_state);
+ $node = $this->getEntity($form_state);
+
+ // Because some of the 'links' are actually submit buttons, we have to
+ // manually wrap each item in and the whole list in . The
+ // is added with a #theme_wrappers function.
+ $element['operations'] = array(
+ '#type' => 'operations',
+ '#subtype' => 'node',
+ '#attached' => array (
+ 'css' => array(
+ drupal_get_path('module', 'node') . '/node.admin.css',
+ ),
+ ),
+ );
+
+ $element['operations']['actions'] = array(
+ '#theme_wrappers' => array('dropbutton_list_wrapper')
+ );
+
+ // Depending on the state of the node (published or unpublished) and
+ // whether the current user has the permission to change the status, the
+ // labels and order of the buttons will vary.
+ if (user_access('administer nodes')) {
+ $element['operations']['actions']['publish'] = array(
+ '#type' => 'submit',
+ '#value' => t('Save and publish'),
+ '#submit' => array(array($this, 'publish'), array($this, 'submit'), array($this, 'save')),
+ '#validate' => array(array($this, 'validate')),
+ '#button_type' => $node->status ? 'primary' : '',
+ '#weight' => 0,
+ '#prefix' => '- ',
+ '#suffix' => '
',
+ );
+ $element['operations']['actions']['unpublish'] = array(
+ '#type' => 'submit',
+ '#value' => t('Save as unpublished'),
+ '#submit' => array(array($this, 'unpublish'), array($this, 'submit'), array($this, 'save')),
+ '#validate' => array(array($this, 'validate')),
+ '#button_type' => empty($node->status) ? 'primary' : '',
+ '#weight' => $node->status ? 1 : -1,
+ '#prefix' => '- ',
+ "#suffix" => '
',
+ );
+
+ if (!empty($node->nid)) {
+ if ($node->status) {
+ $publish_label = t('Save and keep published');
+ $unpublish_label = t('Save and unpublish');
+ }
+ else {
+ $publish_label = t('Save and publish');
+ $unpublish_label = t('Save and keep unpublished');
+ }
+ $element['operations']['actions']['publish']['#value'] = $publish_label;
+ $element['operations']['actions']['unpublish']['#value'] = $unpublish_label;
+ }
+ }
+ // The user has no permission to change the status of the node. Just
+ // show a save button without the 'publish' or 'unpublish' callback in
+ // the #submit definition.
+ else {
+ $element['operations']['actions']['save'] = array(
+ '#type' => 'submit',
+ '#value' => t('Save'),
+ '#submit' => array(array($this, 'submit'), array($this, 'save')),
+ '#validate' => array(array($this, 'validate')),
+ '#button_type' => 'primary',
+ '#weight' => 1,
+ '#prefix' => '- ',
+ "#suffix" => '
',
+ );
+ }
+
+ unset($element['submit']);
+
+ return $element;
+ }
+
+ /*
* Overrides Drupal\Core\Entity\EntityFormController::actions().
*/
protected function actions(array $form, array &$form_state) {
@@ -387,6 +464,34 @@ public function preview(array $form, array &$form_state) {
}
/**
+ * Form submission handler for the 'publish' action.
+ *
+ * @param $form
+ * An associative array containing the structure of the form.
+ * @param $form_state
+ * A reference to a keyed array containing the current state of the form.
+ */
+ public function publish(array $form, array &$form_state) {
+ $node = $this->getEntity($form_state);
+ $node->status = TRUE;
+ return $node;
+ }
+
+ /**
+ * Form submission handler for the 'unpublish' action.
+ *
+ * @param $form
+ * An associative array containing the structure of the form.
+ * @param $form_state
+ * A reference to a keyed array containing the current state of the form.
+ */
+ public function unpublish(array $form, array &$form_state) {
+ $node = $this->getEntity($form_state);
+ $node->status = FALSE;
+ return $node;
+ }
+
+ /**
* Overrides Drupal\Core\Entity\EntityFormController::save().
*/
public function save(array $form, array &$form_state) {
diff --git a/core/modules/node/lib/Drupal/node/Tests/MultiStepNodeFormBasicOptionsTest.php b/core/modules/node/lib/Drupal/node/Tests/MultiStepNodeFormBasicOptionsTest.php
index 873c7ea..769db0a 100644
--- a/core/modules/node/lib/Drupal/node/Tests/MultiStepNodeFormBasicOptionsTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/MultiStepNodeFormBasicOptionsTest.php
@@ -42,14 +42,12 @@ function setUp() {
function testMultiStepNodeFormBasicOptions() {
$edit = array(
'title' => 'a',
- 'status' => FALSE,
'promote' => FALSE,
'sticky' => 1,
'choice[new:0][chtext]' => 'a',
'choice[new:1][chtext]' => 'a',
);
$this->drupalPost('node/add/poll', $edit, t('Add another choice'));
- $this->assertNoFieldChecked('edit-status', 'status stayed unchecked');
$this->assertNoFieldChecked('edit-promote', 'promote stayed unchecked');
$this->assertFieldChecked('edit-sticky', 'sticky stayed checked');
}
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeCreationTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeCreationTest.php
index 36baad2..27ae8bd 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeCreationTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeCreationTest.php
@@ -113,7 +113,7 @@ function testUnpublishedNodeCreation() {
$edit = array();
$edit["title"] = $this->randomName(8);
$edit["body[" . LANGUAGE_NOT_SPECIFIED . "][0][value]"] = $this->randomName(16);
- $this->drupalPost('node/add/page', $edit, t('Save'));
+ $this->drupalPost('node/add/page', $edit, t('Save as unpublished'));
// Check that the user was redirected to the home page.
$this->assertUrl('');
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php
index ce6591f..f3f0b15 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php
@@ -105,7 +105,7 @@ function testLanguageFieldVisibility() {
'title' => $this->randomName(8),
"body[$langcode][0][value]" => $this->randomName(16),
);
- $this->drupalPost('node/add/article', $edit, t('Save'));
+ $this->drupalPost('node/add/article', $edit, t('Save and publish'));
$node = $this->drupalGetNodeByTitle($edit['title']);
$this->assertTrue($node, 'Node found in database.');
diff --git a/core/modules/node/lib/Drupal/node/Tests/PageEditTest.php b/core/modules/node/lib/Drupal/node/Tests/PageEditTest.php
index 20ebfbd..b461492 100644
--- a/core/modules/node/lib/Drupal/node/Tests/PageEditTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/PageEditTest.php
@@ -81,7 +81,7 @@ function testPageEdit() {
$edit['title'] = $this->randomName(8);
$edit[$body_key] = $this->randomName(16);
$edit['revision'] = TRUE;
- $this->drupalPost(NULL, $edit, t('Save'));
+ $this->drupalPost(NULL, $edit, t('Save and keep published'));
// Ensure that the node revision has been created.
$revised_node = $this->drupalGetNodeByTitle($edit['title'], TRUE);
@@ -108,7 +108,7 @@ function testPageAuthoredBy() {
$edit = array();
$edit['title'] = $this->randomName(8);
$edit[$body_key] = $this->randomName(16);
- $this->drupalPost('node/add/page', $edit, t('Save'));
+ $this->drupalPost('node/add/page', $edit, t('Save and publish'));
// Check that the node was authored by the currently logged in user.
$node = $this->drupalGetNodeByTitle($edit['title']);
@@ -118,20 +118,20 @@ function testPageAuthoredBy() {
$edit = array(
'name' => 'invalid-name',
);
- $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+ $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save and keep published'));
$this->assertText('The username invalid-name does not exist.');
// Change the authored by field to an empty string, which should assign
// authorship to the anonymous user (uid 0).
$edit['name'] = '';
- $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+ $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save and keep published'));
$node = node_load($node->nid, TRUE);
$this->assertIdentical($node->uid, '0', 'Node authored by anonymous user.');
// Change the authored by field to another user's name (that is not
// logged in).
$edit['name'] = $this->web_user->name;
- $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+ $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save and keep published'));
$node = node_load($node->nid, TRUE);
$this->assertIdentical($node->uid, $this->web_user->uid, 'Node authored by normal user.');
diff --git a/core/modules/node/node.admin.css b/core/modules/node/node.admin.css
index 101a38d..829dd7d 100644
--- a/core/modules/node/node.admin.css
+++ b/core/modules/node/node.admin.css
@@ -9,3 +9,29 @@
.revision-current {
background: #ffc;
}
+
+/**
+ * Node form dropbuttons.
+ */
+.form-actions .dropbutton-wrapper {
+ float: left;
+ margin-right: 1em;
+}
+
+.dropbutton-wrapper .dropbutton-widget {
+ position: static;
+}
+
+.form-actions .dropbutton-wrapper li a,
+.form-actions .dropbutton-wrapper input {
+ padding: 4px 17px;
+ margin-bottom: 0em;
+ border: medium;
+ border-radius: 0;
+ background: none;
+}
+
+.form-actions .dropbutton-wrapper input:hover {
+ background: none;
+ border: none;
+}
diff --git a/core/modules/node/node.admin.inc b/core/modules/node/node.admin.inc
index 74f100c..10a12c6 100644
--- a/core/modules/node/node.admin.inc
+++ b/core/modules/node/node.admin.inc
@@ -435,7 +435,7 @@ function node_admin_nodes() {
'#attributes' => array('class' => array('container-inline')),
'#access' => $admin_access,
'#attached' => array (
- 'css' => array(drupal_get_path('module', 'node') . '/node.admin.css'),
+ 'css' => array(drupal_get_path('module', 'node') . '/css/node-admin.theme.css'),
),
);
$options = array();
diff --git a/core/modules/node/node.js b/core/modules/node/node.js
index cdc8cbe..b61c117 100644
--- a/core/modules/node/node.js
+++ b/core/modules/node/node.js
@@ -38,14 +38,15 @@ Drupal.behaviors.nodeDetailsSummaries = {
var $context = $(context);
var vals = [];
- $context.find('input:checked').parent().each(function () {
- vals.push(Drupal.checkPlain($.trim($(this).text())));
- });
-
- if (!$context.find('.form-item-status input').is(':checked')) {
- vals.unshift(Drupal.t('Not published'));
+ if ($context.find('input').is(':checked')) {
+ $context.find('input:checked').parent().each(function () {
+ vals.push(Drupal.checkPlain($.trim($(this).text())));
+ });
+ return vals.join(', ');
+ }
+ else {
+ return Drupal.t('Not promoted');
}
- return vals.join(', ');
});
$context.find('fieldset.node-translation-options').drupalSetSummary(function (context) {
diff --git a/core/modules/poll/lib/Drupal/poll/Tests/PollDeleteChoiceTest.php b/core/modules/poll/lib/Drupal/poll/Tests/PollDeleteChoiceTest.php
index ccbd044..d9afce4 100644
--- a/core/modules/poll/lib/Drupal/poll/Tests/PollDeleteChoiceTest.php
+++ b/core/modules/poll/lib/Drupal/poll/Tests/PollDeleteChoiceTest.php
@@ -32,7 +32,7 @@ function testChoiceRemoval() {
// Edit the poll, and try to delete first poll choice.
$this->drupalGet("node/$poll_nid/edit");
$edit['choice[chid:1][chtext]'] = '';
- $this->drupalPost(NULL, $edit, t('Save'));
+ $this->drupalPost(NULL, $edit, t('Save and keep published'));
// Click on the poll title to go to node page.
$this->drupalGet('poll');
diff --git a/core/modules/poll/lib/Drupal/poll/Tests/PollExpirationTest.php b/core/modules/poll/lib/Drupal/poll/Tests/PollExpirationTest.php
index 2cfe9e5..a53183b 100644
--- a/core/modules/poll/lib/Drupal/poll/Tests/PollExpirationTest.php
+++ b/core/modules/poll/lib/Drupal/poll/Tests/PollExpirationTest.php
@@ -40,7 +40,7 @@ function testAutoExpire() {
$edit = array();
$poll_expiration = 604800; // One week.
$edit['runtime'] = $poll_expiration;
- $this->drupalPost(NULL, $edit, t('Save'));
+ $this->drupalPost(NULL, $edit, t('Save and keep published'));
$this->assertRaw(t('Poll %title has been updated.', array('%title' => $title)), 'Poll expiration settings saved.');
// Make sure that the changed expiration settings is kept.
diff --git a/core/modules/poll/lib/Drupal/poll/Tests/PollTestBase.php b/core/modules/poll/lib/Drupal/poll/Tests/PollTestBase.php
index 94da1ef..5b40096 100644
--- a/core/modules/poll/lib/Drupal/poll/Tests/PollTestBase.php
+++ b/core/modules/poll/lib/Drupal/poll/Tests/PollTestBase.php
@@ -51,7 +51,7 @@ function pollCreate($title, $choices, $preview = TRUE) {
// Verify that the vote count element only allows non-negative integers.
$edit['choice[new:1][chvotes]'] = -1;
$edit['choice[new:0][chvotes]'] = $this->randomString(7);
- $this->drupalPost(NULL, $edit, t('Save'));
+ $this->drupalPost(NULL, $edit, t('Save and publish'));
$this->assertText(t('Vote count for new choice must be higher or equal to 0.'));
$this->assertText(t('Vote count for new choice must be a number.'));
@@ -75,7 +75,7 @@ function pollCreate($title, $choices, $preview = TRUE) {
list($edit, $index) = $this->_pollGenerateEdit($title, $choices, $index);
}
- $this->drupalPost(NULL, $edit, t('Save'));
+ $this->drupalPost(NULL, $edit, t('Save and keep published'));
$node = $this->drupalGetNodeByTitle($title);
$this->assertText(t('@type @title has been created.', array('@type' => node_type_get_label('poll'), '@title' => $title)), 'Poll has been created.');
$this->assertTrue($node->nid, 'Poll has been found in the database.');
@@ -196,7 +196,7 @@ function assertPollChoiceOrder(array $choices, $index = 0, $preview = FALSE) {
*/
function pollUpdate($nid, $title, $edit) {
// Edit the poll node.
- $this->drupalPost('node/' . $nid . '/edit', $edit, t('Save'));
+ $this->drupalPost('node/' . $nid . '/edit', $edit, t('Save and keep published'));
$this->assertText(t('@type @title has been updated.', array('@type' => node_type_get_label('poll'), '@title' => $title)), 'Poll has been updated.');
}
}
diff --git a/core/modules/search/lib/Drupal/search/Tests/SearchConfigSettingsFormTest.php b/core/modules/search/lib/Drupal/search/Tests/SearchConfigSettingsFormTest.php
index 3e80c72..894fd67 100644
--- a/core/modules/search/lib/Drupal/search/Tests/SearchConfigSettingsFormTest.php
+++ b/core/modules/search/lib/Drupal/search/Tests/SearchConfigSettingsFormTest.php
@@ -45,7 +45,7 @@ function setUp() {
$langcode = LANGUAGE_NOT_SPECIFIED;
$body_key = "body[$langcode][0][value]";
$edit[$body_key] = l($node->label(), 'node/' . $node->nid) . ' pizza sandwich';
- $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+ $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save and keep published'));
node_update_index();
search_update_totals();
diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php
index dcf53b0..60d526b 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php
@@ -282,7 +282,7 @@ function testBreadCrumbs() {
$edit = array(
'menu[parent]' => $link['menu_name'] . ':' . $link['mlid'],
);
- $this->drupalPost("node/{$parent->nid}/edit", $edit, t('Save'));
+ $this->drupalPost("node/{$parent->nid}/edit", $edit, t('Save and keep published'));
$expected = array(
"node" => $link['link_title'],
);
@@ -308,7 +308,7 @@ function testBreadCrumbs() {
$edit = array(
"field_tags[$langcode]" => implode(',', array_keys($tags)),
);
- $this->drupalPost("node/{$parent->nid}/edit", $edit, t('Save'));
+ $this->drupalPost("node/{$parent->nid}/edit", $edit, t('Save and keep published'));
// Put both terms into a hierarchy Drupal ยป Breadcrumbs. Required for both
// the menu links and the terms itself, since taxonomy_term_page() resets
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/LegacyTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/LegacyTest.php
index d00f373..b9898c6 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/LegacyTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/LegacyTest.php
@@ -39,7 +39,7 @@ function testTaxonomyLegacyNode() {
$edit['date'] = '1969-01-01 00:00:00 -0500';
$edit["body[$langcode][0][value]"] = $this->randomName();
$edit["field_tags[$langcode]"] = $this->randomName();
- $this->drupalPost('node/add/article', $edit, t('Save'));
+ $this->drupalPost('node/add/article', $edit, t('Save and publish'));
// Checks that the node has been saved.
$node = $this->drupalGetNodeByTitle($edit['title']);
$this->assertEqual($node->created, strtotime($edit['date']), 'Legacy node was saved with the right date.');
diff --git a/core/modules/text/lib/Drupal/text/Tests/TextTranslationTest.php b/core/modules/text/lib/Drupal/text/Tests/TextTranslationTest.php
index 742ec1f..dd5d1bd 100644
--- a/core/modules/text/lib/Drupal/text/Tests/TextTranslationTest.php
+++ b/core/modules/text/lib/Drupal/text/Tests/TextTranslationTest.php
@@ -78,7 +78,7 @@ function testTextField() {
);
// Translate the article in french.
- $this->drupalPost('node/add/article', $edit, t('Save'));
+ $this->drupalPost('node/add/article', $edit, t('Save and publish'));
$node = $this->drupalGetNodeByTitle($edit['title']);
$this->drupalGet("node/$node->nid/translate");
$this->clickLink(t('add translation'));
@@ -107,7 +107,7 @@ function testTextFieldFormatted() {
'title' => $title,
'langcode' => 'en',
);
- $this->drupalPost('node/add/article', $edit, t('Save'));
+ $this->drupalPost('node/add/article', $edit, t('Save and publish'));
// Populate the body field: the first item gets the "Full HTML" input
// format, the second one "Filtered HTML".
@@ -118,7 +118,7 @@ function testTextFieldFormatted() {
"body[$langcode][$delta][value]" => $value,
"body[$langcode][$delta][format]" => array_shift($formats),
);
- $this->drupalPost('node/1/edit', $edit, t('Save'));
+ $this->drupalPost('node/1/edit', $edit, t('Save and keep published'));
$this->assertText($body[$delta], t('The body field with delta @delta has been saved.', array('@delta' => $delta)));
}
diff --git a/core/modules/translation/lib/Drupal/translation/Tests/TranslationTest.php b/core/modules/translation/lib/Drupal/translation/Tests/TranslationTest.php
index b3c1ec1..5dfd181 100644
--- a/core/modules/translation/lib/Drupal/translation/Tests/TranslationTest.php
+++ b/core/modules/translation/lib/Drupal/translation/Tests/TranslationTest.php
@@ -75,9 +75,9 @@ function testContentTranslation() {
// Unpublish the original node to check that this has no impact on the
// translation overview page, publish it again afterwards.
$this->drupalLogin($this->admin_user);
- $this->drupalPost('node/' . $node->nid . '/edit', array('status' => FALSE), t('Save'));
+ $this->drupalPost('node/' . $node->nid . '/edit', array(), t('Save and unpublish'));
$this->drupalGet('node/' . $node->nid . '/translate');
- $this->drupalPost('node/' . $node->nid . '/edit', array('status' => NODE_PUBLISHED), t('Save'));
+ $this->drupalPost('node/' . $node->nid . '/edit', array(), t('Save and publish'));
$this->drupalLogin($this->translator);
// Check that the "add translation" link uses a localized path.
@@ -169,8 +169,7 @@ function testLanguageSwitchLinks() {
// Unpublish the Spanish translation to check that the related language
// switch link is not shown.
$this->drupalLogin($this->admin_user);
- $edit = array('status' => FALSE);
- $this->drupalPost("node/$translation_es->nid/edit", $edit, t('Save'));
+ $this->drupalPost("node/$translation_es->nid/edit", array(), t('Save and unpublish'));
$this->drupalLogin($this->translator);
$this->assertLanguageSwitchLinks($node, $translation_es, FALSE);
@@ -180,8 +179,7 @@ function testLanguageSwitchLinks() {
$edit = array('language_interface[enabled][language-url]' => FALSE);
$this->drupalPost('admin/config/regional/language/detection', $edit, t('Save settings'));
$this->resetCaches();
- $edit = array('status' => TRUE);
- $this->drupalPost("node/$translation_es->nid/edit", $edit, t('Save'));
+ $this->drupalPost("node/$translation_es->nid/edit", array(), t('Save and publish'));
$this->drupalLogin($this->translator);
$this->assertLanguageSwitchLinks($node, $translation_es, TRUE, 'node');
}
diff --git a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationUITest.php b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationUITest.php
index 8c2dcef..f6a562f 100644
--- a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationUITest.php
+++ b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationUITest.php
@@ -164,9 +164,14 @@ function testTranslationUI() {
$values[$langcode] = $this->getNewEntityValues($langcode);
$controller = translation_entity_controller($this->entityType);
+ $publish_add_button = $publish_edit_button = t('Save');
+ if (user_access('administer nodes') && $this->entityType == 'node') {
+ $publish_add_button = t('Save and publish');
+ $publish_edit_button = t('Save and keep published');
+ }
$base_path = $controller->getBasePath($entity);
$path = $langcode . '/' . $base_path . '/translations/add/' . $default_langcode . '/' . $langcode;
- $this->drupalPost($path, $this->getEditValues($values, $langcode), t('Save'));
+ $this->drupalPost($path, $this->getEditValues($values, $langcode), $publish_add_button);
if ($this->testLanguageSelector) {
$this->assertNoFieldByXPath('//select[@id="edit-langcode"]', NULL, 'Language selector correclty disabled on translations.');
}
@@ -183,7 +188,7 @@ function testTranslationUI() {
// Add another translation and mark the other ones as outdated.
$values[$langcode] = $this->getNewEntityValues($langcode);
$edit = $this->getEditValues($values, $langcode) + array('translation[retranslate]' => TRUE);
- $this->drupalPost($path, $edit, t('Save'));
+ $this->drupalPost($path, $edit, $publish_edit_button);
$entity = entity_load($this->entityType, $entity->id(), TRUE);
// Check that the entered values have been correctly stored.
@@ -208,7 +213,7 @@ function testTranslationUI() {
else {
$this->assertFieldByXPath('//input[@name="translation[translate]"]', TRUE, 'The translate flag is checked by default.');
$edit = array('translation[translate]' => FALSE);
- $this->drupalPost($path, $edit, t('Save'));
+ $this->drupalPost($path, $edit, $publish_edit_button);
$this->drupalGet($path);
$this->assertFieldByXPath('//input[@name="translation[retranslate]"]', FALSE, 'The retranslate flag is now shown.');
$entity = entity_load($this->entityType, $entity->id(), TRUE);
diff --git a/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php b/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php
index 6416193..0a56ad2 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php
@@ -107,14 +107,14 @@ function testTaggedWith() {
$edit = array();
$edit['title'] = $node_tag1_title = $this->randomName();
$edit[$tag_field] = 'tag1';
- $this->drupalPost($node_add_path, $edit, t('Save'));
+ $this->drupalPost($node_add_path, $edit, t('Save and publish'));
$edit = array();
$edit['title'] = $node_tag1_tag2_title = $this->randomName();
$edit[$tag_field] = 'tag1, tag2';
- $this->drupalPost($node_add_path, $edit, t('Save'));
+ $this->drupalPost($node_add_path, $edit, t('Save and publish'));
$edit = array();
$edit['title'] = $node_no_tags_title = $this->randomName();
- $this->drupalPost($node_add_path, $edit, t('Save'));
+ $this->drupalPost($node_add_path, $edit, t('Save and publish'));
// Create a view that filters by taxonomy term "tag1". It should show only
// the two nodes from above that are tagged with "tag1".
diff --git a/core/themes/seven/style.css b/core/themes/seven/style.css
index 445730f..a109ed8 100644
--- a/core/themes/seven/style.css
+++ b/core/themes/seven/style.css
@@ -747,9 +747,12 @@ select.form-select:focus {
margin-right: 0;
margin-top: 10px;
padding-bottom: 6px;
- padding-top: 6px;
width: 100%;
}
+ .form-actions input:first-child,
+ .form-wrapper input[type="submit"]:first-child {
+ margin-top: 0;
+ }
.exposed-filters .filters,
.exposed-filters .form-item label,
.exposed-filters .form-select {
@@ -1068,6 +1071,34 @@ div.add-or-remove-shortcuts {
text-overflow: clip;
}
+.js .form-actions .dropbutton-widget {
+ background-color: #9dcae7;
+ background-image: none;
+ border: 1px solid #8eB7cd;
+ border-bottom-color: #7691a2;
+ color: #133B54;
+}
+.js .form-actions .dropbutton-widget:focus,
+.js .form-actions .dropbutton-widget:hover {
+ background-color: #73b3dd;
+ border: 1px solid #6ea3bf;
+ border-bottom-color: #4680a0;
+}
+.js .form-actions .dropbutton-widget:active {
+ background-color: #3981b1;
+ border: 1px solid #36647c;
+ border-bottom-color: #284657;
+}
+.js .form-actions .dropbutton-multiple.open .dropbutton-widget:hover {
+ background-color: #9dcae7;
+}
+.js .form-actions .dropbutton-multiple.open .dropbutton-widget:hover {
+ background-color: #9dcae7;
+}
+.js .form-actions .dropbutton-multiple.open .dropbutton-action:hover {
+ background-color: #73b3dd;
+}
+
/* Disable overlay message */
#overlay-disable-message {
background-color: #addafc;