ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilObjPoll.php
Go to the documentation of this file.
1 <?php
2 
3 /* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
4 
5 require_once "Services/Object/classes/class.ilObject2.php";
6 require_once "Services/Object/classes/class.ilObjectActivation.php";
7 
16 class ilObjPoll extends ilObject2
17 {
18  protected $online; // [bool]
19  protected $access_type; // [int]
20  protected $access_begin; // [timestamp]
21  protected $access_end; // [timestamp]
22  protected $access_visibility; // [bool]
23  protected $question; // [string]
24  protected $image; // [string]
25  protected $view_results; // [int]
26  protected $period; // [bool]
27  protected $period_begin; // [timestamp]
28  protected $period_end; // [timestamp]
29 
30  // 4.5
31  protected $max_number_answers = 1; // [int]
32  protected $result_sort_by_votes = false; // [bool]
33  protected $mode_non_anonymous = false; // [bool]
34  protected $show_comments = false; //[bool]
35  protected $show_results_as = 1; //[int]
36 
38  const VIEW_RESULTS_NEVER = 2;
41 
44 
45  public function __construct($a_id = 0, $a_reference = true)
46  {
47  global $DIC;
48 
49  $this->db = $DIC->database();
50  // default
51  $this->setOnline(false);
52  $this->setViewResults(self::VIEW_RESULTS_AFTER_VOTE);
54  $this->setVotingPeriod(false);
55 
56  parent::__construct($a_id, $a_reference);
57  }
58 
59  public function initType()
60  {
61  $this->type = "poll";
62  }
63 
64  public function setOnline($a_value)
65  {
66  $this->online = (bool) $a_value;
67  }
68 
69  public function isOnline()
70  {
71  return $this->online;
72  }
73 
74  public function setAccessType($a_value)
75  {
76  $this->access_type = (int) $a_value;
77  }
78 
79  public function getAccessType()
80  {
81  return $this->access_type;
82  }
83 
84  public function setAccessBegin($a_value)
85  {
86  $this->access_begin = (int) $a_value;
87  }
88 
89  public function getAccessBegin()
90  {
91  return $this->access_begin;
92  }
93 
94  public function setAccessEnd($a_value)
95  {
96  $this->access_end = (int) $a_value;
97  }
98 
99  public function getAccessEnd()
100  {
101  return $this->access_end;
102  }
103 
104  public function setAccessVisibility($a_value)
105  {
106  $this->access_visibility = (bool) $a_value;
107  }
108 
109  public function getAccessVisibility()
110  {
112  }
113 
114  public function setQuestion($a_value)
115  {
116  $this->question = (string) $a_value;
117  }
118 
119  public function getQuestion()
120  {
121  return $this->question;
122  }
123 
124  public function setImage($a_value)
125  {
126  $this->image = (string) $a_value;
127  }
128 
129  public function getImage()
130  {
131  return $this->image;
132  }
133 
134  public function setViewResults($a_value)
135  {
136  $this->view_results = (int) $a_value;
137  }
138 
139  public function getViewResults()
140  {
141  return $this->view_results;
142  }
143 
144  public function setVotingPeriod($a_value)
145  {
146  $this->period = (bool) $a_value;
147  }
148 
149  public function getVotingPeriod()
150  {
151  return $this->period;
152  }
153 
154  public function setVotingPeriodBegin($a_value)
155  {
156  $this->period_begin = (int) $a_value;
157  }
158 
159  public function getVotingPeriodBegin()
160  {
161  return $this->period_begin;
162  }
163 
164  public function setVotingPeriodEnd($a_value)
165  {
166  $this->period_end = (int) $a_value;
167  }
168 
169  public function getVotingPeriodEnd()
170  {
171  return $this->period_end;
172  }
173 
174  public function setMaxNumberOfAnswers($a_value)
175  {
176  $this->max_number_answers = (int) $a_value;
177  }
178 
179  public function getMaxNumberOfAnswers()
180  {
182  }
183 
184  public function setSortResultByVotes($a_value)
185  {
186  $this->result_sort_by_votes = (bool) $a_value;
187  }
188 
189  public function getSortResultByVotes()
190  {
192  }
193 
194  public function setNonAnonymous($a_value)
195  {
196  $this->mode_non_anonymous = (bool) $a_value;
197  }
198 
199  public function getNonAnonymous()
200  {
202  }
203 
204  public function setShowComments($a_value)
205  {
206  $this->show_comments = (bool) $a_value;
207  }
208 
209  public function getShowComments()
210  {
211  return $this->show_comments;
212  }
213 
214  public function setShowResultsAs($a_value)
215  {
216  $this->show_results_as = (int) $a_value;
217  }
218 
219  public function getShowResultsAs()
220  {
221  return $this->show_results_as;
222  }
223 
224  protected function doRead()
225  {
226  $ilDB = $this->db;
227 
228  $set = $ilDB->query("SELECT * FROM il_poll" .
229  " WHERE id = " . $ilDB->quote($this->getId(), "integer"));
230  $row = $ilDB->fetchAssoc($set);
231  $this->setQuestion($row["question"]);
232  $this->setImage($row["image"]);
233  $this->setOnline($row["online_status"]);
234  $this->setViewResults($row["view_results"]);
235  $this->setVotingPeriod($row["period"]);
236  $this->setVotingPeriodBegin($row["period_begin"]);
237  $this->setVotingPeriodEnd($row["period_end"]);
238  $this->setMaxNumberOfAnswers($row["max_answers"]);
239  $this->setSortResultByVotes($row["result_sort"]);
240  $this->setNonAnonymous($row["non_anon"]);
241  $this->setShowResultsAs($row["show_results_as"]);
242 
243  // #14661
244  include_once("./Services/Notes/classes/class.ilNote.php");
245  $this->setShowComments(ilNote::commentsActivated($this->getId(), 0, $this->getType()));
246 
247  if ($this->ref_id) {
248  $activation = ilObjectActivation::getItem($this->ref_id);
249  $this->setAccessType($activation["timing_type"]);
251  // default entry values should not be loaded if not activated
252  $this->setAccessBegin($activation["timing_start"]);
253  $this->setAccessEnd($activation["timing_end"]);
254  $this->setAccessVisibility($activation["visible"]);
255  }
256  }
257  }
258 
259  protected function propertiesToDB()
260  {
261  $fields = array(
262  "question" => array("text", $this->getQuestion()),
263  "image" => array("text", $this->getImage()),
264  "online_status" => array("integer", $this->isOnline()),
265  "view_results" => array("integer", $this->getViewResults()),
266  "period" => array("integer", $this->getVotingPeriod()),
267  "period_begin" => array("integer", $this->getVotingPeriodBegin()),
268  "period_end" => array("integer", $this->getVotingPeriodEnd()),
269  "max_answers" => array("integer", $this->getMaxNumberOfAnswers()),
270  "result_sort" => array("integer", $this->getSortResultByVotes()),
271  "non_anon" => array("integer", $this->getNonAnonymous()),
272  "show_results_as" => array("integer", $this->getShowResultsAs()),
273  );
274 
275  return $fields;
276  }
277 
278  protected function doCreate()
279  {
280  $ilDB = $this->db;
281 
282  if ($this->getId()) {
283  $fields = $this->propertiesToDB();
284  $fields["id"] = array("integer", $this->getId());
285 
286  $ilDB->insert("il_poll", $fields);
287 
288 
289  // object activation default entry will be created on demand
290 
291 
292  // block handling
293  include_once "Modules/Poll/classes/class.ilPollBlock.php";
294  $block = new ilPollBlock();
295  $block->setType("poll");
296  $block->setContextObjId($this->getId());
297  $block->setContextObjType("poll");
298  $block->create();
299  }
300  }
301 
302  protected function doUpdate()
303  {
304  $ilDB = $this->db;
305 
306  if ($this->getId()) {
307  $fields = $this->propertiesToDB();
308 
309  $ilDB->update(
310  "il_poll",
311  $fields,
312  array("id" => array("integer", $this->getId()))
313  );
314 
315  // #14661
316  include_once("./Services/Notes/classes/class.ilNote.php");
317  ilNote::activateComments($this->getId(), 0, $this->getType(), $this->getShowComments());
318 
319  if ($this->ref_id) {
320  $activation = new ilObjectActivation();
321  $activation->setTimingType($this->getAccessType());
322  $activation->setTimingStart($this->getAccessBegin());
323  $activation->setTimingEnd($this->getAccessEnd());
324  $activation->toggleVisible($this->getAccessVisibility());
325  $activation->update($this->ref_id);
326  }
327  }
328  }
329 
330  protected function doDelete()
331  {
332  $ilDB = $this->db;
333 
334  if ($this->getId()) {
335  $this->deleteImage();
336  $this->deleteAllAnswers();
337 
338  if ($this->ref_id) {
340  }
341 
342  $ilDB->manipulate("DELETE FROM il_poll" .
343  " WHERE id = " . $ilDB->quote($this->id, "integer"));
344  }
345  }
346 
355  public function doCloneObject($new_obj, $a_target_id, $a_copy_id = 0)
356  {
357  assert($new_obj instanceof ilObjPoll);
358 
359  // question/image
360  $new_obj->setQuestion($this->getQuestion());
361  $image = $this->getImageFullPath();
362  if ($image) {
363  $image = array("tmp_name" => $image,
364  "name" => $this->getImage());
365  $new_obj->uploadImage($image, true);
366  }
367 
368  //copy online status if object is not the root copy object
369  $cp_options = ilCopyWizardOptions::_getInstance($a_copy_id);
370 
371  if (!$cp_options->isRootNode($this->getRefId())) {
372  $new_obj->setOnline($this->isOnline());
373  }
374 
375  $new_obj->setViewResults($this->getViewResults());
376  $new_obj->setShowComments($this->getShowComments());
377  $new_obj->setShowResultsAs($this->getShowResultsAs());
378  $new_obj->update();
379 
380  // answers
381  $answers = $this->getAnswers();
382  if ($answers) {
383  foreach ($answers as $item) {
384  $new_obj->saveAnswer($item["answer"]);
385  }
386  }
387 
388  return $new_obj;
389  }
390 
391 
392  //
393  // image
394  //
395 
401  public function getImageFullPath($a_as_thumb = false)
402  {
403  $img = $this->getImage();
404  if ($img) {
405  $path = $this->initStorage($this->id);
406  if (!$a_as_thumb) {
407  return $path . $img;
408  } else {
409  return $path . "thb_" . $img;
410  }
411  }
412  }
413 
417  public function deleteImage()
418  {
419  if ($this->id) {
420  include_once "Modules/Poll/classes/class.ilFSStoragePoll.php";
421  $storage = new ilFSStoragePoll($this->id);
422  $storage->delete();
423 
424  $this->setImage(null);
425  }
426  }
427 
435  public static function initStorage($a_id, $a_subdir = null)
436  {
437  include_once "Modules/Poll/classes/class.ilFSStoragePoll.php";
438  $storage = new ilFSStoragePoll($a_id);
439  $storage->create();
440 
441  $path = $storage->getAbsolutePath() . "/";
442 
443  if ($a_subdir) {
444  $path .= $a_subdir . "/";
445 
446  if (!is_dir($path)) {
447  mkdir($path);
448  }
449  }
450 
451  return $path;
452  }
453 
460  public function uploadImage(array $a_upload, $a_clone = false)
461  {
462  if (!$this->id) {
463  return false;
464  }
465 
466  $this->deleteImage();
467 
468  // #10074
469  $clean_name = preg_replace("/[^a-zA-Z0-9\_\.\-]/", "", $a_upload["name"]);
470 
471  $path = $this->initStorage($this->id);
472  $original = "org_" . $this->id . "_" . $clean_name;
473  $thumb = "thb_" . $this->id . "_" . $clean_name;
474  $processed = $this->id . "_" . $clean_name;
475 
476  $success = false;
477  if (!$a_clone) {
478  $success = ilUtil::moveUploadedFile($a_upload["tmp_name"], $original, $path . $original);
479  } else {
480  $success = copy($a_upload["tmp_name"], $path . $original);
481  }
482  if ($success) {
483  chmod($path . $original, 0770);
484 
485  // take quality 100 to avoid jpeg artefacts when uploading jpeg files
486  // taking only frame [0] to avoid problems with animated gifs
487  $original_file = ilUtil::escapeShellArg($path . $original);
488  $thumb_file = ilUtil::escapeShellArg($path . $thumb);
489  $processed_file = ilUtil::escapeShellArg($path . $processed);
490 
491  // -geometry "100x100>" is escaped by -geometry "100x100>"
492  // re-replace ">" with ">"
493  $convert_100 = $original_file . "[0] -geometry \"100x100>\" -quality 100 PNG:" . $thumb_file;
494  $escaped_convert_100 = ilUtil::escapeShellCmd($convert_100);
495  $escaped_convert_100 = str_replace('-geometry "100x100>', '-geometry "100x100>', $escaped_convert_100);
496  ilUtil::execQuoted(PATH_TO_CONVERT, $escaped_convert_100);
497 
498  $convert_300 = $original_file . "[0] -geometry \"" . self::getImageSize() . ">\" -quality 100 PNG:" . $processed_file;
499  $escaped_convert_300 = ilUtil::escapeShellCmd($convert_300);
500  $escaped_convert_300 = str_replace('-geometry "' . self::getImageSize() . '>"', '-geometry "' . self::getImageSize() .'>"', $escaped_convert_300);
501  ilUtil::execQuoted(PATH_TO_CONVERT, $escaped_convert_300);
502 
503  $this->setImage($processed);
504  return true;
505  }
506  return false;
507  }
508 
509  public static function getImageSize()
510  {
511  // :TODO:
512  return "300x300";
513  }
514 
515 
516  //
517  // Answer
518  //
519 
520  public function getAnswers()
521  {
522  $ilDB = $this->db;
523 
524  $res = array();
525 
526  $sql = "SELECT * FROM il_poll_answer" .
527  " WHERE poll_id = " . $ilDB->quote($this->getId(), "integer") .
528  " ORDER BY pos ASC";
529  $set = $ilDB->query($sql);
530  while ($row = $ilDB->fetchAssoc($set)) {
531  $res[] = $row;
532  }
533  return $res;
534  }
535 
536  public function getAnswer($a_id)
537  {
538  $ilDB = $this->db;
539 
540  $sql = "SELECT * FROM il_poll_answer" .
541  " WHERE id = " . $ilDB->quote($a_id, "integer");
542  $set = $ilDB->query($sql);
543  return (array) $ilDB->fetchAssoc($set);
544  }
545 
546  public function saveAnswer($a_text, $a_pos = null)
547  {
548  $ilDB = $this->db;
549 
550  if (!trim($a_text)) {
551  return;
552  }
553 
554  $id = $ilDB->nextId("il_poll_answer");
555 
556  if (!$a_pos) {
557  // append
558  $sql = "SELECT max(pos) pos" .
559  " FROM il_poll_answer" .
560  " WHERE poll_id = " . $ilDB->quote($this->getId(), "integer");
561  $set = $ilDB->query($sql);
562  $a_pos = $ilDB->fetchAssoc($set);
563  $a_pos = (int) $a_pos["pos"] + 10;
564  }
565 
566  $fields = array(
567  "id" => array("integer", $id),
568  "poll_id" => array("integer", $this->getId()),
569  "answer" => array("text", trim($a_text)),
570  "pos" => array("integer", $a_pos)
571  );
572  $ilDB->insert("il_poll_answer", $fields);
573 
574  return $id;
575  }
576 
577  public function updateAnswer($a_id, $a_text)
578  {
579  $ilDB = $this->db;
580 
581  $ilDB->update(
582  "il_poll_answer",
583  array("answer" => array("text", $a_text)),
584  array("id" => array("integer", $a_id))
585  );
586  }
587 
588  public function rebuildAnswerPositions()
589  {
590  $answers = $this->getAnswers();
591 
592  $pos = array();
593  foreach ($answers as $item) {
594  $pos[$item["id"]] = $item["pos"];
595  }
596 
597  $this->updateAnswerPositions($pos);
598  }
599 
600  public function updateAnswerPositions(array $a_pos)
601  {
602  $ilDB = $this->db;
603 
604  asort($a_pos);
605 
606  $pos = 0;
607  foreach (array_keys($a_pos) as $id) {
608  $pos += 10;
609 
610  $ilDB->update(
611  "il_poll_answer",
612  array("pos" => array("integer", $pos)),
613  array("id" => array("integer", $id))
614  );
615  }
616  }
617 
618  public function deleteAnswer($a_id)
619  {
620  $ilDB = $this->db;
621 
622  if ($a_id) {
623  $ilDB->manipulate("DELETE FROM il_poll_vote" .
624  " WHERE answer_id = " . $ilDB->quote($this->getId(), "integer"));
625 
626  $ilDB->manipulate("DELETE FROM il_poll_answer" .
627  " WHERE id = " . $ilDB->quote($a_id, "integer"));
628  }
629  }
630 
631  protected function deleteAllAnswers()
632  {
633  $ilDB = $this->db;
634 
635  if ($this->getId()) {
636  $this->deleteAllVotes();
637 
638  $ilDB->manipulate("DELETE FROM il_poll_answer" .
639  " WHERE poll_id = " . $ilDB->quote($this->getId(), "integer"));
640  }
641  }
642 
643  public function deleteAllVotes()
644  {
645  $ilDB = $this->db;
646 
647  if ($this->getId()) {
648  $ilDB->manipulate("DELETE FROM il_poll_vote" .
649  " WHERE poll_id = " . $ilDB->quote($this->getId(), "integer"));
650  }
651  }
652 
653  public function saveAnswers(array $a_answers)
654  {
655  $existing = $this->getAnswers();
656 
657  $ids = array();
658  $pos = 0;
659  foreach ($a_answers as $answer) {
660  if (trim($answer)) {
661  // existing answer?
662  $found = false;
663  foreach ($existing as $idx => $item) {
664  if (trim($answer) == $item["answer"]) {
665  $found = true;
666  unset($existing[$idx]);
667 
668  $id = $item["id"];
669  }
670  }
671 
672  // create new answer
673  if (!$found) {
674  $id = $this->saveAnswer($answer);
675  }
676 
677  // add existing answer id to order
678  if ($id) {
679  $ids[$id] = ++$pos;
680  }
681  }
682  }
683 
684  // remove obsolete answers
685  if (sizeof($existing)) {
686  foreach ($existing as $item) {
687  $this->deleteAnswer($item["id"]);
688  }
689  }
690 
691  // save current order
692  if (sizeof($ids)) {
693  $this->updateAnswerPositions($ids);
694  }
695 
696  return sizeof($ids);
697  }
698 
699 
700  //
701  // votes
702  //
703 
704  public function saveVote($a_user_id, $a_answers)
705  {
706  $ilDB = $this->db;
707 
708  if ($this->hasUserVoted($a_user_id)) {
709  return;
710  }
711 
712  if (!is_array($a_answers)) {
713  $a_answers = array($a_answers);
714  }
715 
716  foreach ($a_answers as $answer_id) {
717  $fields = array("user_id" => array("integer", $a_user_id),
718  "poll_id" => array("integer", $this->getId()),
719  "answer_id" => array("integer", $answer_id));
720  $ilDB->insert("il_poll_vote", $fields);
721  }
722  }
723 
724  public function hasUserVoted($a_user_id)
725  {
726  $ilDB = $this->db;
727 
728  $sql = "SELECT user_id" .
729  " FROM il_poll_vote" .
730  " WHERE poll_id = " . $ilDB->quote($this->getId(), "integer") .
731  " AND user_id = " . $ilDB->quote($a_user_id, "integer");
732  $ilDB->setLimit(1);
733  $set = $ilDB->query($sql);
734  return (bool) $ilDB->numRows($set);
735  }
736 
737  public function countVotes()
738  {
739  $ilDB = $this->db;
740 
741  $sql = "SELECT COUNT(DISTINCT(user_id)) cnt" .
742  " FROM il_poll_vote" .
743  " WHERE poll_id = " . $ilDB->quote($this->getId(), "integer");
744  $set = $ilDB->query($sql);
745  $row = $ilDB->fetchAssoc($set);
746  return (int) $row["cnt"];
747  }
748 
749  public function getVotePercentages()
750  {
751  $ilDB = $this->db;
752 
753  $res = array();
754  $cnt = 0;
755 
756  $sql = "SELECT answer_id, count(*) cnt" .
757  " FROM il_poll_vote" .
758  " WHERE poll_id = " . $ilDB->quote($this->getId(), "integer") .
759  " GROUP BY answer_id";
760  $set = $ilDB->query($sql);
761  while ($row = $ilDB->fetchAssoc($set)) {
762  $cnt += $row["cnt"];
763  $res[$row["answer_id"]] = array("abs" => $row["cnt"], "perc" => 0);
764  }
765 
766  foreach ($res as $id => $item) {
767  $res[$id]["perc"] = $item["abs"] / $cnt * 100;
768  }
769 
770  return array("perc" => $res, "total" => $this->countVotes());
771  }
772 
773  public function getVotesByUsers()
774  {
775  $ilDB = $this->db;
776 
777  $res = array();
778 
779  $sql = "SELECT answer_id, user_id, firstname, lastname, login" .
780  " FROM il_poll_vote" .
781  " JOIN usr_data ON (usr_data.usr_id = il_poll_vote.user_id)" .
782  " WHERE poll_id = " . $ilDB->quote($this->getId(), "integer");
783  $set = $ilDB->query($sql);
784  while ($row = $ilDB->fetchAssoc($set)) {
785  if (!isset($res[$row["user_id"]])) {
786  $res[$row["user_id"]] = $row;
787  }
788  $res[$row["user_id"]]["answers"][] = $row["answer_id"];
789  }
790 
791  return $res;
792  }
793 }
deleteImage()
remove existing file
const VIEW_RESULTS_AFTER_PERIOD
hasUserVoted($a_user_id)
$path
Definition: aliased.php:25
const VIEW_RESULTS_AFTER_VOTE
static commentsActivated($a_rep_obj_id, $a_obj_id, $a_obj_type, $a_news_id=0)
Are comments activated for object?
const VIEW_RESULTS_NEVER
getImageFullPath($a_as_thumb=false)
Get image incl.
updateAnswer($a_id, $a_text)
setAccessEnd($a_value)
global $DIC
Definition: saml.php:7
setVotingPeriod($a_value)
const VIEW_RESULTS_ALWAYS
setAccessVisibility($a_value)
setAccessType($a_value)
static getItem($a_ref_id)
Get item data.
const SHOW_RESULTS_AS_PIECHART
setSortResultByVotes($a_value)
setQuestion($a_value)
setShowResultsAs($a_value)
setOnline($a_value)
setShowComments($a_value)
getAnswer($a_id)
saveAnswer($a_text, $a_pos=null)
setMaxNumberOfAnswers($a_value)
setAccessBegin($a_value)
static escapeShellCmd($a_arg)
escape shell cmd
const SHOW_RESULTS_AS_BARCHART
setImage($a_value)
saveVote($a_user_id, $a_answers)
static _getInstance($a_copy_id)
Get instance of copy wizard options.
$success
Definition: Utf8Test.php:86
foreach($_POST as $key=> $value) $res
static getImageSize()
updateAnswerPositions(array $a_pos)
uploadImage(array $a_upload, $a_clone=false)
Upload new image file.
static initStorage($a_id, $a_subdir=null)
Init file system storage.
static deleteAllEntries($a_ref_id)
Delete all db entries for ref id.
static execQuoted($cmd, $args=null)
exec command and fix spaces on windows
$row
Class ilObjPoll.
saveAnswers(array $a_answers)
Custom block for polls.
doCloneObject($new_obj, $a_target_id, $a_copy_id=0)
Clone poll.
static activateComments($a_rep_obj_id, $a_obj_id, $a_obj_type, $a_activate=true)
Activate notes feature.
static escapeShellArg($a_arg)
__construct($a_id=0, $a_reference=true)
global $ilDB
setNonAnonymous($a_value)
setViewResults($a_value)
setVotingPeriodBegin($a_value)
Class ilObjectActivation.
setVotingPeriodEnd($a_value)
deleteAnswer($a_id)