/** * Entire Answer data will be returned * in request * * @return object $this */ protected function setOutput() { /*$d = __METHOD__.' '.__LINE__; exit($d);*/ $a = $this->Answer->getArrayCopy(); /** * @todo maybe use special template * for 'app' instead of default template? * */ $a['edit_delete'] = ' <span class="ico del ajax" title="Delete">delete</span> <span class="ico edit ajax" title="Edit">edit</span>'; $a['html'] = \tplAnswer::parse($a); d('before sending out $a: ' . print_r($a, 1)); $this->Output->setData($a); return $this; }
/** * Process submitted Answer * * @return void */ protected function process() { $formVals = $this->Form->getSubmittedValues(); d('formVals: ' . print_r($formVals, 1)); $oAdapter = new AnswerParser($this->Registry); try { $Answer = $oAdapter->parse(new SubmittedAnswerWWW($this->Registry, $formVals)); d('cp created new answer: ' . \print_r($Answer->getArrayCopy(), 1)); d('ans id: ' . $Answer->getResourceId()); /** * In case of ajax we need to send out a * parsed html block with one answer * under the 'answer' key * * In case of non-ajax redirect back to question page, * hopefully the new answer will show up there too */ if (Request::isAjax()) { $aAnswer = $Answer->getArrayCopy(); /** * Add edit and delete tools because * Viewer already owns this comment and is * allowed to edit or delete it right away. * Javascript that usually dynamically adds these tools * is not going to be fired, so these tools * must already be included in the returned html * */ $aAnswer['edit_delete'] = ' <span class="ico del ajax" title="@@Delete@@">@@delete@@</span> <span class="ico edit ajax" title="@@Edit@@">@@edit@@</span>'; $a = array('answer' => \tplAnswer::parse($aAnswer)); d('before sending out $a: ' . print_r($a, 1)); Responder::sendJSON($a); } else { Responder::redirectToPage($this->Question->getUrl()); } } catch (\Lampcms\AnswerParserException $e) { d('Got AnswerParserException ' . $e->getMessage()); /** * The setFormError in Form sends our json in * case of Ajax request, so we don't have to * worry about it here */ $this->Form->setFormError($e->getMessage()); $this->showFormWithErrors(); } }
/** * Get html div with answers for this one question, * sorted according to param passed in request * * Enclose result in <div> and add pagination to bottom * of div if there is any pagination necessary! * * @todo add skip() and limit() to cursor * in order to use pagination. * * @param Question $Question * * @param string $result desired format of result. Possible * options are: html, array or json object * * * * @throws Exception * @return string html block */ public function getAnswers(Question $Question, $result = 'html') { $qid = $Question[Schema::PRIMARY]; $url = $Question['url']; $pageID = $this->Registry->Router->getPageID(); d('url: ' . $url . ' $pageID: ' . $pageID); $this->pagetPath = $Question->getUrl() . '/'; $urlParts = $this->Registry->Ini->getSection('URI_PARTS'); $cond = $this->Registry->Router->getSegment(3, 's', $urlParts['SORT_RECENT']); d('cond: ' . $cond); $noComments = false === (bool) $this->Registry->Ini->MAX_COMMENTS; d('no comments: ' . $noComments); $aFields = $noComments || false === (bool) $this->Registry->Ini->SHOW_COMMENTS ? array('comments' => 0) : array(); /** * Extra security validation, * IMPORTANT because we should never use * anything in Mongo methods directly from * user input */ if (!in_array($cond, array($urlParts['SORT_RECENT'], $urlParts['SORT_BEST'], $urlParts['SORT_OLDEST']))) { throw new Exception('Invalid value of param "cond" was: ' . $cond); } $where = array(Schema::QUESTION_ID => $qid); /** * Important as of version 0.2 no longer using i_del_ts * as indicator of deleted status - instead using i_status */ if (!$this->Registry->Viewer->isModerator()) { d('not moderator. Get only questions with status 1'); $where[Schema::RESOURCE_STATUS_ID] = Schema::POSTED; } else { $where[Schema::RESOURCE_STATUS_ID] < Schema::DELETED; } switch ($cond) { case $urlParts['SORT_RECENT']: /** * Accepted answer will always be the first one, * then most recently modified */ $sort = array(Schema::IS_ACCEPTED => -1, Schema::LAST_MODIFIED_TIMESTAMP => -1); break; case $urlParts['SORT_OLDEST']: $sort = array(Schema::CREATED_TIMESTAMP => 1); break; case $urlParts['SORT_BEST']: default: /** * Accepted answer will be first * then most highly voted */ $sort = array(Schema::IS_ACCEPTED => -1, Schema::VOTES_SCORE => -1); } $cursor = $this->Registry->Mongo->ANSWERS->find($where, $aFields); d('$cursor: ' . gettype($cursor)); $cursor->sort($sort); $oPager = Paginator::factory($this->Registry); $oPager->paginate($cursor, $this->Registry->Ini->PER_PAGE_ANSWERS, array('path' => $this->pagetPath . $cond, 'append' => false, 'currentPage' => $pageID)); $pagerLinks = $oPager->getLinks(); $ownerId = $Question[Schema::POSTER_ID]; $showLink = $ownerId > 0 && ($this->Registry->Viewer->isModerator() || $ownerId == $this->Registry->Viewer->getUid()); $noComments = $noComments ? ' nocomments' : ''; $func = function (&$a) use($showLink, $noComments) { /** * Don't show Accept link for * already accepted answer */ if (!$a['accepted']) { if ($showLink) { $a['accept_link'] = '<a class="accept ttt" title="@@Click to accept this as best answer@@" href="{_WEB_ROOT_}/{_accept_}/' . $a['_id'] . '">@@Accept@@</a>'; } } else { $a['accepted'] = '<img src="{_IMAGE_SITE_}{_DIR_}/images/accepted.png" alt="@@Best answer@@" class="ttt" title="@@Owner of the question accepted this as best answer@@">'; } $a['nocomments'] = $noComments; $a['edited'] = '@@Edited@@'; }; /** * Create div with answers, append pagination links * to bottom and return the whole div block */ $answers = \tplAnswer::loop($cursor, true, $func) . $pagerLinks; return $answers; }
/** * Get html div with answers for this one question, * sorted according to param passed in request * * Enclose result in <div> and add pagination to bottom * of div if there is any pagination necessary! * * @todo add skip() and limit() to cursor * in order to use pagination. * * @param Question $Question * * @param string desired format of result. Possible * options are: html, array or json object * This will be useful for when we have an API * * * @return string html block */ public function getAnswers(Question $Question, $result = 'html') { $Tr = $this->Registry->Tr; $qid = $Question['_id']; $url = $Question['url']; d('url: ' . $url); d('_GET: ' . print_r($_GET, 1)); $cond = $this->Registry->Request->get('sort', 's', 'i_lm_ts'); d('cond: ' . $cond); $noComments = false === (bool) $this->Registry->Ini->MAX_COMMENTS; d('no comments: ' . $noComments); $aFields = $noComments || false === (bool) $this->Registry->Ini->SHOW_COMMENTS ? array('comments' => 0) : array(); /** * Extra security validation, * IMPORTANT because we should never use * anything in Mongo methods directly from * user input */ if (!in_array($cond, array('i_ts', 'i_votes', 'i_lm_ts'))) { throw new Exception('invalid value of param "cond" was: ' . $cond); } $where = array('i_qid' => $qid); if (!$this->Registry->Viewer->isModerator()) { d('not moderator'); $where['i_del_ts'] = null; } switch ($cond) { case 'i_ts': $sort = array('i_ts' => 1); break; case 'i_votes': $sort = array('i_votes' => -1); break; default: $sort = array($cond => -1); } $cursor = $this->Registry->Mongo->ANSWERS->find($where, $aFields); d('$cursor: ' . gettype($cursor)); $cursor->sort($sort); $oPager = Paginator::factory($this->Registry); $oPager->paginate($cursor, $this->Registry->Ini->PER_PAGE_ANSWERS, array('path' => $this->Registry->Ini->SITE_URL . '/q' . $qid . '/' . $url . '/' . $cond, 'append' => false)); //, 'fileName' => '&pageID=%d' $pagerLinks = $oPager->getLinks(); $func = null; $ownerId = $Question['i_uid']; $showLink = $ownerId > 0 && ($this->Registry->Viewer->isModerator() || $ownerId == $this->Registry->Viewer->getUid()); d('adding accept link callback function'); /** * @todo Translate strings */ $accept = $Tr['Accept']; $alt = $Tr['Click to accept this as best answer']; $alt2 = $Tr['Owner of the question accepted this as best answer']; $noComments = $noComments ? ' nocomments' : ''; $addcomment = $Tr['add comment']; $edited = $Tr['Edited']; $reply = $Tr['Reply']; $reply_t = $Tr['Reply to this comment']; $func = function (&$a) use($accept, $alt, $alt2, $addcomment, $reply, $reply_t, $edited, $showLink, $noComments) { /** * Don't show Accept link for * already accepted answer */ if (!$a['accepted']) { if ($showLink) { $a['accept_link'] = '<a class="accept ttt" title="' . $alt . '" href="/accept/' . $a['_id'] . '">' . $accept . '</a>'; } } else { $a['accepted'] = '<img src="/images/accepted.png" alt="Best answer" class="ttt" title="' . $alt2 . '">'; } $a['add_comment'] = $addcomment; $a['nocomments'] = $noComments; $a['reply'] = $reply; $a['reply_t'] = $reply_t; $a['edited'] = $edited; }; /** * Create div with answers, append pagination links * to bottom and return the whole div block */ $answers = \tplAnswer::loop($cursor, true, $func) . $pagerLinks; return $answers; }