PageRenderTime 25ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://github.com/Emaratilicious/Garden
PHP | 327 lines | 216 code | 40 blank | 71 comment | 47 complexity | 939434421b4728bb01a9aec041f9b776 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 empCHANTABILITY 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. if (empty($CheckIDs))
  58. $CheckIDs = array();
  59. $CheckIDs = (array)$CheckIDs;
  60. $CheckedComments = Gdn::UserModel()->GetAttribute($Session->User->UserID, 'CheckedComments', array());
  61. if (!is_array($CheckedComments))
  62. $CheckedComments = array();
  63. if (!array_key_exists($DiscussionID, $CheckedComments)) {
  64. $CheckedComments[$DiscussionID] = array();
  65. } else {
  66. // Were there checked comments in this discussion before the form was posted?
  67. $HadCheckedComments = count($CheckedComments[$DiscussionID]) > 0;
  68. }
  69. foreach ($CheckIDs as $Check) {
  70. if (GetValue('checked', $Check)) {
  71. if (!ArrayHasValue($CheckedComments, $Check['checkId']))
  72. $CheckedComments[$DiscussionID][] = $Check['checkId'];
  73. } else {
  74. RemoveValueFromArray($CheckedComments[$DiscussionID], $Check['checkId']);
  75. }
  76. }
  77. if (count($CheckedComments[$DiscussionID]) == 0)
  78. unset($CheckedComments[$DiscussionID]);
  79. Gdn::UserModel()->SaveAttribute($Session->User->UserID, 'CheckedComments', $CheckedComments);
  80. } else if ($Session->IsValid()) {
  81. // No form posted, just retrieve checked items for display
  82. $DiscussionID = property_exists($Sender, 'DiscussionID') ? $Sender->DiscussionID : 0;
  83. $CheckedComments = Gdn::UserModel()->GetAttribute($Session->User->UserID, 'CheckedComments', array());
  84. if (!is_array($CheckedComments))
  85. $CheckedComments = array();
  86. }
  87. // Retrieve some information about the checked items
  88. $CountDiscussions = count($CheckedComments);
  89. $CountComments = 0;
  90. foreach ($CheckedComments as $DiscID => $Comments) {
  91. if ($DiscID == $DiscussionID)
  92. $CountComments += count($Comments); // Sum of comments in this discussion
  93. }
  94. if ($CountComments > 0) {
  95. $SelectionMessage = Wrap(sprintf(
  96. 'You have selected %1$s in this discussion.',
  97. Plural($CountComments, '%s comment', '%s comments')
  98. ), 'div');
  99. $ActionMessage = T('Take Action:');
  100. // Can the user delete the comment?
  101. $DiscussionModel = new DiscussionModel();
  102. $Discussion = $DiscussionModel->GetID($DiscussionID);
  103. if ($Session->CheckPermission('Vanilla.Comments.Delete', TRUE, 'Category', $Discussion->CategoryID))
  104. $ActionMessage .= ' '.Anchor(T('Delete'), 'vanilla/moderation/confirmcommentdeletes/'.$DiscussionID, 'Delete Popup');
  105. $Sender->EventArguments['SelectionMessage'] = &$SelectionMessage;
  106. $Sender->EventArguments['ActionMessage'] = &$ActionMessage;
  107. $Sender->EventArguments['Discussion'] = $Discussion;
  108. $Sender->FireEvent('BeforeCheckComments');
  109. $ActionMessage .= ' '.Anchor(T('Cancel'), 'vanilla/moderation/clearcommentselections/'.$DiscussionID.'/{TransientKey}/?Target={SelfUrl}', 'CancelAction');
  110. $Sender->InformMessage(
  111. $SelectionMessage
  112. .Wrap($ActionMessage, 'div', array('class' => 'Actions')),
  113. array(
  114. 'CssClass' => 'NoDismiss',
  115. 'id' => 'CheckSummary'
  116. )
  117. );
  118. } else if ($HadCheckedComments) {
  119. // Remove the message completely if there were previously checked comments in this discussion, but none now
  120. $Sender->InformMessage('', array('id' => 'CheckSummary'));
  121. }
  122. }
  123. /**
  124. * Looks at the user's attributes and form postback to see if any discussions
  125. * have been checked for administration, and if so, adds an inform message to
  126. * $Sender to take action.
  127. */
  128. public static function InformCheckedDiscussions($Sender) {
  129. $Session = Gdn::Session();
  130. $HadCheckedDiscussions = FALSE;
  131. $TransientKey = GetValue('TransientKey', $_POST);
  132. if ($Session->IsValid() && $Session->ValidateTransientKey($TransientKey)) {
  133. // Form was posted, so accept changes to checked items.
  134. $CheckIDs = GetValue('CheckIDs', $_POST);
  135. if (empty($CheckIDs))
  136. $CheckIDs = array();
  137. $CheckIDs = (array)$CheckIDs;
  138. $CheckedDiscussions = Gdn::UserModel()->GetAttribute($Session->User->UserID, 'CheckedDiscussions', array());
  139. if (!is_array($CheckedDiscussions))
  140. $CheckedDiscussions = array();
  141. // Were there checked discussions before the form was posted?
  142. $HadCheckedDiscussions = count($CheckedDiscussions) > 0;
  143. foreach ($CheckIDs as $Check) {
  144. if (GetValue('checked', $Check)) {
  145. if (!ArrayHasValue($CheckedDiscussions, $Check['checkId']))
  146. $CheckedDiscussions[] = $Check['checkId'];
  147. } else {
  148. RemoveValueFromArray($CheckedDiscussions, $Check['checkId']);
  149. }
  150. }
  151. Gdn::UserModel()->SaveAttribute($Session->User->UserID, 'CheckedDiscussions', $CheckedDiscussions);
  152. } else if ($Session->IsValid()) {
  153. // No form posted, just retrieve checked items for display
  154. $CheckedDiscussions = Gdn::UserModel()->GetAttribute($Session->User->UserID, 'CheckedDiscussions', array());
  155. if (!is_array($CheckedDiscussions))
  156. $CheckedDiscussions = array();
  157. }
  158. // Retrieve some information about the checked items
  159. $CountDiscussions = count($CheckedDiscussions);
  160. if ($CountDiscussions > 0) {
  161. $SelectionMessage = Wrap(sprintf(
  162. 'You have selected %1$s.',
  163. Plural($CountDiscussions, '%s discussion', '%s discussions')
  164. ), 'div');
  165. $ActionMessage = T('Take Action:');
  166. $ActionMessage .= ' '.Anchor(T('Delete'), 'vanilla/moderation/confirmdiscussiondeletes/', 'Delete Popup');
  167. $Sender->EventArguments['SelectionMessage'] = &$SelectionMessage;
  168. $Sender->EventArguments['ActionMessage'] = &$ActionMessage;
  169. $Sender->FireEvent('BeforeCheckDiscussions');
  170. $ActionMessage .= ' '.Anchor(T('Cancel'), 'vanilla/moderation/cleardiscussionselections/{TransientKey}/?Target={SelfUrl}', 'CancelAction');
  171. $Sender->InformMessage(
  172. $SelectionMessage
  173. .Wrap($ActionMessage, 'div', array('class' => 'Actions')),
  174. array(
  175. 'CssClass' => 'NoDismiss',
  176. 'id' => 'CheckSummary'
  177. )
  178. );
  179. } else if ($HadCheckedDiscussions) {
  180. // Remove the message completely if there were previously checked comments in this discussion, but none now
  181. $Sender->InformMessage('', array('id' => 'CheckSummary'));
  182. }
  183. }
  184. /**
  185. * Remove all comments checked for administration from the user's attributes.
  186. */
  187. public function ClearCommentSelections($DiscussionID = '', $TransientKey = '') {
  188. $Session = Gdn::Session();
  189. if ($Session->ValidateTransientKey($TransientKey)) {
  190. $CheckedComments = Gdn::UserModel()->GetAttribute($Session->User->UserID, 'CheckedComments', array());
  191. unset($CheckedComments[$DiscussionID]);
  192. Gdn::UserModel()->SaveAttribute($Session->UserID, 'CheckedComments', $CheckedComments);
  193. }
  194. Redirect(GetIncomingValue('Target', '/discussions'));
  195. }
  196. /**
  197. * Remove all discussions checked for administration from the user's attributes.
  198. */
  199. public function ClearDiscussionSelections($TransientKey = '') {
  200. $Session = Gdn::Session();
  201. if ($Session->ValidateTransientKey($TransientKey))
  202. Gdn::UserModel()->SaveAttribute($Session->UserID, 'CheckedDiscussions', FALSE);
  203. Redirect(GetIncomingValue('Target', '/discussions'));
  204. }
  205. /**
  206. * Form to confirm that the administrator wants to delete the selected
  207. * comments (and has permission to do so).
  208. */
  209. public function ConfirmCommentDeletes($DiscussionID = '') {
  210. $Session = Gdn::Session();
  211. $this->Form = new Gdn_Form();
  212. $DiscussionModel = new DiscussionModel();
  213. $Discussion = $DiscussionModel->GetID($DiscussionID);
  214. if (!$Discussion)
  215. return;
  216. // Verify that the user has permission to perform the delete
  217. $this->Permission('Vanilla.Comment.Delete', TRUE, 'Category', $Discussion->CategoryID);
  218. $this->Title(T('Confirm'));
  219. $CheckedComments = Gdn::UserModel()->GetAttribute($Session->User->UserID, 'CheckedComments', array());
  220. if (!is_array($CheckedComments))
  221. $CheckedComments = array();
  222. $CommentIDs = array();
  223. $DiscussionIDs = array();
  224. foreach ($CheckedComments as $DiscID => $Comments) {
  225. foreach ($Comments as $Comment) {
  226. if (substr($Comment, 0, 11) == 'Discussion_')
  227. $DiscussionIDs[] = str_replace('Discussion_', '', $Comment);
  228. else if ($DiscID == $DiscussionID)
  229. $CommentIDs[] = str_replace('Comment_', '', $Comment);
  230. }
  231. }
  232. $CountCheckedComments = count($CommentIDs);
  233. $this->SetData('CountCheckedComments', $CountCheckedComments);
  234. if ($this->Form->AuthenticatedPostBack()) {
  235. // Delete the selected comments
  236. $CommentModel = new CommentModel();
  237. foreach ($CommentIDs as $CommentID) {
  238. $CommentModel->Delete($CommentID);
  239. }
  240. // Clear selections
  241. unset($CheckedComments[$DiscussionID]);
  242. Gdn::UserModel()->SaveAttribute($Session->UserID, 'CheckedComments', $CheckedComments);
  243. ModerationController::InformCheckedComments($this);
  244. $this->RedirectUrl = 'discussions';
  245. }
  246. $this->Render();
  247. }
  248. /**
  249. * Form to confirm that the administrator wants to delete the selected
  250. * discussions (and has permission to do so).
  251. */
  252. public function ConfirmDiscussionDeletes() {
  253. $Session = Gdn::Session();
  254. $this->Form = new Gdn_Form();
  255. $DiscussionModel = new DiscussionModel();
  256. // Verify that the user has permission to perform the deletes
  257. $this->Permission('Vanilla.Comment.Delete', TRUE, 'Category', 'any');
  258. $this->Title(T('Confirm'));
  259. $CheckedDiscussions = Gdn::UserModel()->GetAttribute($Session->User->UserID, 'CheckedDiscussions', array());
  260. if (!is_array($CheckedDiscussions))
  261. $CheckedDiscussions = array();
  262. $DiscussionIDs = $CheckedDiscussions;
  263. $CountCheckedDiscussions = count($DiscussionIDs);
  264. $this->SetData('CountCheckedDiscussions', $CountCheckedDiscussions);
  265. // Check permissions on each discussion to make sure the user has permission to delete them
  266. $AllowedDiscussions = array();
  267. $DiscussionData = $DiscussionModel->SQL->Select('DiscussionID, CategoryID')->From('Discussion')->WhereIn('DiscussionID', $DiscussionIDs)->Get();
  268. foreach ($DiscussionData->Result() as $Discussion) {
  269. if ($Session->CheckPermission('Vanilla.Discussions.Delete', TRUE, 'Category', $Discussion->CategoryID))
  270. $AllowedDiscussions[] = $Discussion->DiscussionID;
  271. }
  272. $this->SetData('CountAllowed', count($AllowedDiscussions));
  273. $CountNotAllowed = $CountCheckedDiscussions - count($AllowedDiscussions);
  274. $this->SetData('CountNotAllowed', $CountNotAllowed);
  275. if ($this->Form->AuthenticatedPostBack()) {
  276. // Delete the selected discussions (that the user has permission to delete).
  277. foreach ($AllowedDiscussions as $DiscussionID) {
  278. $DiscussionModel->Delete($DiscussionID);
  279. }
  280. // Clear selections
  281. Gdn::UserModel()->SaveAttribute($Session->UserID, 'CheckedDiscussions', FALSE);
  282. ModerationController::InformCheckedDiscussions($this);
  283. $this->RedirectUrl = 'discussions';
  284. }
  285. $this->Render();
  286. }
  287. }