PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/applications/vanilla/controllers/class.moderationcontroller.php

https://github.com/abhishekmica/Garden
PHP | 319 lines | 210 code | 38 blank | 71 comment | 47 complexity | ac08f50f02062eae780830fe06ecf32e MD5 | raw file
  1. <?php if (!defined('APPLICATION')) exit();
  2. /*
  3. Copyright 2008, 2009 Vanilla Forums Inc.
  4. This file is part of Garden.
  5. Garden is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
  6. Garden is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  7. You should have received a copy of the GNU General Public License along with Garden. If not, see <http://www.gnu.org/licenses/>.
  8. Contact Vanilla Forums Inc. at support [at] vanillaforums [dot] com
  9. */
  10. /**
  11. * Moderation Controller
  12. *
  13. * @package Vanilla
  14. */
  15. /**
  16. * Handles content moderation
  17. *
  18. * @since 2.0.18
  19. * @package Vanilla
  20. */
  21. class ModerationController extends VanillaController {
  22. /**
  23. * Looks at the user's attributes and form postback to see if any comments
  24. * have been checked for administration, and if so, puts an inform message on
  25. * the screen to take action.
  26. */
  27. public function CheckedComments() {
  28. $this->DeliveryType(DELIVERY_TYPE_BOOL);
  29. $this->DeliveryMethod(DELIVERY_METHOD_JSON);
  30. ModerationController::InformCheckedComments($this);
  31. $this->Render();
  32. }
  33. /**
  34. * Looks at the user's attributes and form postback to see if any discussions
  35. * have been checked for administration, and if so, puts an inform message on
  36. * the screen to take action.
  37. */
  38. public function CheckedDiscussions() {
  39. $this->DeliveryType(DELIVERY_TYPE_BOOL);
  40. $this->DeliveryMethod(DELIVERY_METHOD_JSON);
  41. ModerationController::InformCheckedDiscussions($this);
  42. $this->Render();
  43. }
  44. /**
  45. * Looks at the user's attributes and form postback to see if any comments
  46. * have been checked for administration, and if so, adds an inform message to
  47. * $Sender to take action.
  48. */
  49. public static function InformCheckedComments($Sender) {
  50. $Session = Gdn::Session();
  51. $HadCheckedComments = FALSE;
  52. $TransientKey = GetValue('TransientKey', $_POST);
  53. if ($Session->IsValid() && $Session->ValidateTransientKey($TransientKey)) {
  54. // Form was posted, so accept changes to checked items.
  55. $DiscussionID = GetValue('DiscussionID', $_POST, 0);
  56. $CheckIDs = GetValue('CheckIDs', $_POST);
  57. $CheckedComments = Gdn::UserModel()->GetAttribute($Session->User->UserID, 'CheckedComments', array());
  58. if (!is_array($CheckedComments))
  59. $CheckedComments = array();
  60. if (!array_key_exists($DiscussionID, $CheckedComments)) {
  61. $CheckedComments[$DiscussionID] = array();
  62. } else {
  63. // Were there checked comments in this discussion before the form was posted?
  64. $HadCheckedComments = count($CheckedComments[$DiscussionID]) > 0;
  65. }
  66. foreach ($CheckIDs as $Check) {
  67. if ($Check['checked'] == 'true') {
  68. if (!ArrayHasValue($CheckedComments, $Check['checkId']))
  69. $CheckedComments[$DiscussionID][] = $Check['checkId'];
  70. } else {
  71. RemoveValueFromArray($CheckedComments[$DiscussionID], $Check['checkId']);
  72. }
  73. }
  74. if (count($CheckedComments[$DiscussionID]) == 0)
  75. unset($CheckedComments[$DiscussionID]);
  76. Gdn::UserModel()->SaveAttribute($Session->User->UserID, 'CheckedComments', $CheckedComments);
  77. } else if ($Session->IsValid()) {
  78. // No form posted, just retrieve checked items for display
  79. $DiscussionID = property_exists($Sender, 'DiscussionID') ? $Sender->DiscussionID : 0;
  80. $CheckedComments = Gdn::UserModel()->GetAttribute($Session->User->UserID, 'CheckedComments', array());
  81. if (!is_array($CheckedComments))
  82. $CheckedComments = array();
  83. }
  84. // Retrieve some information about the checked items
  85. $CountDiscussions = count($CheckedComments);
  86. $CountComments = 0;
  87. foreach ($CheckedComments as $DiscID => $Comments) {
  88. if ($DiscID == $DiscussionID)
  89. $CountComments += count($Comments); // Sum of comments in this discussion
  90. }
  91. if ($CountComments > 0) {
  92. $SelectionMessage = Wrap(sprintf(
  93. 'You have selected %1$s in this discussion.',
  94. Plural($CountComments, '%s comment', '%s comments')
  95. ), 'div');
  96. $ActionMessage = T('Take Action:');
  97. // Can the user delete the comment?
  98. $DiscussionModel = new DiscussionModel();
  99. $Discussion = $DiscussionModel->GetID($DiscussionID);
  100. if ($Session->CheckPermission('Vanilla.Comments.Delete', TRUE, 'Category', $Discussion->CategoryID))
  101. $ActionMessage .= ' '.Anchor(T('Delete'), 'vanilla/moderation/confirmcommentdeletes/'.$DiscussionID, 'Delete Popup');
  102. $Sender->EventArguments['SelectionMessage'] = &$SelectionMessage;
  103. $Sender->EventArguments['ActionMessage'] = &$ActionMessage;
  104. $Sender->EventArguments['Discussion'] = $Discussion;
  105. $Sender->FireEvent('BeforeCheckComments');
  106. $ActionMessage .= ' '.Anchor(T('Cancel'), 'vanilla/moderation/clearcommentselections/'.$DiscussionID.'/{TransientKey}/?Target={SelfUrl}', 'CancelAction');
  107. $Sender->InformMessage(
  108. $SelectionMessage
  109. .Wrap($ActionMessage, 'div', array('class' => 'Actions')),
  110. array(
  111. 'CssClass' => 'NoDismiss',
  112. 'id' => 'CheckSummary'
  113. )
  114. );
  115. } else if ($HadCheckedComments) {
  116. // Remove the message completely if there were previously checked comments in this discussion, but none now
  117. $Sender->InformMessage('', array('id' => 'CheckSummary'));
  118. }
  119. }
  120. /**
  121. * Looks at the user's attributes and form postback to see if any discussions
  122. * have been checked for administration, and if so, adds an inform message to
  123. * $Sender to take action.
  124. */
  125. public static function InformCheckedDiscussions($Sender) {
  126. $Session = Gdn::Session();
  127. $HadCheckedDiscussions = FALSE;
  128. $TransientKey = GetValue('TransientKey', $_POST);
  129. if ($Session->IsValid() && $Session->ValidateTransientKey($TransientKey)) {
  130. // Form was posted, so accept changes to checked items.
  131. $CheckIDs = GetValue('CheckIDs', $_POST);
  132. $CheckedDiscussions = Gdn::UserModel()->GetAttribute($Session->User->UserID, 'CheckedDiscussions', array());
  133. if (!is_array($CheckedDiscussions))
  134. $CheckedDiscussions = array();
  135. // Were there checked discussions before the form was posted?
  136. $HadCheckedDiscussions = count($CheckedDiscussions) > 0;
  137. foreach ($CheckIDs as $Check) {
  138. if ($Check['checked'] == 'true') {
  139. if (!ArrayHasValue($CheckedDiscussions, $Check['checkId']))
  140. $CheckedDiscussions[] = $Check['checkId'];
  141. } else {
  142. RemoveValueFromArray($CheckedDiscussions, $Check['checkId']);
  143. }
  144. }
  145. Gdn::UserModel()->SaveAttribute($Session->User->UserID, 'CheckedDiscussions', $CheckedDiscussions);
  146. } else if ($Session->IsValid()) {
  147. // No form posted, just retrieve checked items for display
  148. $CheckedDiscussions = Gdn::UserModel()->GetAttribute($Session->User->UserID, 'CheckedDiscussions', array());
  149. if (!is_array($CheckedDiscussions))
  150. $CheckedDiscussions = array();
  151. }
  152. // Retrieve some information about the checked items
  153. $CountDiscussions = count($CheckedDiscussions);
  154. if ($CountDiscussions > 0) {
  155. $SelectionMessage = Wrap(sprintf(
  156. 'You have selected %1$s.',
  157. Plural($CountDiscussions, '%s discussion', '%s discussions')
  158. ), 'div');
  159. $ActionMessage = T('Take Action:');
  160. $ActionMessage .= ' '.Anchor(T('Delete'), 'vanilla/moderation/confirmdiscussiondeletes/', 'Delete Popup');
  161. $Sender->EventArguments['SelectionMessage'] = &$SelectionMessage;
  162. $Sender->EventArguments['ActionMessage'] = &$ActionMessage;
  163. $Sender->FireEvent('BeforeCheckDiscussions');
  164. $ActionMessage .= ' '.Anchor(T('Cancel'), 'vanilla/moderation/cleardiscussionselections/{TransientKey}/?Target={SelfUrl}', 'CancelAction');
  165. $Sender->InformMessage(
  166. $SelectionMessage
  167. .Wrap($ActionMessage, 'div', array('class' => 'Actions')),
  168. array(
  169. 'CssClass' => 'NoDismiss',
  170. 'id' => 'CheckSummary'
  171. )
  172. );
  173. } else if ($HadCheckedDiscussions) {
  174. // Remove the message completely if there were previously checked comments in this discussion, but none now
  175. $Sender->InformMessage('', array('id' => 'CheckSummary'));
  176. }
  177. }
  178. /**
  179. * Remove all comments checked for administration from the user's attributes.
  180. */
  181. public function ClearCommentSelections($DiscussionID = '', $TransientKey = '') {
  182. $Session = Gdn::Session();
  183. if ($Session->ValidateTransientKey($TransientKey)) {
  184. $CheckedComments = Gdn::UserModel()->GetAttribute($Session->User->UserID, 'CheckedComments', array());
  185. unset($CheckedComments[$DiscussionID]);
  186. Gdn::UserModel()->SaveAttribute($Session->UserID, 'CheckedComments', $CheckedComments);
  187. }
  188. Redirect(GetIncomingValue('Target', '/discussions'));
  189. }
  190. /**
  191. * Remove all discussions checked for administration from the user's attributes.
  192. */
  193. public function ClearDiscussionSelections($TransientKey = '') {
  194. $Session = Gdn::Session();
  195. if ($Session->ValidateTransientKey($TransientKey))
  196. Gdn::UserModel()->SaveAttribute($Session->UserID, 'CheckedDiscussions', FALSE);
  197. Redirect(GetIncomingValue('Target', '/discussions'));
  198. }
  199. /**
  200. * Form to confirm that the administrator wants to delete the selected
  201. * comments (and has permission to do so).
  202. */
  203. public function ConfirmCommentDeletes($DiscussionID = '') {
  204. $Session = Gdn::Session();
  205. $this->Form = new Gdn_Form();
  206. $DiscussionModel = new DiscussionModel();
  207. $Discussion = $DiscussionModel->GetID($DiscussionID);
  208. if (!$Discussion)
  209. return;
  210. // Verify that the user has permission to perform the delete
  211. $this->Permission('Vanilla.Comment.Delete', TRUE, 'Category', $Discussion->CategoryID);
  212. $this->Title(T('Confirm'));
  213. $CheckedComments = Gdn::UserModel()->GetAttribute($Session->User->UserID, 'CheckedComments', array());
  214. if (!is_array($CheckedComments))
  215. $CheckedComments = array();
  216. $CommentIDs = array();
  217. $DiscussionIDs = array();
  218. foreach ($CheckedComments as $DiscD => $Comments) {
  219. foreach ($Comments as $Comment) {
  220. if (substr($Comment, 0, 11) == 'Discussion_')
  221. $DiscussionIDs[] = str_replace('Discussion_', '', $Comment);
  222. else if ($DiscID == $DiscussionID)
  223. $CommentIDs[] = str_replace('Comment_', '', $Comment);
  224. }
  225. }
  226. $CountCheckedComments = count($CommentIDs);
  227. $this->SetData('CountCheckedComments', $CountCheckedComments);
  228. if ($this->Form->AuthenticatedPostBack()) {
  229. // Delete the selected comments
  230. $CommentModel = new CommentModel();
  231. foreach ($CommentIDs as $CommentID) {
  232. $CommentModel->Delete($CommentID);
  233. }
  234. // Clear selections
  235. unset($CheckedComments[$DiscussionID]);
  236. Gdn::UserModel()->SaveAttribute($Session->UserID, 'CheckedComments', $CheckedComments);
  237. ModerationController::InformCheckSelections($this);
  238. $this->RedirectUrl = 'discussions';
  239. }
  240. $this->Render();
  241. }
  242. /**
  243. * Form to confirm that the administrator wants to delete the selected
  244. * discussions (and has permission to do so).
  245. */
  246. public function ConfirmDiscussionDeletes() {
  247. $Session = Gdn::Session();
  248. $this->Form = new Gdn_Form();
  249. $DiscussionModel = new DiscussionModel();
  250. // Verify that the user has permission to perform the deletes
  251. $this->Permission('Vanilla.Comment.Delete', TRUE, 'Category', 'any');
  252. $this->Title(T('Confirm'));
  253. $CheckedDiscussions = Gdn::UserModel()->GetAttribute($Session->User->UserID, 'CheckedDiscussions', array());
  254. if (!is_array($CheckedDiscussions))
  255. $CheckedDiscussions = array();
  256. $DiscussionIDs = $CheckedDiscussions;
  257. $CountCheckedDiscussions = count($DiscussionIDs);
  258. $this->SetData('CountCheckedDiscussions', $CountCheckedDiscussions);
  259. // Check permissions on each discussion to make sure the user has permission to delete them
  260. $AllowedDiscussions = array();
  261. $DiscussionData = $DiscussionModel->SQL->Select('DiscussionID, CategoryID')->From('Discussion')->WhereIn('DiscussionID', $DiscussionIDs)->Get();
  262. foreach ($DiscussionData->Result() as $Discussion) {
  263. if ($Session->CheckPermission('Vanilla.Discussions.Delete', TRUE, 'Category', $Discussion->CategoryID))
  264. $AllowedDiscussions[] = $Discussion->DiscussionID;
  265. }
  266. $this->SetData('CountAllowed', count($AllowedDiscussions));
  267. $CountNotAllowed = $CountCheckedDiscussions - count($AllowedDiscussions);
  268. $this->SetData('CountNotAllowed', $CountNotAllowed);
  269. if ($this->Form->AuthenticatedPostBack()) {
  270. // Delete the selected discussions (that the user has permission to delete).
  271. foreach ($AllowedDiscussions as $DiscussionID) {
  272. $DiscussionModel->Delete($DiscussionID);
  273. }
  274. // Clear selections
  275. Gdn::UserModel()->SaveAttribute($Session->UserID, 'CheckedDiscussions', FALSE);
  276. ModerationController::InformCheckedDiscussions($this);
  277. $this->RedirectUrl = 'discussions';
  278. }
  279. $this->Render();
  280. }
  281. }