ILIAS  release_7 Revision v7.30-3-g800a261c036
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
5require_once "Services/Object/classes/class.ilObject2.php";
6require_once "Services/Object/classes/class.ilObjectActivation.php";
7
16class 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
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 {
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 {
212 }
213
214 public function setShowResultsAs($a_value)
215 {
216 $this->show_results_as = (int) $a_value;
217 }
218
219 public function getShowResultsAs()
220 {
222 }
223
224 protected function doRead()
225 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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}
$success
Definition: Utf8Test.php:86
An exception for terminatinating execution or to throw for unit testing.
static _getInstance($a_copy_id)
Get instance of copy wizard options.
static commentsActivated($a_rep_obj_id, $a_obj_id, $a_obj_type, $a_news_id=0)
Are comments activated for object?
static activateComments($a_rep_obj_id, $a_obj_id, $a_obj_type, $a_activate=true)
Activate notes feature.
Class ilObjPoll.
setShowResultsAs($a_value)
const VIEW_RESULTS_ALWAYS
uploadImage(array $a_upload, $a_clone=false)
Upload new image file.
__construct($a_id=0, $a_reference=true)
Constructor @access public.
setNonAnonymous($a_value)
setImage($a_value)
setQuestion($a_value)
static initStorage($a_id, $a_subdir=null)
Init file system storage.
setVotingPeriodBegin($a_value)
const SHOW_RESULTS_AS_PIECHART
saveAnswer($a_text, $a_pos=null)
setAccessBegin($a_value)
const VIEW_RESULTS_AFTER_VOTE
setMaxNumberOfAnswers($a_value)
setVotingPeriod($a_value)
updateAnswerPositions(array $a_pos)
setAccessEnd($a_value)
const SHOW_RESULTS_AS_BARCHART
static getImageSize()
saveAnswers(array $a_answers)
setSortResultByVotes($a_value)
setAccessType($a_value)
const VIEW_RESULTS_AFTER_PERIOD
updateAnswer($a_id, $a_text)
const VIEW_RESULTS_NEVER
doCloneObject($new_obj, $a_target_id, $a_copy_id=0)
Clone poll.
saveVote($a_user_id, $a_answers)
deleteImage()
remove existing file
setOnline($a_value)
setVotingPeriodEnd($a_value)
setAccessVisibility($a_value)
getAnswer($a_id)
setShowComments($a_value)
hasUserVoted($a_user_id)
getImageFullPath($a_as_thumb=false)
Get image incl.
deleteAnswer($a_id)
setViewResults($a_value)
Class ilObject2 This is an intermediate progress of ilObject class.
getType()
get object type @access public
Class ilObjectActivation.
static deleteAllEntries($a_ref_id)
Delete all db entries for ref id.
static getItem($a_ref_id)
Get item data.
getId()
get object id @access public
Custom block for polls.
static moveUploadedFile($a_file, $a_name, $a_target, $a_raise_errors=true, $a_mode="move_uploaded")
move uploaded file
static execQuoted($cmd, $args=null)
exec command and fix spaces on windows
static escapeShellArg($a_arg)
static escapeShellCmd($a_arg)
escape shell cmd
global $DIC
Definition: goto.php:24
$img
Definition: imgupload.php:57
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
foreach($_POST as $key=> $value) $res
global $ilDB