return false;
case 'QnaquestionForm':
case 'QnaanswerForm':
- case 'QnavoteForm';
+ case 'QnaansweredForm':
+ case 'QnavoteForm':
include_once $dir . '/lib/' . strtolower($cls).'.php';
break;
case 'QnA_Question':
switch ($activity->verb) {
case ActivityVerb::POST:
- $notice = Question::saveNew(
+ $notice = QnA_Question::saveNew(
$actor,
- $questionObj->title
- // null,
- // $questionObj->summary,
- // $options
+ $questionObj->title,
+ $questionObj->summary,
+ $options
);
break;
- case Answer::NORMAL:
+ case Answer::ObjectType:
$question = QnA_Question::staticGet('uri', $questionObj->id);
if (empty($question)) {
// FIXME: save the question
throw new Exception("Answer to unknown question.");
}
- $notice = QnA_Answer::saveNew($actor, $question, $activity->verb, $options);
+ $notice = QnA_Answer::saveNew($actor, $question, $options);
break;
default:
- throw new Exception("Unknown verb for question");
+ throw new Exception("Unknown object type received by QnA Plugin");
}
return $notice;
* @param Notice $notice
* @param HTMLOutputter $out
*/
-
function showNotice($notice, $out)
{
switch ($notice->object_type) {
case QnA_Question::OBJECT_TYPE:
- $this->showQuestionNotice($notice, $out);
- break;
+ return $this->showNoticeQuestion($notice, $out);
case QnA_Answer::OBJECT_TYPE:
- $this->showAnswerNotice($notice, $out);
- break;
+ return $this->showNoticeAnswer($notice, $out);
+ default:
+ // TRANS: Exception thrown when performing an unexpected action on a question.
+ // TRANS: %s is the unpexpected object type.
+ throw new Exception(
+ sprintf(
+ _m('Unexpected type for QnA plugin: %s.'),
+ $notice->object_type
+ )
+ );
}
-
- // bad craziness
- $out->elementStart('div', array('class' => 'question'));
-
- $profile = $notice->getProfile();
- $avatar = $profile->getAvatar(AVATAR_MINI_SIZE);
-
- $out->element(
- 'img',
- array(
- 'src' => ($avatar)
- ? $avatar->displayUrl()
- : Avatar::defaultImage(AVATAR_MINI_SIZE),
- 'class' => 'avatar photo question-avatar',
- 'width' => AVATAR_MINI_SIZE,
- 'height' => AVATAR_MINI_SIZE,
- 'alt' => $profile->getBestName()
- )
- );
-
- $out->raw(' '); // avoid for AJAX XML compatibility
-
- // hack for belongsOnTimeline; JS needs to be able to find the author
- $out->elementStart('span', 'vcard author');
- $out->element(
- 'a',
- array(
- 'class' => 'url',
- 'href' => $profile->profileurl,
- 'title' => $profile->getBestName()
- ),
- $profile->nickname
- );
-
- $out->elementEnd('span');
}
-
- function showAnswerNotice($notice, $out)
+
+ function showNoticeQuestion($notice, $out)
{
- $answer = QnA_Answer::fromNotice($notice);
-
- assert(!empty($answer));
-
- $out->elementStart('div', 'answer');
- $out->raw($answer->asHTML());
- $out->elementEnd('div');
- }
-
- function showQuestionNotice($notice, $out)
- {
- $profile = $notice->getProfile();
- $question = QnA_Question::fromNotice($notice);
-
- assert(!empty($question));
- assert(!empty($profile));
-
- $out->elementStart('div', 'question-notice');
-
- $out->elementStart('h3');
+ $user = common_current_user();
- if (!empty($question->url)) {
- $out->element(
- 'a',
- array(
- 'href' => $question->url,
- 'class' => 'question-title'
- ),
- $question->title
- );
+ // @hack we want regular rendering, then just add stuff after that
+ $nli = new NoticeListItem($notice, $out);
+ $nli->showNotice();
+
+ $out->elementStart('div', array('class' => 'entry-content question-content'));
+ $question = QnA_Question::getByNotice($notice);
+
+ if ($question) {
+ if ($user) {
+ $profile = $user->getProfile();
+ $answer = $question->getAnswer($profile);
+ if ($answer) {
+ // User has already answer; show the results.
+ $form = new QnaansweredForm($answer, $out);
+ } else {
+ $form = new QnaanswerForm($question, $out);
+ }
+ $form->show();
+ }
} else {
- $out->text($question->title);
+ $out->text(_m('Question data is missing'));
}
-
- if (!empty($question->location)) {
- $out->elementStart('div', 'question-location');
- $out->element('strong', null, _('Location: '));
- $out->element('span', 'location', $question->location);
- $out->elementEnd('div');
- }
-
- if (!empty($question->description)) {
- $out->elementStart('div', 'question-description');
- $out->element('strong', null, _('Description: '));
- $out->element('span', 'description', $question->description);
- $out->elementEnd('div');
- }
-
- //$answers = $question->getAnswers();
-
- $out->elementStart('div', 'question-answers');
- $out->element('strong', null, _('Answer: '));
- $out->element('span', 'question-answer');
-
$out->elementEnd('div');
- $user = common_current_user();
-
- if (!empty($user)) {
-
- $answer = $question->getAnswer($user->getProfile());
-
- if (empty($answer)) {
- $form = new QnaanswerForm($question, $out);
- $form->show();
- }
+ // @fixme
+ $out->elementStart('div', array('class' => 'entry-content'));
+ }
+ function showNoticeAnswer($notice, $out)
+ {
+ $user = common_current_user();
- }
+ // @hack we want regular rendering, then just add stuff after that
+ $nli = new NoticeListItem($notice, $out);
+ $nli->showNotice();
- $out->elementEnd('div');
+ // @fixme
+ $out->elementStart('div', array('class' => 'entry-content'));
}
/**
$this->id = $this->trimmed('id');
- $this->answer = Answer::staticGet('id', $this->id);
+ $this->answer = QnA_Answer::staticGet('id', $this->id);
if (empty($this->answer)) {
throw new ClientException(_('No such answer.'), 404);
function showPageTitle()
{
$this->elementStart('h1');
- $this->element('a',
- array('href' => $this->answer->url),
- $this->asnwer->title);
+ $this->element(
+ 'a',
+ array('href' => $this->answer->url),
+ $this->answer->title
+ );
$this->elementEnd('h1');
}
}
$this->id = $this->trimmed('id');
- $this->question = Question::staticGet('id', $this->id);
+ $this->question = QnA_Question::staticGet('id', $this->id);
if (empty($this->question)) {
// TRANS: Client exception thrown trying to view a non-existing question.
// TRANS: %1$s is the nickname of the user who asked the question, %2$s is the question.
return sprintf(_m('%1$s\'s question: %2$s'),
$this->user->nickname,
- $this->question->question);
+ $this->question->title);
}
/**
}
$id = $this->trimmed('id');
- $this->question = Question::staticGet('id', $id);
+ $this->question = QnA_Question::staticGet('id', $id);
if (empty($this->question)) {
// TRANS: Client exception thrown trying to respond to a non-existing question.
throw new ClientException(_m('Invalid or missing question.'), 404);
public $id; // char(36) primary key not null -> UUID
public $question_id; // char(36) -> question.id UUID
public $profile_id; // int -> question.id
- public $best; // (int) boolean -> whether the question asker has marked this as the best answer
+ public $best; // (boolean) int -> whether the question asker has marked this as the best answer
+ public $revisions; // int -> count of revisions to this answer
+ public $text; // text -> response text
public $created; // datetime
/**
'description' => 'UUID to the answer notice'
),
'question_id' => array(
- 'type' => 'char',
- 'length' => 36,
- 'not null' => true,
+ 'type' => 'char',
+ 'length' => 36,
+ 'not null' => true,
'description' => 'UUID of question being responded to'
),
- 'best' => array('type' => 'int', 'size' => 'tiny'),
- 'profile_id' => array('type' => 'int'),
- 'created' => array('type' => 'datetime', 'not null' => true),
+ 'best' => array('type' => 'int', 'size' => 'tiny'),
+ 'revisions' => array('type' => 'int'),
+ 'profile_id' => array('type' => 'int'),
+ 'created' => array('type' => 'datetime', 'not null' => true),
),
'primary key' => array('id'),
'unique keys' => array(
*/
function getByNotice($notice)
{
- return self::staticGet('uri', $notice->uri);
+ $answer = self::staticGet('uri', $notice->uri);
+ if (empty($answer)) {
+ throw new Exception("No answer with URI {$this->notice->uri}");
+ }
+ return $answer;
}
/**
*/
function getQuestion()
{
- return Question::staticGet('id', $this->question_id);
+ $question = self::staticGet('id', $this->question_id);
+ if (empty($question)) {
+ throw new Exception("No question with ID {$this->question_id}");
+ }
+ return question;
+ }
+
+ function getProfile()
+ {
+ $profile = Profile::staticGet('id', $this->profile_id);
+ if (empty($profile)) {
+ throw new Exception("No profile with ID {$this->profile_id}");
+ }
+ return $profile;
}
- static function fromNotice($notice)
+ function asHTML()
{
- return self::staticGet('uri', $notice->uri);
+ return self::toHTML(
+ $this->getProfile(),
+ $this->getQuestion()
+ );
}
+ function asString()
+ {
+ return self::toString(
+ $this->getProfile(),
+ $this->getQuestion()
+ );
+ }
+
+ static function toHTML($profile, $event, $response)
+ {
+ $fmt = null;
+
+ $notice = $event->getNotice();
+
+ switch ($response) {
+ case 'Y':
+ $fmt = _("<span class='automatic event-rsvp'><a href='%1s'>%2s</a> is attending <a href='%3s'>%4s</a>.</span>");
+ break;
+ case 'N':
+ $fmt = _("<span class='automatic event-rsvp'><a href='%1s'>%2s</a> is not attending <a href='%3s'>%4s</a>.</span>");
+ break;
+ case '?':
+ $fmt = _("<span class='automatic event-rsvp'><a href='%1s'>%2s</a> might attend <a href='%3s'>%4s</a>.</span>");
+ break;
+ default:
+ throw new Exception("Unknown response code {$response}");
+ break;
+ }
+
+ return sprintf($fmt,
+ htmlspecialchars($profile->profileurl),
+ htmlspecialchars($profile->getBestName()),
+ htmlspecialchars($notice->bestUrl()),
+ htmlspecialchars($event->title));
+ }
+
+ static function toString($profile, $event, $response)
+ {
+ $fmt = null;
+
+ $notice = $event->getNotice();
+
+ switch ($response) {
+ case 'Y':
+ $fmt = _("%1s is attending %2s.");
+ break;
+ case 'N':
+ $fmt = _("%1s is not attending %2s.");
+ break;
+ case '?':
+ $fmt = _("%1s might attend %2s.>");
+ break;
+ default:
+ throw new Exception("Unknown response code {$response}");
+ break;
+ }
+
+ return sprintf($fmt,
+ $profile->getBestName(),
+ $event->title);
+ }
+
+
/**
* Save a new answer notice
*
*
* @return Notice saved notice
*/
- static function saveNew($profile, $question, $options = null)
+ static function saveNew($profile, $question, $text, $options = null)
{
if (empty($options)) {
$options = array();
$answer->id = UUID::gen();
$answer->profile_id = $profile->id;
$answer->question_id = $question->id;
+ $answer->revisions = 0;
+ $answer->best = 0;
+ $answer->text = $text;
$answer->created = common_sql_now();
$answer->uri = common_local_url(
- 'showanswer',
+ 'qnashowanswer',
array('id' => $answer->id)
);
common_log(LOG_DEBUG, "Saving answer: $answer->id, $answer->uri");
$answer->insert();
- // TRANS: Notice content answering a question.
- // TRANS: %s is the answer
$content = sprintf(
_m('answered "%s"'),
- $answer->uri
+ $question->title
);
- $link = '<a href="' . htmlspecialchars($answer->uri) . '">' . htmlspecialchars($answer) . '</a>';
+ $link = '<a href="' . htmlspecialchars($answer->uri) . '">' . htmlspecialchars($question->title) . '</a>';
// TRANS: Rendered version of the notice content answering a question.
// TRANS: %s a link to the question with question title as the link content.
$rendered = sprintf(_m('answered "%s"'), $link);
$options = array_merge(
array(
'urls' => array(),
+ 'content' => $content,
'rendered' => $rendered,
'tags' => $tags,
'replies' => $replies,
'reply_to' => $question->getNotice()->id,
- 'object_type' => self::OBJECT_TYPE),
- $options
- );
+ 'object_type' => self::OBJECT_TYPE
+ ),
+ $options
+ );
if (!array_key_exists('uri', $options)) {
$options['uri'] = $answer->uri;
'closed' => array('type' => 'int', 'size' => 'tiny'),
'description' => array('type' => 'text'),
'created' => array(
- 'type' => 'datetime',
+ 'type' => 'datetime',
'not null' => true
),
),
static function fromNotice($notice)
{
- common_debug('xxxxxxxxxxxxxxx notice-uri = ' . $notice->uri);
return QnA_Question::staticGet('uri', $notice->uri);
}
$q->uri = $options['uri'];
} else {
$q->uri = common_local_url(
- 'showquestion',
+ 'qnashowquestion',
array('id' => $q->id)
);
}
--- /dev/null
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2011, StatusNet, Inc.
+ *
+ * Form for answering a question
+ *
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category QnA
+ * @package StatusNet
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ // This check helps protect against security problems;
+ // your code file can't be executed directly from the web.
+ exit(1);
+}
+
+/**
+ * Form to add a new answer to a question
+ *
+ * @category QnA
+ * @package StatusNet
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link http://status.net/
+ */
+class QnaansweredForm extends Form
+{
+ protected $question;
+ protected $answer;
+
+ /**
+ * Construct a new answer form
+ *
+ * @param QnA_Answer $answer
+ * @param HTMLOutputter $out output channel
+ *
+ * @return void
+ */
+ function __construct(QnA_Answer $answer, HTMLOutputter $out)
+ {
+ parent::__construct($out);
+ $this->question = $answer->getQuestion();
+ $this->answer = $answer;
+ }
+
+ /**
+ * ID of the form
+ *
+ * @return int ID of the form
+ */
+ function id()
+ {
+ return 'answered-form';
+ }
+
+ /**
+ * class of the form
+ *
+ * @return string class of the form
+ */
+ function formClass()
+ {
+ return 'form_settings ajax';
+ }
+
+ /**
+ * Action of the form
+ *
+ * @return string URL of the action
+ */
+ function action()
+ {
+ return common_local_url('qnareviseanswer', array('id' => $this->question->id));
+ }
+
+ /**
+ * Data elements of the form
+ *
+ * @return void
+ */
+ function formData()
+ {
+ $question = $this->question;
+ $out = $this->out;
+ $id = "question-" . $question->id;
+
+ $out->element('p', 'Your answer to:', $question->title);
+ $out->element('input', array('type' => 'text', 'name' => 'answer'));
+ }
+
+ /**
+ * Action elements
+ *
+ * @return void
+ */
+ function formActions()
+ {
+ // TRANS: Button text for submitting a poll response.
+ $this->out->submit('submit', _m('BUTTON', 'Submit'));
+ }
+}