ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilObjSurvey.php
Go to the documentation of this file.
1 <?php
2 
3 /* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
4 
5 use \ILIAS\Survey\Participants;
6 
12 class ilObjSurvey extends ilObject
13 {
17  protected $user;
18 
22  protected $access;
23 
27  protected $plugin_admin;
28 
32 
33 
34  const ANONYMIZE_OFF = 0; // personalized, no codes
35  const ANONYMIZE_ON = 1; // anonymized, codes
36  const ANONYMIZE_FREEACCESS = 2; // anonymized, no codes
37  const ANONYMIZE_CODE_ALL = 3; // personalized, codes
38 
41 
42  // constants to define the print view values.
43  const PRINT_HIDE_LABELS = 1; // Show only the titles in "print" and "PDF Export"
44  const PRINT_SHOW_LABELS = 3; // Show titles and labels in "print" and "PDF Export"
45 
52  public $survey_id;
53 
60  public $author;
61 
67  public $introduction;
68 
74  public $outro;
75 
76 
83 
89  public $start_date;
90 
96  public $end_date;
97 
103  public $questions;
104 
105 
110  public $anonymize;
111 
117 
124 
128  public $template_id;
129  public $pool_usage;
130 
134  protected $log;
135 
139 
140  // 360°
141  protected $mode_360_self_eval; // [bool]
142  protected $mode_360_self_appr; // [bool]
143  protected $mode_360_self_rate; // [bool]
144  protected $mode_360_results; // [int]
145  protected $mode_skill_service; // [bool]
146 
147  const RESULTS_360_NONE = 0;
148  const RESULTS_360_OWN = 1;
149  const RESULTS_360_ALL = 2;
150 
151  // reminder/notification
152  protected $reminder_status; // [bool]
153  protected $reminder_start; // [ilDate]
154  protected $reminder_end; // [ilDate]
155  protected $reminder_frequency; // [int]
156  protected $reminder_target; // [int]
157  protected $reminder_last_sent; // [bool]
158  protected $reminder_tmpl; // [int]
159  protected $tutor_ntf_status; // [bool]
160  protected $tutor_ntf_recipients; // [array]
161  protected $tutor_ntf_target; // [int]
162  protected $tutor_res_status; // [bool]
163  protected $tutor_res_recipients; // [array]
164 
165  protected $view_own_results; // [bool]
166  protected $mail_own_results; // [bool]
167  protected $mail_confirmation; // [bool]
168 
169  protected $anon_user_list; // [bool]
170 
176 
177  protected $mode; //[int]
178  protected $mode_self_eval_results; //[int]
179 
180  //MODE TYPES
181  const MODE_STANDARD = 0;
182  const MODE_360 = 1;
183  const MODE_SELF_EVAL = 2;
184 
185  //self evaluation only access to results
189 
190 
195 
202  public function __construct($a_id = 0, $a_call_by_reference = true)
203  {
204  global $DIC;
205 
206  $this->user = $DIC->user();
207  $this->lng = $DIC->language();
208  $this->db = $DIC->database();
209  $this->access = $DIC->access();
210  $this->log = $DIC["ilLog"];
211  $this->plugin_admin = $DIC["ilPluginAdmin"];
212  $this->tree = $DIC->repositoryTree();
213  $ilUser = $DIC->user();
214  $lng = $DIC->language();
215 
216  $this->type = "svy";
217  $this->survey_id = -1;
218  $this->introduction = "";
219  $this->outro = $lng->txt("survey_finished");
220  $this->author = $ilUser->getFullname();
221  $this->evaluation_access = self::EVALUATION_ACCESS_OFF;
222  $this->questions = array();
223  $this->anonymize = self::ANONYMIZE_OFF;
224  $this->display_question_titles = self::QUESTIONTITLES_VISIBLE;
225  $this->surveyCodeSecurity = true;
226  $this->template_id = null;
227  $this->pool_usage = true;
228  $this->log = ilLoggerFactory::getLogger("svy");
229  $this->mode = self::MODE_STANDARD;
230  $this->mode_self_eval_results = self::RESULTS_SELF_EVAL_OWN;
231 
232  $this->invitation_manager = new Participants\InvitationsManager();
233 
234  parent::__construct($a_id, $a_call_by_reference);
235  }
236 
240  public function create($a_upload = false)
241  {
242  parent::create();
243  if (!$a_upload) {
244  $this->createMetaData();
245  }
246  $this->setOfflineStatus(true);
247  $this->update($a_upload);
248  }
249 
255  public function createMetaData()
256  {
257  parent::createMetaData();
258  $this->saveAuthorToMetadata();
259  }
260 
267  public function update($a_upload = false)
268  {
269  if (!$a_upload) {
270  $this->updateMetaData();
271  }
272 
273  if (!parent::update()) {
274  return false;
275  }
276 
277  // put here object specific stuff
278 
279  return true;
280  }
281 
282  public function createReference()
283  {
284  $result = parent::createReference();
285  $this->saveToDb();
286  return $result;
287  }
288 
293  public function read()
294  {
295  parent::read();
296  $this->loadFromDb();
297  }
298 
305  public function addQuestion($question_id)
306  {
307  array_push($this->questions, $question_id);
308  }
309 
316  public function delete()
317  {
318  if ($this->countReferences() == 1) {
319  $this->deleteMetaData();
320 
321  // Delete all survey questions, constraints and materials
322  foreach ($this->questions as $question_id) {
323  $this->removeQuestion($question_id);
324  }
325  $this->deleteSurveyRecord();
326 
328  }
329 
330  $remove = parent::delete();
331 
332  // always call parent delete function first!!
333  if (!$remove) {
334  return false;
335  }
336  return true;
337  }
338 
344  public function deleteSurveyRecord()
345  {
346  $ilDB = $this->db;
347 
348  $affectedRows = $ilDB->manipulateF(
349  "DELETE FROM svy_svy WHERE survey_id = %s",
350  array('integer'),
351  array($this->getSurveyId())
352  );
353 
354  $result = $ilDB->queryF(
355  "SELECT questionblock_fi FROM svy_qblk_qst WHERE survey_fi = %s",
356  array('integer'),
357  array($this->getSurveyId())
358  );
359  $questionblocks = array();
360  while ($row = $ilDB->fetchAssoc($result)) {
361  array_push($questionblocks, $row["questionblock_fi"]);
362  }
363  if (count($questionblocks)) {
364  $affectedRows = $ilDB->manipulate("DELETE FROM svy_qblk WHERE " . $ilDB->in('questionblock_id', $questionblocks, false, 'integer'));
365  }
366  $affectedRows = $ilDB->manipulateF(
367  "DELETE FROM svy_qblk_qst WHERE survey_fi = %s",
368  array('integer'),
369  array($this->getSurveyId())
370  );
371  $this->deleteAllUserData(false);
372 
373  $affectedRows = $ilDB->manipulateF(
374  "DELETE FROM svy_anonymous WHERE survey_fi = %s",
375  array('integer'),
376  array($this->getSurveyId())
377  );
378 
379  // delete export files
380  $svy_data_dir = ilUtil::getDataDir() . "/svy_data";
381  $directory = $svy_data_dir . "/svy_" . $this->getId();
382  if (is_dir($directory)) {
383  ilUtil::delDir($directory);
384  }
385 
386  $mobs = ilObjMediaObject::_getMobsOfObject("svy:html", $this->getId());
387  // remaining usages are not in text anymore -> delete them
388  // and media objects (note: delete method of ilObjMediaObject
389  // checks whether object is used in another context; if yes,
390  // the object is not deleted!)
391  foreach ($mobs as $mob) {
392  ilObjMediaObject::_removeUsage($mob, "svy:html", $this->getId());
393  $mob_obj = new ilObjMediaObject($mob);
394  $mob_obj->delete();
395  }
396  }
397 
404  public function deleteAllUserData($reset_LP = true)
405  {
406  $ilDB = $this->db;
407 
408  $result = $ilDB->queryF(
409  "SELECT finished_id FROM svy_finished WHERE survey_fi = %s",
410  array('integer'),
411  array($this->getSurveyId())
412  );
413  $active_array = array();
414  while ($row = $ilDB->fetchAssoc($result)) {
415  array_push($active_array, $row["finished_id"]);
416  }
417 
418  $affectedRows = $ilDB->manipulateF(
419  "DELETE FROM svy_finished WHERE survey_fi = %s",
420  array('integer'),
421  array($this->getSurveyId())
422  );
423 
424  foreach ($active_array as $active_fi) {
425  $affectedRows = $ilDB->manipulateF(
426  "DELETE FROM svy_answer WHERE active_fi = %s",
427  array('integer'),
428  array($active_fi)
429  );
430  $affectedRows = $ilDB->manipulateF(
431  "DELETE FROM svy_times WHERE finished_fi = %s",
432  array('integer'),
433  array($active_fi)
434  );
435  }
436 
437  if ($reset_LP) {
438  $lp_obj = ilObjectLP::getInstance($this->getId());
439  $lp_obj->resetLPDataForCompleteObject();
440  }
441  }
442 
448  public function removeSelectedSurveyResults($finished_ids)
449  {
450  $ilDB = $this->db;
451 
452  $user_ids[] = array();
453 
454  foreach ($finished_ids as $finished_id) {
455  $result = $ilDB->queryF(
456  "SELECT finished_id FROM svy_finished WHERE finished_id = %s",
457  array('integer'),
458  array($finished_id)
459  );
460  $row = $ilDB->fetchAssoc($result);
461 
462  if ($row["user_fi"]) {
463  $user_ids[] = $row["user_fi"];
464  }
465 
466  $affectedRows = $ilDB->manipulateF(
467  "DELETE FROM svy_answer WHERE active_fi = %s",
468  array('integer'),
469  array($row["finished_id"])
470  );
471 
472  $affectedRows = $ilDB->manipulateF(
473  "DELETE FROM svy_finished WHERE finished_id = %s",
474  array('integer'),
475  array($finished_id)
476  );
477 
478  $affectedRows = $ilDB->manipulateF(
479  "DELETE FROM svy_times WHERE finished_fi = %s",
480  array('integer'),
481  array($row["finished_id"])
482  );
483  }
484 
485  if (sizeof($user_ids)) {
486  $lp_obj = ilObjectLP::getInstance($this->getId());
487  $lp_obj->resetLPDataForUserIds($user_ids);
488  }
489  }
490 
491  public function &getSurveyParticipants($finished_ids = null, $force_non_anonymous = false, $include_invites = false)
492  {
493  $ilDB = $this->db;
494 
495  $sql = "SELECT * FROM svy_finished" .
496  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer");
497  if ($finished_ids) {
498  $sql .= " AND " . $ilDB->in("finished_id", $finished_ids, "", "integer");
499  }
500 
501  $result = $ilDB->query($sql);
502  $participants = array();
503  if ($result->numRows() > 0) {
504  while ($row = $ilDB->fetchAssoc($result)) {
505  $userdata = $this->getUserDataFromActiveId($row["finished_id"], $force_non_anonymous);
506  $userdata["finished"] = (bool) $row["state"];
507  $userdata["finished_tstamp"] = $row["tstamp"];
508  $participants[$userdata["sortname"] . $userdata["active_id"]] = $userdata;
509  }
510  }
511  $participant_ids = array_column($participants, "usr_id");
512  if ($include_invites) {
513  foreach ($this->invitation_manager->getAllForSurvey($this->getSurveyId()) as $usr_id) {
514  if (!in_array($usr_id, $participant_ids)) {
515  $name = ilObjUser::_lookupName($usr_id);
516  $participants[$name["lastname"] . "," . $name["firstname"] . $usr_id] = [
517  "fullname" => ilObjUser::_lookupFullname($usr_id),
518  "sortname" => $name["lastname"] . "," . $name["firstname"],
519  "fistname" => $name["firstname"],
520  "lastname" => $name["lastname"],
521  "login" => $name["login"],
522  "gender" => "",
523  "usr_id" => $usr_id,
524  "finished" => false,
525  "finished_tstamp" => 0,
526  "invited" => true
527  ];
528  }
529  }
530  }
531 
532  return $participants;
533  }
534 
541  public function isComplete()
542  {
543  if (($this->getTitle()) and (count($this->questions))) {
544  return 1;
545  } else {
546  return 0;
547  }
548  }
549 
555  public function saveCompletionStatus()
556  {
557  $ilDB = $this->db;
558 
559  $complete = 0;
560  if ($this->isComplete()) {
561  $complete = 1;
562  }
563  if ($this->getSurveyId() > 0) {
564  $affectedRows = $ilDB->manipulateF(
565  "UPDATE svy_svy SET complete = %s, tstamp = %s WHERE survey_id = %s",
566  array('text','integer','integer'),
567  array($this->isComplete(), time(), $this->getSurveyId())
568  );
569  }
570  }
571 
579  public function duplicateQuestionForSurvey($question_id, $a_force = false)
580  {
582 
583  $questiontype = $this->getQuestionType($question_id);
584  $question_gui = $this->getQuestionGUI($questiontype, $question_id);
585 
586  // check if question is a pool question at all, if not do nothing
587  if ($this->getId() == $question_gui->object->getObjId() && !$a_force) {
588  return $question_id;
589  }
590 
591  $duplicate_id = $question_gui->object->duplicate(true, "", "", "", $this->getId());
592  return $duplicate_id;
593  }
594 
600  public function insertQuestion($question_id)
601  {
602  $ilDB = $this->db;
603 
604  $this->log->debug("insert question, id:" . $question_id);
605 
606  if (!SurveyQuestion::_isComplete($question_id)) {
607  $this->log->debug("question is not complete");
608  return false;
609  } else {
610  // get maximum sequence index in test
611  // @todo: refactor this
612  $result = $ilDB->queryF(
613  "SELECT survey_question_id FROM svy_svy_qst WHERE survey_fi = %s",
614  array('integer'),
615  array($this->getSurveyId())
616  );
617  $sequence = $result->numRows();
618  $duplicate_id = $this->duplicateQuestionForSurvey($question_id);
619  $this->log->debug("duplicate, id: " . $question_id . ", duplicate id: " . $duplicate_id);
620 
621  // check if question is not already in the survey, see #22018
622  if ($this->isQuestionInSurvey($duplicate_id)) {
623  return false;
624  }
625 
626  $next_id = $ilDB->nextId('svy_svy_qst');
627  $affectedRows = $ilDB->manipulateF(
628  "INSERT INTO svy_svy_qst (survey_question_id, survey_fi, question_fi, sequence, tstamp) VALUES (%s, %s, %s, %s, %s)",
629  array('integer', 'integer', 'integer', 'integer', 'integer'),
630  array($next_id, $this->getSurveyId(), $duplicate_id, $sequence, time())
631  );
632 
633  $this->log->debug("added entry to svy_svy_qst, id: " . $next_id . ", question id: " . $duplicate_id . ", sequence: " . $sequence);
634 
635  $this->loadQuestionsFromDb();
636  return true;
637  }
638  }
639 
646  public function isQuestionInSurvey($a_question_fi)
647  {
648  global $DIC;
649  //return false;
650  $ilDB = $DIC->database();
651 
652  $set = $ilDB->query("SELECT * FROM svy_svy_qst " .
653  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
654  " AND question_fi = " . $ilDB->quote($a_question_fi, "integer"));
655  if ($rec = $ilDB->fetchAssoc($set)) {
656  return true;
657  }
658  return false;
659  }
660 
661 
662 
668  public function insertQuestionblock($questionblock_id)
669  {
670  $ilDB = $this->db;
671  $result = $ilDB->queryF(
672  "SELECT svy_qblk.title, svy_qblk.show_questiontext, svy_qblk.show_blocktitle," .
673  " svy_qblk_qst.question_fi FROM svy_qblk, svy_qblk_qst, svy_svy_qst" .
674  " WHERE svy_qblk.questionblock_id = svy_qblk_qst.questionblock_fi" .
675  " AND svy_svy_qst.question_fi = svy_qblk_qst.question_fi" .
676  " AND svy_qblk.questionblock_id = %s" .
677  " ORDER BY svy_svy_qst.sequence",
678  array('integer'),
679  array($questionblock_id)
680  );
681  $questions = array();
682  $show_questiontext = 0;
683  $show_blocktitle = 0;
684  while ($row = $ilDB->fetchAssoc($result)) {
685  $duplicate_id = $this->duplicateQuestionForSurvey($row["question_fi"]);
686  array_push($questions, $duplicate_id);
687  $title = $row["title"];
688  $show_questiontext = $row["show_questiontext"];
689  $show_blocktitle = $row["show_blocktitle"];
690  }
691  $this->createQuestionblock($title, $show_questiontext, $show_blocktitle, $questions);
692  }
693 
694  public function saveUserSettings($usr_id, $key, $title, $value)
695  {
696  $ilDB = $this->db;
697 
698  $next_id = $ilDB->nextId('svy_settings');
699  $affectedRows = $ilDB->insert("svy_settings", array(
700  "settings_id" => array("integer", $next_id),
701  "usr_id" => array("integer", $usr_id),
702  "keyword" => array("text", $key),
703  "title" => array("text", $title),
704  "value" => array("clob", $value)
705  ));
706  }
707 
708  public function deleteUserSettings($id)
709  {
710  $ilDB = $this->db;
711 
712  $affectedRows = $ilDB->manipulateF(
713  "DELETE FROM svy_settings WHERE settings_id = %s",
714  array('integer'),
715  array($id)
716  );
717  return $affectedRows;
718  }
719 
720  public function getUserSettings($usr_id, $key)
721  {
722  $ilDB = $this->db;
723 
724  $result = $ilDB->queryF(
725  "SELECT * FROM svy_settings WHERE usr_id = %s AND keyword = %s",
726  array('integer', 'text'),
727  array($usr_id, $key)
728  );
729  $found = array();
730  if ($result->numRows()) {
731  while ($row = $ilDB->fetchAssoc($result)) {
732  $found[$row['settings_id']] = $row;
733  }
734  }
735  return $found;
736  }
737 
743  public function saveToDb()
744  {
745  $ilDB = $this->db;
746 
747  // date handling
748  $rmd_start = $this->getReminderStart();
749  if (is_object($rmd_start)) {
750  $rmd_start = $rmd_start->get(IL_CAL_DATE);
751  }
752  $rmd_end = $this->getReminderEnd();
753  if (is_object($rmd_end)) {
754  $rmd_end = $rmd_end->get(IL_CAL_DATE);
755  }
756 
757  if ($this->getSurveyId() < 1) {
758  $next_id = $ilDB->nextId('svy_svy');
759  $affectedRows = $ilDB->insert("svy_svy", array(
760  "survey_id" => array("integer", $next_id),
761  "obj_fi" => array("integer", $this->getId()),
762  "author" => array("text", $this->getAuthor()),
763  "introduction" => array("clob", ilRTE::_replaceMediaObjectImageSrc($this->getIntroduction(), 0)),
764  "outro" => array("clob", ilRTE::_replaceMediaObjectImageSrc($this->getOutro(), 0)),
765  "startdate" => array("text", $this->getStartDate()),
766  "enddate" => array("text", $this->getEndDate()),
767  "evaluation_access" => array("text", $this->getEvaluationAccess()),
768  "complete" => array("text", $this->isComplete()),
769  "created" => array("integer", time()),
770  "anonymize" => array("text", $this->getAnonymize()),
771  "show_question_titles" => array("text", $this->getShowQuestionTitles()),
772  "mailnotification" => array('integer', ($this->getMailNotification()) ? 1 : 0),
773  "mailaddresses" => array('text', strlen($this->getMailAddresses()) ? $this->getMailAddresses() : null),
774  "mailparticipantdata" => array('text', strlen($this->getMailParticipantData()) ? $this->getMailParticipantData() : null),
775  "tstamp" => array("integer", time()),
776  "template_id" => array("integer", $this->getTemplate()),
777  "pool_usage" => array("integer", $this->getPoolUsage()),
778  // Mode type
779  "mode" => array("integer", $this->getMode()),
780  // 360°
781  "mode_360_self_eval" => array("integer", $this->get360SelfEvaluation()),
782  "mode_360_self_rate" => array("integer", $this->get360SelfRaters()),
783  "mode_360_self_appr" => array("integer", $this->get360SelfAppraisee()),
784  "mode_360_results" => array("integer", $this->get360Results()),
785  // competences
786  "mode_skill_service" => array("integer", (int) $this->getSkillService()),
787  // Self Evaluation Only
788  "mode_self_eval_results" => array("integer", ilObjSurvey::RESULTS_SELF_EVAL_OWN),
789  // reminder/notification
790  "reminder_status" => array("integer", (int) $this->getReminderStatus()),
791  "reminder_start" => array("datetime", $rmd_start),
792  "reminder_end" => array("datetime", $rmd_end),
793  "reminder_frequency" => array("integer", (int) $this->getReminderFrequency()),
794  "reminder_target" => array("integer", (int) $this->getReminderTarget()),
795  "reminder_last_sent" => array("datetime", $this->getReminderLastSent()),
796  "reminder_tmpl" => array("text", $this->getReminderTemplate(true)),
797  "tutor_ntf_status" => array("integer", (int) $this->getTutorNotificationStatus()),
798  "tutor_ntf_reci" => array("text", implode(";", (array) $this->getTutorNotificationRecipients())),
799  "tutor_ntf_target" => array("integer", (int) $this->getTutorNotificationTarget()),
800  "own_results_view" => array("integer", $this->hasViewOwnResults()),
801  "own_results_mail" => array("integer", $this->hasMailOwnResults()),
802  "tutor_res_status" => array("integer", (int) $this->getTutorResultsStatus()),
803  "tutor_res_reci" => array("text", implode(";", (array) $this->getTutorResultsRecipients())),
804  "confirmation_mail" => array("integer", $this->hasMailConfirmation()),
805  "anon_user_list" => array("integer", $this->hasAnonymousUserList())
806  ));
807  $this->setSurveyId($next_id);
808  } else {
809  $affectedRows = $ilDB->update("svy_svy", array(
810  "author" => array("text", $this->getAuthor()),
811  "introduction" => array("clob", ilRTE::_replaceMediaObjectImageSrc($this->getIntroduction(), 0)),
812  "outro" => array("clob", ilRTE::_replaceMediaObjectImageSrc($this->getOutro(), 0)),
813  "startdate" => array("text", $this->getStartDate()),
814  "enddate" => array("text", $this->getEndDate()),
815  "evaluation_access" => array("text", $this->getEvaluationAccess()),
816  "complete" => array("text", $this->isComplete()),
817  "anonymize" => array("text", $this->getAnonymize()),
818  "show_question_titles" => array("text", $this->getShowQuestionTitles()),
819  "mailnotification" => array('integer', ($this->getMailNotification()) ? 1 : 0),
820  "mailaddresses" => array('text', strlen($this->getMailAddresses()) ? $this->getMailAddresses() : null),
821  "mailparticipantdata" => array('text', strlen($this->getMailParticipantData()) ? $this->getMailParticipantData() : null),
822  "tstamp" => array("integer", time()),
823  "template_id" => array("integer", $this->getTemplate()),
824  "pool_usage" => array("integer", $this->getPoolUsage()),
825  //MODE TYPE
826  "mode" => array("integer", $this->getMode()),
827  // 360°
828  "mode_360_self_eval" => array("integer", $this->get360SelfEvaluation()),
829  "mode_360_self_rate" => array("integer", $this->get360SelfRaters()),
830  "mode_360_self_appr" => array("integer", $this->get360SelfAppraisee()),
831  "mode_360_results" => array("integer", $this->get360Results()),
832  // Competences
833  "mode_skill_service" => array("integer", (int) $this->getSkillService()),
834  // Self Evaluation Only
835  "mode_self_eval_results" => array("integer", $this->getSelfEvaluationResults()),
836  // reminder/notification
837  "reminder_status" => array("integer", $this->getReminderStatus()),
838  "reminder_start" => array("datetime", $rmd_start),
839  "reminder_end" => array("datetime", $rmd_end),
840  "reminder_frequency" => array("integer", $this->getReminderFrequency()),
841  "reminder_target" => array("integer", $this->getReminderTarget()),
842  "reminder_last_sent" => array("datetime", $this->getReminderLastSent()),
843  "reminder_tmpl" => array("text", $this->getReminderTemplate()),
844  "tutor_ntf_status" => array("integer", $this->getTutorNotificationStatus()),
845  "tutor_ntf_reci" => array("text", implode(";", (array) $this->getTutorNotificationRecipients())),
846  "tutor_ntf_target" => array("integer", $this->getTutorNotificationTarget()),
847  "own_results_view" => array("integer", $this->hasViewOwnResults()),
848  "own_results_mail" => array("integer", $this->hasMailOwnResults()),
849  "tutor_res_status" => array("integer", (int) $this->getTutorResultsStatus()),
850  "tutor_res_reci" => array("text", implode(";", (array) $this->getTutorResultsRecipients())),
851  "confirmation_mail" => array("integer", $this->hasMailConfirmation()),
852  "anon_user_list" => array("integer", $this->hasAnonymousUserList())
853  ), array(
854  "survey_id" => array("integer", $this->getSurveyId())
855  ));
856  }
857  if ($affectedRows) {
858  // save questions to db
859  $this->saveQuestionsToDb();
860  }
861 
862  // moved activation to ilObjectActivation
863  if ($this->ref_id) {
864  ilObjectActivation::getItem($this->ref_id);
865 
866  $item = new ilObjectActivation;
867  if (!$this->isActivationLimited()) {
869  } else {
870  $item->setTimingType(ilObjectActivation::TIMINGS_ACTIVATION);
871  $item->setTimingStart($this->getActivationStartDate());
872  $item->setTimingEnd($this->getActivationEndDate());
873  $item->toggleVisible($this->getActivationVisibility());
874  }
875 
876  $item->update($this->ref_id);
877  }
878  }
879 
886  public function saveQuestionsToDb()
887  {
888  $ilDB = $this->db;
889 
890  $this->log->debug("save questions");
891 
892  // gather old questions state
893  $old_questions = array();
894  $result = $ilDB->queryF(
895  "SELECT survey_question_id,question_fi,sequence" .
896  " FROM svy_svy_qst WHERE survey_fi = %s",
897  array('integer'),
898  array($this->getSurveyId())
899  );
900  while ($row = $ilDB->fetchAssoc($result)) {
901  $old_questions[$row["question_fi"]] = $row; // problem, as soon as duplicates exist, they will be hidden here
902  }
903 
904  // #15231 - diff with current questions state
905  $insert = $update = $delete = array();
906  foreach ($this->questions as $seq => $fi) {
907  if (!array_key_exists($fi, $old_questions)) { // really new fi IDs
908  $insert[] = $fi; // this should be ok, should not create duplicates here
909  } elseif ($old_questions[$fi]["sequence"] != $seq) { // we are updating one of the duplicates (if any)
910  $update[$fi] = $old_questions[$fi]["survey_question_id"];
911  }
912  // keep track of still relevant questions
913  unset($old_questions[$fi]); // deleting old question, if they are not in current array
914  }
915 
916  // delete obsolete question relations
917  if (sizeof($old_questions)) {
918  $del_ids = array();
919  foreach ($old_questions as $fi => $old) {
920  $del_ids[] = $old["survey_question_id"];
921  }
922  $ilDB->manipulate($q = "DELETE FROM svy_svy_qst" .
923  " WHERE " . $ilDB->in("survey_question_id", $del_ids, "", "integer"));
924  $this->log->debug("delete: " . $q);
925  }
926  unset($old_questions);
927 
928  // create/update question relations
929  foreach ($this->questions as $seq => $fi) {
930  if (in_array($fi, $insert)) {
931  // check if question is not already in the survey, see #22018
932  if (!$this->isQuestionInSurvey($fi)) {
933  $next_id = $ilDB->nextId('svy_svy_qst');
934  $ilDB->manipulateF(
935  "INSERT INTO svy_svy_qst" .
936  " (survey_question_id, survey_fi, question_fi, heading, sequence, tstamp)" .
937  " VALUES (%s, %s, %s, %s, %s, %s)",
938  array('integer', 'integer', 'integer', 'text', 'integer', 'integer'),
939  array($next_id, $this->getSurveyId(), $fi, null, $seq, time())
940  );
941  $this->log->debug("insert svy_svy_qst, id:" . $next_id . ", fi: " . $fi . ", seq:" . $seq);
942  }
943  } elseif (array_key_exists($fi, $update)) {
944  $ilDB->manipulate("UPDATE svy_svy_qst" .
945  " SET sequence = " . $ilDB->quote($seq, "integer") .
946  ", tstamp = " . $ilDB->quote(time(), "integer") .
947  " WHERE survey_question_id = " . $ilDB->quote($update[$fi], "integer"));
948  $this->log->debug("update svy_svy_qst, id:" . $update[$fi] . ", fi: " . $fi . ", seq:" . $seq);
949  }
950  }
951  }
952 
960  public function getAnonymousId($id)
961  {
962  $ilDB = $this->db;
963  $result = $ilDB->queryF(
964  "SELECT anonymous_id FROM svy_finished WHERE anonymous_id = %s",
965  array('text'),
966  array($id)
967  );
968  if ($result->numRows()) {
969  $row = $ilDB->fetchAssoc($result);
970  return $row["anonymous_id"];
971  } else {
972  return "";
973  }
974  }
975 
982  public function getQuestionGUI($questiontype, $question_id)
983  {
984  return SurveyQuestionGUI::_getQuestionGUI($questiontype, $question_id);
985  }
986 
994  public function getQuestionType($question_id)
995  {
996  $ilDB = $this->db;
997  if ($question_id < 1) {
998  return -1;
999  }
1000  $result = $ilDB->queryF(
1001  "SELECT type_tag FROM svy_question, svy_qtype WHERE svy_question.question_id = %s AND " .
1002  "svy_question.questiontype_fi = svy_qtype.questiontype_id",
1003  array('integer'),
1004  array($question_id)
1005  );
1006  if ($result->numRows() == 1) {
1007  $data = $ilDB->fetchAssoc($result);
1008  return $data["type_tag"];
1009  } else {
1010  return "";
1011  }
1012  }
1013 
1020  public function getSurveyId()
1021  {
1022  return $this->survey_id;
1023  }
1024 
1028  public function setAnonymize($a_anonymize)
1029  {
1030  switch ($a_anonymize) {
1031  case self::ANONYMIZE_OFF:
1032  case self::ANONYMIZE_ON:
1033  case self::ANONYMIZE_FREEACCESS:
1034  case self::ANONYMIZE_CODE_ALL:
1035  $this->anonymize = $a_anonymize;
1036  break;
1037  default:
1038  $this->anonymize = self::ANONYMIZE_OFF;
1039  break;
1040  }
1041  }
1042 
1048  public function getAnonymize()
1049  {
1050  return ($this->anonymize) ? $this->anonymize : 0;
1051  }
1052 
1058  public function isAccessibleWithoutCode()
1059  {
1060  return ($this->getAnonymize() == self::ANONYMIZE_OFF ||
1061  $this->getAnonymize() == self::ANONYMIZE_FREEACCESS);
1062  }
1063 
1069  public function hasAnonymizedResults()
1070  {
1071  return ($this->getAnonymize() == self::ANONYMIZE_ON ||
1072  $this->getAnonymize() == self::ANONYMIZE_FREEACCESS);
1073  }
1074 
1080  public function loadFromDb()
1081  {
1082  $ilDB = $this->db;
1083  $result = $ilDB->queryF(
1084  "SELECT * FROM svy_svy WHERE obj_fi = %s",
1085  array('integer'),
1086  array($this->getId())
1087  );
1088  if ($result->numRows() == 1) {
1089  $data = $ilDB->fetchAssoc($result);
1090  $this->setSurveyId($data["survey_id"]);
1091  $this->setAuthor($data["author"]);
1092  $this->setIntroduction(ilRTE::_replaceMediaObjectImageSrc($data["introduction"], 1));
1093  if (strcmp($data["outro"], "survey_finished") == 0) {
1094  $this->setOutro($this->lng->txt("survey_finished"));
1095  } else {
1096  $this->setOutro(ilRTE::_replaceMediaObjectImageSrc($data["outro"], 1));
1097  }
1098  $this->setShowQuestionTitles($data["show_question_titles"]);
1099  $this->setStartDate($data["startdate"]);
1100  $this->setEndDate($data["enddate"]);
1101  $this->setAnonymize($data["anonymize"]);
1102  $this->setEvaluationAccess($data["evaluation_access"]);
1103  $this->loadQuestionsFromDb();
1104  $this->setMailNotification($data['mailnotification']);
1105  $this->setMailAddresses($data['mailaddresses']);
1106  $this->setMailParticipantData($data['mailparticipantdata']);
1107  $this->setTemplate($data['template_id']);
1108  $this->setPoolUsage($data['pool_usage']);
1109  // Mode
1110  $this->setMode($data['mode']);
1111  // 360°
1112  $this->set360SelfEvaluation($data['mode_360_self_eval']);
1113  $this->set360SelfRaters($data['mode_360_self_rate']);
1114  $this->set360SelfAppraisee($data['mode_360_self_appr']);
1115  $this->set360Results($data['mode_360_results']);
1116  // Mode self evaluated
1117  $this->setSelfEvaluationResults($data['mode_self_eval_results']);
1118  // Competences
1119  $this->setSkillService($data['mode_skill_service']);
1120  // reminder/notification
1121  $this->setReminderStatus($data["reminder_status"]);
1122  $this->setReminderStart($data["reminder_start"] ? new ilDate($data["reminder_start"], IL_CAL_DATE) : null);
1123  $this->setReminderEnd($data["reminder_end"] ? new ilDate($data["reminder_end"], IL_CAL_DATE) : null);
1124  $this->setReminderFrequency($data["reminder_frequency"]);
1125  $this->setReminderTarget($data["reminder_target"]);
1126  $this->setReminderLastSent($data["reminder_last_sent"]);
1127  $this->setReminderTemplate($data["reminder_tmpl"]);
1128  $this->setTutorNotificationStatus($data["tutor_ntf_status"]);
1129  $this->setTutorNotificationRecipients(explode(";", $data["tutor_ntf_reci"]));
1130  $this->setTutorNotificationTarget($data["tutor_ntf_target"]);
1131  $this->setTutorResultsStatus($data["tutor_res_status"]);
1132  $this->setTutorResultsRecipients(explode(";", $data["tutor_res_reci"]));
1133 
1134  $this->setViewOwnResults($data["own_results_view"]);
1135  $this->setMailOwnResults($data["own_results_mail"]);
1136  $this->setMailConfirmation($data["confirmation_mail"]);
1137 
1138  $this->setAnonymousUserList($data["anon_user_list"]);
1139  }
1140 
1141  // moved activation to ilObjectActivation
1142  if ($this->ref_id) {
1143  $activation = ilObjectActivation::getItem($this->ref_id);
1144  switch ($activation["timing_type"]) {
1146  $this->setActivationLimited(true);
1147  $this->setActivationStartDate($activation["timing_start"]);
1148  $this->setActivationEndDate($activation["timing_end"]);
1149  $this->setActivationVisibility($activation["visible"]);
1150  break;
1151 
1152  default:
1153  $this->setActivationLimited(false);
1154  break;
1155  }
1156  }
1157  }
1158 
1165  public function loadQuestionsFromDb()
1166  {
1167  $ilDB = $this->db;
1168  $this->questions = array();
1169  $result = $ilDB->queryF(
1170  "SELECT * FROM svy_svy_qst WHERE survey_fi = %s ORDER BY sequence",
1171  array('integer'),
1172  array($this->getSurveyId())
1173  );
1174  while ($data = $ilDB->fetchAssoc($result)) {
1175  $this->questions[$data["sequence"]] = $data["question_fi"];
1176  }
1177  }
1178 
1182  public function fixSequenceStructure()
1183  {
1184  global $DIC;
1185 
1186  $ilDB = $DIC->database();
1187  //return;
1188  // we keep all survey question ids with their lowest sequence
1189  $result = $ilDB->queryF(
1190  "SELECT * FROM svy_svy_qst WHERE survey_fi = %s ORDER BY sequence",
1191  array('integer'),
1192  array($this->getSurveyId())
1193  );
1194 
1195  // step 1: find duplicates -> $to_delete_ids
1196  $fis = array();
1197  $to_delete_ids = array();
1198  while ($data = $ilDB->fetchAssoc($result)) {
1199  if (in_array($data["question_fi"], $fis)) { // found a duplicate
1200  $to_delete_ids[] = $data["survey_question_id"];
1201  } else {
1202  $fis[] = $data["question_fi"];
1203  }
1204  }
1205 
1206  // step 2: we delete the duplicates
1207  if (count($to_delete_ids) > 0) {
1208  $ilDB->manipulate($q = "DELETE FROM svy_svy_qst" .
1209  " WHERE " . $ilDB->in("survey_question_id", $to_delete_ids, false, "integer") .
1210  " AND survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer"));
1211  $this->log->debug("delete: " . $q);
1212 
1213  $ilDB->manipulate($q = "DELETE FROM svy_qblk_qst " .
1214  " WHERE " . $ilDB->in("question_fi", $fis, true, "integer") .
1215  " AND survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer"));
1216  $this->log->debug("delete: " . $q);
1217  }
1218 
1219  // step 3: we fix the sequence
1220  $set = $ilDB->query("SELECT * FROM svy_svy_qst " .
1221  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") . " ORDER BY sequence");
1222  $seq = 0;
1223  while ($rec = $ilDB->fetchAssoc($set)) {
1224  $ilDB->manipulate(
1225  $q = "UPDATE svy_svy_qst SET " .
1226  " sequence = " . $ilDB->quote($seq++, "integer") .
1227  " WHERE survey_question_id = " . $ilDB->quote($rec["survey_question_id"], "integer")
1228  );
1229  $this->log->debug("update: " . $q);
1230  }
1231  }
1232 
1233 
1241  public function setAuthor($author = "")
1242  {
1243  $this->author = $author;
1244  }
1245 
1255  public function saveAuthorToMetadata($a_author = "")
1256  {
1257  $md = new ilMD($this->getId(), 0, $this->getType());
1258  $md_life = &$md->getLifecycle();
1259  if (!$md_life) {
1260  if (strlen($a_author) == 0) {
1261  $ilUser = $this->user;
1262  $a_author = $ilUser->getFullname();
1263  }
1264 
1265  $md_life = &$md->addLifecycle();
1266  $md_life->save();
1267  $con = &$md_life->addContribute();
1268  $con->setRole("Author");
1269  $con->save();
1270  $ent = &$con->addEntity();
1271  $ent->setEntity($a_author);
1272  $ent->save();
1273  }
1274  }
1275 
1283  public function getAuthor()
1284  {
1285  $author = array();
1286  $md = new ilMD($this->getId(), 0, $this->getType());
1287  $md_life = &$md->getLifecycle();
1288  if ($md_life) {
1289  $ids = &$md_life->getContributeIds();
1290  foreach ($ids as $id) {
1291  $md_cont = &$md_life->getContribute($id);
1292  if (strcmp($md_cont->getRole(), "Author") == 0) {
1293  $entids = &$md_cont->getEntityIds();
1294  foreach ($entids as $entid) {
1295  $md_ent = &$md_cont->getEntity($entid);
1296  array_push($author, $md_ent->getEntity());
1297  }
1298  }
1299  }
1300  }
1301  return join(",", $author);
1302  }
1303 
1310  public function getShowQuestionTitles()
1311  {
1312  return ($this->display_question_titles) ? 1 : 0;
1313  }
1314 
1321  public function setShowQuestionTitles($a_show)
1322  {
1323  $this->display_question_titles = ($a_show) ? 1 : 0;
1324  }
1325 
1332  public function showQuestionTitles()
1333  {
1334  $this->display_question_titles = 1;
1335  }
1336 
1343  public function hideQuestionTitles()
1344  {
1345  $this->display_question_titles = 0;
1346  }
1347 
1354  public function setIntroduction($introduction = "")
1355  {
1356  $this->introduction = $introduction;
1357  }
1358 
1365  public function setOutro($outro = "")
1366  {
1367  $this->outro = $outro;
1368  }
1369 
1370 
1378  public function getStartDate()
1379  {
1380  return (strlen($this->start_date)) ? $this->start_date : null;
1381  }
1382 
1389  public function canStartSurvey($anonymous_id = null, $a_no_rbac = false)
1390  {
1391  $ilAccess = $this->access;
1392 
1393  $result = true;
1394  $messages = array();
1395  $edit_settings = false;
1396  // check start date
1397  if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getStartDate(), $matches)) {
1398  $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
1399  $now = time();
1400  if ($now < $epoch_time) {
1401  array_push($messages, $this->lng->txt('start_date_not_reached') . ' (' .
1403  $result = false;
1404  $edit_settings = true;
1405  }
1406  }
1407  // check end date
1408  if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndDate(), $matches)) {
1409  $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
1410  $now = time();
1411  if ($now > $epoch_time) {
1412  array_push($messages, $this->lng->txt('end_date_reached') . ' (' .
1414  $result = false;
1415  $edit_settings = true;
1416  }
1417  }
1418 
1419  // check online status
1420  if ($this->getOfflineStatus()) {
1421  array_push($messages, $this->lng->txt("survey_is_offline"));
1422  $result = false;
1423  $edit_settings = true;
1424  }
1425  // check rbac permissions
1426  if (!$a_no_rbac && !$ilAccess->checkAccess("read", "", $this->ref_id)) {
1427  array_push($messages, $this->lng->txt("cannot_participate_survey"));
1428  $result = false;
1429  }
1430  /*
1431  // 2. check previous access
1432  if (!$result["error"])
1433  {
1434  $ilUser = $this->user;
1435  $survey_started = $this->isSurveyStarted($ilUser->getId(), $anonymous_id);
1436  if ($survey_started === 1)
1437  {
1438  array_push($messages, $this->lng->txt("already_completed_survey"));
1439  $result = FALSE;
1440  }
1441  }
1442  */
1443  return array(
1444  "result" => $result,
1445  "messages" => $messages,
1446  "edit_settings" => $edit_settings
1447  );
1448  }
1449 
1457  public function setStartDate($start_date = "")
1458  {
1459  $this->start_date = $start_date;
1460  }
1461 
1470  public function setStartDateAndTime($start_date = "", $start_time)
1471  {
1472  $y = '';
1473  $m = '';
1474  $d = '';
1475  $h = '';
1476  $i = '';
1477  $s = '';
1478  if (preg_match("/(\d{4})-(\d{2})-(\d{2})/", $start_date, $matches)) {
1479  $y = $matches[1];
1480  $m = $matches[2];
1481  $d = $matches[3];
1482  }
1483  if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $start_time, $matches)) {
1484  $h = $matches[1];
1485  $i = $matches[2];
1486  $s = $matches[3];
1487  }
1488  $this->start_date = sprintf('%04d%02d%02d%02d%02d%02d', $y, $m, $d, $h, $i, $s);
1489  }
1490 
1498  public function getEndDate()
1499  {
1500  return (strlen($this->end_date)) ? $this->end_date : null;
1501  }
1502 
1510  public function setEndDate($end_date = "")
1511  {
1512  $this->end_date = $end_date;
1513  }
1514 
1523  public function setEndDateAndTime($end_date = "", $end_time)
1524  {
1525  $y = '';
1526  $m = '';
1527  $d = '';
1528  $h = '';
1529  $i = '';
1530  $s = '';
1531  if (preg_match("/(\d{4})-(\d{2})-(\d{2})/", $end_date, $matches)) {
1532  $y = $matches[1];
1533  $m = $matches[2];
1534  $d = $matches[3];
1535  }
1536  if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $end_time, $matches)) {
1537  $h = $matches[1];
1538  $i = $matches[2];
1539  $s = $matches[3];
1540  }
1541  $this->end_date = sprintf('%04d%02d%02d%02d%02d%02d', $y, $m, $d, $h, $i, $s);
1542  }
1543 
1551  public function getEvaluationAccess()
1552  {
1553  return ($this->evaluation_access) ? $this->evaluation_access : self::EVALUATION_ACCESS_OFF;
1554  }
1555 
1563  public function setEvaluationAccess($evaluation_access = self::EVALUATION_ACCESS_OFF)
1564  {
1565  $this->evaluation_access = ($evaluation_access) ? $evaluation_access : self::EVALUATION_ACCESS_OFF;
1566  }
1567 
1568  public function setActivationVisibility($a_value)
1569  {
1570  $this->activation_visibility = (bool) $a_value;
1571  }
1572 
1573  public function getActivationVisibility()
1574  {
1576  }
1577 
1578  public function isActivationLimited()
1579  {
1580  return (bool) $this->activation_limited;
1581  }
1582 
1583  public function setActivationLimited($a_value)
1584  {
1585  $this->activation_limited = (bool) $a_value;
1586  }
1587 
1595  public function getIntroduction()
1596  {
1597  return (strlen($this->introduction)) ? $this->introduction : null;
1598  }
1599 
1607  public function getOutro()
1608  {
1609  return (strlen($this->outro)) ? $this->outro : null;
1610  }
1611 
1618  public function &getExistingQuestions()
1619  {
1620  $ilDB = $this->db;
1621  $existing_questions = array();
1622  $result = $ilDB->queryF(
1623  "SELECT svy_question.original_id FROM svy_question, svy_svy_qst WHERE " .
1624  "svy_svy_qst.survey_fi = %s AND svy_svy_qst.question_fi = svy_question.question_id",
1625  array('integer'),
1626  array($this->getSurveyId())
1627  );
1628  while ($data = $ilDB->fetchAssoc($result)) {
1629  if ($data["original_id"]) {
1630  array_push($existing_questions, $data["original_id"]);
1631  }
1632  }
1633  return $existing_questions;
1634  }
1635 
1642  public function &getQuestionpoolTitles($could_be_offline = false, $showPath = false)
1643  {
1644  return ilObjSurveyQuestionPool::_getAvailableQuestionpools($use_object_id = true, $could_be_offline, $showPath);
1645  }
1646 
1655  public function moveQuestions($move_questions, $target_index, $insert_mode)
1656  {
1657  $array_pos = array_search($target_index, $this->questions);
1658  if ($insert_mode == 0) {
1659  $part1 = array_slice($this->questions, 0, $array_pos);
1660  $part2 = array_slice($this->questions, $array_pos);
1661  } elseif ($insert_mode == 1) {
1662  $part1 = array_slice($this->questions, 0, $array_pos + 1);
1663  $part2 = array_slice($this->questions, $array_pos + 1);
1664  }
1665  $found = 0;
1666  foreach ($move_questions as $question_id) {
1667  if (!(array_search($question_id, $part1) === false)) {
1668  unset($part1[array_search($question_id, $part1)]);
1669  $found++;
1670  }
1671  if (!(array_search($question_id, $part2) === false)) {
1672  unset($part2[array_search($question_id, $part2)]);
1673  $found++;
1674  }
1675  }
1676  // sanity check: do not move questions if they have not be found in the array
1677  if ($found != count($move_questions)) {
1678  return;
1679  }
1680  $part1 = array_values($part1);
1681  $part2 = array_values($part2);
1682  $this->questions = array_values(array_merge($part1, $move_questions, $part2));
1683  foreach ($move_questions as $question_id) {
1684  $constraints = $this->getConstraints($question_id);
1685  foreach ($constraints as $idx => $constraint) {
1686  foreach ($part2 as $next_question_id) {
1687  if ($constraint["question"] == $next_question_id) {
1688  // constraint concerning a question that follows -> delete constraint
1689  $this->deleteConstraint($constraint["id"]);
1690  }
1691  }
1692  }
1693  }
1694  $this->saveQuestionsToDb();
1695  }
1696 
1703  public function removeQuestion($question_id)
1704  {
1705  $question = self::_instanciateQuestion($question_id);
1706  #20610 if no question found, do nothing.
1707  if ($question) {
1708  $question->delete($question_id);
1709  $this->removeConstraintsConcerningQuestion($question_id);
1710  }
1711  }
1712 
1719  public function removeConstraintsConcerningQuestion($question_id)
1720  {
1721  $ilDB = $this->db;
1722  $result = $ilDB->queryF(
1723  "SELECT constraint_fi FROM svy_qst_constraint WHERE question_fi = %s AND survey_fi = %s",
1724  array('integer','integer'),
1725  array($question_id, $this->getSurveyId())
1726  );
1727  if ($result->numRows() > 0) {
1728  $remove_constraints = array();
1729  while ($row = $ilDB->fetchAssoc($result)) {
1730  array_push($remove_constraints, $row["constraint_fi"]);
1731  }
1732  $affectedRows = $ilDB->manipulateF(
1733  "DELETE FROM svy_qst_constraint WHERE question_fi = %s AND survey_fi = %s",
1734  array('integer','integer'),
1735  array($question_id, $this->getSurveyId())
1736  );
1737  foreach ($remove_constraints as $key => $constraint_id) {
1738  $affectedRows = $ilDB->manipulateF(
1739  "DELETE FROM svy_constraint WHERE constraint_id = %s",
1740  array('integer'),
1741  array($constraint_id)
1742  );
1743  }
1744  }
1745  }
1746 
1754  public function removeQuestions($remove_questions, $remove_questionblocks)
1755  {
1756  $ilDB = $this->db;
1757 
1758  $block_sizes = array();
1759  foreach ($this->getSurveyQuestions() as $question_id => $data) {
1760  if (in_array($question_id, $remove_questions) or in_array($data["questionblock_id"], $remove_questionblocks)) {
1761  unset($this->questions[array_search($question_id, $this->questions)]);
1762  $this->removeQuestion($question_id);
1763  } elseif ($data["questionblock_id"]) {
1764  $block_sizes[$data["questionblock_id"]]++;
1765  }
1766  }
1767 
1768  // blocks with just 1 question need to be deleted
1769  foreach ($block_sizes as $block_id => $size) {
1770  if ($size < 2) {
1771  $remove_questionblocks[] = $block_id;
1772  }
1773  }
1774 
1775  foreach (array_unique($remove_questionblocks) as $questionblock_id) {
1776  $affectedRows = $ilDB->manipulateF(
1777  "DELETE FROM svy_qblk WHERE questionblock_id = %s",
1778  array('integer'),
1779  array($questionblock_id)
1780  );
1781  $affectedRows = $ilDB->manipulateF(
1782  "DELETE FROM svy_qblk_qst WHERE questionblock_fi = %s AND survey_fi = %s",
1783  array('integer','integer'),
1784  array($questionblock_id, $this->getSurveyId())
1785  );
1786  }
1787 
1788  $this->questions = array_values($this->questions);
1789  $this->saveQuestionsToDb();
1790  }
1791 
1798  public function unfoldQuestionblocks($questionblocks)
1799  {
1800  $ilDB = $this->db;
1801  foreach ($questionblocks as $index) {
1802  $affectedRows = $ilDB->manipulateF(
1803  "DELETE FROM svy_qblk WHERE questionblock_id = %s",
1804  array('integer'),
1805  array($index)
1806  );
1807  $affectedRows = $ilDB->manipulateF(
1808  "DELETE FROM svy_qblk_qst WHERE questionblock_fi = %s AND survey_fi = %s",
1809  array('integer','integer'),
1810  array($index, $this->getSurveyId())
1811  );
1812  }
1813  }
1814 
1815  public function removeQuestionFromBlock($question_id, $questionblock_id)
1816  {
1817  $ilDB = $this->db;
1818 
1819  $affectedRows = $ilDB->manipulateF(
1820  "DELETE FROM svy_qblk_qst WHERE questionblock_fi = %s AND survey_fi = %s AND question_fi = %s",
1821  array('integer','integer','integer'),
1822  array($questionblock_id, $this->getSurveyId(), $question_id)
1823  );
1824  }
1825 
1826  public function addQuestionToBlock($question_id, $questionblock_id)
1827  {
1828  $ilDB = $this->db;
1829 
1830  // see #22018
1831  if (!$this->isQuestionInAnyBlock($question_id)) {
1832  $next_id = $ilDB->nextId('svy_qblk_qst');
1833  $affectedRows = $ilDB->manipulateF(
1834  "INSERT INTO svy_qblk_qst (qblk_qst_id, survey_fi, questionblock_fi, " .
1835  "question_fi) VALUES (%s, %s, %s, %s)",
1836  array('integer', 'integer', 'integer', 'integer'),
1837  array($next_id, $this->getSurveyId(), $questionblock_id, $question_id)
1838  );
1839 
1840  $this->deleteConstraints($question_id); // #13713
1841  }
1842  }
1843 
1850  public function isQuestionInAnyBlock($a_question_fi)
1851  {
1852  global $DIC;
1853 
1854  $ilDB = $DIC->database();
1855 
1856  $set = $ilDB->query("SELECT * FROM svy_qblk_qst " .
1857  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
1858  " AND question_fi = " . $ilDB->quote($a_question_fi, "integer"));
1859  if ($rec = $ilDB->fetchAssoc($set)) {
1860  return true;
1861  }
1862  return false;
1863  }
1864 
1865 
1872  public function &getQuestionblockQuestions($questionblock_id)
1873  {
1874  $ilDB = $this->db;
1875  $titles = array();
1876  $result = $ilDB->queryF(
1877  "SELECT svy_question.title, svy_qblk_qst.question_fi, svy_qblk_qst.survey_fi FROM " .
1878  "svy_qblk, svy_qblk_qst, svy_question WHERE svy_qblk.questionblock_id = svy_qblk_qst.questionblock_fi AND " .
1879  "svy_question.question_id = svy_qblk_qst.question_fi AND svy_qblk.questionblock_id = %s",
1880  array('integer'),
1881  array($questionblock_id)
1882  );
1883  $survey_id = "";
1884  while ($row = $ilDB->fetchAssoc($result)) {
1885  $titles[$row["question_fi"]] = $row["title"];
1886  $survey_id = $row["survey_fi"];
1887  }
1888  $result = $ilDB->queryF(
1889  "SELECT question_fi, sequence FROM svy_svy_qst WHERE survey_fi = %s ORDER BY sequence",
1890  array('integer'),
1891  array($survey_id)
1892  );
1893  $resultarray = array();
1894  $counter = 1;
1895  while ($row = $ilDB->fetchAssoc($result)) {
1896  if (array_key_exists($row["question_fi"], $titles)) {
1897  $resultarray[$counter++] = $titles[$row["question_fi"]];
1898  }
1899  }
1900  return $resultarray;
1901  }
1902 
1909  public function &getQuestionblockQuestionIds($questionblock_id)
1910  {
1911  $ilDB = $this->db;
1912 
1913  // we need a correct order here, see #22011
1914  $result = $ilDB->queryF(
1915  "SELECT a.question_fi FROM svy_qblk_qst a JOIN svy_svy_qst b ON (a.question_fi = b.question_fi) " .
1916  " WHERE a.questionblock_fi = %s ORDER BY b.sequence",
1917  array("integer"),
1918  array($questionblock_id)
1919  );
1920  $ids = array();
1921  if ($result->numRows()) {
1922  while ($data = $ilDB->fetchAssoc($result)) {
1923  if (!in_array($data['question_fi'], $ids)) { // no duplicates, see #22018
1924  array_push($ids, $data['question_fi']);
1925  }
1926  }
1927  }
1928 
1929  return $ids;
1930  }
1931 
1939  public static function _getQuestionblock($questionblock_id)
1940  {
1941  global $DIC;
1942 
1943  $ilDB = $DIC->database();
1944  $result = $ilDB->queryF(
1945  "SELECT * FROM svy_qblk WHERE questionblock_id = %s",
1946  array('integer'),
1947  array($questionblock_id)
1948  );
1949  $row = $ilDB->fetchAssoc($result);
1950  return $row;
1951  }
1952 
1961  public static function _addQuestionblock($title = "", $owner = 0, $show_questiontext = true, $show_blocktitle = false)
1962  {
1963  global $DIC;
1964 
1965  $ilDB = $DIC->database();
1966  $next_id = $ilDB->nextId('svy_qblk');
1967  $ilDB->manipulateF(
1968  "INSERT INTO svy_qblk (questionblock_id, title, show_questiontext," .
1969  " show_blocktitle, owner_fi, tstamp) " .
1970  "VALUES (%s, %s, %s, %s, %s, %s)",
1971  array('integer','text','integer','integer','integer','integer'),
1972  array($next_id, $title, $show_questiontext, $show_blocktitle, $owner, time())
1973  );
1974  return $next_id;
1975  }
1976 
1984  public function createQuestionblock($title, $show_questiontext, $show_blocktitle, $questions)
1985  {
1986  $ilDB = $this->db;
1987 
1988  // if the selected questions are not in a continous selection, move all questions of the
1989  // questionblock at the position of the first selected question
1990  $this->moveQuestions($questions, $questions[0], 0);
1991 
1992  // now save the question block
1993  $ilUser = $this->user;
1994  $next_id = $ilDB->nextId('svy_qblk');
1995  $affectedRows = $ilDB->manipulateF(
1996  "INSERT INTO svy_qblk (questionblock_id, title, show_questiontext," .
1997  " show_blocktitle, owner_fi, tstamp) VALUES (%s, %s, %s, %s, %s, %s)",
1998  array('integer','text','text','text','integer','integer'),
1999  array($next_id, $title, $show_questiontext, $show_blocktitle, $ilUser->getId(), time())
2000  );
2001  if ($affectedRows) {
2002  $questionblock_id = $next_id;
2003  foreach ($questions as $index) {
2004  if (!$this->isQuestionInAnyBlock($index)) {
2005  $next_id = $ilDB->nextId('svy_qblk_qst'); // #22018
2006  $affectedRows = $ilDB->manipulateF(
2007  "INSERT INTO svy_qblk_qst (qblk_qst_id, survey_fi, questionblock_fi, " .
2008  "question_fi) VALUES (%s, %s, %s, %s)",
2009  array('integer', 'integer', 'integer', 'integer'),
2010  array($next_id, $this->getSurveyId(), $questionblock_id, $index)
2011  );
2012  $this->deleteConstraints($index);
2013  }
2014  }
2015  }
2016  }
2017 
2025  public function modifyQuestionblock($questionblock_id, $title, $show_questiontext, $show_blocktitle)
2026  {
2027  $ilDB = $this->db;
2028  $affectedRows = $ilDB->manipulateF(
2029  "UPDATE svy_qblk SET title = %s, show_questiontext = %s," .
2030  " show_blocktitle = %s WHERE questionblock_id = %s",
2031  array('text','text','text','integer'),
2032  array($title, $show_questiontext, $show_blocktitle, $questionblock_id)
2033  );
2034  }
2035 
2042  public function deleteConstraints($question_id)
2043  {
2044  $ilDB = $this->db;
2045  $result = $ilDB->queryF(
2046  "SELECT constraint_fi FROM svy_qst_constraint WHERE question_fi = %s AND survey_fi = %s",
2047  array('integer','integer'),
2048  array($question_id, $this->getSurveyId())
2049  );
2050  $constraints = array();
2051  while ($row = $ilDB->fetchAssoc($result)) {
2052  array_push($constraints, $row["constraint_fi"]);
2053  }
2054  foreach ($constraints as $constraint_id) {
2055  $this->deleteConstraint($constraint_id);
2056  }
2057  }
2058 
2066  public function deleteConstraint($constraint_id)
2067  {
2068  $ilDB = $this->db;
2069  $affectedRows = $ilDB->manipulateF(
2070  "DELETE FROM svy_constraint WHERE constraint_id = %s",
2071  array('integer'),
2072  array($constraint_id)
2073  );
2074  $affectedRows = $ilDB->manipulateF(
2075  "DELETE FROM svy_qst_constraint WHERE constraint_fi = %s",
2076  array('integer'),
2077  array($constraint_id)
2078  );
2079  }
2080 
2086  public function &getSurveyQuestions($with_answers = false)
2087  {
2088  $ilDB = $this->db;
2089  // get questionblocks
2090  $all_questions = array();
2091  $result = $ilDB->queryF(
2092  "SELECT svy_qtype.type_tag, svy_qtype.plugin, svy_question.question_id, " .
2093  "svy_svy_qst.heading FROM svy_qtype, svy_question, svy_svy_qst WHERE svy_svy_qst.survey_fi = %s AND " .
2094  "svy_svy_qst.question_fi = svy_question.question_id AND svy_question.questiontype_fi = svy_qtype.questiontype_id " .
2095  "ORDER BY svy_svy_qst.sequence",
2096  array('integer'),
2097  array($this->getSurveyId())
2098  );
2099  while ($row = $ilDB->fetchAssoc($result)) {
2100  $add = true;
2101  if ($row["plugin"]) {
2102  if (!$this->isPluginActive($row["type_tag"])) {
2103  $add = false;
2104  }
2105  }
2106  if ($add) {
2107  $question = self::_instanciateQuestion($row["question_id"]);
2108  $questionrow = $question->getQuestionDataArray($row["question_id"]);
2109  foreach ($row as $key => $value) {
2110  $questionrow[$key] = $value;
2111  }
2112  $all_questions[$row["question_id"]] = $questionrow;
2113  $all_questions[$row["question_id"]]["usableForPrecondition"] = $question->usableForPrecondition();
2114  $all_questions[$row["question_id"]]["availableRelations"] = $question->getAvailableRelations();
2115  }
2116  }
2117  // get all questionblocks
2118  $questionblocks = array();
2119  if (count($all_questions)) {
2120  $result = $ilDB->queryF(
2121  "SELECT svy_qblk.*, svy_qblk_qst.question_fi FROM svy_qblk, svy_qblk_qst WHERE " .
2122  "svy_qblk.questionblock_id = svy_qblk_qst.questionblock_fi AND svy_qblk_qst.survey_fi = %s " .
2123  "AND " . $ilDB->in('svy_qblk_qst.question_fi', array_keys($all_questions), false, 'integer'),
2124  array('integer'),
2125  array($this->getSurveyId())
2126  );
2127  while ($row = $ilDB->fetchAssoc($result)) {
2128  $questionblocks[$row['question_fi']] = $row;
2129  }
2130  }
2131 
2132  foreach ($all_questions as $question_id => $row) {
2133  $constraints = $this->getConstraints($question_id);
2134  if (isset($questionblocks[$question_id])) {
2135  $all_questions[$question_id]["questionblock_title"] = $questionblocks[$question_id]['title'];
2136  $all_questions[$question_id]["questionblock_id"] = $questionblocks[$question_id]['questionblock_id'];
2137  $all_questions[$question_id]["constraints"] = $constraints;
2138  } else {
2139  $all_questions[$question_id]["questionblock_title"] = "";
2140  $all_questions[$question_id]["questionblock_id"] = "";
2141  $all_questions[$question_id]["constraints"] = $constraints;
2142  }
2143  if ($with_answers) {
2144  $answers = array();
2145  $result = $ilDB->queryF(
2146  "SELECT svy_variable.*, svy_category.title FROM svy_variable, svy_category " .
2147  "WHERE svy_variable.question_fi = %s AND svy_variable.category_fi = svy_category.category_id " .
2148  "ORDER BY sequence ASC",
2149  array('integer'),
2150  array($question_id)
2151  );
2152  if ($result->numRows() > 0) {
2153  while ($data = $ilDB->fetchAssoc($result)) {
2154  array_push($answers, $data["title"]);
2155  }
2156  }
2157  $all_questions[$question_id]["answers"] = $answers;
2158  }
2159  }
2160  return $all_questions;
2161  }
2162 
2169  public function setObligatoryStates($obligatory_questions)
2170  {
2171  $ilDB = $this->db;
2172  $result = $ilDB->queryF(
2173  "SELECT * FROM svy_svy_qst WHERE survey_fi = %s",
2174  array('integer'),
2175  array($this->getSurveyId())
2176  );
2177  if ($result->numRows()) {
2178  while ($row = $ilDB->fetchAssoc($result)) {
2179  if (!array_key_exists($row["question_fi"], $obligatory_questions)) {
2180  $obligatory_questions[$row["question_fi"]] = 0;
2181  }
2182  }
2183  }
2184 
2185  // set the obligatory states in the database
2186  foreach ($obligatory_questions as $question_fi => $obligatory) {
2187  // #12420
2188  $ilDB->manipulate("UPDATE svy_question" .
2189  " SET obligatory = " . $ilDB->quote($obligatory, "integer") .
2190  " WHERE question_id = " . $ilDB->quote($question_fi, "integer"));
2191  }
2192  }
2193 
2199  public function &getSurveyPages()
2200  {
2201  $ilDB = $this->db;
2202  // get questionblocks
2203  $all_questions = array();
2204  $result = $ilDB->queryF(
2205  "SELECT svy_question.*, svy_qtype.type_tag, svy_svy_qst.heading FROM " .
2206  "svy_question, svy_qtype, svy_svy_qst WHERE svy_svy_qst.survey_fi = %s AND " .
2207  "svy_svy_qst.question_fi = svy_question.question_id AND svy_question.questiontype_fi = svy_qtype.questiontype_id " .
2208  "ORDER BY svy_svy_qst.sequence",
2209  array('integer'),
2210  array($this->getSurveyId())
2211  );
2212  while ($row = $ilDB->fetchAssoc($result)) {
2213  $all_questions[$row["question_id"]] = $row;
2214  }
2215  // get all questionblocks
2216  $questionblocks = array();
2217  if (count($all_questions)) {
2218  $result = $ilDB->queryF(
2219  "SELECT svy_qblk.*, svy_qblk_qst.question_fi FROM svy_qblk, svy_qblk_qst " .
2220  "WHERE svy_qblk.questionblock_id = svy_qblk_qst.questionblock_fi AND svy_qblk_qst.survey_fi = %s " .
2221  "AND " . $ilDB->in('svy_qblk_qst.question_fi', array_keys($all_questions), false, 'integer'),
2222  array('integer'),
2223  array($this->getSurveyId())
2224  );
2225  while ($row = $ilDB->fetchAssoc($result)) {
2226  $questionblocks[$row['question_fi']] = $row;
2227  }
2228  }
2229 
2230  $all_pages = array();
2231  $pageindex = -1;
2232  $currentblock = "";
2233  foreach ($all_questions as $question_id => $row) {
2234  $constraints = array();
2235  if (isset($questionblocks[$question_id])) {
2236  if (!$currentblock or ($currentblock != $questionblocks[$question_id]['questionblock_id'])) {
2237  $pageindex++;
2238  }
2239  $all_questions[$question_id]['page'] = $pageindex;
2240  $all_questions[$question_id]["questionblock_title"] = $questionblocks[$question_id]['title'];
2241  $all_questions[$question_id]["questionblock_id"] = $questionblocks[$question_id]['questionblock_id'];
2242  $all_questions[$question_id]["questionblock_show_questiontext"] = $questionblocks[$question_id]['show_questiontext'];
2243  $all_questions[$question_id]["questionblock_show_blocktitle"] = $questionblocks[$question_id]['show_blocktitle'];
2244  $currentblock = $questionblocks[$question_id]['questionblock_id'];
2245  $constraints = $this->getConstraints($question_id);
2246  $all_questions[$question_id]["constraints"] = $constraints;
2247  } else {
2248  $pageindex++;
2249  $all_questions[$question_id]['page'] = $pageindex;
2250  $all_questions[$question_id]["questionblock_title"] = "";
2251  $all_questions[$question_id]["questionblock_id"] = "";
2252  $all_questions[$question_id]["questionblock_show_questiontext"] = 1;
2253  $all_questions[$question_id]["questionblock_show_blocktitle"] = 1;
2254  $currentblock = "";
2255  $constraints = $this->getConstraints($question_id);
2256  $all_questions[$question_id]["constraints"] = $constraints;
2257  }
2258  if (!isset($all_pages[$pageindex])) {
2259  $all_pages[$pageindex] = array();
2260  }
2261  array_push($all_pages[$pageindex], $all_questions[$question_id]);
2262  }
2263  // calculate position percentage for every page
2264  $max = count($all_pages);
2265  $counter = 1;
2266  foreach ($all_pages as $index => $block) {
2267  foreach ($block as $blockindex => $question) {
2268  $all_pages[$index][$blockindex]["position"] = $counter / $max;
2269  }
2270  $counter++;
2271  }
2272 
2273  return $all_pages;
2274  }
2275 
2284  public function getNextPage($active_page_question_id, $direction)
2285  {
2286  $foundpage = -1;
2287  $pages = &$this->getSurveyPages();
2288  if (strcmp($active_page_question_id, "") == 0) {
2289  return $pages[0];
2290  }
2291  foreach ($pages as $key => $question_array) {
2292  foreach ($question_array as $question) {
2293  if ($active_page_question_id == $question["question_id"]) {
2294  $foundpage = $key;
2295  }
2296  }
2297  }
2298  if ($foundpage == -1) {
2299  // error: page not found
2300  } else {
2301  $foundpage += $direction;
2302  if ($foundpage < 0) {
2303  return 0;
2304  }
2305  if ($foundpage >= count($pages)) {
2306  return 1;
2307  }
2308  return $pages[$foundpage];
2309  }
2310  }
2311 
2318  public function &getAvailableQuestionpools($use_obj_id = false, $could_be_offline = false, $showPath = false, $permission = "read")
2319  {
2320  return ilObjSurveyQuestionPool::_getAvailableQuestionpools($use_obj_id, $could_be_offline, $showPath, $permission);
2321  }
2322 
2328  public function getPrecondition($id)
2329  {
2330  $ilDB = $this->db;
2331 
2332  $result_array = array();
2333  $result = $ilDB->queryF(
2334  "SELECT svy_constraint.*, svy_relation.*, svy_qst_constraint.question_fi ref_question_fi FROM svy_qst_constraint, svy_constraint, " .
2335  "svy_relation WHERE svy_constraint.relation_fi = svy_relation.relation_id AND " .
2336  "svy_qst_constraint.constraint_fi = svy_constraint.constraint_id AND svy_constraint.constraint_id = %s",
2337  array('integer'),
2338  array($id)
2339  );
2340  $pc = array();
2341  if ($result->numRows()) {
2342  $pc = $ilDB->fetchAssoc($result);
2343  }
2344  return $pc;
2345  }
2346 
2352  public function getConstraints($question_id)
2353  {
2354  $ilDB = $this->db;
2355 
2356  $result_array = array();
2357  $result = $ilDB->queryF(
2358  "SELECT svy_constraint.*, svy_relation.* FROM svy_qst_constraint, svy_constraint, svy_relation " .
2359  "WHERE svy_constraint.relation_fi = svy_relation.relation_id AND " .
2360  "svy_qst_constraint.constraint_fi = svy_constraint.constraint_id AND svy_qst_constraint.question_fi = %s " .
2361  "AND svy_qst_constraint.survey_fi = %s",
2362  array('integer','integer'),
2363  array($question_id, $this->getSurveyId())
2364  );
2365  while ($row = $ilDB->fetchAssoc($result)) {
2366  $question_type = SurveyQuestion::_getQuestionType($row["question_fi"]);
2367  SurveyQuestion::_includeClass($question_type);
2368  $question = new $question_type();
2369  $question->loadFromDb($row["question_fi"]);
2370  $valueoutput = $question->getPreconditionValueOutput($row["value"]);
2371  array_push($result_array, array("id" => $row["constraint_id"], "question" => $row["question_fi"], "short" => $row["shortname"], "long" => $row["longname"], "value" => $row["value"], "conjunction" => $row["conjunction"], "valueoutput" => $valueoutput));
2372  }
2373  return $result_array;
2374  }
2375 
2381  public static function _getConstraints($survey_id)
2382  {
2383  global $DIC;
2384 
2385  $ilDB = $DIC->database();
2386  $result_array = array();
2387  $result = $ilDB->queryF(
2388  "SELECT svy_qst_constraint.question_fi as for_question, svy_constraint.*, svy_relation.* " .
2389  "FROM svy_qst_constraint, svy_constraint, svy_relation WHERE svy_constraint.relation_fi = svy_relation.relation_id " .
2390  "AND svy_qst_constraint.constraint_fi = svy_constraint.constraint_id AND svy_qst_constraint.survey_fi = %s",
2391  array('integer'),
2392  array($survey_id)
2393  );
2394  while ($row = $ilDB->fetchAssoc($result)) {
2395  array_push($result_array, array("id" => $row["constraint_id"], "for_question" => $row["for_question"], "question" => $row["question_fi"], "short" => $row["shortname"], "long" => $row["longname"], "relation_id" => $row["relation_id"], "value" => $row["value"], 'conjunction' => $row['conjunction']));
2396  }
2397  return $result_array;
2398  }
2399 
2400 
2406  public function &getVariables($question_id)
2407  {
2408  $ilDB = $this->db;
2409 
2410  $result_array = array();
2411  $result = $ilDB->queryF(
2412  "SELECT svy_variable.*, svy_category.title FROM svy_variable LEFT JOIN " .
2413  "svy_category ON svy_variable.category_fi = svy_category.category_id WHERE svy_variable.question_fi = %s " .
2414  "ORDER BY svy_variable.sequence",
2415  array('integer'),
2416  array($question_id)
2417  );
2418  while ($row = $ilDB->fetchObject($result)) {
2419  $result_array[$row->sequence] = $row;
2420  }
2421  return $result_array;
2422  }
2423 
2432  public function addConstraint($if_question_id, $relation, $value, $conjunction)
2433  {
2434  $ilDB = $this->db;
2435 
2436  $next_id = $ilDB->nextId('svy_constraint');
2437  $affectedRows = $ilDB->manipulateF(
2438  "INSERT INTO svy_constraint (constraint_id, question_fi, relation_fi, value, conjunction) VALUES " .
2439  "(%s, %s, %s, %s, %s)",
2440  array('integer','integer','integer','float', 'integer'),
2441  array($next_id, $if_question_id, $relation, $value, $conjunction)
2442  );
2443  if ($affectedRows) {
2444  return $next_id;
2445  } else {
2446  return null;
2447  }
2448  }
2449 
2450 
2457  public function addConstraintToQuestion($to_question_id, $constraint_id)
2458  {
2459  $ilDB = $this->db;
2460 
2461  $next_id = $ilDB->nextId('svy_qst_constraint');
2462  $affectedRows = $ilDB->manipulateF(
2463  "INSERT INTO svy_qst_constraint (question_constraint_id, survey_fi, question_fi, " .
2464  "constraint_fi) VALUES (%s, %s, %s, %s)",
2465  array('integer','integer','integer','integer'),
2466  array($next_id, $this->getSurveyId(), $to_question_id, $constraint_id)
2467  );
2468  }
2469 
2480  public function updateConstraint($precondition_id, $if_question_id, $relation, $value, $conjunction)
2481  {
2482  $ilDB = $this->db;
2483  $affectedRows = $ilDB->manipulateF(
2484  "UPDATE svy_constraint SET question_fi = %s, relation_fi = %s, value = %s, conjunction = %s " .
2485  "WHERE constraint_id = %s",
2486  array('integer','integer','float','integer','integer'),
2487  array($if_question_id, $relation, $value, $conjunction, $precondition_id)
2488  );
2489  }
2490 
2491  public function updateConjunctionForQuestions($questions, $conjunction)
2492  {
2493  $ilDB = $this->db;
2494  foreach ($questions as $question_id) {
2495  $affectedRows = $ilDB->manipulateF(
2496  "UPDATE svy_constraint SET conjunction = %s " .
2497  "WHERE constraint_id IN (SELECT constraint_fi FROM svy_qst_constraint WHERE svy_qst_constraint.question_fi = %s)",
2498  array('integer','integer'),
2499  array($conjunction, $question_id)
2500  );
2501  }
2502  }
2503 
2509  public function getAllRelations($short_as_key = false)
2510  {
2511  $ilDB = $this->db;
2512 
2513  // #7987
2514  $custom_order = array("equal", "not_equal", "less", "less_or_equal", "more", "more_or_equal");
2515  $custom_order = array_flip($custom_order);
2516 
2517  $result_array = array();
2518  $result = $ilDB->query("SELECT * FROM svy_relation");
2519  while ($row = $ilDB->fetchAssoc($result)) {
2520  if ($short_as_key) {
2521  $result_array[$row["shortname"]] = array("short" => $row["shortname"], "long" => $row["longname"], "id" => $row["relation_id"], "order" => $custom_order[$row["longname"]]);
2522  } else {
2523  $result_array[$row["relation_id"]] = array("short" => $row["shortname"], "long" => $row["longname"], "order" => $custom_order[$row["longname"]]);
2524  }
2525  }
2526 
2527  $result_array = ilUtil::sortArray($result_array, "order", "ASC", true, true);
2528  foreach ($result_array as $idx => $item) {
2529  unset($result_array[$idx]["order"]);
2530  }
2531 
2532  return $result_array;
2533  }
2534 
2535 
2536 
2537 
2545  public function deleteWorkingData($question_id, $active_id)
2546  {
2547  $ilDB = $this->db;
2548 
2549  $affectedRows = $ilDB->manipulateF(
2550  "DELETE FROM svy_answer WHERE question_fi = %s AND active_fi = %s",
2551  array('integer','integer'),
2552  array($question_id, $active_id)
2553  );
2554  }
2555 
2564  public function loadWorkingData($question_id, $active_id)
2565  {
2566  $ilDB = $this->db;
2567  $result_array = array();
2568  $result = $ilDB->queryF(
2569  "SELECT * FROM svy_answer WHERE question_fi = %s AND active_fi = %s",
2570  array('integer','integer'),
2571  array($question_id, $active_id)
2572  );
2573  if ($result->numRows() >= 1) {
2574  while ($row = $ilDB->fetchAssoc($result)) {
2575  array_push($result_array, $row);
2576  }
2577  return $result_array;
2578  } else {
2579  return $result_array;
2580  }
2581  }
2582 
2589  public function startSurvey($user_id, $anonymous_id, $appraisee_id)
2590  {
2591  $ilDB = $this->db;
2592 
2593  if ($this->getAnonymize() && (strlen($anonymous_id) == 0)) {
2594  return;
2595  }
2596 
2597  if (strcmp($user_id, "") == 0) {
2598  if ($user_id == ANONYMOUS_USER_ID) {
2599  $user_id = 0;
2600  }
2601  }
2602  $next_id = $ilDB->nextId('svy_finished');
2603  $affectedRows = $ilDB->manipulateF(
2604  "INSERT INTO svy_finished (finished_id, survey_fi, user_fi, anonymous_id, state, tstamp, appr_id) " .
2605  "VALUES (%s, %s, %s, %s, %s, %s, %s)",
2606  array('integer','integer','integer','text','text','integer','integer'),
2607  array($next_id, $this->getSurveyId(), $user_id, $anonymous_id, 0, time(), $appraisee_id)
2608  );
2609  return $next_id;
2610  }
2611 
2618  public function finishSurvey($finished_id)
2619  {
2620  $ilDB = $this->db;
2621 
2622  $ilDB->manipulateF(
2623  "UPDATE svy_finished SET state = %s, tstamp = %s" .
2624  " WHERE survey_fi = %s AND finished_id = %s",
2625  array('text','integer','integer','integer'),
2626  array(1, time(), $this->getSurveyId(), $finished_id)
2627  );
2628 
2629  // self eval writes skills on finishing
2630  if ($this->getMode() == ilObjSurvey::MODE_SELF_EVAL) {
2631  $user = $this->getUserDataFromActiveId($finished_id);
2632  $sskill = new ilSurveySkill($this);
2633  $sskill->writeAndAddSelfEvalSkills($user['usr_id']);
2634  }
2635 
2636  $this->checkTutorNotification();
2637  }
2638 
2646  public function setPage($finished_id, $page_id)
2647  {
2648  $ilDB = $this->db;
2649 
2650  $affectedRows = $ilDB->manipulateF(
2651  "UPDATE svy_finished SET lastpage = %s WHERE finished_id = %s",
2652  array('integer','integer'),
2653  array(($page_id) ? $page_id : 0, $finished_id)
2654  );
2655  }
2656 
2662  public function sendNotificationMail($a_user_id, $a_anonymize_id, $a_appr_id)
2663  {
2664  // #12755
2665  $placeholders = array(
2666  "FIRST_NAME" => "firstname",
2667  "LAST_NAME" => "lastname",
2668  "LOGIN" => "login",
2669  // old style
2670  "firstname" => "firstname"
2671  );
2672 
2673  //mailaddresses is just text split by commas.
2674  //sendMail can send emails if it gets an user id or an email as first parameter.
2675  $recipients = preg_split('/,/', $this->mailaddresses);
2676  foreach ($recipients as $recipient) {
2677  // #11298
2678  $ntf = new ilSystemNotification();
2679  $ntf->setLangModules(array("survey"));
2680  $ntf->setRefId($this->getRefId());
2681  $ntf->setSubjectLangId('finished_mail_subject');
2682 
2683  $messagetext = $this->mailparticipantdata;
2684  if (trim($messagetext)) {
2685  if (!$this->hasAnonymizedResults()) {
2686  $data = ilObjUser::_getUserData(array($a_user_id));
2687  $data = $data[0];
2688  }
2689  foreach ($placeholders as $key => $mapping) {
2690  if ($this->hasAnonymizedResults()) { // #16480
2691  $messagetext = str_replace('[' . $key . ']', '', $messagetext);
2692  } else {
2693  $messagetext = str_replace('[' . $key . ']', trim($data[$mapping]), $messagetext);
2694  }
2695  }
2696  $ntf->setIntroductionDirect($messagetext);
2697  } else {
2698  $ntf->setIntroductionLangId('survey_notification_finished_introduction');
2699  }
2700 
2701  // 360°? add appraisee data
2702  if ($a_appr_id) {
2703  $ntf->addAdditionalInfo(
2704  'survey_360_appraisee',
2706  );
2707  }
2708 
2709  $active_id = $this->getActiveID($a_user_id, $a_anonymize_id, $a_appr_id);
2710  $ntf->addAdditionalInfo(
2711  'results',
2712  $this->getParticipantTextResults($active_id),
2713  true
2714  );
2715 
2716  $ntf->setGotoLangId('survey_notification_tutor_link');
2717  $ntf->setReasonLangId('survey_notification_finished_reason');
2718 
2719  if (is_numeric($recipient)) {
2720  $lng = $ntf->getUserLanguage($recipient);
2721  $ntf->sendMail(array($recipient), null, null);
2722  } else {
2723  $recipient = trim($recipient);
2724  $user_ids = ilObjUser::getUserIdsByEmail($recipient);
2725  if (empty($user_ids)) {
2726  $ntf->sendMail(array($recipient), null, null);
2727  } else {
2728  foreach ($user_ids as $user_id) {
2729  $lng = $ntf->getUserLanguage($user_id);
2730  $ntf->sendMail(array($user_id), null, null);
2731  }
2732  }
2733  }
2734  }
2735  }
2736 
2737  protected function getParticipantTextResults($active_id)
2738  {
2739  $textresult = "";
2740  $userResults = &$this->getUserSpecificResults(array($active_id));
2741  $questions = &$this->getSurveyQuestions(true);
2742  $questioncounter = 1;
2743  foreach ($questions as $question_id => $question_data) {
2744  $textresult .= $questioncounter++ . ". " . $question_data["title"] . "\n";
2745  $found = $userResults[$question_id][$active_id];
2746  $text = "";
2747  if (is_array($found)) {
2748  $text = implode("\n", $found);
2749  } else {
2750  $text = $found;
2751  }
2752  if (strlen($text) == 0) {
2753  $text = self::getSurveySkippedValue();
2754  }
2755  $text = str_replace("<br />", "\n", $text);
2756  $textresult .= $text . "\n\n";
2757  }
2758  return $textresult;
2759  }
2760 
2768  public function isSurveyStarted($user_id, $anonymize_id, $appr_id = 0)
2769  {
2770  $ilDB = $this->db;
2771 
2772  // #15031 - should not matter if code was used by registered or anonymous (each code must be unique)
2773  if ($anonymize_id) {
2774  $result = $ilDB->queryF(
2775  "SELECT * FROM svy_finished" .
2776  " WHERE survey_fi = %s AND anonymous_id = %s AND appr_id = %s",
2777  array('integer','text','integer'),
2778  array($this->getSurveyId(), $anonymize_id, $appr_id)
2779  );
2780  } else {
2781  $result = $ilDB->queryF(
2782  "SELECT * FROM svy_finished" .
2783  " WHERE survey_fi = %s AND user_fi = %s AND appr_id = %s",
2784  array('integer','integer','integer'),
2785  array($this->getSurveyId(), $user_id, $appr_id)
2786  );
2787  }
2788  if ($result->numRows() == 0) {
2789  return false;
2790  } else {
2791  $row = $ilDB->fetchAssoc($result);
2792  // yes, we are doing it this way
2793  $_SESSION["finished_id"][$this->getId()] = $row["finished_id"];
2794 
2795  return (int) $row["state"];
2796  }
2797  }
2798 
2806  public function getActiveID($user_id, $anonymize_id, $appr_id)
2807  {
2808  $ilDB = $this->db;
2809 
2810  // see self::isSurveyStarted()
2811 
2812  // #15031 - should not matter if code was used by registered or anonymous (each code must be unique)
2813  if ($anonymize_id) {
2814  $result = $ilDB->queryF(
2815  "SELECT finished_id FROM svy_finished" .
2816  " WHERE survey_fi = %s AND anonymous_id = %s AND appr_id = %s",
2817  array('integer','text','integer'),
2818  array($this->getSurveyId(), $anonymize_id, $appr_id)
2819  );
2820  } else {
2821  $result = $ilDB->queryF(
2822  "SELECT finished_id FROM svy_finished" .
2823  " WHERE survey_fi = %s AND user_fi = %s AND appr_id = %s",
2824  array('integer','integer','integer'),
2825  array($this->getSurveyId(), $user_id, $appr_id)
2826  );
2827  }
2828  if ($result->numRows() == 0) {
2829  return false;
2830  } else {
2831  $row = $ilDB->fetchAssoc($result);
2832  return $row["finished_id"];
2833  }
2834  }
2835 
2843  public function getLastActivePage($active_id)
2844  {
2845  $ilDB = $this->db;
2846  $result = $ilDB->queryF(
2847  "SELECT lastpage FROM svy_finished WHERE finished_id = %s",
2848  array('integer'),
2849  array($active_id)
2850  );
2851  if ($result->numRows() == 0) {
2852  return "";
2853  } else {
2854  $row = $ilDB->fetchAssoc($result);
2855  return ($row["lastpage"]) ? $row["lastpage"] : '';
2856  }
2857  }
2858 
2867  public function checkConstraint($constraint_data, $working_data)
2868  {
2869  if (!is_array($working_data) || count($working_data) == 0) {
2870  return 0;
2871  }
2872 
2873  if ((count($working_data) == 1) and (strcmp($working_data[0]["value"], "") == 0)) {
2874  return 0;
2875  }
2876 
2877  $found = false;
2878  foreach ($working_data as $data) {
2879  switch ($constraint_data["short"]) {
2880  case "<":
2881  if ($data["value"] < $constraint_data["value"]) {
2882  $found = true;
2883  }
2884  break;
2885 
2886  case "<=":
2887  if ($data["value"] <= $constraint_data["value"]) {
2888  $found = true;
2889  }
2890  break;
2891 
2892  case "=":
2893  if ($data["value"] == $constraint_data["value"]) {
2894  $found = true;
2895  }
2896  break;
2897 
2898  case "<>":
2899  if ($data["value"] <> $constraint_data["value"]) {
2900  $found = true;
2901  }
2902  break;
2903 
2904  case ">=":
2905  if ($data["value"] >= $constraint_data["value"]) {
2906  $found = true;
2907  }
2908  break;
2909 
2910  case ">":
2911  if ($data["value"] > $constraint_data["value"]) {
2912  $found = true;
2913  }
2914  break;
2915  }
2916  if ($found) {
2917  break;
2918  }
2919  }
2920 
2921  return (int) $found;
2922  }
2923 
2924  public static function _hasDatasets($survey_id)
2925  {
2926  global $DIC;
2927 
2928  $ilDB = $DIC->database();
2929 
2930  $result = $ilDB->queryF(
2931  "SELECT finished_id FROM svy_finished WHERE survey_fi = %s",
2932  array('integer'),
2933  array($survey_id)
2934  );
2935  return ($result->numRows()) ? true : false;
2936  }
2937 
2944  public function &getSurveyFinishedIds()
2945  {
2946  $ilDB = $this->db;
2947  $ilLog = $this->log;
2948 
2949  $users = array();
2950  $result = $ilDB->queryF(
2951  "SELECT * FROM svy_finished WHERE survey_fi = %s",
2952  array('integer'),
2953  array($this->getSurveyId())
2954  );
2955  if ($result->numRows()) {
2956  while ($row = $ilDB->fetchAssoc($result)) {
2957  array_push($users, $row["finished_id"]);
2958  }
2959  }
2960  return $users;
2961  }
2962 
2969  public function getUserSpecificResults($finished_ids)
2970  {
2971  $evaluation = array();
2972 
2973  foreach (array_keys($this->getSurveyQuestions()) as $question_id) {
2974  // get question instance
2975  $question_type = SurveyQuestion::_getQuestionType($question_id);
2976  SurveyQuestion::_includeClass($question_type);
2977  $question = new $question_type();
2978  $question->loadFromDb($question_id);
2979 
2980  $q_eval = SurveyQuestion::_instanciateQuestionEvaluation($question_id, $finished_ids);
2981  $q_res = $q_eval->getResults();
2982 
2983  $data = array();
2984  foreach ($finished_ids as $user_id) {
2985  $data[$user_id] = $q_eval->parseUserSpecificResults($q_res, $user_id);
2986  }
2987 
2988  $evaluation[$question_id] = $data;
2989  }
2990 
2991  return $evaluation;
2992  }
2993 
3001  public function getUserDataFromActiveId($active_id, $force_non_anonymous = false)
3002  {
3003  $ilDB = $this->db;
3004 
3005  $surveySetting = new ilSetting("survey");
3006  $use_anonymous_id = $surveySetting->get("use_anonymous_id");
3007  $result = $ilDB->queryF(
3008  "SELECT * FROM svy_finished WHERE finished_id = %s",
3009  array('integer'),
3010  array($active_id)
3011  );
3012  $row = array();
3013  $foundrows = $result->numRows();
3014  if ($foundrows) {
3015  $row = $ilDB->fetchAssoc($result);
3016  }
3017  $name = ($use_anonymous_id) ? $row["anonymous_id"] : $this->lng->txt("anonymous");
3018  $userdata = array(
3019  "fullname" => $name,
3020  "sortname" => $name,
3021  "firstname" => "",
3022  "lastname" => "",
3023  "login" => "",
3024  "gender" => "",
3025  "active_id" => "$active_id"
3026  );
3027  if ($foundrows) {
3028  if (($row["user_fi"] > 0) &&
3029  (($row["user_fi"] != ANONYMOUS_USER_ID &&
3030  !$this->hasAnonymizedResults() &&
3031  !$this->get360Mode()) || // 360° uses ANONYMIZE_CODE_ALL which is wrong - see ilObjSurveyGUI::afterSave()
3032  (bool) $force_non_anonymous)) {
3033  if (strlen(ilObjUser::_lookupLogin($row["user_fi"])) == 0) {
3034  $userdata["fullname"] = $userdata["sortname"] = $this->lng->txt("deleted_user");
3035  } else {
3036  $user = new ilObjUser($row["user_fi"]);
3037  $userdata['usr_id'] = $row['user_fi'];
3038  $userdata["fullname"] = $user->getFullname();
3039  $gender = $user->getGender();
3040  if (strlen($gender) == 1) {
3041  $gender = $this->lng->txt("gender_$gender");
3042  }
3043  $userdata["gender"] = $gender;
3044  $userdata["firstname"] = $user->getFirstname();
3045  $userdata["lastname"] = $user->getLastname();
3046  $userdata["sortname"] = $user->getLastname() . ", " . $user->getFirstname();
3047  $userdata["login"] = $user->getLogin();
3048  }
3049  }
3050  }
3051  return $userdata;
3052  }
3053 
3063  public function &getEvaluationByUser($questions, $active_id)
3064  {
3065  $ilDB = $this->db;
3066 
3067  // collect all answers
3068  $answers = array();
3069  $result = $ilDB->queryF(
3070  "SELECT * FROM svy_answer WHERE active_fi = %s",
3071  array('integer'),
3072  array($active_id)
3073  );
3074  while ($row = $ilDB->fetchAssoc($result)) {
3075  if (!is_array($answers[$row["question_fi"]])) {
3076  $answers[$row["question_fi"]] = array();
3077  }
3078  array_push($answers[$row["question_fi"]], $row);
3079  }
3080  $userdata = $this->getUserDataFromActiveId($active_id);
3081  $resultset = array(
3082  "name" => $userdata["fullname"],
3083  "firstname" => $userdata["firstname"],
3084  "lastname" => $userdata["lastname"],
3085  "login" => $userdata["login"],
3086  "gender" => $userdata["gender"],
3087  "answers" => array()
3088  );
3089  foreach ($questions as $key => $question) {
3090  if (array_key_exists($key, $answers)) {
3091  $resultset["answers"][$key] = $answers[$key];
3092  } else {
3093  $resultset["answers"][$key] = array();
3094  }
3095  sort($resultset["answers"][$key]);
3096  }
3097  return $resultset;
3098  }
3099 
3105  public function getQuestionsTable($arrFilter)
3106  {
3107  $ilUser = $this->user;
3108  $ilDB = $this->db;
3109  $where = "";
3110  if (is_array($arrFilter)) {
3111  if (array_key_exists('title', $arrFilter) && strlen($arrFilter['title'])) {
3112  $where .= " AND " . $ilDB->like('svy_question.title', 'text', "%%" . $arrFilter['title'] . "%%");
3113  }
3114  if (array_key_exists('description', $arrFilter) && strlen($arrFilter['description'])) {
3115  $where .= " AND " . $ilDB->like('svy_question.description', 'text', "%%" . $arrFilter['description'] . "%%");
3116  }
3117  if (array_key_exists('author', $arrFilter) && strlen($arrFilter['author'])) {
3118  $where .= " AND " . $ilDB->like('svy_question.author', 'text', "%%" . $arrFilter['author'] . "%%");
3119  }
3120  if (array_key_exists('type', $arrFilter) && strlen($arrFilter['type'])) {
3121  $where .= " AND svy_qtype.type_tag = " . $ilDB->quote($arrFilter['type'], 'text');
3122  }
3123  if (array_key_exists('spl', $arrFilter) && strlen($arrFilter['spl'])) {
3124  $where .= " AND svy_question.obj_fi = " . $ilDB->quote($arrFilter['spl'], 'integer');
3125  }
3126  }
3127 
3128  $spls = &$this->getAvailableQuestionpools($use_obj_id = true, $could_be_offline = false, $showPath = false);
3129  $forbidden = "";
3130  $forbidden = " AND " . $ilDB->in('svy_question.obj_fi', array_keys($spls), false, 'integer');
3131  $forbidden .= " AND svy_question.complete = " . $ilDB->quote("1", 'text');
3132  $existing = "";
3133  $existing_questions = &$this->getExistingQuestions();
3134  if (count($existing_questions)) {
3135  $existing = " AND " . $ilDB->in('svy_question.question_id', $existing_questions, true, 'integer');
3136  }
3137 
3139 
3140  $query_result = $ilDB->query("SELECT svy_question.*, svy_qtype.type_tag, svy_qtype.plugin, object_reference.ref_id" .
3141  " FROM svy_question, svy_qtype, object_reference" .
3142  " WHERE svy_question.original_id IS NULL" . $forbidden . $existing .
3143  " AND svy_question.obj_fi = object_reference.obj_id AND svy_question.tstamp > 0" .
3144  " AND svy_question.questiontype_fi = svy_qtype.questiontype_id " . $where);
3145 
3146  $rows = array();
3147  if ($query_result->numRows()) {
3148  while ($row = $ilDB->fetchAssoc($query_result)) {
3149  if (array_key_exists('spl_txt', $arrFilter) && strlen($arrFilter['spl_txt'])) {
3150  if (!stristr($spls[$row["obj_fi"]], $arrFilter['spl_txt'])) {
3151  continue;
3152  }
3153  }
3154 
3155  $row['ttype'] = $trans[$row['type_tag']];
3156  if ($row["plugin"]) {
3157  if ($this->isPluginActive($row["type_tag"])) {
3158  array_push($rows, $row);
3159  }
3160  } else {
3161  array_push($rows, $row);
3162  }
3163  }
3164  }
3165  return $rows;
3166  }
3167 
3173  public function getQuestionblocksTable($arrFilter)
3174  {
3175  $ilUser = $this->user;
3176  $ilDB = $this->db;
3177 
3178  $where = "";
3179  if (is_array($arrFilter)) {
3180  if (array_key_exists('title', $arrFilter) && strlen($arrFilter['title'])) {
3181  $where .= " AND " . $ilDB->like('svy_qblk.title', 'text', "%%" . $arrFilter['title'] . "%%");
3182  }
3183  }
3184 
3185  $query_result = $ilDB->query("SELECT svy_qblk.*, svy_svy.obj_fi FROM svy_qblk , svy_qblk_qst, svy_svy WHERE " .
3186  "svy_qblk.questionblock_id = svy_qblk_qst.questionblock_fi AND svy_svy.survey_id = svy_qblk_qst.survey_fi " .
3187  "$where GROUP BY svy_qblk.questionblock_id, svy_qblk.title, svy_qblk.show_questiontext, svy_qblk.show_blocktitle, " .
3188  "svy_qblk.owner_fi, svy_qblk.tstamp, svy_svy.obj_fi");
3189  $rows = array();
3190  if ($query_result->numRows()) {
3191  $survey_ref_ids = ilUtil::_getObjectsByOperations("svy", "write");
3192  $surveytitles = array();
3193  foreach ($survey_ref_ids as $survey_ref_id) {
3194  $survey_id = ilObject::_lookupObjId($survey_ref_id);
3195  $surveytitles[$survey_id] = ilObject::_lookupTitle($survey_id);
3196  }
3197  while ($row = $ilDB->fetchAssoc($query_result)) {
3198  $questions_array = &$this->getQuestionblockQuestions($row["questionblock_id"]);
3199  $counter = 1;
3200  foreach ($questions_array as $key => $value) {
3201  $questions_array[$key] = "$counter. $value";
3202  $counter++;
3203  }
3204  if (strlen($surveytitles[$row["obj_fi"]])) { // only questionpools which are not in trash
3205  $rows[$row["questionblock_id"]] = array(
3206  "questionblock_id" => $row["questionblock_id"],
3207  "title" => $row["title"],
3208  "svy" => $surveytitles[$row["obj_fi"]],
3209  "contains" => join(", ", $questions_array),
3210  "owner" => $row["owner_fi"]
3211  );
3212  }
3213  }
3214  }
3215  return $rows;
3216  }
3217 
3224  public function toXML()
3225  {
3226  $a_xml_writer = new ilXmlWriter;
3227  // set xml header
3228  $a_xml_writer->xmlHeader();
3229  $attrs = array(
3230  "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
3231  "xsi:noNamespaceSchemaLocation" => "http://www.ilias.de/download/xsd/ilias_survey_4_2.xsd"
3232  );
3233  $a_xml_writer->xmlStartTag("surveyobject", $attrs);
3234  $attrs = array(
3235  "id" => $this->getSurveyId(),
3236  "title" => $this->getTitle()
3237  );
3238  $a_xml_writer->xmlStartTag("survey", $attrs);
3239 
3240  $a_xml_writer->xmlElement("description", null, $this->getDescription());
3241  $a_xml_writer->xmlElement("author", null, $this->getAuthor());
3242  $a_xml_writer->xmlStartTag("objectives");
3243  $attrs = array(
3244  "label" => "introduction"
3245  );
3246  $this->addMaterialTag($a_xml_writer, $this->getIntroduction(), true, true, $attrs);
3247  $attrs = array(
3248  "label" => "outro"
3249  );
3250  $this->addMaterialTag($a_xml_writer, $this->getOutro(), true, true, $attrs);
3251  $a_xml_writer->xmlEndTag("objectives");
3252 
3253  if ($this->getAnonymize()) {
3254  $attribs = array("enabled" => "1");
3255  } else {
3256  $attribs = array("enabled" => "0");
3257  }
3258  $a_xml_writer->xmlElement("anonymisation", $attribs);
3259  $a_xml_writer->xmlStartTag("restrictions");
3260  if ($this->getAnonymize() == 2) {
3261  $attribs = array("type" => "free");
3262  } else {
3263  $attribs = array("type" => "restricted");
3264  }
3265  $a_xml_writer->xmlElement("access", $attribs);
3266  if ($this->getStartDate()) {
3267  $attrs = array("type" => "date");
3268  preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getStartDate(), $matches);
3269  $a_xml_writer->xmlElement("startingtime", $attrs, sprintf("%04d-%02d-%02dT%02d:%02d:00", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
3270  }
3271  if ($this->getEndDate()) {
3272  $attrs = array("type" => "date");
3273  preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndDate(), $matches);
3274  $a_xml_writer->xmlElement("endingtime", $attrs, sprintf("%04d-%02d-%02dT%02d:%02d:00", $matches[1], $matches[2], $matches[3], $matches[4], $matches[5], $matches[6]));
3275  }
3276  $a_xml_writer->xmlEndTag("restrictions");
3277 
3278  // constraints
3279  $pages = &$this->getSurveyPages();
3280  $hasconstraints = false;
3281  foreach ($pages as $question_array) {
3282  foreach ($question_array as $question) {
3283  if (count($question["constraints"])) {
3284  $hasconstraints = true;
3285  }
3286  }
3287  }
3288 
3289  if ($hasconstraints) {
3290  $a_xml_writer->xmlStartTag("constraints");
3291  foreach ($pages as $question_array) {
3292  foreach ($question_array as $question) {
3293  if (count($question["constraints"])) {
3294  // found constraints
3295  foreach ($question["constraints"] as $constraint) {
3296  $attribs = array(
3297  "sourceref" => $question["question_id"],
3298  "destref" => $constraint["question"],
3299  "relation" => $constraint["short"],
3300  "value" => $constraint["value"],
3301  "conjunction" => $constraint["conjunction"]
3302  );
3303  $a_xml_writer->xmlElement("constraint", $attribs);
3304  }
3305  }
3306  }
3307  }
3308  $a_xml_writer->xmlEndTag("constraints");
3309  }
3310 
3311  // add the rest of the preferences in qtimetadata tags, because there is no correspondent definition in QTI
3312  $a_xml_writer->xmlStartTag("metadata");
3313 
3314  $custom_properties = array();
3315  $custom_properties["evaluation_access"] = $this->getEvaluationAccess();
3316  $custom_properties["status"] = !$this->getOfflineStatus();
3317  $custom_properties["display_question_titles"] = $this->getShowQuestionTitles();
3318  $custom_properties["pool_usage"] = (int) $this->getPoolUsage();
3319 
3320  $custom_properties["own_results_view"] = (int) $this->hasViewOwnResults();
3321  $custom_properties["own_results_mail"] = (int) $this->hasMailOwnResults();
3322  $custom_properties["confirmation_mail"] = (int) $this->hasMailConfirmation();
3323 
3324  $custom_properties["anon_user_list"] = (int) $this->hasAnonymousUserList();
3325  $custom_properties["mode"] = (int) $this->getMode();
3326  $custom_properties["mode_360_self_eval"] = (int) $this->get360SelfEvaluation();
3327  $custom_properties["mode_360_self_rate"] = (int) $this->get360SelfRaters();
3328  $custom_properties["mode_360_self_appr"] = (int) $this->get360SelfAppraisee();
3329  $custom_properties["mode_360_results"] = $this->get360Results();
3330  $custom_properties["mode_skill_service"] = (int) $this->getSkillService();
3331  $custom_properties["mode_self_eval_results"] = (int) $this->getSelfEvaluationResults();
3332 
3333 
3334  // :TODO: skills?
3335 
3336  // reminder/tutor notification are (currently?) not exportable
3337 
3338  foreach ($custom_properties as $label => $value) {
3339  $a_xml_writer->xmlStartTag("metadatafield");
3340  $a_xml_writer->xmlElement("fieldlabel", null, $label);
3341  $a_xml_writer->xmlElement("fieldentry", null, $value);
3342  $a_xml_writer->xmlEndTag("metadatafield");
3343  }
3344 
3345  $a_xml_writer->xmlStartTag("metadatafield");
3346  $a_xml_writer->xmlElement("fieldlabel", null, "SCORM");
3347  $md = new ilMD($this->getId(), 0, $this->getType());
3348  $writer = new ilXmlWriter();
3349  $md->toXml($writer);
3350  $metadata = $writer->xmlDumpMem();
3351  $a_xml_writer->xmlElement("fieldentry", null, $metadata);
3352  $a_xml_writer->xmlEndTag("metadatafield");
3353 
3354  $a_xml_writer->xmlEndTag("metadata");
3355  $a_xml_writer->xmlEndTag("survey");
3356 
3357  $attribs = array("id" => $this->getId());
3358  $a_xml_writer->xmlStartTag("surveyquestions", $attribs);
3359  // add questionblock descriptions
3360  foreach ($pages as $question_array) {
3361  if (count($question_array) > 1) {
3362  $attribs = array("id" => $question_array[0]["question_id"]);
3363  $attribs = array("showQuestiontext" => $question_array[0]["questionblock_show_questiontext"],
3364  "showBlocktitle" => $question_array[0]["questionblock_show_blocktitle"]);
3365  $a_xml_writer->xmlStartTag("questionblock", $attribs);
3366  if (strlen($question_array[0]["questionblock_title"])) {
3367  $a_xml_writer->xmlElement("questionblocktitle", null, $question_array[0]["questionblock_title"]);
3368  }
3369  }
3370  foreach ($question_array as $question) {
3371  if (strlen($question["heading"])) {
3372  $a_xml_writer->xmlElement("textblock", null, $question["heading"]);
3373  }
3374  $questionObject = self::_instanciateQuestion($question["question_id"]);
3375  //questionObject contains all the fields from the database. (loadFromDb)
3376  //we don't need the value from svy_qst_oblig table, we already have the values from svy_question table.
3377  //if ($questionObject !== FALSE) $questionObject->insertXML($a_xml_writer, FALSE, $obligatory_states[$question["question_id"]]);
3378  if ($questionObject !== false) {
3379  $questionObject->insertXML($a_xml_writer, false);
3380  }
3381  }
3382  if (count($question_array) > 1) {
3383  $a_xml_writer->xmlEndTag("questionblock");
3384  }
3385  }
3386 
3387  $a_xml_writer->xmlEndTag("surveyquestions");
3388  $a_xml_writer->xmlEndTag("surveyobject");
3389  $xml = $a_xml_writer->xmlDumpMem(false);
3390  return $xml;
3391  }
3392 
3400  public static function _instanciateQuestion($question_id)
3401  {
3402  if ($question_id < 1) {
3403  return false;
3404  }
3405  $question_type = SurveyQuestion::_getQuestionType($question_id);
3406  if (strlen($question_type) == 0) {
3407  return false;
3408  }
3409  SurveyQuestion::_includeClass($question_type);
3410  $question = new $question_type();
3411  $question->loadFromDb($question_id);
3412  return $question;
3413  }
3414 
3421  public function locateImportFiles($a_dir)
3422  {
3423  if (!is_dir($a_dir) || is_int(strpos($a_dir, ".."))) {
3424  return;
3425  }
3426  $importDirectory = "";
3427  $xmlFile = "";
3428 
3429  $current_dir = opendir($a_dir);
3430  $files = array();
3431  while ($entryname = readdir($current_dir)) {
3432  $files[] = $entryname;
3433  }
3434 
3435  foreach ($files as $file) {
3436  if (is_dir($a_dir . "/" . $file) and ($file != "." and $file != "..")) {
3437  // found directory created by zip
3438  $importDirectory = $a_dir . "/" . $file;
3439  }
3440  }
3441  closedir($current_dir);
3442  if (strlen($importDirectory)) {
3443  // find the xml file
3444  $current_dir = opendir($importDirectory);
3445  $files = array();
3446  while ($entryname = readdir($current_dir)) {
3447  $files[] = $entryname;
3448  }
3449  foreach ($files as $file) {
3450  if (@is_file($importDirectory . "/" . $file) &&
3451  ($file != "." && $file != "..") &&
3452  (preg_match("/^[0-9]{10}__[0-9]+__(svy_)*[0-9]+\.[A-Za-z]{1,3}$/", $file) ||
3453  preg_match("/^[0-9]{10}__[0-9]+__(survey__)*[0-9]+\.[A-Za-z]{1,3}$/", $file))) {
3454  // found xml file
3455  $xmlFile = $importDirectory . "/" . $file;
3456  }
3457  }
3458  }
3459  return array("dir" => $importDirectory, "xml" => $xmlFile);
3460  }
3461 
3470  public function importObject($file_info, $svy_qpl_id)
3471  {
3472  if ($svy_qpl_id < 1) {
3473  $svy_qpl_id = -1;
3474  }
3475  // check if file was uploaded
3476  $source = $file_info["tmp_name"];
3477  $error = "";
3478  if (($source == 'none') || (!$source) || $file_info["error"] > UPLOAD_ERR_OK) {
3479  $error = $this->lng->txt("import_no_file_selected");
3480  }
3481  // check correct file type
3482  $isXml = false;
3483  $isZip = false;
3484  if ((strcmp($file_info["type"], "text/xml") == 0) || (strcmp($file_info["type"], "application/xml") == 0)) {
3485  $this->log->debug("isXML");
3486  $isXml = true;
3487  }
3488  // too many different mime-types, so we use the suffix
3489  $suffix = pathinfo($file_info["name"]);
3490  if (strcmp(strtolower($suffix["extension"]), "zip") == 0) {
3491  $this->log->debug("isZip");
3492  $isZip = true;
3493  }
3494  if (!$isXml && !$isZip) {
3495  $error = $this->lng->txt("import_wrong_file_type");
3496  $this->log->debug("Survey: Import error. Filetype was \"" . $file_info["type"] . "\"");
3497  }
3498  if (strlen($error) == 0) {
3499  // import file as a survey
3500  $import_dir = $this->getImportDirectory();
3501  $import_subdir = "";
3502  $importfile = "";
3503  if ($isZip) {
3504  $importfile = $import_dir . "/" . $file_info["name"];
3505  ilUtil::moveUploadedFile($source, $file_info["name"], $importfile);
3506  ilUtil::unzip($importfile);
3507  $found = $this->locateImportFiles($import_dir);
3508  if (!((strlen($found["dir"]) > 0) && (strlen($found["xml"]) > 0))) {
3509  $error = $this->lng->txt("wrong_import_file_structure");
3510  return $error;
3511  }
3512  $importfile = $found["xml"];
3513  $import_subdir = $found["dir"];
3514  } else {
3515  $importfile = tempnam($import_dir, "survey_import");
3516  ilUtil::moveUploadedFile($source, $file_info["name"], $importfile);
3517  }
3518 
3519  $this->log->debug("Import file = $importfile");
3520  $this->log->debug("Import subdir = $import_subdir");
3521 
3522  $fh = fopen($importfile, "r");
3523  if (!$fh) {
3524  $error = $this->lng->txt("import_error_opening_file");
3525  return $error;
3526  }
3527  $xml = fread($fh, filesize($importfile));
3528  $result = fclose($fh);
3529  if (!$result) {
3530  $error = $this->lng->txt("import_error_closing_file");
3531  return $error;
3532  }
3533 
3534  unset($_SESSION["import_mob_xhtml"]);
3535  if (strpos($xml, "questestinterop")) {
3536  throw new ilInvalidSurveyImportFileException("Unsupported survey version (< 3.8) found.");
3537  } else {
3538  $this->log->debug("survey id = " . $this->getId());
3539  $this->log->debug("question pool id = " . $svy_qpl_id);
3540 
3541  $imp = new ilImport();
3542  $config = $imp->getConfig("Modules/Survey");
3543  $config->setQuestionPoolID($svy_qpl_id);
3544  $imp->getMapping()->addMapping("Modules/Survey", "svy", 0, $this->getId());
3545  $imp->importFromDirectory($import_subdir, "svy", "Modules/Survey");
3546  $this->log->debug("config(Modules/survey)->getQuestionPoolId =" . $config->getQuestionPoolID());
3547  return "";
3548 
3549  //old code
3550  $import = new SurveyImportParser($svy_qpl_id, "", true);
3551  $import->setSurveyObject($this);
3552  $import->setXMLContent($xml);
3553  $import->startParsing();
3554  }
3555 
3556  if (is_array($_SESSION["import_mob_xhtml"])) {
3557  foreach ($_SESSION["import_mob_xhtml"] as $mob) {
3558  $importfile = $import_subdir . "/" . $mob["uri"];
3559  if (file_exists($importfile)) {
3560  if (!$mob["type"]) {
3561  $mob["type"] = "svy:html";
3562  }
3563 
3564  $media_object = ilObjMediaObject::_saveTempFileAsMediaObject(basename($importfile), $importfile, false);
3565 
3566  // survey mob
3567  if ($mob["type"] == "svy:html") {
3568  ilObjMediaObject::_saveUsage($media_object->getId(), "svy:html", $this->getId());
3569  $this->setIntroduction(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getIntroduction()));
3570  $this->setOutro(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getOutro()));
3571  }
3572  // question mob
3573  elseif ($import->questions[$mob["id"]]) {
3574  $new_qid = $import->questions[$mob["id"]];
3575  ilObjMediaObject::_saveUsage($media_object->getId(), $mob["type"], $new_qid);
3576  $new_question = SurveyQuestion::_instanciateQuestion($new_qid);
3577  $qtext = $new_question->getQuestiontext();
3578  $qtext = ilRTE::_replaceMediaObjectImageSrc($qtext, 0);
3579  $qtext = str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $qtext);
3580  $qtext = ilRTE::_replaceMediaObjectImageSrc($qtext, 1);
3581  $new_question->setQuestiontext($qtext);
3582  $new_question->saveToDb();
3583 
3584  // also fix existing original in pool
3585  if ($new_question->getOriginalId()) {
3586  $pool_question = SurveyQuestion::_instanciateQuestion($new_question->getOriginalId());
3587  $pool_question->setQuestiontext($qtext);
3588  $pool_question->saveToDb();
3589  }
3590  }
3591  } else {
3592  $ilLog = $this->log;
3593  $ilLog->write("Error: Could not open XHTML mob file for test introduction during test import. File $importfile does not exist!");
3594  }
3595  }
3598  $this->saveToDb();
3599  }
3600 
3601  // delete import directory
3603  }
3604  return $error;
3605  }
3606 
3615  public function cloneObject($a_target_id, $a_copy_id = 0, $a_omit_tree = false)
3616  {
3617  $ilDB = $this->db;
3618 
3619  $this->loadFromDb();
3620 
3621  //survey mode
3622  $svy_type = $this->getMode();
3623 
3624  // Copy settings
3625  $newObj = parent::cloneObject($a_target_id, $a_copy_id, $a_omit_tree);
3626  $this->cloneMetaData($newObj);
3627  $newObj->updateMetaData();
3628 
3629  $newObj->setAuthor($this->getAuthor());
3630  $newObj->setIntroduction($this->getIntroduction());
3631  $newObj->setOutro($this->getOutro());
3632  $newObj->setEvaluationAccess($this->getEvaluationAccess());
3633  $newObj->setStartDate($this->getStartDate());
3634  $newObj->setEndDate($this->getEndDate());
3635  $newObj->setAnonymize($this->getAnonymize());
3636  $newObj->setShowQuestionTitles($this->getShowQuestionTitles());
3637  $newObj->setTemplate($this->getTemplate());
3638  $newObj->setPoolUsage($this->getPoolUsage());
3639  $newObj->setViewOwnResults($this->hasViewOwnResults());
3640  $newObj->setMailOwnResults($this->hasMailOwnResults());
3641  $newObj->setMailConfirmation($this->hasMailConfirmation());
3642  $newObj->setAnonymousUserList($this->hasAnonymousUserList());
3643 
3644  // #12661
3645  if ($this->get360Mode()) {
3646  $newObj->setMode(ilObjSurvey::MODE_360);
3647  $newObj->set360SelfEvaluation($this->get360SelfEvaluation());
3648  $newObj->set360SelfAppraisee($this->get360SelfAppraisee());
3649  $newObj->set360SelfRaters($this->get360SelfRaters());
3650  $newObj->set360Results($this->get360Results());
3651  $newObj->setSkillService($this->getSkillService());
3652  }
3653  //svy mode self eval: skills + view results
3654  if ($svy_type == ilObjSurvey::MODE_SELF_EVAL) {
3655  $newObj->setMode(ilObjSurvey::MODE_SELF_EVAL);
3656  $newObj->setSkillService($this->getSkillService());
3657  $newObj->setSelfEvaluationResults($this->getSelfEvaluationResults());
3658  }
3659 
3660  // reminder/notification
3661  $newObj->setReminderStatus($this->getReminderStatus());
3662  $newObj->setReminderStart($this->getReminderStart());
3663  $newObj->setReminderEnd($this->getReminderEnd());
3664  $newObj->setReminderFrequency($this->getReminderFrequency());
3665  $newObj->setReminderTarget($this->getReminderTarget());
3666  $newObj->setReminderTemplate($this->getReminderTemplate());
3667  // reminder_last_sent must not be copied!
3668  $newObj->setTutorNotificationStatus($this->getTutorNotificationStatus());
3669  $newObj->setTutorNotificationRecipients($this->getTutorNotificationRecipients());
3670  $newObj->setTutorNotificationTarget($this->getTutorNotificationTarget());
3671  $newObj->setTutorResultsStatus($this->getTutorResultsStatus());
3672  $newObj->setTutorResultsRecipients($this->getTutorResultsRecipients());
3673 
3674  $newObj->setMailNotification($this->getMailNotification());
3675  $newObj->setMailAddresses($this->getMailAddresses());
3676  $newObj->setMailParticipantData($this->getMailParticipantData());
3677 
3678  $question_pointer = array();
3679  // clone the questions
3680  $mapping = array();
3681 
3682  foreach ($this->questions as $key => $question_id) {
3684  $question = self::_instanciateQuestion($question_id);
3685  if ($question) { // #10824
3686  $question->id = -1;
3687  $original_id = SurveyQuestion::_getOriginalId($question_id, false);
3688  $question->setObjId($newObj->getId());
3689  $question->saveToDb($original_id);
3690  $newObj->questions[$key] = $question->getId();
3691  $question_pointer[$question_id] = $question->getId();
3692  $mapping[$question_id] = $question->getId();
3693  }
3694  }
3695 
3696  //copy online status if object is not the root copy object
3697  $cp_options = ilCopyWizardOptions::_getInstance($a_copy_id);
3698 
3699  if (!$cp_options->isRootNode($this->getRefId())) {
3700  $newObj->setOfflineStatus($this->getOfflineStatus());
3701  }
3702 
3703  $newObj->saveToDb();
3704  $newObj->cloneTextblocks($mapping);
3705 
3706  // #14929
3707  if (($svy_type == ilObjSurvey::MODE_360 || $svy_type == ilObjSurvey::MODE_SELF_EVAL) &&
3708  $this->getSkillService()) {
3709  $src_skills = new ilSurveySkill($this);
3710  $tgt_skills = new ilSurveySkill($newObj);
3711 
3712  foreach ($mapping as $src_qst_id => $tgt_qst_id) {
3713  $qst_skill = $src_skills->getSkillForQuestion($src_qst_id);
3714  if ($qst_skill) {
3715  $tgt_skills->addQuestionSkillAssignment($tgt_qst_id, $qst_skill["base_skill_id"], $qst_skill["tref_id"]);
3716  }
3717  }
3718  }
3719 
3720  // clone the questionblocks
3721  $questionblocks = array();
3722  $questionblock_questions = array();
3723  $result = $ilDB->queryF(
3724  "SELECT * FROM svy_qblk_qst WHERE survey_fi = %s",
3725  array('integer'),
3726  array($this->getSurveyId())
3727  );
3728  if ($result->numRows() > 0) {
3729  while ($row = $ilDB->fetchAssoc($result)) {
3730  array_push($questionblock_questions, $row);
3731  $questionblocks[$row["questionblock_fi"]] = $row["questionblock_fi"];
3732  }
3733  }
3734  // create new questionblocks
3735  foreach ($questionblocks as $key => $value) {
3736  $questionblock = self::_getQuestionblock($key);
3737  $questionblock_id = self::_addQuestionblock($questionblock["title"], $questionblock["owner_fi"], $questionblock["show_questiontext"], $questionblock["show_blocktitle"]);
3738  $questionblocks[$key] = $questionblock_id;
3739  }
3740  // create new questionblock questions
3741  foreach ($questionblock_questions as $key => $value) {
3742  if ($questionblocks[$value["questionblock_fi"]] &&
3743  $question_pointer[$value["question_fi"]]) {
3744  $next_id = $ilDB->nextId('svy_qblk_qst');
3745  $affectedRows = $ilDB->manipulateF(
3746  "INSERT INTO svy_qblk_qst (qblk_qst_id, survey_fi, questionblock_fi, question_fi) " .
3747  "VALUES (%s, %s, %s, %s)",
3748  array('integer','integer','integer','integer'),
3749  array($next_id, $newObj->getSurveyId(), $questionblocks[$value["questionblock_fi"]], $question_pointer[$value["question_fi"]])
3750  );
3751  }
3752  }
3753 
3754  // clone the constraints
3755  $constraints = self::_getConstraints($this->getSurveyId());
3756  $newConstraints = array();
3757  foreach ($constraints as $key => $constraint) {
3758  if ($question_pointer[$constraint["for_question"]] &&
3759  $question_pointer[$constraint["question"]]) {
3760  if (!array_key_exists($constraint['id'], $newConstraints)) {
3761  $constraint_id = $newObj->addConstraint($question_pointer[$constraint["question"]], $constraint["relation_id"], $constraint["value"], $constraint['conjunction']);
3762  $newConstraints[$constraint['id']] = $constraint_id;
3763  }
3764  $newObj->addConstraintToQuestion($question_pointer[$constraint["for_question"]], $newConstraints[$constraint['id']]);
3765  }
3766  }
3767 
3768  // #16210 - clone LP settings
3769  $obj_settings = new ilLPObjSettings($this->getId());
3770  $obj_settings->cloneSettings($newObj->getId());
3771  unset($obj_settings);
3772 
3773  return $newObj;
3774  }
3775 
3776  public function getTextblock($question_id)
3777  {
3778  $ilDB = $this->db;
3779  $result = $ilDB->queryF(
3780  "SELECT * FROM svy_svy_qst WHERE question_fi = %s",
3781  array('integer'),
3782  array($question_id)
3783  );
3784  if ($result->numRows()) {
3785  $row = $ilDB->fetchAssoc($result);
3786  return $row["heading"];
3787  } else {
3788  return "";
3789  }
3790  }
3791 
3797  public function cloneTextblocks($mapping)
3798  {
3799  foreach ($mapping as $original_id => $new_id) {
3800  $textblock = $this->getTextblock($original_id);
3801  $this->saveHeading(ilUtil::stripSlashes($textblock, true, ilObjAdvancedEditing::_getUsedHTMLTagsAsString("survey")), $new_id);
3802  }
3803  }
3804 
3812  public function createExportDirectory()
3813  {
3814  $svy_data_dir = ilUtil::getDataDir() . "/svy_data";
3815  ilUtil::makeDir($svy_data_dir);
3816  if (!is_writable($svy_data_dir)) {
3817  throw new ilSurveyException("Survey Data Directory (" . $svy_data_dir . ") not writeable.");
3818  }
3819 
3820  // create learning module directory (data_dir/lm_data/lm_<id>)
3821  $svy_dir = $svy_data_dir . "/svy_" . $this->getId();
3822  ilUtil::makeDir($svy_dir);
3823  if (!@is_dir($svy_dir)) {
3824  throw new ilSurveyException("Creation of Survey Directory failed.");
3825  }
3826  // create Export subdirectory (data_dir/lm_data/lm_<id>/Export)
3827  $export_dir = $svy_dir . "/export";
3828  ilUtil::makeDir($export_dir);
3829  if (!@is_dir($export_dir)) {
3830  throw new ilSurveyException("Creation of Export Directory failed.");
3831  }
3832  }
3833 
3837  public function getExportDirectory()
3838  {
3839  $export_dir = ilUtil::getDataDir() . "/svy_data" . "/svy_" . $this->getId() . "/export";
3840 
3841  return $export_dir;
3842  }
3843 
3851  public function createImportDirectory()
3852  {
3853  $svy_data_dir = ilUtil::getDataDir() . "/svy_data";
3854  ilUtil::makeDir($svy_data_dir);
3855 
3856  if (!is_writable($svy_data_dir)) {
3857  throw new ilSurveyException("Survey Data Directory (" . $svy_data_dir . ") not writeable.");
3858  }
3859 
3860  // create test directory (data_dir/svy_data/svy_<id>)
3861  $svy_dir = $svy_data_dir . "/svy_" . $this->getId();
3862  ilUtil::makeDir($svy_dir);
3863  if (!@is_dir($svy_dir)) {
3864  throw new ilSurveyException("Creation of Survey Directory failed.");
3865  }
3866 
3867  // create import subdirectory (data_dir/svy_data/svy_<id>/import)
3868  $import_dir = $svy_dir . "/import";
3869  ilUtil::makeDir($import_dir);
3870  if (!@is_dir($import_dir)) {
3871  throw new ilSurveyException("Creation of Import Directory failed.");
3872  }
3873  }
3874 
3878  public function getImportDirectory()
3879  {
3880  $import_dir = ilUtil::getDataDir() . "/svy_data" .
3881  "/svy_" . $this->getId() . "/import";
3882  if (!is_dir($import_dir)) {
3883  ilUtil::makeDirParents($import_dir);
3884  }
3885  if (@is_dir($import_dir)) {
3886  return $import_dir;
3887  } else {
3888  return false;
3889  }
3890  }
3891 
3892  public function saveHeading($heading = "", $insertbefore)
3893  {
3894  $ilDB = $this->db;
3895  if ($heading) {
3896  $affectedRows = $ilDB->manipulateF(
3897  "UPDATE svy_svy_qst SET heading=%s WHERE survey_fi=%s AND question_fi=%s",
3898  array('text','integer','integer'),
3899  array($heading, $this->getSurveyId(), $insertbefore)
3900  );
3901  } else {
3902  $affectedRows = $ilDB->manipulateF(
3903  "UPDATE svy_svy_qst SET heading=%s WHERE survey_fi=%s AND question_fi=%s",
3904  array('text','integer','integer'),
3905  array(null, $this->getSurveyId(), $insertbefore)
3906  );
3907  }
3908  }
3909 
3910  public function isAnonymousKey($key)
3911  {
3912  $ilDB = $this->db;
3913 
3914  $result = $ilDB->queryF(
3915  "SELECT anonymous_id FROM svy_anonymous WHERE survey_key = %s AND survey_fi = %s",
3916  array('text','integer'),
3917  array($key, $this->getSurveyId())
3918  );
3919  return ($result->numRows() == 1) ? true : false;
3920  }
3921 
3922  public function bindSurveyCodeToUser($user_id, $code)
3923  {
3924  $ilDB = $this->db;
3925 
3926  if ($user_id == ANONYMOUS_USER_ID) {
3927  return;
3928  }
3929 
3930  if ($this->checkSurveyCode($code)) {
3931  $ilDB->manipulate("UPDATE svy_anonymous" .
3932  " SET user_key = " . $ilDB->quote(md5($user_id), "text") .
3933  " WHERE survey_key = " . $ilDB->quote($code, "text"));
3934  }
3935  }
3936 
3937  public function isAnonymizedParticipant($key)
3938  {
3939  $ilDB = $this->db;
3940 
3941  $result = $ilDB->queryF(
3942  "SELECT finished_id FROM svy_finished WHERE anonymous_id = %s AND survey_fi = %s",
3943  array('text','integer'),
3944  array($key, $this->getSurveyId())
3945  );
3946  return ($result->numRows() == 1) ? true : false;
3947  }
3948 
3949  public function checkSurveyCode($code)
3950  {
3951  if ($this->isAnonymousKey($code)) {
3952  if ($this->isSurveyStarted("", $code) == 1) {
3953  return false;
3954  } else {
3955  return true;
3956  }
3957  } else {
3958  return false;
3959  }
3960  }
3961 
3969  public function getSurveyCodesForExport(array $a_codes = null, array $a_ids = null)
3970  {
3971  $ilDB = $this->db;
3972  $ilUser = $this->user;
3973  $lng = $this->lng;
3974 
3975  $sql = "SELECT svy_anonymous.*, svy_finished.state" .
3976  " FROM svy_anonymous" .
3977  " LEFT JOIN svy_finished ON (svy_anonymous.survey_key = svy_finished.anonymous_id)" .
3978  " WHERE svy_anonymous.survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
3979  " AND svy_anonymous.user_key IS NULL";
3980 
3981  if ($a_codes) {
3982  $sql .= " AND " . $ilDB->in("svy_anonymous.survey_key", $a_codes, "", "text");
3983  } elseif ($a_ids) {
3984  $sql .= " AND " . $ilDB->in("svy_anonymous.anonymous_id", $a_ids, "", "text");
3985  }
3986 
3987  $export = array();
3988 
3989  // #14905
3990  $titles = array();
3991  $titles[] = '"' . $lng->txt("survey_code") . '"';
3992  $titles[] = '"' . $lng->txt("email") . '"';
3993  $titles[] = '"' . $lng->txt("lastname") . '"';
3994  $titles[] = '"' . $lng->txt("firstname") . '"';
3995  $titles[] = '"' . $lng->txt("create_date") . '"';
3996  $titles[] = '"' . $lng->txt("used") . '"';
3997  $titles[] = '"' . $lng->txt("mail_sent_short") . '"';
3998  $titles[] = '"' . $lng->txt("survey_code_url") . '"';
3999  $export[] = implode(";", $titles);
4000 
4001  $result = $ilDB->query($sql);
4002  $default_lang = $ilUser->getPref("survey_code_language");
4003  while ($row = $ilDB->fetchAssoc($result)) {
4004  $item = array();
4005  $item[] = $row["survey_key"];
4006 
4007  if ($row["externaldata"]) {
4008  $ext = unserialize($row["externaldata"]);
4009  $item[] = $ext["email"];
4010  $item[] = $ext["lastname"];
4011  $item[] = $ext["firstname"];
4012  } else {
4013  $item[] = "";
4014  $item[] = "";
4015  $item[] = "";
4016  }
4017 
4018  // No relative (today, tomorrow...) dates in export.
4019  $date = new ilDateTime($row['tstamp'], IL_CAL_UNIX);
4020  $item[] = $date->get(IL_CAL_DATETIME);
4021 
4022  $item[] = ($this->isSurveyCodeUsed($row["survey_key"])) ? 1 : 0;
4023  $item[] = ($row["sent"]) ? 1 : 0;
4024 
4025  $params = array("accesscode" => $row["survey_key"]);
4026  if ($default_lang) {
4027  $params["lang"] = $default_lang;
4028  }
4029  $item[] = ilLink::_getLink($this->getRefId(), "svy", $params);
4030 
4031  $export[] = '"' . implode('";"', $item) . '"';
4032  }
4033  return implode("\n", $export);
4034  }
4035 
4043  public function getSurveyCodesTableData(array $ids = null, $lang = null)
4044  {
4045  $ilDB = $this->db;
4046 
4047  $codes = array();
4048 
4049  $sql = "SELECT svy_anonymous.*, svy_finished.state" .
4050  " FROM svy_anonymous" .
4051  " LEFT JOIN svy_finished ON (svy_anonymous.survey_key = svy_finished.anonymous_id)" .
4052  " WHERE svy_anonymous.survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") /*.
4053  " AND svy_anonymous.user_key IS NULL" */; // #15860
4054 
4055  if ($ids) {
4056  $sql .= " AND " . $ilDB->in("svy_anonymous.anonymous_id", $ids, "", "integer");
4057  }
4058 
4059  $sql .= " ORDER BY tstamp, survey_key ASC";
4060  $result = $ilDB->query($sql);
4061  if ($result->numRows() > 0) {
4062  while ($row = $ilDB->fetchAssoc($result)) {
4063  $href = "";
4064  $used = false;
4065  if ($this->isSurveyCodeUsed($row["survey_key"])) {
4066  $used = true;
4067  } else {
4068  $params = array("accesscode" => $row["survey_key"]);
4069  if ($lang) {
4070  $params["lang"] = $lang;
4071  }
4072  $href = ilLink::_getLink($this->getRefId(), "svy", $params);
4073  }
4074 
4075 
4076  $item = array(
4077  'id' => $row["anonymous_id"],
4078  'code' => $row["survey_key"],
4079  'date' => $row["tstamp"],
4080  'used' => $used,
4081  'sent' => $row['sent'],
4082  'href' => $href,
4083  'email' => '',
4084  'last_name' => '',
4085  'first_name' => ''
4086  );
4087 
4088  if ($row["externaldata"]) {
4089  $ext = unserialize($row["externaldata"]);
4090  $item['email'] = $ext['email'];
4091  $item['last_name'] = $ext['lastname'];
4092  $item['first_name'] = $ext['firstname'];
4093  }
4094 
4095  array_push($codes, $item);
4096  }
4097  }
4098  return $codes;
4099  }
4100 
4101  public function isSurveyCodeUsed($code)
4102  {
4103  $ilDB = $this->db;
4104  $result = $ilDB->queryF(
4105  "SELECT finished_id FROM svy_finished WHERE survey_fi = %s AND anonymous_id = %s",
4106  array('integer','text'),
4107  array($this->getSurveyId(), $code)
4108  );
4109  return ($result->numRows() > 0) ? true : false;
4110  }
4111 
4112  public function isSurveyCodeUnique($code)
4113  {
4114  $ilDB = $this->db;
4115  $result = $ilDB->queryF(
4116  "SELECT anonymous_id FROM svy_anonymous WHERE survey_fi = %s AND survey_key = %s",
4117  array('integer','text'),
4118  array($this->getSurveyId(), $code)
4119  );
4120  return ($result->numRows() > 0) ? false : true;
4121  }
4122 
4123  public function createSurveyCodes($nrOfCodes)
4124  {
4125  $ilDB = $this->db;
4126 
4127  $res = array();
4128 
4129  for ($i = 0; $i < $nrOfCodes; $i++) {
4130  $next_id = $ilDB->nextId('svy_anonymous');
4131  $ilDB->manipulateF(
4132  "INSERT INTO svy_anonymous (anonymous_id, survey_key, survey_fi, tstamp) " .
4133  "VALUES (%s, %s, %s, %s)",
4134  array('integer','text','integer','integer'),
4135  array($next_id, $this->createNewAccessCode(), $this->getSurveyId(), time())
4136  );
4137  $res[] = $next_id;
4138  }
4139 
4140  return $res;
4141  }
4142 
4143  public function importSurveyCode($a_anonymize_key, $a_created, $a_data)
4144  {
4145  $ilDB = $this->db;
4146 
4147  $next_id = $ilDB->nextId('svy_anonymous');
4148  $ilDB->manipulateF(
4149  "INSERT INTO svy_anonymous (anonymous_id, survey_key, survey_fi, externaldata, tstamp) " .
4150  "VALUES (%s, %s, %s, %s, %s)",
4151  array('integer','text','integer','text','integer'),
4152  array($next_id, $a_anonymize_key, $this->getSurveyId(), serialize($a_data), $a_created)
4153  );
4154  }
4155 
4157  {
4158  $ilDB = $this->db;
4159 
4160  $ids = array();
4161  foreach ($data as $dataset) {
4162  $anonymize_key = $this->createNewAccessCode();
4163  $next_id = $ilDB->nextId('svy_anonymous');
4164  $affectedRows = $ilDB->manipulateF(
4165  "INSERT INTO svy_anonymous (anonymous_id, survey_key, survey_fi, externaldata, tstamp) " .
4166  "VALUES (%s, %s, %s, %s, %s)",
4167  array('integer','text','integer','text','integer'),
4168  array($next_id, $anonymize_key, $this->getSurveyId(), serialize($dataset), time())
4169  );
4170  $ids[] = $next_id;
4171  }
4172  return $ids;
4173  }
4174 
4175  public function sendCodes($not_sent, $subject, $message, $lang)
4176  {
4177  global $DIC;
4178  /*
4179  * 0 = all
4180  * 1 = not sent
4181  * 2 = finished
4182  * 3 = not finished
4183  */
4184  $check_finished = ($not_sent > 1);
4185 
4186 
4187  $mail = new ilMail(ANONYMOUS_USER_ID);
4188  $recipients = $this->getExternalCodeRecipients($check_finished);
4189  foreach ($recipients as $data) {
4190  if ($data['email'] && $data['code']) {
4191  $do_send = false;
4192  switch ((int) $not_sent) {
4193  case 1:
4194  $do_send = !(bool) $data['sent'];
4195  break;
4196 
4197  case 2:
4198  $do_send = $data['finished'];
4199  break;
4200 
4201  case 3:
4202  $do_send = !$data['finished'];
4203  break;
4204 
4205  default:
4206  $do_send = true;
4207  break;
4208  }
4209  if ($do_send) {
4210  // build text
4211  $messagetext = $message;
4213  $this->getRefId(),
4214  "svy",
4215  array(
4216  "accesscode" => $data["code"],
4217  "lang" => $lang
4218  )
4219  );
4220  $messagetext = str_replace('[url]', $url, $messagetext);
4221  foreach ($data as $key => $value) {
4222  $messagetext = str_replace('[' . $key . ']', $value, $messagetext);
4223  }
4224 
4225  // send mail
4226  $mail->enqueue(
4227  $data['email'], // to
4228  "", // cc
4229  "", // bcc
4230  $subject, // subject
4231  $messagetext, // message
4232  array() // attachments
4233  );
4234  }
4235  }
4236  }
4237 
4238  $ilDB = $this->db;
4239  $ilDB->manipulateF(
4240  "UPDATE svy_anonymous SET sent = %s WHERE survey_fi = %s AND externaldata IS NOT NULL",
4241  array('integer','integer'),
4242  array(1, $this->getSurveyId())
4243  );
4244  }
4245 
4246  public function getExternalCodeRecipients($a_check_finished = false)
4247  {
4248  $ilDB = $this->db;
4249  $result = $ilDB->queryF(
4250  "SELECT survey_key code, externaldata, sent FROM svy_anonymous WHERE survey_fi = %s",
4251  array('integer'),
4252  array($this->getSurveyId())
4253  );
4254  $res = array();
4255  while ($row = $ilDB->fetchAssoc($result)) {
4256  if (!$row['externaldata']) {
4257  continue;
4258  }
4259 
4260  $externaldata = unserialize($row['externaldata']);
4261  if (!$externaldata['email']) {
4262  continue;
4263  }
4264 
4265  $externaldata['code'] = $row['code'];
4266  $externaldata['sent'] = $row['sent'];
4267 
4268  if ($a_check_finished) {
4269  #23294
4270  //$externaldata['finished'] = $this->isSurveyCodeUsed($row['code']);
4271  $externaldata['finished'] = $this->isSurveyFinishedByCode($row['code']);
4272  }
4273 
4274  array_push($res, $externaldata);
4275  }
4276  return $res;
4277  }
4278 
4284  public function isSurveyFinishedByCode($a_code)
4285  {
4286  $result = $this->db->queryF(
4287  "SELECT state FROM svy_finished WHERE survey_fi = %s AND anonymous_id = %s",
4288  array('integer','text'),
4289  array($this->getSurveyId(), $a_code)
4290  );
4291 
4292  $row = $this->db->fetchAssoc($result);
4293 
4294  return $row['state'];
4295  }
4296 
4302  public function deleteSurveyCode($survey_code)
4303  {
4304  $ilDB = $this->db;
4305 
4306  if (strlen($survey_code) > 0) {
4307  $affectedRows = $ilDB->manipulateF(
4308  "DELETE FROM svy_anonymous WHERE survey_fi = %s AND survey_key = %s",
4309  array('integer', 'text'),
4310  array($this->getSurveyId(), $survey_code)
4311  );
4312  }
4313  }
4314 
4321  public function getUserAccessCode($user_id)
4322  {
4323  $ilDB = $this->db;
4324  $access_code = "";
4325  $result = $ilDB->queryF(
4326  "SELECT survey_key FROM svy_anonymous WHERE survey_fi = %s AND user_key = %s",
4327  array('integer','text'),
4328  array($this->getSurveyId(), md5($user_id))
4329  );
4330  if ($result->numRows()) {
4331  $row = $ilDB->fetchAssoc($result);
4332  $access_code = $row["survey_key"];
4333  }
4334  return $access_code;
4335  }
4336 
4343  public function saveUserAccessCode($user_id, $access_code)
4344  {
4345  $ilDB = $this->db;
4346 
4347  // not really sure what to do about ANONYMOUS_USER_ID
4348 
4349  $next_id = $ilDB->nextId('svy_anonymous');
4350  $affectedRows = $ilDB->manipulateF(
4351  "INSERT INTO svy_anonymous (anonymous_id, survey_key, survey_fi, user_key, tstamp) " .
4352  "VALUES (%s, %s, %s, %s, %s)",
4353  array('integer','text', 'integer', 'text', 'integer'),
4354  array($next_id, $access_code, $this->getSurveyId(), md5($user_id), time())
4355  );
4356  }
4357 
4363  public function createNewAccessCode()
4364  {
4365  // create a 5 character code
4366  $codestring = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
4367  mt_srand();
4368  $code = "";
4369  for ($i = 1; $i <= 5; $i++) {
4370  $index = mt_rand(0, strlen($codestring) - 1);
4371  $code .= substr($codestring, $index, 1);
4372  }
4373  // verify it against the database
4374  while (!$this->isSurveyCodeUnique($code)) {
4375  $code = $this->createNewAccessCode();
4376  }
4377  return $code;
4378  }
4379 
4380  public function getLastAccess($finished_id)
4381  {
4382  $ilDB = $this->db;
4383 
4384  $result = $ilDB->queryF(
4385  "SELECT tstamp FROM svy_answer WHERE active_fi = %s ORDER BY tstamp DESC",
4386  array('integer'),
4387  array($finished_id)
4388  );
4389  if ($result->numRows()) {
4390  $row = $ilDB->fetchAssoc($result);
4391  return $row["tstamp"];
4392  } else {
4393  $result = $ilDB->queryF(
4394  "SELECT tstamp FROM svy_finished WHERE finished_id = %s",
4395  array('integer'),
4396  array($finished_id)
4397  );
4398  if ($result->numRows()) {
4399  $row = $ilDB->fetchAssoc($result);
4400  return $row["tstamp"];
4401  }
4402  }
4403  return "";
4404  }
4405 
4412  public function prepareTextareaOutput($txt_output)
4413  {
4414  return ilUtil::prepareTextareaOutput($txt_output, $prepare_for_latex_output);
4415  }
4416 
4424  public function isHTML($a_text)
4425  {
4426  if (preg_match("/<[^>]*?>/", $a_text)) {
4427  return true;
4428  } else {
4429  return false;
4430  }
4431  }
4432 
4441  public function addMaterialTag(&$a_xml_writer, $a_material, $close_material_tag = true, $add_mobs = true, $attribs = null)
4442  {
4443  $a_xml_writer->xmlStartTag("material", $attribs);
4444  $attrs = array(
4445  "type" => "text/plain"
4446  );
4447  if ($this->isHTML($a_material)) {
4448  $attrs["type"] = "text/xhtml";
4449  }
4450  $mattext = ilRTE::_replaceMediaObjectImageSrc($a_material, 0);
4451  $a_xml_writer->xmlElement("mattext", $attrs, $mattext);
4452 
4453  if ($add_mobs) {
4454  $mobs = ilObjMediaObject::_getMobsOfObject("svy:html", $this->getId());
4455  foreach ($mobs as $mob) {
4456  $mob_id = "il_" . IL_INST_ID . "_mob_" . $mob;
4457  if (strpos($mattext, $mob_id) !== false) {
4458  $mob_obj = new ilObjMediaObject($mob);
4459  $imgattrs = array(
4460  "label" => $mob_id,
4461  "uri" => "objects/" . "il_" . IL_INST_ID . "_mob_" . $mob . "/" . $mob_obj->getTitle(),
4462  "type" => "svy:html",
4463  "id" => $this->getId()
4464  );
4465  $a_xml_writer->xmlElement("matimage", $imgattrs, null);
4466  }
4467  }
4468  }
4469  if ($close_material_tag) {
4470  $a_xml_writer->xmlEndTag("material");
4471  }
4472  }
4473 
4482  public function canExportSurveyCode()
4483  {
4484  if ($this->getAnonymize() != self::ANONYMIZE_OFF) {
4485  if ($this->surveyCodeSecurity == false) {
4486  return true;
4487  }
4488  }
4489  return false;
4490  }
4491 
4499  public function processPrintoutput2FO($print_output)
4500  {
4501  if (extension_loaded("tidy")) {
4502  $config = array(
4503  "indent" => false,
4504  "output-xml" => true,
4505  "numeric-entities" => true
4506  );
4507  $tidy = new tidy();
4508  $tidy->parseString($print_output, $config, 'utf8');
4509  $tidy->cleanRepair();
4510  $print_output = tidy_get_output($tidy);
4511  $print_output = preg_replace("/^.*?(<html)/", "\\1", $print_output);
4512  } else {
4513  $print_output = str_replace("&nbsp;", "&#160;", $print_output);
4514  $print_output = str_replace("&otimes;", "X", $print_output);
4515 
4516  // #17680 - metric questions use &#160; in print view
4517  $print_output = str_replace("&gt;", "~|gt|~", $print_output); // see #21550
4518  $print_output = str_replace("&lt;", "~|lt|~", $print_output);
4519  $print_output = str_replace("&#160;", "~|nbsp|~", $print_output);
4520  $print_output = preg_replace('/&(?!amp)/', '&amp;', $print_output);
4521  $print_output = str_replace("~|nbsp|~", "&#160;", $print_output);
4522  $print_output = str_replace("~|gt|~", "&gt;", $print_output);
4523  $print_output = str_replace("~|lt|~", "&lt;", $print_output);
4524  }
4525  $xsl = file_get_contents("./Modules/Survey/xml/question2fo.xsl");
4526 
4527  // additional font support
4528  $xsl = str_replace(
4529  'font-family="Helvetica, unifont"',
4530  'font-family="' . $GLOBALS['ilSetting']->get('rpc_pdf_font', 'Helvetica, unifont') . '"',
4531  $xsl
4532  );
4533  $args = array( '/_xml' => $print_output, '/_xsl' => $xsl );
4534  $xh = xslt_create();
4535  $params = array();
4536  try {
4537  $output = xslt_process($xh, "arg:/_xml", "arg:/_xsl", null, $args, $params);
4538  } catch (Exception $e) {
4539  $this->log->error("Print XSLT failed:");
4540  $this->log->error("Content: " . $print_output);
4541  $this->log->error("Xsl: " . $xsl);
4542  throw ($e);
4543  }
4544  xslt_error($xh);
4545  xslt_free($xh);
4546 
4547  return $output;
4548  }
4549 
4556  public function deliverPDFfromFO($fo)
4557  {
4558  $ilLog = $this->log;
4559 
4560  $fo_file = ilUtil::ilTempnam() . ".fo";
4561  $fp = fopen($fo_file, "w");
4562  fwrite($fp, $fo);
4563  fclose($fp);
4564 
4565  try {
4566  $pdf_base64 = ilRpcClientFactory::factory('RPCTransformationHandler')->ilFO2PDF($fo);
4567  ilUtil::deliverData($pdf_base64->scalar, ilUtil::getASCIIFilename($this->getTitle()) . ".pdf", "application/pdf");
4568  return true;
4569  } catch (Exception $e) {
4570  $ilLog->write(__METHOD__ . ': ' . $e->getMessage());
4571  return false;
4572  }
4573  }
4574 
4581  public function isPluginActive($a_pname)
4582  {
4583  $ilPluginAdmin = $this->plugin_admin;
4584  if ($ilPluginAdmin->isActive(IL_COMP_MODULE, "SurveyQuestionPool", "svyq", $a_pname)) {
4585  return true;
4586  } else {
4587  return false;
4588  }
4589  }
4590 
4596  public function setSurveyId($survey_id)
4597  {
4598  $this->survey_id = $survey_id;
4599  }
4600 
4607  public function &getUserData($ids)
4608  {
4609  $ilDB = $this->db;
4610 
4611  if (!is_array($ids) || count($ids) == 0) {
4612  return array();
4613  }
4614 
4615  $result = $ilDB->query("SELECT usr_id, login, lastname, firstname FROM usr_data WHERE " . $ilDB->in('usr_id', $ids, false, 'integer') . " ORDER BY login");
4616  $result_array = array();
4617  while ($row = $ilDB->fetchAssoc($result)) {
4618  $result_array[$row["usr_id"]] = $row;
4619  }
4620  return $result_array;
4621  }
4622 
4623  public function getMailNotification()
4624  {
4625  return $this->mailnotification;
4626  }
4627 
4628  public function setMailNotification($a_notification)
4629  {
4630  $this->mailnotification = ($a_notification) ? true : false;
4631  }
4632 
4633  public function getMailAddresses()
4634  {
4635  return $this->mailaddresses;
4636  }
4637 
4638  public function setMailAddresses($a_addresses)
4639  {
4640  $this->mailaddresses = $a_addresses;
4641  }
4642 
4643  public function getMailParticipantData()
4644  {
4646  }
4647 
4648  public function setMailParticipantData($a_data)
4649  {
4650  $this->mailparticipantdata = $a_data;
4651  }
4652 
4653  public function setStartTime($finished_id, $first_question)
4654  {
4655  $ilDB = $this->db;
4656  $time = time();
4657  //primary for table svy_times
4658  $id = $ilDB->nextId('svy_times');
4659  $_SESSION['svy_entered_page'] = $time;
4660  $affectedRows = $ilDB->manipulateF(
4661  "INSERT INTO svy_times (id, finished_fi, entered_page, left_page, first_question) VALUES (%s, %s, %s, %s,%s)",
4662  array('integer','integer', 'integer', 'integer', 'integer'),
4663  array($id, $finished_id, $time, null, $first_question)
4664  );
4665  }
4666 
4667  public function setEndTime($finished_id)
4668  {
4669  $ilDB = $this->db;
4670  $time = time();
4671  $affectedRows = $ilDB->manipulateF(
4672  "UPDATE svy_times SET left_page = %s WHERE finished_fi = %s AND entered_page = %s",
4673  array('integer', 'integer', 'integer'),
4674  array($time, $finished_id, $_SESSION['svy_entered_page'])
4675  );
4676  unset($_SESSION['svy_entered_page']);
4677  }
4678 
4679  public function getWorkingtimeForParticipant($finished_id)
4680  {
4681  $ilDB = $this->db;
4682 
4683  $result = $ilDB->queryF(
4684  "SELECT * FROM svy_times WHERE finished_fi = %s",
4685  array('integer'),
4686  array($finished_id)
4687  );
4688  $total = 0;
4689  while ($row = $ilDB->fetchAssoc($result)) {
4690  if ($row['left_page'] > 0 && $row['entered_page'] > 0) {
4691  $total += $row['left_page'] - $row['entered_page'];
4692  }
4693  }
4694  return $total;
4695  }
4696 
4697  public function setTemplate($template_id)
4698  {
4699  $this->template_id = (int) $template_id;
4700  }
4701 
4702  public function getTemplate()
4703  {
4704  return $this->template_id;
4705  }
4706 
4707  public function updateOrder(array $a_order)
4708  {
4709  if (sizeof($this->questions) == sizeof($a_order)) {
4710  $this->questions = array_flip($a_order);
4711  $this->saveQuestionsToDB();
4712  }
4713  }
4714 
4715  public function getPoolUsage()
4716  {
4717  return $this->pool_usage;
4718  }
4719 
4720  public function setPoolUsage($a_value)
4721  {
4722  $this->pool_usage = (bool) $a_value;
4723  }
4724 
4730  public function isPoolActive()
4731  {
4732  $use_pool = (bool) $this->getPoolUsage();
4733  $template_settings = $this->getTemplate();
4734  if ($template_settings) {
4735  $template_settings = new ilSettingsTemplate($template_settings);
4736  $template_settings = $template_settings->getSettings();
4737  $template_settings = $template_settings["use_pool"];
4738  if ($template_settings && $template_settings["hide"]) {
4739  $use_pool = (bool) $template_settings["value"];
4740  }
4741  }
4742  return $use_pool;
4743  }
4744 
4751  {
4752  if (!$template_id) {
4753  return;
4754  }
4755 
4756  $template = new ilSettingsTemplate($template_id);
4757  $template_settings = $template->getSettings();
4758  //ilUtil::dumpVar($template_settings); exit;
4759  if ($template_settings) {
4760  if ($template_settings["show_question_titles"] !== null) {
4761  if ($template_settings["show_question_titles"]["value"]) {
4762  $this->setShowQuestionTitles(true);
4763  } else {
4764  $this->setShowQuestionTitles(false);
4765  }
4766  }
4767 
4768  if ($template_settings["use_pool"] !== null) {
4769  if ($template_settings["use_pool"]["value"]) {
4770  $this->setPoolUsage(true);
4771  } else {
4772  $this->setPoolUsage(false);
4773  }
4774  }
4775 
4776 
4777  /* see #0021719
4778  if($template_settings["anonymization_options"]["value"])
4779  {
4780  $anon_map = array('personalized' => self::ANONYMIZE_OFF,
4781  'anonymize_with_code' => self::ANONYMIZE_ON,
4782  'anonymize_without_code' => self::ANONYMIZE_FREEACCESS);
4783  $this->setAnonymize($anon_map[$template_settings["anonymization_options"]["value"]]);
4784  }*/
4785 
4786  // see #0021719 and ilObjectSurveyGUI::savePropertiesObject
4787  $this->setEvaluationAccess($template_settings["evaluation_access"]["value"]);
4788  $codes = (bool) $template_settings["acc_codes"]["value"];
4789  $anon = (bool) $template_settings["anonymization_options"]["value"];
4790  if (!$anon) {
4791  if (!$codes) {
4793  } else {
4795  }
4796  } else {
4797  if ($codes) {
4799  } else {
4801  }
4802 
4803  $this->setAnonymousUserList($_POST["anon_list"]);
4804  }
4805 
4806 
4807 
4808  /* other settings: not needed here
4809  * - enabled_end_date
4810  * - enabled_start_date
4811  * - rte_switch
4812  */
4813  }
4814 
4815  $this->setTemplate($template_id);
4816  $this->saveToDb();
4817  }
4818 
4819  public function updateCode($a_id, $a_email, $a_last_name, $a_first_name, $a_sent)
4820  {
4821  $ilDB = $this->db;
4822 
4823  $a_email = trim($a_email);
4824 
4825  // :TODO:
4826  if (($a_email && !ilUtil::is_email($a_email)) || $a_email == "") {
4827  return false;
4828  }
4829 
4830  $data = array("email" => $a_email,
4831  "lastname" => trim($a_last_name),
4832  "firstname" => trim($a_first_name));
4833 
4834  $fields = array(
4835  "externaldata" => array("text", serialize($data)),
4836  "sent" => array("integer", $a_sent)
4837  );
4838 
4839  $ilDB->update(
4840  "svy_anonymous",
4841  $fields,
4842  array("anonymous_id" => array("integer", $a_id))
4843  );
4844 
4845  return true;
4846  }
4847 
4848 
4849  //
4850  // 360°
4851  //
4852 
4853  public function get360Mode()
4854  {
4855  if ($this->getMode() == ilObjSurvey::MODE_360) {
4856  return true;
4857  }
4858  return false;
4859  }
4860 
4861  public function set360SelfEvaluation($a_value)
4862  {
4863  $this->mode_360_self_eval = (bool) $a_value;
4864  }
4865 
4866  public function get360SelfEvaluation()
4867  {
4868  return (bool) $this->mode_360_self_eval;
4869  }
4870 
4871  public function set360SelfAppraisee($a_value)
4872  {
4873  $this->mode_360_self_appr = (bool) $a_value;
4874  }
4875 
4876  public function get360SelfAppraisee()
4877  {
4878  return (bool) $this->mode_360_self_appr;
4879  }
4880 
4881  public function set360SelfRaters($a_value)
4882  {
4883  $this->mode_360_self_rate = (bool) $a_value;
4884  }
4885 
4886  public function get360SelfRaters()
4887  {
4888  return (bool) $this->mode_360_self_rate;
4889  }
4890 
4891  public function set360Results($a_value)
4892  {
4893  $this->mode_360_results = (int) $a_value;
4894  }
4895 
4896  public function get360Results()
4897  {
4898  return (int) $this->mode_360_results;
4899  }
4900 
4901  public function addAppraisee($a_user_id)
4902  {
4903  global $DIC;
4904 
4905  $ilDB = $DIC->database();
4906  $access = $DIC->access();
4907 
4908  if (!$this->isAppraisee($a_user_id) &&
4909  $a_user_id != ANONYMOUS_USER_ID) {
4910  $fields = array(
4911  "obj_id" => array("integer", $this->getSurveyId()),
4912  "user_id" => array("integer", $a_user_id)
4913  );
4914  $ilDB->insert("svy_360_appr", $fields);
4915 
4916  // send notification and add to desktop
4917  if ($access->checkAccessOfUser($a_user_id, "read", "", $this->getRefId())) {
4918  $this->sendAppraiseeNotification($a_user_id);
4919  }
4920  }
4921  }
4922 
4928  public function sendAppraiseeNotification($a_user_id)
4929  {
4930  $ntf = new ilSystemNotification();
4931  $ntf->setLangModules(array("svy", "survey"));
4932  $ntf->setRefId($this->getRefId());
4933  $ntf->setGotoLangId('url');
4934 
4935  // user specific language
4936  $lng = $ntf->getUserLanguage($a_user_id);
4937 
4938  $ntf->setIntroductionLangId("svy_user_added_360_appraisee_mail");
4939  $subject = str_replace("%1", $this->getTitle(), $lng->txt("svy_user_added_360_appraisee"));
4940 
4941  // #10044
4942  $mail = new ilMail(ANONYMOUS_USER_ID);
4943  $mail->enqueue(
4944  ilObjUser::_lookupLogin($a_user_id),
4945  null,
4946  null,
4947  $subject,
4948  $ntf->composeAndGetMessage($a_user_id, null, "read", true),
4949  []
4950  );
4951  }
4952 
4958  public function sendAppraiseeCloseNotification($a_user_id)
4959  {
4960  $ntf = new ilSystemNotification();
4961  $ntf->setLangModules(array("svy", "survey"));
4962  $ntf->setRefId($this->getRefId());
4963  $ntf->setGotoLangId('url');
4964 
4965  // user specific language
4966  $lng = $ntf->getUserLanguage($a_user_id);
4967 
4968  $ntf->setIntroductionLangId("svy_user_added_360_appraisee_close_mail");
4969  $subject = str_replace("%1", $this->getTitle(), $lng->txt("svy_user_added_360_appraisee"));
4970 
4971  // #10044
4972  $mail = new ilMail(ANONYMOUS_USER_ID);
4973  $mail->enqueue(
4974  ilObjUser::_lookupLogin($a_user_id),
4975  null,
4976  null,
4977  $subject,
4978  $ntf->composeAndGetMessage($a_user_id, null, "read", true),
4979  []
4980  );
4981  }
4982 
4988  public function sendRaterNotification($a_user_id, $a_appraisee_id)
4989  {
4990  $ntf = new ilSystemNotification();
4991  $ntf->setLangModules(array("svy", "survey"));
4992  $ntf->setRefId($this->getRefId());
4993  $ntf->setGotoLangId('url');
4994 
4995  // user specific language
4996  $lng = $ntf->getUserLanguage($a_user_id);
4997 
4998  $ntf->setIntroductionLangId("svy_user_added_360_rater_mail");
4999  $subject = str_replace("%1", $this->getTitle(), $lng->txt("svy_user_added_360_rater"));
5000  $ntf->addAdditionalInfo("survey_360_appraisee", ilUserUtil::getNamePresentation($a_appraisee_id, false, false, "", true));
5001 
5002  // #10044
5003  $mail = new ilMail(ANONYMOUS_USER_ID);
5004  $mail->enqueue(
5005  ilObjUser::_lookupLogin($a_user_id),
5006  null,
5007  null,
5008  $subject,
5009  $ntf->composeAndGetMessage($a_user_id, null, "read", true),
5010  []
5011  );
5012  }
5013 
5014  public function isAppraisee($a_user_id)
5015  {
5016  $ilDB = $this->db;
5017 
5018  $set = $ilDB->query("SELECT user_id" .
5019  " FROM svy_360_appr" .
5020  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5021  " AND user_id = " . $ilDB->quote($a_user_id, "integer"));
5022  return (bool) $ilDB->numRows($set);
5023  }
5024 
5025  public function isAppraiseeClosed($a_user_id)
5026  {
5027  $ilDB = $this->db;
5028 
5029  $set = $ilDB->query("SELECT has_closed" .
5030  " FROM svy_360_appr" .
5031  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5032  " AND user_id = " . $ilDB->quote($a_user_id, "integer"));
5033  $row = $ilDB->fetchAssoc($set);
5034  return $row["has_closed"];
5035  }
5036 
5037  public function deleteAppraisee($a_user_id)
5038  {
5039  $ilDB = $this->db;
5040 
5041  $ilDB->manipulate("DELETE FROM svy_360_appr" .
5042  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5043  " AND user_id = " . $ilDB->quote($a_user_id, "integer"));
5044 
5045  $set = $ilDB->query("SELECT user_id" .
5046  " FROM svy_360_rater" .
5047  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5048  " AND appr_id = " . $ilDB->quote($a_user_id, "integer"));
5049  while ($row = $ilDB->fetchAssoc($set)) {
5050  $this->deleteRater($a_user_id, $row["user_id"]);
5051  }
5052  // appraisee will not be part of raters table
5053  if ($this->get360SelfEvaluation()) {
5054  $this->deleteRater($a_user_id, $a_user_id);
5055  }
5056  }
5057 
5058  public function getAppraiseesData()
5059  {
5060  $ilDB = $this->db;
5061 
5062  $res = array();
5063 
5064  $set = $ilDB->query("SELECT * FROM svy_360_appr" .
5065  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer"));
5066  while ($row = $ilDB->fetchAssoc($set)) {
5067  $name = ilObjUser::_lookupName($row["user_id"]);
5068  $name["email"] = ilObjUser::_lookupEmail($row["user_id"]);
5069  $name["name"] = $name["lastname"] . ", " . $name["firstname"];
5070  $res[$row["user_id"]] = $name;
5071 
5072  $finished = 0;
5073  $raters = $this->getRatersData($row["user_id"]);
5074  foreach ($raters as $rater) {
5075  if ($rater["finished"]) {
5076  $finished++;
5077  }
5078  }
5079  $res[$row["user_id"]]["finished"] = $finished . "/" . sizeof($raters);
5080  $res[$row["user_id"]]["closed"] = $row["has_closed"];
5081  }
5082 
5083  return $res;
5084  }
5085 
5086  public function addRater($a_appraisee_id, $a_user_id, $a_anonymous_id = 0)
5087  {
5088  global $DIC;
5089 
5090  $ilDB = $DIC->database();
5091  $access = $DIC->access();
5092 
5093  if ($this->isAppraisee($a_appraisee_id) &&
5094  !$this->isRater($a_appraisee_id, $a_user_id, $a_anonymous_id)) {
5095  $fields = array(
5096  "obj_id" => array("integer", $this->getSurveyId()),
5097  "appr_id" => array("integer", $a_appraisee_id),
5098  "user_id" => array("integer", $a_user_id),
5099  "anonymous_id" => array("integer", $a_anonymous_id)
5100  );
5101  $ilDB->insert("svy_360_rater", $fields);
5102 
5103  // send notification and add to desktop
5104  if ($access->checkAccessOfUser($a_user_id, "read", "", $this->getRefId())) {
5105  $this->sendRaterNotification($a_user_id, $a_appraisee_id);
5106  }
5107  }
5108  }
5109 
5110  public function isRater($a_appraisee_id, $a_user_id, $a_anonymous_id = 0)
5111  {
5112  $ilDB = $this->db;
5113 
5114  // user is rater if already appraisee and active self-evaluation
5115  if ($this->isAppraisee($a_user_id) &&
5116  $this->get360SelfEvaluation() &&
5117  (!$a_appraisee_id || $a_appraisee_id == $a_user_id)) {
5118  return true;
5119  }
5120 
5121  // :TODO: should we get rid of code as well?
5122 
5123  $sql = "SELECT user_id" .
5124  " FROM svy_360_rater" .
5125  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5126  " AND user_id = " . $ilDB->quote($a_user_id, "integer") .
5127  " AND anonymous_id = " . $ilDB->quote($a_anonymous_id, "integer");
5128  if ($a_appraisee_id) {
5129  $sql .= " AND appr_id = " . $ilDB->quote($a_appraisee_id, "integer");
5130  }
5131  $set = $ilDB->query($sql);
5132  return (bool) $ilDB->numRows($set);
5133  }
5134 
5135  public function deleteRater($a_appraisee_id, $a_user_id, $a_anonymous_id = 0)
5136  {
5137  $ilDB = $this->db;
5138 
5139  $finished_id = $this->getFinishedIdForAppraiseeIdAndRaterId($a_appraisee_id, $a_user_id);
5140  if ($finished_id) {
5141  $this->removeSelectedSurveyResults(array($finished_id));
5142  }
5143 
5144  $ilDB->manipulate("DELETE FROM svy_360_rater" .
5145  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5146  " AND appr_id = " . $ilDB->quote($a_appraisee_id, "integer") .
5147  " AND user_id = " . $ilDB->quote($a_user_id, "integer") .
5148  " AND anonymous_id = " . $ilDB->quote($a_anonymous_id, "integer"));
5149  }
5150 
5151  public function getRatersData($a_appraisee_id)
5152  {
5153  $ilDB = $this->db;
5154 
5155  $res = $anonymous_ids = array();
5156 
5157  $set = $ilDB->query("SELECT * FROM svy_360_rater" .
5158  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5159  " AND appr_id = " . $ilDB->quote($a_appraisee_id, "integer"));
5160  while ($row = $ilDB->fetchAssoc($set)) {
5161  if ($row["anonymous_id"]) {
5162  $res["a" . $row["anonymous_id"]] = array(
5163  "lastname" => "unknown code " . $row["anonymous_id"],
5164  "sent" => $row["mail_sent"],
5165  "finished" => null
5166  );
5167  $anonymous_ids[] = $row["anonymous_id"];
5168  } else {
5169  $name = ilObjUser::_lookupName($row["user_id"]);
5170  $name["name"] = $name["lastname"] . ", " . $name["firstname"];
5171  $name["user_id"] = "u" . $name["user_id"];
5172  $name["email"] = ilObjUser::_lookupEmail($row["user_id"]);
5173  $name["sent"] = $row["mail_sent"];
5174  $name["finished"] = (bool) $this->is360SurveyStarted($a_appraisee_id, $row["user_id"]);
5175  $res["u" . $row["user_id"]] = $name;
5176  }
5177  }
5178 
5179  if (sizeof($anonymous_ids)) {
5180  $data = $this->getSurveyCodesTableData($anonymous_ids);
5181  foreach ($data as $item) {
5182  if (isset($res["a" . $item["id"]])) {
5183  $res["a" . $item["id"]] = array(
5184  "user_id" => "a" . $item["id"],
5185  "lastname" => $item["last_name"],
5186  "firstname" => $item["first_name"],
5187  "name" => $item["last_name"] . ", " . $item["first_name"],
5188  "login" => "",
5189  "email" => $item["email"],
5190  "code" => $item["code"],
5191  "href" => $item["href"],
5192  "sent" => $res["a" . $item["id"]]["sent"],
5193  "finished" => (bool) $this->is360SurveyStarted($a_appraisee_id, null, $item["code"])
5194  );
5195  }
5196  }
5197  }
5198 
5199  return $res;
5200  }
5201 
5202  public function getAppraiseesToRate($a_user_id, $a_anonymous_id = null)
5203  {
5204  $ilDB = $this->db;
5205 
5206  $res = array();
5207 
5208  $sql = "SELECT appr_id FROM svy_360_rater" .
5209  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer");
5210 
5211  if ($a_user_id) {
5212  $sql .= " AND user_id = " . $ilDB->quote($a_user_id, "integer");
5213  } else {
5214  $sql .= " AND anonymous_id = " . $ilDB->quote($a_anonymous_id, "integer");
5215  }
5216 
5217  $set = $ilDB->query($sql);
5218  while ($row = $ilDB->fetchAssoc($set)) {
5219  $res[] = $row["appr_id"];
5220  }
5221 
5222  // user may evaluate himself if already appraisee
5223  if ($this->get360SelfEvaluation() &&
5224  $this->isAppraisee($a_user_id) &&
5225  !in_array($a_user_id, $res)) {
5226  $res[] = $a_user_id;
5227  }
5228 
5229  return $res;
5230  }
5231 
5232  public function getAnonymousIdByCode($a_code)
5233  {
5234  $ilDB = $this->db;
5235 
5236  $set = $ilDB->query("SELECT anonymous_id FROM svy_anonymous" .
5237  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
5238  " AND survey_key = " . $ilDB->quote($a_code, "text"));
5239  $res = $ilDB->fetchAssoc($set);
5240  return $res["anonymous_id"];
5241  }
5242 
5243  public function is360SurveyStarted($appr_id, $user_id, $anonymous_code = null)
5244  {
5245  $ilDB = $this->db;
5246 
5247  $sql = "SELECT * FROM svy_finished" .
5248  " WHERE survey_fi =" . $ilDB->quote($this->getSurveyId(), "integer") .
5249  " AND appr_id = " . $ilDB->quote($appr_id, "integer");
5250  if ($user_id) {
5251  $sql .= " AND user_fi = " . $ilDB->quote($user_id, "integer");
5252  } else {
5253  $sql .= " AND anonymous_id = " . $ilDB->quote($anonymous_code, "text");
5254  }
5255  $result = $ilDB->query($sql);
5256  if ($result->numRows() == 0) {
5257  return false;
5258  } else {
5259  $row = $ilDB->fetchAssoc($result);
5260  return (int) $row["state"];
5261  }
5262  }
5263 
5264  public function getUserSurveyExecutionStatus($a_code = null)
5265  {
5266  $ilUser = $this->user;
5267  $ilDB = $this->db;
5268 
5269  $user_id = $ilUser->getId();
5270 
5271  // code is obligatory?
5272  if (!$this->isAccessibleWithoutCode()) {
5273  if (!$a_code) {
5274  // registered raters do not need code
5275  if ($this->get360Mode() &&
5276  $user_id != ANONYMOUS_USER_ID &&
5277  $this->isRater(0, $user_id)) {
5278  // auto-generate code
5279  $a_code = $this->createNewAccessCode();
5280  $this->saveUserAccessCode($user_id, $a_code);
5281  } else {
5282  return null;
5283  }
5284  }
5285  } elseif ($user_id == ANONYMOUS_USER_ID ||
5286  $this->getAnonymize() == self::ANONYMIZE_FREEACCESS) {
5287  if (!$a_code) {
5288  // auto-generate code
5289  $a_code = $this->createNewAccessCode();
5290  $this->saveUserAccessCode($user_id, $a_code);
5291  }
5292  } else {
5293  $a_code = null;
5294  }
5295 
5296  $res = array();
5297 
5298  $sql = "SELECT * FROM svy_finished" .
5299  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer");
5300  // if proper user id is given, use it or current code
5301  if ($user_id != ANONYMOUS_USER_ID) {
5302  $sql .= " AND (user_fi = " . $ilDB->quote($user_id, "integer") .
5303  " OR anonymous_id = " . $ilDB->quote($a_code, "text") . ")";
5304  }
5305  // use anonymous code to find finished id(s)
5306  else {
5307  $sql .= " AND anonymous_id = " . $ilDB->quote($a_code, "text");
5308  }
5309  $set = $ilDB->query($sql);
5310  while ($row = $ilDB->fetchAssoc($set)) {
5311  $res[$row["finished_id"]] = array("appr_id" => $row["appr_id"],
5312  "user_id" => $row["user_fi"],
5313  "code" => $row["anonymous_id"],
5314  "finished" => (bool) $row["state"]);
5315  }
5316 
5317  return array("code" => $a_code, "runs" => $res);
5318  }
5319 
5320  public function findCodeForUser($a_user_id)
5321  {
5322  $ilDB = $this->db;
5323 
5324  if ($a_user_id != ANONYMOUS_USER_ID) {
5325  $set = $ilDB->query("SELECT sf.anonymous_id FROM svy_finished sf" .
5326  " WHERE sf.survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
5327  " AND sf.user_fi = " . $ilDB->quote($a_user_id, "integer"));
5328  $a_code = $ilDB->fetchAssoc($set);
5329  return $a_code["anonymous_id"];
5330  }
5331  }
5332 
5333  public function isUnusedCode($a_code, $a_user_id)
5334  {
5335  $ilDB = $this->db;
5336 
5337  $set = $ilDB->query("SELECT user_fi FROM svy_finished" .
5338  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
5339  " AND anonymous_id = " . $ilDB->quote($a_code, "text"));
5340  $user_id = $ilDB->fetchAssoc($set);
5341  $user_id = $user_id["user_fi"];
5342 
5343  if ($user_id && ($user_id != $a_user_id || $user_id == ANONYMOUS_USER_ID)) {
5344  return false;
5345  }
5346  return true;
5347  }
5348 
5349  public function getFinishedIdsForAppraiseeId($a_appr_id, $a_exclude_appraisee = false)
5350  {
5351  $ilDB = $this->db;
5352 
5353  $res = array();
5354 
5355  $set = $ilDB->query("SELECT finished_id, user_fi FROM svy_finished" .
5356  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
5357  " AND appr_id = " . $ilDB->quote($a_appr_id, "integer"));
5358  while ($row = $ilDB->fetchAssoc($set)) {
5359  if ($a_exclude_appraisee && $row["user_fi"] == $a_appr_id) {
5360  continue;
5361  }
5362  $res[] = $row["finished_id"];
5363  }
5364 
5365  return $res;
5366  }
5367 
5375  public function getFinishedIdForAppraiseeIdAndRaterId($a_appr_id, $a_rat_id)
5376  {
5377  $ilDB = $this->db;
5378 
5379  $set = $ilDB->query("SELECT finished_id, user_fi FROM svy_finished" .
5380  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
5381  " AND appr_id = " . $ilDB->quote($a_appr_id, "integer") .
5382  " AND user_fi = " . $ilDB->quote($a_rat_id, "integer"));
5383  $row = $ilDB->fetchAssoc($set);
5384  return $row["finished_id"];
5385  }
5386 
5387 
5388  // 360° using competence/skill service
5389 
5395  public function setSkillService($a_val)
5396  {
5397  $this->mode_skill_service = $a_val;
5398  }
5399 
5405  public function getSkillService()
5406  {
5408  }
5409 
5410  public function set360RaterSent($a_appraisee_id, $a_user_id, $a_anonymous_id, $a_tstamp = null)
5411  {
5412  $ilDB = $this->db;
5413 
5414  if (!$a_tstamp) {
5415  $a_tstamp = time();
5416  }
5417 
5418  $ilDB->manipulate("UPDATE svy_360_rater" .
5419  " SET mail_sent = " . $ilDB->quote($a_tstamp, "integer") .
5420  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5421  " AND appr_id = " . $ilDB->quote($a_appraisee_id, "integer") .
5422  " AND user_id = " . $ilDB->quote($a_user_id, "integer") .
5423  " AND anonymous_id = " . $ilDB->quote($a_anonymous_id, "integer"));
5424  }
5425 
5426  public function closeAppraisee($a_user_id)
5427  {
5428  global $DIC;
5429 
5430  $ilDB = $DIC->database();
5431  $user = $DIC->user();
5432 
5433  // close the appraisee
5434  $ilDB->manipulate("UPDATE svy_360_appr" .
5435  " SET has_closed = " . $ilDB->quote(time(), "integer") .
5436  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5437  " AND user_id = " . $ilDB->quote($a_user_id, "integer"));
5438 
5439  // write competences
5440  $skmg_set = new ilSkillManagementSettings();
5441  if ($this->getSkillService() && $skmg_set->isActivated()) {
5442  $sskill = new ilSurveySkill($this);
5443  $sskill->writeAndAddAppraiseeSkills($a_user_id);
5444  }
5445 
5446  // send notification
5447  if ($user->getId() != $a_user_id) {
5448  $this->sendAppraiseeCloseNotification($a_user_id);
5449  }
5450  }
5451 
5452  public function openAllAppraisees()
5453  {
5454  $ilDB = $this->db;
5455 
5456  $ilDB->manipulate("UPDATE svy_360_appr" .
5457  " SET has_closed = " . $ilDB->quote(null, "integer") .
5458  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer"));
5459  }
5460 
5461  public static function validateExternalRaterCode($a_ref_id, $a_code)
5462  {
5463  if (!isset($_SESSION["360_extrtr"][$a_ref_id])) {
5464  $svy = new self($a_ref_id);
5465  $svy->loadFromDB();
5466 
5467  if ($svy->canStartSurvey(null, true) &&
5468  $svy->get360Mode() &&
5469  $svy->isAnonymousKey($a_code)) {
5470  $anonymous_id = $svy->getAnonymousIdByCode($a_code);
5471  if ($anonymous_id) {
5472  if (sizeof($svy->getAppraiseesToRate(null, $anonymous_id))) {
5473  $_SESSION["360_extrtr"][$a_ref_id] = true;
5474  return true;
5475  }
5476  }
5477  }
5478 
5479  $_SESSION["360_extrtr"][$a_ref_id] = false;
5480  return false;
5481  }
5482 
5483  return $_SESSION["360_extrtr"][$a_ref_id];
5484  }
5485 
5486 
5487  //
5488  // reminder/notification
5489  //
5490 
5491  public function getReminderStatus()
5492  {
5493  return (bool) $this->reminder_status;
5494  }
5495 
5496  public function setReminderStatus($a_value)
5497  {
5498  $this->reminder_status = (bool) $a_value;
5499  }
5500 
5501  public function getReminderStart()
5502  {
5503  return $this->reminder_start;
5504  }
5505 
5506  public function setReminderStart(ilDate $a_value = null)
5507  {
5508  $this->reminder_start = $a_value;
5509  }
5510 
5511  public function getReminderEnd()
5512  {
5513  return $this->reminder_end;
5514  }
5515 
5516  public function setReminderEnd(ilDate $a_value = null)
5517  {
5518  $this->reminder_end = $a_value;
5519  }
5520 
5521  public function getReminderFrequency()
5522  {
5524  }
5525 
5526  public function setReminderFrequency($a_value)
5527  {
5528  $this->reminder_frequency = (int) $a_value;
5529  }
5530 
5531  public function getReminderTarget()
5532  {
5533  return $this->reminder_target;
5534  }
5535 
5536  public function setReminderTarget($a_value)
5537  {
5538  $this->reminder_target = (int) $a_value;
5539  }
5540 
5541  public function getReminderLastSent()
5542  {
5544  }
5545 
5546  public function setReminderLastSent($a_value)
5547  {
5548  $this->reminder_last_sent = $a_value;
5549  }
5550 
5555  public function getReminderTemplate($selectDefault = false)
5556  {
5557  if ($selectDefault) {
5558  $defaultTemplateId = 0;
5559  $this->getReminderMailTemplates($defaultTemplateId);
5560 
5561  if ($defaultTemplateId > 0) {
5562  return $defaultTemplateId;
5563  }
5564  }
5565 
5566  return $this->reminder_tmpl;
5567  }
5568 
5569  public function setReminderTemplate($a_value)
5570  {
5571  $this->reminder_tmpl = $a_value;
5572  }
5573 
5574  public function getTutorNotificationStatus()
5575  {
5576  return (bool) $this->tutor_ntf_status;
5577  }
5578 
5579  public function setTutorNotificationStatus($a_value)
5580  {
5581  $this->tutor_ntf_status = (bool) $a_value;
5582  }
5583 
5585  {
5587  }
5588 
5589  public function setTutorNotificationRecipients(array $a_value)
5590  {
5591  $this->tutor_ntf_recipients = $a_value;
5592  }
5593 
5594  public function getTutorNotificationTarget()
5595  {
5596  return $this->tutor_ntf_target;
5597  }
5598 
5599  public function setTutorNotificationTarget($a_value)
5600  {
5601  $this->tutor_ntf_target = (int) $a_value;
5602  }
5603 
5604  public function getTutorResultsStatus()
5605  {
5606  return (bool) $this->tutor_res_status;
5607  }
5608 
5609  public function setTutorResultsStatus($a_value)
5610  {
5611  $this->tutor_res_status = (bool) $a_value;
5612  }
5613 
5614  public function getTutorResultsRecipients()
5615  {
5617  }
5618 
5619  public function setTutorResultsRecipients(array $a_value)
5620  {
5621  $this->tutor_res_recipients = $a_value;
5622  }
5623 
5624  protected function checkTutorNotification()
5625  {
5626  $ilDB = $this->db;
5627 
5628  if ($this->getTutorNotificationStatus()) {
5629  $user_ids = $this->getNotificationTargetUserIds(($this->getTutorNotificationTarget() == self::NOTIFICATION_INVITED_USERS));
5630  if ($user_ids) {
5631  $set = $ilDB->query("SELECT COUNT(*) numall FROM svy_finished" .
5632  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
5633  " AND state = " . $ilDB->quote(1, "integer") .
5634  " AND " . $ilDB->in("user_fi", $user_ids, "", "integer"));
5635  $row = $ilDB->fetchAssoc($set);
5636  if ($row["numall"] == sizeof($user_ids)) {
5637  $this->sendTutorNotification();
5638  }
5639  }
5640  }
5641  }
5642 
5649  public function sent360Reminders()
5650  {
5651  global $DIC;
5652 
5653  $access = $DIC->access();
5654 
5655  // collect all open ratings
5656  $rater_ids = array();
5657  foreach ($this->getAppraiseesData() as $app) {
5658  $this->log->debug("Handle appraisee " . $app['user_id']);
5659 
5660  if (!$this->isAppraiseeClosed($app['user_id'])) {
5661  $this->log->debug("Check self evaluation, self: " . $this->get360SelfAppraisee() . ", target: " . $this->getReminderTarget());
5662 
5663  // self evaluation?
5664  if ($this->get360SelfEvaluation() &&
5666  $this->log->debug("...1");
5667  // did user already finished self evaluation?
5668  if (!$this->is360SurveyStarted($app['user_id'], $app['user_id'])) {
5669  $this->log->debug("...2");
5670  if (!is_array($rater_ids[$app['user_id']])) {
5671  $rater_ids[$app['user_id']] = array();
5672  }
5673  if (!in_array($app["user_id"], $rater_ids[$app['user_id']])) {
5674  $rater_ids[$app['user_id']][] = $app["user_id"];
5675  }
5676  }
5677  }
5678 
5679  $this->log->debug("Check raters.");
5680 
5681  // should raters be notified?
5683  foreach ($this->getRatersData($app['user_id']) as $rater) {
5684  // is rater not anonymous and did not rate yet?
5685  if (!$rater["anonymous_id"] && !$rater["finished"]) {
5686  if (!is_array($rater_ids[$rater["user_id"]])) {
5687  $rater_ids[$rater["user_id"]] = array();
5688  }
5689  if (!in_array($app["user_id"], $rater_ids[$rater["user_id"]])) {
5690  $rater_ids[$rater["user_id"]][] = $app["user_id"];
5691  }
5692  }
5693  }
5694  }
5695  }
5696  }
5697 
5698  $this->log->debug("Found raters:" . count($rater_ids));
5699 
5700  foreach ($rater_ids as $id => $app) {
5701  if ($access->checkAccessOfUser($id, "read", "", $this->getRefId())) {
5702  $this->send360ReminderToUser($id, $app);
5703  }
5704  }
5705  }
5706 
5712  public function send360ReminderToUser($a_user_id, $a_appraisee_ids)
5713  {
5714  $this->log->debug("Send mail to:" . $a_user_id);
5715 
5716  $ntf = new ilSystemNotification();
5717  $ntf->setLangModules(array("svy", "survey"));
5718  $ntf->setRefId($this->getRefId());
5719  $ntf->setGotoLangId('url');
5720 
5721  // user specific language
5722  $lng = $ntf->getUserLanguage($a_user_id);
5723 
5724  $ntf->setIntroductionLangId("svy_user_added_360_rater_reminder_mail");
5725  $subject = str_replace("%1", $this->getTitle(), $lng->txt("svy_user_added_360_rater"));
5726 
5727  foreach ($a_appraisee_ids as $appraisee_id) {
5728  $ntf->addAdditionalInfo("survey_360_appraisee", ilUserUtil::getNamePresentation($appraisee_id, false, false, "", true));
5729  }
5730 
5731  // #10044
5732  $mail = new ilMail(ANONYMOUS_USER_ID);
5733  $mail->enqueue(
5734  ilObjUser::_lookupLogin($a_user_id),
5735  null,
5736  null,
5737  $subject,
5738  $ntf->composeAndGetMessage($a_user_id, null, "read", true),
5739  []
5740  );
5741  }
5742 
5743 
5744  public function getNotificationTargetUserIds($a_use_invited)
5745  {
5746  $tree = $this->tree;
5747 
5748  if ((bool) $a_use_invited) {
5749  $user_ids = $this->invitation_manager->getAllForSurvey($this->getSurveyId());
5750  } else {
5751  $parent_grp_ref_id = $tree->checkForParentType($this->getRefId(), "grp");
5752  if ($parent_grp_ref_id) {
5753  $part = new ilGroupParticipants(ilObject::_lookupObjId($parent_grp_ref_id));
5754  $user_ids = $part->getMembers();
5755  } else {
5756  $parent_crs_ref_id = $tree->checkForParentType($this->getRefId(), "crs");
5757  if ($parent_crs_ref_id) {
5758  $part = new ilCourseParticipants(ilObject::_lookupObjId($parent_crs_ref_id));
5759  $user_ids = $part->getMembers();
5760  }
5761  }
5762  }
5763  return $user_ids;
5764  }
5765 
5766  protected function sendTutorNotification()
5767  {
5768  $link = ilLink::_getStaticLink($this->getRefId(), "svy");
5769 
5770  foreach ($this->getTutorNotificationRecipients() as $user_id) {
5771  // use language of recipient to compose message
5772  $ulng = ilLanguageFactory::_getLanguageOfUser($user_id);
5773  $ulng->loadLanguageModule('survey');
5774 
5775  $subject = sprintf($ulng->txt('survey_notification_tutor_subject'), $this->getTitle());
5776  $message = sprintf($ulng->txt('survey_notification_tutor_salutation'), ilObjUser::_lookupFullname($user_id)) . "\n\n";
5777 
5778  $message .= $ulng->txt('survey_notification_tutor_body') . ":\n\n";
5779  $message .= $ulng->txt('obj_svy') . ": " . $this->getTitle() . "\n";
5780  $message .= "\n" . $ulng->txt('survey_notification_tutor_link') . ": " . $link;
5781 
5782  $mail_obj = new ilMail(ANONYMOUS_USER_ID);
5783  $mail_obj->appendInstallationSignature(true);
5784  $mail_obj->enqueue(
5785  ilObjUser::_lookupLogin($user_id),
5786  "",
5787  "",
5788  $subject,
5789  $message,
5790  array()
5791  );
5792  }
5793  }
5794 
5795  public function checkReminder()
5796  {
5797  $ilDB = $this->db;
5798  $ilAccess = $this->access;
5799 
5800  $now = time();
5801  $now_with_format = date("YmdHis", $now);
5802  $today = date("Y-m-d");
5803 
5804  $this->log->debug("Check status and dates.");
5805 
5806  // object settings / participation period
5807  if (
5808  $this->getOfflineStatus() ||
5809  !$this->getReminderStatus() ||
5810  ($this->getStartDate() && $now_with_format < $this->getStartDate()) ||
5811  ($this->getEndDate() && $now_with_format > $this->getEndDate())) {
5812  return false;
5813  }
5814 
5815  // reminder period
5816  $start = $this->getReminderStart();
5817  if ($start) {
5818  $start = $start->get(IL_CAL_DATE);
5819  }
5820  $end = $this->getReminderEnd();
5821  if ($end) {
5822  $end = $end->get(IL_CAL_DATE);
5823  }
5824  if ($today < $start ||
5825  ($end && $today > $end)) {
5826  return false;
5827  }
5828 
5829  $this->log->debug("Check access period.");
5830 
5831  // object access period
5832  $item_data = ilObjectActivation::getItem($this->getRefId());
5833  if ($item_data["timing_type"] == ilObjectActivation::TIMINGS_ACTIVATION &&
5834  ($now < $item_data["timing_start"] ||
5835  $now > $item_data["timing_end"])) {
5836  return false;
5837  }
5838 
5839  $this->log->debug("Check frequency.");
5840 
5841  // check frequency
5842  $cut = new ilDate($today, IL_CAL_DATE);
5843  $cut->increment(IL_CAL_DAY, $this->getReminderFrequency() * -1);
5844  if (!$this->getReminderLastSent() ||
5845  $cut->get(IL_CAL_DATE) >= substr($this->getReminderLastSent(), 0, 10)) {
5846  $missing_ids = array();
5847 
5848  if (!$this->get360Mode()) {
5849  $this->log->debug("Entering survey mode.");
5850 
5851  // #16871
5852  $user_ids = $this->getNotificationTargetUserIds(($this->getReminderTarget() == self::NOTIFICATION_INVITED_USERS));
5853  if ($user_ids) {
5854  // gather participants who already finished
5855  $finished_ids = array();
5856  $set = $ilDB->query("SELECT user_fi FROM svy_finished" .
5857  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
5858  " AND state = " . $ilDB->quote(1, "text") .
5859  " AND " . $ilDB->in("user_fi", $user_ids, "", "integer"));
5860  while ($row = $ilDB->fetchAssoc($set)) {
5861  $finished_ids[] = $row["user_fi"];
5862  }
5863 
5864  // some users missing out?
5865  $missing_ids = array_diff($user_ids, $finished_ids);
5866  if ($missing_ids) {
5867  foreach ($missing_ids as $idx => $user_id) {
5868  // should be able to participate
5869  if (!$ilAccess->checkAccessOfUser($user_id, "read", "", $this->getRefId(), "svy", $this->getId())) {
5870  unset($missing_ids[$idx]);
5871  }
5872  }
5873  }
5874  if ($missing_ids) {
5875  $this->sentReminder($missing_ids);
5876  }
5877  }
5878  } else {
5879  $this->log->debug("Entering 360 mode.");
5880 
5881  $this->sent360Reminders();
5882  }
5883 
5884 
5885  $this->setReminderLastSent($today);
5886  $this->saveToDb();
5887 
5888  return sizeof($missing_ids);
5889  }
5890 
5891  return false;
5892  }
5893 
5894  protected function sentReminder(array $a_recipient_ids)
5895  {
5896  global $DIC;
5897 
5898  // use mail template
5899  if ($this->getReminderTemplate() &&
5900  array_key_exists($this->getReminderTemplate(), $this->getReminderMailTemplates())) {
5902  $templateService = $DIC['mail.texttemplates.service'];
5903  $tmpl = $templateService->loadTemplateForId((int) $this->getReminderTemplate());
5904 
5905  $tmpl_params = array(
5906  "ref_id" => $this->getRefId(),
5907  "ts" => time()
5908  );
5909  } else {
5910  $tmpl = null;
5911  $link = ilLink::_getStaticLink($this->getRefId(), "svy");
5912  }
5913 
5914  foreach ($a_recipient_ids as $user_id) {
5915  if ($tmpl) {
5916  $subject = $tmpl->getSubject();
5917  $message = $this->sentReminderPlaceholders($tmpl->getMessage(), $user_id, $tmpl_params);
5918  }
5919  // use lng
5920  else {
5921  // use language of recipient to compose message
5922  $ulng = ilLanguageFactory::_getLanguageOfUser($user_id);
5923  $ulng->loadLanguageModule('survey');
5924 
5925  $subject = sprintf($ulng->txt('survey_reminder_subject'), $this->getTitle());
5926  $message = sprintf($ulng->txt('survey_reminder_salutation'), ilObjUser::_lookupFullname($user_id)) . "\n\n";
5927 
5928  $message .= $ulng->txt('survey_reminder_body') . ":\n\n";
5929  $message .= $ulng->txt('obj_svy') . ": " . $this->getTitle() . "\n";
5930  $message .= "\n" . $ulng->txt('survey_reminder_link') . ": " . $link;
5931  }
5932 
5933  $mail_obj = new ilMail(ANONYMOUS_USER_ID);
5934  $mail_obj->appendInstallationSignature(true);
5935  $mail_obj->enqueue(
5936  ilObjUser::_lookupLogin($user_id),
5937  "",
5938  "",
5939  $subject,
5940  $message,
5941  array()
5942  );
5943  }
5944  }
5945 
5946  public function setActivationStartDate($starting_time = null)
5947  {
5948  $this->activation_starting_time = $starting_time;
5949  }
5950 
5951  public function setActivationEndDate($ending_time = null)
5952  {
5953  $this->activation_ending_time = $ending_time;
5954  }
5955 
5956  public function getActivationStartDate()
5957  {
5958  return (strlen($this->activation_starting_time)) ? $this->activation_starting_time : null;
5959  }
5960 
5961  public function getActivationEndDate()
5962  {
5963  return (strlen($this->activation_ending_time)) ? $this->activation_ending_time : null;
5964  }
5965 
5966  public function setViewOwnResults($a_value)
5967  {
5968  $this->view_own_results = (bool) $a_value;
5969  }
5970 
5971  public function hasViewOwnResults()
5972  {
5973  return $this->view_own_results;
5974  }
5975 
5976  public function setMailOwnResults($a_value)
5977  {
5978  $this->mail_own_results = (bool) $a_value;
5979  }
5980 
5981  public function hasMailOwnResults()
5982  {
5983  return $this->mail_own_results;
5984  }
5985 
5986  public function setMailConfirmation($a_value)
5987  {
5988  $this->mail_confirmation = (bool) $a_value;
5989  }
5990 
5991  public function hasMailConfirmation()
5992  {
5993  return $this->mail_confirmation;
5994  }
5995 
5996  public function setAnonymousUserList($a_value)
5997  {
5998  $this->anon_user_list = (bool) $a_value;
5999  }
6000 
6001  public function hasAnonymousUserList()
6002  {
6003  return $this->anon_user_list;
6004  }
6005 
6006  public static function getSurveySkippedValue()
6007  {
6008  global $DIC;
6009 
6010  $lng = $DIC->language();
6011 
6012  // #13541
6013 
6014  $surveySetting = new ilSetting("survey");
6015  if (!$surveySetting->get("skipped_is_custom", false)) {
6016  return $lng->txt("skipped");
6017  } else {
6018  return $surveySetting->get("skipped_custom_value", "");
6019  }
6020  }
6021 
6026  public function getReminderMailTemplates(&$defaultTemplateId = null)
6027  {
6028  global $DIC;
6029 
6030  $res = array();
6031 
6033  $templateService = $DIC['mail.texttemplates.service'];
6034  foreach ($templateService->loadTemplatesForContextId((string) ilSurveyMailTemplateReminderContext::ID) as $tmpl) {
6035  $res[$tmpl->getTplId()] = $tmpl->getTitle();
6036  if (null !== $defaultTemplateId && $tmpl->isDefault()) {
6037  $defaultTemplateId = $tmpl->getTplId();
6038  }
6039  }
6040 
6041  return $res;
6042  }
6043 
6044  protected function sentReminderPlaceholders($a_message, $a_user_id, array $a_context_params)
6045  {
6046  // see ilMail::replacePlaceholders()
6047  try {
6049 
6050  $user = new \ilObjUser($a_user_id);
6051 
6052  $processor = new \ilMailTemplatePlaceholderResolver($context, $a_message);
6053  $a_message = $processor->resolve($user, $a_context_params);
6054  } catch (\Exception $e) {
6055  ilLoggerFactory::getLogger('mail')->error(__METHOD__ . ' has been called with invalid context.');
6056  }
6057 
6058  return $a_message;
6059  }
6060 
6061  public function setMode($a_value)
6062  {
6063  $this->mode = $a_value;
6064  }
6065 
6066  public function getMode()
6067  {
6068  return $this->mode;
6069  }
6070 
6071  public function setSelfEvaluationResults($a_value)
6072  {
6073  $this->mode_self_eval_results = $a_value;
6074  }
6075 
6076  public function getSelfEvaluationResults()
6077  {
6079  }
6080 
6081  public static function getSurveysWithTutorResults()
6082  {
6083  global $ilDB;
6084 
6085  $res = array();
6086 
6088 
6089 
6090  $q = "SELECT obj_fi FROM svy_svy" .
6091  " WHERE tutor_res_cron IS NULL" .
6092  " AND tutor_res_status = " . $ilDB->quote(1, "integer") .
6093  " AND enddate < " . $ilDB->quote(date("Ymd000000"), "text");
6094 
6095  if (DEVMODE) {
6096  $q = "SELECT obj_fi FROM svy_svy" .
6097  " WHERE tutor_res_status = " . $ilDB->quote(1, "integer") .
6098  " AND enddate < " . $ilDB->quote(date("Ymd000000"), "text");
6099  }
6100 
6101  $set = $ilDB->query($q);
6102 
6103  $log->debug($q);
6104 
6105  while ($row = $ilDB->fetchAssoc($set)) {
6106  $res[] = $row["obj_fi"];
6107  }
6108 
6109  return $res;
6110  }
6111 
6112  public function sendTutorResults()
6113  {
6114  global $ilCtrl, $ilDB;
6115 
6117 
6118  include_once "./Services/Mail/classes/class.ilMail.php";
6119  include_once "./Services/User/classes/class.ilObjUser.php";
6120  include_once "./Services/Language/classes/class.ilLanguageFactory.php";
6121  include_once "./Services/User/classes/class.ilUserUtil.php";
6122 
6123  include_once "./Services/Link/classes/class.ilLink.php";
6124  $link = ilLink::_getStaticLink($this->getRefId(), "svy");
6125 
6126  // somehow needed in cron-calls
6127  //$ilCtrl->setTargetScript("ilias.php");
6128  //$ilCtrl->initBaseClass("ilobjsurveygui");
6129 
6130  // yeah, I know...
6131  $old_ref_id = $_GET["ref_id"];
6132  $old_base_class = $_GET["baseClass"];
6133  $_GET["ref_id"] = $this->getRefId();
6134  $ilCtrl->setTargetScript("ilias.php");
6135  $_GET["baseClass"] = "ilObjSurveyGUI";
6136 
6137  $ilCtrl->setParameterByClass("ilSurveyEvaluationGUI", "ref_id", $this->getRefId());
6138 
6139  try {
6140  $gui = new ilSurveyEvaluationGUI($this);
6141  $html = $gui->evaluation(1, true, true);
6142  } catch (Exception $exception) {
6143  $_GET["ref_id"] = $old_ref_id;
6144  $_GET["baseClass"] = $old_base_class;
6145  throw $exception;
6146  }
6147  $_GET["ref_id"] = $old_ref_id;
6148  $_GET["baseClass"] = $old_base_class;
6149 
6150  $html = preg_replace("/\?dummy\=[0-9]+/", "", $html);
6151  $html = preg_replace("/\?vers\=[0-9A-Za-z\-]+/", "", $html);
6152  $html = str_replace('.css$Id$', ".css", $html);
6153  $html = preg_replace("/src=\"\\.\\//ims", "src=\"" . ILIAS_HTTP_PATH . "/", $html);
6154  $html = preg_replace("/href=\"\\.\\//ims", "href=\"" . ILIAS_HTTP_PATH . "/", $html);
6155 
6156  $log->debug("--pdf start, ref id " . $this->getRefId());
6157  $log->debug("html length: " . strlen($html));
6158  $log->debug("html (first 1000 chars): " . substr($html, 0, 1000));
6159  //echo $html; exit;
6160  $pdf_factory = new ilHtmlToPdfTransformerFactory();
6161  $pdf = $pdf_factory->deliverPDFFromHTMLString($html, "survey.pdf", ilHtmlToPdfTransformerFactory::PDF_OUTPUT_FILE, "Survey", "Results");
6162  $log->debug("--pdf end");
6163 
6164  /*
6165  $log->debug("calling phantom for ref_id: " . $this->getRefId());
6166 
6167  $pdf = $gui->callPdfGeneration($url, "pdf", true, true);
6168 
6169  $log->debug("phantom called : " . $pdf);*/
6170 
6171  if (!$pdf ||
6172  !file_exists($pdf)) {
6173  return false;
6174  }
6175 
6176  // prepare mail attachment
6177  require_once 'Services/Mail/classes/class.ilFileDataMail.php';
6178  $att = "survey_" . $this->getRefId() . ".pdf";
6179  $mail_data = new ilFileDataMail(ANONYMOUS_USER_ID);
6180  $mail_data->copyAttachmentFile($pdf, $att);
6181 
6182  foreach ($this->getTutorResultsRecipients() as $user_id) {
6183  // use language of recipient to compose message
6184  $ulng = ilLanguageFactory::_getLanguageOfUser($user_id);
6185  $ulng->loadLanguageModule('survey');
6186 
6187  $subject = sprintf($ulng->txt('survey_results_tutor_subject'), $this->getTitle());
6188  $message = sprintf($ulng->txt('survey_notification_tutor_salutation'), ilObjUser::_lookupFullname($user_id)) . "\n\n";
6189 
6190  $message .= $ulng->txt('survey_results_tutor_body') . ":\n\n";
6191  $message .= $ulng->txt('obj_svy') . ": " . $this->getTitle() . "\n";
6192  $message .= "\n" . $ulng->txt('survey_notification_tutor_link') . ": " . $link;
6193 
6194  $mail_obj = new ilMail(ANONYMOUS_USER_ID);
6195  $mail_obj->appendInstallationSignature(true);
6196  $log->debug("send mail to user id: " . $user_id . ",login: " . ilObjUser::_lookupLogin($user_id));
6197  $mail_obj->enqueue(
6198  ilObjUser::_lookupLogin($user_id),
6199  "",
6200  "",
6201  $subject,
6202  $message,
6203  array($att)
6204  );
6205  }
6206 
6207  $ilDB->manipulate("UPDATE svy_svy" .
6208  " SET tutor_res_cron = " . $ilDB->quote(1, "integer") .
6209  " WHERE survey_id = " . $ilDB->quote($this->getSurveyId(), "integer"));
6210 
6211  return true;
6212  }
6213 } // END class.ilObjSurvey
createSurveyCodes($nrOfCodes)
setTutorResultsRecipients(array $a_value)
showQuestionTitles()
Sets the question titles visible during the query.
static _lookupLogin($a_user_id)
lookup login
$app
Definition: cli.php:38
static sortArray( $array, $a_array_sortby, $a_array_sortorder=0, $a_numeric=false, $a_keep_keys=false)
sortArray
static _lookupName($a_user_id)
lookup user name
xslt_create()
static getUserIdsByEmail($a_email)
STATIC METHOD get all user_ids of an email address.
set360RaterSent($a_appraisee_id, $a_user_id, $a_anonymous_id, $a_tstamp=null)
static makeDirParents($a_dir)
Create a new directory and all parent directories.
deliverPDFfromFO($fo)
Delivers a PDF file from a XSL-FO string.
static _instanciateQuestion($question_id)
Creates an instance of a question with a given question id.
static deliverData($a_data, $a_filename, $mime="application/octet-stream", $charset="")
deliver data for download via browser.
static _getMobsOfObject($a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
get mobs of object
getAppraiseesToRate($a_user_id, $a_anonymous_id=null)
getUserSurveyExecutionStatus($a_code=null)
createNewAccessCode()
Returns a new, unused survey access code.
updateConjunctionForQuestions($questions, $conjunction)
is360SurveyStarted($appr_id, $user_id, $anonymous_code=null)
& getQuestionpoolTitles($could_be_offline=false, $showPath=false)
Get the titles of all available survey question pools.
$size
Definition: RandomTest.php:84
setEndDateAndTime($end_date="", $end_time)
Sets the end date of the survey.
isAnonymizedParticipant($key)
sentReminderPlaceholders($a_message, $a_user_id, array $a_context_params)
__construct($a_id=0, $a_call_by_reference=true)
Constructor public.
& getSurveyPages()
Returns the survey pages in an array (a page contains one or more questions)
$context
Definition: webdav.php:26
deleteRater($a_appraisee_id, $a_user_id, $a_anonymous_id=0)
$data
Definition: storeScorm.php:23
getReminderTemplate($selectDefault=false)
const IL_CAL_DATETIME
& getEvaluationByUser($questions, $active_id)
Calculates the evaluation data for a given user or anonymous id.
processPrintoutput2FO($print_output)
Convert a print output to XSL-FO.
setReminderLastSent($a_value)
$_SESSION["AccountId"]
$result
static _getUsedHTMLTagsAsString($a_module="")
Returns a string of all allowed HTML tags for text editing.
set360Results($a_value)
const EVALUATION_ACCESS_OFF
getParticipantTextResults($active_id)
applySettingsTemplate($template_id)
Apply settings template.
& getSurveyFinishedIds()
Get the finished id&#39;s of all survey participants.
getQuestionGUI($questiontype, $question_id)
Returns a question gui object to a given questiontype and question id.
static validateExternalRaterCode($a_ref_id, $a_code)
static is_email($a_email, ilMailRfc822AddressParserFactory $mailAddressParserFactory=null)
This preg-based function checks whether an e-mail address is formally valid.
setMailNotification($a_notification)
saveUserSettings($usr_id, $key, $title, $value)
getConstraints($question_id)
Returns the constraints to a given question or questionblock.
const EVALUATION_ACCESS_PARTICIPANTS
$_GET["client_id"]
Class ilFileDataMail.
setTutorNotificationTarget($a_value)
static getSurveySkippedValue()
static _lookupFullname($a_user_id)
Lookup Full Name.
deleteSurveyCode($survey_code)
Deletes a given survey access code.
& getSurveyParticipants($finished_ids=null, $force_non_anonymous=false, $include_invites=false)
getWorkingtimeForParticipant($finished_id)
deleteAllUserData($reset_LP=true)
Deletes all user data of a survey.
getSurveyId()
Returns the survey database id.
updateMetaData()
update meta data entry
xslt_free(&$proc)
getSurveyCodesForExport(array $a_codes=null, array $a_ids=null)
Returns a list of survey codes for file export.
static prepareTextareaOutput($txt_output, $prepare_for_latex_output=false, $omitNl2BrWhenTextArea=false)
Prepares a string for a text area output where latex code may be in it If the text is HTML-free...
isComplete()
Returns 1, if a survey is complete for use.
removeQuestions($remove_questions, $remove_questionblocks)
Remove questions from the survey.
static _hasDatasets($survey_id)
getAnonymousIdByCode($a_code)
Class ilObjSurvey.
isAccessibleWithoutCode()
Checks if the survey is accessable without a survey code.
read()
read object data from db into object public
static factory($a_package, $a_timeout=0)
Creates an ilRpcClient instance to our ilServer.
canStartSurvey($anonymous_id=null, $a_no_rbac=false)
Checks if the survey can be started.
if(!array_key_exists('PATH_INFO', $_SERVER)) $config
Definition: metadata.php:68
setReminderFrequency($a_value)
removeQuestion($question_id)
Remove a question from the survey.
static getItem($a_ref_id)
Get item data.
static _getObjectsByOperations($a_obj_type, $a_operation, $a_usr_id=0, $limit=0)
Get all objects of a specific type and check access This function is not recursive, instead it parses the serialized rbac_pa entries.
deleteConstraint($constraint_id)
Deletes a constraint of a question.
getOfflineStatus()
Get offline status.
setAuthor($author="")
Sets the authors name of the ilObjSurvey object.
const NOTIFICATION_APPRAISEES
sendAppraiseeCloseNotification($a_user_id)
Send appraisee notification.
static _isComplete($question_id)
Checks whether the question is complete or not.
static unzip($a_file, $overwrite=false, $a_flat=false)
unzip file
static _includeClass($question_type, $gui=0)
Include the php class file for a given question type.
static _getQuestionType($question_id)
Returns the question type of a question with a given id.
XML writer class.
getUserDataFromActiveId($active_id, $force_non_anonymous=false)
Returns the user information from an active_id (survey_finished.finished_id)
sendAppraiseeNotification($a_user_id)
Send appraisee notification.
prepareTextareaOutput($txt_output)
Prepares a string for a text area output in surveys.
setPoolUsage($a_value)
Import class.
setSkillService($a_val)
Set skill service.
& getVariables($question_id)
Returns all variables of a question.
locateImportFiles($a_dir)
Locates the import directory and the xml file in a directory with an unzipped import file...
getIntroduction()
Gets the introduction text.
unfoldQuestionblocks($questionblocks)
Unfolds question blocks of a question pool.
static _lookupTitle($a_id)
lookup object title
create($a_upload=false)
create survey object
getAnonymize()
get anonymize status
setViewOwnResults($a_value)
sendNotificationMail($a_user_id, $a_anonymize_id, $a_appr_id)
getUserAccessCode($user_id)
Returns a survey access code that was saved for a registered user.
static _getConstraints($survey_id)
Returns the constraints to a given question or questionblock.
closeAppraisee($a_user_id)
bindSurveyCodeToUser($user_id, $code)
setTutorNotificationStatus($a_value)
Survey Question Import Parser.
setObligatoryStates($obligatory_questions)
Sets the obligatory states for questions in a survey from the questions form.
const IL_CAL_UNIX
static _removeUsage($a_mob_id, $a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
Remove usage of mob in another container.
getLastAccess($finished_id)
static _saveTempFileAsMediaObject($name, $tmp_name, $upload=true)
Create new media object and update page in db and return new media object.
static _getQuestionGUI($questiontype, $question_id=-1)
Creates a question gui representation.
static getASCIIFilename($a_filename)
convert utf8 to ascii filename
static _replaceMediaObjectImageSrc($a_text, $a_direction=0, $nic=IL_INST_ID)
Replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
static formatDate(ilDateTime $date, $a_skip_day=false, $a_include_wd=false, $include_seconds=false)
Format a date public.
Survey exception class.
canExportSurveyCode()
Checks if the survey code can be exported with the survey evaluation.
user()
Definition: user.php:4
$total
Definition: Utf8Test.php:87
getAllRelations($short_as_key=false)
Returns all available relations.
& getQuestionblockQuestions($questionblock_id)
Returns the question titles of all questions of a question block.
$index
Definition: metadata.php:128
addRater($a_appraisee_id, $a_user_id, $a_anonymous_id=0)
setMailAddresses($a_addresses)
removeQuestionFromBlock($question_id, $questionblock_id)
getSurveyCodesTableData(array $ids=null, $lang=null)
Fetches the data for the survey codes table.
global $ilCtrl
Definition: ilias.php:18
Skill/Competence handling in surveys.
removeConstraintsConcerningQuestion($question_id)
Remove constraints concerning a question with a given question_id.
insertQuestion($question_id)
Inserts a question in the survey and saves the relation to the database.
getUserSpecificResults($finished_ids)
Calculates the evaluation data for the user specific results.
removeSelectedSurveyResults($finished_ids)
Deletes the user data of a given array of survey participants.
getEndDate()
Gets the end date of the survey.
insertQuestionblock($questionblock_id)
Inserts a questionblock in the survey and saves the relation to the database.
setStartTime($finished_id, $first_question)
setReminderEnd(ilDate $a_value=null)
xslt_error(&$proc)
if($format !==null) $name
Definition: metadata.php:230
getAuthor()
Gets the authors name of the ilObjSurvey object.
isHTML($a_text)
Checks if a given string contains HTML or not.
hideQuestionTitles()
Sets the question titles hidden during the query.
saveQuestionsToDb()
Saves the survey questions to the database.
duplicateQuestionForSurvey($question_id, $a_force=false)
Takes a question and creates a copy of the question for use in the survey.
const IL_CAL_DAY
$messages
Definition: xapiexit.php:5
deleteSurveyRecord()
Deletes the survey from the database.
updateConstraint($precondition_id, $if_question_id, $relation, $value, $conjunction)
Updates a precondition.
isPluginActive($a_pname)
Checks whether or not a question plugin with a given name is active.
setAnonymousUserList($a_value)
update($a_upload=false)
update object data
static _getInstance($a_copy_id)
Get instance of copy wizard options.
hasAnonymizedResults()
Checks if the survey results are to be anonymized.
isAppraisee($a_user_id)
static _getOriginalId($question_id, $a_return_question_id_if_no_original=true)
Returns the original id of a question.
getNextPage($active_page_question_id, $direction)
Returns the next "page" of a running test.
setReminderTemplate($a_value)
Class for single dates.
foreach($_POST as $key=> $value) $res
setReminderTarget($a_value)
getLastActivePage($active_id)
Returns the question id of the last active page a user visited in a survey.
& getSurveyQuestions($with_answers=false)
Returns the survey questions and questionblocks in an array.
$mobs
getId()
get object id public
static _instanciateQuestionEvaluation($question_id, array $a_finished_ids=null)
Creates an instance of a question evaluation with a given question id.
const ANONYMIZE_FREEACCESS
set360SelfEvaluation($a_value)
Class ilHtmlToPdfTransformerFactory.
isUnusedCode($a_code, $a_user_id)
setShowQuestionTitles($a_show)
Sets the status of the display_question_titles attribute.
loadFromDb()
Loads a survey object from a database.
setActivationLimited($a_value)
const NOTIFICATION_PARENT_COURSE
setMailParticipantData($a_data)
const RESULTS_SELF_EVAL_OWN
const NOTIFICATION_APPRAISEES_AND_RATERS
getFinishedIdsForAppraiseeId($a_appr_id, $a_exclude_appraisee=false)
updateCode($a_id, $a_email, $a_last_name, $a_first_name, $a_sent)
static moveUploadedFile($a_file, $a_name, $a_target, $a_raise_errors=true, $a_mode="move_uploaded")
move uploaded file
updateOrder(array $a_order)
setActivationStartDate($starting_time=null)
getEvaluationAccess()
Gets the learners evaluation access.
static _lookupObjId($a_id)
setActivationVisibility($a_value)
addQuestion($question_id)
Adds a question to the survey (used in importer!)
const QUESTIONTITLES_VISIBLE
getImportDirectory()
get import directory of survey
getQuestionblocksTable($arrFilter)
Calculates the data for the output of the questionblock browser.
const QUESTIONTITLES_HIDDEN
getQuestionType($question_id)
Returns the question type of a question with a given id.
setMailOwnResults($a_value)
setReminderStart(ilDate $a_value=null)
if(!defined('PATH_SEPARATOR')) $GLOBALS['_PEAR_default_error_mode']
Definition: PEAR.php:64
setTutorNotificationRecipients(array $a_value)
setIntroduction($introduction="")
Sets the introduction text.
getTitle()
get object title public
getDescription()
get object description
const IL_COMP_MODULE
$ilUser
Definition: imgupload.php:18
set360SelfRaters($a_value)
getShowQuestionTitles()
Gets the status of the display_question_titles attribute.
cloneMetaData($target_obj)
Copy meta data.
toXML()
Returns a QTI xml representation of the survey.
xmlHeader()
Writes xml header public.
setSelfEvaluationResults($a_value)
static _addQuestionblock($title="", $owner=0, $show_questiontext=true, $show_blocktitle=false)
Adds a questionblock to the database.
addConstraintToQuestion($to_question_id, $constraint_id)
Adds a constraint to a question.
$xml
Definition: metadata.php:332
importSurveyCode($a_anonymize_key, $a_created, $a_data)
Class ilObjMediaObject.
setSurveyId($survey_id)
Sets the survey id.
static stripSlashes($a_str, $a_strip_html=true, $a_allow="")
strip slashes if magic qoutes is enabled
isQuestionInAnyBlock($a_question_fi)
Is question already in a block?
static getNamePresentation( $a_user_id, $a_user_image=false, $a_profile_link=false, $a_profile_back_link="", $a_force_first_lastname=false, $a_omit_login=false, $a_sortable=true, $a_return_data_array=false, $a_ctrl_path="ilpublicuserprofilegui")
Default behaviour is:
createQuestionblock($title, $show_questiontext, $show_blocktitle, $questions)
Creates a question block for the survey.
const NOTIFICATION_INVITED_USERS
getExportDirectory()
get export directory of survey
static _instanciateQuestion($question_id)
Creates an instance of a question with a given question id.
static _getQuestionblock($questionblock_id)
Returns the database row for a given question block.
setMailConfirmation($a_value)
setReminderStatus($a_value)
setPage($finished_id, $page_id)
Sets the number of the active survey page.
getType()
get object type public
getNotificationTargetUserIds($a_use_invited)
setEvaluationAccess($evaluation_access=self::EVALUATION_ACCESS_OFF)
Sets the learners evaluation access.
createImportDirectory()
creates data directory for import files (data_dir/svy_data/svy_<id>/import, depending on data directo...
createExportDirectory()
creates data directory for export files (data_dir/svy_data/svy_<id>/export, depending on data directo...
setTimingType($a_type)
Set timing type.
static makeDir($a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...
setEndDate($end_date="")
Sets the end date of the survey.
static _getLanguageOfUser($a_usr_id)
Get language object of user.
send360ReminderToUser($a_user_id, $a_appraisee_ids)
Send rater notification.
& getUserData($ids)
Returns a data of all users specified by id list.
finishSurvey($finished_id)
Finishes the survey creating an entry in the database.
$rows
Definition: xhr_table.php:10
const EVALUATION_ACCESS_ALL
getFinishedIdForAppraiseeIdAndRaterId($a_appr_id, $a_rat_id)
Get finished id for an appraisee and a rater.
deleteWorkingData($question_id, $active_id)
Deletes the working data of a question in the database.
$lang
Definition: xapiexit.php:8
saveCompletionStatus()
Saves the completion status of the survey.
static ilTempnam($a_temp_path=null)
Returns a unique and non existing Path for e temporary file or directory.
static getSurveysWithTutorResults()
setEndTime($finished_id)
getExternalCodeRecipients($a_check_finished=false)
getStartDate()
Gets the start date of the survey.
checkConstraint($constraint_data, $working_data)
Checks if a constraint is valid.
& getAvailableQuestionpools($use_obj_id=false, $could_be_offline=false, $showPath=false, $permission="read")
Returns the available question pools for the active user.
createSurveyCodesForExternalData($data)
const IL_CAL_DATE
saveUserAccessCode($user_id, $access_code)
Saves a survey access code for a registered user to the database.
cloneTextblocks($mapping)
Clones the textblocks of survey questions.
saveToDb()
Saves a survey object to a database.
static getDataDir()
get data directory (outside webspace)
createMetaData()
Create meta data entry.
& getExistingQuestions()
Gets the question id&#39;s of the questions which are already in the survey.
getQuestionsTable($arrFilter)
Calculates the data for the output of the question browser.
saveHeading($heading="", $insertbefore)
setOfflineStatus($a_status)
Set offline status.
getRatersData($a_appraisee_id)
static _lookupEmail($a_user_id)
Lookup email.
__construct(Container $dic, ilPlugin $plugin)
isRater($a_appraisee_id, $a_user_id, $a_anonymous_id=0)
isSurveyFinishedByCode($a_code)
Get if survey is finished for an specific anonymous user code.
addAppraisee($a_user_id)
setStartDateAndTime($start_date="", $start_time)
Sets the start date of the survey.
addConstraint($if_question_id, $relation, $value, $conjunction)
Adds a constraint.
isQuestionInSurvey($a_question_fi)
Check if a question is already in the survey.
getSkillService()
Get skill service.
global $ilDB
$DIC
Definition: xapitoken.php:46
saveAuthorToMetadata($a_author="")
Saves an authors name into the lifecycle metadata if no lifecycle metadata exists This will only be c...
const RESULTS_SELF_EVAL_NONE
getRefId()
get reference id public
getAnonymousId($id)
Checks for an anomyous survey id in the database an returns the id.
countReferences()
count references of object
setTutorResultsStatus($a_value)
deleteMetaData()
delete meta data entry
$message
Definition: xapiexit.php:14
getTextblock($question_id)
findCodeForUser($a_user_id)
getActiveID($user_id, $anonymize_id, $appr_id)
Checks if a user already started a survey.
setTemplate($template_id)
static getLogger($a_component_id)
Get component logger.
$url
getOutro()
Gets the outro text.
getUserSettings($usr_id, $key)
const IL_CAL_TIMESTAMP
Survey evaluation graphical output.
update()
update object in db
set360SelfAppraisee($a_value)
const ANONYMIZE_CODE_ALL
sendCodes($not_sent, $subject, $message, $lang)
modifyQuestionblock($questionblock_id, $title, $show_questiontext, $show_blocktitle)
Modifies a question block.
Class ilInvalidSurveyImportFileException.
moveQuestions($move_questions, $target_index, $insert_mode)
Move questions and/or questionblocks to another position.
isPoolActive()
Get current pool status.
addMaterialTag(&$a_xml_writer, $a_material, $close_material_tag=true, $add_mobs=true, $attribs=null)
Creates an XML material tag from a plain text or xhtml text.
loadWorkingData($question_id, $active_id)
Gets the working data of question from the database.
setStartDate($start_date="")
Sets the start date of the survey.
static getInstance($a_obj_id)
static delDir($a_dir, $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
static _getAvailableQuestionpools($use_object_id=false, $could_be_offline=false, $showPath=false, $permission="read")
Returns the available question pools for the active user.
static _saveUsage($a_mob_id, $a_type, $a_id, $a_usage_hist_nr=0, $a_lang="-")
Save usage of mob within another container (e.g.
deleteConstraints($question_id)
Deletes the constraints for a question.
importObject($file_info, $svy_qpl_id)
Imports a survey from XML into the ILIAS database.
Class ilObjectActivation.
static _getUserData($a_internalids)
return user data for given user ids
$source
Definition: metadata.php:76
Wrapper classes for system notifications.
isAppraiseeClosed($a_user_id)
$_POST["username"]
const RESULTS_SELF_EVAL_ALL
startSurvey($user_id, $anonymous_id, $appraisee_id)
Starts the survey creating an entry in the database.
setAnonymize($a_anonymize)
set anonymize status
setActivationEndDate($ending_time=null)
Settings template application class.
& getQuestionblockQuestionIds($questionblock_id)
Returns the question id&#39;s of all questions of a question block.
sendRaterNotification($a_user_id, $a_appraisee_id)
Send rater notification.
isSurveyStarted($user_id, $anonymize_id, $appr_id=0)
Checks if a user already started a survey.
loadQuestionsFromDb()
Loads the survey questions from the database.
sent360Reminders()
Send 360 reminders.
deleteAppraisee($a_user_id)
for($i=6; $i< 13; $i++) for($i=1; $i< 13; $i++) $d
Definition: date.php:296
setOutro($outro="")
Sets the outro text.
fixSequenceStructure()
Remove duplicate sequence entries, see #22018.
$i
Definition: metadata.php:24
getPrecondition($id)
Returns a precondition with a given id.
addQuestionToBlock($question_id, $questionblock_id)