| 1 |
<?php
|
| 2 |
// $Id: comment_cck.module,v 1.13 2009/05/08 18:59:42 coreymitchell Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* Implementation of hook_perm().
|
| 6 |
*/
|
| 7 |
function comment_cck_perm() {
|
| 8 |
return array('change cck fields through comments');
|
| 9 |
}
|
| 10 |
|
| 11 |
/**
|
| 12 |
* Implementation of hook_form_alter().
|
| 13 |
*/
|
| 14 |
function comment_cck_form_alter(&$form, &$form_state, $form_id) {
|
| 15 |
if ($form_id == 'comment_form' && user_access('change cck fields through comments')) {
|
| 16 |
$node = node_load($form['nid']['#value']);
|
| 17 |
// Check if any fields in this node type are comment_cck enabled.
|
| 18 |
if ($fields = variable_get('comment_cck_fields_'. $node->type, array())) {
|
| 19 |
// Include the functions to load the full node form.
|
| 20 |
module_load_include('inc', 'content', 'includes/content.node_form');
|
| 21 |
// This is a dummy node form, in which to gather the original fields.
|
| 22 |
$node_form['type'] = array(
|
| 23 |
'#type' => 'value',
|
| 24 |
'#value' => $node->type,
|
| 25 |
);
|
| 26 |
$node_form['#node'] = $node;
|
| 27 |
// This form will contain only the comment_cck enabled fields.
|
| 28 |
$final_form = $node_form;
|
| 29 |
$node_form = content_form($node_form, $form_state);
|
| 30 |
|
| 31 |
foreach ($fields as $field) {
|
| 32 |
if (isset($node_form[$field])) {
|
| 33 |
// Only add fields that are comment_cck enabled.
|
| 34 |
$final_form[$field] = $node_form[$field];
|
| 35 |
$form['#field_info'][$field] = $node_form['#field_info'][$field];
|
| 36 |
}
|
| 37 |
}
|
| 38 |
|
| 39 |
// If the fieldgroup module is installed, put fields into groups.
|
| 40 |
if (function_exists('fieldgroup_form_alter')) {
|
| 41 |
// Call fieldgroup_form_alter() to group the fields.
|
| 42 |
$final_form_id = $node->type .'_node_form';
|
| 43 |
fieldgroup_form_alter($final_form, array(), $final_form_id);
|
| 44 |
}
|
| 45 |
// Leaving the node type in the form causes it to output, so remove.
|
| 46 |
unset($final_form['type']);
|
| 47 |
|
| 48 |
// Add the comment_cck fields to comment_filter in order to postion it
|
| 49 |
// within the comment form.
|
| 50 |
$form['comment_filter']['comment_cck'] = $final_form;
|
| 51 |
// Set the position of the comment_cck fields within the comment form.
|
| 52 |
$form['comment_filter']['comment_cck']['#weight'] = 50;
|
| 53 |
// Set the comment_cck fields to output in the correct format.
|
| 54 |
$form['comment_filter']['comment_cck']['#tree'] = TRUE;
|
| 55 |
}
|
| 56 |
return;
|
| 57 |
}
|
| 58 |
if ($form_id == 'content_field_edit_form' && !$form_state['change_basic']) {
|
| 59 |
// Enable comment_ck to alter this field within this content type.
|
| 60 |
$form['widget']['comment_cck_enabled'] = array(
|
| 61 |
'#type' => 'checkbox',
|
| 62 |
'#title' => t('Allow comments to alter this field'),
|
| 63 |
'#description' => t('If checked, comments can alter this CCK field.'),
|
| 64 |
'#default_value' => in_array($form['field_name']['#value'], variable_get('comment_cck_fields_'. $form['type_name']['#value'], array())),
|
| 65 |
);
|
| 66 |
$form['#submit'][] = '_comment_cck_field_edit_form_submit';
|
| 67 |
}
|
| 68 |
}
|
| 69 |
|
| 70 |
function _comment_cck_field_edit_form_submit($form, &$form_state) {
|
| 71 |
$type_name = $form_state['values']['type_name'];
|
| 72 |
$field_name = $form_state['values']['field_name'];
|
| 73 |
if ($form_state['values']['comment_cck_enabled'] == TRUE) {
|
| 74 |
$fields = variable_get('comment_cck_fields_'. $type_name, array());
|
| 75 |
// Merge this field with other fields for this content type.
|
| 76 |
$fields = array_merge(array($field_name => $field_name), $fields);
|
| 77 |
variable_set('comment_cck_fields_'. $type_name, $fields);
|
| 78 |
}
|
| 79 |
else {
|
| 80 |
// Get the list of comment_cck enabled fields for this content type.
|
| 81 |
$fields = variable_get('comment_cck_fields_'. $type_name, array());
|
| 82 |
// Unset this field from the list.
|
| 83 |
unset($fields[$field_name]);
|
| 84 |
// Set the list of comment_cck enabled fields again.
|
| 85 |
variable_set('comment_cck_fields_'. $type_name, $fields);
|
| 86 |
}
|
| 87 |
return;
|
| 88 |
}
|
| 89 |
|
| 90 |
/**
|
| 91 |
* Implementation of hook_comment().
|
| 92 |
*/
|
| 93 |
function comment_cck_comment(&$comment, $op) {
|
| 94 |
// Ignore if a user without the correct permissions submitted this comment.
|
| 95 |
if (!user_access('change cck fields through comments') && $op != 'view') {
|
| 96 |
return;
|
| 97 |
}
|
| 98 |
|
| 99 |
switch ($op) {
|
| 100 |
case 'update': case 'insert':
|
| 101 |
$original_node = node_load($comment['nid']);
|
| 102 |
if ($fields = variable_get('comment_cck_fields_'. $original_node->type, array())) {
|
| 103 |
// Ungroup the fields in this comment, if necessary.
|
| 104 |
$comment_fields = _comment_cck_ungroup_fields($comment['comment_cck'], $fields, $original_node->type);
|
| 105 |
// Merge the updated fields in this comment with the original node.
|
| 106 |
$node = (object) array_merge((array) $original_node, $comment_fields);
|
| 107 |
if($op == 'update') {
|
| 108 |
// We don't want a node revision, since we're updating an old comment.
|
| 109 |
// @TODO: Do we?
|
| 110 |
$node->revision = 0;
|
| 111 |
$node->vid = db_result(db_query('SELECT vid FROM {comment_cck_revisions} WHERE cid = %d', $comment['cid']));
|
| 112 |
// Save the node with the updated field data.
|
| 113 |
node_save($node);
|
| 114 |
}
|
| 115 |
else {
|
| 116 |
$node->revision = 1;
|
| 117 |
// Save the node with the updated field data.
|
| 118 |
node_save($node);
|
| 119 |
// Record that this comment added a node revision.
|
| 120 |
db_query('INSERT INTO {comment_cck_revisions} (cid, vid, previous_vid) VALUES (%d, %d, %d)', $comment['cid'], $node->vid, $previous_vid);
|
| 121 |
// Update the comment revision id.
|
| 122 |
// @TODO: What is this needed for?
|
| 123 |
$comment['revision_id'] = $node->vid;
|
| 124 |
}
|
| 125 |
}
|
| 126 |
break;
|
| 127 |
|
| 128 |
case 'view':
|
| 129 |
$node = node_load($comment->nid);
|
| 130 |
if ($fields = variable_get('comment_cck_fields_'. $node->type, array())) {
|
| 131 |
// We'll prepend the updated fields to the comment, not append.
|
| 132 |
$comment_text = $comment->comment;
|
| 133 |
// Get the comment_cck revisions associated with this comment.
|
| 134 |
$comment_revision = db_fetch_object(db_query('SELECT * FROM {comment_cck_revisions} WHERE cid = %d', $comment->cid));
|
| 135 |
if (!is_object($comment_revision)) {
|
| 136 |
// @TODO: Get this to work on preview. For now, degrade gracefully.
|
| 137 |
break;
|
| 138 |
}
|
| 139 |
if ($comment->op == t('Preview')) {
|
| 140 |
// @TODO: Is this a better way to check for preview? Get working!
|
| 141 |
break;
|
| 142 |
}
|
| 143 |
$current_node = _comment_cck_build_node((int) $comment->nid, $comment_revision->vid);
|
| 144 |
$previous_node = _comment_cck_build_node((int) $comment->nid, $comment_revision->previous_vid);
|
| 145 |
$cck_fields = content_types($node->type);
|
| 146 |
|
| 147 |
$result = array();
|
| 148 |
foreach ($fields as $field) {
|
| 149 |
// Check if the field was changed with this comment.
|
| 150 |
if ($current_node->$field != $previous_node->$field) {
|
| 151 |
// Render the current field.
|
| 152 |
$current_field = _comment_cck_render_field($field, $cck_fields, $current_node);
|
| 153 |
// Render the previous field.
|
| 154 |
$previous_field = _comment_cck_render_field($field, $cck_fields, $previous_node);
|
| 155 |
// Iterate over the current field values.
|
| 156 |
foreach ($current_field as $delta => $item) {
|
| 157 |
// Make sure they're different.
|
| 158 |
if ($item != $previous_field[$delta]) {
|
| 159 |
// They're different. Add them.
|
| 160 |
_comment_cck_rendering(TRUE);
|
| 161 |
$result[] = array($cck_fields['fields'][$field]['widget']['label'] .': ', drupal_render($previous_field[$delta]), "»", drupal_render($item));
|
| 162 |
_comment_cck_rendering(FALSE);
|
| 163 |
}
|
| 164 |
}
|
| 165 |
}
|
| 166 |
}
|
| 167 |
// If this comment changed any fields, update the comment output.
|
| 168 |
if (!empty($result)) {
|
| 169 |
drupal_add_css(drupal_get_path('module', 'comment_cck') .'/comment_cck.css');
|
| 170 |
// @TODO: Create template and preprocessing function.
|
| 171 |
$comment->comment = theme('table', array(), $result, array('class' => 'comment_cck')) . $comment_text;
|
| 172 |
}
|
| 173 |
}
|
| 174 |
break;
|
| 175 |
}
|
| 176 |
return $comment;
|
| 177 |
}
|
| 178 |
|
| 179 |
/**
|
| 180 |
* Build a node and it's content.
|
| 181 |
*/
|
| 182 |
function _comment_cck_build_node($criteria, $revision) {
|
| 183 |
$node = node_load($criteria, $revision);
|
| 184 |
$node = node_build_content($node);
|
| 185 |
return $node;
|
| 186 |
}
|
| 187 |
|
| 188 |
/**
|
| 189 |
* Render a field.
|
| 190 |
*/
|
| 191 |
function _comment_cck_render_field($field_name, $cck_fields, $node) {
|
| 192 |
// Mostly taken from content.module.
|
| 193 |
$field_types = _content_field_types();
|
| 194 |
$field = $cck_fields['fields'][$field_name];
|
| 195 |
$node_field = isset($node->$field_name) ? $node->$field_name : array();
|
| 196 |
$cck_submodule = $field_types[$field['type']]['module'];
|
| 197 |
$function = $cck_submodule .'_field';
|
| 198 |
if (function_exists($function)) {
|
| 199 |
$result = $function('view', $node, $field, $node_field, NULL, NULL);
|
| 200 |
}
|
| 201 |
if (!isset($result)) {
|
| 202 |
$result = content_field('view', $node, $field, $node_field, NULL, NULL);
|
| 203 |
}
|
| 204 |
$return = array();
|
| 205 |
if (is_array($result)) {
|
| 206 |
$return = $result;
|
| 207 |
}
|
| 208 |
elseif (isset($result)) {
|
| 209 |
$return[] = $result;
|
| 210 |
}
|
| 211 |
return $return;
|
| 212 |
}
|
| 213 |
|
| 214 |
/**
|
| 215 |
* Implementation of hook_preprocess_content_field().
|
| 216 |
*/
|
| 217 |
function comment_cck_preprocess_content_field(&$variables) {
|
| 218 |
if (_comment_cck_rendering()) {
|
| 219 |
// Hide the field labels as output by CCK.
|
| 220 |
$variables['label_display'] = 'hidden';
|
| 221 |
}
|
| 222 |
}
|
| 223 |
|
| 224 |
/**
|
| 225 |
* Flatten grouped fields.
|
| 226 |
*/
|
| 227 |
function _comment_cck_ungroup_fields($comment_fields, $fields, $node_type) {
|
| 228 |
// @TODO: I'm sure this can be improved, but it works for now.
|
| 229 |
if (module_exists('fieldgroup')) {
|
| 230 |
$comment_fields_flat = array();
|
| 231 |
foreach ($fields as $key => $field) {
|
| 232 |
if ($group_name = fieldgroup_get_group($node_type, $field)) {
|
| 233 |
if ($comment_fields[$group_name][$field]) {
|
| 234 |
$comment_fields_flat[$key] = $comment_fields[$group_name][$field];
|
| 235 |
}
|
| 236 |
}
|
| 237 |
else {
|
| 238 |
$comment_fields_flat[$key] = $comment_fields[$field];
|
| 239 |
}
|
| 240 |
}
|
| 241 |
return $comment_fields_flat;
|
| 242 |
}
|
| 243 |
|
| 244 |
return $comment_fields;
|
| 245 |
}
|
| 246 |
|
| 247 |
/**
|
| 248 |
* Keep track if we're rendering a field for a comment rather than a node.
|
| 249 |
*/
|
| 250 |
function _comment_cck_rendering($set = NULL) {
|
| 251 |
static $rendering;
|
| 252 |
if (!is_null($set)) {
|
| 253 |
$rendering = $set;
|
| 254 |
}
|
| 255 |
return $rendering;
|
| 256 |
}
|