Initial commit

This commit is contained in:
Mauricio Dinarte 2024-12-04 10:11:27 -06:00
commit c5e731d8ae
2773 changed files with 600767 additions and 0 deletions

View file

@ -0,0 +1,32 @@
(function ($) {
Drupal.behaviors.commentFieldsetSummaries = {
attach: function (context) {
$('fieldset.comment-node-settings-form', context).drupalSetSummary(function (context) {
return Drupal.checkPlain($('.form-item-comment input:checked', context).next('label').text());
});
// Provide the summary for the node type form.
$('fieldset.comment-node-type-settings-form', context).drupalSetSummary(function(context) {
var vals = [];
// Default comment setting.
vals.push($(".form-item-comment select option:selected", context).text());
// Threading.
var threading = $(".form-item-comment-default-mode input:checked", context).next('label').text();
if (threading) {
vals.push(threading);
}
// Comments per page.
var number = $(".form-item-comment-default-per-page select option:selected", context).val();
vals.push(Drupal.t('@number comments per page', {'@number': number}));
return Drupal.checkPlain(vals.join(', '));
});
}
};
})(jQuery);

View file

@ -0,0 +1,5 @@
.indented {
margin-left: 0;
margin-right: 25px;
}

View file

@ -0,0 +1,52 @@
<?php
/**
* @file
* Default theme implementation to provide an HTML container for comments.
*
* Available variables:
* - $content: The array of content-related elements for the node. Use
* render($content) to print them all, or
* print a subset such as render($content['comment_form']).
* - $classes: String of classes that can be used to style contextually through
* CSS. It can be manipulated through the variable $classes_array from
* preprocess functions. The default value has the following:
* - comment-wrapper: The current template type, i.e., "theming hook".
* - $title_prefix (array): An array containing additional output populated by
* modules, intended to be displayed in front of the main title tag that
* appears in the template.
* - $title_suffix (array): An array containing additional output populated by
* modules, intended to be displayed after the main title tag that appears in
* the template.
*
* The following variables are provided for contextual information.
* - $node: Node object the comments are attached to.
* The constants below the variables show the possible values and should be
* used for comparison.
* - $display_mode
* - COMMENT_MODE_FLAT
* - COMMENT_MODE_THREADED
*
* Other variables:
* - $classes_array: Array of html class attribute values. It is flattened
* into a string within the variable $classes.
*
* @see template_preprocess_comment_wrapper()
*
* @ingroup themeable
*/
?>
<div id="comments" class="<?php print $classes; ?>"<?php print $attributes; ?>>
<?php if ($content['comments'] && $node->type != 'forum'): ?>
<?php print render($title_prefix); ?>
<h2 class="title"><?php print t('Comments'); ?></h2>
<?php print render($title_suffix); ?>
<?php endif; ?>
<?php print render($content['comments']); ?>
<?php if ($content['comment_form']): ?>
<h2 class="title comment-form"><?php print t('Add new comment'); ?></h2>
<?php print render($content['comment_form']); ?>
<?php endif; ?>
</div>

View file

@ -0,0 +1,284 @@
<?php
/**
* @file
* Admin page callbacks for the comment module.
*/
/**
* Menu callback; present an administrative comment listing.
*/
function comment_admin($type = 'new') {
$edit = $_POST;
if (isset($edit['operation']) && ($edit['operation'] == 'delete') && isset($edit['comments']) && $edit['comments']) {
return drupal_get_form('comment_multiple_delete_confirm');
}
else {
return drupal_get_form('comment_admin_overview', $type);
}
}
/**
* Form builder for the comment overview administration form.
*
* @param $arg
* Current path's fourth component: the type of overview form ('approval' or
* 'new').
*
* @ingroup forms
* @see comment_admin_overview_validate()
* @see comment_admin_overview_submit()
* @see theme_comment_admin_overview()
*/
function comment_admin_overview($form, &$form_state, $arg) {
// Build an 'Update options' form.
$form['options'] = array(
'#type' => 'fieldset',
'#title' => t('Update options'),
'#attributes' => array('class' => array('container-inline')),
);
if ($arg == 'approval') {
$options['publish'] = t('Publish the selected comments');
}
else {
$options['unpublish'] = t('Unpublish the selected comments');
}
$options['delete'] = t('Delete the selected comments');
$form['options']['operation'] = array(
'#type' => 'select',
'#title' => t('Operation'),
'#title_display' => 'invisible',
'#options' => $options,
'#default_value' => 'publish',
);
$form['options']['submit'] = array(
'#type' => 'submit',
'#value' => t('Update'),
);
// Load the comments that need to be displayed.
$status = ($arg == 'approval') ? COMMENT_NOT_PUBLISHED : COMMENT_PUBLISHED;
$header = array(
'subject' => array('data' => t('Subject'), 'field' => 'subject'),
'author' => array('data' => t('Author'), 'field' => 'name'),
'posted_in' => array('data' => t('Posted in'), 'field' => 'node_title'),
'changed' => array('data' => t('Updated'), 'field' => 'c.changed', 'sort' => 'desc'),
'operations' => array('data' => t('Operations')),
);
$query = db_select('comment', 'c')->extend('PagerDefault')->extend('TableSort');
$query->join('node', 'n', 'n.nid = c.nid');
$query->addField('n', 'title', 'node_title');
$query->addTag('node_access');
$result = $query
->fields('c', array('cid', 'subject', 'name', 'changed'))
->condition('c.status', $status)
->limit(50)
->orderByHeader($header)
->execute();
$cids = array();
// We collect a sorted list of node_titles during the query to attach to the
// comments later.
foreach ($result as $row) {
$cids[] = $row->cid;
$node_titles[] = $row->node_title;
}
$comments = comment_load_multiple($cids);
// Build a table listing the appropriate comments.
$options = array();
$destination = drupal_get_destination();
foreach ($comments as $comment) {
// Remove the first node title from the node_titles array and attach to
// the comment.
$comment->node_title = array_shift($node_titles);
$comment_body = field_get_items('comment', $comment, 'comment_body');
$options[$comment->cid] = array(
'subject' => array(
'data' => array(
'#type' => 'link',
'#title' => $comment->subject,
'#href' => 'comment/' . $comment->cid,
'#options' => array('attributes' => array('title' => truncate_utf8($comment_body[0]['value'], 128)), 'fragment' => 'comment-' . $comment->cid),
),
),
'author' => theme('username', array('account' => $comment)),
'posted_in' => array(
'data' => array(
'#type' => 'link',
'#title' => $comment->node_title,
'#href' => 'node/' . $comment->nid,
),
),
'changed' => format_date($comment->changed, 'short'),
'operations' => array(
'data' => array(
'#type' => 'link',
'#title' => t('edit'),
'#href' => 'comment/' . $comment->cid . '/edit',
'#options' => array('query' => $destination),
),
),
);
}
$form['comments'] = array(
'#type' => 'tableselect',
'#header' => $header,
'#options' => $options,
'#empty' => t('No comments available.'),
);
$form['pager'] = array('#theme' => 'pager');
return $form;
}
/**
* Validate comment_admin_overview form submissions.
*/
function comment_admin_overview_validate($form, &$form_state) {
$form_state['values']['comments'] = array_diff($form_state['values']['comments'], array(0));
// We can't execute any 'Update options' if no comments were selected.
if (count($form_state['values']['comments']) == 0) {
form_set_error('', t('Select one or more comments to perform the update on.'));
}
}
/**
* Process comment_admin_overview form submissions.
*
* Execute the chosen 'Update option' on the selected comments, such as
* publishing, unpublishing or deleting.
*/
function comment_admin_overview_submit($form, &$form_state) {
$operation = $form_state['values']['operation'];
$cids = $form_state['values']['comments'];
if ($operation == 'delete') {
comment_delete_multiple($cids);
}
else {
foreach ($cids as $cid => $value) {
$comment = comment_load($value);
if ($operation == 'unpublish') {
$comment->status = COMMENT_NOT_PUBLISHED;
}
elseif ($operation == 'publish') {
$comment->status = COMMENT_PUBLISHED;
}
comment_save($comment);
}
}
drupal_set_message(t('The update has been performed.'));
$form_state['redirect'] = 'admin/content/comment';
cache_clear_all();
}
/**
* List the selected comments and verify that the admin wants to delete them.
*
* @param $form_state
* An associative array containing the current state of the form.
* @return
* TRUE if the comments should be deleted, FALSE otherwise.
* @ingroup forms
* @see comment_multiple_delete_confirm_submit()
*/
function comment_multiple_delete_confirm($form, &$form_state) {
$edit = $form_state['input'];
$form['comments'] = array(
'#prefix' => '<ul>',
'#suffix' => '</ul>',
'#tree' => TRUE,
);
// array_filter() returns only elements with actual values.
$comment_counter = 0;
foreach (array_filter($edit['comments']) as $cid => $value) {
$comment = comment_load($cid);
if (is_object($comment) && is_numeric($comment->cid)) {
$subject = db_query('SELECT subject FROM {comment} WHERE cid = :cid', array(':cid' => $cid))->fetchField();
$form['comments'][$cid] = array('#type' => 'hidden', '#value' => $cid, '#prefix' => '<li>', '#suffix' => check_plain($subject) . '</li>');
$comment_counter++;
}
}
$form['operation'] = array('#type' => 'hidden', '#value' => 'delete');
if (!$comment_counter) {
drupal_set_message(t('There do not appear to be any comments to delete, or your selected comment was deleted by another administrator.'));
drupal_goto('admin/content/comment');
}
else {
return confirm_form($form,
t('Are you sure you want to delete these comments and all their children?'),
'admin/content/comment', t('This action cannot be undone.'),
t('Delete comments'), t('Cancel'));
}
}
/**
* Process comment_multiple_delete_confirm form submissions.
*/
function comment_multiple_delete_confirm_submit($form, &$form_state) {
if ($form_state['values']['confirm']) {
comment_delete_multiple(array_keys($form_state['values']['comments']));
cache_clear_all();
$count = count($form_state['values']['comments']);
watchdog('content', 'Deleted @count comments.', array('@count' => $count));
drupal_set_message(format_plural($count, 'Deleted 1 comment.', 'Deleted @count comments.'));
}
$form_state['redirect'] = 'admin/content/comment';
}
/**
* Page callback for comment deletions.
*/
function comment_confirm_delete_page($cid) {
if ($comment = comment_load($cid)) {
return drupal_get_form('comment_confirm_delete', $comment);
}
return MENU_NOT_FOUND;
}
/**
* Form builder; Builds the confirmation form for deleting a single comment.
*
* @ingroup forms
* @see comment_confirm_delete_submit()
*/
function comment_confirm_delete($form, &$form_state, $comment) {
$form['#comment'] = $comment;
// Always provide entity id in the same form key as in the entity edit form.
$form['cid'] = array('#type' => 'value', '#value' => $comment->cid);
return confirm_form(
$form,
t('Are you sure you want to delete the comment %title?', array('%title' => $comment->subject)),
'node/' . $comment->nid,
t('Any replies to this comment will be lost. This action cannot be undone.'),
t('Delete'),
t('Cancel'),
'comment_confirm_delete');
}
/**
* Process comment_confirm_delete form submissions.
*/
function comment_confirm_delete_submit($form, &$form_state) {
$comment = $form['#comment'];
// Delete the comment and its replies.
comment_delete($comment->cid);
drupal_set_message(t('The comment and all its replies have been deleted.'));
watchdog('content', 'Deleted comment @cid and its replies.', array('@cid' => $comment->cid));
// Clear the cache so an anonymous user sees that his comment was deleted.
cache_clear_all();
$form_state['redirect'] = "node/$comment->nid";
}

View file

@ -0,0 +1,145 @@
<?php
/**
* @file
* Hooks provided by the Comment module.
*/
/**
* @addtogroup hooks
* @{
*/
/**
* The comment passed validation and is about to be saved.
*
* Modules may make changes to the comment before it is saved to the database.
*
* @param $comment
* The comment object.
*/
function hook_comment_presave($comment) {
// Remove leading & trailing spaces from the comment subject.
$comment->subject = trim($comment->subject);
}
/**
* The comment is being inserted.
*
* @param $comment
* The comment object.
*/
function hook_comment_insert($comment) {
// Reindex the node when comments are added.
search_touch_node($comment->nid);
}
/**
* The comment is being updated.
*
* @param $comment
* The comment object.
*/
function hook_comment_update($comment) {
// Reindex the node when comments are updated.
search_touch_node($comment->nid);
}
/**
* Comments are being loaded from the database.
*
* @param $comments
* An array of comment objects indexed by cid.
*/
function hook_comment_load($comments) {
$result = db_query('SELECT cid, foo FROM {mytable} WHERE cid IN (:cids)', array(':cids' => array_keys($comments)));
foreach ($result as $record) {
$comments[$record->cid]->foo = $record->foo;
}
}
/**
* The comment is being viewed. This hook can be used to add additional data to the comment before theming.
*
* @param $comment
* Passes in the comment the action is being performed on.
* @param $view_mode
* View mode, e.g. 'full', 'teaser'...
* @param $langcode
* The language code used for rendering.
*
* @see hook_entity_view()
*/
function hook_comment_view($comment, $view_mode, $langcode) {
// how old is the comment
$comment->time_ago = time() - $comment->changed;
}
/**
* The comment was built; the module may modify the structured content.
*
* This hook is called after the content has been assembled in a structured array
* and may be used for doing processing which requires that the complete comment
* content structure has been built.
*
* If the module wishes to act on the rendered HTML of the comment rather than the
* structured content array, it may use this hook to add a #post_render callback.
* Alternatively, it could also implement hook_preprocess_comment(). See
* drupal_render() and theme() documentation respectively for details.
*
* @param $build
* A renderable array representing the comment.
*
* @see comment_view()
* @see hook_entity_view_alter()
*/
function hook_comment_view_alter(&$build) {
// Check for the existence of a field added by another module.
if ($build['#view_mode'] == 'full' && isset($build['an_additional_field'])) {
// Change its weight.
$build['an_additional_field']['#weight'] = -10;
}
// Add a #post_render callback to act on the rendered HTML of the comment.
$build['#post_render'][] = 'my_module_comment_post_render';
}
/**
* Act on a comment that is being saved in a published state.
*
* @param $comment
* Passes in the comment the action is being performed on.
* @return
* Nothing.
*/
function hook_comment_publish($comment) {
drupal_set_message(t('Comment: @subject has been published', array('@subject' => $comment->subject)));
}
/**
* Act on a comment that is being saved in an unpublished state.
*
* @param $comment
* Passes in the comment the action is being performed on.
* @return
* Nothing.
*/
function hook_comment_unpublish($comment) {
drupal_set_message(t('Comment: @subject has been unpublished', array('@subject' => $comment->subject)));
}
/**
* The comment is being deleted by the moderator.
*
* @param $comment
* Passes in the comment the action is being performed on.
* @return
* Nothing.
*/
function hook_comment_delete($comment) {
drupal_set_message(t('Comment: @subject has been deleted', array('@subject' => $comment->subject)));
}
/**
* @} End of "addtogroup hooks".
*/

View file

@ -0,0 +1,13 @@
#comments {
margin-top: 15px;
}
.indented {
margin-left: 25px; /* LTR */
}
.comment-unpublished {
background-color: #fff4f4;
}
.comment-preview {
background-color: #ffffea;
}

View file

@ -0,0 +1,15 @@
name = Comment
description = Allows users to comment on and discuss published content.
package = Core
version = VERSION
core = 7.x
dependencies[] = text
files[] = comment.module
files[] = comment.test
configure = admin/content/comment
stylesheets[all][] = comment.css
; Information added by Drupal.org packaging script on 2024-03-06
version = "7.100"
project = "drupal"
datestamp = "1709734591"

View file

@ -0,0 +1,575 @@
<?php
/**
* @file
* Install, update and uninstall functions for the comment module.
*/
/**
* Implements hook_uninstall().
*/
function comment_uninstall() {
// Remove variables.
variable_del('comment_block_count');
$node_types = array_keys(node_type_get_types());
foreach ($node_types as $node_type) {
field_attach_delete_bundle('comment', 'comment_node_' . $node_type);
variable_del('comment_' . $node_type);
variable_del('comment_anonymous_' . $node_type);
variable_del('comment_controls_' . $node_type);
variable_del('comment_default_mode_' . $node_type);
variable_del('comment_default_order_' . $node_type);
variable_del('comment_default_per_page_' . $node_type);
variable_del('comment_form_location_' . $node_type);
variable_del('comment_preview_' . $node_type);
variable_del('comment_subject_field_' . $node_type);
}
}
/**
* Implements hook_enable().
*/
function comment_enable() {
// Insert records into the node_comment_statistics for nodes that are missing.
$query = db_select('node', 'n');
$query->leftJoin('node_comment_statistics', 'ncs', 'ncs.nid = n.nid');
$query->addField('n', 'created', 'last_comment_timestamp');
$query->addField('n', 'uid', 'last_comment_uid');
$query->addField('n', 'nid');
$query->addExpression('0', 'comment_count');
$query->addExpression('NULL', 'last_comment_name');
$query->isNull('ncs.comment_count');
db_insert('node_comment_statistics')
->from($query)
->execute();
}
/**
* Implements hook_modules_enabled().
*
* Creates comment body fields for node types existing before the comment module
* is enabled. We use hook_modules_enabled() rather than hook_enable() so we can
* react to node types of existing modules, and those of modules being enabled
* both before and after comment module in the loop of module_enable().
*
* There is a separate comment bundle for each node type to allow for
* per-node-type customization of comment fields. Each one of these bundles
* needs a comment body field instance. A comment bundle is needed even for
* node types whose comments are disabled by default, because individual nodes
* may override that default.
*
* @see comment_node_type_insert()
*/
function comment_modules_enabled($modules) {
// Only react if comment module is one of the modules being enabled.
// 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);
}
}
}
/**
* Implements hook_update_dependencies().
*/
function comment_update_dependencies() {
// comment_update_7005() creates the comment body field and therefore must
// run after all Field modules have been enabled, which happens in
// system_update_7027().
$dependencies['comment'][7005] = array(
'system' => 7027,
);
// comment_update_7006() needs to query the {filter_format} table to get a
// list of existing text formats, so it must run after filter_update_7000(),
// which creates that table.
$dependencies['comment'][7006] = array(
'filter' => 7000,
);
return $dependencies;
}
/**
* @addtogroup updates-6.x-to-7.x
* @{
*/
/**
* Rename comment display setting variables.
*/
function comment_update_7000() {
$types = _update_7000_node_get_types();
foreach ($types as $type => $type_object) {
variable_del('comment_default_order' . $type);
// Drupal 6 had four display modes:
// - COMMENT_MODE_FLAT_COLLAPSED = 1
// - COMMENT_MODE_FLAT_EXPANDED = 2
// - COMMENT_MODE_THREADED_COLLAPSED = 3
// - COMMENT_MODE_THREADED_EXPANDED = 4
//
// Drupal 7 doesn't support collapsed/expanded modes anymore, so we
// migrate all the flat modes to COMMENT_MODE_FLAT (0) and all the threaded
// modes to COMMENT_MODE_THREADED (1).
$setting = variable_get('comment_default_mode_' . $type, 4);
if ($setting == 3 || $setting == 4) {
variable_set('comment_default_mode_' . $type, 1);
}
else {
variable_set('comment_default_mode_' . $type, 0);
}
// There were only two comment modes in the past:
// - 1 was 'required' previously, convert into DRUPAL_REQUIRED (2).
// - 0 was 'optional' previously, convert into DRUPAL_OPTIONAL (1).
$preview = variable_get('comment_preview_' . $type, 1) ? 2 : 1;
variable_set('comment_preview_' . $type, $preview);
}
}
/**
* Change comment status from published being 0 to being 1
*/
function comment_update_7001() {
// Choose a temporary status value different from the existing status values.
$tmp_status = db_query('SELECT MAX(status) FROM {comments}')->fetchField() + 1;
$changes = array(
0 => $tmp_status,
1 => 0,
$tmp_status => 1,
);
foreach ($changes as $old => $new) {
db_update('comments')
->fields(array('status' => $new))
->condition('status', $old)
->execute();
}
}
/**
* Rename {comments} table to {comment} and upgrade it.
*/
function comment_update_7002() {
db_rename_table('comments', 'comment');
// Add user-related indexes. These may already exist from Drupal 6.
if (!db_index_exists('comment', 'comment_uid')) {
db_add_index('comment', 'comment_uid', array('uid'));
db_add_index('node_comment_statistics', 'last_comment_uid', array('last_comment_uid'));
}
// Create a language column.
db_add_field('comment', 'language', array(
'type' => 'varchar',
'length' => 12,
'not null' => TRUE,
'default' => '',
));
db_add_index('comment', 'comment_nid_language', array('nid', 'language'));
}
/**
* Split {comment}.timestamp into 'created' and 'changed', improve indexing on {comment}.
*/
function comment_update_7003() {
// Drop the old indexes.
db_drop_index('comment', 'status');
db_drop_index('comment', 'pid');
// Create a created column.
db_add_field('comment', 'created', array(
'type' => 'int',
'not null' => TRUE,
'default' => 0,
));
// Rename the timestamp column to changed.
db_change_field('comment', 'timestamp', 'changed', array(
'type' => 'int',
'not null' => TRUE,
'default' => 0,
));
// Migrate the data.
// @todo db_update() should support this.
db_query('UPDATE {comment} SET created = changed');
// Recreate the indexes.
// The 'comment_num_new' index is optimized for comment_num_new()
// and comment_new_page_count().
db_add_index('comment', 'comment_num_new', array('nid', 'status', 'created', 'cid', 'thread'));
db_add_index('comment', 'comment_pid_status', array('pid', 'status'));
}
/**
* Upgrade the {node_comment_statistics} table.
*/
function comment_update_7004() {
db_add_field('node_comment_statistics', 'cid', array(
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The {comment}.cid of the last comment.',
));
db_add_index('node_comment_statistics', 'cid', array('cid'));
// The comment_count index may have been added in Drupal 6.
if (!db_index_exists('node_comment_statistics', 'comment_count')) {
// Add an index on the comment_count.
db_add_index('node_comment_statistics', 'comment_count', array('comment_count'));
}
}
/**
* Create the comment_body field.
*/
function comment_update_7005() {
// Create comment body field.
$field = array(
'field_name' => 'comment_body',
'type' => 'text_long',
'module' => 'text',
'entity_types' => array(
'comment',
),
'settings' => array(),
'cardinality' => 1,
);
_update_7000_field_create_field($field);
// Add the field to comments for all existing bundles.
$generic_instance = array(
'entity_type' => 'comment',
'label' => t('Comment'),
'settings' => array(
'text_processing' => 1,
),
'required' => TRUE,
'display' => array(
'default' => array(
'label' => 'hidden',
'type' => 'text_default',
'weight' => 0,
'settings' => array(),
'module' => 'text',
),
),
'widget' => array(
'type' => 'text_textarea',
'settings' => array(
'rows' => 5,
),
'weight' => 0,
'module' => 'text',
),
'description' => '',
);
$types = _update_7000_node_get_types();
foreach ($types as $type => $type_object) {
$instance = $generic_instance;
$instance['bundle'] = 'comment_node_' . $type;
_update_7000_field_create_instance($field, $instance);
}
}
/**
* Migrate data from the comment field to field storage.
*/
function comment_update_7006(&$sandbox) {
// This is a multipass update. First set up some comment variables.
if (empty($sandbox['total'])) {
$comments = (bool) db_query_range('SELECT 1 FROM {comment}', 0, 1)->fetchField();
$sandbox['types'] = array();
if ($comments) {
$sandbox['types'] = array_keys(_update_7000_node_get_types());
}
$sandbox['total'] = count($sandbox['types']);
}
if (!empty($sandbox['types'])) {
$type = array_shift($sandbox['types']);
$query = db_select('comment', 'c');
$query->innerJoin('node', 'n', 'c.nid = n.nid AND n.type = :type', array(':type' => $type));
$query->addField('c', 'cid', 'entity_id');
$query->addExpression("'comment_node_$type'", 'bundle');
$query->addExpression("'comment'", 'entity_type');
$query->addExpression('0', 'deleted');
$query->addExpression("'" . LANGUAGE_NONE . "'", 'language');
$query->addExpression('0', 'delta');
$query->addField('c', 'comment', 'comment_body_value');
$query->addField('c', 'format', 'comment_body_format');
db_insert('field_data_comment_body')
->from($query)
->execute();
$sandbox['#finished'] = 1 - count($sandbox['types']) / $sandbox['total'];
}
// On the last pass of the update, $sandbox['types'] will be empty.
if (empty($sandbox['types'])) {
// Update the comment body text formats. For an explanation of these
// updates, see the code comments in user_update_7010().
db_update('field_data_comment_body')
->fields(array('comment_body_format' => NULL))
->condition('comment_body_value', '')
->condition('comment_body_format', 0)
->execute();
$existing_formats = db_query("SELECT format FROM {filter_format}")->fetchCol();
$default_format = variable_get('filter_default_format', 1);
db_update('field_data_comment_body')
->fields(array('comment_body_format' => $default_format))
->isNotNull('comment_body_format')
->condition('comment_body_format', $existing_formats, 'NOT IN')
->execute();
// Finally, remove the old comment data.
db_drop_field('comment', 'comment');
db_drop_field('comment', 'format');
}
}
/**
* @} End of "addtogroup updates-6.x-to-7.x".
*/
/**
* @addtogroup updates-7.x-extra
* @{
*/
/**
* Add an index to the created column.
*/
function comment_update_7007() {
db_add_index('comment', 'comment_created', array('created'));
}
/**
* Update database to match Drupal 7 schema.
*/
function comment_update_7008() {
// Update default status to 1.
db_change_field('comment', 'status', 'status', array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 1,
'size' => 'tiny',
));
// Realign indexes.
db_drop_index('comment', 'comment_status_pid');
db_add_index('comment', 'comment_status_pid', array('pid', 'status'));
db_drop_index('comment', 'comment_pid_status');
db_drop_index('comment', 'nid');
}
/**
* Change the last_comment_timestamp column description.
*/
function comment_update_7009() {
db_change_field('node_comment_statistics', 'last_comment_timestamp', '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.',
));
}
/**
* @} End of "addtogroup updates-7.x-extra".
*/
/**
* 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.',
),
'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.',
),
'nid' => array(
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The {node}.nid to which this comment is a reply.',
),
'uid' => array(
'type' => 'int',
'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 vancode representation of the comment's place in a thread.",
),
'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.",
),
'language' => array(
'description' => 'The {languages}.language of this comment.',
'type' => 'varchar',
'length' => 12,
'not null' => TRUE,
'default' => '',
),
),
'indexes' => array(
'comment_status_pid' => array('pid', 'status'),
'comment_num_new' => array('nid', 'status', 'created', 'cid', 'thread'),
'comment_uid' => array('uid'),
'comment_nid_language' => array('nid', 'language'),
'comment_created' => array('created'),
),
'primary key' => array('cid'),
'foreign keys' => array(
'comment_node' => array(
'table' => 'node',
'columns' => array('nid' => 'nid'),
),
'comment_author' => array(
'table' => 'users',
'columns' => array('uid' => 'uid'),
),
),
);
$schema['node_comment_statistics'] = array(
'description' => 'Maintains statistics of node and comments posts to show "new" and "updated" flags.',
'fields' => array(
'nid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The {node}.nid for which the statistics are compiled.',
),
'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',
'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 node.',
),
),
'primary key' => array('nid'),
'indexes' => array(
'node_comment_timestamp' => array('last_comment_timestamp'),
'comment_count' => array('comment_count'),
'last_comment_uid' => array('last_comment_uid'),
),
'foreign keys' => array(
'statistics_node' => array(
'table' => 'node',
'columns' => array('nid' => 'nid'),
),
'last_comment_author' => array(
'table' => 'users',
'columns' => array(
'last_comment_uid' => 'uid',
),
),
),
);
return $schema;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,123 @@
<?php
/**
* @file
* User page callbacks for the comment module.
*/
/**
* This function is responsible for generating a comment reply form.
* There are several cases that have to be handled, including:
* - replies to comments
* - replies to nodes
* - attempts to reply to nodes that can no longer accept comments
* - respecting access permissions ('access comments', 'post comments', etc.)
*
* The node or comment that is being replied to must appear above the comment
* form to provide the user context while authoring the comment.
*
* @param $node
* Every comment belongs to a node. This is that node.
*
* @param $pid
* Some comments are replies to other comments. In those cases, $pid is the parent
* comment's cid.
*
* @return array
* An associative array containing:
* - An array for rendering the node or parent comment.
* - comment_node: If the comment is a reply to the node.
* - comment_parent: If the comment is a reply to another comment.
* - comment_form: The comment form as a renderable array.
*/
function comment_reply($node, $pid = NULL) {
// Set the breadcrumb trail.
drupal_set_breadcrumb(array(l(t('Home'), NULL), l($node->title, 'node/' . $node->nid)));
$op = isset($_POST['op']) ? $_POST['op'] : '';
$build = array();
// The user is previewing a comment prior to submitting it.
if ($op == t('Preview')) {
if (user_access('post comments')) {
$build['comment_form'] = drupal_get_form("comment_node_{$node->type}_form", (object) array('pid' => $pid, 'nid' => $node->nid));
}
else {
drupal_set_message(t('You are not authorized to post comments.'), 'error');
drupal_goto("node/$node->nid");
}
}
else {
// $pid indicates that this is a reply to a comment.
if ($pid) {
if (user_access('access comments')) {
// Load the comment whose cid = $pid
$comment = db_query('SELECT c.*, u.uid, u.name AS registered_name, u.signature, u.signature_format, u.picture, u.data FROM {comment} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = :cid AND c.status = :status', array(
':cid' => $pid,
':status' => COMMENT_PUBLISHED,
))->fetchObject();
if ($comment) {
// If that comment exists, make sure that the current comment and the
// parent comment both belong to the same parent node.
if ($comment->nid != $node->nid) {
// Attempting to reply to a comment not belonging to the current nid.
drupal_set_message(t('The comment you are replying to does not exist.'), 'error');
drupal_goto("node/$node->nid");
}
// Display the parent comment
$comment->node_type = 'comment_node_' . $node->type;
field_attach_load('comment', array($comment->cid => $comment));
$comment->name = $comment->uid ? $comment->registered_name : $comment->name;
$build['comment_parent'] = comment_view($comment, $node);
}
else {
drupal_set_message(t('The comment you are replying to does not exist.'), 'error');
drupal_goto("node/$node->nid");
}
}
else {
drupal_set_message(t('You are not authorized to view comments.'), 'error');
drupal_goto("node/$node->nid");
}
}
// This is the case where the comment is in response to a node. Display the node.
elseif (user_access('access content')) {
$build['comment_node'] = node_view($node);
}
// Should we show the reply box?
if ($node->comment != COMMENT_NODE_OPEN) {
drupal_set_message(t("This discussion is closed: you can't post new comments."), 'error');
drupal_goto("node/$node->nid");
}
elseif (user_access('post comments')) {
$edit = array('nid' => $node->nid, 'pid' => $pid);
$build['comment_form'] = drupal_get_form("comment_node_{$node->type}_form", (object) $edit);
}
else {
drupal_set_message(t('You are not authorized to post comments.'), 'error');
drupal_goto("node/$node->nid");
}
}
return $build;
}
/**
* Menu callback; publish specified comment.
*
* @param $cid
* A comment identifier.
*/
function comment_approve($cid) {
if (!isset($_GET['token']) || !drupal_valid_token($_GET['token'], "comment/$cid/approve")) {
return MENU_ACCESS_DENIED;
}
if ($comment = comment_load($cid)) {
$comment->status = COMMENT_PUBLISHED;
comment_save($comment);
drupal_set_message(t('Comment approved.'));
drupal_goto('node/' . $comment->nid);
}
return MENU_NOT_FOUND;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,243 @@
<?php
/**
* @file
* Builds placeholder replacement tokens for comment-related data.
*/
/**
* Implements hook_token_info().
*/
function comment_token_info() {
$type = array(
'name' => t('Comments'),
'description' => t('Tokens for comments posted on the site.'),
'needs-data' => 'comment',
);
// Comment-related tokens for nodes
$node['comment-count'] = array(
'name' => t("Comment count"),
'description' => t("The number of comments posted on a node."),
);
$node['comment-count-new'] = array(
'name' => t("New comment count"),
'description' => t("The number of comments posted on a node since the reader last viewed it."),
);
// Core comment tokens
$comment['cid'] = array(
'name' => t("Comment ID"),
'description' => t("The unique ID of the comment."),
);
$comment['hostname'] = array(
'name' => t("IP Address"),
'description' => t("The IP address of the computer the comment was posted from."),
);
$comment['name'] = array(
'name' => t("Name"),
'description' => t("The name left by the comment author."),
);
$comment['mail'] = array(
'name' => t("Email address"),
'description' => t("The email address left by the comment author."),
);
$comment['homepage'] = array(
'name' => t("Home page"),
'description' => t("The home page URL left by the comment author."),
);
$comment['title'] = array(
'name' => t("Title"),
'description' => t("The title of the comment."),
);
$comment['body'] = array(
'name' => t("Content"),
'description' => t("The formatted content of the comment itself."),
);
$comment['url'] = array(
'name' => t("URL"),
'description' => t("The URL of the comment."),
);
$comment['edit-url'] = array(
'name' => t("Edit URL"),
'description' => t("The URL of the comment's edit page."),
);
// Chained tokens for comments
$comment['created'] = array(
'name' => t("Date created"),
'description' => t("The date the comment was posted."),
'type' => 'date',
);
$comment['changed'] = array(
'name' => t("Date changed"),
'description' => t("The date the comment was most recently updated."),
'type' => 'date',
);
$comment['parent'] = array(
'name' => t("Parent"),
'description' => t("The comment's parent, if comment threading is active."),
'type' => 'comment',
);
$comment['node'] = array(
'name' => t("Node"),
'description' => t("The node the comment was posted to."),
'type' => 'node',
);
$comment['author'] = array(
'name' => t("Author"),
'description' => t("The author of the comment, if they were logged in."),
'type' => 'user',
);
return array(
'types' => array('comment' => $type),
'tokens' => array(
'node' => $node,
'comment' => $comment,
),
);
}
/**
* Implements hook_tokens().
*/
function comment_tokens($type, $tokens, array $data = array(), array $options = array()) {
$url_options = array('absolute' => TRUE);
if (isset($options['language'])) {
$url_options['language'] = $options['language'];
$language_code = $options['language']->language;
}
else {
$language_code = NULL;
}
$sanitize = !empty($options['sanitize']);
$replacements = array();
if ($type == 'comment' && !empty($data['comment'])) {
$comment = $data['comment'];
foreach ($tokens as $name => $original) {
switch ($name) {
// Simple key values on the comment.
case 'cid':
$replacements[$original] = $comment->cid;
break;
// Poster identity information for comments
case 'hostname':
$replacements[$original] = $sanitize ? check_plain($comment->hostname) : $comment->hostname;
break;
case 'name':
$name = ($comment->uid == 0) ? variable_get('anonymous', t('Anonymous')) : $comment->name;
$replacements[$original] = $sanitize ? filter_xss($name) : $name;
break;
case 'mail':
if ($comment->uid != 0) {
$account = user_load($comment->uid);
$mail = $account->mail;
}
else {
$mail = $comment->mail;
}
$replacements[$original] = $sanitize ? check_plain($mail) : $mail;
break;
case 'homepage':
$replacements[$original] = $sanitize ? check_url($comment->homepage) : $comment->homepage;
break;
case 'title':
$replacements[$original] = $sanitize ? filter_xss($comment->subject) : $comment->subject;
break;
case 'body':
if ($items = field_get_items('comment', $comment, 'comment_body', $language_code)) {
$instance = field_info_instance('comment', 'body', 'comment_body');
$field_langcode = field_language('comment', $comment, 'comment_body', $language_code);
$replacements[$original] = $sanitize ? _text_sanitize($instance, $field_langcode, $items[0], 'value') : $items[0]['value'];
}
break;
// Comment related URLs.
case 'url':
$url_options['fragment'] = 'comment-' . $comment->cid;
$replacements[$original] = url('comment/' . $comment->cid, $url_options);
break;
case 'edit-url':
$url_options['fragment'] = NULL;
$replacements[$original] = url('comment/' . $comment->cid . '/edit', $url_options);
break;
// Default values for the chained tokens handled below.
case 'author':
$replacements[$original] = $sanitize ? filter_xss($comment->name) : $comment->name;
break;
case 'parent':
if (!empty($comment->pid)) {
$parent = comment_load($comment->pid);
$replacements[$original] = $sanitize ? filter_xss($parent->subject) : $parent->subject;
}
break;
case 'created':
$replacements[$original] = format_date($comment->created, 'medium', '', NULL, $language_code);
break;
case 'changed':
$replacements[$original] = format_date($comment->changed, 'medium', '', NULL, $language_code);
break;
case 'node':
$node = node_load($comment->nid);
$title = $node->title;
$replacements[$original] = $sanitize ? filter_xss($title) : $title;
break;
}
}
// Chained token relationships.
if ($node_tokens = token_find_with_prefix($tokens, 'node')) {
$node = node_load($comment->nid);
$replacements += token_generate('node', $node_tokens, array('node' => $node), $options);
}
if ($date_tokens = token_find_with_prefix($tokens, 'created')) {
$replacements += token_generate('date', $date_tokens, array('date' => $comment->created), $options);
}
if ($date_tokens = token_find_with_prefix($tokens, 'changed')) {
$replacements += token_generate('date', $date_tokens, array('date' => $comment->changed), $options);
}
if (($parent_tokens = token_find_with_prefix($tokens, 'parent')) && $parent = comment_load($comment->pid)) {
$replacements += token_generate('comment', $parent_tokens, array('comment' => $parent), $options);
}
if (($author_tokens = token_find_with_prefix($tokens, 'author')) && $account = user_load($comment->uid)) {
$replacements += token_generate('user', $author_tokens, array('user' => $account), $options);
}
}
elseif ($type == 'node' & !empty($data['node'])) {
$node = $data['node'];
foreach ($tokens as $name => $original) {
switch($name) {
case 'comment-count':
$replacements[$original] = $node->comment_count;
break;
case 'comment-count-new':
$replacements[$original] = comment_num_new($node->nid);
break;
}
}
}
return $replacements;
}

View file

@ -0,0 +1,92 @@
<?php
/**
* @file
* Default theme implementation for comments.
*
* Available variables:
* - $author: Comment author. Can be link or plain text.
* - $content: An array of comment items. Use render($content) to print them all, or
* print a subset such as render($content['field_example']). Use
* hide($content['field_example']) to temporarily suppress the printing of a
* given element.
* - $created: Formatted date and time for when the comment was created.
* Preprocess functions can reformat it by calling format_date() with the
* desired parameters on the $comment->created variable.
* - $changed: Formatted date and time for when the comment was last changed.
* Preprocess functions can reformat it by calling format_date() with the
* desired parameters on the $comment->changed variable.
* - $new: New comment marker.
* - $permalink: Comment permalink.
* - $submitted: Submission information created from $author and $created during
* template_preprocess_comment().
* - $picture: Authors picture.
* - $signature: Authors signature.
* - $status: Comment status. Possible values are:
* comment-unpublished, comment-published or comment-preview.
* - $title: Linked title.
* - $classes: String of classes that can be used to style contextually through
* CSS. It can be manipulated through the variable $classes_array from
* preprocess functions. The default values can be one or more of the following:
* - comment: The current template type, i.e., "theming hook".
* - comment-by-anonymous: Comment by an unregistered user.
* - comment-by-node-author: Comment by the author of the parent node.
* - comment-preview: When previewing a new or edited comment.
* The following applies only to viewers who are registered users:
* - comment-unpublished: An unpublished comment visible only to administrators.
* - comment-by-viewer: Comment by the user currently viewing the page.
* - comment-new: New comment since last the visit.
* - $title_prefix (array): An array containing additional output populated by
* modules, intended to be displayed in front of the main title tag that
* appears in the template.
* - $title_suffix (array): An array containing additional output populated by
* modules, intended to be displayed after the main title tag that appears in
* the template.
*
* These two variables are provided for context:
* - $comment: Full comment object.
* - $node: Node object the comments are attached to.
*
* Other variables:
* - $classes_array: Array of html class attribute values. It is flattened
* into a string within the variable $classes.
*
* @see template_preprocess()
* @see template_preprocess_comment()
* @see template_process()
* @see theme_comment()
*
* @ingroup themeable
*/
?>
<div class="<?php print $classes; ?> clearfix"<?php print $attributes; ?>>
<?php print $picture ?>
<?php if ($new): ?>
<span class="new"><?php print $new ?></span>
<?php endif; ?>
<?php print render($title_prefix); ?>
<h3<?php print $title_attributes; ?>><?php print $title ?></h3>
<?php print render($title_suffix); ?>
<div class="submitted">
<?php print $permalink; ?>
<?php print $submitted; ?>
</div>
<div class="content"<?php print $content_attributes; ?>>
<?php
// We hide the comments and links now so that we can render them later.
hide($content['links']);
print render($content);
?>
<?php if ($signature): ?>
<div class="user-signature clearfix">
<?php print $signature ?>
</div>
<?php endif; ?>
</div>
<?php print render($content['links']) ?>
</div>

View file

@ -0,0 +1,11 @@
name = "Comment Hooks Test"
description = "Support module for comment hook tests."
core = 7.x
package = Testing
version = VERSION
hidden = TRUE
; Information added by Drupal.org packaging script on 2024-03-06
version = "7.100"
project = "drupal"
datestamp = "1709734591"

View file

@ -0,0 +1,20 @@
<?php
/**
* @file
* Test module for the comment hooks testing.
*/
/**
* Implements hook_comment_publish().
*/
function comment_hook_test_comment_publish($comment) {
$_SESSION['comment_hook_test'][] = (__FUNCTION__ . ' called');
}
/**
* Implements hook_comment_unpublish().
*/
function comment_hook_test_comment_unpublish($comment) {
$_SESSION['comment_hook_test'][] = (__FUNCTION__ . ' called');
}