/extensions/WikiForum/WikiForumClass.php

https://github.com/ChuguluGames/mediawiki-svn · PHP · 1745 lines · 1454 code · 165 blank · 126 comment · 248 complexity · 9dcdbd906abf82ddb4268f00f3a9f999 MD5 · raw file

  1. <?php
  2. /**
  3. * Main class for WikiForum extension, contains all the logic to manage forums,
  4. * categories, individual topics, etc.
  5. *
  6. * @file
  7. * @ingroup Extensions
  8. */
  9. class WikiForumClass {
  10. private $result = true; // boolean; if true, everything went well
  11. private $errorTitle = ''; // error page title
  12. private $errorIcon = ''; // error icon name
  13. private $errorMessage = ''; // error message
  14. /**
  15. * Find a thread's ID number when you know the title.
  16. *
  17. * @param $titleText String: thread title
  18. * @return Integer: thread ID number
  19. */
  20. public static function findThreadIDByTitle( $titleText ) {
  21. // Titles are stored with spaces in the DB but the query will otherwise
  22. // use friggin' underscores...
  23. $titleText = str_replace( '_', ' ', $titleText );
  24. $dbr = wfGetDB( DB_SLAVE );
  25. $res = $dbr->selectRow(
  26. 'wikiforum_threads',
  27. 'wft_thread',
  28. // Database::makeList calls Database::addQuotes so that we don't
  29. // need to do it here yet this still is safe
  30. array( 'wft_thread_name' => $titleText ),
  31. __METHOD__
  32. );
  33. if ( $res ) {
  34. $threadId = $res->wft_thread;
  35. } else {
  36. // Something went wrong...
  37. $threadId = 0;
  38. }
  39. return $threadId;
  40. }
  41. /**
  42. * Deletes the reply with ID = $replyId.
  43. *
  44. * @param $replyId Integer: ID number of the reply to delete
  45. * @return Boolean: was reply deletion successful or not?
  46. */
  47. function deleteReply( $replyId ) {
  48. global $wgUser;
  49. $dbr = wfGetDB( DB_SLAVE );
  50. $reply = $dbr->fetchObject( $dbr->select(
  51. 'wikiforum_replies',
  52. array( 'wfr_reply_id', 'wfr_user' ),
  53. array( 'wfr_deleted' => 0, 'wfr_reply_id' => intval( $replyId ) ),
  54. __METHOD__
  55. ) );
  56. if (
  57. $reply->wfr_reply_id > 0 && $wgUser->getId() > 0 &&
  58. (
  59. $wgUser->getId() == $reply->wfr_user ||
  60. $wgUser->isAllowed( 'wikiforum-moderator' )
  61. ) &&
  62. !wfReadOnly()
  63. )
  64. {
  65. $dbw = wfGetDB( DB_MASTER );
  66. $result = $dbw->update(
  67. 'wikiforum_replies',
  68. array(
  69. 'wfr_deleted' => wfTimestampNow(),
  70. 'wfr_deleted_user' => $wgUser->getId(),
  71. ),
  72. array(
  73. 'wfr_reply_id' => $reply->wfr_reply_id
  74. ),
  75. __METHOD__
  76. );
  77. } else {
  78. $result = false;
  79. }
  80. if ( $result == false ) {
  81. $this->errorTitle = wfMsg( 'wikiforum-error-delete' );
  82. $this->errorMessage = wfMsg( 'wikiforum-error-general' );
  83. }
  84. return $result;
  85. }
  86. /**
  87. * Deletes the thread with ID = $threadId.
  88. *
  89. * @param $threadId Integer: ID number of the thread to delete
  90. * @return Boolean: was thread deletion successful or not?
  91. */
  92. function deleteThread( $threadId ) {
  93. global $wgUser;
  94. $dbr = wfGetDB( DB_SLAVE );
  95. $thread = $dbr->fetchObject( $dbr->select(
  96. 'wikiforum_threads',
  97. array( 'wft_thread', 'wft_user', 'wft_forum' ),
  98. array( 'wft_deleted' => 0, 'wft_thread' => intval( $threadId ) ),
  99. __METHOD__
  100. ) );
  101. if (
  102. $thread->wft_thread > 0 && $wgUser->getId() > 0 &&
  103. ( $wgUser->getId() == $thread->wft_user || $wgUser->isAllowed( 'wikiforum-moderator' ) ) &&
  104. !wfReadOnly()
  105. )
  106. {
  107. $dbw = wfGetDB( DB_MASTER );
  108. $result = $dbw->update(
  109. 'wikiforum_threads',
  110. array(
  111. 'wft_deleted' => wfTimestampNow(),
  112. 'wft_deleted_user' => $wgUser->getId(),
  113. ),
  114. array(
  115. 'wft_thread' => $thread->wft_thread
  116. ),
  117. __METHOD__
  118. );
  119. // Update threads/replies counters
  120. $replyCount = $dbw->selectField(
  121. 'wikiforum_threads',
  122. 'wft_reply_count',
  123. array( 'wft_thread' => intval( $thread->wft_thread ) ),
  124. __METHOD__
  125. );
  126. // When the thread we're about to delete is deleted, we also need
  127. // to update the information about the latest post & its author
  128. $new = $dbw->select(
  129. 'wikiforum_threads',
  130. array(
  131. 'wft_last_post_user', 'wft_last_post_timestamp',
  132. ),
  133. array(
  134. 'wft_forum' => intval( $thread->wft_forum ),
  135. 'wft_deleted' => 0 // 0 means not deleted
  136. ),
  137. __METHOD__,
  138. array( 'LIMIT' => 1 )
  139. );
  140. $row = $dbw->fetchRow( $new );
  141. // Update the forum table so that the data shown on
  142. // Special:WikiForum is up to date
  143. $dbw->update(
  144. 'wikiforum_forums',
  145. array(
  146. "wff_reply_count = wff_reply_count - $replyCount",
  147. 'wff_thread_count = wff_thread_count - 1',
  148. 'wff_last_post_user' => intval( $row['wft_last_post_user'] ),
  149. 'wff_last_post_timestamp' => intval( $row['wft_last_post_timestamp'] )
  150. ),
  151. array(
  152. 'wff_forum' => intval( $thread->wft_forum )
  153. ),
  154. __METHOD__
  155. );
  156. } else {
  157. $result = false;
  158. }
  159. if ( $result == false ) {
  160. $this->errorTitle = wfMsg( 'wikiforum-error-delete' );
  161. $this->errorMessage = wfMsg( 'wikiforum-error-general' );
  162. }
  163. return $result;
  164. }
  165. /**
  166. * Deletes the category with ID = $categoryId.
  167. *
  168. * @param $categoryId Integer: ID number of the category to delete
  169. * @return Boolean: was category deletion successful or not?
  170. */
  171. function deleteCategory( $categoryId ) {
  172. global $wgUser;
  173. if (
  174. $wgUser->isAllowed( 'wikiforum-admin' ) &&
  175. !wfReadOnly()
  176. )
  177. {
  178. $dbw = wfGetDB( DB_MASTER );
  179. $result = $dbw->update(
  180. 'wikiforum_category',
  181. array(
  182. 'wfc_deleted' => wfTimestampNow(),
  183. 'wfc_deleted_user' => $wgUser->getId(),
  184. ),
  185. array(
  186. 'wfc_category' => intval( $categoryId )
  187. ),
  188. __METHOD__
  189. );
  190. } else {
  191. $result = false;
  192. }
  193. if ( $result == false ) {
  194. $this->errorTitle = wfMsg( 'wikiforum-error-delete' );
  195. $this->errorMessage = wfMsg( 'wikiforum-error-general' );
  196. }
  197. return $result;
  198. }
  199. /**
  200. * Deletes the forum with ID = $forumId.
  201. *
  202. * @param $forumId Integer: ID number of the forum to delete
  203. * @return Boolean: was forum deletion successful or not?
  204. */
  205. function deleteForum( $forumId ) {
  206. global $wgUser;
  207. if (
  208. $wgUser->isAllowed( 'wikiforum-admin' ) &&
  209. !wfReadOnly()
  210. )
  211. {
  212. $dbw = wfGetDB( DB_MASTER );
  213. $result = $dbw->update(
  214. 'wikiforum_forums',
  215. array(
  216. 'wff_deleted' => wfTimestampNow(),
  217. 'wff_deleted_user' => $wgUser->getId(),
  218. ),
  219. array(
  220. 'wff_forum' => intval( $forumId )
  221. ),
  222. __METHOD__
  223. );
  224. } else {
  225. $result = false;
  226. }
  227. if ( $result == false ) {
  228. $this->errorTitle = wfMsg( 'wikiforum-error-delete' );
  229. $this->errorMessage = wfMsg( 'wikiforum-error-general' );
  230. }
  231. return $result;
  232. }
  233. /**
  234. * Reopens the thread with ID = $threadId.
  235. *
  236. * @param $threadId Integer: ID number of the thread to reopen
  237. * @return Boolean: was thread reopening successful or not?
  238. */
  239. function reopenThread( $threadId ) {
  240. global $wgUser;
  241. $dbr = wfGetDB( DB_SLAVE );
  242. $thread = $dbr->selectRow(
  243. 'wikiforum_threads',
  244. 'wft_thread',
  245. array(
  246. 'wft_closed > 0',
  247. 'wft_deleted' => 0,
  248. 'wft_thread' => intval( $threadId )
  249. ),
  250. __METHOD__
  251. );
  252. if (
  253. $thread->wft_thread > 0 &&
  254. $wgUser->isAllowed( 'wikiforum-moderator' ) &&
  255. !wfReadOnly()
  256. )
  257. {
  258. $dbw = wfGetDB( DB_MASTER );
  259. $result = $dbw->update(
  260. 'wikiforum_threads',
  261. array(
  262. 'wft_closed' => 0,
  263. 'wft_closed_user' => 0
  264. ),
  265. array( 'wft_thread' => $thread->wft_thread ),
  266. __METHOD__
  267. );
  268. } else {
  269. $result = false;
  270. }
  271. if ( $result == false ) {
  272. $this->errorTitle = wfMsg( 'wikiforum-error-thread-reopen' );
  273. $this->errorMessage = wfMsg( 'wikiforum-error-general' );
  274. }
  275. return $result;
  276. }
  277. /**
  278. * Closes the thread with ID = $threadId.
  279. *
  280. * @param $threadId Integer: ID number of the thread to close
  281. * @return Boolean: was thread closed successfully or not?
  282. */
  283. function closeThread( $threadId ) {
  284. global $wgUser;
  285. $dbr = wfGetDB( DB_SLAVE );
  286. $thread = $dbr->selectRow(
  287. 'wikiforum_threads',
  288. 'wft_thread',
  289. array(
  290. 'wft_closed' => 0,
  291. 'wft_deleted' => 0,
  292. 'wft_thread' => intval( $threadId )
  293. ),
  294. __METHOD__
  295. );
  296. if (
  297. $thread->wft_thread > 0 &&
  298. $wgUser->isAllowed( 'wikiforum-moderator' ) &&
  299. !wfReadOnly()
  300. )
  301. {
  302. $dbw = wfGetDB( DB_MASTER );
  303. $result = $dbw->update(
  304. 'wikiforum_threads',
  305. array(
  306. 'wft_closed' => wfTimestampNow(),
  307. 'wft_closed_user' => $wgUser->getId()
  308. ),
  309. array( 'wft_thread' => intval( $thread->wft_thread ) ),
  310. __METHOD__
  311. );
  312. } else {
  313. $result = false;
  314. }
  315. if ( $result == false ) {
  316. $this->errorTitle = wfMsg( 'wikiforum-error-thread-close' );
  317. $this->errorMessage = wfMsg( 'wikiforum-error-general' );
  318. }
  319. return $result;
  320. }
  321. /**
  322. * Makes the thread with ID = $threadId sticky.
  323. *
  324. * @param $threadId Integer: ID number of the thread to mark as sticky
  325. * @param $value
  326. * @return Boolean: was thread deletion successful or not?
  327. */
  328. function makeSticky( $threadId, $value ) {
  329. global $wgUser;
  330. $dbr = wfGetDB( DB_SLAVE );
  331. $thread = $dbr->fetchObject( $dbr->select(
  332. 'wikiforum_threads',
  333. 'wft_thread',
  334. array( 'wft_deleted' => 0, 'wft_thread' => $threadId ),
  335. __METHOD__
  336. ) );
  337. if (
  338. $thread->wft_thread > 0 &&
  339. $wgUser->isAllowed( 'wikiforum-admin' ) &&
  340. !wfReadOnly()
  341. )
  342. {
  343. if ( $value == false ) {
  344. $value = 0;
  345. }
  346. $dbw = wfGetDB( DB_MASTER );
  347. $result = $dbw->update(
  348. 'wikiforum_threads',
  349. array( 'wft_sticky' => $value ),
  350. array( 'wft_thread' => $thread->wft_thread ),
  351. __METHOD__
  352. );
  353. } else {
  354. $result = false;
  355. }
  356. if ( $result == false ) {
  357. $this->errorTitle = wfMsg( 'wikiforum-error-sticky' );
  358. $this->errorMessage = wfMsg( 'wikiforum-error-general' );
  359. }
  360. return $result;
  361. }
  362. function pasteThread( $threadId, $forumId ) {
  363. global $wgUser;
  364. $dbr = wfGetDB( DB_SLAVE );
  365. $thread = $dbr->select(
  366. 'wikiforum_threads',
  367. 'wft_thread',
  368. array( 'wft_deleted' => 0, 'wft_thread' => intval( $threadId ) ),
  369. __METHOD__
  370. );
  371. $forum = $dbr->select(
  372. 'wikiforum_forums',
  373. 'wff_forum',
  374. array( 'wff_deleted' => 0, 'wff_forum' => intval( $forumId ) ),
  375. __METHOD__
  376. );
  377. if ( $thread->wft_thread > 0 && $forum->wff_forum > 0 && $wgUser->isAllowed( 'wikiforum-moderator' ) ) {
  378. if ( $thread->wft_forum != $forum->wff_forum ) {
  379. $dbw = wfGetDB( DB_MASTER );
  380. $result = $dbw->update(
  381. 'wikiforum_threads',
  382. array( 'wft_forum' => $forum->wff_forum ),
  383. array( 'wft_thread' => $thread->wft_thread ),
  384. __METHOD__
  385. );
  386. } else {
  387. $result = true;
  388. }
  389. } else {
  390. $result = false;
  391. }
  392. if ( $result == false ) {
  393. $this->errorTitle = wfMsg( 'wikiforum-error-move-thread' );
  394. $this->errorMessage = wfMsg( 'wikiforum-error-general' );
  395. }
  396. return $result;
  397. }
  398. function editThread( $threadId, $title, $text ) {
  399. global $wgUser;
  400. if (
  401. $text && $title && strlen( $text ) > 1 &&
  402. strlen( $title ) > 1
  403. )
  404. {
  405. $dbr = wfGetDB( DB_SLAVE );
  406. $thread = $dbr->fetchObject( $dbr->select(
  407. 'wikiforum_threads',
  408. array( 'wft_thread', 'wft_thread_name', 'wft_text', 'wft_user' ),
  409. array( 'wft_deleted' => 0, 'wft_thread' => $threadId ),
  410. __METHOD__
  411. ) );
  412. if ( $thread->wft_thread > 0 ) {
  413. if (
  414. $thread->wft_thread_name != $title ||
  415. $thread->wft_text != $text
  416. )
  417. {
  418. if (
  419. $wgUser->getId() > 0 &&
  420. (
  421. $wgUser->getId() == $thread->wft_user ||
  422. $wgUser->isAllowed( 'wikiforum-moderator' )
  423. ) &&
  424. !wfReadOnly()
  425. )
  426. {
  427. $dbw = wfGetDB( DB_MASTER );
  428. $result = $dbw->update(
  429. 'wikiforum_threads',
  430. array(
  431. 'wft_thread_name' => $title,
  432. 'wft_text' => $text,
  433. 'wft_edit_timestamp' => wfTimestampNow(),
  434. 'wft_edit_user' => $wgUser->getId()
  435. ),
  436. array( 'wft_thread' => $thread->wft_thread ),
  437. __METHOD__
  438. );
  439. } else {
  440. $this->errorMessage = wfMsg( 'wikiforum-error-no-rights' );
  441. $result = false;
  442. }
  443. } else {
  444. $result = true; // no changes
  445. }
  446. } else {
  447. $this->errorMessage = wfMsg( 'wikiforum-error-not-found' );
  448. $result = false;
  449. }
  450. if ( $result == false ) {
  451. $this->errorTitle = wfMsg( 'wikiforum-error-edit' );
  452. if ( $this->errorMessage == '' ) {
  453. $this->errorMessage = wfMsg( 'wikiforum-error-general' );
  454. }
  455. }
  456. } else {
  457. if (
  458. !$text && !$title ||
  459. strlen( $text ) == 0 && strlen( $title ) == 0
  460. )
  461. {
  462. $result = false;
  463. } else {
  464. $this->result = false;
  465. $result = false;
  466. }
  467. }
  468. return $result;
  469. }
  470. function addThread( $forumId, $title, $text ) {
  471. global $wgUser, $wgWikiForumAllowAnonymous;
  472. if ( $wgWikiForumAllowAnonymous || $wgUser->isLoggedIn() ) {
  473. if (
  474. $forumId > 0 && strlen( $text ) > 1 &&
  475. // @todo FIXME/CHECKME: use wfMsgForContent()?
  476. strlen( $title ) > 1 && $title != wfMsg( 'wikiforum-thread-title' )
  477. )
  478. {
  479. $dbr = wfGetDB( DB_SLAVE );
  480. $overview = $dbr->fetchObject( $dbr->select(
  481. array( 'wikiforum_forums', 'wikiforum_category' ),
  482. array( 'wff_forum', 'wff_announcement' ),
  483. array(
  484. 'wfc_deleted' => 0,
  485. 'wff_deleted' => 0,
  486. 'wfc_category = wff_category',
  487. 'wff_forum' => intval( $forumId )
  488. ),
  489. __METHOD__
  490. ) );
  491. if ( $overview->wff_forum > 0 && !wfReadOnly() ) {
  492. $dbw = wfGetDB( DB_MASTER );
  493. $timestamp = wfTimestampNow();
  494. if ( $overview->wff_announcement == false || $wgUser->isAllowed( 'wikiforum-moderator' ) ) {
  495. $doublepost = $dbr->selectRow(
  496. 'wikiforum_threads',
  497. 'wft_thread AS id',
  498. array(
  499. 'wft_deleted' => 0,
  500. 'wft_thread_name' => $title,
  501. 'wft_text' => $text,
  502. 'wft_user' => intval( $wgUser->getId() ),
  503. 'wft_forum' => $forumId,
  504. 'wft_posted_timestamp > ' . ( $timestamp - ( 24 * 3600 ) )
  505. ),
  506. __METHOD__
  507. );
  508. if ( $doublepost === false ) {
  509. $result = $dbw->insert(
  510. 'wikiforum_threads',
  511. array(
  512. 'wft_thread_name' => $title,
  513. 'wft_text' => $text,
  514. 'wft_posted_timestamp' => $timestamp,
  515. 'wft_user' => intval( $wgUser->getId() ),
  516. 'wft_forum' => $forumId,
  517. 'wft_last_post_timestamp' => $timestamp
  518. ),
  519. __METHOD__
  520. );
  521. if ( $result == true ) {
  522. $dbw->update(
  523. 'wikiforum_forums',
  524. array(
  525. 'wff_thread_count = wff_thread_count + 1',
  526. 'wff_last_post_timestamp' => $timestamp,
  527. 'wff_last_post_user' => $wgUser->getId()
  528. ),
  529. array( 'wff_forum' => $forumId ),
  530. __METHOD__
  531. );
  532. $this->result = true;
  533. } else {
  534. $this->result = false;
  535. }
  536. } else {
  537. $this->errorMessage = wfMsg( 'wikiforum-error-double-post' );
  538. $this->result = false;
  539. }
  540. } else {
  541. $this->errorMessage = wfMsg( 'wikiforum-error-no-rights' );
  542. $this->result = false;
  543. }
  544. } else {
  545. $this->result = false;
  546. }
  547. } else {
  548. $this->errorMessage = wfMsg( 'wikiforum-error-no-text-or-title' );
  549. $this->result = false;
  550. }
  551. } else {
  552. $this->errorMessage = wfMsg( 'wikiforum-error-no-rights' );
  553. $this->result = false;
  554. }
  555. if ( $this->result == false ) {
  556. $this->errorTitle = wfMsg( 'wikiforum-error-add' );
  557. if ( $this->errorMessage == '' ) {
  558. $this->errorMessage = wfMsg( 'wikiforum-error-general' );
  559. }
  560. }
  561. return $this->result;
  562. }
  563. /**
  564. * Edit the reply with ID = $replyId.
  565. *
  566. * @param $replyId Integer: internal ID number of the reply
  567. * @param $text String: new reply text
  568. * @return Boolean: did everything go well (true) or not (false)?
  569. */
  570. function editReply( $replyId, $text ) {
  571. global $wgUser, $wgRequest;
  572. if ( $text && strlen( $text ) > 1 ) {
  573. $dbr = wfGetDB( DB_SLAVE );
  574. $reply = $dbr->fetchObject( $dbr->select(
  575. 'wikiforum_replies',
  576. array( 'wfr_thread', 'wfr_reply_id', 'wfr_reply_text', 'wfr_user' ),
  577. array( 'wfr_reply_id' => intval( $replyId ) ),
  578. __METHOD__
  579. ) );
  580. $thread = $dbr->fetchObject( $dbr->select(
  581. 'wikiforum_threads',
  582. array( 'wft_thread', 'wft_closed' ),
  583. array( 'wft_deleted' => 0, 'wft_thread' => $reply->wfr_thread ),
  584. __METHOD__
  585. ) );
  586. if ( $reply->wfr_reply_id > 0 && $thread->wft_thread > 0 ) {
  587. if ( $reply->wfr_reply_text != $text ) {
  588. if (
  589. $wgUser->getId() > 0 &&
  590. ( ( $wgUser->getId() == $reply->wfr_user &&
  591. $thread->wft_closed == 0 ) ||
  592. $wgUser->isAllowed( 'wikiforum-moderator' )
  593. ) && !wfReadOnly()
  594. )
  595. {
  596. $dbw = wfGetDB( DB_MASTER );
  597. $result = $dbw->update(
  598. 'wikiforum_replies',
  599. array(
  600. 'wfr_reply_text' => $text,
  601. 'wfr_edit_timestamp' => wfTimestampNow(),
  602. 'wfr_edit_user' => $wgUser->getId()
  603. ),
  604. array( 'wfr_reply_id' => $reply->wfr_reply_id ),
  605. __METHOD__
  606. );
  607. } else {
  608. $this->errorMessage = wfMsg( 'wikiforum-error-no-rights' );
  609. $result = false;
  610. }
  611. } else {
  612. $result = true;
  613. }
  614. } else {
  615. $this->errorMessage = wfMsg( 'wikiforum-error-not-found' );
  616. $result = false;
  617. }
  618. } else {
  619. $form = $wgRequest->getBool( 'form' );
  620. if ( isset( $form ) && $form == true ) {
  621. $this->errorMessage = wfMsg( 'wikiforum-error-no-reply' );
  622. $result = false;
  623. } else {
  624. $result = true;
  625. }
  626. }
  627. if ( $result == false ) {
  628. $this->errorTitle = wfMsg( 'wikiforum-error-edit' );
  629. if ( $this->errorMessage == '' ) {
  630. $this->errorMessage = wfMsg( 'wikiforum-error-general' );
  631. }
  632. }
  633. return $result;
  634. }
  635. /**
  636. * Add a reply with the text $text to the thread with ID = $threadId.
  637. *
  638. * @param $threadId Integer: internal ID number of the thread to reply to
  639. * @param $text String: reply text
  640. */
  641. function addReply( $threadId, $text ) {
  642. global $wgUser, $wgWikiForumAllowAnonymous;
  643. $timestamp = wfTimestampNow();
  644. if ( $wgWikiForumAllowAnonymous || $wgUser->isLoggedIn() ) {
  645. if ( $threadId > 0 ) {
  646. if ( strlen( $text ) > 1 ) {
  647. $dbr = wfGetDB( DB_SLAVE );
  648. $thread = $dbr->selectRow(
  649. 'wikiforum_threads',
  650. 'wft_thread',
  651. array(
  652. 'wft_deleted' => 0,
  653. 'wft_closed' => 0,
  654. 'wft_thread' => intval( $threadId )
  655. ),
  656. __METHOD__
  657. );
  658. if ( $thread->wft_thread > 0 && !wfReadOnly() ) {
  659. $dbw = wfGetDB( DB_MASTER );
  660. $doublepost = $dbr->selectRow(
  661. 'wikiforum_replies',
  662. 'wfr_reply_id AS id',
  663. array(
  664. 'wfr_deleted' => 0,
  665. 'wfr_reply_text' => $text,
  666. 'wfr_user' => $wgUser->getId(),
  667. 'wfr_thread' => $thread->wft_thread,
  668. 'wfr_posted_timestamp > ' . ( $timestamp - ( 24 * 3600 ) )
  669. ),
  670. __METHOD__
  671. );
  672. if ( $doublepost === false ) {
  673. $result = $dbw->insert(
  674. 'wikiforum_replies',
  675. array(
  676. 'wfr_reply_text' => $text,
  677. 'wfr_posted_timestamp' => $timestamp,
  678. 'wfr_user' => $wgUser->getId(),
  679. 'wfr_thread' => $thread->wft_thread
  680. ),
  681. __METHOD__
  682. );
  683. if ( $result == true ) {
  684. $dbw->update(
  685. 'wikiforum_threads',
  686. array(
  687. 'wft_reply_count = wft_reply_count + 1',
  688. 'wft_last_post_timestamp' => $timestamp,
  689. 'wft_last_post_user' => $wgUser->getId()
  690. ),
  691. array( 'wft_thread' => intval( $threadId ) ),
  692. __METHOD__
  693. );
  694. $pkForum = $dbr->selectRow(
  695. 'wikiforum_threads',
  696. 'wft_forum',
  697. array( 'wft_thread' => intval( $threadId ) ),
  698. __METHOD__
  699. );
  700. $dbw->update(
  701. 'wikiforum_forums',
  702. array( 'wff_reply_count = wff_reply_count + 1' ),
  703. array( 'wff_forum' => intval( $pkForum->wft_forum ) ),
  704. __METHOD__
  705. );
  706. $this->result = true;
  707. } else {
  708. $this->result = false;
  709. }
  710. } else {
  711. $this->errorMessage = wfMsg( 'wikiforum-error-double-post' );
  712. $this->result = false;
  713. }
  714. } else {
  715. $this->errorMessage = wfMsg( 'wikiforum-error-thread-closed' );
  716. $this->result = false;
  717. }
  718. } else {
  719. $this->errorMessage = wfMsg( 'wikiforum-error-no-reply' );
  720. $this->result = false;
  721. }
  722. } else {
  723. $this->errorMessage = wfMsg( 'wikiforum-error-not-found' );
  724. $this->result = false;
  725. }
  726. } else {
  727. $this->errorMessage = wfMsg( 'wikiforum-error-no-rights' );
  728. $this->result = false;
  729. }
  730. if ( $this->result == false ) {
  731. $this->errorTitle = wfMsg( 'wikiforum-error-add' );
  732. if ( $this->errorMessage == '' ) {
  733. $this->errorMessage = wfMsg( 'wikiforum-error-general' );
  734. }
  735. }
  736. return $this->result;
  737. }
  738. function addCategory( $categoryName ) {
  739. global $wgUser;
  740. if (
  741. $wgUser->isAllowed( 'wikiforum-admin' ) &&
  742. !wfReadOnly()
  743. )
  744. {
  745. if ( strlen( $categoryName ) > 0 ) {
  746. $dbr = wfGetDB( DB_SLAVE );
  747. $sortkey = $dbr->selectRow(
  748. 'wikiforum_category',
  749. 'MAX(wfc_sortkey) AS the_key',
  750. array( 'wfc_deleted' => 0 ),
  751. __METHOD__
  752. );
  753. $dbw = wfGetDB( DB_MASTER );
  754. $this->result = $dbw->insert(
  755. 'wikiforum_category',
  756. array(
  757. 'wfc_category_name' => $categoryName,
  758. 'wfc_sortkey' => ( $sortkey->the_key + 1 ),
  759. 'wfc_added_timestamp' => wfTimestampNow(),
  760. 'wfc_added_user' => $wgUser->getId()
  761. ),
  762. __METHOD__
  763. );
  764. } else {
  765. $this->errorMessage = wfMsg( 'wikiforum-no-text-or-title' );
  766. $this->result = false;
  767. }
  768. } else {
  769. $this->errorMessage = wfMsg( 'wikiforum-error-no-rights' );
  770. $this->result = false;
  771. }
  772. if ( $this->result == false ) {
  773. $this->errorTitle = wfMsg( 'wikiforum-error-add' );
  774. if ( $this->errorMessage == '' ) {
  775. $this->errorMessage = wfMsg( 'wikiforum-error-general' );
  776. }
  777. }
  778. return $this->result;
  779. }
  780. function editCategory( $id, $categoryName ) {
  781. global $wgUser;
  782. if ( $wgUser->isAllowed( 'wikiforum-admin' ) ) {
  783. if ( strlen( $categoryName ) > 0 ) {
  784. $dbr = wfGetDB( DB_SLAVE );
  785. $category = $dbr->fetchObject( $dbr->select(
  786. 'wikiforum_category',
  787. array( 'wfc_category', 'wfc_category_name' ),
  788. array( 'wfc_deleted' => 0, 'wfc_category' => intval( $id ) ),
  789. __METHOD__
  790. ) );
  791. if (
  792. $category->wfc_category > 0 &&
  793. $category->wfc_category_name != $categoryName &&
  794. !wfReadOnly()
  795. )
  796. {
  797. $dbw = wfGetDB( DB_MASTER );
  798. $this->result = $dbw->update(
  799. 'wikiforum_category',
  800. array(
  801. 'wfc_category_name' => $categoryName,
  802. 'wfc_edited' => wfTimestampNow(),
  803. 'wfc_edited_user' => $wgUser->getId()
  804. ),
  805. array( 'wfc_category' => intval( $category->wfc_category ) ),
  806. __METHOD__
  807. );
  808. }
  809. } else {
  810. $this->errorMessage = wfMsg( 'wikiforum-no-text-or-title' );
  811. $this->result = false;
  812. }
  813. } else {
  814. $this->errorMessage = wfMsg( 'wikiforum-error-no-rights' );
  815. $this->result = false;
  816. }
  817. if ( $this->result == false ) {
  818. $this->errorTitle = wfMsg( 'wikiforum-error-edit' );
  819. if ( $this->errorMessage == '' ) {
  820. $this->errorMessage = wfMsg( 'wikiforum-error-general' );
  821. }
  822. }
  823. return $this->result;
  824. }
  825. function addForum( $categoryId, $forumName, $description, $announcement ) {
  826. global $wgUser;
  827. if ( $wgUser->isAllowed( 'wikiforum-admin' ) ) {
  828. if ( strlen( $forumName ) > 0 ) {
  829. $dbr = wfGetDB( DB_SLAVE );
  830. $sortkey = $dbr->selectRow(
  831. 'wikiforum_forums',
  832. 'MAX(wff_sortkey) AS the_key',
  833. array(
  834. 'wff_deleted' => 0,
  835. 'wff_category' => intval( $categoryId )
  836. ),
  837. __METHOD__
  838. );
  839. $category = $dbr->selectRow(
  840. 'wikiforum_category',
  841. 'wfc_category',
  842. array(
  843. 'wfc_deleted' => 0,
  844. 'wfc_category' => intval( $categoryId )
  845. ),
  846. __METHOD__
  847. );
  848. if ( $category->wfc_category > 0 && !wfReadOnly() ) {
  849. $dbw = wfGetDB( DB_MASTER );
  850. $this->result = $dbw->insert(
  851. 'wikiforum_forums',
  852. array(
  853. 'wff_forum_name' => $forumName,
  854. 'wff_description' => $description,
  855. 'wff_category' => $category->wfc_category,
  856. 'wff_sortkey' => ( $sortkey->the_key + 1 ),
  857. 'wff_added_timestamp' => wfTimestampNow(),
  858. 'wff_added_user' => $wgUser->getId(),
  859. 'wff_announcement' => $announcement
  860. ),
  861. __METHOD__
  862. );
  863. } else {
  864. $this->errorMessage = wfMsg( 'wikiforum-error-not-found' );
  865. $this->result = false;
  866. }
  867. } else {
  868. $this->errorMessage = wfMsg( 'wikiforum-no-text-or-title' );
  869. $this->result = false;
  870. }
  871. } else {
  872. $this->errorMessage = wfMsg( 'wikiforum-error-no-rights' );
  873. $this->result = false;
  874. }
  875. if ( $this->result == false ) {
  876. $this->errorTitle = wfMsg( 'wikiforum-error-add' );
  877. if ( $this->errorMessage == '' ) {
  878. $this->errorMessage = wfMsg( 'wikiforum-error-general' );
  879. }
  880. }
  881. return $this->result;
  882. }
  883. /**
  884. * Edit a forum.
  885. *
  886. * @param $id Integer: internal forum ID number
  887. * @param $forumName String: forum name as supplied by the user
  888. * @param $description String: forum description as supplied by the user
  889. * @param $announcement
  890. * @return Boolean: did everything go well (true) or not (false)?
  891. */
  892. function editForum( $id, $forumName, $description, $announcement ) {
  893. global $wgUser;
  894. if ( $wgUser->isAllowed( 'wikiforum-admin' ) ) {
  895. if ( strlen( $forumName ) > 0 ) {
  896. $dbr = wfGetDB( DB_SLAVE );
  897. $forum = $dbr->fetchObject( $dbr->select(
  898. 'wikiforum_forums',
  899. array(
  900. 'wff_forum', 'wff_forum_name', 'wff_description',
  901. 'wff_announcement'
  902. ),
  903. array( 'wff_deleted' => 0, 'wff_forum' => intval( $id ) ),
  904. __METHOD__
  905. ) );
  906. if (
  907. $forum->wff_forum > 0 &&
  908. (
  909. $forum->wff_forum_name != $forumName ||
  910. $forum->wff_description != $description ||
  911. $forum->wff_announcement != $announcement
  912. ) && !wfReadOnly()
  913. )
  914. {
  915. $dbw = wfGetDB( DB_MASTER );
  916. $this->result = $dbw->update(
  917. 'wikiforum_forums',
  918. array(
  919. 'wff_forum_name' => $forumName,
  920. 'wff_description' => $description,
  921. 'wff_edited_timestamp' => wfTimestampNow(),
  922. 'wff_edited_user' => $wgUser->getId(),
  923. 'wff_announcement' => $announcement
  924. ),
  925. array( 'wff_forum' => intval( $forum->wff_forum ) ),
  926. __METHOD__
  927. );
  928. }
  929. } else {
  930. $this->errorMessage = wfMsg( 'wikiforum-no-text-or-title' );
  931. $this->result = false;
  932. }
  933. } else {
  934. $this->errorMessage = wfMsg( 'wikiforum-error-no-rights' );
  935. $this->result = false;
  936. }
  937. if ( $this->result == false ) {
  938. $this->errorTitle = wfMsg( 'wikiforum-error-add' );
  939. if ( $this->errorMessage == '' ) {
  940. $this->errorMessage = wfMsg( 'wikiforum-error-general' );
  941. }
  942. }
  943. return $this->result;
  944. }
  945. function sortKeys( $id, $type, $direction_up ) {
  946. global $wgUser;
  947. if ( $wgUser->isAllowed( 'wikiforum-admin' ) ) {
  948. $dbr = wfGetDB( DB_SLAVE );
  949. if ( $type == 'category' ) {
  950. // in the past, both tables had a SortKey column
  951. // nowadays the columns are prefixed with an abbreviation
  952. // of the table name, which is the standard MW convention
  953. // it also means that we need to figure out wtf the
  954. // abbreviation is later on in the code...this will make it
  955. // possible
  956. $columnPrefix = 'wfc_';
  957. $fieldname = 'wfc_category';
  958. $tablename = 'wikiforum_category';
  959. $sqlData = $dbr->select(
  960. $tablename,
  961. array( $fieldname, 'wfc_sortkey' ),
  962. array( 'wfc_deleted' => 0 ),
  963. __METHOD__,
  964. array( 'ORDER BY' => 'wfc_sortkey ASC' )
  965. );
  966. } else {
  967. $columnPrefix = 'wff_';
  968. $fieldname = 'wff_forum';
  969. $tablename = 'wikiforum_forums';
  970. $forum = $dbr->selectRow(
  971. $tablename,
  972. 'wff_category',
  973. array( 'wff_deleted' => 0, 'wff_forum' => intval( $id ) ),
  974. __METHOD__
  975. );
  976. $sqlData = $dbr->select(
  977. $tablename,
  978. array( $fieldname, 'wff_sortkey' ),
  979. array(
  980. 'wff_deleted' => 0,
  981. 'wff_category' => $forum->wff_category
  982. ),
  983. __METHOD__,
  984. array( 'ORDER BY' => 'wff_sortkey ASC' )
  985. );
  986. }
  987. $i = 0;
  988. $new_array = array();
  989. $name = $columnPrefix . 'sortkey';
  990. foreach ( $sqlData as $entry ) {
  991. $entry->$name = $i;
  992. array_push( $new_array, $entry );
  993. $i++;
  994. }
  995. for ( $i = 0; $i < sizeof( $new_array ); $i++ ) {
  996. if ( $new_array[$i]->$fieldname == $id ) {
  997. if ( $direction_up == true && $i > 0 ) {
  998. $new_array[$i]->$name--;
  999. $new_array[$i - 1]->$name++;
  1000. } elseif ( $direction_up == false && $i + 1 < sizeof( $new_array ) ) {
  1001. $new_array[$i]->$name++;
  1002. $new_array[$i + 1]->$name--;
  1003. }
  1004. $i = sizeof( $new_array );
  1005. }
  1006. }
  1007. $dbw = wfGetDB( DB_MASTER );
  1008. if ( !wfReadOnly() ) {
  1009. foreach ( $new_array as $entry ) {
  1010. $result = $dbw->update(
  1011. $tablename,
  1012. array( $columnPrefix . 'sortkey' => $entry->$name ),
  1013. array( $fieldname => $entry->$fieldname ),
  1014. __METHOD__
  1015. );
  1016. }
  1017. }
  1018. }
  1019. }
  1020. /**
  1021. * Show an overview of all available categories and their forums.
  1022. * Used in the special page class.
  1023. *
  1024. * @return HTML
  1025. */
  1026. function showOverview() {
  1027. global $wgOut, $wgUser, $wgLang, $wgScriptPath;
  1028. $output = $this->showFailure();
  1029. $dbr = wfGetDB( DB_SLAVE );
  1030. $sqlCategories = $dbr->select(
  1031. 'wikiforum_category',
  1032. '*',
  1033. array( 'wfc_deleted' => 0 ),
  1034. __METHOD__,
  1035. array( 'ORDER BY' => 'wfc_sortkey ASC, wfc_category ASC' )
  1036. );
  1037. // If there is nothing (i.e. this is a brand new installation),
  1038. // display a message instead of an empty page to the users trying
  1039. // to access Special:WikiForum
  1040. // Otherwise give 'em a search box to search the forum because
  1041. // Special:Search doesn't work for WikiForum
  1042. if ( !$dbr->numRows( $sqlCategories ) ) {
  1043. $output .= wfMsgExt( 'wikiforum-forum-is-empty', 'parse' );
  1044. } else {
  1045. $output .= WikiForumGui::getSearchbox();
  1046. }
  1047. $specialPage = SpecialPage::getTitleFor( 'WikiForum' );
  1048. foreach ( $sqlCategories as $cat ) {
  1049. $sqlForums = $dbr->select(
  1050. array( 'wikiforum_forums', 'user' ),
  1051. array( '*', 'user_name' ),
  1052. array( 'wff_deleted' => 0, ' wff_category' => $cat->wfc_category ),
  1053. __METHOD__,
  1054. array( 'ORDER BY' => 'wff_sortkey ASC, wff_forum ASC' ),
  1055. array( 'user' => array( 'LEFT JOIN', 'user_id = wff_last_post_user' ) )
  1056. );
  1057. $menuLink = '';
  1058. $categoryLink = '';
  1059. if ( $wgUser->isAllowed( 'wikiforum-admin' ) ) {
  1060. $icon = '<img src="' . $wgScriptPath . '/extensions/WikiForum/icons/folder_add.png" title="' . wfMsg( 'wikiforum-add-forum' ) . '" /> ';
  1061. $menuLink = $icon . '<a href="' . $specialPage->escapeFullURL( array( 'addforum' => $cat->wfc_category ) ) . '">' .
  1062. wfMsg( 'wikiforum-add-forum' ) . '</a>';
  1063. $categoryLink = $this->showAdminIcons(
  1064. 'category', $cat->wfc_category, true, true
  1065. );
  1066. $output .= WikiForumGui::getHeaderRow( 0, '', 0, '', $menuLink );
  1067. }
  1068. $output .= WikiForumGui::getMainHeader(
  1069. $cat->wfc_category_name,
  1070. wfMsg( 'wikiforum-threads' ),
  1071. wfMsg( 'wikiforum-replies' ),
  1072. wfMsg( 'wikiforum-latest-thread' ),
  1073. $categoryLink
  1074. );
  1075. foreach ( $sqlForums as $forum ) {
  1076. $forum_link = $this->showAdminIcons(
  1077. 'forum', $forum->wff_forum, true, true
  1078. );
  1079. $icon = '<img src="' . $wgScriptPath . '/extensions/WikiForum/icons/folder.png" title="' .
  1080. wfMsg( 'wikiforum-forum-name', $forum->wff_forum_name ) . '" /> ';
  1081. $last_post = '';
  1082. if ( $forum->wff_last_post_timestamp > 0 ) {
  1083. $last_post = wfMsg(
  1084. 'wikiforum-by',
  1085. $wgLang->timeanddate( $forum->wff_last_post_timestamp ),
  1086. WikiForumClass::getUserLink( $forum->user_name )
  1087. );
  1088. }
  1089. $output .= WikiForumGui::getMainBody(
  1090. '<p class="mw-wikiforum-issue">' . $icon .
  1091. '<a href="' . $specialPage->escapeFullURL( array( 'forum' => $forum->wff_forum ) ) . '">' .
  1092. $forum->wff_forum_name . '</a></p>' .
  1093. '<p class="mw-wikiforum-descr">' . $forum->wff_description . '</p>',
  1094. $forum->wff_thread_count,
  1095. $forum->wff_reply_count,
  1096. $last_post,
  1097. $forum_link,
  1098. false
  1099. );
  1100. }
  1101. $output .= WikiForumGui::getMainFooter();
  1102. }
  1103. // Forum admins are allowed to add new categories
  1104. if ( $wgUser->isAllowed( 'wikiforum-admin' ) ) {
  1105. $icon = '<img src="' . $wgScriptPath . '/extensions/WikiForum/icons/database_add.png" title="' . wfMsg( 'wikiforum-add-category' ) . '" /> ';
  1106. $menuLink = $icon . '<a href="' . $specialPage->escapeFullURL( array( 'addcategory' => true ) ) . '">' .
  1107. wfMsg( 'wikiforum-add-category' ) . '</a>';
  1108. $output .= WikiForumGui::getHeaderRow( 0, '', 0, '', $menuLink );
  1109. }
  1110. return $output;
  1111. }
  1112. function showCategory( $categoryId ) {
  1113. global $wgOut, $wgLang, $wgUser, $wgScriptPath;
  1114. $output = $this->showFailure();
  1115. $dbr = wfGetDB( DB_SLAVE );
  1116. $sqlData = $dbr->select(
  1117. 'wikiforum_category',
  1118. array( 'wfc_category', 'wfc_category_name' ),
  1119. array( 'wfc_deleted' => 0, 'wfc_category' => intval( $categoryId ) ),
  1120. __METHOD__
  1121. );
  1122. $data_overview = $dbr->fetchObject( $sqlData );
  1123. if ( $data_overview ) {
  1124. $sqlForums = $dbr->select(
  1125. array( 'wikiforum_forums', 'user' ),
  1126. array( '*', 'user_name' ),
  1127. array(
  1128. 'wff_deleted' => 0,
  1129. 'wff_category' => $data_overview->wfc_category
  1130. ),
  1131. __METHOD__,
  1132. array( 'ORDER BY' => 'wff_sortkey ASC, wff_forum ASC' ),
  1133. array( 'user' => array( 'LEFT JOIN', 'user_id = wff_last_post_user' ) )
  1134. );
  1135. $menuLink = '';
  1136. $categoryLink = '';
  1137. $specialPage = SpecialPage::getTitleFor( 'WikiForum' );
  1138. // Forum admins are allowed to add new forums
  1139. if ( $wgUser->isAllowed( 'wikiforum-admin' ) ) {
  1140. $icon = '<img src="' . $wgScriptPath . '/extensions/WikiForum/icons/folder_add.png" title="' . wfMsg( 'wikiforum-add-forum' ) . '" /> ';
  1141. $menuLink = $icon . '<a href="' . $specialPage->escapeFullURL( array( 'addforum' => $data_overview->wfc_category ) ) . '">' .
  1142. wfMsg( 'wikiforum-add-forum' ) . '</a>';
  1143. $categoryLink = $this->showAdminIcons(
  1144. 'category', $data_overview->wfc_category, false, false
  1145. );
  1146. }
  1147. $output .= WikiForumGui::getSearchbox();
  1148. $output .= WikiForumGui::getHeaderRow(
  1149. $data_overview->wfc_category,
  1150. $data_overview->wfc_category_name,
  1151. 0,
  1152. '',
  1153. $menuLink
  1154. );
  1155. $output .= WikiForumGui::getMainHeader(
  1156. $data_overview->wfc_category_name,
  1157. wfMsg( 'wikiforum-threads' ),
  1158. wfMsg( 'wikiforum-replies' ),
  1159. wfMsg( 'wikiforum-latest-thread' ),
  1160. $categoryLink
  1161. );
  1162. foreach ( $sqlForums as $forum ) {
  1163. $forum_link = $this->showAdminIcons(
  1164. 'forum', $forum->wff_forum, true, true
  1165. );
  1166. $icon = '<img src="' . $wgScriptPath . '/extensions/WikiForum/icons/folder.png" title="' .
  1167. wfMsg( 'wikiforum-forum-name', $forum->wff_forum_name ) . '" /> ';
  1168. $last_post = '';
  1169. // If there are replies, indicate that somehow...
  1170. // This message will be shown only when there is one reply or
  1171. // more
  1172. if ( $forum->wff_last_post_timestamp > 0 ) {
  1173. $last_post = wfMsg(
  1174. 'wikiforum-by',
  1175. $wgLang->timeanddate( $forum->wff_last_post_timestamp ),
  1176. WikiForumClass::getUserLink( $forum->user_name )
  1177. );
  1178. }
  1179. $output .= WikiForumGui::getMainBody(
  1180. '<p class="mw-wikiforum-issue">' . $icon .
  1181. '<a href="' . $specialPage->escapeFullURL( array( 'forum' => $forum->wff_forum ) ) . '">' .
  1182. $forum->wff_forum_name . '</a></p>' .
  1183. '<p class="mw-wikiforum-descr">' . $forum->wff_description . '</p>',
  1184. $forum->wff_thread_count,
  1185. $forum->wff_reply_count,
  1186. $last_post,
  1187. $forum_link,
  1188. false
  1189. );
  1190. }
  1191. $output .= WikiForumGui::getMainFooter();
  1192. } else {
  1193. $this->errorTitle = wfMsg( 'wikiforum-cat-not-found' );
  1194. $this->errorMessage = wfMsg(
  1195. 'wikiforum-cat-not-found-text',
  1196. '<a href="' . $specialPage->escapeFullURL() . '">' .
  1197. wfMsg( 'wikiforum-overview' ) . '</a>'
  1198. );
  1199. }
  1200. // Jack: unnecessary duplication of the "Overview" link on the bottom
  1201. // of the page, thus removed
  1202. // $output .= WikiForumGui::getHeaderRow( 0, '', 0, '', '' );
  1203. $output .= $this->showFailure();
  1204. return $output;
  1205. }
  1206. function showForum( $forumId ) {
  1207. global $wgOut, $wgLang, $wgUser, $wgRequest, $wgScriptPath;
  1208. $output = $this->showFailure();
  1209. $dbr = wfGetDB( DB_SLAVE );
  1210. $f_movethread = $wgRequest->getInt( 'movethread' );
  1211. // sorting
  1212. if ( $wgRequest->getVal( 'sd' ) == 'up' ) {
  1213. $sort_direction = 'ASC';
  1214. } else {
  1215. $sort_direction = 'DESC';
  1216. }
  1217. if ( $wgRequest->getVal( 'st' ) == 'answers' ) {
  1218. $sort_type = 'wft_reply_count';
  1219. } elseif ( $wgRequest->getVal( 'st' ) == 'calls' ) {
  1220. $sort_type = 'wft_view_count';
  1221. } elseif ( $wgRequest->getVal( 'st' ) == 'thread' ) {
  1222. $sort_type = 'wft_thread_name';
  1223. } else {
  1224. $sort_type = 'wft_last_post_timestamp';
  1225. }
  1226. // end sorting
  1227. $maxThreadsPerPage = intval( wfMsgForContent( 'wikiforum-max-threads-per-page' ) );
  1228. // limiting
  1229. if ( $maxThreadsPerPage && $wgRequest->getVal( 'lc' ) > 0 ) {
  1230. $limit_count = $wgRequest->getVal( 'lc' );
  1231. } elseif ( $maxThreadsPerPage > 0 ) {
  1232. $limit_count = $maxThreadsPerPage;
  1233. }
  1234. if ( is_numeric( $wgRequest->getVal( 'lp' ) ) ) {
  1235. $limit_page = $wgRequest->getVal( 'lp' ) - 1;
  1236. } else {
  1237. $limit_page = 0;
  1238. }
  1239. // end limiting
  1240. $sqlData = $dbr->select(
  1241. array( 'wikiforum_forums', 'wikiforum_category' ),
  1242. array(
  1243. 'wff_forum', 'wff_forum_name', 'wfc_category',
  1244. 'wfc_category_name', 'wff_announcement'
  1245. ),
  1246. array(
  1247. 'wff_deleted' => 0,
  1248. 'wfc_deleted' => 0,
  1249. 'wff_category = wfc_category',
  1250. 'wff_forum' => intval( $forumId )
  1251. ),
  1252. __METHOD__
  1253. );
  1254. $data_overview = $dbr->fetchObject( $sqlData );
  1255. $specialPage = SpecialPage::getTitleFor( 'WikiForum' );
  1256. if ( $data_overview ) {
  1257. $options['ORDER BY'] = 'wft_sticky DESC, ' . $sort_type . ' ' . $sort_direction;
  1258. if ( $limit_count > 0 ) {
  1259. $options['LIMIT'] = $limit_count;
  1260. $options['OFFSET'] = $limit_page * $limit_count;
  1261. }
  1262. $forumIdNumber = $data_overview->wff_forum;
  1263. $sqlThreads = $dbr->select(
  1264. array( 'wikiforum_threads', 'user' ),
  1265. array( '*', 'user_name' ),
  1266. array( 'wft_deleted' => 0, 'wft_forum' => $forumIdNumber ),
  1267. __METHOD__,
  1268. $options,
  1269. array( 'user' => array( 'LEFT JOIN', 'user_id = wft_user' ) )
  1270. );
  1271. $button['up'] = '<img src="' . $wgScriptPath . '/extensions/WikiForum/icons/bullet_arrow_up.png" alt="" />';
  1272. $button['down'] = '<img src="' . $wgScriptPath . '/extensions/WikiForum/icons/bullet_arrow_down.png" alt="" />';
  1273. // Non-moderators cannot post in an announcement-only forum
  1274. if ( $data_overview->wff_announcement == true && !$wgUser->isAllowed( 'wikiforum-moderator' ) ) {
  1275. $write_thread = '';
  1276. } else {
  1277. $icon = '<img src="' . $wgScriptPath . '/extensions/WikiForum/icons/note_add.png" title="' . wfMsg( 'wikiforum-write-thread' ) . '" /> ';
  1278. $write_thread = $icon . '<a href="' . $specialPage->escapeFullURL( array( 'writethread' => $forumIdNumber ) ) . '">' .
  1279. wfMsg( 'wikiforum-write-thread' ) . '</a>';
  1280. }
  1281. $output .= WikiForumGui::getSearchbox();
  1282. $output .= WikiForumGui::getHeaderRow(
  1283. $data_overview->wfc_category,
  1284. $data_overview->wfc_category_name,
  1285. $forumIdNumber,
  1286. $data_overview->wff_forum_name,
  1287. $write_thread
  1288. );
  1289. // @todo FIXME: the logic here seems wonky from the end-users point
  1290. // of view and this code is horrible...
  1291. $output .= WikiForumGui::getMainHeader(
  1292. $data_overview->wff_forum_name . ' <a href="' .
  1293. $specialPage->escapeFullURL( array( 'st' => 'thread', 'sd' => 'up', 'forum' => $forumIdNumber ) ) . '">' . $button['up'] .
  1294. '</a><a href="' .
  1295. $specialPage->escapeFullURL( array( 'st' => 'thread', 'sd' => 'down', 'forum' => $forumIdNumber ) ) . '">' . $button['down'] . '</a>',
  1296. wfMsg( 'wikiforum-replies' ) . ' <a href="' .
  1297. $specialPage->escapeFullURL( array( 'st' => 'answers', 'sd' => 'up', 'forum' => $forumIdNumber ) ) . '">' . $button['up'] .
  1298. '</a><a href="' . $specialPage->escapeFullURL( array( 'st' => 'answers', 'sd' => 'down', 'forum' => $forumIdNumber ) ) . '">' . $button['down'] . '</a>',
  1299. wfMsg( 'wikiforum-views' ) . ' <a href="' .
  1300. $specialPage->escapeFullURL( array( 'st' => 'calls', 'sd' => 'up', 'forum' => $forumIdNumber ) ) . '">' . $button['up'] . '</a><a href="' .
  1301. $specialPage->escapeFullURL( array( 'st' => 'calls', 'sd' => 'down', 'forum' => $forumIdNumber ) ) . '">' . $button['down'] . '</a>',
  1302. wfMsg( 'wikiforum-latest-reply' ) . ' <a href="' .
  1303. $specialPage->escapeFullURL( array( 'st' => 'last', 'sd' => 'up', 'forum' => $forumIdNumber ) ) . '">' . $button['up'] .
  1304. '</a><a href="' . $specialPage->escapeFullURL( array( 'st' => 'last', 'sd' => 'up', 'forum' => $forumIdNumber ) ) . '">' . $button['down'] . '</a>',
  1305. false
  1306. );
  1307. $threads_exist = false;
  1308. foreach ( $sqlThreads as $thread ) {
  1309. $threads_exist = true;
  1310. $icon = $this->getThreadIcon(
  1311. $thread->wft_posted_timestamp,
  1312. $thread->wft_closed,
  1313. $thread->wft_sticky
  1314. );
  1315. $last_post = '';
  1316. if ( $thread->wft_reply_count > 0 ) {
  1317. $last_post = wfMsg(
  1318. 'wikiforum-by',
  1319. $wgLang->timeanddate( $thread->wft_last_post_timestamp ),
  1320. WikiForumClass::getUserLinkById( $thread->wft_last_post_user )
  1321. );
  1322. }
  1323. if ( $thread->wft_sticky == true ) {
  1324. $sticky = 'sticky';
  1325. } else {
  1326. $sticky = false;
  1327. }
  1328. $output .= WikiForumGui::getMainBody(
  1329. '<p class="mw-wikiforum-thread">' . $icon .
  1330. '<a href="' . $specialPage->escapeFullURL( array( 'thread' => $thread->wft_thread ) ) . '">' .
  1331. htmlspecialchars( $thread->wft_thread_name ) . '</a>
  1332. <p class="mw-wikiforum-descr">' .
  1333. wfMsg(
  1334. 'wikiforum-posted',
  1335. $wgLang->timeanddate( $thread->wft_posted_timestamp ),
  1336. WikiForumClass::getUserLink( $thread->user_name )
  1337. ) . '</p></p>',
  1338. $thread->wft_reply_count,
  1339. $thread->wft_view_count,
  1340. $last_post,
  1341. false,
  1342. $sticky
  1343. );
  1344. }
  1345. if ( $threads_exist == false ) {
  1346. $output .= WikiForumGui::getSingleLine( wfMsg( 'wikiforum-no-threads' ), 4 );
  1347. }
  1348. $output .= WikiForumGui::getMainFooter();
  1349. $countReplies = '';
  1350. if ( $limit_count > 0 ) {
  1351. $countReplies = $dbr->selectRow(
  1352. 'wikiforum_threads',
  1353. array( 'COUNT(*) AS count' ),
  1354. array(
  1355. 'wft_deleted' => 0,
  1356. 'wft_forum' => intval( $data_overview->wff_forum )
  1357. ),
  1358. __METHOD__
  1359. );
  1360. $output .= WikiForumGui::getFooterRow(
  1361. $limit_page,
  1362. ( isset( $countReplies->count ) ? $countReplies->count : 0 ),
  1363. $limit_count,
  1364. $data_overview->wff_forum
  1365. );
  1366. }
  1367. } else {
  1368. $this->errorTitle = wfMsg( 'wikiforum-forum-not-found' );
  1369. $this->errorMessage = wfMsg(
  1370. 'wikiforum-forum-not-found-text',
  1371. '<a href="' . $specialPage->escapeFullURL() . '">' .
  1372. wfMsg( 'wikiforum-overview' ) . '</a>'
  1373. );
  1374. }
  1375. $pastethread_link = '';
  1376. if ( $f_movethread > 0 ) {
  1377. $icon = '<img src="' . $wgScriptPath . '/extensions/WikiForum/icons/paste_plain.png" title="' . wfMsg( 'wikiforum-paste-thread' ) . '" /> ';
  1378. $pastethread_link = $icon . '<a href="' . $specialPage->escapeFullURL( array( 'pastethread' => $f_movethread ) ) . '">' . wfMsg( 'wikiforum-paste-thread' ) . '</a> ';
  1379. $output .= WikiForumGui::getHeaderRow( 0, '', 0, '', $pastethread_link );
  1380. }
  1381. $output .= $this->showFailure();
  1382. return $output;
  1383. }
  1384. function showThread( $threadId ) {
  1385. global $wgOut, $wgRequest, $wgUser, $wgLang, $wgScriptPath;
  1386. $output = $this->showFailure();
  1387. $dbr = wfGetDB( DB_SLAVE );
  1388. $sqlData = $dbr->select(
  1389. array( 'wikiforum_forums', 'wikiforum_category', 'wikiforum_threads', 'user' ),
  1390. array(
  1391. 'wft_thread', 'wft_thread_name', 'wft_text', 'wff_forum',
  1392. 'wff_forum_name', 'wfc_category', 'wfc_category_name',
  1393. 'user_name', 'user_id', 'wft_sticky', 'wft_edit_timestamp',
  1394. 'wft_edit_user', 'wft_posted_timestamp', 'wft_user',
  1395. 'wft_closed', 'wft_closed_user',
  1396. ),
  1397. array(
  1398. 'wff_deleted' => 0,
  1399. 'wfc_deleted' => 0,
  1400. 'wft_deleted' => 0,
  1401. 'wff_category = wfc_category',
  1402. 'wff_forum = wft_forum',
  1403. 'wft_thread' => intval( $threadId )
  1404. ),
  1405. __METHOD__,
  1406. array(),
  1407. array( 'user' => array( 'LEFT JOIN', 'user_id = wft_user' ) )
  1408. );
  1409. $data_overview = $dbr->fetchObject( $sqlData );
  1410. $maxRepliesPerPage = intval( wfMsgForContent( 'wikiforum-max-replies-per-page' ) );
  1411. // limiting
  1412. if ( $maxRepliesPerPage && $wgRequest->getVal( 'lc' ) > 0 ) {
  1413. $limit_count = $wgRequest->getVal( 'lc' );
  1414. } elseif ( $maxRepliesPerPage > 0 ) {
  1415. $limit_count = $maxRepliesPerPage;
  1416. }
  1417. if ( is_numeric( $wgRequest->getVal( 'lp' ) ) ) {
  1418. $limit_page = $wgRequest->getVal( 'lp' ) - 1;
  1419. } else {
  1420. $limit_page = 0;
  1421. }
  1422. // end limiting
  1423. $specialPage = SpecialPage::getTitleFor( 'WikiForum' );
  1424. if ( $data_overview ) {
  1425. $queryOptions['ORDER BY'] = 'wfr_posted_timestamp ASC';
  1426. if ( $limit_count > 0 ) {
  1427. $queryOptions['LIMIT'] = $limit_count;
  1428. $queryOptions['OFFSET'] = $limit_page * $limit_count;
  1429. }
  1430. $replies = $dbr->select(
  1431. array( 'wikiforum_replies', 'user' ),
  1432. array( '*', 'user_name', 'user_id' ),
  1433. array(
  1434. 'wfr_deleted' => 0,
  1435. 'wfr_thread' => $data_overview->wft_thread
  1436. ),
  1437. __METHOD__,
  1438. $queryOptions,
  1439. array( 'user' => array( 'LEFT JOIN', 'user_id = wfr_user' ) )
  1440. );
  1441. if ( !wfReadOnly() ) {
  1442. $dbw = wfGetDB( DB_MASTER );
  1443. $dbw->update(
  1444. 'wikiforum_threads',
  1445. array( 'wft_view_count = wft_view_count + 1' ),
  1446. array( 'wft_thread' => intval( $data_overview->wft_thread ) ),
  1447. __METHOD__
  1448. );
  1449. }
  1450. $editButtons = $this->showThreadButtons(
  1451. $data_overview->wft_user,
  1452. $data_overview->wft_closed,
  1453. $data_overview->wft_thread,
  1454. $data_overview->wff_forum
  1455. );
  1456. $menuLink = '';
  1457. if ( $wgUser->isAllowed( 'wikiforum-admin' ) ) {
  1458. if ( $data_overview->wft_sticky == 1 ) {
  1459. $icon = '<img src="' . $wgScriptPath . '/extensions/WikiForum/icons/tag_blue_delete.png" title="' . wfMsg( 'wikiforum-remove-sticky' ) . '" /> ';
  1460. $menuLink = $icon . '<a href="' . $specialPage->escapeFullURL( array( 'removesticky' => $data_overview->wft_thread ) ) . '">' .
  1461. wfMsg( 'wikiforum-remove-sticky' ) . '</a> ';
  1462. } else {
  1463. $icon = '<img src="' . $wgScriptPath . '/extensions/WikiForum/icons/tag_blue_add.png" title="' . wfMsg( 'wikiforum-make-sticky' ) . '" /> ';
  1464. $menuLink = $icon . '<a href="' . $specialPage->escapeFullURL( array( 'makesticky' => $data_overview->wft_thread ) ) . '">' .
  1465. wfMsg( 'wikiforum-make-sticky' ) . '</a> ';
  1466. }
  1467. }
  1468. $icon = '<img src="' . $wgScriptPath . '/extensions/WikiForum/icons/comment_add.png" title="' . wfMsg( 'wikiforum-write-reply' ) . '" /> ';
  1469. // Replying is only possible to open threads
  1470. if ( $data_overview->wft_closed == 0 ) {
  1471. $menuLink .= $icon . '<a href="#writereply">' .
  1472. wfMsg( 'wikiforum-write-reply' ) . '</a>';
  1473. }
  1474. $posted = wfMsg(
  1475. 'wikiforum-posted',
  1476. $wgLang->timeanddate( $data_overview->wft_posted_timestamp ),
  1477. WikiForumClass::getUserLink( $data_overview->user_name )
  1478. );
  1479. if ( $data_overview->wft_edit_timestamp > 0 ) {
  1480. $posted .= '<br /><i>' .
  1481. wfMsg(
  1482. 'wikiforum-edited',
  1483. $wgLang->timeanddate( $data_overview->wft_edit_timestamp ),
  1484. WikiForumClass::getUserLinkById( $data_overview->wft_edit_user )
  1485. ) . '</i>';
  1486. }
  1487. $output .= WikiForumGui::getSearchbox();
  1488. $output .= WikiForumGui::getHeaderRow(
  1489. $data_overview->wfc_category,
  1490. $data_overview->wfc_category_name,
  1491. $data_overview->wff_forum,
  1492. $data_overview->wff_forum_name,
  1493. $menuLink
  1494. );
  1495. // Add topic name to the title
  1496. // @todo FIXME: this is lame and doesn't apply to the <title> attribute
  1497. $wgOut->setPageTitle( wfMsg( 'wikiforum-topic-name', $data_overview->wft_thread_name ) );
  1498. $output .= WikiForumGui::getThreadHeader(
  1499. htmlspecialchars( $data_overview->wft_thread_name ),
  1500. $this->parseIt( $data_overview->wft_text ),// $wgOut->parse( $data_overview->wft_text ),
  1501. $posted,
  1502. $editButtons,
  1503. $data_overview->wft_thread,
  1504. $data_overview->user_id
  1505. );
  1506. foreach ( $replies as $reply ) {
  1507. $editButtons = $this->showReplyButtons(
  1508. $reply->wfr_user,
  1509. $reply->wfr_reply_id,
  1510. $data_overview->wft_thread,
  1511. $data_overview->wft_closed
  1512. );
  1513. $posted = wfMsg(
  1514. 'wikiforum-posted',
  1515. $wgLang->timeanddate( $reply->wfr_posted_timestamp ),
  1516. WikiForumClass::getUserLink( $reply->user_name )
  1517. );
  1518. if ( $reply->wfr_edit_timestamp > 0 ) {
  1519. $posted .= '<br /><i>' .
  1520. wfMsg(
  1521. 'wikiforum-edited',
  1522. $wgLang->timeanddate( $reply->wfr_edit_timestamp ),
  1523. WikiForumClass::getUserLinkById( $reply->wfr_edit_user )
  1524. ) . '</i>';
  1525. }
  1526. $output .= WikiForumGui::getReply(
  1527. $this->parseIt( $reply->wfr_reply_text ),// $wgOut->parse( $reply->wfr_reply_text ),
  1528. $posted,
  1529. $editButtons,
  1530. $reply->wfr_reply_id,
  1531. $reply->user_id
  1532. );
  1533. }
  1534. $output .= WikiForumGui::getThreadFooter();
  1535. if ( $limit_count > 0 ) {
  1536. $countReplies = $dbr->selectRow(
  1537. 'wikiforum_replies',
  1538. 'COUNT(*) AS count',
  1539. array(
  1540. 'wfr_deleted' => 0,
  1541. 'wfr_thread' => $data_overview->wft_thread
  1542. ),
  1543. __METHOD__
  1544. );
  1545. $output .= WikiForumGui::getFooterRow(
  1546. $limit_page,
  1547. $countReplies->count,
  1548. $limit_count,
  1549. $data_overview->wff_forum,
  1550. intval( $threadId )
  1551. );
  1552. }
  1553. $mod_editcomment = $wgRequest->getInt( 'editcomment' );
  1554. $mod_form = $wgRequest->getBool( 'form' );
  1555. if (
  1556. $data_overview->wft_closed == 0 ||
  1557. ( isset( $mod_editcomment ) && $mod_editcomment > 0 &&
  1558. $mod_form != true &&
  1559. $wgUser->isAllowed( 'wikiforum-moderator' )
  1560. )
  1561. )
  1562. {
  1563. $output .= $this->showEditor( $data_overview->wft_thread, 'addcomment' );
  1564. } else {
  1565. $this->errorTitle = wfMsg( 'wikiforum-thread-closed' );
  1566. $this->errorMessage = wfMsg( 'wikiforum-error-thread-closed' );
  1567. $this->errorIcon = 'lock.png';// 'icon_thread_closed';
  1568. }
  1569. } else {
  1570. $this->errorTitle = wfMsg( 'wikiforum-thread-not-found' );
  1571. $this->errorMessage = wfMsg(
  1572. 'wikiforum-thread-not-found-text',
  1573. '<a href="' . $specialPage->escapeFullURL() . '">' .
  1574. wfMsg( 'wikiforum-overview' ) . '</a>'
  1575. );
  1576. }
  1577. $movethread_link = '';
  1578. if ( $wgUser->isAllowed( 'wikiforum-moderator' ) ) {
  1579. $icon = '<img src="' . $wgScriptPath . '/extensions/WikiForum/icons/note_go.png" title="' . wfMsg( 'wikiforum-move-thread' ) . '" /> ';
  1580. $movethread_link = $icon . '<a href="' . $specialPage->escapeFullURL( array( 'movethread' => $data_overview->wft_thread ) ) . '">' . wfMsg( 'wikiforum-move-thread' ) . '</a> ';