qnanewanswer.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. <?php
  2. /**
  3. * StatusNet - the distributed open-source microblogging tool
  4. * Copyright (C) 2011, StatusNet, Inc.
  5. *
  6. * Answer a question
  7. *
  8. * PHP version 5
  9. *
  10. * This program is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU Affero General Public License as published by
  12. * the Free Software Foundation, either version 3 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU Affero General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Affero General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. *
  23. * @category QnA
  24. * @package StatusNet
  25. * @author Zach Copley <zach@status.net>
  26. * @copyright 2011 StatusNet, Inc.
  27. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
  28. * @link http://status.net/
  29. */
  30. if (!defined('STATUSNET')) {
  31. // This check helps protect against security problems;
  32. // your code file can't be executed directly from the web.
  33. exit(1);
  34. }
  35. /**
  36. * Answer a question
  37. *
  38. * @category QnA
  39. * @package StatusNet
  40. * @author Zach Copley <zach@status.net>
  41. * @copyright 2010 StatusNet, Inc.
  42. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
  43. * @link http://status.net/
  44. */
  45. class QnanewanswerAction extends Action
  46. {
  47. protected $user = null;
  48. protected $error = null;
  49. protected $complete = null;
  50. public $question = null;
  51. protected $content = null;
  52. /**
  53. * Returns the title of the action
  54. *
  55. * @return string Action title
  56. */
  57. function title()
  58. {
  59. // TRANS: Page title for and answer to a question.
  60. return _m('Answer');
  61. }
  62. /**
  63. * For initializing members of the class.
  64. *
  65. * @param array $argarray misc. arguments
  66. *
  67. * @return boolean true
  68. */
  69. function prepare($argarray)
  70. {
  71. parent::prepare($argarray);
  72. if ($this->boolean('ajax')) {
  73. StatusNet::setApi(true);
  74. }
  75. common_debug("in qnanewanswer");
  76. $this->user = common_current_user();
  77. if (empty($this->user)) {
  78. throw new ClientException(
  79. // TRANS: Client exception thrown trying to answer a question while not logged in.
  80. _m("You must be logged in to answer to a question."),
  81. 403
  82. );
  83. }
  84. if ($this->isPost()) {
  85. $this->checkSessionToken();
  86. }
  87. $id = substr($this->trimmed('id'), 9);
  88. $this->question = QnA_Question::getKV('id', $id);
  89. if (empty($this->question)) {
  90. throw new ClientException(
  91. // TRANS: Client exception thrown trying to respond to a non-existing question.
  92. _m('Invalid or missing question.'),
  93. 404
  94. );
  95. }
  96. $this->answerText = $this->trimmed('answer');
  97. return true;
  98. }
  99. /**
  100. * Handler method
  101. *
  102. * @param array $argarray is ignored since it's now passed in in prepare()
  103. *
  104. * @return void
  105. */
  106. function handle($argarray=null)
  107. {
  108. parent::handle($argarray);
  109. if ($this->isPost()) {
  110. $this->newAnswer();
  111. } else {
  112. $this->showForm();
  113. }
  114. return;
  115. }
  116. /**
  117. * Add a new answer
  118. *
  119. * @return void
  120. */
  121. function newAnswer()
  122. {
  123. $profile = $this->user->getProfile();
  124. try {
  125. $notice = QnA_Answer::saveNew(
  126. $profile,
  127. $this->question,
  128. $this->answerText
  129. );
  130. } catch (ClientException $ce) {
  131. $this->error = $ce->getMessage();
  132. $this->showForm($this->error);
  133. return;
  134. }
  135. if ($this->boolean('ajax')) {
  136. common_debug("ajaxy part");
  137. $answer = $this->question->getAnswer($profile);
  138. $this->startHTML('text/xml;charset=utf-8');
  139. $this->elementStart('head');
  140. // TRANS: Page title after sending an answer.
  141. $this->element('title', null, _m('Answers'));
  142. $this->elementEnd('head');
  143. $this->elementStart('body');
  144. $nli = new NoticeAnswerListItem($notice, $this, $this->question, $answer);
  145. $nli->show();
  146. $this->elementEnd('body');
  147. $this->endHTML();
  148. } else {
  149. common_debug("not ajax");
  150. common_redirect($this->question->getUrl(), 303);
  151. }
  152. }
  153. /**
  154. * Show the Answer form
  155. *
  156. * @return void
  157. */
  158. function showContent()
  159. {
  160. if (!empty($this->error)) {
  161. $this->element('p', 'error', $this->error);
  162. }
  163. $form = new QnanewanswerForm($this->question, $this);
  164. $form->show();
  165. return;
  166. }
  167. /**
  168. * Return true if read only.
  169. *
  170. * MAY override
  171. *
  172. * @param array $args other arguments
  173. *
  174. * @return boolean is read only action?
  175. */
  176. function isReadOnly($args)
  177. {
  178. if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
  179. $_SERVER['REQUEST_METHOD'] == 'HEAD') {
  180. return true;
  181. } else {
  182. return false;
  183. }
  184. }
  185. /**
  186. * Show an Ajax-y error message
  187. *
  188. * Goes back to the browser, where it's shown in a popup.
  189. *
  190. * @param string $msg Message to show
  191. *
  192. * @return void
  193. */
  194. function ajaxErrorMsg($msg)
  195. {
  196. $this->startHTML('text/xml;charset=utf-8', true);
  197. $this->elementStart('head');
  198. // TRANS: Page title after an AJAX error occurs on the post answer page.
  199. $this->element('title', null, _m('Ajax Error'));
  200. $this->elementEnd('head');
  201. $this->elementStart('body');
  202. $this->element('p', array('id' => 'error'), $msg);
  203. $this->elementEnd('body');
  204. $this->endHTML();
  205. }
  206. /**
  207. * Show an Ajax-y answer form
  208. *
  209. * Goes back to the browser, where it's shown in a popup.
  210. *
  211. * @param string $msg Message to show
  212. *
  213. * @return void
  214. */
  215. function ajaxShowForm()
  216. {
  217. common_debug('ajaxShowForm()');
  218. $this->startHTML('text/xml;charset=utf-8', true);
  219. $this->elementStart('head');
  220. // TRANS: Title for form to send answer to a question.
  221. $this->element('title', null, _m('TITLE','Your answer'));
  222. $this->elementEnd('head');
  223. $this->elementStart('body');
  224. $form = new QnanewanswerForm($this, $this->question);
  225. $form->show();
  226. $this->elementEnd('body');
  227. $this->endHTML();
  228. }
  229. /**
  230. * @param string $msg An error message, if any
  231. *
  232. * @return void
  233. */
  234. function showForm($msg = null)
  235. {
  236. common_debug("show form - msg = $msg");
  237. if ($this->boolean('ajax')) {
  238. if ($msg) {
  239. $this->ajaxErrorMsg($msg);
  240. } else {
  241. $this->ajaxShowForm();
  242. }
  243. return;
  244. }
  245. $this->msg = $msg;
  246. $this->showPage();
  247. }
  248. }
  249. class NoticeAnswerListItem extends NoticeListItem
  250. {
  251. protected $question;
  252. protected $answer;
  253. /**
  254. * constructor
  255. *
  256. * Also initializes the profile attribute.
  257. *
  258. * @param Notice $notice The notice we'll display
  259. */
  260. function __construct($notice, $out=null, $question, $answer)
  261. {
  262. parent::__construct($notice, $out);
  263. $this->question = $question;
  264. $this->answer = $answer;
  265. }
  266. function show()
  267. {
  268. if (empty($this->notice)) {
  269. common_log(LOG_WARNING, "Trying to show missing notice; skipping.");
  270. return;
  271. } else if (empty($this->profile)) {
  272. common_log(LOG_WARNING, "Trying to show missing profile (" . $this->notice->profile_id . "); skipping.");
  273. return;
  274. }
  275. $this->showStart();
  276. $this->showNotice();
  277. $this->showNoticeInfo();
  278. $notice = $this->question->getNotice();
  279. $this->out->hidden('inreplyto', $notice->id);
  280. $this->showEnd();
  281. }
  282. /**
  283. * show the content of the notice
  284. *
  285. * Shows the content of the notice. This is pre-rendered for efficiency
  286. * at save time. Some very old notices might not be pre-rendered, so
  287. * they're rendered on the spot.
  288. *
  289. * @return void
  290. */
  291. function showContent()
  292. {
  293. $this->out->elementStart('p', array('class' => 'e-content answer-content'));
  294. if ($this->notice->rendered) {
  295. $this->out->raw($this->notice->rendered);
  296. } else {
  297. // XXX: may be some uncooked notices in the DB,
  298. // we cook them right now. This should probably disappear in future
  299. // versions (>> 0.4.x)
  300. $this->out->raw(common_render_content($this->notice->content, $this->notice));
  301. }
  302. if (!empty($this->answer)) {
  303. $form = new QnashowanswerForm($this->out, $this->answer);
  304. $form->show();
  305. } else {
  306. // TRANS: Error message displayed when an answer has no content.
  307. $out->text(_m('Answer data is missing.'));
  308. }
  309. $this->out->elementEnd('p');
  310. }
  311. }