reverted: --- b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php +++ a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php @@ -137,7 +137,7 @@ */ function getDefaultFeedItemCount() { // Our tests are based off of rss.xml, so let's find out how many elements should be related. + $feed_count = db_query_range('SELECT COUNT(DISTINCT nid) FROM {node_field_data} n WHERE n.promote = 1 AND n.status = 1', 0, config('system.rss')->get('items.limit'))->fetchField(); - $feed_count = db_query_range('SELECT COUNT(DISTINCT nid) FROM {node_field_data} n WHERE n.status = 1', 0, config('system.rss')->get('items.limit'))->fetchField(); return $feed_count > 10 ? 10 : $feed_count; } reverted: --- b/core/modules/book/book.install +++ a/core/modules/book/book.install @@ -42,6 +42,7 @@ $book_node_type = node_type_set_defaults($book_node_type); node_type_save($book_node_type); node_add_body_field($book_node_type); + // Default to not promoted. variable_set('node_options_book', array('status')); } reverted: --- b/core/modules/comment/lib/Drupal/comment/Tests/CommentInterfaceTest.php +++ a/core/modules/comment/lib/Drupal/comment/Tests/CommentInterfaceTest.php @@ -126,21 +126,21 @@ $this->assertText(t('The comment you are replying to does not exist.'), 'Replying to an unpublished comment'); // Attempt to post to node with comments disabled. + $this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'comment' => COMMENT_NODE_HIDDEN)); - $this->node = $this->drupalCreateNode(array('type' => 'article', 'comment' => COMMENT_NODE_HIDDEN)); $this->assertTrue($this->node, 'Article node created.'); $this->drupalGet('comment/reply/' . $this->node->nid); $this->assertText('This discussion is closed', 'Posting to node with comments disabled'); $this->assertNoField('edit-comment', 'Comment body field found.'); // Attempt to post to node with read-only comments. + $this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'comment' => COMMENT_NODE_CLOSED)); - $this->node = $this->drupalCreateNode(array('type' => 'article', 'comment' => COMMENT_NODE_CLOSED)); $this->assertTrue($this->node, 'Article node created.'); $this->drupalGet('comment/reply/' . $this->node->nid); $this->assertText('This discussion is closed', 'Posting to node with comments read-only'); $this->assertNoField('edit-comment', 'Comment body field found.'); // Attempt to post to node with comments enabled (check field names etc). + $this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'comment' => COMMENT_NODE_OPEN)); - $this->node = $this->drupalCreateNode(array('type' => 'article', 'comment' => COMMENT_NODE_OPEN)); $this->assertTrue($this->node, 'Article node created.'); $this->drupalGet('comment/reply/' . $this->node->nid); $this->assertNoText('This discussion is closed', 'Posting to node with comments enabled'); reverted: --- b/core/modules/comment/lib/Drupal/comment/Tests/CommentNewIndicatorTest.php +++ a/core/modules/comment/lib/Drupal/comment/Tests/CommentNewIndicatorTest.php @@ -38,7 +38,7 @@ // Test if the right links are displayed when no comment is present for the // node. $this->drupalLogin($this->admin_user); + $this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'comment' => COMMENT_NODE_OPEN)); - $this->node = $this->drupalCreateNode(array('type' => 'article', 'comment' => COMMENT_NODE_OPEN)); $this->drupalGet('node'); $this->assertNoLink(t('@count comments', array('@count' => 0))); $this->assertNoLink(t('@count new comments', array('@count' => 0))); reverted: --- b/core/modules/comment/lib/Drupal/comment/Tests/CommentPagerTest.php +++ a/core/modules/comment/lib/Drupal/comment/Tests/CommentPagerTest.php @@ -31,7 +31,7 @@ $this->setCommentPreview(DRUPAL_DISABLED); // Create a node and three comments. + $node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1)); - $node = $this->drupalCreateNode(array('type' => 'article')); $comments = array(); $comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE); $comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE); @@ -107,7 +107,7 @@ $this->setCommentsPerPage(1000); // Create a node and three comments. + $node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1)); - $node = $this->drupalCreateNode(array('type' => 'article')); $comments = array(); $comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE); $comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE); @@ -207,7 +207,7 @@ $this->setCommentsPerPage(1); // Create a node and three comments. + $node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1)); - $node = $this->drupalCreateNode(array('type' => 'article')); $comments = array(); $comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE); $comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE); reverted: --- b/core/modules/comment/lib/Drupal/comment/Tests/CommentTestBase.php +++ a/core/modules/comment/lib/Drupal/comment/Tests/CommentTestBase.php @@ -75,7 +75,7 @@ )); // Create a test node authored by the web user. + $this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'uid' => $this->web_user->uid)); - $this->node = $this->drupalCreateNode(array('type' => 'article', 'uid' => $this->web_user->uid)); } /** reverted: --- b/core/modules/comment/lib/Drupal/comment/Tests/CommentThreadingTest.php +++ a/core/modules/comment/lib/Drupal/comment/Tests/CommentThreadingTest.php @@ -36,7 +36,7 @@ // Create a node. $this->drupalLogin($this->web_user); + $this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'uid' => $this->web_user->uid)); - $this->node = $this->drupalCreateNode(array('type' => 'article', 'uid' => $this->web_user->uid)); // Post comment #1. $this->drupalLogin($this->web_user); reverted: --- b/core/modules/contextual/lib/Drupal/contextual/Tests/ContextualDynamicContextTest.php +++ a/core/modules/contextual/lib/Drupal/contextual/Tests/ContextualDynamicContextTest.php @@ -53,9 +53,9 @@ // - An article, which should be user-editable. // - A page, which should not be user-editable. // - A second article, which should also be user-editable. + $node1 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1)); + $node2 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 1)); + $node3 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1)); - $node1 = $this->drupalCreateNode(array('type' => 'article')); - $node2 = $this->drupalCreateNode(array('type' => 'page')); - $node3 = $this->drupalCreateNode(array('type' => 'article')); // Now, on the front page, all article nodes should have contextual links // placeholders, as should the view that contains them. reverted: --- b/core/modules/file/lib/Drupal/file/Tests/FileFieldRSSContentTest.php +++ a/core/modules/file/lib/Drupal/file/Tests/FileFieldRSSContentTest.php @@ -57,8 +57,9 @@ $edit = array("fields[$field_name][type]" => 'file_rss_enclosure'); $this->drupalPost(NULL, $edit, t('Save')); + // Create a new node with a file field set. Promote to frontpage + // needs to be set so this node will appear in the RSS feed. + $node = $this->drupalCreateNode(array('type' => $type_name, 'promote' => 1)); - // Create a new node with a file field set. - $node = $this->drupalCreateNode(array('type' => $type_name)); $test_file = $this->getTestFile('text'); // Create a new node with the uploaded file. reverted: --- b/core/modules/filter/lib/Drupal/filter/Tests/FilterSecurityTest.php +++ a/core/modules/filter/lib/Drupal/filter/Tests/FilterSecurityTest.php @@ -71,7 +71,7 @@ */ function testDisableFilterModule() { // Create a new node. + $node = $this->drupalCreateNode(array('promote' => 1)); - $node = $this->drupalCreateNode(); $body_raw = $node->body[Language::LANGCODE_NOT_SPECIFIED][0]['value']; $format_id = $node->body[Language::LANGCODE_NOT_SPECIFIED][0]['format']; $this->drupalGet('node/' . $node->nid); reverted: --- b/core/modules/forum/forum.install +++ a/core/modules/forum/forum.install @@ -12,7 +12,7 @@ // Set the weight of the forum.module to 1 so it is loaded after the taxonomy.module. module_set_weight('forum', 1); // Forum topics are published by default, but do not have any other default + // options set (for example, they are not promoted to the front page). - // options set. // @todo Convert to default module configuration, once Node module's content // types are converted. variable_set('node_options_forum', array('status')); reverted: --- b/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php +++ a/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php @@ -204,7 +204,7 @@ // Test loading multiple forum nodes on the front page. $this->drupalLogin($this->drupalCreateUser(array('administer content types', 'create forum content', 'post comments'))); + $this->drupalPost('admin/structure/types/manage/forum', array('node_options[promote]' => 'promote'), t('Save content type')); - $this->drupalPost('admin/structure/types/manage/forum', array(), t('Save content type')); $this->createForumTopic($this->forum, FALSE); $this->createForumTopic($this->forum, FALSE); $this->drupalGet('node'); reverted: --- b/core/modules/locale/lib/Drupal/locale/Tests/LocaleContentTest.php +++ a/core/modules/locale/lib/Drupal/locale/Tests/LocaleContentTest.php @@ -178,6 +178,7 @@ $nodes[$langcode] = $this->drupalCreateNode(array( 'langcode' => $langcode, 'type' => $type->type, + 'promote' => NODE_PROMOTED, )); } reverted: --- b/core/modules/locale/lib/Drupal/locale/Tests/LocalePathTest.php +++ a/core/modules/locale/lib/Drupal/locale/Tests/LocalePathTest.php @@ -119,8 +119,8 @@ $this->container->get('path.crud')->delete($edit); // Create language nodes to check priority of aliases. + $first_node = $this->drupalCreateNode(array('type' => 'page', 'promote' => 1)); + $second_node = $this->drupalCreateNode(array('type' => 'page', 'promote' => 1)); - $first_node = $this->drupalCreateNode(array('type' => 'page')); - $second_node = $this->drupalCreateNode(array('type' => 'page')); // Assign a custom path alias to the first node with the English language. $edit = array( reverted: --- /dev/null +++ a/core/modules/node/config/action.action.node_promote_action.yml @@ -0,0 +1,6 @@ +id: node_promote_action +label: 'Promote content to front page' +status: '1' +langcode: en +type: node +plugin: node_promote_action reverted: --- /dev/null +++ a/core/modules/node/config/action.action.node_unpromote_action.yml @@ -0,0 +1,6 @@ +id: node_unpromote_action +label: 'Remove content from front page' +status: '1' +langcode: en +type: node +plugin: node_unpromote_action reverted: --- b/core/modules/node/config/views.view.frontpage.yml +++ a/core/modules/node/config/views.view.frontpage.yml @@ -58,6 +58,42 @@ sort_asc_label: Asc sort_desc_label: Desc filters: + promote: + admin_label: '' + expose: + description: '' + identifier: '' + label: '' + multiple: '0' + operator: '' + operator_id: '0' + remember: '0' + remember_roles: + authenticated: authenticated + required: '0' + use_operator: '0' + exposed: '0' + field: promote + group: '1' + group_info: + default_group: All + default_group_multiple: { } + description: '' + group_items: { } + identifier: '' + label: '' + multiple: '0' + optional: '1' + remember: '0' + widget: select + group_type: group + id: promote + is_grouped: '0' + operator: '=' + relationship: none + table: node_field_data + value: '1' + plugin_id: boolean status: expose: operator: '0' reverted: --- b/core/modules/node/content_types.inc +++ a/core/modules/node/content_types.inc @@ -195,9 +195,10 @@ ); $form['workflow']['node_options'] = array('#type' => 'checkboxes', '#title' => t('Default options'), + '#default_value' => variable_get('node_options_' . $type->type, array('status', 'promote')), - '#default_value' => variable_get('node_options_' . $type->type, array('status')), '#options' => array( 'status' => t('Published'), + 'promote' => t('Promoted to front page'), 'sticky' => t('Sticky at top of lists'), 'revision' => t('Create new revision'), ), reverted: --- b/core/modules/node/lib/Drupal/node/NodeFormController.php +++ a/core/modules/node/lib/Drupal/node/NodeFormController.php @@ -28,10 +28,10 @@ protected function prepareEntity() { $node = $this->entity; // Set up default values, if required. + $node_options = variable_get('node_options_' . $node->type, array('status', 'promote')); - $node_options = variable_get('node_options_' . $node->type, array('status')); // If this is a new node, fill in the default values. if (!isset($node->nid) || isset($node->is_new)) { + foreach (array('status', 'promote', 'sticky') as $key) { - foreach (array('status', 'sticky') as $key) { // Multistep node forms might have filled in something already. if (!isset($node->$key)) { $node->$key = (int) in_array($key, $node_options); @@ -212,6 +212,12 @@ '#weight' => 95, ); + $form['options']['promote'] = array( + '#type' => 'checkbox', + '#title' => t('Promoted to front page'), + '#default_value' => $node->promote, + ); + $form['options']['sticky'] = array( '#type' => 'checkbox', '#title' => t('Sticky at top of lists'), reverted: --- b/core/modules/node/lib/Drupal/node/NodeStorageController.php +++ a/core/modules/node/lib/Drupal/node/NodeStorageController.php @@ -182,6 +182,11 @@ 'description' => t('Whether comments are allowed on this node: 0 = no, 1 = closed (read only), 2 = open (read/write).'), 'type' => 'integer_field', ); + $properties['promote'] = array( + 'label' => t('Promote'), + 'description' => t('A boolean indicating whether the node should be displayed on the front page.'), + 'type' => 'boolean_field', + ); $properties['sticky'] = array( 'label' => t('Sticky'), 'description' => t('A boolean indicating whether the node should be displayed at the top of lists in which it appears.'), reverted: --- /dev/null +++ a/core/modules/node/lib/Drupal/node/Plugin/Action/DemoteNode.php @@ -0,0 +1,33 @@ +promote = NODE_NOT_PROMOTED; + $entity->save(); + } + +} reverted: --- /dev/null +++ a/core/modules/node/lib/Drupal/node/Plugin/Action/PromoteNode.php @@ -0,0 +1,34 @@ +status = NODE_PUBLISHED; + $entity->promote = NODE_PROMOTED; + $entity->save(); + } + +} reverted: --- b/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php +++ a/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php @@ -144,6 +144,16 @@ public $comment; /** + * The node promotion status. + * + * Promoted nodes should be displayed on the front page of the site. The value + * is either NODE_PROMOTED or NODE_NOT_PROMOTED. + * + * @var \Drupal\Core\Entity\Field\FieldInterface + */ + public $promote; + + /** * The node sticky status. * * Sticky nodes should be displayed at the top of lists in which they appear. @@ -209,6 +219,7 @@ unset($this->created); unset($this->changed); unset($this->comment); + unset($this->promote); unset($this->sticky); unset($this->tnid); unset($this->translate); reverted: --- b/core/modules/node/lib/Drupal/node/Tests/MultiStepNodeFormBasicOptionsTest.php +++ a/core/modules/node/lib/Drupal/node/Tests/MultiStepNodeFormBasicOptionsTest.php @@ -66,10 +66,12 @@ $edit = array( 'title' => 'a', + 'promote' => FALSE, 'sticky' => 1, "{$this->field_name}[$langcode][0][value]" => $this->randomString(32), ); $this->drupalPost('node/add/page', $edit, t('Add another item')); + $this->assertNoFieldChecked('edit-promote', 'promote stayed unchecked'); $this->assertFieldChecked('edit-sticky', 'sticky stayed checked'); } reverted: --- b/core/modules/node/lib/Drupal/node/Tests/NodeAccessRecordsTest.php +++ a/core/modules/node/lib/Drupal/node/Tests/NodeAccessRecordsTest.php @@ -41,29 +41,36 @@ $this->assertEqual($records[0]->realm, 'test_article_realm', 'Grant with article_realm acquired for node without alteration.'); $this->assertEqual($records[0]->gid, 1, 'Grant with gid = 1 acquired for node without alteration.'); + // Create an unpromoted "Basic page" node. + $node2 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 0)); + $this->assertTrue(node_load($node2->nid), 'Unpromoted basic page node created.'); - // Create a "Basic page" node. - $node2 = $this->drupalCreateNode(array('type' => 'page')); - $this->assertTrue(node_load($node2->nid), 'Basic page node created.'); // Check to see if grants added by node_test_node_access_records made it in. $records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node2->nid))->fetchAll(); + $this->assertEqual(count($records), 1, 'Returned the correct number of rows.'); - $this->assertEqual(count($records), 2, 'Returned the correct number of rows.'); $this->assertEqual($records[0]->realm, 'test_page_realm', 'Grant with page_realm acquired for node without alteration.'); $this->assertEqual($records[0]->gid, 1, 'Grant with gid = 1 acquired for node without alteration.'); - $this->assertEqual($records[1]->realm, 'test_alter_realm', 'Altered grant with alter_realm acquired for node.'); - $this->assertEqual($records[1]->gid, 2, 'Altered grant with gid = 2 acquired for node.'); + // Create an unpromoted, unpublished "Basic page" node. + $node3 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 0, 'status' => 0)); + $this->assertTrue(node_load($node3->nid), 'Unpromoted, unpublished basic page node created.'); - // Create an unpublished "Basic page" node. - $node3 = $this->drupalCreateNode(array('type' => 'page', 'status' => 0)); - $this->assertTrue(node_load($node3->nid), 'Unpublished basic page node created.'); // Check to see if grants added by node_test_node_access_records made it in. $records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node3->nid))->fetchAll(); + $this->assertEqual(count($records), 1, 'Returned the correct number of rows.'); - $this->assertEqual(count($records), 2, 'Returned the correct number of rows.'); $this->assertEqual($records[0]->realm, 'test_page_realm', 'Grant with page_realm acquired for node without alteration.'); $this->assertEqual($records[0]->gid, 1, 'Grant with gid = 1 acquired for node without alteration.'); + + // Create a promoted "Basic page" node. + $node4 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 1)); + $this->assertTrue(node_load($node4->nid), 'Promoted basic page node created.'); + + // Check to see if grant added by node_test_node_access_records was altered + // by node_test_node_access_records_alter. + $records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node4->nid))->fetchAll(); + $this->assertEqual(count($records), 1, 'Returned the correct number of rows.'); + $this->assertEqual($records[0]->realm, 'test_alter_realm', 'Altered grant with alter_realm acquired for node.'); + $this->assertEqual($records[0]->gid, 2, 'Altered grant with gid = 2 acquired for node.'); - $this->assertEqual($records[1]->realm, 'test_alter_realm', 'Altered grant with alter_realm acquired for node.'); - $this->assertEqual($records[1]->gid, 2, 'Altered grant with gid = 2 acquired for node.'); // Check to see if we can alter grants with hook_node_grants_alter(). $operations = array('view', 'update', 'delete'); @@ -78,8 +85,8 @@ // Check that core does not grant access to an unpublished node when an // empty $grants array is returned. + $node6 = $this->drupalCreateNode(array('status' => 0, 'disable_node_access' => TRUE)); + $records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node6->nid))->fetchAll(); - $node4 = $this->drupalCreateNode(array('status' => 0, 'disable_node_access' => TRUE)); - $records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node4->nid))->fetchAll(); $this->assertEqual(count($records), 0, 'Returned no records for unpublished node.'); } } reverted: --- b/core/modules/node/lib/Drupal/node/Tests/NodeFormButtonsTest.php +++ a/core/modules/node/lib/Drupal/node/Tests/NodeFormButtonsTest.php @@ -108,7 +108,7 @@ // Set article content type default to unpublished. This will change the // the initial order of buttons and/or status of the node when creating // a node. + variable_set('node_options_article', array('promote')); - variable_set('node_options_article', array()); $this->refreshVariables(); // Verify the buttons on a node add form for an administrator. reverted: --- b/core/modules/node/lib/Drupal/node/Tests/NodeLoadMultipleTest.php +++ a/core/modules/node/lib/Drupal/node/Tests/NodeLoadMultipleTest.php @@ -37,12 +37,12 @@ * Creates four nodes and ensures that they are loaded correctly. */ function testNodeMultipleLoad() { + $node1 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1)); + $node2 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1)); + $node3 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 0)); + $node4 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 0)); - $node1 = $this->drupalCreateNode(array('type' => 'article', 'status' => 1)); - $node2 = $this->drupalCreateNode(array('type' => 'article', 'status' => 1)); - $node3 = $this->drupalCreateNode(array('type' => 'article', 'status' => 0)); - $node4 = $this->drupalCreateNode(array('type' => 'page', 'status' => 0)); + // Confirm that promoted nodes appear in the default node listing. - // Confirm that published nodes appear in the default node listing. $this->drupalGet('node'); $this->assertText($node1->label(), 'Node title appears on the default listing.'); $this->assertText($node2->label(), 'Node title appears on the default listing.'); @@ -50,7 +50,7 @@ $this->assertNoText($node4->label(), 'Node title does not appear in the default listing.'); // Load nodes with only a condition. Nodes 3 and 4 will be loaded. + $nodes = entity_load_multiple_by_properties('node', array('promote' => 0)); - $nodes = entity_load_multiple_by_properties('node', array('status' => 0)); $this->assertEqual($node3->label(), $nodes[$node3->nid]->label(), 'Node was loaded.'); $this->assertEqual($node4->label(), $nodes[$node4->nid]->label(), 'Node was loaded.'); $count = count($nodes); reverted: --- b/core/modules/node/lib/Drupal/node/Tests/NodeRSSContentTest.php +++ a/core/modules/node/lib/Drupal/node/Tests/NodeRSSContentTest.php @@ -46,7 +46,7 @@ */ function testNodeRSSContent() { // Create a node. + $node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1)); - $node = $this->drupalCreateNode(array('type' => 'article')); $this->drupalGet('rss.xml'); reverted: --- b/core/modules/node/lib/Drupal/node/Tests/NodeTitleTest.php +++ a/core/modules/node/lib/Drupal/node/Tests/NodeTitleTest.php @@ -41,8 +41,10 @@ */ function testNodeTitle() { // Create "Basic page" content with title. + // Add the node to the frontpage so we can test if teaser links are clickable. $settings = array( 'title' => $this->randomName(8), + 'promote' => 1, ); $node = $this->drupalCreateNode($settings); reverted: --- b/core/modules/node/lib/Drupal/node/Tests/SummaryLengthTest.php +++ a/core/modules/node/lib/Drupal/node/Tests/SummaryLengthTest.php @@ -26,6 +26,7 @@ // Create a node to view. $settings = array( 'body' => array(array('value' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vitae arcu at leo cursus laoreet. Curabitur dui tortor, adipiscing malesuada tempor in, bibendum ac diam. Cras non tellus a libero pellentesque condimentum. What is a Drupalism? Suspendisse ac lacus libero. Ut non est vel nisl faucibus interdum nec sed leo. Pellentesque sem risus, vulputate eu semper eget, auctor in libero. Ut fermentum est vitae metus convallis scelerisque. Phasellus pellentesque rhoncus tellus, eu dignissim purus posuere id. Quisque eu fringilla ligula. Morbi ullamcorper, lorem et mattis egestas, tortor neque pretium velit, eget eleifend odio turpis eu purus. Donec vitae metus quis leo pretium tincidunt a pulvinar sem. Morbi adipiscing laoreet mauris vel placerat. Nullam elementum, nisl sit amet scelerisque malesuada, dolor nunc hendrerit quam, eu ultrices erat est in orci. Curabitur feugiat egestas nisl sed accumsan.')), + 'promote' => 1, ); $node = $this->drupalCreateNode($settings); $this->assertTrue(node_load($node->nid), 'Node created.'); reverted: --- b/core/modules/node/lib/Drupal/node/Tests/Views/BulkFormTest.php +++ a/core/modules/node/lib/Drupal/node/Tests/Views/BulkFormTest.php @@ -38,7 +38,7 @@ $this->drupalGet('test-node-bulk-form'); $elements = $this->xpath('//select[@id="edit-action"]//option'); + $this->assertIdentical(count($elements), 8, 'All node operations are found.'); - $this->assertIdentical(count($elements), 6, 'All node operations are found.'); // Block a node using the bulk form. $this->assertTrue($node->status); reverted: --- b/core/modules/node/lib/Drupal/node/Tests/Views/FrontpageTest.php +++ a/core/modules/node/lib/Drupal/node/Tests/Views/FrontpageTest.php @@ -88,18 +88,27 @@ } } + // Create some nodes which aren't on the frontpage, either because they + // aren't promoted or because they aren't published. - // Create some nodes which aren't on the frontpage, because they aren't - // published. $not_expected_nids = array(); $values = array(); $values['type'] = 'article'; $values['title'] = $this->randomName(); + $values['status'] = TRUE; + $values['promote'] = FALSE; + $node = $this->nodeStorageController->create($values); + $node->save(); + $not_expected_nids[] = $node->id(); + + $values['promote'] = TRUE; $values['status'] = FALSE; + $values['title'] = $this->randomName(); $node = $this->nodeStorageController->create($values); $node->save(); $not_expected_nids[] = $node->id(); + $values['promote'] = TRUE; $values['sticky'] = TRUE; $values['status'] = FALSE; $values['title'] = $this->randomName(); reverted: --- b/core/modules/node/node.install +++ a/core/modules/node/node.install @@ -157,6 +157,12 @@ 'not null' => TRUE, 'default' => 0, ), + 'promote' => array( + 'description' => 'Boolean indicating whether the node translation should be displayed on the front page.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), 'sticky' => array( 'description' => 'Boolean indicating whether the node translation should be displayed at the top of lists in which it appears.', 'type' => 'int', @@ -169,7 +175,7 @@ 'node_created' => array('created'), 'node_default_langcode' => array('default_langcode'), 'node_langcode' => array('langcode'), + 'node_frontpage' => array('promote', 'status', 'sticky', 'created'), - 'node_frontpage' => array('status', 'sticky', 'created'), 'node_status_type' => array('status', 'type', 'nid'), 'node_title_type' => array('title', array('type', 4)), 'node_type' => array(array('type', 4)), @@ -275,6 +281,12 @@ 'not null' => TRUE, 'default' => 0, ), + 'promote' => array( + 'description' => 'Boolean indicating whether the node (at the time of this revision) should be displayed on the front page.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), 'sticky' => array( 'description' => 'Boolean indicating whether the node (at the time of this revision) should be displayed at the top of lists in which it appears.', 'type' => 'int', @@ -514,6 +526,7 @@ // Delete node search ranking variables. variable_del('node_rank_relevance'); variable_del('node_rank_sticky'); + variable_del('node_rank_promote'); variable_del('node_rank_recent'); // Delete remaining general module variables. @@ -912,6 +925,12 @@ 'not null' => TRUE, 'default' => 0, ), + 'promote' => array( + 'description' => 'Boolean indicating whether the node translation should be displayed on the front page.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), 'sticky' => array( 'description' => 'Boolean indicating whether the node translation should be displayed at the top of lists in which it appears.', 'type' => 'int', @@ -922,7 +941,7 @@ 'indexes' => array( 'node_changed' => array('changed'), 'node_created' => array('created'), + 'node_frontpage' => array('promote', 'status', 'sticky', 'created'), - 'node_frontpage' => array('status', 'sticky', 'created'), 'node_status_type' => array('status', 'type', 'nid'), 'node_title_type' => array('title', array('type', 4)), 'node_type' => array(array('type', 4)), @@ -1028,6 +1047,12 @@ 'not null' => TRUE, 'default' => 0, ), + 'promote' => array( + 'description' => 'Boolean indicating whether the node (at the time of this revision) should be displayed on the front page.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), 'sticky' => array( 'description' => 'Boolean indicating whether the node (at the time of this revision) should be displayed at the top of lists in which it appears.', 'type' => 'int', @@ -1118,7 +1143,7 @@ foreach ($indexes as $index) { db_drop_index('node', $index); } + $fields = array('title', 'uid', 'status', 'created', 'changed', 'comment', 'promote', 'sticky'); - $fields = array('title', 'uid', 'status', 'created', 'changed', 'comment', 'sticky'); foreach ($fields as $field) { db_drop_field('node', $field); } diff -u b/core/modules/node/node.module b/core/modules/node/node.module --- b/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -99,7 +99,7 @@ $output .= '

' . t('Uses') . '

'; $output .= '
'; $output .= '
' . t('Creating content') . '
'; - $output .= '
' . t('When new content is created, the Node module records basic information about the content, including the author, date of creation, and the Content type. It also manages the publishing options, which define whether or not the content is published and/or sticky at the top of content lists. Default settings can be configured for each type of content on your site.', array('@content-type' => url('admin/structure/types'))) . '
'; + $output .= '
' . t('When new content is created, the Node module records basic information about the content, including the author, date of creation, and the Content type. It also manages the publishing options, which define whether or not the content is published, promoted to the front page of the site, and/or sticky at the top of content lists. Default settings can be configured for each type of content on your site.', array('@content-type' => url('admin/structure/types'))) . '
'; $output .= '
' . t('Creating custom content types') . '
'; $output .= '
' . t('The Node module gives users with the Administer content types permission the ability to create new content types in addition to the default ones already configured. Creating custom content types allows you the flexibility to add fields and configure default settings that suit the differing needs of various site content.', array('@content-new' => url('admin/structure/types/add'), '@field' => url('admin/help/field'))) . '
'; $output .= '
' . t('Administering content') . '
'; @@ -746,11 +746,6 @@ // The sticky flag is either 0 or 1, which is automatically normalized. 'score' => 'n.sticky', ), - 'promote' => array( - 'title' => t('Content is promoted to the front page'), - // The promote flag is either 0 or 1, which is automatically normalized. - 'score' => 'n.promote', - ), ); // Add relevance based on creation or changed date. @@ -1081,6 +1076,9 @@ // Gather node classes. $variables['attributes']['class'][] = 'node'; $variables['attributes']['class'][] = drupal_html_class('node-' . $node->type); + if ($node->promote) { + $variables['attributes']['class'][] = 'promoted'; + } if ($node->sticky) { $variables['attributes']['class'][] = 'sticky'; } @@ -1323,6 +1321,11 @@ // The sticky flag is either 0 or 1, which is automatically normalized. 'score' => 'n.sticky', ), + 'promote' => array( + 'title' => t('Content is promoted to the front page'), + // The promote flag is either 0 or 1, which is automatically normalized. + 'score' => 'n.promote', + ), ); // Add relevance based on creation or changed date. @@ -1562,7 +1565,7 @@ $items['admin/structure/types'] = array( 'title' => 'Content types', - 'description' => 'Manage content types, including default status, comment settings, etc.', + 'description' => 'Manage content types, including default status, front page promotion, comment settings, etc.', 'page callback' => 'node_overview_types', 'access arguments' => array('administer content types'), 'file' => 'content_types.inc', @@ -1994,6 +1997,7 @@ $nids = db_select('node_field_data', 'n') ->distinct() ->fields('n', array('nid')) + ->condition('n.promote', 1) ->condition('n.status', 1) ->orderBy('n.created', 'DESC') ->range(0, $rss_config->get('items.limit')) reverted: --- b/core/modules/node/node.pages.inc +++ a/core/modules/node/node.pages.inc @@ -167,7 +167,7 @@ // Do we need to preview trimmed version of post as well as full version? if ($trimmed != $full) { + drupal_set_message(t('The trimmed version of your post shows what your post looks like when promoted to the main page or when exported for syndication. You can insert the delimiter "<!--break-->" (without the quotes) to fine-tune where your post gets split.')); - drupal_set_message(t('The trimmed version of your post shows what your post looks like when exported for syndication. You can insert the delimiter "<!--break-->" (without the quotes) to fine-tune where your post gets split.')); $output .= '

' . t('Preview trimmed version') . '

'; $output .= $trimmed; $output .= '

' . t('Preview full version') . '

'; reverted: --- b/core/modules/node/templates/node.html.twig +++ a/core/modules/node/templates/node.html.twig @@ -10,6 +10,7 @@ * - created: Formatted creation date. Preprocess functions can reformat it by * calling format_date() with the desired parameters on * $variables['node']->created. + * - promote: Whether the node is promoted to the front page. * - sticky: Whether the node is 'sticky'. Sticky nodes are ordered above * other non-sticky nodes in teaser listings * - status: Whether the node is published. @@ -45,6 +46,7 @@ * would result in: "view-mode-teaser", and full: "view-mode-full". * - preview: Whether a node is in preview mode. * The following are controlled through the node publishing options. + * - promoted: Appears on nodes promoted to the front page. * - sticky: Appears on nodes ordered above other non-sticky nodes in teaser * listings. * - unpublished: Appears on unpublished nodes visible only to site admins.