PageRenderTime 62ms CodeModel.GetById 38ms RepoModel.GetById 1ms app.codeStats 0ms

/Model/Post.php

https://github.com/milesj/forum
PHP | 397 lines | 216 code | 45 blank | 136 comment | 12 complexity | 209a9cb6c71f91994535e7e1a33ce336 MD5 | raw file
  1. <?php
  2. /**
  3. * @copyright 2006-2013, Miles Johnson - http://milesj.me
  4. * @license https://github.com/milesj/admin/blob/master/license.md
  5. * @link http://milesj.me/code/cakephp/admin
  6. */
  7. App::uses('ForumAppModel', 'Forum.Model');
  8. /**
  9. * @property Forum $Forum
  10. * @property Topic $Topic
  11. * @property User $User
  12. * @property PostRating $PostRating
  13. */
  14. class Post extends ForumAppModel {
  15. /**
  16. * Belongs to.
  17. *
  18. * @type array
  19. */
  20. public $belongsTo = array(
  21. 'Forum' => array(
  22. 'className' => 'Forum.Forum',
  23. 'counterCache' => true
  24. ),
  25. 'Topic' => array(
  26. 'className' => 'Forum.Topic',
  27. 'counterCache' => true
  28. ),
  29. 'User' => array(
  30. 'className' => USER_MODEL,
  31. 'counterCache' => true
  32. )
  33. );
  34. /**
  35. * Has many.
  36. *
  37. * @type array
  38. */
  39. public $hasMany = array(
  40. 'PostRating' => array(
  41. 'className' => 'Forum.PostRating',
  42. 'dependent' => true,
  43. 'limit' => 25
  44. )
  45. );
  46. /**
  47. * Validation.
  48. *
  49. * @type array
  50. */
  51. public $validations = array(
  52. 'default' => array(
  53. 'forum_id' => array(
  54. 'rule' => 'notEmpty'
  55. ),
  56. 'topic_id' => array(
  57. 'rule' => 'notEmpty'
  58. ),
  59. 'user_id' => array(
  60. 'rule' => 'notEmpty'
  61. ),
  62. 'content' => array(
  63. 'rule' => 'notEmpty'
  64. )
  65. )
  66. );
  67. /**
  68. * Admin settings.
  69. *
  70. * @type array
  71. */
  72. public $admin = array(
  73. 'iconClass' => 'icon-comments',
  74. 'editorFields' => array('content')
  75. );
  76. /**
  77. * Validate and add a post.
  78. *
  79. * @param array $data
  80. * @return bool|int
  81. */
  82. public function addPost($data) {
  83. $this->set($data);
  84. if ($this->validates()) {
  85. $settings = Configure::read('Forum.settings');
  86. $isAdmin = $this->Session->read('Acl.isAdmin');
  87. if (($secondsLeft = $this->checkFlooding($settings['postFloodInterval'])) > 0 && !$isAdmin) {
  88. return $this->invalid('content', 'You must wait %s more second(s) till you can post a reply', $secondsLeft);
  89. } else if ($this->checkHourly($settings['postsPerHour']) && !$isAdmin) {
  90. return $this->invalid('content', 'You are only allowed to post %s time(s) per hour', $settings['postsPerHour']);
  91. } else {
  92. $this->create();
  93. $this->save($data, false, array('topic_id', 'forum_id', 'user_id', 'userIP', 'content'));
  94. $data['post_id'] = $this->id;
  95. $this->Topic->update($data['topic_id'], array(
  96. 'lastPost_id' => $data['post_id'],
  97. 'lastUser_id' => $data['user_id'],
  98. ));
  99. $this->Topic->Forum->chainUpdate($data['forum_id'], array(
  100. 'lastTopic_id' => $data['topic_id'],
  101. 'lastPost_id' => $data['post_id'],
  102. 'lastUser_id' => $data['user_id']
  103. ));
  104. return $data['post_id'];
  105. }
  106. }
  107. return false;
  108. }
  109. /**
  110. * Save the first post with a topic.
  111. *
  112. * @param array $data
  113. * @return int
  114. */
  115. public function addFirstPost($data) {
  116. $this->create();
  117. $this->save(array(
  118. 'topic_id' => $data['topic_id'],
  119. 'forum_id' => $data['forum_id'],
  120. 'user_id' => $data['user_id'],
  121. 'userIP' => $data['userIP'],
  122. 'content' => $data['content']
  123. ), false);
  124. return $this->id;
  125. }
  126. /**
  127. * Check the posting flood interval.
  128. *
  129. * @param int $interval
  130. * @return bool
  131. */
  132. public function checkFlooding($interval) {
  133. if ($posts = $this->Session->read('Forum.posts')) {
  134. $timeLeft = time() - array_pop($posts);
  135. if ($timeLeft <= $interval) {
  136. return $interval - $timeLeft;
  137. }
  138. }
  139. return false;
  140. }
  141. /**
  142. * Check the hourly posting.
  143. *
  144. * @param int $max
  145. * @return bool
  146. */
  147. public function checkHourly($max) {
  148. $pastHour = strtotime('-1 hour');
  149. if ($posts = $this->Session->read('Forum.posts')) {
  150. $count = 0;
  151. foreach ($posts as $time) {
  152. if ($time >= $pastHour) {
  153. ++$count;
  154. }
  155. }
  156. if ($count >= $max) {
  157. return true;
  158. }
  159. }
  160. return false;
  161. }
  162. /**
  163. * Return a post based on ID.
  164. *
  165. * @param int $id
  166. * @return array
  167. */
  168. public function getById($id) {
  169. return $this->find('first', array(
  170. 'conditions' => array('Post.id' => $id),
  171. 'contain' => array(
  172. 'Topic', 'User',
  173. 'Forum' => array('Parent')
  174. ),
  175. 'cache' => array(__METHOD__, $id)
  176. ));
  177. }
  178. /**
  179. * Return a list of IDs within a topic.
  180. *
  181. * @param int $topic_id
  182. * @return array
  183. */
  184. public function getIdsForTopic($topic_id) {
  185. return $this->find('list', array(
  186. 'conditions' => array('Post.topic_id' => $topic_id),
  187. 'order' => array('Post.id' => 'ASC')
  188. ));
  189. }
  190. /**
  191. * Return the latest posts by a user.
  192. *
  193. * @param int $user_id
  194. * @param int $limit
  195. * @return array
  196. */
  197. public function getLatestByUser($user_id, $limit = 5) {
  198. return $this->find('all', array(
  199. 'conditions' => array('Post.user_id' => $user_id),
  200. 'order' => array('Post.created' => 'DESC'),
  201. 'limit' => $limit,
  202. 'contain' => array(
  203. 'Topic' => array('User')
  204. )
  205. ));
  206. }
  207. /**
  208. * Return the latest posts by a user, grouped by the topic ID.
  209. *
  210. * @param int $user_id
  211. * @param int $limit
  212. * @return array
  213. */
  214. public function getGroupedLatestByUser($user_id, $limit = 10) {
  215. return $this->find('all', array(
  216. 'conditions' => array('Post.user_id' => $user_id),
  217. 'order' => array('Post.created' => 'DESC'),
  218. 'group' => array('Post.topic_id'),
  219. 'limit' => $limit,
  220. 'contain' => array(
  221. 'Topic' => array('LastUser', 'LastPost', 'User')
  222. ),
  223. 'cache' => array(__METHOD__, $user_id, $limit),
  224. 'cacheExpires' => '+5 minutes'
  225. ));
  226. }
  227. /**
  228. * Get popular scoring posts by a user.
  229. *
  230. * @param int $user_id
  231. * @param int $limit
  232. * @return array
  233. */
  234. public function getPopularByUser($user_id, $limit = 10) {
  235. return $this->find('all', array(
  236. 'conditions' => array('Post.user_id' => $user_id),
  237. 'order' => array('Post.score' => 'DESC'),
  238. 'limit' => $limit,
  239. 'cache' => array(__METHOD__, $user_id, $limit),
  240. 'cacheExpires' => '+5 minutes'
  241. ));
  242. }
  243. /**
  244. * Get popular scoring posts in a topic.
  245. *
  246. * @param int $topic_id
  247. * @param int $limit
  248. * @return array
  249. */
  250. public function getPopularInTopic($topic_id, $limit = 10) {
  251. return $this->find('all', array(
  252. 'conditions' => array('Post.topic_id' => $topic_id),
  253. 'order' => array('Post.score' => 'DESC'),
  254. 'limit' => $limit,
  255. 'contain' => array('User'),
  256. 'cache' => array(__METHOD__, $topic_id, $limit),
  257. 'cacheExpires' => '+5 minutes'
  258. ));
  259. }
  260. /**
  261. * Return a post for quoting.
  262. *
  263. * @param int $id
  264. * @return array
  265. */
  266. public function getQuote($id) {
  267. return $this->find('first', array(
  268. 'conditions' => array('Post.id' => $id),
  269. 'contain' => array('User')
  270. ));
  271. }
  272. /**
  273. * Return the latest posts in a topic.
  274. *
  275. * @param int $topic_id
  276. * @param int $limit
  277. * @return array
  278. */
  279. public function getTopicReview($topic_id, $limit = 10) {
  280. return $this->find('all', array(
  281. 'conditions' => array('Post.topic_id' => $topic_id),
  282. 'contain' => array('User'),
  283. 'order' => array('Post.created' => 'DESC'),
  284. 'limit' => $limit
  285. ));
  286. }
  287. /**
  288. * Increase the down ratings.
  289. *
  290. * @param int $id
  291. * @return bool
  292. */
  293. public function rateDown($id) {
  294. $down = (int) Configure::read('Forum.settings.rateDownPoints');
  295. return $this->updateAll(
  296. array('Post.down' => 'Post.down + ' . $down, 'Post.score' => 'Post.score - ' . $down),
  297. array('Post.id' => $id)
  298. );
  299. }
  300. /**
  301. * Increase the up ratings.
  302. *
  303. * @param int $id
  304. * @return bool
  305. */
  306. public function rateUp($id) {
  307. $up = (int) Configure::read('Forum.settings.rateUpPoints');
  308. return $this->updateAll(
  309. array('Post.up' => 'Post.up + ' . $up, 'Post.score' => 'Post.score + ' . $up),
  310. array('Post.id' => $id)
  311. );
  312. }
  313. /**
  314. * Move all posts to a new forum.
  315. *
  316. * @param int $start_id
  317. * @param int $moved_id
  318. * @return bool
  319. */
  320. public function moveAll($start_id, $moved_id) {
  321. return $this->updateAll(
  322. array('Post.forum_id' => $moved_id),
  323. array('Post.forum_id' => $start_id)
  324. );
  325. }
  326. /**
  327. * Parse the HTML version.
  328. *
  329. * @param array $options
  330. * @return bool
  331. */
  332. public function beforeSave($options = array()) {
  333. return $this->validateDecoda('Post');
  334. }
  335. /**
  336. * Null associations.
  337. */
  338. public function afterDelete() {
  339. $this->Forum->updateAll(
  340. array('Forum.lastPost_id' => null),
  341. array('Forum.lastPost_id' => $this->id)
  342. );
  343. $this->Topic->updateAll(
  344. array('Topic.firstPost_id' => null),
  345. array('Topic.firstPost_id' => $this->id)
  346. );
  347. $this->Topic->updateAll(
  348. array('Topic.lastPost_id' => null),
  349. array('Topic.lastPost_id' => $this->id)
  350. );
  351. }
  352. }