[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/modules/project_issue/includes/ -> comment.inc (source)

   1  <?php
   2  // $Id: comment.inc,v 1.156 2010/01/17 00:26:58 dww Exp $
   3  
   4  function project_issue_comment(&$arg, $op) {
   5    // $arg can be a comment object, or a form or form_values.
   6    if (is_object($arg)) {
   7      $nid = $arg->nid;
   8    }
   9    elseif (is_array($arg)) {
  10      $nid = is_array($arg['nid']) ? $arg['nid']['#value'] : $arg['nid'];
  11    }
  12    $node = node_load($nid);
  13    if ($node->type != 'project_issue') {
  14      return;
  15    }
  16    // Make a copy here so we have all the original metadata, since some
  17    // of it can change below.
  18    $original_node = drupal_clone($node);
  19    $old_data = (object) $original_node->project_issue;
  20    $old_data->title = $original_node->title;
  21  
  22    // Maintain an array of project ids that are affected by this comment
  23    // operation. We'll use this to invalidate the "Issue cockpit" block cache
  24    // for any of these projects.
  25    $affected_projects = array();
  26  
  27    switch ($op) {
  28      case 'insert':
  29        // Get a lock on the issue in order to generate the next comment ID.
  30        $tries = 20;
  31        $sleep_increment = 0;
  32        while ($tries) {
  33          $lock = db_query("UPDATE {project_issues} SET db_lock = 1 WHERE nid = %d AND db_lock = 0", $arg['nid']);
  34          if (db_affected_rows()) {
  35            $id = db_result(db_query("SELECT last_comment_id FROM {project_issues} WHERE nid = %d", $arg['nid'])) + 1;
  36            db_query("UPDATE {project_issues} SET last_comment_id = %d, db_lock = 0 WHERE nid = %d", $id, $arg['nid']);
  37            break;
  38          }
  39  
  40          // Wait a random and increasing amount of time before the next attempt.
  41          $sleep = rand(10000, 1000000) + $sleep_increment;
  42          usleep($sleep);
  43          $sleep_increment += 50000;
  44          $tries--;
  45        }
  46  
  47        if (isset($id)) {
  48          $rid = isset($arg['project_info']['rid']) ? $arg['project_info']['rid'] : 0;
  49          db_query("INSERT INTO {project_issue_comments} (nid, cid, pid, rid, component, category, priority, assigned, sid, title, timestamp, comment_number) VALUES (%d, %d, %d, %d, '%s', '%s', %d, %d, %d, '%s', %d, %d)", $arg['nid'], $arg['cid'], $arg['project_info']['pid'], $rid, $arg['project_info']['component'], $arg['category'], $arg['priority'], $arg['project_info']['assigned'], $arg['sid'], $arg['title'], $arg['timestamp'], $id);
  50          db_query("UPDATE {comments} SET subject = '%s' WHERE cid = %d", "#$id", $arg['cid']);
  51          project_issue_update_by_comment($arg, 'insert');
  52          $affected_projects[$old_data->pid] = 1;
  53          $affected_projects[$arg['project_info']['pid']] = 1;
  54        }
  55        else {
  56          drupal_set_message(t('There was an error submitting your comment -- please try again. If the problem persists, contact the system administrator.'), 'error');
  57          watchdog('project_issue', 'Error obtaining lock for project issue %nid', array('%nid' => $arg['nid']), WATCHDOG_ERROR, 'node/'. $arg['nid']);
  58          // This is a bit extreme, but we have to clean up the failed comment,
  59          // or it will appear on the issue.
  60          _comment_delete_thread((object) $arg);
  61          _comment_update_node_statistics($arg['nid']);
  62          cache_clear_all();
  63          // The hard redirect prevents any bogus data from being inserted for the failed comment.
  64          drupal_goto('node/'. $arg['nid']);
  65        }
  66        break;
  67  
  68      case 'update':
  69        project_issue_update_by_comment($arg, 'update');
  70        // Updating a comment can't change anything relevant about the issue for
  71        // the purposes of the issue blocks, so we don't need to touch
  72        // $affected_projects here.
  73        break;
  74  
  75      case 'delete':
  76        // Save the project that's specified in this comment so we can
  77        // invalidate its issue block cache.
  78        $deleted_comment_project_id = db_result(db_query("SELECT pid FROM {project_issue_comments} WHERE cid = %d", $arg->cid));
  79        $affected_projects[$deleted_comment_project_id] = 1;
  80        // Actually delete the comment
  81        db_query("DELETE FROM {project_issue_comments} WHERE cid = %d", $arg->cid);
  82        $current_data = project_issue_update_by_comment($arg, 'delete');
  83        // We should also invalidate the block cache for whatever project is now
  84        // used for this issue, since we might be deleting a comment that moved
  85        // an issue from one project to another.
  86        $affected_projects[$current_data->pid] = 1;      
  87        break;
  88  
  89      case 'view':
  90        if (isset($arg->cid)) {
  91          $project_issue_table = project_issue_comment_view($original_node, $arg);
  92        }
  93        else {
  94          // Previewing a comment.
  95          $test = drupal_clone($arg);
  96          $test->pid = $arg->project_info['pid'];
  97          $test->component = $arg->project_info['component'];
  98          $test->assigned = $arg->project_info['assigned'];
  99          // Add a dummy rid if necessary -- prevents incorrect change data.
 100          $test->rid = isset($arg->project_info['rid']) ? $arg->project_info['rid'] : 0;
 101          $comment_changes = project_issue_metadata_changes($node, $old_data, $test, project_issue_field_labels('web'));
 102          $project_issue_table = theme('project_issue_comment_table', $comment_changes);
 103        }
 104        if ($project_issue_table) {
 105          $arg->comment = '<div class="project-issue"><div class="summary">'. $project_issue_table .'</div></div>' . $arg->comment;
 106        }
 107        break;
 108  
 109    }
 110    // If there are any affected projects, invalidate the block cache for those.
 111    if (!empty($affected_projects)) {
 112      foreach ($affected_projects as $pid => $value) {
 113        $cid = 'project_issue_cockpit_block:'. $pid;
 114        cache_clear_all($cid, 'cache');
 115      }
 116    }
 117  }
 118  
 119  /**
 120   * Add project issue metadata to the comment form.
 121   *
 122   * @param $form
 123   *   Reference to form structure.
 124   * @param $form_state
 125   *   Current form state.
 126   */
 127  function project_issue_form_comment_form_alter(&$form, &$form_state) {
 128    $nid = $form['nid']['#value'];
 129    $node = node_load($nid);
 130  
 131    // Allows only project_issue
 132    if ($node->type != 'project_issue') {
 133      return;
 134    }
 135  
 136    // Comment body is not required since we validate that ourselves.
 137    unset($form['comment_filter']['comment']['#required']);
 138  
 139    // The 'your name' item just wastes screen estate.
 140    unset($form['_author']);
 141  
 142    // For existing comments, we want to preserve the comment subject,
 143    // Even if the subject field is disabled.
 144    if ($cid = $form['cid']['#value']) {
 145      $subject = db_result(db_query('SELECT subject FROM {comments} WHERE cid = %d', $cid));
 146    }
 147    // For new comments, show the expected next number for previews.
 148    // This is only for show, the number will be generated when the comment
 149    // is posted.
 150    else {
 151      $next_id = db_result(db_query('SELECT last_comment_id FROM {project_issues} WHERE nid = %d', $form['nid']['#value'])) + 1;
 152      $subject = "#$next_id";
 153      // Clobber the comment signature for new followups if necessary.
 154      // TODO: Revamp this for Drupal 6.
 155      if (!variable_get('project_issue_show_comment_signatures', 0)) {
 156        $form['comment_filter']['comment']['#default_value'] = '';
 157      }
 158    }
 159    $form['subject'] = array(
 160      '#type' => 'value',
 161      '#value' => $subject,
 162    );
 163  
 164    // Any time we're on a reply page, show the full issue below the reply.
 165    if (project_issue_is_comment_reply()) {
 166      $form['#pre_render'][] = 'project_issue_comment_pre_render';
 167    }
 168  
 169    // Make sure project is current here -- it may have changed when posted.
 170    if (!empty($form_state['values']['project_info']['pid'])) {
 171      $node->project_issue['pid'] = $form_state['values']['project_info']['pid'];
 172    }
 173    $project = node_load(array('nid' => $node->project_issue['pid'], 'type' => 'project_project'));
 174  
 175    project_issue_set_breadcrumb($node, $project);
 176  
 177    // Only allow metadata changes on new followups.
 178    if (isset($form['cid']['#value'])) {
 179      return;
 180    }
 181  
 182    // We have to set $form['#action'] to prevent AHAH nastiness.
 183    if (!empty($form['pid']['#value'])) {
 184      $form['#action'] = url('comment/reply/' . $nid . '/' . $form['pid']['#value']);
 185    }
 186    else {
 187      $form['#action'] = url('comment/reply/' . $nid);
 188    }
 189  
 190    // We need to ask for almost the same metadata as project issue itself
 191    // so let's reuse the form.
 192    $form += project_issue_form($node, $form_state, TRUE);
 193  
 194    // comment.module is basically still FAPI v1. It sets the preview button to
 195    // #type 'button', so FAPI doesn't really consider that a form submission.
 196    // However, we depend on the form being rebuilt on preview to do our magic.
 197    // Thanks to a change in 6.14 core, form.inc will only rebuild the form if
 198    // $form_state['submitted'] is TRUE. So, we set the preview button to
 199    // actually be a 'submit' button so that the form is rebuilt on preview and
 200    // our comment preview code can kick in.
 201    $form['preview']['#type'] = 'submit';
 202  
 203    // We need this otherwise pid collides with comment.
 204    $form['project_info']['#tree'] = TRUE;
 205    $form['project_info']['#weight'] = -2;
 206  
 207    // Remove the form item that displays the current project, and
 208    // replace the static single project value with a select list
 209    // of all projects to make swapping simpler.
 210    unset($form['project_info']['project_display']);
 211    $uris = NULL;
 212  
 213    if (variable_get('project_issue_autocomplete', 0) == 1) {
 214      $form['project_info']['project_title'] = array(
 215        '#type' => 'textfield',
 216        '#title' => t('Project'),
 217        '#default_value' => $project->title,
 218        '#required' => TRUE,
 219        '#weight' => -1,
 220        '#size' => 35,
 221        '#autocomplete_path' => 'project/autocomplete/issue/project',
 222        '#attributes' => array(
 223          'onFocus' => 'project_issue_autocomplete_handler()',
 224        ),
 225        '#ahah' => array(
 226          'progress' => array(
 227            'type' => 'none',
 228          ),
 229          'path' => 'project/issues/update_project',
 230          'wrapper' => 'project-info-wrapper',
 231        ),
 232      );
 233    }
 234    else {
 235      $projects = project_projects_select_options($uris);
 236      $form['project_info']['pid'] = array(
 237        '#type' => 'select',
 238        '#title' => t('Project'),
 239        '#default_value' => $project->nid,
 240        '#options' => $projects,
 241        '#required' => TRUE,
 242        '#weight' => -1,
 243        '#ahah' => array(
 244          'path' => 'project/issues/update_project',
 245          'wrapper' => 'project-info-wrapper',
 246          'event' => 'change',
 247        ),
 248      );
 249    }
 250  
 251    $form['issue_info']['#weight'] = -1;
 252    $form['#prefix'] = '<div class="project-issue"><div class="node-form"><div class="standard">';
 253    $form['#suffix'] = '</div></div></div>';
 254  
 255    $form['original_issue'] = array(
 256      '#type' => 'fieldset',
 257      '#title' => t('Edit issue settings'),
 258      '#description' => t('Note: changing any of these items will update the issue\'s overall values.'),
 259      '#collapsible' => TRUE,
 260      '#weight' => -10,
 261    );
 262  
 263    $form['original_issue']['title'] = array(
 264      '#type' => 'textfield',
 265      '#title' => t('Issue title'),
 266      '#maxlength' => 128,
 267      '#default_value' => $node->title,
 268      '#weight' => -30,
 269      '#required' => TRUE,
 270    );
 271  
 272    $form['project_info']['assigned'] = $form['issue_info']['assigned'];
 273    unset($form['issue_info']['assigned']);
 274  
 275    $form['project_info']['#prefix'] = '<div id="project-info-wrapper" class="inline-options">';
 276    $form['project_info']['#suffix'] = '</div>';
 277  
 278    // Remove the 'Project information' and 'Issue information' fieldsets,
 279    // since we'll move everything inside the 'Edit issue settings' fieldset.
 280    unset($form['project_info']['#type'], $form['project_info']['#title']);
 281    unset($form['issue_info']['#type'], $form['issue_info']['#title']);
 282  
 283    // Restructure the UI to de-emphasize the original project form inputs.
 284    $form['original_issue']['project_info'] = $form['project_info'];
 285    $form['original_issue']['issue_info'] = $form['issue_info'];
 286    unset($form['project_info'], $form['issue_info']);
 287    unset($form['issue_details'], $form['project_help']);
 288    drupal_add_js(drupal_get_path('module', 'project_issue') .'/project_issue.js');
 289  }
 290  
 291  /**
 292   * Validate issue metadata on the comment form.
 293   *
 294   * @param $form
 295   *   The Drupal form structure.
 296   * @param $form_state
 297   *   The current state of the form.
 298   */
 299  function project_issue_form_comment_validate($form, &$form_state) {
 300    if (empty($form['cid']['#value']) && variable_get('project_issue_autocomplete', 0) == 1) {
 301      if (empty($form_state['values']['project_info']['project_title'])) {
 302        form_set_error('project_title', t('You must enter a project to navigate to.'));
 303      }
 304      else {
 305        $pid = db_result(db_query("SELECT nid FROM {node} WHERE title = '%s' AND type = '%s'", $form_state['values']['project_info']['project_title'], 'project_project'));
 306        if (empty($pid)) {
 307          form_set_error('project_info][project_title', t('The name you entered (%title) is not a valid project.', array('%title' => $form_state['values']['project_info']['project_title'])));
 308        }
 309        else {
 310          $form_state['values']['project_info']['pid'] = $pid;
 311        }
 312      }
 313    }
 314  
 315    if (!empty($form_state['rebuild'])) {
 316      return;
 317    }
 318    $values = $form_state['values'];
 319    $project_info = $form_state['values']['project_info'];
 320    $nid = $values['nid'];
 321    $node = node_load($nid);
 322  
 323    // Make a copy here so we have all the original metadata, since some
 324    // of it can change below.
 325    $original_node = drupal_clone($node);
 326    $old_data = (object) $original_node->project_issue;
 327    $old_data->title = $original_node->title;
 328  
 329    // Adjust new file attachments to go to the issues directory.
 330    // We have to do this during validate, otherwise we might miss
 331    // adjusting the filename before comment upload saves it (module weighting)
 332    // TODO: is this still true?
 333    project_issue_change_comment_upload_path($values);
 334  
 335    // Only validate metadata changes on new followups.
 336    if (isset($values['cid'])) {
 337      return;
 338    }
 339  
 340    // Make sure project is current here -- it may have changed when posted.
 341    if (isset($project_info['pid'])) {
 342      $node->project_issue['pid'] = $project_info['pid'];
 343    }
 344    $project = node_load($node->project_issue['pid']);
 345  
 346    if (!empty($project) && $project->type == 'project_project') {
 347      // Force all comments to be a child of the main issue, to match the
 348      // flat display, and also to prevent accidentally deleting a thread.
 349      $form_state['values']['pid'] = 0;
 350  
 351      // Validate version.
 352      if (module_exists('project_release') && isset($project_info['rid']) && ($releases = project_release_get_releases($project, 0, 'version', 'all', array($project_info['rid'])))) {
 353        $rid = $project_info['rid'];
 354        if ($rid && !in_array($rid, array_keys($releases))) {
 355          $rid = 0;
 356        }
 357        // Check to make sure this release is not marked as an invalid
 358        // release node for user selection.
 359        $invalid_rids = variable_get('project_issue_invalid_releases', array());
 360        if (!empty($invalid_rids) &&
 361            ((empty($rid) && in_array($node->project_issue['rid'], $invalid_rids))
 362             || in_array($rid, $invalid_rids))) {
 363          form_set_error('project_info][rid', t('%version is not a valid version, please select a different value.', array('%version' => $releases[$node->project_issue['rid']])));
 364        }
 365        elseif (empty($rid)) {
 366          form_set_error('project_info][rid', t('You have to specify a valid version.'));
 367        }
 368      }
 369      // Add a dummy rid if necessary -- prevents incorrect change data.
 370      else {
 371        $rid = 0;
 372      }
 373      // Validate component.
 374      $component = $project_info['component'];
 375      if ($component && !in_array($component, $project->project_issue['components'])) {
 376        $component = 0;
 377      }
 378      empty($component) && form_set_error('project_info][component', t('You have to specify a valid component.'));
 379    }
 380    else {
 381      form_set_error('project_info][pid', t('You have to specify a valid project.'));
 382    }
 383    empty($values['category']) && form_set_error('category', t('You have to specify a valid category.'));
 384  
 385    // Now, make sure the comment changes *something* about the issue.
 386    // If the user uploaded a file, so long as it's not marked for removal,
 387    // we consider that a valid change to the issue, too.
 388    $has_file = FALSE;
 389    $files = isset($values['files']) ? $values['files'] : array();
 390    foreach ($files as $number => $data) {
 391      if (empty($data['remove'])) {
 392        $has_file = TRUE;
 393        break;
 394      }
 395    }
 396    if (!$has_file && empty($values['comment'])) {
 397  
 398      $comment = drupal_clone((object) $values);
 399      $comment->pid = $project_info['pid'];
 400      $comment->component = $component;
 401      $comment->rid = $rid;
 402      $comment->assigned = $project_info['assigned'];
 403      $comment_changes = project_issue_metadata_changes($node, $old_data, $comment, project_issue_field_labels('web'));
 404      // If the PID changed, rebuild the form
 405      if (isset($comment_changes['pid']['new']) && $comment_changes['pid']['new'] === TRUE) {
 406        $form_state['rebuild'] = TRUE;
 407      }
 408      $has_change = FALSE;
 409      foreach ($comment_changes as $field => $changes) {
 410        if (isset($changes['new'])) {
 411          $has_change = TRUE;
 412          break;
 413        }
 414      }
 415      if (!$has_change) {
 416        form_set_error('comment', t('You must either add a comment, upload a file, or change something about this issue.'));
 417      }
 418    }
 419  }
 420  
 421  /**
 422   * Theme a project issue metadata table.
 423   *
 424   * @param $comment_changes
 425   *  Array containing metadata differences between comments
 426   *  as returned by project_issue_metadata_changes().
 427   * @return
 428   *  The themed metadata table.
 429   */
 430  function theme_project_issue_comment_table($comment_changes) {
 431    $rows = array();
 432    foreach ($comment_changes as $field => $change) {
 433      if (!empty($change['label']) && isset($change['old']) && isset($change['new'])) {
 434        $rows[] = theme('project_issue_comment_table_row', $field, $change);
 435      }
 436    }
 437    return $rows ? theme('table', array(), $rows) : '';
 438  }
 439  
 440  /**
 441   * Theme a single row of the project issue metadata changes table.
 442   *
 443   * @param $field
 444   *   The name of the field to theme.
 445   * @param $change
 446   *   A nested array containing changes to project issue metadata
 447   *   for the given issue or comment.
 448   * @return
 449   *   An array representing one row of the table.
 450   *
 451   * NOTE:  If you override this theme function, you *must* make sure
 452   * that you sanitize all output from this function that is displayed
 453   * to the user.  No further escaping/filtering of the data in this
 454   * table will take place after this function.  In most cases
 455   * this means that you need to run the $change['label'], $change['old'],
 456   * and $change['new'] values through either the check_plain() or
 457   * filter_xss() function to prevent XSS and other types
 458   * of problems due to any malicious input in these
 459   * field values.
 460   */
 461  function theme_project_issue_comment_table_row($field, $change) {
 462    // Allow anchor, emphasis, and strong tags in metadata tables.
 463    $allowed_tags = array('a', 'em', 'strong');
 464    // Fields that should be rendered as plain text, not filtered HTML.
 465    $plain_fields = array('title', 'pid', 'rid');
 466  
 467    if (is_array($change['old']) || is_array($change['new'])) {
 468      $removed = array();
 469      if (is_array($change['old'])){
 470        foreach ($change['old'] as $item) {
 471          $removed[] = '-'. $item;
 472        }
 473      }
 474      elseif (!empty($change['old'])) {
 475        $removed[] = '-'. $change['old'];
 476      }
 477  
 478      $added = array();
 479      if (is_array($change['new'])) {
 480        foreach ($change['new'] as $item) {
 481          $added[] = '+'. $item;
 482        }
 483      }
 484      elseif (!empty($change['new'])) {
 485        $added[] = '+'. $change['new'];
 486      }
 487  
 488      return array(
 489        filter_xss($change['label'], $allowed_tags) .':',
 490        filter_xss(implode(', ', $removed), $allowed_tags),
 491        filter_xss(implode(', ', $added), $allowed_tags),
 492      );
 493    }
 494    elseif (in_array($field, $plain_fields)) {
 495      return array(
 496        filter_xss($change['label'], $allowed_tags) .':',
 497        check_plain(project_issue_change_summary($field, $change['old'])),
 498        '&raquo; '. check_plain(project_issue_change_summary($field, $change['new'])),
 499      );
 500    }
 501    else {
 502      return array(
 503        filter_xss($change['label'], $allowed_tags) .':',
 504        filter_xss(project_issue_change_summary($field, $change['old']), $allowed_tags),
 505        '&raquo; '. filter_xss(project_issue_change_summary($field, $change['new']), $allowed_tags),
 506      );
 507    }
 508  }
 509  
 510  /**
 511   * Returns the issue metadata table for a comment.
 512   *
 513   * @param $node
 514   *  The corresponding node.
 515   * @param $comment
 516   *  The comment, if it's set then metadata will be returned. If it's not
 517   *  set then metadata will be precalculated.
 518   * @return
 519   *  A themed table of issue metadata.
 520   */
 521  function project_issue_comment_view(&$node, $comment = NULL) {
 522    static $project_issue_tables;
 523  
 524    if (isset($comment)) {
 525      return isset($project_issue_tables[$comment->cid]) ? $project_issue_tables[$comment->cid] : '';
 526    }
 527    if (!empty($node->comment_count)) {
 528      $old = unserialize(db_result(db_query('SELECT original_issue_data FROM {project_issues} WHERE nid = %d', $node->nid)));
 529      $labels = project_issue_field_labels('web');
 530      $result = db_query('SELECT p.cid, p.title, p.pid, p.rid, p.component, p.category, p.priority, p.assigned, p.sid FROM {project_issue_comments} p INNER JOIN {comments} c ON p.cid = c.cid WHERE p.nid = %d AND c.status = %d ORDER BY p.timestamp ASC', $node->nid, COMMENT_PUBLISHED);
 531      while ($followup = db_fetch_object($result)) {
 532        $followup_changes = project_issue_metadata_changes($node, $old, $followup, project_issue_field_labels('web'));
 533        $project_issue_tables[$followup->cid] = theme('project_issue_comment_table', $followup_changes);
 534        $old = $followup;
 535      }
 536    }
 537  }
 538  
 539  /**
 540   * Updates the project issue based on the comment inserted/updated/deleted.
 541   *
 542   * @param $comment_data
 543   *  The comment data that's been submitted.
 544   * @param $op
 545   *  The comment operation performed, 'insert', 'update', 'delete'.
 546   * @return
 547   *   An object representing the comment data used to update the issue.
 548   */
 549  function project_issue_update_by_comment($comment_data, $op) {
 550    switch ($op) {
 551      case 'insert':
 552        // Massage the incoming data so the structure is consistent throughout the function.
 553        $comment_data['component'] = $comment_data['project_info']['component'];
 554        $comment_data['pid'] = $comment_data['project_info']['pid'];
 555        $comment_data['rid'] = isset($comment_data['project_info']['rid']) ? $comment_data['project_info']['rid'] : 0;
 556        unset ($comment_data['project_info']);
 557        $comment_data = (object) $comment_data;
 558        // Mark the node for email notification during hook_exit(), so all issue
 559        // and file data is in a consistent state before we generate the email.
 560        if (!isset($comment_data->followup_no_mail)) {  // Temporary hack to get around sending of auto-close emails.
 561          project_issue_set_mail_notify($comment_data->nid);
 562        }
 563        break;
 564      case 'update':
 565        $comment_data = (object) $comment_data;
 566        break;
 567    }
 568  
 569    // In order to deal with deleted/unpublished comments, make sure that we're performing
 570    // the updates to the issue with the latest available published comment.
 571    $comment_data = project_issue_get_newest_comment($comment_data);
 572  
 573    // Update the issue data to reflect the new final states.
 574    db_query("UPDATE {project_issues} SET pid = %d, category = '%s', component = '%s', priority = %d, rid = %d, assigned = %d, sid = %d WHERE nid = %d", $comment_data->pid, $comment_data->category, $comment_data->component, $comment_data->priority, $comment_data->rid, $comment_data->assigned, $comment_data->sid, $comment_data->nid);
 575  
 576    // Update the issue title.
 577    $node = node_load($comment_data->nid, NULL, TRUE);  // Don't use cached since we changed data above.
 578    $node->title = $comment_data->title;
 579  
 580    // This also updates the changed date of the issue.
 581    node_save($node);
 582  
 583    // Return the object of comment data we used to update the issue.
 584    return $comment_data;
 585  }
 586  
 587  /**
 588   * Adjusts the filepath of issue followups so files are saved to
 589   * the correct issues directory.
 590   *
 591   * @param $comment
 592   *   An array of the submitted comment values.
 593   */
 594  function project_issue_change_comment_upload_path(&$comment) {
 595    static $run = NULL;
 596  
 597    // Only for new comments with attachments.
 598    if (empty($comment['cid']) && isset($comment['files']) && !isset($run)) {
 599      $run = TRUE;  // Make sure this only gets run once.
 600      project_issue_rewrite_issue_filepath($comment['files']);
 601    }
 602  }
 603  
 604  /**
 605   * Retrieves the newest published comment for an issue.
 606   *
 607   * @param $comment_data
 608   *   An object representing the current comment being edited
 609   * @return
 610   *   An object representing the most recent published comment for the issue.
 611   */
 612  function project_issue_get_newest_comment($comment_data) {
 613    // Get the cid of the most recent comment.
 614    $latest_cid = db_result(db_query_range('SELECT pic.cid FROM {project_issue_comments} pic INNER JOIN {comments} c ON c.cid = pic.cid WHERE c.nid = %d AND c.status = %d ORDER BY pic.timestamp DESC', $comment_data->nid, COMMENT_PUBLISHED, 0, 1));
 615    if ($latest_cid) {
 616      $comment_data = db_fetch_object(db_query('SELECT * FROM {project_issue_comments} WHERE cid = %d', $latest_cid));
 617    }
 618    // No more comments on the issue -- use the original issue metadata.
 619    else {
 620      // nid isn't stored in the original issue data, so capture it here and pass back
 621      // into the object.
 622      $nid = $comment_data->nid;
 623      $comment_data = unserialize(db_result(db_query("SELECT original_issue_data FROM {project_issues} WHERE nid = %d", $comment_data->nid)));
 624      $comment_data->nid = $nid;
 625    }
 626    return $comment_data;
 627  }
 628  
 629  /**
 630   * Test to determine if the active page is the comment reply form.
 631   *
 632   * @return
 633   *   TRUE if the active page is the comment reply form, FALSE otherwise.
 634   */
 635  function project_issue_is_comment_reply() {
 636    return arg(0) == 'comment' && arg(1) == 'reply';
 637  }
 638  
 639  /**
 640   * Test to determine if the active page is the comment edit form.
 641   *
 642   * @return
 643   *   TRUE if the active page is the comment edit form, FALSE otherwise.
 644   */
 645  function project_issue_is_comment_edit() {
 646    return arg(0) == 'comment' && arg(1) == 'edit';
 647  }
 648  
 649  /**
 650   * Appends the comment thread to the comment reply form.
 651   */
 652  function project_issue_comment_pre_render($form) {
 653    // Force the correct formatting.
 654    $_GET['mode'] = COMMENT_MODE_FLAT_EXPANDED;
 655    $_GET['sort'] = COMMENT_ORDER_OLDEST_FIRST;
 656  
 657    $suffix = empty($form['#suffix']) ? '' : $form['#suffix'];
 658    $node = node_load($form['nid']['#value']);
 659  
 660    // Unfortunately, the comment module blindly puts the node view
 661    // after the comment form on preview, in the case where the comment
 662    // parent is 0.  If we want our issue previews to be consistent, this
 663    // ugly hack is necessary.
 664    if (isset($form['#parameters'][1]['values']['op']) && $form['#parameters'][1]['values']['op'] == t('Preview')) {
 665      $preview = comment_render($node, 0);
 666    }
 667    else {
 668      $preview = node_show($node, 0);
 669    }
 670  
 671    $form['#suffix'] = $suffix . $preview;
 672    return $form;
 673  }


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7