+ }
+
+ public function hasVoted($uid)
+ {
+ $res = XDB::query('SELECT id
+ FROM survey_votes
+ WHERE survey_id = {?} AND uid = {?};', $this->id, $uid); // checks whether the user has already voted
+ return ($res->numRows() != 0);
+ }
+ // }}}
+
+ // {{{ static function deleteSurvey() : deletes a survey (and all its votes)
+ public static function deleteSurvey($sid)
+ {
+ $sql = 'DELETE s.*, v.*, a.*
+ FROM surveys AS s
+ LEFT JOIN survey_votes AS v
+ ON v.survey_id=s.id
+ LEFT JOIN survey_answers AS a
+ ON a.vote_id=v.id
+ WHERE s.id={?};';
+ return XDB::execute($sql, $sid);
+ }
+ // }}}
+
+ // {{{ static function purgeVotes() : clears all votes concerning a survey (I'm not sure whether it's really useful)
+ public static function purgeVotes($sid)
+ {
+ $sql = 'DELETE v.*, a.*
+ FROM survey_votes AS v
+ LEFT JOIN survey_answers AS a
+ ON a.vote_id=v.id
+ WHERE v.survey_id={?};';
+ return XDB::execute($sql, $sid);
+ }
+ // }}}
+
+ // }}}
+}
+// }}}
+
+// {{{ abstract class SurveyQuestion
+abstract class SurveyQuestion
+{
+ // {{{ common properties, constructor, and basic methods
+ private $question;
+ private $comment;
+
+ public function __construct($args)
+ {
+ $this->update($args);
+ }
+
+ public function update($a)
+ {
+ $this->question = $a['question'];
+ $this->comment = $a['comment'];
+ }
+
+ abstract protected function getQuestionType();
+ // }}}
+
+ // {{{ function toArray() : converts to array
+ public function toArray()
+ {
+ return array('type' => $this->getQuestionType(), 'question' => $this->question, 'comment' => $this->comment);
+ }
+ // }}}
+
+ // {{{ function checkSyntax() : checks question elements (before storing into database), not currently needed (with new structure)
+ protected function checkSyntax()
+ {
+ return null;
+ }
+ // }}}
+
+ // {{{ function checkAnswer : returns a correct answer (or a null value if error)
+ public function checkAnswer($ans)
+ {
+ return null;
+ }
+ // }}}
+
+ // {{{ functions regarding the results of a survey
+ abstract public function getResultArray($sid, $qid);
+
+ public function formatAnswer($ans)
+ {
+ return $ans;
+ }
+
+ public function getCSVColumns()
+ {
+ return $this->question;
+ }
+ // }}}
+}
+// }}}
+
+// {{{ abstract class SurveySimple and its derived classes : "open" questions
+// {{{ abstract class SurveySimple extends SurveyQuestion
+abstract class SurveySimple extends SurveyQuestion
+{
+ public function checkAnswer($ans)
+ {
+ return array($ans);
+ }
+
+ public function getResultArray($sid, $qid)
+ {
+ $sql = 'SELECT answer
+ FROM survey_answers
+ WHERE vote_id IN (SELECT id FROM survey_votes WHERE survey_id={?})
+ AND question_id={?}
+ ORDER BY RAND()
+ LIMIT 5;';
+ $res = XDB::query($sql, $sid, $qid);
+ return $res->fetchAllAssoc();
+ }
+}
+// }}}
+
+// {{{ class SurveyText extends SurveySimple : simple text field, allowing a few words
+class SurveyText extends SurveySimple
+{
+ public function getQuestionType()
+ {
+ return "text";
+ }
+}
+// }}}
+
+// {{{ class SurveyTextarea extends SurveySimple : textarea field, allowing longer comments
+class SurveyTextarea extends SurveySimple
+{
+ public function getQuestionType()
+ {
+ return "textarea";
+ }
+}
+// }}}
+
+// {{{ class SurveyNum extends SurveySimple : allows numerical answers
+class SurveyNum extends SurveySimple
+{
+ public function checkAnswer($ans)
+ {
+ return array(intval($ans));
+ }
+
+ protected function getQuestionType()
+ {
+ return "num";
+ }
+}
+// }}}
+// }}}
+
+// {{{ abstract class SurveyList and its derived classes : restricted questions that allows only a list of possible answers
+// {{{ abstract class SurveyList extends SurveyQuestion
+abstract class SurveyList extends SurveyQuestion
+{
+ protected $choices;
+
+ public function update($args)
+ {
+ parent::update($args);
+ $this->choices = array();
+ foreach ($args['choices'] as $val) {
+ if (trim($val) || trim($val) == '0') {
+ $this->choices[] = $val;
+ }