drupal/core/modules/comment/comment.install

715 lines
24 KiB
Plaintext

<?php
/**
* @file
* Install, update and uninstall functions for the Comment module.
*/
use Drupal\Core\Language\Language;
use Drupal\comment\Plugin\Field\FieldType\CommentItem;
use Drupal\field\Entity\Field;
/**
* Implements hook_uninstall().
*/
function comment_uninstall() {
// Remove the comment fields.
$fields = entity_load_multiple_by_properties('field_entity', array('type' => 'comment'));
foreach ($fields as $field) {
entity_invoke_bundle_hook('delete', 'comment', $field->entity_type . '__' . $field->name);
$field->delete();
}
// Remove state setting.
\Drupal::state()->delete('comment.node_comment_statistics_scale');
}
/**
* Implements hook_install().
*/
function comment_install() {
// By default, maintain entity statistics for comments.
// @see \Drupal\comment\CommentStorageController::updateEntityStatistics().
\Drupal::state()->set('comment.maintain_entity_statistics', TRUE);
}
/**
* Implements hook_schema().
*/
function comment_schema() {
$schema['comment'] = array(
'description' => 'Stores comments and associated data.',
'fields' => array(
'cid' => array(
'type' => 'serial',
'not null' => TRUE,
'description' => 'Primary Key: Unique comment ID.',
),
'uuid' => array(
'description' => 'Unique Key: Universally unique identifier for this entity.',
'type' => 'varchar',
'length' => 128,
'not null' => FALSE,
),
'pid' => array(
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The {comment}.cid to which this comment is a reply. If set to 0, this comment is not a reply to an existing comment.',
),
'entity_id' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The entity_id of the entity to which this comment is a reply.',
),
'entity_type' => array(
'type' => 'varchar',
'not null' => TRUE,
'default' => 'node',
'length' => 255,
'description' => 'The entity_type of the entity to which this comment is a reply.',
),
'field_id' => array(
'type' => 'varchar',
'not null' => TRUE,
'default' => 'node.comment',
'length' => 255,
'description' => 'The field_id of the field that was used to add this comment.',
),
'uid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The {users}.uid who authored the comment. If set to 0, this comment was created by an anonymous user.',
),
'subject' => array(
'type' => 'varchar',
'length' => 64,
'not null' => TRUE,
'default' => '',
'description' => 'The comment title.',
),
'hostname' => array(
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
'default' => '',
'description' => "The author's host name.",
),
'created' => array(
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The time that the comment was created, as a Unix timestamp.',
),
'changed' => array(
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The time that the comment was last edited, as a Unix timestamp.',
),
'status' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 1,
'size' => 'tiny',
'description' => 'The published status of a comment. (0 = Not Published, 1 = Published)',
),
'thread' => array(
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'description' => "The alphadecimal representation of the comment's place in a thread, consisting of a base 36 string prefixed by an integer indicating its length.",
),
'name' => array(
'type' => 'varchar',
'length' => 60,
'not null' => FALSE,
'description' => "The comment author's name. Uses {users}.name if the user is logged in, otherwise uses the value typed into the comment form.",
),
'mail' => array(
'type' => 'varchar',
'length' => 64,
'not null' => FALSE,
'description' => "The comment author's e-mail address from the comment form, if user is anonymous, and the 'Anonymous users may/must leave their contact information' setting is turned on.",
),
'homepage' => array(
'type' => 'varchar',
'length' => 255,
'not null' => FALSE,
'description' => "The comment author's home page address from the comment form, if user is anonymous, and the 'Anonymous users may/must leave their contact information' setting is turned on.",
),
'langcode' => array(
'description' => 'The {language}.langcode of this comment.',
'type' => 'varchar',
'length' => 12,
'not null' => TRUE,
'default' => '',
),
),
'indexes' => array(
'comment_status_pid' => array('pid', 'status'),
'comment_num_new' => array(
'entity_id',
array('entity_type', 32),
array('field_id', 32),
'status',
'created',
'cid',
'thread',
),
'comment_uid' => array('uid'),
'comment_entity_langcode' => array(
'entity_id',
array('entity_type', 32),
array('field_id', 32),
'langcode',
),
'comment_created' => array('created'),
),
'primary key' => array('cid'),
'unique keys' => array(
'uuid' => array('uuid'),
),
'foreign keys' => array(
'comment_author' => array(
'table' => 'users',
'columns' => array('uid' => 'uid'),
),
),
);
$schema['comment_entity_statistics'] = array(
'description' => 'Maintains statistics of entity and comments posts to show "new" and "updated" flags.',
'fields' => array(
'entity_id' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The entity_id of the entity for which the statistics are compiled.',
),
'entity_type' => array(
'type' => 'varchar',
'not null' => TRUE,
'default' => 'node',
'length' => 255,
'description' => 'The entity_type of the entity to which this comment is a reply.',
),
'field_id' => array(
'type' => 'varchar',
'not null' => TRUE,
'default' => 'node__comment',
'length' => 255,
'description' => 'The field_id of the field that was used to add this comment.',
),
'cid' => array(
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The {comment}.cid of the last comment.',
),
'last_comment_timestamp' => array(
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The Unix timestamp of the last comment that was posted within this node, from {comment}.changed.',
),
'last_comment_name' => array(
'type' => 'varchar',
'length' => 60,
'not null' => FALSE,
'description' => 'The name of the latest author to post a comment on this node, from {comment}.name.',
),
'last_comment_uid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The user ID of the latest author to post a comment on this node, from {comment}.uid.',
),
'comment_count' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The total number of comments on this entity.',
),
),
'primary key' => array('entity_id', array('entity_type', 32), array('field_id', 32)),
'indexes' => array(
'last_comment_timestamp' => array('last_comment_timestamp'),
'comment_count' => array('comment_count'),
'last_comment_uid' => array('last_comment_uid'),
),
'foreign keys' => array(
'last_comment_author' => array(
'table' => 'users',
'columns' => array(
'last_comment_uid' => 'uid',
),
),
),
);
return $schema;
}
/**
* @addtogroup updates-7.x-to-8.x
* @{
*/
/**
* Implements hook_update_dependencies().
*/
function comment_update_dependencies() {
// Node comment status cannot be turned into fields until after the fields and
// instances are converted to ConfigEntities.
$dependencies['comment'][8006]['field'] = 8003;
return $dependencies;
}
/**
* Renames {comment}.language to {comment}.langcode.
*/
function comment_update_8000() {
db_drop_index('comment', 'comment_nid_language');
$langcode_spec = array(
'type' => 'varchar',
'length' => 12,
'not null' => TRUE,
'default' => '',
'description' => "Language code, e.g. 'de' or 'en-US'.",
);
db_change_field('comment', 'language', 'langcode', $langcode_spec);
db_add_index('comment', 'comment_nid_langcode', array('nid', 'langcode'));
}
/**
* Create a UUID column for comments.
*/
function comment_update_8001() {
$spec = array(
'description' => 'Unique Key: Universally unique identifier for this entity.',
'type' => 'varchar',
'length' => 128,
'not null' => FALSE,
);
$keys = array(
'unique keys' => array(
'uuid' => array('uuid'),
),
);
// Account for sites having the contributed UUID module installed.
if (db_field_exists('comment', 'uuid')) {
db_change_field('comment', 'uuid', 'uuid', $spec, $keys);
}
else {
db_add_field('comment', 'uuid', $spec, $keys);
}
}
/**
* Make *id fields unsigned.
*/
function comment_update_8002() {
db_drop_index('comment', 'comment_num_new');
db_drop_index('comment', 'comment_nid_langcode');
db_change_field('comment', 'nid', 'nid',
array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The {node}.nid to which this comment is a reply.',
),
array('indexes' => array(
'comment_num_new' => array('nid', 'status', 'created', 'cid', 'thread'),
'comment_nid_langcode' => array('nid', 'langcode'),
))
);
db_drop_index('comment', 'comment_uid');
db_change_field('comment', 'uid', 'uid',
array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The {users}.uid who authored the comment. If set to 0, this comment was created by an anonymous user.',
),
array('indexes' => array(
'comment_uid' => array('uid'),
))
);
db_drop_index('node_comment_statistics', 'last_comment_uid');
db_change_field('node_comment_statistics', 'last_comment_uid', 'last_comment_uid',
array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The user ID of the latest author to post a comment on this node, from {comment}.uid.',
),
array('indexes' => array(
'last_comment_uid' => array('last_comment_uid'),
))
);
}
/**
* Generate a UUID for all comments.
*/
function comment_update_8003(&$sandbox) {
if (!isset($sandbox['progress'])) {
$sandbox['progress'] = 0;
$sandbox['last'] = 0;
$sandbox['max'] = db_query('SELECT COUNT(cid) FROM {comment} WHERE uuid IS NULL')->fetchField();
}
$cids = db_query_range('SELECT cid FROM {comment} WHERE cid > :cid AND uuid IS NULL ORDER BY cid ASC', 0, 10, array(':cid' => $sandbox['last']))->fetchCol();
update_add_uuids($sandbox, 'comment', 'cid', $cids);
$sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']);
}
/**
* Convert variables to state.
*/
function comment_update_8004() {
update_variables_to_state(array(
'node_cron_comments_scale' => 'comment.node_comment_statistics_scale',
'comment_maintain_node_statistics' => 'comment.maintain_entity_statistics',
));
}
/**
* Update the {comment_node_statistics} and {comment} tables to new structure.
*/
function comment_update_8005(&$sandbox) {
// Drop old indexes.
if (db_index_exists('comment', 'comment_node')) {
// Drop the comment_node foreign key.
db_drop_index('comment', 'comment_node');
}
db_drop_index('comment', 'comment_num_new');
db_drop_index('comment', 'comment_nid_langcode');
// Add the entity_type and field id columns to comment.
db_add_field('comment', 'entity_type', array(
'type' => 'varchar',
'not null' => TRUE,
'default' => 'node',
'length' => 255,
'description' => 'The entity_type of the entity to which this comment is a reply.',
));
db_add_field('comment', 'field_id', array(
'type' => 'varchar',
'not null' => TRUE,
'default' => 'node__comment',
'length' => 255,
'description' => 'The field_id of the field that was used to add this comment.',
));
// Rename the nid column to entity_id.
db_change_field('comment', 'nid', 'entity_id', array(
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The entity_id of the entity to which this comment is a reply.',
));
db_add_index('comment', 'comment_num_new', array(
'entity_id',
array('entity_type', 32),
array('field_id', 32),
'status',
'created',
'cid',
'thread'
));
// Add the comment_entity_langcode index.
db_add_index('comment', 'comment_entity_langcode', array(
'entity_id',
array('entity_type', 32),
array('field_id', 32),
'langcode',
));
// We need to drop all indexes to make sure their constrains named properly.
db_drop_primary_key('node_comment_statistics');
if (db_index_exists('node_comment_statistics', 'statistics_node')) {
// Drop the statistics_node foreign key.
db_drop_index('node_comment_statistics', 'statistics_node');
}
db_drop_index('node_comment_statistics', 'node_comment_timestamp');
db_drop_index('node_comment_statistics', 'comment_count');
db_drop_index('node_comment_statistics', 'last_comment_uid');
// Rename {node_comment_statistics} to {comment_entity_statistics}.
db_rename_table('node_comment_statistics', 'comment_entity_statistics');
// Add the entity_type and field id columns to comment_entity_statistics.
db_add_field('comment_entity_statistics', 'entity_type', array(
'type' => 'varchar',
'not null' => TRUE,
'default' => 'node',
'length' => 255,
'description' => 'The entity_type of the entity to which this comment is a reply.',
));
db_add_field('comment_entity_statistics', 'field_id', array(
'type' => 'varchar',
'not null' => TRUE,
'default' => 'node__comment',
'length' => 255,
'description' => 'The field_id of the field that was used to add this comment.',
));
// Rename the nid column in entity_comment_statistics to entity_id.
db_change_field('comment_entity_statistics', 'nid', 'entity_id', array(
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The entity_id of the entity to which this comment is a reply.',
));
// Add indexes.
db_add_primary_key('comment_entity_statistics', array('entity_id', array('entity_type', 32), array('field_id',32)));
db_add_index('comment_entity_statistics', 'last_comment_timestamp', array('last_comment_timestamp'));
db_add_index('comment_entity_statistics', 'comment_count', array('comment_count'));
db_add_index('comment_entity_statistics', 'last_comment_uid', array('last_comment_uid'));
}
/**
* Adds comment fields for all node types.
*
* Field instance settings "default_mode", "per_page" and "form_location" are
* preserved to allow migrate contrib modules.
*/
function comment_update_8006(&$sandbox) {
// Entity module update functions are needed to update components of node
// entity display and form display for new comment fields.
module_load_install('entity');
// Loop over defined node_types.
$node_types = array_keys(_update_7000_node_get_types());
foreach ($node_types as $node_type) {
// COMMENT_OPEN
$default_value = update_variable_get('comment_' . $node_type, 2);
// Add a default comment field for existing node comments.
$field_name = 'comment_' . $node_type;
$field = array(
// We need one per content type to match the existing comment bundles.
'id' => 'node.' . $field_name,
'type' => 'comment',
'module' => 'comment',
'name' => $field_name,
'entity_type' => 'node',
);
// Make sure field doesn't already exist.
$index = 0;
// @todo Refactor once https://drupal.org/node/1856972 lands.
while (!\Drupal::config('field.field.node.' . $field['name'])->isNew()) {
// Append a numeric index.
$field['id'] = 'node.' . $field_name . '_' . $index;
$field['name'] = $field_name . '_' . $index;
// Increment index.
$index++;
}
$field_object = new Field($field);
$field['schema'] = CommentItem::schema($field_object);
_update_8003_field_create_field($field);
// @todo Refactor once https://drupal.org/node/1856972 lands.
if (\Drupal::config("field.instance.node.$node_type." . $field['name'])->isNew()) {
// Add the comment field, setting the instance settings to match those for
// the given node_type.
$instance_settings = array(
// COMMENT_MODE_THREADED
'default_mode' => update_variable_get('comment_default_mode_' . $node_type, 1),
'per_page' => update_variable_get('comment_default_per_page_' . $node_type, 50),
// COMMENT_FORM_BELOW
'form_location' => update_variable_get('comment_form_location_' . $node_type, 1),
// COMMENT_ANONYMOUS_MAYNOT_CONTACT
'anonymous' => update_variable_get('comment_anonymous_' . $node_type, 0),
'subject' => update_variable_get('comment_subject_field_' . $node_type, 1),
// DRUPAL_OPTIONAL
'preview' => update_variable_get('comment_preview_' . $node_type, 1),
);
$instance = array(
'id' => "node.$node_type." . $field['name'],
'entity_type' => 'node',
'bundle' => $node_type,
'default_value' => array(array('status' => $default_value)),
'deleted' => '0',
'description' => '',
'label' => 'Comment settings',
'required' => TRUE,
'settings' => $instance_settings,
);
_update_8003_field_create_instance($field, $instance);
}
// Prepare defaults for the default and full view modes.
$display_options_default = array(
'label' => 'hidden',
'type' => 'comment_default',
'settings' => array(),
'weight' => 20,
);
// Assign display settings for the 'default' and 'full' view modes.
$display = _update_8000_entity_get_display('node', $node_type, 'default');
$display->set('content.' . $field['name'], $display_options_default)
->save();
$display = _update_8000_entity_get_display('node', $node_type, 'full');
$display->set('content.' . $field['name'], $display_options_default)
->save();
// Assign widget settings for the 'default' form mode.
$display_options_default = array(
'type' => 'comment_default',
'settings' => array(),
'weight' => 20,
);
$display = _update_8000_entity_get_form_display('node', $node_type, 'default');
$display->set('content.' . $field['name'], $display_options_default)
->save();
// Clean up old variables.
update_variable_del('comment_' . $node_type);
update_variable_del('comment_default_mode_' . $node_type);
update_variable_del('comment_default_per_page_' . $node_type);
update_variable_del('comment_anonymous_' . $node_type);
update_variable_del('comment_subject_field_' . $node_type);
update_variable_del('comment_form_location_' . $node_type);
update_variable_del('comment_preview_' . $node_type);
}
}
/**
* Update existing comment values from node table to field data.
*/
function comment_update_8007(&$sandbox) {
$types = array_keys(_update_7000_node_get_types());
// Load each node type in batch and initialize field values for comment field.
if (!isset($sandbox['progress'])) {
$sandbox['progress'] = 0;
$sandbox['current_nid'] = 0;
// We track all node types here.
$sandbox['node_types'] = $types;
// We start with this node type.
$sandbox['node_type'] = array_shift($sandbox['node_types']);
$sandbox['#finished'] = 1;
$sandbox['max'] = db_query('SELECT COUNT(nid) FROM {node}')->fetchField();
}
// Set the initial values of comment fields for existing nodes. Note that
// contrib modules will need to handle the upgrade path on their own, as
// they are disabled during core upgrade.
// Node table will always exist up until here because in 7.x comment
// depends on node.
$nodes = db_select('node', 'n')
->fields('n', array('nid', 'comment', 'vid', 'langcode'))
->condition('type', $sandbox['node_type'])
->condition('nid', $sandbox['current_nid'], '>')
->range(0, 50)
->orderBy('nid', 'ASC')
->execute()
->fetchAllAssoc('nid');
if (count($nodes) > 0) {
$insert = db_insert('node__comment_' . $sandbox['node_type'])
->fields(array(
'bundle',
'entity_id',
'revision_id',
'langcode',
'delta',
'comment_' . $sandbox['node_type'] . '_status',
));
$revision = db_insert('node_revision__comment_' . $sandbox['node_type'])
->fields(array(
'bundle',
'entity_id',
'revision_id',
'langcode',
'delta',
'comment_' . $sandbox['node_type'] . '_status',
));
// Update the field name to match the node type.
db_update('comment')
->fields(array(
'field_id' => 'node__comment_' . $sandbox['node_type'],
))
->condition('entity_id', array_keys($nodes))
->execute();
foreach ($nodes as $nid => $node) {
$insert->values(array(
'bundle' => $sandbox['node_type'],
'entity_id' => $nid,
'revision_id' => $node->vid,
'langcode' => Language::LANGCODE_NOT_SPECIFIED,
'delta' => 0,
'comment_' . $sandbox['node_type'] . '_status' => $node->comment,
));
$revision->values(array(
'bundle' => $sandbox['node_type'],
'entity_id' => $nid,
'revision_id' => $node->vid,
'langcode' => Language::LANGCODE_NOT_SPECIFIED,
'delta' => 0,
'comment_' . $sandbox['node_type'] . '_status' => $node->comment,
));
$sandbox['progress']++;
$sandbox['current_nid'] = $nid;
}
$insert->execute();
$revision->execute();
// Populate the field name to match the node type.
db_update('comment_entity_statistics')
->fields(array(
'field_id' => 'node__comment_' . $sandbox['node_type'],
))
->condition('entity_id', array_keys($nodes))
->execute();
}
else {
// Move to the next node type.
$sandbox['node_type'] = array_shift($sandbox['node_types']);
// Reset the current nid pointer.
$sandbox['current_nid'] = 0;
}
$sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']);
}
/**
* Removes the existing fields.
*
* Data was migrated in comment_update_8007().
*/
function comment_update_8008(&$sandbox) {
// Remove the {node}.comment field.
db_drop_field('node', 'comment');
// Remove the {node_revision}.comment field.
db_drop_field('node_revision', 'comment');
}
/**
* Remove the comment_block_count variable.
*/
function comment_update_8009() {
update_variable_del('comment_block_count');
}
/**
* @} End of "addtogroup updates-7.x-to-8.x".
* The next series of updates should start at 9000.
*/