Commit 46973e74 authored by alexpott's avatar alexpott

Issue #111715 by andypost, swentel, tim.plunkett, sun, Berdir, amateescu,...

Issue #111715 by andypost, swentel, tim.plunkett, sun, Berdir, amateescu, kkaefer, YesCT, dagmar, chx: Convert node/content types into configuration.
parent 0d1cf2c1
......@@ -59,7 +59,15 @@ public function setOperation($operation) {
* {@inheritdoc}
*/
public function getBaseFormID() {
return $this->entity->entityType() . '_form';
// Assign ENTITYTYPE_form as base form ID to invoke corresponding
// hook_form_alter(), #validate, #submit, and #theme callbacks, but only if
// it is different from the actual form ID, since callbacks would be invoked
// twice otherwise.
$base_form_id = $this->entity->entityType() . '_form';
if ($base_form_id == $this->getFormID()) {
$base_form_id = '';
}
return $base_form_id;
}
/**
......
......@@ -182,7 +182,9 @@ public function render() {
'#empty' => t('There is no @label yet.', array('@label' => $this->entityInfo['label'])),
);
foreach ($this->load() as $entity) {
$build['#rows'][$entity->id()] = $this->buildRow($entity);
if ($row = $this->buildRow($entity)) {
$build['#rows'][$entity->id()] = $row;
}
}
return $build;
}
......
......@@ -5,14 +5,6 @@
* Install, update and uninstall functions for the book module.
*/
/**
* Implements hook_install().
*/
function book_install() {
// Add the node type.
_book_install_type_create();
}
/**
* Implements hook_uninstall().
*/
......@@ -24,28 +16,6 @@ function book_uninstall() {
menu_cache_clear_all();
}
/**
* Creates the book content type.
*/
function _book_install_type_create() {
// Create an additional node type.
$book_node_type = array(
'type' => 'book',
'name' => t('Book page'),
'base' => 'node_content',
'description' => t('<em>Books</em> have a built-in hierarchical navigation. Use for handbooks or tutorials.'),
'custom' => 1,
'modified' => 1,
'locked' => 0,
);
$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'));
}
/**
* Implements hook_schema().
*/
......
......@@ -6,6 +6,7 @@
*/
use Drupal\Core\Entity\EntityInterface;
use Drupal\node\NodeTypeInterface;
use Drupal\Core\Language\Language;
use Drupal\entity\Plugin\Core\Entity\EntityDisplay;
use Drupal\Core\Template\Attribute;
......@@ -1230,25 +1231,24 @@ function book_type_is_allowed($type) {
* Updates book.settings configuration object if the machine-readable name of a
* node type is changed.
*/
function book_node_type_update($type) {
if (!empty($type->old_type) && $type->old_type != $type->type) {
function book_node_type_update(NodeTypeInterface $type) {
if ($type->getOriginalID() != $type->id()) {
$config = config('book.settings');
// Update the list of node types that are allowed to be added to books.
$allowed_types = $config->get('allowed_types');
$old_key = array_search($type->old_type, $allowed_types);
$old_key = array_search($type->getOriginalID(), $allowed_types);
if ($old_key !== FALSE) {
// Replace the old machine-readable name with the new machine-readable
// name.
$allowed_types[$old_key] = $type->type;
$allowed_types[$old_key] = $type->id();
// Ensure that the allowed_types array is sorted consistently.
// @see book_admin_settings_submit()
// @see BookSettingsForm::submitForm()
sort($allowed_types);
$config->set('allowed_types', $allowed_types);
}
// Update the setting for the "Add child page" link.
if ($config->get('child_type') == $type->old_type) {
$config->set('child_type', $type->type);
if ($config->get('child_type') == $type->getOriginalID()) {
$config->set('child_type', $type->id());
}
$config->save();
}
......
type: book
uuid: c5ca890d-7db7-4c45-bf0f-0a12430923ff
name: 'Book page'
description: '<em>Books</em> have a built-in hierarchical navigation. Use for handbooks or tutorials.'
help: ''
has_title: '1'
title_label: Title
settings:
node:
preview: '1'
options:
status: status
# Not promoted to front page.
promote: '0'
sticky: '0'
revision: '0'
submitted: '1'
status: '1'
langcode: en
......@@ -69,9 +69,6 @@ function comment_modules_enabled($modules) {
// hook_node_type_insert() is used to create body fields while the comment
// module is enabled.
if (in_array('comment', $modules)) {
// Ensure that the list of node types reflects newly enabled modules.
node_types_rebuild();
// Create comment body fields for each node type, if needed.
foreach (node_type_get_types() as $type => $info) {
_comment_body_field_create($info);
......
......@@ -9,6 +9,7 @@
* book page, etc.
*/
use Drupal\node\NodeTypeInterface;
use Drupal\entity\Plugin\Core\Entity\EntityDisplay;
use Drupal\file\Plugin\Core\Entity\File;
use Drupal\Core\Entity\EntityInterface;
......@@ -113,25 +114,6 @@ function comment_entity_bundle_info() {
return $bundles;
}
/**
* Loads the comment bundle name corresponding a given content type.
*
* This function is used as a menu loader callback in comment_menu().
*
* @param $name
* The machine name of the node type whose comment fields are to be edited.
*
* @return
* The comment bundle name corresponding to the node type.
*
* @see comment_menu_alter()
*/
function comment_node_type_load($name) {
if ($type = node_type_load($name)) {
return 'comment_node_' . $type->type;
}
}
/**
* Entity URI callback.
*/
......@@ -277,10 +259,10 @@ function comment_menu_alter(&$items) {
// Adjust the Field UI tabs on admin/structure/types/manage/[node-type].
// See comment_entity_bundle_info().
$items['admin/structure/types/manage/%/comment/fields']['title'] = 'Comment fields';
$items['admin/structure/types/manage/%/comment/fields']['weight'] = 3;
$items['admin/structure/types/manage/%/comment/display']['title'] = 'Comment display';
$items['admin/structure/types/manage/%/comment/display']['weight'] = 4;
$items['admin/structure/types/manage/{bundle}/comment/fields']['title'] = 'Comment fields';
$items['admin/structure/types/manage/{bundle}/comment/fields']['weight'] = 3;
$items['admin/structure/types/manage/{bundle}/comment/display']['title'] = 'Comment display';
$items['admin/structure/types/manage/{bundle}/comment/display']['weight'] = 4;
}
/**
......@@ -309,9 +291,9 @@ function comment_node_type_insert($info) {
/**
* Implements hook_node_type_update().
*/
function comment_node_type_update($info) {
if (!empty($info->old_type) && $info->type != $info->old_type) {
entity_invoke_bundle_hook('rename', 'comment', 'comment_node_' . $info->old_type, 'comment_node_' . $info->type);
function comment_node_type_update(NodeTypeInterface $type) {
if ($type->original->id() != $type->id()) {
entity_invoke_bundle_hook('rename', 'comment', 'comment_node_' . $type->original->id(), 'comment_node_' . $type->id());
}
}
......@@ -990,6 +972,7 @@ function comment_view_multiple($comments, $view_mode = 'full', $langcode = NULL)
*/
function comment_form_node_type_form_alter(&$form, $form_state) {
if (isset($form['type'])) {
$node_type = $form_state['controller']->getEntity();
$form['comment'] = array(
'#type' => 'details',
'#title' => t('Comment settings'),
......@@ -1008,7 +991,7 @@ function comment_form_node_type_form_alter(&$form, $form_state) {
$form['comment']['comment'] = array(
'#type' => 'select',
'#title' => t('Default comment setting for new content'),
'#default_value' => variable_get('comment_' . $form['#node_type']->type, COMMENT_NODE_OPEN),
'#default_value' => variable_get('comment_' . $node_type->id(), COMMENT_NODE_OPEN),
'#options' => array(
COMMENT_NODE_OPEN => t('Open'),
COMMENT_NODE_CLOSED => t('Closed'),
......@@ -1018,19 +1001,19 @@ function comment_form_node_type_form_alter(&$form, $form_state) {
$form['comment']['comment_default_mode'] = array(
'#type' => 'checkbox',
'#title' => t('Threading'),
'#default_value' => variable_get('comment_default_mode_' . $form['#node_type']->type, COMMENT_MODE_THREADED),
'#default_value' => variable_get('comment_default_mode_' . $node_type->id(), COMMENT_MODE_THREADED),
'#description' => t('Show comment replies in a threaded list.'),
);
$form['comment']['comment_default_per_page'] = array(
'#type' => 'select',
'#title' => t('Comments per page'),
'#default_value' => variable_get('comment_default_per_page_' . $form['#node_type']->type, 50),
'#default_value' => variable_get('comment_default_per_page_' . $node_type->id(), 50),
'#options' => _comment_per_page(),
);
$form['comment']['comment_anonymous'] = array(
'#type' => 'select',
'#title' => t('Anonymous commenting'),
'#default_value' => variable_get('comment_anonymous_' . $form['#node_type']->type, COMMENT_ANONYMOUS_MAYNOT_CONTACT),
'#default_value' => variable_get('comment_anonymous_' . $node_type->id(), COMMENT_ANONYMOUS_MAYNOT_CONTACT),
'#options' => array(
COMMENT_ANONYMOUS_MAYNOT_CONTACT => t('Anonymous posters may not enter their contact information'),
COMMENT_ANONYMOUS_MAY_CONTACT => t('Anonymous posters may leave their contact information'),
......@@ -1041,17 +1024,17 @@ function comment_form_node_type_form_alter(&$form, $form_state) {
$form['comment']['comment_subject_field'] = array(
'#type' => 'checkbox',
'#title' => t('Allow comment title'),
'#default_value' => variable_get('comment_subject_field_' . $form['#node_type']->type, 1),
'#default_value' => variable_get('comment_subject_field_' . $node_type->id(), 1),
);
$form['comment']['comment_form_location'] = array(
'#type' => 'checkbox',
'#title' => t('Show reply form on the same page as comments'),
'#default_value' => variable_get('comment_form_location_' . $form['#node_type']->type, COMMENT_FORM_BELOW),
'#default_value' => variable_get('comment_form_location_' . $node_type->id(), COMMENT_FORM_BELOW),
);
$form['comment']['comment_preview'] = array(
'#type' => 'radios',
'#title' => t('Preview comment'),
'#default_value' => variable_get('comment_preview_' . $form['#node_type']->type, DRUPAL_OPTIONAL),
'#default_value' => variable_get('comment_preview_' . $node_type->id(), DRUPAL_OPTIONAL),
'#options' => array(
DRUPAL_DISABLED => t('Disabled'),
DRUPAL_OPTIONAL => t('Optional'),
......@@ -1062,7 +1045,7 @@ function comment_form_node_type_form_alter(&$form, $form_state) {
if (module_exists('content_translation')) {
$comment_form = $form;
$comment_form_state['content_translation']['key'] = 'language_configuration';
$form['comment'] += content_translation_enable_widget('comment', 'comment_node_' . $form['#node_type']->type, $comment_form, $comment_form_state);
$form['comment'] += translation_entity_enable_widget('comment', 'comment_node_' . $node_type->id(), $comment_form, $comment_form_state);
array_unshift($form['#submit'], 'comment_translation_configuration_element_submit');
}
}
......@@ -1084,7 +1067,7 @@ function comment_translation_configuration_element_submit($form, &$form_state) {
$key = 'language_configuration';
$comment_form_state = array(
'content_translation' => array('key' => $key),
'language' => array($key => array('entity_type' => 'comment', 'bundle' => 'comment_node_' . $form['#node_type']->type)),
'language' => array($key => array('entity_type' => 'comment', 'bundle' => 'comment_node_' . $form_state['controller']->getEntity()->id())),
'values' => array($key => array('content_translation' => $form_state['values']['content_translation'])),
);
content_translation_language_configuration_element_submit($form, $comment_form_state);
......
......@@ -202,19 +202,19 @@ public function testFieldComponent() {
* Tests renaming and deleting a bundle.
*/
public function testRenameDeleteBundle() {
$this->enableModules(array('field_sql_storage', 'field_test', 'node', 'system'));
$this->installSchema('node', array('node_type'));
$this->enableModules(array('field_sql_storage', 'field_test', 'node', 'system', 'text'));
$this->installSchema('system', array('variable'));
$this->installSchema('node', array('node'));
// Create a node bundle and display object.
node_type_save((object) array('type' => 'article'));
entity_create('node_type', array('type' => 'article'))->save();
entity_get_display('node', 'article', 'default')->save();
// Rename the article bundle and assert the entity display is renamed.
$info = node_type_load('article');
$info->old_type = 'article';
$info->type = 'article_rename';
node_type_save($info);
$info->save();
$old_display = entity_load('entity_display', 'node.article.default');
$this->assertFalse($old_display);
$new_display = entity_load('entity_display', 'node.article_rename.default');
......@@ -222,7 +222,7 @@ public function testRenameDeleteBundle() {
$this->assertEqual('node.article_rename.default', $new_display->id);
// Delete the bundle.
node_type_delete('article_rename');
$info->delete();
$display = entity_load('entity_display', 'node.article_rename.default');
$this->assertFalse($display);
}
......
......@@ -1176,7 +1176,7 @@ function field_entity_bundle_rename($entity_type, $bundle_old, $bundle_new) {
}
}
// Clear the cache.
// Clear the field cache.
field_cache_clear();
// Update bundle settings.
......
......@@ -80,7 +80,6 @@ public static function getInfo() {
function setUp() {
parent::setUp();
$this->installSchema('language', array('language'));
$this->installSchema('node', array('node_type'));
$this->field_name = drupal_strtolower($this->randomName() . '_field_name');
......
......@@ -267,13 +267,11 @@ function field_ui_entity_bundle_rename($entity_type, $bundle_old, $bundle_new) {
*/
function field_ui_form_node_type_form_alter(&$form, $form_state) {
// We want to display the button only on add page.
if (empty($form['#node_type']->type)) {
$form['actions']['save_continue'] = array(
'#type' => 'submit',
'#value' => t('Save and manage fields'),
'#weight' => 45,
);
$form['#submit'][] = 'field_ui_form_node_type_form_submit';
if ($form_state['controller']->getEntity()->isNew()) {
$form['actions']['save_continue'] = $form['actions']['submit'];
$form['actions']['save_continue']['#value'] = t('Save and manage fields');
$form['actions']['save_continue']['#weight'] = $form['actions']['save_continue']['#weight'] + 5;
$form['actions']['save_continue']['#submit'][] = 'field_ui_form_node_type_form_submit';
}
}
......
type: forum
uuid: c14b392d-0889-46bd-889e-a239e8b6cd89
name: 'Forum topic'
description: 'A <em>forum topic</em> starts a new discussion thread within a forum.'
help: ''
has_title: '1'
title_label: Subject
settings:
node:
preview: '1'
options:
status: status
# Not promoted to front page.
promote: '0'
sticky: '0'
revision: '0'
submitted: '1'
status: '1'
langcode: en
......@@ -11,11 +11,10 @@
function forum_install() {
// 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).
// @todo Convert to default module configuration, once Node module's content
// types are converted.
variable_set('node_options_forum', array('status'));
// Do not allow to delete the forum's node type machine name.
$locked = Drupal::state()->get('node.type.locked');
$locked['forum'] = 'forum';
Drupal::state()->set('node.type.locked', $locked);
}
/**
......@@ -106,11 +105,6 @@ function forum_enable() {
))
->save();
}
// Ensure the forum node type is available.
node_types_rebuild();
$types = node_type_get_types();
node_add_body_field($types['forum']);
}
/**
......@@ -120,8 +114,6 @@ function forum_uninstall() {
// Load the dependent Taxonomy module, in case it has been disabled.
drupal_load('module', 'taxonomy');
variable_del('node_options_forum');
if ($field = field_info_field('taxonomy_forums')) {
$field->delete();
}
......@@ -129,6 +121,10 @@ function forum_uninstall() {
// Purge field data now to allow taxonomy module to be uninstalled
// if this is the only field remaining.
field_purge_batch(10);
// Allow to delete a forum's node type.
$locked = Drupal::state()->get('node.type.locked');
unset($locked['forum']);
Drupal::state()->set('node.type.locked', $locked);
}
/**
......
......@@ -174,13 +174,13 @@ function forum_menu_local_tasks(&$data, $router_item, $root_path) {
$links = array();
// Loop through all bundles for forum taxonomy vocabulary field.
$field = field_info_field('taxonomy_forums');
foreach ($field['bundles']['node'] as $type) {
if (node_access('create', $type)) {
$links[$type] = array(
foreach ($field['bundles']['node'] as $type_name) {
if (($type = entity_load('node_type', $type_name)) && node_access('create', $type_name)) {
$links[$type_name] = array(
'#theme' => 'menu_local_action',
'#link' => array(
'title' => t('Add new @node_type', array('@node_type' => node_type_get_label($type))),
'href' => 'node/add/' . $type . '/' . $forum_term->id(),
'title' => t('Add new @node_type', array('@node_type' => $type->label())),
'href' => 'node/add/' . $type_name . '/' . $forum_term->id(),
),
);
}
......@@ -426,20 +426,6 @@ function forum_node_load($nodes) {
}
}
/**
* Implements hook_node_info().
*/
function forum_node_info() {
return array(
'forum' => array(
'name' => t('Forum topic'),
'base' => 'forum',
'description' => t('A <em>forum topic</em> starts a new discussion thread within a forum.'),
'title_label' => t('Subject'),
)
);
}
/**
* Implements hook_permission().
*/
......
......@@ -204,7 +204,7 @@ function testForum() {
// 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('settings[node][options][promote]' => 'promote'), t('Save content type'));
$this->createForumTopic($this->forum, FALSE);
$this->createForumTopic($this->forum, FALSE);
$this->drupalGet('node');
......
......@@ -5,6 +5,7 @@
* Add language handling functionality to Drupal.
*/
use Drupal\node\NodeTypeInterface;
use Drupal\Core\Language\Language;
/**
......@@ -322,6 +323,18 @@ function language_configuration_element_process($element, &$form_state, &$form)
),
);
// Do not add the submit callback for the language content settings page,
// which is handled separately.
if (array_search('language_content_settings_form_submit', $form['#submit']) === FALSE) {
// Determine where to attach the language_configuration element submit handler.
// @todo Form API: Allow form widgets/sections to declare #submit handlers.
if (isset($form['actions']['submit']['#submit']) && array_search('language_configuration_element_submit', $form['actions']['submit']['#submit']) === FALSE) {
$form['actions']['submit']['#submit'][] = 'language_configuration_element_submit';
}
elseif (array_search('language_configuration_element_submit', $form['#submit']) === FALSE) {
$form['#submit'][] = 'language_configuration_element_submit';
}
}
return $element;
}
......@@ -412,10 +425,10 @@ function language_get_default_configuration_settings_key($entity_type, $bundle)
/**
* Implements hook_node_type_update().
*/
function language_node_type_update($info) {
if (!empty($info->old_type) && $info->old_type != $info->type) {
language_save_default_configuration('node', $info->type, language_get_default_configuration('node', $info->old_type));
language_clear_default_configuration('node', $info->old_type);
function language_node_type_update(NodeTypeInterface $type) {
if ($type->original->id() != $type->id()) {
language_save_default_configuration('node', $type->id(), language_get_default_configuration('node', $type->original->id()));
language_clear_default_configuration('node', $type->original->id());
}
}
......
......@@ -670,7 +670,7 @@ function menu_node_submit(EntityInterface $node, $form, $form_state) {
*/
function menu_form_node_type_form_alter(&$form, $form_state) {
$menu_options = menu_get_menus();
$type = $form['#node_type'];
$type = $form_state['controller']->getEntity();
$form['menu'] = array(
'#type' => 'details',
'#title' => t('Menu settings'),
......@@ -683,7 +683,7 @@ function menu_form_node_type_form_alter(&$form, $form_state) {
$form['menu']['menu_options'] = array(
'#type' => 'checkboxes',
'#title' => t('Available menus'),
'#default_value' => variable_get('menu_options_' . $type->type, array('main')),
'#default_value' => variable_get('menu_options_' . $type->id(), array('main')),
'#options' => $menu_options,
'#description' => t('The menus available to place links in for this content type.'),
);
......@@ -696,7 +696,7 @@ function menu_form_node_type_form_alter(&$form, $form_state) {
$form['menu']['menu_parent'] = array(
'#type' => 'select',
'#title' => t('Default parent item'),
'#default_value' => variable_get('menu_parent_' . $type->type, 'main:0'),
'#default_value' => variable_get('menu_parent_' . $type->id(), 'main:0'),
'#options' => $options,
'#description' => t('Choose the menu item to be the default parent for a new link in the content authoring form.'),
'#attributes' => array('class' => array('menu-title-select')),
......
This diff is collapsed.
......@@ -18,10 +18,10 @@ Drupal.behaviors.contentTypes = {
});
$context.find('#edit-workflow').drupalSetSummary(function(context) {
var vals = [];
$(context).find("input[name^='node_options']:checked").parent().each(function() {
$(context).find("input[name^='settings[node][options']:checked").parent().each(function() {
vals.push(Drupal.checkPlain($(this).text()));
});
if (!$(context).find('#edit-node-options-status').is(':checked')) {
if (!$(context).find('#edit-settings-node-options-status').is(':checked')) {
vals.unshift(Drupal.t('Not published'));
}
return vals.join(', ');
......@@ -43,7 +43,7 @@ Drupal.behaviors.contentTypes = {
$context.find('input:checked').next('label').each(function() {
vals.push(Drupal.checkPlain($(this).text()));
});
if (!$context.find('#edit-node-submitted').is(':checked')) {
if (!$context.find('#edit-settings-node-submitted').is(':checked')) {
vals.unshift(Drupal.t("Don't display post information"));
}
return vals.join(', ');
......
<?php
/**
* @file
* Contains \Drupal\node\Form\NodeTypeDeleteConfirm.
*/
namespace Drupal\node\Form;
use Drupal\Core\Entity\EntityConfirmFormBase;
use Drupal\Core\Entity\EntityControllerInterface;
use Drupal\Core\Database\Connection;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Provides a form for content type deletion.
*/
class NodeTypeDeleteConfirm extends EntityConfirmFormBase implements EntityControllerInterface {
/**
* The database connection.
*
* @var \Drupal\Core\Database\Connection
*/
protected $database;
/**
* Constructs a new NodeTypeDeleteConfirm object.
*
* @param \Drupal\Core\Database\Connection $database
* The database connection.
*/