flag_comment.inc 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. <?php
  2. /**
  3. * @file
  4. * Contains the flag_comment class.
  5. */
  6. /**
  7. * Implements a comment flag.
  8. */
  9. class flag_comment extends flag_entity {
  10. function options() {
  11. $options = parent::options();
  12. $options += array(
  13. 'access_author' => '',
  14. );
  15. return $options;
  16. }
  17. /**
  18. * Options form extras for comment flags.
  19. */
  20. function options_form(&$form) {
  21. parent::options_form($form);
  22. $form['access']['access_author'] = array(
  23. '#type' => 'radios',
  24. '#title' => t('Flag access by content authorship'),
  25. '#options' => array(
  26. '' => t('No additional restrictions'),
  27. 'comment_own' => t('Users may only flag own comments'),
  28. 'comment_others' => t('Users may only flag comments by others'),
  29. 'node_own' => t('Users may only flag comments of nodes they own'),
  30. 'node_others' => t('Users may only flag comments of nodes by others'),
  31. ),
  32. '#default_value' => $this->access_author,
  33. '#description' => t("Restrict access to this flag based on the user's ownership of the content. Users must also have access to the flag through the role settings."),
  34. );
  35. }
  36. function type_access_multiple($entity_ids, $account) {
  37. $access = array();
  38. // If all subtypes are allowed, we have nothing to say here.
  39. if (empty($this->types)) {
  40. return $access;
  41. }
  42. // Ensure node types are granted access. This avoids a
  43. // node_load() on every type, usually done by applies_to_entity_id().
  44. $query = db_select('comment', 'c');
  45. $query->innerJoin('node', 'n', 'c.nid = n.nid');
  46. $result = $query
  47. ->fields('c', array('cid'))
  48. ->condition('c.cid', $entity_ids, 'IN')
  49. ->condition('n.type', $this->types, 'NOT IN')
  50. ->execute();
  51. foreach ($result as $row) {
  52. $access[$row->nid] = FALSE;
  53. }
  54. return $access;
  55. }
  56. function get_entity_id($comment) {
  57. // Store the comment object in the static cache, to avoid getting it
  58. // again unneedlessly.
  59. $this->remember_entity($comment->cid, $comment);
  60. return $comment->cid;
  61. }
  62. /**
  63. * Overrides flag_flag::get_flagging_record().
  64. *
  65. * This queries for flagging records for all comments on the node for the
  66. * current comment, and prefills the flag_get_user_flags() static cache with
  67. * the result for a performance gain.
  68. */
  69. function get_flagging_record($entity_id, $uid = NULL, $sid = NULL) {
  70. static $seen_comment_nids = array();
  71. $comment = $this->fetch_entity($entity_id);
  72. // Figure out if this is the first comment we've seen for its parent node.
  73. if (!isset($seen_comment_nids[$comment->nid])) {
  74. // Preload the flag_get_user_flags() static cache with flagging records
  75. // for all the comments on the node. This means that if multiple comments
  76. // on this node are being viewed, only one query is run for all their
  77. // flagging records, rather than one for each comment. This is because
  78. // flag_get_user_flags() can only optimized across flags on one entity.
  79. $flag_get_user_flags_cache = &drupal_static('flag_get_user_flags');
  80. // We need to get a row for each comment, including empty ones if there is
  81. // no flagging, so that the cache is warmed up for all comments. Therefore
  82. // the query has to have the {comment} table as its base, and include the
  83. // comment cid field.
  84. $query = db_select('comment', 'c');
  85. $query->leftJoin('flagging', 'f',
  86. "c.cid = f.entity_id AND f.entity_type = 'comment'");
  87. $query->fields('f')
  88. ->fields('c', array('cid'))
  89. ->condition('c.nid', $comment->nid)
  90. ->condition(db_or()
  91. // We want to include rows for comments which have no flaggings at all
  92. // for the current user.
  93. ->isNull('f.flagging_id')
  94. // The same conditions as flag_get_user_flags()'s query.
  95. ->condition(db_and()
  96. ->condition(db_or()
  97. ->condition('f.uid', $uid)
  98. ->condition('f.uid', 0)
  99. )
  100. ->condition('f.sid', $sid)
  101. )
  102. );
  103. // The result set can have multiple rows for a single comment, and rows
  104. // which have no flagging ID, so there's nothing useful to index it by.
  105. $result = $query->execute()->fetchAll();
  106. $flag_names = _flag_get_flag_names();
  107. foreach ($result as $flagging_data) {
  108. $cid = $flagging_data->cid;
  109. // At the very least, we need an empty array for the entity ID key in
  110. // the cache array, so it counts as present.
  111. if (!isset($flag_get_user_flags_cache[$uid][$sid]['comment'][$cid])) {
  112. $flag_get_user_flags_cache[$uid][$sid]['comment'][$cid] = array();
  113. }
  114. // If the flagging table gave us no data, we're done with this row.
  115. if (is_null($flagging_data->flagging_id)) {
  116. continue;
  117. }
  118. // Remove the comment ID field from the row, so it's just the flagging
  119. // table row.
  120. unset($flagging_data->cid);
  121. $flag_get_user_flags_cache[$uid][$sid]['comment'][$cid][$flag_names[$flagging_data->fid]] = $flagging_data;
  122. }
  123. // Mark that we've seen this node so we don't process it again.
  124. $seen_comment_nids[$comment->nid] = TRUE;
  125. }
  126. // Return data for the comment we were asked about.
  127. $user_flags = flag_get_user_flags($this->entity_type, $entity_id, $uid, $sid);
  128. return isset($user_flags[$this->name]) ? $user_flags[$this->name] : NULL;
  129. }
  130. function get_labels_token_types() {
  131. return array_merge(array('comment', 'node'), parent::get_labels_token_types());
  132. }
  133. function replace_tokens($label, $contexts, $options, $entity_id) {
  134. if ($entity_id) {
  135. if (($comment = $this->fetch_entity($entity_id)) && ($node = node_load($comment->nid))) {
  136. $contexts['node'] = $node;
  137. $contexts['comment'] = $comment;
  138. }
  139. }
  140. return parent::replace_tokens($label, $contexts, $options, $entity_id);
  141. }
  142. function get_flag_action($entity_id) {
  143. $flag_action = parent::get_flag_action($entity_id);
  144. $comment = $this->fetch_entity($entity_id);
  145. $flag_action->content_title = $comment->subject;
  146. $flag_action->content_url = $this->_flag_url("comment/$comment->cid", "comment-$comment->cid");
  147. return $flag_action;
  148. }
  149. function get_relevant_action_objects($entity_id) {
  150. $comment = $this->fetch_entity($entity_id);
  151. return array(
  152. 'comment' => $comment,
  153. 'node' => node_load($comment->nid),
  154. );
  155. }
  156. }