ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilObjSurvey.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 include_once "./Services/Object/classes/class.ilObject.php";
5 
15 class ilObjSurvey extends ilObject
16 {
20  protected $user;
21 
25  protected $access;
26 
30  protected $plugin_admin;
31 
35 
36  const INVITATION_OFF = 0;
37  const INVITATION_ON = 1;
38 
39  const MODE_UNLIMITED = 0;
41 
42  const ANONYMIZE_OFF = 0; // personalized, no codes
43  const ANONYMIZE_ON = 1; // anonymized, codes
44  const ANONYMIZE_FREEACCESS = 2; // anonymized, no codes
45  const ANONYMIZE_CODE_ALL = 3; // personalized, codes
46 
49 
50  // constants to define the print view values.
51  const PRINT_HIDE_LABELS = 1; // Show only the titles in "print" and "PDF Export"
52  const PRINT_SHOW_LABELS = 3; // Show titles and labels in "print" and "PDF Export"
53 
60  public $survey_id;
61 
68  public $author;
69 
75  public $introduction;
76 
82  public $outro;
83 
84 
91 
97  public $start_date;
98 
104  public $end_date;
105 
111  public $questions;
112 
118  public $invitation;
119 
126 
131  public $anonymize;
132 
138 
145 
149  public $template_id;
150  public $pool_usage;
151 
155  protected $log;
156 
160 
161  // 360°
162  protected $mode_360_self_eval; // [bool]
163  protected $mode_360_self_appr; // [bool]
164  protected $mode_360_self_rate; // [bool]
165  protected $mode_360_results; // [int]
166  protected $mode_skill_service; // [bool]
167 
168  const RESULTS_360_NONE = 0;
169  const RESULTS_360_OWN = 1;
170  const RESULTS_360_ALL = 2;
171 
172  // reminder/notification
173  protected $reminder_status; // [bool]
174  protected $reminder_start; // [ilDate]
175  protected $reminder_end; // [ilDate]
176  protected $reminder_frequency; // [int]
177  protected $reminder_target; // [int]
178  protected $reminder_last_sent; // [bool]
179  protected $reminder_tmpl; // [int]
180  protected $tutor_ntf_status; // [bool]
181  protected $tutor_ntf_recipients; // [array]
182  protected $tutor_ntf_target; // [int]
183 
184  protected $view_own_results; // [bool]
185  protected $mail_own_results; // [bool]
186  protected $mail_confirmation; // [bool]
187 
188  protected $anon_user_list; // [bool]
189 
195 
196  protected $mode; //[int]
197  protected $mode_self_eval_results; //[int]
198 
199  //MODE TYPES
200  const MODE_STANDARD = 0;
201  const MODE_360 = 1;
202  const MODE_SELF_EVAL = 2;
203 
204  //self evaluation only access to results
208 
209 
216  public function __construct($a_id = 0, $a_call_by_reference = true)
217  {
218  global $DIC;
219 
220  $this->user = $DIC->user();
221  $this->lng = $DIC->language();
222  $this->db = $DIC->database();
223  $this->access = $DIC->access();
224  $this->log = $DIC["ilLog"];
225  $this->plugin_admin = $DIC["ilPluginAdmin"];
226  $this->tree = $DIC->repositoryTree();
227  $ilUser = $DIC->user();
228  $lng = $DIC->language();
229 
230  $this->type = "svy";
231  $this->survey_id = -1;
232  $this->introduction = "";
233  $this->outro = $lng->txt("survey_finished");
234  $this->author = $ilUser->getFullname();
235  $this->evaluation_access = self::EVALUATION_ACCESS_OFF;
236  $this->questions = array();
237  $this->invitation = self::INVITATION_OFF;
238  $this->invitation_mode = self::MODE_PREDEFINED_USERS;
239  $this->anonymize = self::ANONYMIZE_OFF;
240  $this->display_question_titles = self::QUESTIONTITLES_VISIBLE;
241  $this->surveyCodeSecurity = true;
242  $this->template_id = null;
243  $this->pool_usage = true;
244  $this->log = ilLoggerFactory::getLogger("svy");
245  $this->mode = self::MODE_STANDARD;
246  $this->mode_self_eval_results = self::RESULTS_SELF_EVAL_OWN;
247 
248  parent::__construct($a_id, $a_call_by_reference);
249  }
250 
254  public function create($a_upload = false)
255  {
256  parent::create();
257  if (!$a_upload) {
258  $this->createMetaData();
259  }
260  $this->setOfflineStatus(true);
261  $this->update($a_upload);
262  }
263 
269  public function createMetaData()
270  {
271  parent::createMetaData();
272  $this->saveAuthorToMetadata();
273  }
274 
281  public function update($a_upload = false)
282  {
283  if (!$a_upload) {
284  $this->updateMetaData();
285  }
286 
287  if (!parent::update()) {
288  return false;
289  }
290 
291  // put here object specific stuff
292 
293  return true;
294  }
295 
296  public function createReference()
297  {
298  $result = parent::createReference();
299  $this->saveToDb();
300  return $result;
301  }
302 
307  public function read()
308  {
309  parent::read();
310  $this->loadFromDb();
311  }
312 
319  public function addQuestion($question_id)
320  {
321  array_push($this->questions, $question_id);
322  }
323 
330  public function delete()
331  {
332  if ($this->countReferences() == 1) {
333  $this->deleteMetaData();
334 
335  // Delete all survey questions, constraints and materials
336  foreach ($this->questions as $question_id) {
337  $this->removeQuestion($question_id);
338  }
339  $this->deleteSurveyRecord();
340 
342  }
343 
344  $remove = parent::delete();
345 
346  // always call parent delete function first!!
347  if (!$remove) {
348  return false;
349  }
350  return true;
351  }
352 
358  public function deleteSurveyRecord()
359  {
360  $ilDB = $this->db;
361 
362  $affectedRows = $ilDB->manipulateF(
363  "DELETE FROM svy_svy WHERE survey_id = %s",
364  array('integer'),
365  array($this->getSurveyId())
366  );
367 
368  $result = $ilDB->queryF(
369  "SELECT questionblock_fi FROM svy_qblk_qst WHERE survey_fi = %s",
370  array('integer'),
371  array($this->getSurveyId())
372  );
373  $questionblocks = array();
374  while ($row = $ilDB->fetchAssoc($result)) {
375  array_push($questionblocks, $row["questionblock_fi"]);
376  }
377  if (count($questionblocks)) {
378  $affectedRows = $ilDB->manipulate("DELETE FROM svy_qblk WHERE " . $ilDB->in('questionblock_id', $questionblocks, false, 'integer'));
379  }
380  $affectedRows = $ilDB->manipulateF(
381  "DELETE FROM svy_qblk_qst WHERE survey_fi = %s",
382  array('integer'),
383  array($this->getSurveyId())
384  );
385  $this->deleteAllUserData(false);
386 
387  $affectedRows = $ilDB->manipulateF(
388  "DELETE FROM svy_anonymous WHERE survey_fi = %s",
389  array('integer'),
390  array($this->getSurveyId())
391  );
392 
393  // delete export files
394  $svy_data_dir = ilUtil::getDataDir() . "/svy_data";
395  $directory = $svy_data_dir . "/svy_" . $this->getId();
396  if (is_dir($directory)) {
397  ilUtil::delDir($directory);
398  }
399 
400  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
401  $mobs = ilObjMediaObject::_getMobsOfObject("svy:html", $this->getId());
402  // remaining usages are not in text anymore -> delete them
403  // and media objects (note: delete method of ilObjMediaObject
404  // checks whether object is used in another context; if yes,
405  // the object is not deleted!)
406  foreach ($mobs as $mob) {
407  ilObjMediaObject::_removeUsage($mob, "svy:html", $this->getId());
408  $mob_obj = new ilObjMediaObject($mob);
409  $mob_obj->delete();
410  }
411  }
412 
419  public function deleteAllUserData($reset_LP = true)
420  {
421  $ilDB = $this->db;
422 
423  $result = $ilDB->queryF(
424  "SELECT finished_id FROM svy_finished WHERE survey_fi = %s",
425  array('integer'),
426  array($this->getSurveyId())
427  );
428  $active_array = array();
429  while ($row = $ilDB->fetchAssoc($result)) {
430  array_push($active_array, $row["finished_id"]);
431  }
432 
433  $affectedRows = $ilDB->manipulateF(
434  "DELETE FROM svy_finished WHERE survey_fi = %s",
435  array('integer'),
436  array($this->getSurveyId())
437  );
438 
439  foreach ($active_array as $active_fi) {
440  $affectedRows = $ilDB->manipulateF(
441  "DELETE FROM svy_answer WHERE active_fi = %s",
442  array('integer'),
443  array($active_fi)
444  );
445  $affectedRows = $ilDB->manipulateF(
446  "DELETE FROM svy_times WHERE finished_fi = %s",
447  array('integer'),
448  array($active_fi)
449  );
450  }
451 
452  if ($reset_LP) {
453  include_once "Services/Object/classes/class.ilObjectLP.php";
454  $lp_obj = ilObjectLP::getInstance($this->getId());
455  $lp_obj->resetLPDataForCompleteObject();
456  }
457  }
458 
464  public function removeSelectedSurveyResults($finished_ids)
465  {
466  $ilDB = $this->db;
467 
468  $user_ids[] = array();
469 
470  foreach ($finished_ids as $finished_id) {
471  $result = $ilDB->queryF(
472  "SELECT finished_id FROM svy_finished WHERE finished_id = %s",
473  array('integer'),
474  array($finished_id)
475  );
476  $row = $ilDB->fetchAssoc($result);
477 
478  if ($row["user_fi"]) {
479  $user_ids[] = $row["user_fi"];
480  }
481 
482  $affectedRows = $ilDB->manipulateF(
483  "DELETE FROM svy_answer WHERE active_fi = %s",
484  array('integer'),
485  array($row["finished_id"])
486  );
487 
488  $affectedRows = $ilDB->manipulateF(
489  "DELETE FROM svy_finished WHERE finished_id = %s",
490  array('integer'),
491  array($finished_id)
492  );
493 
494  $affectedRows = $ilDB->manipulateF(
495  "DELETE FROM svy_times WHERE finished_fi = %s",
496  array('integer'),
497  array($row["finished_id"])
498  );
499  }
500 
501  if (sizeof($user_ids)) {
502  include_once "Services/Object/classes/class.ilObjectLP.php";
503  $lp_obj = ilObjectLP::getInstance($this->getId());
504  $lp_obj->resetLPDataForUserIds($user_ids);
505  }
506  }
507 
508  public function &getSurveyParticipants($finished_ids = null, $force_non_anonymous = false)
509  {
510  $ilDB = $this->db;
511 
512  $sql = "SELECT * FROM svy_finished" .
513  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer");
514  if ($finished_ids) {
515  $sql .= " AND " . $ilDB->in("finished_id", $finished_ids, "", "integer");
516  }
517 
518  $result = $ilDB->query($sql);
519  $participants = array();
520  if ($result->numRows() > 0) {
521  while ($row = $ilDB->fetchAssoc($result)) {
522  $userdata = $this->getUserDataFromActiveId($row["finished_id"], $force_non_anonymous);
523  $userdata["finished"] = (bool) $row["state"];
524  $userdata["finished_tstamp"] = $row["tstamp"];
525  $participants[$userdata["sortname"] . $userdata["active_id"]] = $userdata;
526  }
527  }
528  return $participants;
529  }
530 
537  public function isComplete()
538  {
539  if (($this->getTitle()) and (count($this->questions))) {
540  return 1;
541  } else {
542  return 0;
543  }
544  }
545 
551  public function saveCompletionStatus()
552  {
553  $ilDB = $this->db;
554 
555  $complete = 0;
556  if ($this->isComplete()) {
557  $complete = 1;
558  }
559  if ($this->getSurveyId() > 0) {
560  $affectedRows = $ilDB->manipulateF(
561  "UPDATE svy_svy SET complete = %s, tstamp = %s WHERE survey_id = %s",
562  array('text','integer','integer'),
563  array($this->isComplete(), time(), $this->getSurveyId())
564  );
565  }
566  }
567 
575  public function duplicateQuestionForSurvey($question_id, $a_force = false)
576  {
578 
579  $questiontype = $this->getQuestionType($question_id);
580  $question_gui = $this->getQuestionGUI($questiontype, $question_id);
581 
582  // check if question is a pool question at all, if not do nothing
583  if ($this->getId() == $question_gui->object->getObjId() && !$a_force) {
584  return $question_id;
585  }
586 
587  $duplicate_id = $question_gui->object->duplicate(true, "", "", "", $this->getId());
588  return $duplicate_id;
589  }
590 
596  public function insertQuestion($question_id)
597  {
598  $ilDB = $this->db;
599 
600  $this->log->debug("insert question, id:" . $question_id);
601 
602  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
603  if (!SurveyQuestion::_isComplete($question_id)) {
604  $this->log->debug("question is not complete");
605  return false;
606  } else {
607  // get maximum sequence index in test
608  // @todo: refactor this
609  $result = $ilDB->queryF(
610  "SELECT survey_question_id FROM svy_svy_qst WHERE survey_fi = %s",
611  array('integer'),
612  array($this->getSurveyId())
613  );
614  $sequence = $result->numRows();
615  $duplicate_id = $this->duplicateQuestionForSurvey($question_id);
616  $this->log->debug("duplicate, id: " . $question_id . ", duplicate id: " . $duplicate_id);
617 
618  // check if question is not already in the survey, see #22018
619  if ($this->isQuestionInSurvey($duplicate_id)) {
620  return false;
621  }
622 
623  $next_id = $ilDB->nextId('svy_svy_qst');
624  $affectedRows = $ilDB->manipulateF(
625  "INSERT INTO svy_svy_qst (survey_question_id, survey_fi, question_fi, sequence, tstamp) VALUES (%s, %s, %s, %s, %s)",
626  array('integer', 'integer', 'integer', 'integer', 'integer'),
627  array($next_id, $this->getSurveyId(), $duplicate_id, $sequence, time())
628  );
629 
630  $this->log->debug("added entry to svy_svy_qst, id: " . $next_id . ", question id: " . $duplicate_id . ", sequence: " . $sequence);
631 
632  $this->loadQuestionsFromDb();
633  return true;
634  }
635  }
636 
643  public function isQuestionInSurvey($a_question_fi)
644  {
645  global $DIC;
646  //return false;
647  $ilDB = $DIC->database();
648 
649  $set = $ilDB->query("SELECT * FROM svy_svy_qst " .
650  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
651  " AND question_fi = " . $ilDB->quote($a_question_fi, "integer"));
652  if ($rec = $ilDB->fetchAssoc($set)) {
653  return true;
654  }
655  return false;
656  }
657 
658 
659 
665  public function insertQuestionblock($questionblock_id)
666  {
667  $ilDB = $this->db;
668  $result = $ilDB->queryF(
669  "SELECT svy_qblk.title, svy_qblk.show_questiontext, svy_qblk.show_blocktitle," .
670  " svy_qblk_qst.question_fi FROM svy_qblk, svy_qblk_qst, svy_svy_qst" .
671  " WHERE svy_qblk.questionblock_id = svy_qblk_qst.questionblock_fi" .
672  " AND svy_svy_qst.question_fi = svy_qblk_qst.question_fi" .
673  " AND svy_qblk.questionblock_id = %s" .
674  " ORDER BY svy_svy_qst.sequence",
675  array('integer'),
676  array($questionblock_id)
677  );
678  $questions = array();
679  $show_questiontext = 0;
680  $show_blocktitle = 0;
681  while ($row = $ilDB->fetchAssoc($result)) {
682  $duplicate_id = $this->duplicateQuestionForSurvey($row["question_fi"]);
683  array_push($questions, $duplicate_id);
684  $title = $row["title"];
685  $show_questiontext = $row["show_questiontext"];
686  $show_blocktitle = $row["show_blocktitle"];
687  }
688  $this->createQuestionblock($title, $show_questiontext, $show_blocktitle, $questions);
689  }
690 
691  public function saveUserSettings($usr_id, $key, $title, $value)
692  {
693  $ilDB = $this->db;
694 
695  $next_id = $ilDB->nextId('svy_settings');
696  $affectedRows = $ilDB->insert("svy_settings", array(
697  "settings_id" => array("integer", $next_id),
698  "usr_id" => array("integer", $usr_id),
699  "keyword" => array("text", $key),
700  "title" => array("text", $title),
701  "value" => array("clob", $value)
702  ));
703  }
704 
705  public function deleteUserSettings($id)
706  {
707  $ilDB = $this->db;
708 
709  $affectedRows = $ilDB->manipulateF(
710  "DELETE FROM svy_settings WHERE settings_id = %s",
711  array('integer'),
712  array($id)
713  );
714  return $affectedRows;
715  }
716 
717  public function getUserSettings($usr_id, $key)
718  {
719  $ilDB = $this->db;
720 
721  $result = $ilDB->queryF(
722  "SELECT * FROM svy_settings WHERE usr_id = %s AND keyword = %s",
723  array('integer', 'text'),
724  array($usr_id, $key)
725  );
726  $found = array();
727  if ($result->numRows()) {
728  while ($row = $ilDB->fetchAssoc($result)) {
729  $found[$row['settings_id']] = $row;
730  }
731  }
732  return $found;
733  }
734 
740  public function saveToDb()
741  {
742  $ilDB = $this->db;
743 
744  // date handling
745  $rmd_start = $this->getReminderStart();
746  if (is_object($rmd_start)) {
747  $rmd_start = $rmd_start->get(IL_CAL_DATE);
748  }
749  $rmd_end = $this->getReminderEnd();
750  if (is_object($rmd_end)) {
751  $rmd_end = $rmd_end->get(IL_CAL_DATE);
752  }
753 
754  include_once("./Services/RTE/classes/class.ilRTE.php");
755  if ($this->getSurveyId() < 1) {
756  $next_id = $ilDB->nextId('svy_svy');
757  $affectedRows = $ilDB->insert("svy_svy", array(
758  "survey_id" => array("integer", $next_id),
759  "obj_fi" => array("integer", $this->getId()),
760  "author" => array("text", $this->getAuthor()),
761  "introduction" => array("clob", ilRTE::_replaceMediaObjectImageSrc($this->getIntroduction(), 0)),
762  "outro" => array("clob", ilRTE::_replaceMediaObjectImageSrc($this->getOutro(), 0)),
763  "startdate" => array("text", $this->getStartDate()),
764  "enddate" => array("text", $this->getEndDate()),
765  "evaluation_access" => array("text", $this->getEvaluationAccess()),
766  "invitation" => array("text", $this->getInvitation()),
767  "invitation_mode" => array("text", $this->getInvitationMode()),
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  "confirmation_mail" => array("integer", $this->hasMailConfirmation()),
803  "anon_user_list" => array("integer", $this->hasAnonymousUserList())
804  ));
805  $this->setSurveyId($next_id);
806  } else {
807  $affectedRows = $ilDB->update("svy_svy", array(
808  "author" => array("text", $this->getAuthor()),
809  "introduction" => array("clob", ilRTE::_replaceMediaObjectImageSrc($this->getIntroduction(), 0)),
810  "outro" => array("clob", ilRTE::_replaceMediaObjectImageSrc($this->getOutro(), 0)),
811  "startdate" => array("text", $this->getStartDate()),
812  "enddate" => array("text", $this->getEndDate()),
813  "evaluation_access" => array("text", $this->getEvaluationAccess()),
814  "invitation" => array("text", $this->getInvitation()),
815  "invitation_mode" => array("text", $this->getInvitationMode()),
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  "confirmation_mail" => array("integer", $this->hasMailConfirmation()),
850  "anon_user_list" => array("integer", $this->hasAnonymousUserList())
851  ), array(
852  "survey_id" => array("integer", $this->getSurveyId())
853  ));
854  }
855  if ($affectedRows) {
856  // save questions to db
857  $this->saveQuestionsToDb();
858  }
859 
860  // moved activation to ilObjectActivation
861  if ($this->ref_id) {
862  include_once "./Services/Object/classes/class.ilObjectActivation.php";
863  ilObjectActivation::getItem($this->ref_id);
864 
865  $item = new ilObjectActivation;
866  if (!$this->isActivationLimited()) {
868  } else {
869  $item->setTimingType(ilObjectActivation::TIMINGS_ACTIVATION);
870  $item->setTimingStart($this->getActivationStartDate());
871  $item->setTimingEnd($this->getActivationEndDate());
872  $item->toggleVisible($this->getActivationVisibility());
873  }
874 
875  $item->update($this->ref_id);
876  }
877  }
878 
885  public function saveQuestionsToDb()
886  {
887  $ilDB = $this->db;
888 
889  $this->log->debug("save questions");
890 
891  // gather old questions state
892  $old_questions = array();
893  $result = $ilDB->queryF(
894  "SELECT survey_question_id,question_fi,sequence" .
895  " FROM svy_svy_qst WHERE survey_fi = %s",
896  array('integer'),
897  array($this->getSurveyId())
898  );
899  while ($row = $ilDB->fetchAssoc($result)) {
900  $old_questions[$row["question_fi"]] = $row; // problem, as soon as duplicates exist, they will be hidden here
901  }
902 
903  // #15231 - diff with current questions state
904  $insert = $update = $delete = array();
905  foreach ($this->questions as $seq => $fi) {
906  if (!array_key_exists($fi, $old_questions)) { // really new fi IDs
907  $insert[] = $fi; // this should be ok, should not create duplicates here
908  } elseif ($old_questions[$fi]["sequence"] != $seq) { // we are updating one of the duplicates (if any)
909  $update[$fi] = $old_questions[$fi]["survey_question_id"];
910  }
911  // keep track of still relevant questions
912  unset($old_questions[$fi]); // deleting old question, if they are not in current array
913  }
914 
915  // delete obsolete question relations
916  if (sizeof($old_questions)) {
917  $del_ids = array();
918  foreach ($old_questions as $fi => $old) {
919  $del_ids[] = $old["survey_question_id"];
920  }
921  $ilDB->manipulate($q = "DELETE FROM svy_svy_qst" .
922  " WHERE " . $ilDB->in("survey_question_id", $del_ids, "", "integer"));
923  $this->log->debug("delete: " . $q);
924  }
925  unset($old_questions);
926 
927  // create/update question relations
928  foreach ($this->questions as $seq => $fi) {
929  if (in_array($fi, $insert)) {
930  // check if question is not already in the survey, see #22018
931  if (!$this->isQuestionInSurvey($fi)) {
932  $next_id = $ilDB->nextId('svy_svy_qst');
933  $ilDB->manipulateF(
934  "INSERT INTO svy_svy_qst" .
935  " (survey_question_id, survey_fi, question_fi, heading, sequence, tstamp)" .
936  " VALUES (%s, %s, %s, %s, %s, %s)",
937  array('integer', 'integer', 'integer', 'text', 'integer', 'integer'),
938  array($next_id, $this->getSurveyId(), $fi, null, $seq, time())
939  );
940  $this->log->debug("insert svy_svy_qst, id:" . $next_id . ", fi: " . $fi . ", seq:" . $seq);
941  }
942  } elseif (array_key_exists($fi, $update)) {
943  $ilDB->manipulate("UPDATE svy_svy_qst" .
944  " SET sequence = " . $ilDB->quote($seq, "integer") .
945  ", tstamp = " . $ilDB->quote(time(), "integer") .
946  " WHERE survey_question_id = " . $ilDB->quote($update[$fi], "integer"));
947  $this->log->debug("update svy_svy_qst, id:" . $update[$fi] . ", fi: " . $fi . ", seq:" . $seq);
948  }
949  }
950  }
951 
959  public function getAnonymousId($id)
960  {
961  $ilDB = $this->db;
962  $result = $ilDB->queryF(
963  "SELECT anonymous_id FROM svy_finished WHERE anonymous_id = %s",
964  array('text'),
965  array($id)
966  );
967  if ($result->numRows()) {
968  $row = $ilDB->fetchAssoc($result);
969  return $row["anonymous_id"];
970  } else {
971  return "";
972  }
973  }
974 
981  public function getQuestionGUI($questiontype, $question_id)
982  {
983  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestionGUI.php";
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  include_once("./Services/RTE/classes/class.ilRTE.php");
1093  $this->setIntroduction(ilRTE::_replaceMediaObjectImageSrc($data["introduction"], 1));
1094  if (strcmp($data["outro"], "survey_finished") == 0) {
1095  $this->setOutro($this->lng->txt("survey_finished"));
1096  } else {
1097  $this->setOutro(ilRTE::_replaceMediaObjectImageSrc($data["outro"], 1));
1098  }
1099  $this->setInvitation($data["invitation"]);
1100  $this->setInvitationMode($data["invitation_mode"]);
1101  $this->setShowQuestionTitles($data["show_question_titles"]);
1102  $this->setStartDate($data["startdate"]);
1103  $this->setEndDate($data["enddate"]);
1104  $this->setAnonymize($data["anonymize"]);
1105  $this->setEvaluationAccess($data["evaluation_access"]);
1106  $this->loadQuestionsFromDb();
1107  $this->setMailNotification($data['mailnotification']);
1108  $this->setMailAddresses($data['mailaddresses']);
1109  $this->setMailParticipantData($data['mailparticipantdata']);
1110  $this->setTemplate($data['template_id']);
1111  $this->setPoolUsage($data['pool_usage']);
1112  // Mode
1113  $this->setMode($data['mode']);
1114  // 360°
1115  $this->set360SelfEvaluation($data['mode_360_self_eval']);
1116  $this->set360SelfRaters($data['mode_360_self_rate']);
1117  $this->set360SelfAppraisee($data['mode_360_self_appr']);
1118  $this->set360Results($data['mode_360_results']);
1119  // Mode self evaluated
1120  $this->setSelfEvaluationResults($data['mode_self_eval_results']);
1121  // Competences
1122  $this->setSkillService($data['mode_skill_service']);
1123  // reminder/notification
1124  $this->setReminderStatus($data["reminder_status"]);
1125  $this->setReminderStart($data["reminder_start"] ? new ilDate($data["reminder_start"], IL_CAL_DATE) : null);
1126  $this->setReminderEnd($data["reminder_end"] ? new ilDate($data["reminder_end"], IL_CAL_DATE) : null);
1127  $this->setReminderFrequency($data["reminder_frequency"]);
1128  $this->setReminderTarget($data["reminder_target"]);
1129  $this->setReminderLastSent($data["reminder_last_sent"]);
1130  $this->setReminderTemplate($data["reminder_tmpl"]);
1131  $this->setTutorNotificationStatus($data["tutor_ntf_status"]);
1132  $this->setTutorNotificationRecipients(explode(";", $data["tutor_ntf_reci"]));
1133  $this->setTutorNotificationTarget($data["tutor_ntf_target"]);
1134 
1135  $this->setViewOwnResults($data["own_results_view"]);
1136  $this->setMailOwnResults($data["own_results_mail"]);
1137  $this->setMailConfirmation($data["confirmation_mail"]);
1138 
1139  $this->setAnonymousUserList($data["anon_user_list"]);
1140  }
1141 
1142  // moved activation to ilObjectActivation
1143  if ($this->ref_id) {
1144  include_once "./Services/Object/classes/class.ilObjectActivation.php";
1145  $activation = ilObjectActivation::getItem($this->ref_id);
1146  switch ($activation["timing_type"]) {
1148  $this->setActivationLimited(true);
1149  $this->setActivationStartDate($activation["timing_start"]);
1150  $this->setActivationEndDate($activation["timing_end"]);
1151  $this->setActivationVisibility($activation["visible"]);
1152  break;
1153 
1154  default:
1155  $this->setActivationLimited(false);
1156  break;
1157  }
1158  }
1159  }
1160 
1167  public function loadQuestionsFromDb()
1168  {
1169  $ilDB = $this->db;
1170  $this->questions = array();
1171  $result = $ilDB->queryF(
1172  "SELECT * FROM svy_svy_qst WHERE survey_fi = %s ORDER BY sequence",
1173  array('integer'),
1174  array($this->getSurveyId())
1175  );
1176  while ($data = $ilDB->fetchAssoc($result)) {
1177  $this->questions[$data["sequence"]] = $data["question_fi"];
1178  }
1179  }
1180 
1184  public function fixSequenceStructure()
1185  {
1186  global $DIC;
1187 
1188  $ilDB = $DIC->database();
1189  //return;
1190  // we keep all survey question ids with their lowest sequence
1191  $result = $ilDB->queryF(
1192  "SELECT * FROM svy_svy_qst WHERE survey_fi = %s ORDER BY sequence",
1193  array('integer'),
1194  array($this->getSurveyId())
1195  );
1196 
1197  // step 1: find duplicates -> $to_delete_ids
1198  $fis = array();
1199  $to_delete_ids = array();
1200  while ($data = $ilDB->fetchAssoc($result)) {
1201  if (in_array($data["question_fi"], $fis)) { // found a duplicate
1202  $to_delete_ids[] = $data["survey_question_id"];
1203  } else {
1204  $fis[] = $data["question_fi"];
1205  }
1206  }
1207 
1208  // step 2: we delete the duplicates
1209  if (count($to_delete_ids) > 0) {
1210  $ilDB->manipulate($q = "DELETE FROM svy_svy_qst" .
1211  " WHERE " . $ilDB->in("survey_question_id", $to_delete_ids, false, "integer") .
1212  " AND survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer"));
1213  $this->log->debug("delete: " . $q);
1214 
1215  $ilDB->manipulate($q = "DELETE FROM svy_qblk_qst " .
1216  " WHERE " . $ilDB->in("question_fi", $fis, true, "integer") .
1217  " AND survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer"));
1218  $this->log->debug("delete: " . $q);
1219  }
1220 
1221  // step 3: we fix the sequence
1222  $set = $ilDB->query("SELECT * FROM svy_svy_qst " .
1223  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") . " ORDER BY sequence");
1224  $seq = 0;
1225  while ($rec = $ilDB->fetchAssoc($set)) {
1226  $ilDB->manipulate(
1227  $q = "UPDATE svy_svy_qst SET " .
1228  " sequence = " . $ilDB->quote($seq++, "integer") .
1229  " WHERE survey_question_id = " . $ilDB->quote($rec["survey_question_id"], "integer")
1230  );
1231  $this->log->debug("update: " . $q);
1232  }
1233  }
1234 
1235 
1243  public function setAuthor($author = "")
1244  {
1245  $this->author = $author;
1246  }
1247 
1257  public function saveAuthorToMetadata($a_author = "")
1258  {
1259  $md = new ilMD($this->getId(), 0, $this->getType());
1260  $md_life = &$md->getLifecycle();
1261  if (!$md_life) {
1262  if (strlen($a_author) == 0) {
1263  $ilUser = $this->user;
1264  $a_author = $ilUser->getFullname();
1265  }
1266 
1267  $md_life = &$md->addLifecycle();
1268  $md_life->save();
1269  $con = &$md_life->addContribute();
1270  $con->setRole("Author");
1271  $con->save();
1272  $ent = &$con->addEntity();
1273  $ent->setEntity($a_author);
1274  $ent->save();
1275  }
1276  }
1277 
1285  public function getAuthor()
1286  {
1287  $author = array();
1288  include_once "./Services/MetaData/classes/class.ilMD.php";
1289  $md = new ilMD($this->getId(), 0, $this->getType());
1290  $md_life = &$md->getLifecycle();
1291  if ($md_life) {
1292  $ids = &$md_life->getContributeIds();
1293  foreach ($ids as $id) {
1294  $md_cont = &$md_life->getContribute($id);
1295  if (strcmp($md_cont->getRole(), "Author") == 0) {
1296  $entids = &$md_cont->getEntityIds();
1297  foreach ($entids as $entid) {
1298  $md_ent = &$md_cont->getEntity($entid);
1299  array_push($author, $md_ent->getEntity());
1300  }
1301  }
1302  }
1303  }
1304  return join(",", $author);
1305  }
1306 
1313  public function getShowQuestionTitles()
1314  {
1315  return ($this->display_question_titles) ? 1 : 0;
1316  }
1317 
1324  public function setShowQuestionTitles($a_show)
1325  {
1326  $this->display_question_titles = ($a_show) ? 1 : 0;
1327  }
1328 
1335  public function showQuestionTitles()
1336  {
1337  $this->display_question_titles = 1;
1338  }
1339 
1346  public function hideQuestionTitles()
1347  {
1348  $this->display_question_titles = 0;
1349  }
1350 
1358  public function setInvitation($invitation = 0)
1359  {
1360  $ilDB = $this->db;
1361  $ilAccess = $this->access;
1362 
1363  $this->invitation = $invitation;
1365  $this->disinviteAllUsers();
1366  } elseif ($invitation == self::INVITATION_ON) {
1367  if ($this->getInvitationMode() == self::MODE_UNLIMITED) {
1368  $result = $ilDB->query("SELECT usr_id FROM usr_data");
1369  while ($row = $ilDB->fetchAssoc($result)) {
1370  if ($ilAccess->checkAccessOfUser($row["usr_id"], "read", "", $this->getRefId(), "svy", $this->getId())) {
1371  $this->inviteUser($row['usr_id']);
1372  }
1373  }
1374  }
1375  }
1376  }
1377 
1386  {
1387  $this->invitation_mode = $invitation_mode;
1388  }
1389 
1399  {
1400  $this->invitation_mode = $invitation_mode;
1401  $this->setInvitation($invitation);
1402  }
1403 
1410  public function setIntroduction($introduction = "")
1411  {
1412  $this->introduction = $introduction;
1413  }
1414 
1421  public function setOutro($outro = "")
1422  {
1423  $this->outro = $outro;
1424  }
1425 
1433  public function getInvitation()
1434  {
1435  return ($this->invitation) ? $this->invitation : self::INVITATION_OFF;
1436  }
1437 
1445  public function getInvitationMode()
1446  {
1447  include_once "./Services/Administration/classes/class.ilSetting.php";
1448  $surveySetting = new ilSetting("survey");
1449  $unlimited_invitation = $surveySetting->get("unlimited_invitation");
1450  if (!$unlimited_invitation && $this->invitation_mode == self::MODE_UNLIMITED) {
1451  return self::MODE_PREDEFINED_USERS;
1452  } else {
1453  return ($this->invitation_mode) ? $this->invitation_mode : self::MODE_UNLIMITED;
1454  }
1455  }
1456 
1464  public function getStartDate()
1465  {
1466  return (strlen($this->start_date)) ? $this->start_date : null;
1467  }
1468 
1475  public function canStartSurvey($anonymous_id = null, $a_no_rbac = false)
1476  {
1477  $ilAccess = $this->access;
1478 
1479  $result = true;
1480  $messages = array();
1481  $edit_settings = false;
1482  // check start date
1483  if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getStartDate(), $matches)) {
1484  $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
1485  $now = time();
1486  if ($now < $epoch_time) {
1487  array_push($messages, $this->lng->txt('start_date_not_reached') . ' (' .
1489  $result = false;
1490  $edit_settings = true;
1491  }
1492  }
1493  // check end date
1494  if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndDate(), $matches)) {
1495  $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
1496  $now = time();
1497  if ($now > $epoch_time) {
1498  array_push($messages, $this->lng->txt('end_date_reached') . ' (' .
1500  $result = false;
1501  $edit_settings = true;
1502  }
1503  }
1504 
1505  // check online status
1506  if ($this->getOfflineStatus()) {
1507  array_push($messages, $this->lng->txt("survey_is_offline"));
1508  $result = false;
1509  $edit_settings = true;
1510  }
1511  // check rbac permissions
1512  if (!$a_no_rbac && !$ilAccess->checkAccess("read", "", $this->ref_id)) {
1513  array_push($messages, $this->lng->txt("cannot_participate_survey"));
1514  $result = false;
1515  }
1516  /*
1517  // 2. check previous access
1518  if (!$result["error"])
1519  {
1520  $ilUser = $this->user;
1521  $survey_started = $this->isSurveyStarted($ilUser->getId(), $anonymous_id);
1522  if ($survey_started === 1)
1523  {
1524  array_push($messages, $this->lng->txt("already_completed_survey"));
1525  $result = FALSE;
1526  }
1527  }
1528  */
1529  return array(
1530  "result" => $result,
1531  "messages" => $messages,
1532  "edit_settings" => $edit_settings
1533  );
1534  }
1535 
1543  public function setStartDate($start_date = "")
1544  {
1545  $this->start_date = $start_date;
1546  }
1547 
1556  public function setStartDateAndTime($start_date = "", $start_time)
1557  {
1558  $y = '';
1559  $m = '';
1560  $d = '';
1561  $h = '';
1562  $i = '';
1563  $s = '';
1564  if (preg_match("/(\d{4})-(\d{2})-(\d{2})/", $start_date, $matches)) {
1565  $y = $matches[1];
1566  $m = $matches[2];
1567  $d = $matches[3];
1568  }
1569  if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $start_time, $matches)) {
1570  $h = $matches[1];
1571  $i = $matches[2];
1572  $s = $matches[3];
1573  }
1574  $this->start_date = sprintf('%04d%02d%02d%02d%02d%02d', $y, $m, $d, $h, $i, $s);
1575  }
1576 
1584  public function getEndDate()
1585  {
1586  return (strlen($this->end_date)) ? $this->end_date : null;
1587  }
1588 
1596  public function setEndDate($end_date = "")
1597  {
1598  $this->end_date = $end_date;
1599  }
1600 
1609  public function setEndDateAndTime($end_date = "", $end_time)
1610  {
1611  $y = '';
1612  $m = '';
1613  $d = '';
1614  $h = '';
1615  $i = '';
1616  $s = '';
1617  if (preg_match("/(\d{4})-(\d{2})-(\d{2})/", $end_date, $matches)) {
1618  $y = $matches[1];
1619  $m = $matches[2];
1620  $d = $matches[3];
1621  }
1622  if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $end_time, $matches)) {
1623  $h = $matches[1];
1624  $i = $matches[2];
1625  $s = $matches[3];
1626  }
1627  $this->end_date = sprintf('%04d%02d%02d%02d%02d%02d', $y, $m, $d, $h, $i, $s);
1628  }
1629 
1637  public function getEvaluationAccess()
1638  {
1639  return ($this->evaluation_access) ? $this->evaluation_access : self::EVALUATION_ACCESS_OFF;
1640  }
1641 
1649  public function setEvaluationAccess($evaluation_access = self::EVALUATION_ACCESS_OFF)
1650  {
1651  $this->evaluation_access = ($evaluation_access) ? $evaluation_access : self::EVALUATION_ACCESS_OFF;
1652  }
1653 
1654  public function setActivationVisibility($a_value)
1655  {
1656  $this->activation_visibility = (bool) $a_value;
1657  }
1658 
1659  public function getActivationVisibility()
1660  {
1662  }
1663 
1664  public function isActivationLimited()
1665  {
1666  return (bool) $this->activation_limited;
1667  }
1668 
1669  public function setActivationLimited($a_value)
1670  {
1671  $this->activation_limited = (bool) $a_value;
1672  }
1673 
1681  public function getIntroduction()
1682  {
1683  return (strlen($this->introduction)) ? $this->introduction : null;
1684  }
1685 
1693  public function getOutro()
1694  {
1695  return (strlen($this->outro)) ? $this->outro : null;
1696  }
1697 
1704  public function &getExistingQuestions()
1705  {
1706  $ilDB = $this->db;
1707  $existing_questions = array();
1708  $result = $ilDB->queryF(
1709  "SELECT svy_question.original_id FROM svy_question, svy_svy_qst WHERE " .
1710  "svy_svy_qst.survey_fi = %s AND svy_svy_qst.question_fi = svy_question.question_id",
1711  array('integer'),
1712  array($this->getSurveyId())
1713  );
1714  while ($data = $ilDB->fetchAssoc($result)) {
1715  if ($data["original_id"]) {
1716  array_push($existing_questions, $data["original_id"]);
1717  }
1718  }
1719  return $existing_questions;
1720  }
1721 
1728  public function &getQuestionpoolTitles($could_be_offline = false, $showPath = false)
1729  {
1730  include_once "./Modules/SurveyQuestionPool/classes/class.ilObjSurveyQuestionPool.php";
1731  return ilObjSurveyQuestionPool::_getAvailableQuestionpools($use_object_id = true, $could_be_offline, $showPath);
1732  }
1733 
1742  public function moveQuestions($move_questions, $target_index, $insert_mode)
1743  {
1744  $array_pos = array_search($target_index, $this->questions);
1745  if ($insert_mode == 0) {
1746  $part1 = array_slice($this->questions, 0, $array_pos);
1747  $part2 = array_slice($this->questions, $array_pos);
1748  } elseif ($insert_mode == 1) {
1749  $part1 = array_slice($this->questions, 0, $array_pos + 1);
1750  $part2 = array_slice($this->questions, $array_pos + 1);
1751  }
1752  $found = 0;
1753  foreach ($move_questions as $question_id) {
1754  if (!(array_search($question_id, $part1) === false)) {
1755  unset($part1[array_search($question_id, $part1)]);
1756  $found++;
1757  }
1758  if (!(array_search($question_id, $part2) === false)) {
1759  unset($part2[array_search($question_id, $part2)]);
1760  $found++;
1761  }
1762  }
1763  // sanity check: do not move questions if they have not be found in the array
1764  if ($found != count($move_questions)) {
1765  return;
1766  }
1767  $part1 = array_values($part1);
1768  $part2 = array_values($part2);
1769  $this->questions = array_values(array_merge($part1, $move_questions, $part2));
1770  foreach ($move_questions as $question_id) {
1771  $constraints = $this->getConstraints($question_id);
1772  foreach ($constraints as $idx => $constraint) {
1773  foreach ($part2 as $next_question_id) {
1774  if ($constraint["question"] == $next_question_id) {
1775  // constraint concerning a question that follows -> delete constraint
1776  $this->deleteConstraint($constraint["id"]);
1777  }
1778  }
1779  }
1780  }
1781  $this->saveQuestionsToDb();
1782  }
1783 
1790  public function removeQuestion($question_id)
1791  {
1792  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
1793  $question = self::_instanciateQuestion($question_id);
1794  #20610 if no question found, do nothing.
1795  if ($question) {
1796  $question->delete($question_id);
1797  $this->removeConstraintsConcerningQuestion($question_id);
1798  }
1799  }
1800 
1807  public function removeConstraintsConcerningQuestion($question_id)
1808  {
1809  $ilDB = $this->db;
1810  $result = $ilDB->queryF(
1811  "SELECT constraint_fi FROM svy_qst_constraint WHERE question_fi = %s AND survey_fi = %s",
1812  array('integer','integer'),
1813  array($question_id, $this->getSurveyId())
1814  );
1815  if ($result->numRows() > 0) {
1816  $remove_constraints = array();
1817  while ($row = $ilDB->fetchAssoc($result)) {
1818  array_push($remove_constraints, $row["constraint_fi"]);
1819  }
1820  $affectedRows = $ilDB->manipulateF(
1821  "DELETE FROM svy_qst_constraint WHERE question_fi = %s AND survey_fi = %s",
1822  array('integer','integer'),
1823  array($question_id, $this->getSurveyId())
1824  );
1825  foreach ($remove_constraints as $key => $constraint_id) {
1826  $affectedRows = $ilDB->manipulateF(
1827  "DELETE FROM svy_constraint WHERE constraint_id = %s",
1828  array('integer'),
1829  array($constraint_id)
1830  );
1831  }
1832  }
1833  }
1834 
1842  public function removeQuestions($remove_questions, $remove_questionblocks)
1843  {
1844  $ilDB = $this->db;
1845 
1846  $block_sizes = array();
1847  foreach ($this->getSurveyQuestions() as $question_id => $data) {
1848  if (in_array($question_id, $remove_questions) or in_array($data["questionblock_id"], $remove_questionblocks)) {
1849  unset($this->questions[array_search($question_id, $this->questions)]);
1850  $this->removeQuestion($question_id);
1851  } elseif ($data["questionblock_id"]) {
1852  $block_sizes[$data["questionblock_id"]]++;
1853  }
1854  }
1855 
1856  // blocks with just 1 question need to be deleted
1857  foreach ($block_sizes as $block_id => $size) {
1858  if ($size < 2) {
1859  $remove_questionblocks[] = $block_id;
1860  }
1861  }
1862 
1863  foreach (array_unique($remove_questionblocks) as $questionblock_id) {
1864  $affectedRows = $ilDB->manipulateF(
1865  "DELETE FROM svy_qblk WHERE questionblock_id = %s",
1866  array('integer'),
1867  array($questionblock_id)
1868  );
1869  $affectedRows = $ilDB->manipulateF(
1870  "DELETE FROM svy_qblk_qst WHERE questionblock_fi = %s AND survey_fi = %s",
1871  array('integer','integer'),
1872  array($questionblock_id, $this->getSurveyId())
1873  );
1874  }
1875 
1876  $this->questions = array_values($this->questions);
1877  $this->saveQuestionsToDb();
1878  }
1879 
1886  public function unfoldQuestionblocks($questionblocks)
1887  {
1888  $ilDB = $this->db;
1889  foreach ($questionblocks as $index) {
1890  $affectedRows = $ilDB->manipulateF(
1891  "DELETE FROM svy_qblk WHERE questionblock_id = %s",
1892  array('integer'),
1893  array($index)
1894  );
1895  $affectedRows = $ilDB->manipulateF(
1896  "DELETE FROM svy_qblk_qst WHERE questionblock_fi = %s AND survey_fi = %s",
1897  array('integer','integer'),
1898  array($index, $this->getSurveyId())
1899  );
1900  }
1901  }
1902 
1903  public function removeQuestionFromBlock($question_id, $questionblock_id)
1904  {
1905  $ilDB = $this->db;
1906 
1907  $affectedRows = $ilDB->manipulateF(
1908  "DELETE FROM svy_qblk_qst WHERE questionblock_fi = %s AND survey_fi = %s AND question_fi = %s",
1909  array('integer','integer','integer'),
1910  array($questionblock_id, $this->getSurveyId(), $question_id)
1911  );
1912  }
1913 
1914  public function addQuestionToBlock($question_id, $questionblock_id)
1915  {
1916  $ilDB = $this->db;
1917 
1918  // see #22018
1919  if (!$this->isQuestionInAnyBlock($question_id)) {
1920  $next_id = $ilDB->nextId('svy_qblk_qst');
1921  $affectedRows = $ilDB->manipulateF(
1922  "INSERT INTO svy_qblk_qst (qblk_qst_id, survey_fi, questionblock_fi, " .
1923  "question_fi) VALUES (%s, %s, %s, %s)",
1924  array('integer', 'integer', 'integer', 'integer'),
1925  array($next_id, $this->getSurveyId(), $questionblock_id, $question_id)
1926  );
1927 
1928  $this->deleteConstraints($question_id); // #13713
1929  }
1930  }
1931 
1938  public function isQuestionInAnyBlock($a_question_fi)
1939  {
1940  global $DIC;
1941 
1942  $ilDB = $DIC->database();
1943 
1944  $set = $ilDB->query("SELECT * FROM svy_qblk_qst " .
1945  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
1946  " AND question_fi = " . $ilDB->quote($a_question_fi, "integer"));
1947  if ($rec = $ilDB->fetchAssoc($set)) {
1948  return true;
1949  }
1950  return false;
1951  }
1952 
1953 
1960  public function &getQuestionblockQuestions($questionblock_id)
1961  {
1962  $ilDB = $this->db;
1963  $titles = array();
1964  $result = $ilDB->queryF(
1965  "SELECT svy_question.title, svy_qblk_qst.question_fi, svy_qblk_qst.survey_fi FROM " .
1966  "svy_qblk, svy_qblk_qst, svy_question WHERE svy_qblk.questionblock_id = svy_qblk_qst.questionblock_fi AND " .
1967  "svy_question.question_id = svy_qblk_qst.question_fi AND svy_qblk.questionblock_id = %s",
1968  array('integer'),
1969  array($questionblock_id)
1970  );
1971  $survey_id = "";
1972  while ($row = $ilDB->fetchAssoc($result)) {
1973  $titles[$row["question_fi"]] = $row["title"];
1974  $survey_id = $row["survey_fi"];
1975  }
1976  $result = $ilDB->queryF(
1977  "SELECT question_fi, sequence FROM svy_svy_qst WHERE survey_fi = %s ORDER BY sequence",
1978  array('integer'),
1979  array($survey_id)
1980  );
1981  $resultarray = array();
1982  $counter = 1;
1983  while ($row = $ilDB->fetchAssoc($result)) {
1984  if (array_key_exists($row["question_fi"], $titles)) {
1985  $resultarray[$counter++] = $titles[$row["question_fi"]];
1986  }
1987  }
1988  return $resultarray;
1989  }
1990 
1997  public function &getQuestionblockQuestionIds($questionblock_id)
1998  {
1999  $ilDB = $this->db;
2000 
2001  // we need a correct order here, see #22011
2002  $result = $ilDB->queryF(
2003  "SELECT a.question_fi FROM svy_qblk_qst a JOIN svy_svy_qst b ON (a.question_fi = b.question_fi) " .
2004  " WHERE a.questionblock_fi = %s ORDER BY b.sequence",
2005  array("integer"),
2006  array($questionblock_id)
2007  );
2008  $ids = array();
2009  if ($result->numRows()) {
2010  while ($data = $ilDB->fetchAssoc($result)) {
2011  if (!in_array($data['question_fi'], $ids)) { // no duplicates, see #22018
2012  array_push($ids, $data['question_fi']);
2013  }
2014  }
2015  }
2016 
2017  return $ids;
2018  }
2019 
2027  public static function _getQuestionblock($questionblock_id)
2028  {
2029  global $DIC;
2030 
2031  $ilDB = $DIC->database();
2032  $result = $ilDB->queryF(
2033  "SELECT * FROM svy_qblk WHERE questionblock_id = %s",
2034  array('integer'),
2035  array($questionblock_id)
2036  );
2037  $row = $ilDB->fetchAssoc($result);
2038  return $row;
2039  }
2040 
2049  public static function _addQuestionblock($title = "", $owner = 0, $show_questiontext = true, $show_blocktitle = false)
2050  {
2051  global $DIC;
2052 
2053  $ilDB = $DIC->database();
2054  $next_id = $ilDB->nextId('svy_qblk');
2055  $ilDB->manipulateF(
2056  "INSERT INTO svy_qblk (questionblock_id, title, show_questiontext," .
2057  " show_blocktitle, owner_fi, tstamp) " .
2058  "VALUES (%s, %s, %s, %s, %s, %s)",
2059  array('integer','text','integer','integer','integer','integer'),
2060  array($next_id, $title, $show_questiontext, $show_blocktitle, $owner, time())
2061  );
2062  return $next_id;
2063  }
2064 
2072  public function createQuestionblock($title, $show_questiontext, $show_blocktitle, $questions)
2073  {
2074  $ilDB = $this->db;
2075 
2076  // if the selected questions are not in a continous selection, move all questions of the
2077  // questionblock at the position of the first selected question
2078  $this->moveQuestions($questions, $questions[0], 0);
2079 
2080  // now save the question block
2081  $ilUser = $this->user;
2082  $next_id = $ilDB->nextId('svy_qblk');
2083  $affectedRows = $ilDB->manipulateF(
2084  "INSERT INTO svy_qblk (questionblock_id, title, show_questiontext," .
2085  " show_blocktitle, owner_fi, tstamp) VALUES (%s, %s, %s, %s, %s, %s)",
2086  array('integer','text','text','text','integer','integer'),
2087  array($next_id, $title, $show_questiontext, $show_blocktitle, $ilUser->getId(), time())
2088  );
2089  if ($affectedRows) {
2090  $questionblock_id = $next_id;
2091  foreach ($questions as $index) {
2092  if (!$this->isQuestionInAnyBlock($index)) {
2093  $next_id = $ilDB->nextId('svy_qblk_qst'); // #22018
2094  $affectedRows = $ilDB->manipulateF(
2095  "INSERT INTO svy_qblk_qst (qblk_qst_id, survey_fi, questionblock_fi, " .
2096  "question_fi) VALUES (%s, %s, %s, %s)",
2097  array('integer', 'integer', 'integer', 'integer'),
2098  array($next_id, $this->getSurveyId(), $questionblock_id, $index)
2099  );
2100  $this->deleteConstraints($index);
2101  }
2102  }
2103  }
2104  }
2105 
2113  public function modifyQuestionblock($questionblock_id, $title, $show_questiontext, $show_blocktitle)
2114  {
2115  $ilDB = $this->db;
2116  $affectedRows = $ilDB->manipulateF(
2117  "UPDATE svy_qblk SET title = %s, show_questiontext = %s," .
2118  " show_blocktitle = %s WHERE questionblock_id = %s",
2119  array('text','text','text','integer'),
2120  array($title, $show_questiontext, $show_blocktitle, $questionblock_id)
2121  );
2122  }
2123 
2130  public function deleteConstraints($question_id)
2131  {
2132  $ilDB = $this->db;
2133  $result = $ilDB->queryF(
2134  "SELECT constraint_fi FROM svy_qst_constraint WHERE question_fi = %s AND survey_fi = %s",
2135  array('integer','integer'),
2136  array($question_id, $this->getSurveyId())
2137  );
2138  $constraints = array();
2139  while ($row = $ilDB->fetchAssoc($result)) {
2140  array_push($constraints, $row["constraint_fi"]);
2141  }
2142  foreach ($constraints as $constraint_id) {
2143  $this->deleteConstraint($constraint_id);
2144  }
2145  }
2146 
2154  public function deleteConstraint($constraint_id)
2155  {
2156  $ilDB = $this->db;
2157  $affectedRows = $ilDB->manipulateF(
2158  "DELETE FROM svy_constraint WHERE constraint_id = %s",
2159  array('integer'),
2160  array($constraint_id)
2161  );
2162  $affectedRows = $ilDB->manipulateF(
2163  "DELETE FROM svy_qst_constraint WHERE constraint_fi = %s",
2164  array('integer'),
2165  array($constraint_id)
2166  );
2167  }
2168 
2174  public function &getSurveyQuestions($with_answers = false)
2175  {
2176  $ilDB = $this->db;
2177  // get questionblocks
2178  $all_questions = array();
2179  $result = $ilDB->queryF(
2180  "SELECT svy_qtype.type_tag, svy_qtype.plugin, svy_question.question_id, " .
2181  "svy_svy_qst.heading FROM svy_qtype, svy_question, svy_svy_qst WHERE svy_svy_qst.survey_fi = %s AND " .
2182  "svy_svy_qst.question_fi = svy_question.question_id AND svy_question.questiontype_fi = svy_qtype.questiontype_id " .
2183  "ORDER BY svy_svy_qst.sequence",
2184  array('integer'),
2185  array($this->getSurveyId())
2186  );
2187  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
2188  while ($row = $ilDB->fetchAssoc($result)) {
2189  $add = true;
2190  if ($row["plugin"]) {
2191  if (!$this->isPluginActive($row["type_tag"])) {
2192  $add = false;
2193  }
2194  }
2195  if ($add) {
2196  $question = self::_instanciateQuestion($row["question_id"]);
2197  $questionrow = $question->getQuestionDataArray($row["question_id"]);
2198  foreach ($row as $key => $value) {
2199  $questionrow[$key] = $value;
2200  }
2201  $all_questions[$row["question_id"]] = $questionrow;
2202  $all_questions[$row["question_id"]]["usableForPrecondition"] = $question->usableForPrecondition();
2203  $all_questions[$row["question_id"]]["availableRelations"] = $question->getAvailableRelations();
2204  }
2205  }
2206  // get all questionblocks
2207  $questionblocks = array();
2208  if (count($all_questions)) {
2209  $result = $ilDB->queryF(
2210  "SELECT svy_qblk.*, svy_qblk_qst.question_fi FROM svy_qblk, svy_qblk_qst WHERE " .
2211  "svy_qblk.questionblock_id = svy_qblk_qst.questionblock_fi AND svy_qblk_qst.survey_fi = %s " .
2212  "AND " . $ilDB->in('svy_qblk_qst.question_fi', array_keys($all_questions), false, 'integer'),
2213  array('integer'),
2214  array($this->getSurveyId())
2215  );
2216  while ($row = $ilDB->fetchAssoc($result)) {
2217  $questionblocks[$row['question_fi']] = $row;
2218  }
2219  }
2220 
2221  foreach ($all_questions as $question_id => $row) {
2222  $constraints = $this->getConstraints($question_id);
2223  if (isset($questionblocks[$question_id])) {
2224  $all_questions[$question_id]["questionblock_title"] = $questionblocks[$question_id]['title'];
2225  $all_questions[$question_id]["questionblock_id"] = $questionblocks[$question_id]['questionblock_id'];
2226  $all_questions[$question_id]["constraints"] = $constraints;
2227  } else {
2228  $all_questions[$question_id]["questionblock_title"] = "";
2229  $all_questions[$question_id]["questionblock_id"] = "";
2230  $all_questions[$question_id]["constraints"] = $constraints;
2231  }
2232  if ($with_answers) {
2233  $answers = array();
2234  $result = $ilDB->queryF(
2235  "SELECT svy_variable.*, svy_category.title FROM svy_variable, svy_category " .
2236  "WHERE svy_variable.question_fi = %s AND svy_variable.category_fi = svy_category.category_id " .
2237  "ORDER BY sequence ASC",
2238  array('integer'),
2239  array($question_id)
2240  );
2241  if ($result->numRows() > 0) {
2242  while ($data = $ilDB->fetchAssoc($result)) {
2243  array_push($answers, $data["title"]);
2244  }
2245  }
2246  $all_questions[$question_id]["answers"] = $answers;
2247  }
2248  }
2249  return $all_questions;
2250  }
2251 
2258  public function setObligatoryStates($obligatory_questions)
2259  {
2260  $ilDB = $this->db;
2261  $result = $ilDB->queryF(
2262  "SELECT * FROM svy_svy_qst WHERE survey_fi = %s",
2263  array('integer'),
2264  array($this->getSurveyId())
2265  );
2266  if ($result->numRows()) {
2267  while ($row = $ilDB->fetchAssoc($result)) {
2268  if (!array_key_exists($row["question_fi"], $obligatory_questions)) {
2269  $obligatory_questions[$row["question_fi"]] = 0;
2270  }
2271  }
2272  }
2273 
2274  // set the obligatory states in the database
2275  foreach ($obligatory_questions as $question_fi => $obligatory) {
2276  // #12420
2277  $ilDB->manipulate("UPDATE svy_question" .
2278  " SET obligatory = " . $ilDB->quote($obligatory, "integer") .
2279  " WHERE question_id = " . $ilDB->quote($question_fi, "integer"));
2280  }
2281  }
2282 
2288  public function &getSurveyPages()
2289  {
2290  $ilDB = $this->db;
2291  // get questionblocks
2292  $all_questions = array();
2293  $result = $ilDB->queryF(
2294  "SELECT svy_question.*, svy_qtype.type_tag, svy_svy_qst.heading FROM " .
2295  "svy_question, svy_qtype, svy_svy_qst WHERE svy_svy_qst.survey_fi = %s AND " .
2296  "svy_svy_qst.question_fi = svy_question.question_id AND svy_question.questiontype_fi = svy_qtype.questiontype_id " .
2297  "ORDER BY svy_svy_qst.sequence",
2298  array('integer'),
2299  array($this->getSurveyId())
2300  );
2301  while ($row = $ilDB->fetchAssoc($result)) {
2302  $all_questions[$row["question_id"]] = $row;
2303  }
2304  // get all questionblocks
2305  $questionblocks = array();
2306  if (count($all_questions)) {
2307  $result = $ilDB->queryF(
2308  "SELECT svy_qblk.*, svy_qblk_qst.question_fi FROM svy_qblk, svy_qblk_qst " .
2309  "WHERE svy_qblk.questionblock_id = svy_qblk_qst.questionblock_fi AND svy_qblk_qst.survey_fi = %s " .
2310  "AND " . $ilDB->in('svy_qblk_qst.question_fi', array_keys($all_questions), false, 'integer'),
2311  array('integer'),
2312  array($this->getSurveyId())
2313  );
2314  while ($row = $ilDB->fetchAssoc($result)) {
2315  $questionblocks[$row['question_fi']] = $row;
2316  }
2317  }
2318 
2319  $all_pages = array();
2320  $pageindex = -1;
2321  $currentblock = "";
2322  foreach ($all_questions as $question_id => $row) {
2323  $constraints = array();
2324  if (isset($questionblocks[$question_id])) {
2325  if (!$currentblock or ($currentblock != $questionblocks[$question_id]['questionblock_id'])) {
2326  $pageindex++;
2327  }
2328  $all_questions[$question_id]['page'] = $pageindex;
2329  $all_questions[$question_id]["questionblock_title"] = $questionblocks[$question_id]['title'];
2330  $all_questions[$question_id]["questionblock_id"] = $questionblocks[$question_id]['questionblock_id'];
2331  $all_questions[$question_id]["questionblock_show_questiontext"] = $questionblocks[$question_id]['show_questiontext'];
2332  $all_questions[$question_id]["questionblock_show_blocktitle"] = $questionblocks[$question_id]['show_blocktitle'];
2333  $currentblock = $questionblocks[$question_id]['questionblock_id'];
2334  $constraints = $this->getConstraints($question_id);
2335  $all_questions[$question_id]["constraints"] = $constraints;
2336  } else {
2337  $pageindex++;
2338  $all_questions[$question_id]['page'] = $pageindex;
2339  $all_questions[$question_id]["questionblock_title"] = "";
2340  $all_questions[$question_id]["questionblock_id"] = "";
2341  $all_questions[$question_id]["questionblock_show_questiontext"] = 1;
2342  $all_questions[$question_id]["questionblock_show_blocktitle"] = 1;
2343  $currentblock = "";
2344  $constraints = $this->getConstraints($question_id);
2345  $all_questions[$question_id]["constraints"] = $constraints;
2346  }
2347  if (!isset($all_pages[$pageindex])) {
2348  $all_pages[$pageindex] = array();
2349  }
2350  array_push($all_pages[$pageindex], $all_questions[$question_id]);
2351  }
2352  // calculate position percentage for every page
2353  $max = count($all_pages);
2354  $counter = 1;
2355  foreach ($all_pages as $index => $block) {
2356  foreach ($block as $blockindex => $question) {
2357  $all_pages[$index][$blockindex]["position"] = $counter / $max;
2358  }
2359  $counter++;
2360  }
2361 
2362  return $all_pages;
2363  }
2364 
2373  public function getNextPage($active_page_question_id, $direction)
2374  {
2375  $foundpage = -1;
2376  $pages = &$this->getSurveyPages();
2377  if (strcmp($active_page_question_id, "") == 0) {
2378  return $pages[0];
2379  }
2380  foreach ($pages as $key => $question_array) {
2381  foreach ($question_array as $question) {
2382  if ($active_page_question_id == $question["question_id"]) {
2383  $foundpage = $key;
2384  }
2385  }
2386  }
2387  if ($foundpage == -1) {
2388  // error: page not found
2389  } else {
2390  $foundpage += $direction;
2391  if ($foundpage < 0) {
2392  return 0;
2393  }
2394  if ($foundpage >= count($pages)) {
2395  return 1;
2396  }
2397  return $pages[$foundpage];
2398  }
2399  }
2400 
2407  public function &getAvailableQuestionpools($use_obj_id = false, $could_be_offline = false, $showPath = false, $permission = "read")
2408  {
2409  include_once "./Modules/SurveyQuestionPool/classes/class.ilObjSurveyQuestionPool.php";
2410  return ilObjSurveyQuestionPool::_getAvailableQuestionpools($use_obj_id, $could_be_offline, $showPath, $permission);
2411  }
2412 
2418  public function getPrecondition($id)
2419  {
2420  $ilDB = $this->db;
2421 
2422  $result_array = array();
2423  $result = $ilDB->queryF(
2424  "SELECT svy_constraint.*, svy_relation.*, svy_qst_constraint.question_fi ref_question_fi FROM svy_qst_constraint, svy_constraint, " .
2425  "svy_relation WHERE svy_constraint.relation_fi = svy_relation.relation_id AND " .
2426  "svy_qst_constraint.constraint_fi = svy_constraint.constraint_id AND svy_constraint.constraint_id = %s",
2427  array('integer'),
2428  array($id)
2429  );
2430  $pc = array();
2431  if ($result->numRows()) {
2432  $pc = $ilDB->fetchAssoc($result);
2433  }
2434  return $pc;
2435  }
2436 
2442  public function getConstraints($question_id)
2443  {
2444  $ilDB = $this->db;
2445 
2446  $result_array = array();
2447  $result = $ilDB->queryF(
2448  "SELECT svy_constraint.*, svy_relation.* FROM svy_qst_constraint, svy_constraint, svy_relation " .
2449  "WHERE svy_constraint.relation_fi = svy_relation.relation_id AND " .
2450  "svy_qst_constraint.constraint_fi = svy_constraint.constraint_id AND svy_qst_constraint.question_fi = %s " .
2451  "AND svy_qst_constraint.survey_fi = %s",
2452  array('integer','integer'),
2453  array($question_id, $this->getSurveyId())
2454  );
2455  while ($row = $ilDB->fetchAssoc($result)) {
2456  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
2457  $question_type = SurveyQuestion::_getQuestionType($row["question_fi"]);
2458  SurveyQuestion::_includeClass($question_type);
2459  $question = new $question_type();
2460  $question->loadFromDb($row["question_fi"]);
2461  $valueoutput = $question->getPreconditionValueOutput($row["value"]);
2462  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));
2463  }
2464  return $result_array;
2465  }
2466 
2472  public static function _getConstraints($survey_id)
2473  {
2474  global $DIC;
2475 
2476  $ilDB = $DIC->database();
2477  $result_array = array();
2478  $result = $ilDB->queryF(
2479  "SELECT svy_qst_constraint.question_fi as for_question, svy_constraint.*, svy_relation.* " .
2480  "FROM svy_qst_constraint, svy_constraint, svy_relation WHERE svy_constraint.relation_fi = svy_relation.relation_id " .
2481  "AND svy_qst_constraint.constraint_fi = svy_constraint.constraint_id AND svy_qst_constraint.survey_fi = %s",
2482  array('integer'),
2483  array($survey_id)
2484  );
2485  while ($row = $ilDB->fetchAssoc($result)) {
2486  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']));
2487  }
2488  return $result_array;
2489  }
2490 
2491 
2497  public function &getVariables($question_id)
2498  {
2499  $ilDB = $this->db;
2500 
2501  $result_array = array();
2502  $result = $ilDB->queryF(
2503  "SELECT svy_variable.*, svy_category.title FROM svy_variable LEFT JOIN " .
2504  "svy_category ON svy_variable.category_fi = svy_category.category_id WHERE svy_variable.question_fi = %s " .
2505  "ORDER BY svy_variable.sequence",
2506  array('integer'),
2507  array($question_id)
2508  );
2509  while ($row = $ilDB->fetchObject($result)) {
2510  $result_array[$row->sequence] = $row;
2511  }
2512  return $result_array;
2513  }
2514 
2523  public function addConstraint($if_question_id, $relation, $value, $conjunction)
2524  {
2525  $ilDB = $this->db;
2526 
2527  $next_id = $ilDB->nextId('svy_constraint');
2528  $affectedRows = $ilDB->manipulateF(
2529  "INSERT INTO svy_constraint (constraint_id, question_fi, relation_fi, value, conjunction) VALUES " .
2530  "(%s, %s, %s, %s, %s)",
2531  array('integer','integer','integer','float', 'integer'),
2532  array($next_id, $if_question_id, $relation, $value, $conjunction)
2533  );
2534  if ($affectedRows) {
2535  return $next_id;
2536  } else {
2537  return null;
2538  }
2539  }
2540 
2541 
2548  public function addConstraintToQuestion($to_question_id, $constraint_id)
2549  {
2550  $ilDB = $this->db;
2551 
2552  $next_id = $ilDB->nextId('svy_qst_constraint');
2553  $affectedRows = $ilDB->manipulateF(
2554  "INSERT INTO svy_qst_constraint (question_constraint_id, survey_fi, question_fi, " .
2555  "constraint_fi) VALUES (%s, %s, %s, %s)",
2556  array('integer','integer','integer','integer'),
2557  array($next_id, $this->getSurveyId(), $to_question_id, $constraint_id)
2558  );
2559  }
2560 
2571  public function updateConstraint($precondition_id, $if_question_id, $relation, $value, $conjunction)
2572  {
2573  $ilDB = $this->db;
2574  $affectedRows = $ilDB->manipulateF(
2575  "UPDATE svy_constraint SET question_fi = %s, relation_fi = %s, value = %s, conjunction = %s " .
2576  "WHERE constraint_id = %s",
2577  array('integer','integer','float','integer','integer'),
2578  array($if_question_id, $relation, $value, $conjunction, $precondition_id)
2579  );
2580  }
2581 
2582  public function updateConjunctionForQuestions($questions, $conjunction)
2583  {
2584  $ilDB = $this->db;
2585  foreach ($questions as $question_id) {
2586  $affectedRows = $ilDB->manipulateF(
2587  "UPDATE svy_constraint SET conjunction = %s " .
2588  "WHERE constraint_id IN (SELECT constraint_fi FROM svy_qst_constraint WHERE svy_qst_constraint.question_fi = %s)",
2589  array('integer','integer'),
2590  array($conjunction, $question_id)
2591  );
2592  }
2593  }
2594 
2600  public function getAllRelations($short_as_key = false)
2601  {
2602  $ilDB = $this->db;
2603 
2604  // #7987
2605  $custom_order = array("equal", "not_equal", "less", "less_or_equal", "more", "more_or_equal");
2606  $custom_order = array_flip($custom_order);
2607 
2608  $result_array = array();
2609  $result = $ilDB->query("SELECT * FROM svy_relation");
2610  while ($row = $ilDB->fetchAssoc($result)) {
2611  if ($short_as_key) {
2612  $result_array[$row["shortname"]] = array("short" => $row["shortname"], "long" => $row["longname"], "id" => $row["relation_id"], "order" => $custom_order[$row["longname"]]);
2613  } else {
2614  $result_array[$row["relation_id"]] = array("short" => $row["shortname"], "long" => $row["longname"], "order" => $custom_order[$row["longname"]]);
2615  }
2616  }
2617 
2618  $result_array = ilUtil::sortArray($result_array, "order", "ASC", true, true);
2619  foreach ($result_array as $idx => $item) {
2620  unset($result_array[$idx]["order"]);
2621  }
2622 
2623  return $result_array;
2624  }
2625 
2629  public function disinviteAllUsers()
2630  {
2631  $ilDB = $this->db;
2632  $result = $ilDB->queryF(
2633  "SELECT user_fi FROM svy_inv_usr WHERE survey_fi = %s",
2634  array('integer'),
2635  array($this->getSurveyId())
2636  );
2637  while ($row = $ilDB->fetchAssoc($result)) {
2638  $this->disinviteUser($row['user_fi']);
2639  }
2640  }
2641 
2647  public function disinviteUser($user_id)
2648  {
2649  $ilDB = $this->db;
2650 
2651  $affectedRows = $ilDB->manipulateF(
2652  "DELETE FROM svy_inv_usr WHERE survey_fi = %s AND user_fi = %s",
2653  array('integer','integer'),
2654  array($this->getSurveyId(), $user_id)
2655  );
2656  include_once './Services/User/classes/class.ilObjUser.php';
2657  ilObjUser::_dropDesktopItem($user_id, $this->getRefId(), "svy");
2658  }
2659 
2666  public function inviteUser($user_id)
2667  {
2668  $ilDB = $this->db;
2669 
2670  $result = $ilDB->queryF(
2671  "SELECT user_fi FROM svy_inv_usr WHERE user_fi = %s AND survey_fi = %s",
2672  array('integer','integer'),
2673  array($user_id, $this->getSurveyId())
2674  );
2675  if ($result->numRows() < 1) {
2676  $next_id = $ilDB->nextId('svy_inv_usr');
2677  $affectedRows = $ilDB->manipulateF(
2678  "INSERT INTO svy_inv_usr (invited_user_id, survey_fi, user_fi, tstamp) " .
2679  "VALUES (%s, %s, %s, %s)",
2680  array('integer','integer','integer','integer'),
2681  array($next_id, $this->getSurveyId(), $user_id, time())
2682  );
2683  }
2684  if ($this->getInvitation() == self::INVITATION_ON) {
2685  include_once './Services/User/classes/class.ilObjUser.php';
2686  ilObjUser::_addDesktopItem($user_id, $this->getRefId(), "svy");
2687  }
2688  }
2689 
2696  public function &getInvitedUsers()
2697  {
2698  $ilDB = $this->db;
2699 
2700  $result_array = array();
2701  $result = $ilDB->queryF(
2702  "SELECT user_fi FROM svy_inv_usr WHERE survey_fi = %s",
2703  array('integer'),
2704  array($this->getSurveyId())
2705  );
2706  while ($row = $ilDB->fetchAssoc($result)) {
2707  array_push($result_array, $row["user_fi"]);
2708  }
2709  return $result_array;
2710  }
2711 
2719  public function deleteWorkingData($question_id, $active_id)
2720  {
2721  $ilDB = $this->db;
2722 
2723  $affectedRows = $ilDB->manipulateF(
2724  "DELETE FROM svy_answer WHERE question_fi = %s AND active_fi = %s",
2725  array('integer','integer'),
2726  array($question_id, $active_id)
2727  );
2728  }
2729 
2738  public function loadWorkingData($question_id, $active_id)
2739  {
2740  $ilDB = $this->db;
2741  $result_array = array();
2742  $result = $ilDB->queryF(
2743  "SELECT * FROM svy_answer WHERE question_fi = %s AND active_fi = %s",
2744  array('integer','integer'),
2745  array($question_id, $active_id)
2746  );
2747  if ($result->numRows() >= 1) {
2748  while ($row = $ilDB->fetchAssoc($result)) {
2749  array_push($result_array, $row);
2750  }
2751  return $result_array;
2752  } else {
2753  return $result_array;
2754  }
2755  }
2756 
2763  public function startSurvey($user_id, $anonymous_id, $appraisee_id)
2764  {
2765  $ilDB = $this->db;
2766 
2767  if ($this->getAnonymize() && (strlen($anonymous_id) == 0)) {
2768  return;
2769  }
2770 
2771  if (strcmp($user_id, "") == 0) {
2772  if ($user_id == ANONYMOUS_USER_ID) {
2773  $user_id = 0;
2774  }
2775  }
2776  $next_id = $ilDB->nextId('svy_finished');
2777  $affectedRows = $ilDB->manipulateF(
2778  "INSERT INTO svy_finished (finished_id, survey_fi, user_fi, anonymous_id, state, tstamp, appr_id) " .
2779  "VALUES (%s, %s, %s, %s, %s, %s, %s)",
2780  array('integer','integer','integer','text','text','integer','integer'),
2781  array($next_id, $this->getSurveyId(), $user_id, $anonymous_id, 0, time(), $appraisee_id)
2782  );
2783  return $next_id;
2784  }
2785 
2792  public function finishSurvey($finished_id)
2793  {
2794  $ilDB = $this->db;
2795 
2796  $ilDB->manipulateF(
2797  "UPDATE svy_finished SET state = %s, tstamp = %s" .
2798  " WHERE survey_fi = %s AND finished_id = %s",
2799  array('text','integer','integer','integer'),
2800  array(1, time(), $this->getSurveyId(), $finished_id)
2801  );
2802 
2803  // self eval writes skills on finishing
2804  if ($this->getMode() == ilObjSurvey::MODE_SELF_EVAL) {
2805  $user = $this->getUserDataFromActiveId($finished_id);
2806  $sskill = new ilSurveySkill($this);
2807  $sskill->writeSelfEvalSkills($user['usr_id']);
2808  }
2809 
2810  $this->checkTutorNotification();
2811  }
2812 
2820  public function setPage($finished_id, $page_id)
2821  {
2822  $ilDB = $this->db;
2823 
2824  $affectedRows = $ilDB->manipulateF(
2825  "UPDATE svy_finished SET lastpage = %s WHERE finished_id = %s",
2826  array('integer','integer'),
2827  array(($page_id) ? $page_id : 0, $finished_id)
2828  );
2829  }
2830 
2836  public function sendNotificationMail($a_user_id, $a_anonymize_id, $a_appr_id)
2837  {
2838  // #12755
2839  $placeholders = array(
2840  "FIRST_NAME" => "firstname",
2841  "LAST_NAME" => "lastname",
2842  "LOGIN" => "login",
2843  // old style
2844  "firstname" => "firstname"
2845  );
2846 
2847  //mailaddresses is just text split by commas.
2848  //sendMail can send emails if it gets an user id or an email as first parameter.
2849  $recipients = preg_split('/,/', $this->mailaddresses);
2850  foreach ($recipients as $recipient) {
2851  // #11298
2852  $ntf = new ilSystemNotification();
2853  $ntf->setLangModules(array("survey"));
2854  $ntf->setRefId($this->getRefId());
2855  $ntf->setSubjectLangId('finished_mail_subject');
2856 
2857  $messagetext = $this->mailparticipantdata;
2858  if (trim($messagetext)) {
2859  if (!$this->hasAnonymizedResults()) {
2860  $data = ilObjUser::_getUserData(array($a_user_id));
2861  $data = $data[0];
2862  }
2863  foreach ($placeholders as $key => $mapping) {
2864  if ($this->hasAnonymizedResults()) { // #16480
2865  $messagetext = str_replace('[' . $key . ']', '', $messagetext);
2866  } else {
2867  $messagetext = str_replace('[' . $key . ']', trim($data[$mapping]), $messagetext);
2868  }
2869  }
2870  $ntf->setIntroductionDirect($messagetext);
2871  } else {
2872  $ntf->setIntroductionLangId('survey_notification_finished_introduction');
2873  }
2874 
2875  // 360°? add appraisee data
2876  if ($a_appr_id) {
2877  $ntf->addAdditionalInfo(
2878  'survey_360_appraisee',
2880  );
2881  }
2882 
2883  $active_id = $this->getActiveID($a_user_id, $a_anonymize_id, $a_appr_id);
2884  $ntf->addAdditionalInfo(
2885  'results',
2886  $this->getParticipantTextResults($active_id),
2887  true
2888  );
2889 
2890  $ntf->setGotoLangId('survey_notification_tutor_link');
2891  $ntf->setReasonLangId('survey_notification_finished_reason');
2892 
2893  if (is_numeric($recipient)) {
2894  $lng = $ntf->getUserLanguage($recipient);
2895  $ntf->sendMail(array($recipient), null, null);
2896  } else {
2897  $recipient = trim($recipient);
2898  $user_ids = ilObjUser::getUserIdsByEmail($recipient);
2899  if (empty($user_ids)) {
2900  $ntf->sendMail(array($recipient), null, null);
2901  } else {
2902  foreach ($user_ids as $user_id) {
2903  $lng = $ntf->getUserLanguage($user_id);
2904  $ntf->sendMail(array($user_id), null, null);
2905  }
2906  }
2907  }
2908  }
2909  }
2910 
2911  protected function getParticipantTextResults($active_id)
2912  {
2913  $textresult = "";
2914  $userResults = &$this->getUserSpecificResults(array($active_id));
2915  $questions = &$this->getSurveyQuestions(true);
2916  $questioncounter = 1;
2917  foreach ($questions as $question_id => $question_data) {
2918  $textresult .= $questioncounter++ . ". " . $question_data["title"] . "\n";
2919  $found = $userResults[$question_id][$active_id];
2920  $text = "";
2921  if (is_array($found)) {
2922  $text = implode("\n", $found);
2923  } else {
2924  $text = $found;
2925  }
2926  if (strlen($text) == 0) {
2927  $text = self::getSurveySkippedValue();
2928  }
2929  $text = str_replace("<br />", "\n", $text);
2930  $textresult .= $text . "\n\n";
2931  }
2932  return $textresult;
2933  }
2934 
2942  public function isSurveyStarted($user_id, $anonymize_id, $appr_id = 0)
2943  {
2944  $ilDB = $this->db;
2945 
2946  // #15031 - should not matter if code was used by registered or anonymous (each code must be unique)
2947  if ($anonymize_id) {
2948  $result = $ilDB->queryF(
2949  "SELECT * FROM svy_finished" .
2950  " WHERE survey_fi = %s AND anonymous_id = %s AND appr_id = %s",
2951  array('integer','text','integer'),
2952  array($this->getSurveyId(), $anonymize_id, $appr_id)
2953  );
2954  } else {
2955  $result = $ilDB->queryF(
2956  "SELECT * FROM svy_finished" .
2957  " WHERE survey_fi = %s AND user_fi = %s AND appr_id = %s",
2958  array('integer','integer','integer'),
2959  array($this->getSurveyId(), $user_id, $appr_id)
2960  );
2961  }
2962  if ($result->numRows() == 0) {
2963  return false;
2964  } else {
2965  $row = $ilDB->fetchAssoc($result);
2966  // yes, we are doing it this way
2967  $_SESSION["finished_id"][$this->getId()] = $row["finished_id"];
2968 
2969  return (int) $row["state"];
2970  }
2971  }
2972 
2980  public function getActiveID($user_id, $anonymize_id, $appr_id)
2981  {
2982  $ilDB = $this->db;
2983 
2984  // see self::isSurveyStarted()
2985 
2986  // #15031 - should not matter if code was used by registered or anonymous (each code must be unique)
2987  if ($anonymize_id) {
2988  $result = $ilDB->queryF(
2989  "SELECT finished_id FROM svy_finished" .
2990  " WHERE survey_fi = %s AND anonymous_id = %s AND appr_id = %s",
2991  array('integer','text','integer'),
2992  array($this->getSurveyId(), $anonymize_id, $appr_id)
2993  );
2994  } else {
2995  $result = $ilDB->queryF(
2996  "SELECT finished_id FROM svy_finished" .
2997  " WHERE survey_fi = %s AND user_fi = %s AND appr_id = %s",
2998  array('integer','integer','integer'),
2999  array($this->getSurveyId(), $user_id, $appr_id)
3000  );
3001  }
3002  if ($result->numRows() == 0) {
3003  return false;
3004  } else {
3005  $row = $ilDB->fetchAssoc($result);
3006  return $row["finished_id"];
3007  }
3008  }
3009 
3017  public function getLastActivePage($active_id)
3018  {
3019  $ilDB = $this->db;
3020  $result = $ilDB->queryF(
3021  "SELECT lastpage FROM svy_finished WHERE finished_id = %s",
3022  array('integer'),
3023  array($active_id)
3024  );
3025  if ($result->numRows() == 0) {
3026  return "";
3027  } else {
3028  $row = $ilDB->fetchAssoc($result);
3029  return ($row["lastpage"]) ? $row["lastpage"] : '';
3030  }
3031  }
3032 
3041  public function checkConstraint($constraint_data, $working_data)
3042  {
3043  if (!is_array($working_data) || count($working_data) == 0) {
3044  return 0;
3045  }
3046 
3047  if ((count($working_data) == 1) and (strcmp($working_data[0]["value"], "") == 0)) {
3048  return 0;
3049  }
3050 
3051  $found = false;
3052  foreach ($working_data as $data) {
3053  switch ($constraint_data["short"]) {
3054  case "<":
3055  if ($data["value"] < $constraint_data["value"]) {
3056  $found = true;
3057  }
3058  break;
3059 
3060  case "<=":
3061  if ($data["value"] <= $constraint_data["value"]) {
3062  $found = true;
3063  }
3064  break;
3065 
3066  case "=":
3067  if ($data["value"] == $constraint_data["value"]) {
3068  $found = true;
3069  }
3070  break;
3071 
3072  case "<>":
3073  if ($data["value"] <> $constraint_data["value"]) {
3074  $found = true;
3075  }
3076  break;
3077 
3078  case ">=":
3079  if ($data["value"] >= $constraint_data["value"]) {
3080  $found = true;
3081  }
3082  break;
3083 
3084  case ">":
3085  if ($data["value"] > $constraint_data["value"]) {
3086  $found = true;
3087  }
3088  break;
3089  }
3090  if ($found) {
3091  break;
3092  }
3093  }
3094 
3095  return (int) $found;
3096  }
3097 
3098  public static function _hasDatasets($survey_id)
3099  {
3100  global $DIC;
3101 
3102  $ilDB = $DIC->database();
3103 
3104  $result = $ilDB->queryF(
3105  "SELECT finished_id FROM svy_finished WHERE survey_fi = %s",
3106  array('integer'),
3107  array($survey_id)
3108  );
3109  return ($result->numRows()) ? true : false;
3110  }
3111 
3118  public function &getSurveyFinishedIds()
3119  {
3120  $ilDB = $this->db;
3121  $ilLog = $this->log;
3122 
3123  $users = array();
3124  $result = $ilDB->queryF(
3125  "SELECT * FROM svy_finished WHERE survey_fi = %s",
3126  array('integer'),
3127  array($this->getSurveyId())
3128  );
3129  if ($result->numRows()) {
3130  while ($row = $ilDB->fetchAssoc($result)) {
3131  array_push($users, $row["finished_id"]);
3132  }
3133  }
3134  return $users;
3135  }
3136 
3143  public function getUserSpecificResults($finished_ids)
3144  {
3145  $evaluation = array();
3146 
3147  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
3148  foreach (array_keys($this->getSurveyQuestions()) as $question_id) {
3149  // get question instance
3150  $question_type = SurveyQuestion::_getQuestionType($question_id);
3151  SurveyQuestion::_includeClass($question_type);
3152  $question = new $question_type();
3153  $question->loadFromDb($question_id);
3154 
3155  $q_eval = SurveyQuestion::_instanciateQuestionEvaluation($question_id, $finished_ids);
3156  $q_res = $q_eval->getResults();
3157 
3158  $data = array();
3159  foreach ($finished_ids as $user_id) {
3160  $data[$user_id] = $q_eval->parseUserSpecificResults($q_res, $user_id);
3161  }
3162 
3163  $evaluation[$question_id] = $data;
3164  }
3165 
3166  return $evaluation;
3167  }
3168 
3176  public function getUserDataFromActiveId($active_id, $force_non_anonymous = false)
3177  {
3178  $ilDB = $this->db;
3179 
3180  $surveySetting = new ilSetting("survey");
3181  $use_anonymous_id = array_key_exists("use_anonymous_id", $_GET) ? $_GET["use_anonymous_id"] : $surveySetting->get("use_anonymous_id");
3182  $result = $ilDB->queryF(
3183  "SELECT * FROM svy_finished WHERE finished_id = %s",
3184  array('integer'),
3185  array($active_id)
3186  );
3187  $row = array();
3188  $foundrows = $result->numRows();
3189  if ($foundrows) {
3190  $row = $ilDB->fetchAssoc($result);
3191  }
3192  $name = ($use_anonymous_id) ? $row["anonymous_id"] : $this->lng->txt("anonymous");
3193  $userdata = array(
3194  "fullname" => $name,
3195  "sortname" => $name,
3196  "firstname" => "",
3197  "lastname" => "",
3198  "login" => "",
3199  "gender" => "",
3200  "active_id" => "$active_id"
3201  );
3202  if ($foundrows) {
3203  if (($row["user_fi"] > 0) &&
3204  (($row["user_fi"] != ANONYMOUS_USER_ID &&
3205  !$this->hasAnonymizedResults() &&
3206  !$this->get360Mode()) || // 360° uses ANONYMIZE_CODE_ALL which is wrong - see ilObjSurveyGUI::afterSave()
3207  (bool) $force_non_anonymous)) {
3208  include_once './Services/User/classes/class.ilObjUser.php';
3209  if (strlen(ilObjUser::_lookupLogin($row["user_fi"])) == 0) {
3210  $userdata["fullname"] = $userdata["sortname"] = $this->lng->txt("deleted_user");
3211  } else {
3212  $user = new ilObjUser($row["user_fi"]);
3213  $userdata['usr_id'] = $row['user_fi'];
3214  $userdata["fullname"] = $user->getFullname();
3215  $gender = $user->getGender();
3216  if (strlen($gender) == 1) {
3217  $gender = $this->lng->txt("gender_$gender");
3218  }
3219  $userdata["gender"] = $gender;
3220  $userdata["firstname"] = $user->getFirstname();
3221  $userdata["lastname"] = $user->getLastname();
3222  $userdata["sortname"] = $user->getLastname() . ", " . $user->getFirstname();
3223  $userdata["login"] = $user->getLogin();
3224  }
3225  }
3226  }
3227  return $userdata;
3228  }
3229 
3239  public function &getEvaluationByUser($questions, $active_id)
3240  {
3241  $ilDB = $this->db;
3242 
3243  // collect all answers
3244  $answers = array();
3245  $result = $ilDB->queryF(
3246  "SELECT * FROM svy_answer WHERE active_fi = %s",
3247  array('integer'),
3248  array($active_id)
3249  );
3250  while ($row = $ilDB->fetchAssoc($result)) {
3251  if (!is_array($answers[$row["question_fi"]])) {
3252  $answers[$row["question_fi"]] = array();
3253  }
3254  array_push($answers[$row["question_fi"]], $row);
3255  }
3256  $userdata = $this->getUserDataFromActiveId($active_id);
3257  $resultset = array(
3258  "name" => $userdata["fullname"],
3259  "firstname" => $userdata["firstname"],
3260  "lastname" => $userdata["lastname"],
3261  "login" => $userdata["login"],
3262  "gender" => $userdata["gender"],
3263  "answers" => array()
3264  );
3265  foreach ($questions as $key => $question) {
3266  if (array_key_exists($key, $answers)) {
3267  $resultset["answers"][$key] = $answers[$key];
3268  } else {
3269  $resultset["answers"][$key] = array();
3270  }
3271  sort($resultset["answers"][$key]);
3272  }
3273  return $resultset;
3274  }
3275 
3281  public function getQuestionsTable($arrFilter)
3282  {
3283  $ilUser = $this->user;
3284  $ilDB = $this->db;
3285  $where = "";
3286  if (is_array($arrFilter)) {
3287  if (array_key_exists('title', $arrFilter) && strlen($arrFilter['title'])) {
3288  $where .= " AND " . $ilDB->like('svy_question.title', 'text', "%%" . $arrFilter['title'] . "%%");
3289  }
3290  if (array_key_exists('description', $arrFilter) && strlen($arrFilter['description'])) {
3291  $where .= " AND " . $ilDB->like('svy_question.description', 'text', "%%" . $arrFilter['description'] . "%%");
3292  }
3293  if (array_key_exists('author', $arrFilter) && strlen($arrFilter['author'])) {
3294  $where .= " AND " . $ilDB->like('svy_question.author', 'text', "%%" . $arrFilter['author'] . "%%");
3295  }
3296  if (array_key_exists('type', $arrFilter) && strlen($arrFilter['type'])) {
3297  $where .= " AND svy_qtype.type_tag = " . $ilDB->quote($arrFilter['type'], 'text');
3298  }
3299  if (array_key_exists('spl', $arrFilter) && strlen($arrFilter['spl'])) {
3300  $where .= " AND svy_question.obj_fi = " . $ilDB->quote($arrFilter['spl'], 'integer');
3301  }
3302  }
3303 
3304  $spls = &$this->getAvailableQuestionpools($use_obj_id = true, $could_be_offline = false, $showPath = false);
3305  $forbidden = "";
3306  $forbidden = " AND " . $ilDB->in('svy_question.obj_fi', array_keys($spls), false, 'integer');
3307  $forbidden .= " AND svy_question.complete = " . $ilDB->quote("1", 'text');
3308  $existing = "";
3309  $existing_questions = &$this->getExistingQuestions();
3310  if (count($existing_questions)) {
3311  $existing = " AND " . $ilDB->in('svy_question.question_id', $existing_questions, true, 'integer');
3312  }
3313 
3314  include_once "./Modules/SurveyQuestionPool/classes/class.ilObjSurveyQuestionPool.php";
3316 
3317  $query_result = $ilDB->query("SELECT svy_question.*, svy_qtype.type_tag, svy_qtype.plugin, object_reference.ref_id" .
3318  " FROM svy_question, svy_qtype, object_reference" .
3319  " WHERE svy_question.original_id IS NULL" . $forbidden . $existing .
3320  " AND svy_question.obj_fi = object_reference.obj_id AND svy_question.tstamp > 0" .
3321  " AND svy_question.questiontype_fi = svy_qtype.questiontype_id " . $where);
3322 
3323  $rows = array();
3324  if ($query_result->numRows()) {
3325  while ($row = $ilDB->fetchAssoc($query_result)) {
3326  if (array_key_exists('spl_txt', $arrFilter) && strlen($arrFilter['spl_txt'])) {
3327  if (!stristr($spls[$row["obj_fi"]], $arrFilter['spl_txt'])) {
3328  continue;
3329  }
3330  }
3331 
3332  $row['ttype'] = $trans[$row['type_tag']];
3333  if ($row["plugin"]) {
3334  if ($this->isPluginActive($row["type_tag"])) {
3335  array_push($rows, $row);
3336  }
3337  } else {
3338  array_push($rows, $row);
3339  }
3340  }
3341  }
3342  return $rows;
3343  }
3344 
3350  public function getQuestionblocksTable($arrFilter)
3351  {
3352  $ilUser = $this->user;
3353  $ilDB = $this->db;
3354 
3355  $where = "";
3356  if (is_array($arrFilter)) {
3357  if (array_key_exists('title', $arrFilter) && strlen($arrFilter['title'])) {
3358  $where .= " AND " . $ilDB->like('svy_qblk.title', 'text', "%%" . $arrFilter['title'] . "%%");
3359  }
3360  }
3361 
3362  $query_result = $ilDB->query("SELECT svy_qblk.*, svy_svy.obj_fi FROM svy_qblk , svy_qblk_qst, svy_svy WHERE " .
3363  "svy_qblk.questionblock_id = svy_qblk_qst.questionblock_fi AND svy_svy.survey_id = svy_qblk_qst.survey_fi " .
3364  "$where GROUP BY svy_qblk.questionblock_id, svy_qblk.title, svy_qblk.show_questiontext, svy_qblk.show_blocktitle, " .
3365  "svy_qblk.owner_fi, svy_qblk.tstamp, svy_svy.obj_fi");
3366  $rows = array();
3367  if ($query_result->numRows()) {
3368  $survey_ref_ids = ilUtil::_getObjectsByOperations("svy", "write");
3369  $surveytitles = array();
3370  foreach ($survey_ref_ids as $survey_ref_id) {
3371  $survey_id = ilObject::_lookupObjId($survey_ref_id);
3372  $surveytitles[$survey_id] = ilObject::_lookupTitle($survey_id);
3373  }
3374  while ($row = $ilDB->fetchAssoc($query_result)) {
3375  $questions_array = &$this->getQuestionblockQuestions($row["questionblock_id"]);
3376  $counter = 1;
3377  foreach ($questions_array as $key => $value) {
3378  $questions_array[$key] = "$counter. $value";
3379  $counter++;
3380  }
3381  if (strlen($surveytitles[$row["obj_fi"]])) { // only questionpools which are not in trash
3382  $rows[$row["questionblock_id"]] = array(
3383  "questionblock_id" => $row["questionblock_id"],
3384  "title" => $row["title"],
3385  "svy" => $surveytitles[$row["obj_fi"]],
3386  "contains" => join(", ", $questions_array),
3387  "owner" => $row["owner_fi"]
3388  );
3389  }
3390  }
3391  }
3392  return $rows;
3393  }
3394 
3401  public function toXML()
3402  {
3403  include_once("./Services/Xml/classes/class.ilXmlWriter.php");
3404  $a_xml_writer = new ilXmlWriter;
3405  // set xml header
3406  $a_xml_writer->xmlHeader();
3407  $attrs = array(
3408  "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
3409  "xsi:noNamespaceSchemaLocation" => "http://www.ilias.de/download/xsd/ilias_survey_4_2.xsd"
3410  );
3411  $a_xml_writer->xmlStartTag("surveyobject", $attrs);
3412  $attrs = array(
3413  "id" => $this->getSurveyId(),
3414  "title" => $this->getTitle()
3415  );
3416  $a_xml_writer->xmlStartTag("survey", $attrs);
3417 
3418  $a_xml_writer->xmlElement("description", null, $this->getDescription());
3419  $a_xml_writer->xmlElement("author", null, $this->getAuthor());
3420  $a_xml_writer->xmlStartTag("objectives");
3421  $attrs = array(
3422  "label" => "introduction"
3423  );
3424  $this->addMaterialTag($a_xml_writer, $this->getIntroduction(), true, true, $attrs);
3425  $attrs = array(
3426  "label" => "outro"
3427  );
3428  $this->addMaterialTag($a_xml_writer, $this->getOutro(), true, true, $attrs);
3429  $a_xml_writer->xmlEndTag("objectives");
3430 
3431  if ($this->getAnonymize()) {
3432  $attribs = array("enabled" => "1");
3433  } else {
3434  $attribs = array("enabled" => "0");
3435  }
3436  $a_xml_writer->xmlElement("anonymisation", $attribs);
3437  $a_xml_writer->xmlStartTag("restrictions");
3438  if ($this->getAnonymize() == 2) {
3439  $attribs = array("type" => "free");
3440  } else {
3441  $attribs = array("type" => "restricted");
3442  }
3443  $a_xml_writer->xmlElement("access", $attribs);
3444  if ($this->getStartDate()) {
3445  $attrs = array("type" => "date");
3446  preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getStartDate(), $matches);
3447  $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]));
3448  }
3449  if ($this->getEndDate()) {
3450  $attrs = array("type" => "date");
3451  preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndDate(), $matches);
3452  $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]));
3453  }
3454  $a_xml_writer->xmlEndTag("restrictions");
3455 
3456  // constraints
3457  $pages = &$this->getSurveyPages();
3458  $hasconstraints = false;
3459  foreach ($pages as $question_array) {
3460  foreach ($question_array as $question) {
3461  if (count($question["constraints"])) {
3462  $hasconstraints = true;
3463  }
3464  }
3465  }
3466 
3467  if ($hasconstraints) {
3468  $a_xml_writer->xmlStartTag("constraints");
3469  foreach ($pages as $question_array) {
3470  foreach ($question_array as $question) {
3471  if (count($question["constraints"])) {
3472  // found constraints
3473  foreach ($question["constraints"] as $constraint) {
3474  $attribs = array(
3475  "sourceref" => $question["question_id"],
3476  "destref" => $constraint["question"],
3477  "relation" => $constraint["short"],
3478  "value" => $constraint["value"],
3479  "conjunction" => $constraint["conjunction"]
3480  );
3481  $a_xml_writer->xmlElement("constraint", $attribs);
3482  }
3483  }
3484  }
3485  }
3486  $a_xml_writer->xmlEndTag("constraints");
3487  }
3488 
3489  // add the rest of the preferences in qtimetadata tags, because there is no correspondent definition in QTI
3490  $a_xml_writer->xmlStartTag("metadata");
3491 
3492  $custom_properties = array();
3493  $custom_properties["evaluation_access"] = $this->getEvaluationAccess();
3494  $custom_properties["status"] = !$this->getOfflineStatus();
3495  $custom_properties["display_question_titles"] = $this->getShowQuestionTitles();
3496  $custom_properties["pool_usage"] = (int) $this->getPoolUsage();
3497 
3498  $custom_properties["own_results_view"] = (int) $this->hasViewOwnResults();
3499  $custom_properties["own_results_mail"] = (int) $this->hasMailOwnResults();
3500  $custom_properties["confirmation_mail"] = (int) $this->hasMailConfirmation();
3501 
3502  $custom_properties["anon_user_list"] = (int) $this->hasAnonymousUserList();
3503  $custom_properties["mode"] = (int) $this->getMode();
3504  $custom_properties["mode_360_self_eval"] = (int) $this->get360SelfEvaluation();
3505  $custom_properties["mode_360_self_rate"] = (int) $this->get360SelfRaters();
3506  $custom_properties["mode_360_self_appr"] = (int) $this->get360SelfAppraisee();
3507  $custom_properties["mode_360_results"] = $this->get360Results();
3508  $custom_properties["mode_skill_service"] = (int) $this->getSkillService();
3509  $custom_properties["mode_self_eval_results"] = (int) $this->getSelfEvaluationResults();
3510 
3511 
3512  // :TODO: skills?
3513 
3514  // reminder/tutor notification are (currently?) not exportable
3515 
3516  foreach ($custom_properties as $label => $value) {
3517  $a_xml_writer->xmlStartTag("metadatafield");
3518  $a_xml_writer->xmlElement("fieldlabel", null, $label);
3519  $a_xml_writer->xmlElement("fieldentry", null, $value);
3520  $a_xml_writer->xmlEndTag("metadatafield");
3521  }
3522 
3523  $a_xml_writer->xmlStartTag("metadatafield");
3524  $a_xml_writer->xmlElement("fieldlabel", null, "SCORM");
3525  include_once "./Services/MetaData/classes/class.ilMD.php";
3526  $md = new ilMD($this->getId(), 0, $this->getType());
3527  $writer = new ilXmlWriter();
3528  $md->toXml($writer);
3529  $metadata = $writer->xmlDumpMem();
3530  $a_xml_writer->xmlElement("fieldentry", null, $metadata);
3531  $a_xml_writer->xmlEndTag("metadatafield");
3532 
3533  $a_xml_writer->xmlEndTag("metadata");
3534  $a_xml_writer->xmlEndTag("survey");
3535 
3536  $attribs = array("id" => $this->getId());
3537  $a_xml_writer->xmlStartTag("surveyquestions", $attribs);
3538  // add questionblock descriptions
3539  foreach ($pages as $question_array) {
3540  if (count($question_array) > 1) {
3541  $attribs = array("id" => $question_array[0]["question_id"]);
3542  $attribs = array("showQuestiontext" => $question_array[0]["questionblock_show_questiontext"],
3543  "showBlocktitle" => $question_array[0]["questionblock_show_blocktitle"]);
3544  $a_xml_writer->xmlStartTag("questionblock", $attribs);
3545  if (strlen($question_array[0]["questionblock_title"])) {
3546  $a_xml_writer->xmlElement("questionblocktitle", null, $question_array[0]["questionblock_title"]);
3547  }
3548  }
3549  foreach ($question_array as $question) {
3550  if (strlen($question["heading"])) {
3551  $a_xml_writer->xmlElement("textblock", null, $question["heading"]);
3552  }
3553  $questionObject = self::_instanciateQuestion($question["question_id"]);
3554  //questionObject contains all the fields from the database. (loadFromDb)
3555  //we don't need the value from svy_qst_oblig table, we already have the values from svy_question table.
3556  //if ($questionObject !== FALSE) $questionObject->insertXML($a_xml_writer, FALSE, $obligatory_states[$question["question_id"]]);
3557  if ($questionObject !== false) {
3558  $questionObject->insertXML($a_xml_writer, false);
3559  }
3560  }
3561  if (count($question_array) > 1) {
3562  $a_xml_writer->xmlEndTag("questionblock");
3563  }
3564  }
3565 
3566  $a_xml_writer->xmlEndTag("surveyquestions");
3567  $a_xml_writer->xmlEndTag("surveyobject");
3568  $xml = $a_xml_writer->xmlDumpMem(false);
3569  return $xml;
3570  }
3571 
3579  public static function _instanciateQuestion($question_id)
3580  {
3581  if ($question_id < 1) {
3582  return false;
3583  }
3584  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
3585  $question_type = SurveyQuestion::_getQuestionType($question_id);
3586  if (strlen($question_type) == 0) {
3587  return false;
3588  }
3589  SurveyQuestion::_includeClass($question_type);
3590  $question = new $question_type();
3591  $question->loadFromDb($question_id);
3592  return $question;
3593  }
3594 
3601  public function locateImportFiles($a_dir)
3602  {
3603  if (!is_dir($a_dir) || is_int(strpos($a_dir, ".."))) {
3604  return;
3605  }
3606  $importDirectory = "";
3607  $xmlFile = "";
3608 
3609  $current_dir = opendir($a_dir);
3610  $files = array();
3611  while ($entryname = readdir($current_dir)) {
3612  $files[] = $entryname;
3613  }
3614 
3615  foreach ($files as $file) {
3616  if (is_dir($a_dir . "/" . $file) and ($file != "." and $file != "..")) {
3617  // found directory created by zip
3618  $importDirectory = $a_dir . "/" . $file;
3619  }
3620  }
3621  closedir($current_dir);
3622  if (strlen($importDirectory)) {
3623  // find the xml file
3624  $current_dir = opendir($importDirectory);
3625  $files = array();
3626  while ($entryname = readdir($current_dir)) {
3627  $files[] = $entryname;
3628  }
3629  foreach ($files as $file) {
3630  if (@is_file($importDirectory . "/" . $file) &&
3631  ($file != "." && $file != "..") &&
3632  (preg_match("/^[0-9]{10}__[0-9]+__(svy_)*[0-9]+\.[A-Za-z]{1,3}$/", $file) ||
3633  preg_match("/^[0-9]{10}__[0-9]+__(survey__)*[0-9]+\.[A-Za-z]{1,3}$/", $file))) {
3634  // found xml file
3635  $xmlFile = $importDirectory . "/" . $file;
3636  }
3637  }
3638  }
3639  return array("dir" => $importDirectory, "xml" => $xmlFile);
3640  }
3641 
3650  public function importObject($file_info, $svy_qpl_id)
3651  {
3652  if ($svy_qpl_id < 1) {
3653  $svy_qpl_id = -1;
3654  }
3655  // check if file was uploaded
3656  $source = $file_info["tmp_name"];
3657  $error = "";
3658  if (($source == 'none') || (!$source) || $file_info["error"] > UPLOAD_ERR_OK) {
3659  $error = $this->lng->txt("import_no_file_selected");
3660  }
3661  // check correct file type
3662  $isXml = false;
3663  $isZip = false;
3664  if ((strcmp($file_info["type"], "text/xml") == 0) || (strcmp($file_info["type"], "application/xml") == 0)) {
3665  $this->log->debug("isXML");
3666  $isXml = true;
3667  }
3668  // too many different mime-types, so we use the suffix
3669  $suffix = pathinfo($file_info["name"]);
3670  if (strcmp(strtolower($suffix["extension"]), "zip") == 0) {
3671  $this->log->debug("isZip");
3672  $isZip = true;
3673  }
3674  if (!$isXml && !$isZip) {
3675  $error = $this->lng->txt("import_wrong_file_type");
3676  $this->log->debug("Survey: Import error. Filetype was \"" . $file_info["type"] . "\"");
3677  }
3678  if (strlen($error) == 0) {
3679  // import file as a survey
3680  $import_dir = $this->getImportDirectory();
3681  $import_subdir = "";
3682  $importfile = "";
3683  if ($isZip) {
3684  $importfile = $import_dir . "/" . $file_info["name"];
3685  ilUtil::moveUploadedFile($source, $file_info["name"], $importfile);
3686  ilUtil::unzip($importfile);
3687  $found = $this->locateImportFiles($import_dir);
3688  if (!((strlen($found["dir"]) > 0) && (strlen($found["xml"]) > 0))) {
3689  $error = $this->lng->txt("wrong_import_file_structure");
3690  return $error;
3691  }
3692  $importfile = $found["xml"];
3693  $import_subdir = $found["dir"];
3694  } else {
3695  $importfile = tempnam($import_dir, "survey_import");
3696  ilUtil::moveUploadedFile($source, $file_info["name"], $importfile);
3697  }
3698 
3699  $this->log->debug("Import file = $importfile");
3700  $this->log->debug("Import subdir = $import_subdir");
3701 
3702  $fh = fopen($importfile, "r");
3703  if (!$fh) {
3704  $error = $this->lng->txt("import_error_opening_file");
3705  return $error;
3706  }
3707  $xml = fread($fh, filesize($importfile));
3708  $result = fclose($fh);
3709  if (!$result) {
3710  $error = $this->lng->txt("import_error_closing_file");
3711  return $error;
3712  }
3713 
3714  unset($_SESSION["import_mob_xhtml"]);
3715  if (strpos($xml, "questestinterop")) {
3716  include_once("./Modules/Survey/exceptions/class.ilInvalidSurveyImportFileException.php");
3717  throw new ilInvalidSurveyImportFileException("Unsupported survey version (< 3.8) found.");
3718  } else {
3719  $this->log->debug("survey id = " . $this->getId());
3720  $this->log->debug("question pool id = " . $svy_qpl_id);
3721 
3722  include_once("./Services/Export/classes/class.ilImport.php");
3723  $imp = new ilImport();
3724  $config = $imp->getConfig("Modules/Survey");
3725  $config->setQuestionPoolID($svy_qpl_id);
3726  $imp->getMapping()->addMapping("Modules/Survey", "svy", 0, $this->getId());
3727  $imp->importFromDirectory($import_subdir, "svy", "Modules/Survey");
3728  $this->log->debug("config(Modules/survey)->getQuestionPoolId =" . $config->getQuestionPoolID());
3729  return "";
3730 
3731  //old code
3732  include_once "./Services/Survey/classes/class.SurveyImportParser.php";
3733  $import = new SurveyImportParser($svy_qpl_id, "", true);
3734  $import->setSurveyObject($this);
3735  $import->setXMLContent($xml);
3736  $import->startParsing();
3737  }
3738 
3739  if (is_array($_SESSION["import_mob_xhtml"])) {
3740  include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
3741  include_once "./Services/RTE/classes/class.ilRTE.php";
3742  include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
3743  foreach ($_SESSION["import_mob_xhtml"] as $mob) {
3744  $importfile = $import_subdir . "/" . $mob["uri"];
3745  if (file_exists($importfile)) {
3746  if (!$mob["type"]) {
3747  $mob["type"] = "svy:html";
3748  }
3749 
3750  $media_object = ilObjMediaObject::_saveTempFileAsMediaObject(basename($importfile), $importfile, false);
3751 
3752  // survey mob
3753  if ($mob["type"] == "svy:html") {
3754  ilObjMediaObject::_saveUsage($media_object->getId(), "svy:html", $this->getId());
3755  $this->setIntroduction(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getIntroduction()));
3756  $this->setOutro(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getOutro()));
3757  }
3758  // question mob
3759  elseif ($import->questions[$mob["id"]]) {
3760  $new_qid = $import->questions[$mob["id"]];
3761  ilObjMediaObject::_saveUsage($media_object->getId(), $mob["type"], $new_qid);
3762  $new_question = SurveyQuestion::_instanciateQuestion($new_qid);
3763  $qtext = $new_question->getQuestiontext();
3764  $qtext = ilRTE::_replaceMediaObjectImageSrc($qtext, 0);
3765  $qtext = str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $qtext);
3766  $qtext = ilRTE::_replaceMediaObjectImageSrc($qtext, 1);
3767  $new_question->setQuestiontext($qtext);
3768  $new_question->saveToDb();
3769 
3770  // also fix existing original in pool
3771  if ($new_question->getOriginalId()) {
3772  $pool_question = SurveyQuestion::_instanciateQuestion($new_question->getOriginalId());
3773  $pool_question->setQuestiontext($qtext);
3774  $pool_question->saveToDb();
3775  }
3776  }
3777  } else {
3778  $ilLog = $this->log;
3779  $ilLog->write("Error: Could not open XHTML mob file for test introduction during test import. File $importfile does not exist!");
3780  }
3781  }
3784  $this->saveToDb();
3785  }
3786 
3787  // delete import directory
3789  }
3790  return $error;
3791  }
3792 
3801  public function cloneObject($a_target_id, $a_copy_id = 0, $a_omit_tree = false)
3802  {
3803  $ilDB = $this->db;
3804 
3805  $this->loadFromDb();
3806 
3807  //survey mode
3808  $svy_type = $this->getMode();
3809 
3810  // Copy settings
3811  $newObj = parent::cloneObject($a_target_id, $a_copy_id, $a_omit_tree);
3812  $this->cloneMetaData($newObj);
3813  $newObj->updateMetaData();
3814 
3815  $newObj->setAuthor($this->getAuthor());
3816  $newObj->setIntroduction($this->getIntroduction());
3817  $newObj->setOutro($this->getOutro());
3818  $newObj->setEvaluationAccess($this->getEvaluationAccess());
3819  $newObj->setStartDate($this->getStartDate());
3820  $newObj->setEndDate($this->getEndDate());
3821  $newObj->setInvitation($this->getInvitation());
3822  $newObj->setInvitationMode($this->getInvitationMode());
3823  $newObj->setAnonymize($this->getAnonymize());
3824  $newObj->setShowQuestionTitles($this->getShowQuestionTitles());
3825  $newObj->setTemplate($this->getTemplate());
3826  $newObj->setPoolUsage($this->getPoolUsage());
3827  $newObj->setViewOwnResults($this->hasViewOwnResults());
3828  $newObj->setMailOwnResults($this->hasMailOwnResults());
3829  $newObj->setMailConfirmation($this->hasMailConfirmation());
3830  $newObj->setAnonymousUserList($this->hasAnonymousUserList());
3831 
3832  // #12661
3833  if ($this->get360Mode()) {
3834  $newObj->setMode(ilObjSurvey::MODE_360);
3835  $newObj->set360SelfEvaluation($this->get360SelfEvaluation());
3836  $newObj->set360SelfAppraisee($this->get360SelfAppraisee());
3837  $newObj->set360SelfRaters($this->get360SelfRaters());
3838  $newObj->set360Results($this->get360Results());
3839  $newObj->setSkillService($this->getSkillService());
3840  }
3841  //svy mode self eval: skills + view results
3842  if ($svy_type == ilObjSurvey::MODE_SELF_EVAL) {
3843  $newObj->setMode(ilObjSurvey::MODE_SELF_EVAL);
3844  $newObj->setSkillService($this->getSkillService());
3845  $newObj->setSelfEvaluationResults($this->getSelfEvaluationResults());
3846  }
3847 
3848  // reminder/notification
3849  $newObj->setReminderStatus($this->getReminderStatus());
3850  $newObj->setReminderStart($this->getReminderStart());
3851  $newObj->setReminderEnd($this->getReminderEnd());
3852  $newObj->setReminderFrequency($this->getReminderFrequency());
3853  $newObj->setReminderTarget($this->getReminderTarget());
3854  $newObj->setReminderTemplate($this->getReminderTemplate());
3855  // reminder_last_sent must not be copied!
3856  $newObj->setTutorNotificationStatus($this->getTutorNotificationStatus());
3857  $newObj->setTutorNotificationRecipients($this->getTutorNotificationRecipients());
3858  $newObj->setTutorNotificationTarget($this->getTutorNotificationTarget());
3859 
3860  $newObj->setMailNotification($this->getMailNotification());
3861  $newObj->setMailAddresses($this->getMailAddresses());
3862  $newObj->setMailParticipantData($this->getMailParticipantData());
3863 
3864  $question_pointer = array();
3865  // clone the questions
3866  $mapping = array();
3867  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
3868 
3869  foreach ($this->questions as $key => $question_id) {
3871  $question = self::_instanciateQuestion($question_id);
3872  if ($question) { // #10824
3873  $question->id = -1;
3874  $original_id = SurveyQuestion::_getOriginalId($question_id, false);
3875  $question->setObjId($newObj->getId());
3876  $question->saveToDb($original_id);
3877  $newObj->questions[$key] = $question->getId();
3878  $question_pointer[$question_id] = $question->getId();
3879  $mapping[$question_id] = $question->getId();
3880  }
3881  }
3882 
3883  //copy online status if object is not the root copy object
3884  $cp_options = ilCopyWizardOptions::_getInstance($a_copy_id);
3885 
3886  if (!$cp_options->isRootNode($this->getRefId())) {
3887  $newObj->setOfflineStatus($this->getOfflineStatus());
3888  }
3889 
3890  $newObj->saveToDb();
3891  $newObj->cloneTextblocks($mapping);
3892 
3893  // #14929
3894  if (($svy_type == ilObjSurvey::MODE_360 || $svy_type == ilObjSurvey::MODE_SELF_EVAL) &&
3895  $this->getSkillService()) {
3896  include_once "./Modules/Survey/classes/class.ilSurveySkill.php";
3897  $src_skills = new ilSurveySkill($this);
3898  $tgt_skills = new ilSurveySkill($newObj);
3899 
3900  foreach ($mapping as $src_qst_id => $tgt_qst_id) {
3901  $qst_skill = $src_skills->getSkillForQuestion($src_qst_id);
3902  if ($qst_skill) {
3903  $tgt_skills->addQuestionSkillAssignment($tgt_qst_id, $qst_skill["base_skill_id"], $qst_skill["tref_id"]);
3904  }
3905  }
3906  }
3907 
3908  // clone the questionblocks
3909  $questionblocks = array();
3910  $questionblock_questions = array();
3911  $result = $ilDB->queryF(
3912  "SELECT * FROM svy_qblk_qst WHERE survey_fi = %s",
3913  array('integer'),
3914  array($this->getSurveyId())
3915  );
3916  if ($result->numRows() > 0) {
3917  while ($row = $ilDB->fetchAssoc($result)) {
3918  array_push($questionblock_questions, $row);
3919  $questionblocks[$row["questionblock_fi"]] = $row["questionblock_fi"];
3920  }
3921  }
3922  // create new questionblocks
3923  foreach ($questionblocks as $key => $value) {
3924  $questionblock = self::_getQuestionblock($key);
3925  $questionblock_id = self::_addQuestionblock($questionblock["title"], $questionblock["owner_fi"], $questionblock["show_questiontext"], $questionblock["show_blocktitle"]);
3926  $questionblocks[$key] = $questionblock_id;
3927  }
3928  // create new questionblock questions
3929  foreach ($questionblock_questions as $key => $value) {
3930  if ($questionblocks[$value["questionblock_fi"]] &&
3931  $question_pointer[$value["question_fi"]]) {
3932  $next_id = $ilDB->nextId('svy_qblk_qst');
3933  $affectedRows = $ilDB->manipulateF(
3934  "INSERT INTO svy_qblk_qst (qblk_qst_id, survey_fi, questionblock_fi, question_fi) " .
3935  "VALUES (%s, %s, %s, %s)",
3936  array('integer','integer','integer','integer'),
3937  array($next_id, $newObj->getSurveyId(), $questionblocks[$value["questionblock_fi"]], $question_pointer[$value["question_fi"]])
3938  );
3939  }
3940  }
3941 
3942  // clone the constraints
3943  $constraints = self::_getConstraints($this->getSurveyId());
3944  $newConstraints = array();
3945  foreach ($constraints as $key => $constraint) {
3946  if ($question_pointer[$constraint["for_question"]] &&
3947  $question_pointer[$constraint["question"]]) {
3948  if (!array_key_exists($constraint['id'], $newConstraints)) {
3949  $constraint_id = $newObj->addConstraint($question_pointer[$constraint["question"]], $constraint["relation_id"], $constraint["value"], $constraint['conjunction']);
3950  $newConstraints[$constraint['id']] = $constraint_id;
3951  }
3952  $newObj->addConstraintToQuestion($question_pointer[$constraint["for_question"]], $newConstraints[$constraint['id']]);
3953  }
3954  }
3955 
3956  // #16210 - clone LP settings
3957  include_once('./Services/Tracking/classes/class.ilLPObjSettings.php');
3958  $obj_settings = new ilLPObjSettings($this->getId());
3959  $obj_settings->cloneSettings($newObj->getId());
3960  unset($obj_settings);
3961 
3962  return $newObj;
3963  }
3964 
3965  public function getTextblock($question_id)
3966  {
3967  $ilDB = $this->db;
3968  $result = $ilDB->queryF(
3969  "SELECT * FROM svy_svy_qst WHERE question_fi = %s",
3970  array('integer'),
3971  array($question_id)
3972  );
3973  if ($result->numRows()) {
3974  $row = $ilDB->fetchAssoc($result);
3975  return $row["heading"];
3976  } else {
3977  return "";
3978  }
3979  }
3980 
3986  public function cloneTextblocks($mapping)
3987  {
3988  foreach ($mapping as $original_id => $new_id) {
3989  $textblock = $this->getTextblock($original_id);
3990  include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
3991  $this->saveHeading(ilUtil::stripSlashes($textblock, true, ilObjAdvancedEditing::_getUsedHTMLTagsAsString("survey")), $new_id);
3992  }
3993  }
3994 
4002  public function createExportDirectory()
4003  {
4004  $svy_data_dir = ilUtil::getDataDir() . "/svy_data";
4005  ilUtil::makeDir($svy_data_dir);
4006  if (!is_writable($svy_data_dir)) {
4007  include_once "Modules/Survey/exceptions/class.ilSurveyException.php";
4008  throw new ilSurveyException("Survey Data Directory (" . $svy_data_dir . ") not writeable.");
4009  }
4010 
4011  // create learning module directory (data_dir/lm_data/lm_<id>)
4012  $svy_dir = $svy_data_dir . "/svy_" . $this->getId();
4013  ilUtil::makeDir($svy_dir);
4014  if (!@is_dir($svy_dir)) {
4015  include_once "Modules/Survey/exceptions/class.ilSurveyException.php";
4016  throw new ilSurveyException("Creation of Survey Directory failed.");
4017  }
4018  // create Export subdirectory (data_dir/lm_data/lm_<id>/Export)
4019  $export_dir = $svy_dir . "/export";
4020  ilUtil::makeDir($export_dir);
4021  if (!@is_dir($export_dir)) {
4022  include_once "Modules/Survey/exceptions/class.ilSurveyException.php";
4023  throw new ilSurveyException("Creation of Export Directory failed.");
4024  }
4025  }
4026 
4030  public function getExportDirectory()
4031  {
4032  $export_dir = ilUtil::getDataDir() . "/svy_data" . "/svy_" . $this->getId() . "/export";
4033 
4034  return $export_dir;
4035  }
4036 
4044  public function createImportDirectory()
4045  {
4046  $svy_data_dir = ilUtil::getDataDir() . "/svy_data";
4047  ilUtil::makeDir($svy_data_dir);
4048 
4049  if (!is_writable($svy_data_dir)) {
4050  include_once "Modules/Survey/exceptions/class.ilSurveyException.php";
4051  throw new ilSurveyException("Survey Data Directory (" . $svy_data_dir . ") not writeable.");
4052  }
4053 
4054  // create test directory (data_dir/svy_data/svy_<id>)
4055  $svy_dir = $svy_data_dir . "/svy_" . $this->getId();
4056  ilUtil::makeDir($svy_dir);
4057  if (!@is_dir($svy_dir)) {
4058  include_once "Modules/Survey/exceptions/class.ilSurveyException.php";
4059  throw new ilSurveyException("Creation of Survey Directory failed.");
4060  }
4061 
4062  // create import subdirectory (data_dir/svy_data/svy_<id>/import)
4063  $import_dir = $svy_dir . "/import";
4064  ilUtil::makeDir($import_dir);
4065  if (!@is_dir($import_dir)) {
4066  include_once "Modules/Survey/exceptions/class.ilSurveyException.php";
4067  throw new ilSurveyException("Creation of Import Directory failed.");
4068  }
4069  }
4070 
4074  public function getImportDirectory()
4075  {
4076  $import_dir = ilUtil::getDataDir() . "/svy_data" .
4077  "/svy_" . $this->getId() . "/import";
4078  if (!is_dir($import_dir)) {
4079  ilUtil::makeDirParents($import_dir);
4080  }
4081  if (@is_dir($import_dir)) {
4082  return $import_dir;
4083  } else {
4084  return false;
4085  }
4086  }
4087 
4088  public function saveHeading($heading = "", $insertbefore)
4089  {
4090  $ilDB = $this->db;
4091  if ($heading) {
4092  $affectedRows = $ilDB->manipulateF(
4093  "UPDATE svy_svy_qst SET heading=%s WHERE survey_fi=%s AND question_fi=%s",
4094  array('text','integer','integer'),
4095  array($heading, $this->getSurveyId(), $insertbefore)
4096  );
4097  } else {
4098  $affectedRows = $ilDB->manipulateF(
4099  "UPDATE svy_svy_qst SET heading=%s WHERE survey_fi=%s AND question_fi=%s",
4100  array('text','integer','integer'),
4101  array(null, $this->getSurveyId(), $insertbefore)
4102  );
4103  }
4104  }
4105 
4106  public function isAnonymousKey($key)
4107  {
4108  $ilDB = $this->db;
4109 
4110  $result = $ilDB->queryF(
4111  "SELECT anonymous_id FROM svy_anonymous WHERE survey_key = %s AND survey_fi = %s",
4112  array('text','integer'),
4113  array($key, $this->getSurveyId())
4114  );
4115  return ($result->numRows() == 1) ? true : false;
4116  }
4117 
4118  public function bindSurveyCodeToUser($user_id, $code)
4119  {
4120  $ilDB = $this->db;
4121 
4122  if ($user_id == ANONYMOUS_USER_ID) {
4123  return;
4124  }
4125 
4126  if ($this->checkSurveyCode($code)) {
4127  $ilDB->manipulate("UPDATE svy_anonymous" .
4128  " SET user_key = " . $ilDB->quote(md5($user_id), "text") .
4129  " WHERE survey_key = " . $ilDB->quote($code, "text"));
4130  }
4131  }
4132 
4134  {
4135  $ilDB = $this->db;
4136 
4137  $result = $ilDB->queryF(
4138  "SELECT finished_id FROM svy_finished WHERE anonymous_id = %s AND survey_fi = %s",
4139  array('text','integer'),
4140  array($key, $this->getSurveyId())
4141  );
4142  return ($result->numRows() == 1) ? true : false;
4143  }
4144 
4145  public function checkSurveyCode($code)
4146  {
4147  if ($this->isAnonymousKey($code)) {
4148  if ($this->isSurveyStarted("", $code) == 1) {
4149  return false;
4150  } else {
4151  return true;
4152  }
4153  } else {
4154  return false;
4155  }
4156  }
4157 
4165  public function getSurveyCodesForExport(array $a_codes = null, array $a_ids = null)
4166  {
4167  $ilDB = $this->db;
4168  $ilUser = $this->user;
4169  $lng = $this->lng;
4170 
4171  include_once "./Services/Link/classes/class.ilLink.php";
4172 
4173  $sql = "SELECT svy_anonymous.*, svy_finished.state" .
4174  " FROM svy_anonymous" .
4175  " LEFT JOIN svy_finished ON (svy_anonymous.survey_key = svy_finished.anonymous_id)" .
4176  " WHERE svy_anonymous.survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
4177  " AND svy_anonymous.user_key IS NULL";
4178 
4179  if ($a_codes) {
4180  $sql .= " AND " . $ilDB->in("svy_anonymous.survey_key", $a_codes, "", "text");
4181  } elseif ($a_ids) {
4182  $sql .= " AND " . $ilDB->in("svy_anonymous.anonymous_id", $a_ids, "", "text");
4183  }
4184 
4185  $export = array();
4186 
4187  // #14905
4188  $titles = array();
4189  $titles[] = '"' . $lng->txt("survey_code") . '"';
4190  $titles[] = '"' . $lng->txt("email") . '"';
4191  $titles[] = '"' . $lng->txt("lastname") . '"';
4192  $titles[] = '"' . $lng->txt("firstname") . '"';
4193  $titles[] = '"' . $lng->txt("create_date") . '"';
4194  $titles[] = '"' . $lng->txt("used") . '"';
4195  $titles[] = '"' . $lng->txt("mail_sent_short") . '"';
4196  $titles[] = '"' . $lng->txt("survey_code_url") . '"';
4197  $export[] = implode(";", $titles);
4198 
4199  $result = $ilDB->query($sql);
4200  $default_lang = $ilUser->getPref("survey_code_language");
4201  while ($row = $ilDB->fetchAssoc($result)) {
4202  $item = array();
4203  $item[] = $row["survey_key"];
4204 
4205  if ($row["externaldata"]) {
4206  $ext = unserialize($row["externaldata"]);
4207  $item[] = $ext["email"];
4208  $item[] = $ext["lastname"];
4209  $item[] = $ext["firstname"];
4210  } else {
4211  $item[] = "";
4212  $item[] = "";
4213  $item[] = "";
4214  }
4215 
4216  // No relative (today, tomorrow...) dates in export.
4217  $date = new ilDateTime($row['tstamp'], IL_CAL_UNIX);
4218  $item[] = $date->get(IL_CAL_DATETIME);
4219 
4220  $item[] = ($this->isSurveyCodeUsed($row["survey_key"])) ? 1 : 0;
4221  $item[] = ($row["sent"]) ? 1 : 0;
4222 
4223  $params = array("accesscode" => $row["survey_key"]);
4224  if ($default_lang) {
4225  $params["lang"] = $default_lang;
4226  }
4227  $item[] = ilLink::_getLink($this->getRefId(), "svy", $params);
4228 
4229  $export[] = '"' . implode('";"', $item) . '"';
4230  }
4231  return implode("\n", $export);
4232  }
4233 
4241  public function getSurveyCodesTableData(array $ids = null, $lang = null)
4242  {
4243  $ilDB = $this->db;
4244 
4245  include_once "./Services/Link/classes/class.ilLink.php";
4246 
4247  $codes = array();
4248 
4249  $sql = "SELECT svy_anonymous.*, svy_finished.state" .
4250  " FROM svy_anonymous" .
4251  " LEFT JOIN svy_finished ON (svy_anonymous.survey_key = svy_finished.anonymous_id)" .
4252  " WHERE svy_anonymous.survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") /*.
4253  " AND svy_anonymous.user_key IS NULL" */; // #15860
4254 
4255  if ($ids) {
4256  $sql .= " AND " . $ilDB->in("svy_anonymous.anonymous_id", $ids, "", "integer");
4257  }
4258 
4259  $sql .= " ORDER BY tstamp, survey_key ASC";
4260  $result = $ilDB->query($sql);
4261  if ($result->numRows() > 0) {
4262  while ($row = $ilDB->fetchAssoc($result)) {
4263  $href = "";
4264  $used = false;
4265  if ($this->isSurveyCodeUsed($row["survey_key"])) {
4266  $used = true;
4267  } else {
4268  $params = array("accesscode" => $row["survey_key"]);
4269  if ($lang) {
4270  $params["lang"] = $lang;
4271  }
4272  $href = ilLink::_getLink($this->getRefId(), "svy", $params);
4273  }
4274 
4275 
4276  $item = array(
4277  'id' => $row["anonymous_id"],
4278  'code' => $row["survey_key"],
4279  'date' => $row["tstamp"],
4280  'used' => $used,
4281  'sent' => $row['sent'],
4282  'href' => $href,
4283  'email' => '',
4284  'last_name' => '',
4285  'first_name' => ''
4286  );
4287 
4288  if ($row["externaldata"]) {
4289  $ext = unserialize($row["externaldata"]);
4290  $item['email'] = $ext['email'];
4291  $item['last_name'] = $ext['lastname'];
4292  $item['first_name'] = $ext['firstname'];
4293  }
4294 
4295  array_push($codes, $item);
4296  }
4297  }
4298  return $codes;
4299  }
4300 
4301  public function isSurveyCodeUsed($code)
4302  {
4303  $ilDB = $this->db;
4304  $result = $ilDB->queryF(
4305  "SELECT finished_id FROM svy_finished WHERE survey_fi = %s AND anonymous_id = %s",
4306  array('integer','text'),
4307  array($this->getSurveyId(), $code)
4308  );
4309  return ($result->numRows() > 0) ? true : false;
4310  }
4311 
4312  public function isSurveyCodeUnique($code)
4313  {
4314  $ilDB = $this->db;
4315  $result = $ilDB->queryF(
4316  "SELECT anonymous_id FROM svy_anonymous WHERE survey_fi = %s AND survey_key = %s",
4317  array('integer','text'),
4318  array($this->getSurveyId(), $code)
4319  );
4320  return ($result->numRows() > 0) ? false : true;
4321  }
4322 
4323  public function createSurveyCodes($nrOfCodes)
4324  {
4325  $ilDB = $this->db;
4326 
4327  $res = array();
4328 
4329  for ($i = 0; $i < $nrOfCodes; $i++) {
4330  $next_id = $ilDB->nextId('svy_anonymous');
4331  $ilDB->manipulateF(
4332  "INSERT INTO svy_anonymous (anonymous_id, survey_key, survey_fi, tstamp) " .
4333  "VALUES (%s, %s, %s, %s)",
4334  array('integer','text','integer','integer'),
4335  array($next_id, $this->createNewAccessCode(), $this->getSurveyId(), time())
4336  );
4337  $res[] = $next_id;
4338  }
4339 
4340  return $res;
4341  }
4342 
4343  public function importSurveyCode($a_anonymize_key, $a_created, $a_data)
4344  {
4345  $ilDB = $this->db;
4346 
4347  $next_id = $ilDB->nextId('svy_anonymous');
4348  $ilDB->manipulateF(
4349  "INSERT INTO svy_anonymous (anonymous_id, survey_key, survey_fi, externaldata, tstamp) " .
4350  "VALUES (%s, %s, %s, %s, %s)",
4351  array('integer','text','integer','text','integer'),
4352  array($next_id, $a_anonymize_key, $this->getSurveyId(), serialize($a_data), $a_created)
4353  );
4354  }
4355 
4357  {
4358  $ilDB = $this->db;
4359 
4360  $ids = array();
4361  foreach ($data as $dataset) {
4362  $anonymize_key = $this->createNewAccessCode();
4363  $next_id = $ilDB->nextId('svy_anonymous');
4364  $affectedRows = $ilDB->manipulateF(
4365  "INSERT INTO svy_anonymous (anonymous_id, survey_key, survey_fi, externaldata, tstamp) " .
4366  "VALUES (%s, %s, %s, %s, %s)",
4367  array('integer','text','integer','text','integer'),
4368  array($next_id, $anonymize_key, $this->getSurveyId(), serialize($dataset), time())
4369  );
4370  $ids[] = $next_id;
4371  }
4372  return $ids;
4373  }
4374 
4375  public function sendCodes($not_sent, $subject, $message, $lang)
4376  {
4377  global $DIC;
4378  /*
4379  * 0 = all
4380  * 1 = not sent
4381  * 2 = finished
4382  * 3 = not finished
4383  */
4384  $check_finished = ($not_sent > 1);
4385 
4386  include_once "./Services/Mail/classes/class.ilMail.php";
4387  include_once "./Services/Link/classes/class.ilLink.php";
4388 
4389  $mail = new ilMail(ANONYMOUS_USER_ID);
4390  $recipients = $this->getExternalCodeRecipients($check_finished);
4391  foreach ($recipients as $data) {
4392  if ($data['email'] && $data['code']) {
4393  $do_send = false;
4394  switch ((int) $not_sent) {
4395  case 1:
4396  $do_send = !(bool) $data['sent'];
4397  break;
4398 
4399  case 2:
4400  $do_send = $data['finished'];
4401  break;
4402 
4403  case 3:
4404  $do_send = !$data['finished'];
4405  break;
4406 
4407  default:
4408  $do_send = true;
4409  break;
4410  }
4411  if ($do_send) {
4412  // build text
4413  $messagetext = $message;
4415  $this->getRefId(),
4416  "svy",
4417  array(
4418  "accesscode" => $data["code"],
4419  "lang" => $lang
4420  )
4421  );
4422  $messagetext = str_replace('[url]', $url, $messagetext);
4423  foreach ($data as $key => $value) {
4424  $messagetext = str_replace('[' . $key . ']', $value, $messagetext);
4425  }
4426 
4427  // send mail
4428  $mail->sendMail(
4429  $data['email'], // to
4430  "", // cc
4431  "", // bcc
4432  $subject, // subject
4433  $messagetext, // message
4434  array(), // attachments
4435  array('normal') // type
4436  );
4437  }
4438  }
4439  }
4440 
4441  $ilDB = $this->db;
4442  $ilDB->manipulateF(
4443  "UPDATE svy_anonymous SET sent = %s WHERE survey_fi = %s AND externaldata IS NOT NULL",
4444  array('integer','integer'),
4445  array(1, $this->getSurveyId())
4446  );
4447  }
4448 
4449  public function getExternalCodeRecipients($a_check_finished = false)
4450  {
4451  $ilDB = $this->db;
4452  $result = $ilDB->queryF(
4453  "SELECT survey_key code, externaldata, sent FROM svy_anonymous WHERE survey_fi = %s",
4454  array('integer'),
4455  array($this->getSurveyId())
4456  );
4457  $res = array();
4458  while ($row = $ilDB->fetchAssoc($result)) {
4459  if (!$row['externaldata']) {
4460  continue;
4461  }
4462 
4463  $externaldata = unserialize($row['externaldata']);
4464  if (!$externaldata['email']) {
4465  continue;
4466  }
4467 
4468  $externaldata['code'] = $row['code'];
4469  $externaldata['sent'] = $row['sent'];
4470 
4471  if ($a_check_finished) {
4472  #23294
4473  //$externaldata['finished'] = $this->isSurveyCodeUsed($row['code']);
4474  $externaldata['finished'] = $this->isSurveyFinishedByCode($row['code']);
4475  }
4476 
4477  array_push($res, $externaldata);
4478  }
4479  return $res;
4480  }
4481 
4487  public function isSurveyFinishedByCode($a_code)
4488  {
4489  $result = $this->db->queryF(
4490  "SELECT state FROM svy_finished WHERE survey_fi = %s AND anonymous_id = %s",
4491  array('integer','text'),
4492  array($this->getSurveyId(), $a_code)
4493  );
4494 
4495  $row = $this->db->fetchAssoc($result);
4496 
4497  return $row['state'];
4498  }
4499 
4505  public function deleteSurveyCode($survey_code)
4506  {
4507  $ilDB = $this->db;
4508 
4509  if (strlen($survey_code) > 0) {
4510  $affectedRows = $ilDB->manipulateF(
4511  "DELETE FROM svy_anonymous WHERE survey_fi = %s AND survey_key = %s",
4512  array('integer', 'text'),
4513  array($this->getSurveyId(), $survey_code)
4514  );
4515  }
4516  }
4517 
4524  public function getUserAccessCode($user_id)
4525  {
4526  $ilDB = $this->db;
4527  $access_code = "";
4528  $result = $ilDB->queryF(
4529  "SELECT survey_key FROM svy_anonymous WHERE survey_fi = %s AND user_key = %s",
4530  array('integer','text'),
4531  array($this->getSurveyId(), md5($user_id))
4532  );
4533  if ($result->numRows()) {
4534  $row = $ilDB->fetchAssoc($result);
4535  $access_code = $row["survey_key"];
4536  }
4537  return $access_code;
4538  }
4539 
4546  public function saveUserAccessCode($user_id, $access_code)
4547  {
4548  $ilDB = $this->db;
4549 
4550  // not really sure what to do about ANONYMOUS_USER_ID
4551 
4552  $next_id = $ilDB->nextId('svy_anonymous');
4553  $affectedRows = $ilDB->manipulateF(
4554  "INSERT INTO svy_anonymous (anonymous_id, survey_key, survey_fi, user_key, tstamp) " .
4555  "VALUES (%s, %s, %s, %s, %s)",
4556  array('integer','text', 'integer', 'text', 'integer'),
4557  array($next_id, $access_code, $this->getSurveyId(), md5($user_id), time())
4558  );
4559  }
4560 
4566  public function createNewAccessCode()
4567  {
4568  // create a 5 character code
4569  $codestring = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
4570  mt_srand();
4571  $code = "";
4572  for ($i = 1; $i <= 5; $i++) {
4573  $index = mt_rand(0, strlen($codestring) - 1);
4574  $code .= substr($codestring, $index, 1);
4575  }
4576  // verify it against the database
4577  while (!$this->isSurveyCodeUnique($code)) {
4578  $code = $this->createNewAccessCode();
4579  }
4580  return $code;
4581  }
4582 
4583  public function getLastAccess($finished_id)
4584  {
4585  $ilDB = $this->db;
4586 
4587  $result = $ilDB->queryF(
4588  "SELECT tstamp FROM svy_answer WHERE active_fi = %s ORDER BY tstamp DESC",
4589  array('integer'),
4590  array($finished_id)
4591  );
4592  if ($result->numRows()) {
4593  $row = $ilDB->fetchAssoc($result);
4594  return $row["tstamp"];
4595  } else {
4596  $result = $ilDB->queryF(
4597  "SELECT tstamp FROM svy_finished WHERE finished_id = %s",
4598  array('integer'),
4599  array($finished_id)
4600  );
4601  if ($result->numRows()) {
4602  $row = $ilDB->fetchAssoc($result);
4603  return $row["tstamp"];
4604  }
4605  }
4606  return "";
4607  }
4608 
4615  public function prepareTextareaOutput($txt_output)
4616  {
4617  return ilUtil::prepareTextareaOutput($txt_output, $prepare_for_latex_output);
4618  }
4619 
4627  public function isHTML($a_text)
4628  {
4629  if (preg_match("/<[^>]*?>/", $a_text)) {
4630  return true;
4631  } else {
4632  return false;
4633  }
4634  }
4635 
4644  public function addMaterialTag(&$a_xml_writer, $a_material, $close_material_tag = true, $add_mobs = true, $attribs = null)
4645  {
4646  include_once "./Services/RTE/classes/class.ilRTE.php";
4647  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
4648 
4649  $a_xml_writer->xmlStartTag("material", $attribs);
4650  $attrs = array(
4651  "type" => "text/plain"
4652  );
4653  if ($this->isHTML($a_material)) {
4654  $attrs["type"] = "text/xhtml";
4655  }
4656  $mattext = ilRTE::_replaceMediaObjectImageSrc($a_material, 0);
4657  $a_xml_writer->xmlElement("mattext", $attrs, $mattext);
4658 
4659  if ($add_mobs) {
4660  $mobs = ilObjMediaObject::_getMobsOfObject("svy:html", $this->getId());
4661  foreach ($mobs as $mob) {
4662  $mob_id = "il_" . IL_INST_ID . "_mob_" . $mob;
4663  if (strpos($mattext, $mob_id) !== false) {
4664  $mob_obj = new ilObjMediaObject($mob);
4665  $imgattrs = array(
4666  "label" => $mob_id,
4667  "uri" => "objects/" . "il_" . IL_INST_ID . "_mob_" . $mob . "/" . $mob_obj->getTitle(),
4668  "type" => "svy:html",
4669  "id" => $this->getId()
4670  );
4671  $a_xml_writer->xmlElement("matimage", $imgattrs, null);
4672  }
4673  }
4674  }
4675  if ($close_material_tag) {
4676  $a_xml_writer->xmlEndTag("material");
4677  }
4678  }
4679 
4688  public function canExportSurveyCode()
4689  {
4690  if ($this->getAnonymize() != self::ANONYMIZE_OFF) {
4691  if ($this->surveyCodeSecurity == false) {
4692  return true;
4693  }
4694  }
4695  return false;
4696  }
4697 
4705  public function processPrintoutput2FO($print_output)
4706  {
4707  if (extension_loaded("tidy")) {
4708  $config = array(
4709  "indent" => false,
4710  "output-xml" => true,
4711  "numeric-entities" => true
4712  );
4713  $tidy = new tidy();
4714  $tidy->parseString($print_output, $config, 'utf8');
4715  $tidy->cleanRepair();
4716  $print_output = tidy_get_output($tidy);
4717  $print_output = preg_replace("/^.*?(<html)/", "\\1", $print_output);
4718  } else {
4719  $print_output = str_replace("&nbsp;", "&#160;", $print_output);
4720  $print_output = str_replace("&otimes;", "X", $print_output);
4721 
4722  // #17680 - metric questions use &#160; in print view
4723  $print_output = str_replace("&gt;", "~|gt|~", $print_output); // see #21550
4724  $print_output = str_replace("&lt;", "~|lt|~", $print_output);
4725  $print_output = str_replace("&#160;", "~|nbsp|~", $print_output);
4726  $print_output = preg_replace('/&(?!amp)/', '&amp;', $print_output);
4727  $print_output = str_replace("~|nbsp|~", "&#160;", $print_output);
4728  $print_output = str_replace("~|gt|~", "&gt;", $print_output);
4729  $print_output = str_replace("~|lt|~", "&lt;", $print_output);
4730  }
4731  $xsl = file_get_contents("./Modules/Survey/xml/question2fo.xsl");
4732 
4733  // additional font support
4734  $xsl = str_replace(
4735  'font-family="Helvetica, unifont"',
4736  'font-family="' . $GLOBALS['ilSetting']->get('rpc_pdf_font', 'Helvetica, unifont') . '"',
4737  $xsl
4738  );
4739  $args = array( '/_xml' => $print_output, '/_xsl' => $xsl );
4740  $xh = xslt_create();
4741  $params = array();
4742  try {
4743  $output = xslt_process($xh, "arg:/_xml", "arg:/_xsl", null, $args, $params);
4744  } catch (Exception $e) {
4745  $this->log->error("Print XSLT failed:");
4746  $this->log->error("Content: " . $print_output);
4747  $this->log->error("Xsl: " . $xsl);
4748  throw ($e);
4749  }
4750  xslt_error($xh);
4751  xslt_free($xh);
4752 
4753  return $output;
4754  }
4755 
4762  public function deliverPDFfromFO($fo)
4763  {
4764  $ilLog = $this->log;
4765 
4766  $fo_file = ilUtil::ilTempnam() . ".fo";
4767  $fp = fopen($fo_file, "w");
4768  fwrite($fp, $fo);
4769  fclose($fp);
4770 
4771  include_once './Services/WebServices/RPC/classes/class.ilRpcClientFactory.php';
4772  try {
4773  $pdf_base64 = ilRpcClientFactory::factory('RPCTransformationHandler')->ilFO2PDF($fo);
4774  ilUtil::deliverData($pdf_base64->scalar, ilUtil::getASCIIFilename($this->getTitle()) . ".pdf", "application/pdf");
4775  return true;
4776  } catch (Exception $e) {
4777  $ilLog->write(__METHOD__ . ': ' . $e->getMessage());
4778  return false;
4779  }
4780  }
4781 
4788  public function isPluginActive($a_pname)
4789  {
4790  $ilPluginAdmin = $this->plugin_admin;
4791  if ($ilPluginAdmin->isActive(IL_COMP_MODULE, "SurveyQuestionPool", "svyq", $a_pname)) {
4792  return true;
4793  } else {
4794  return false;
4795  }
4796  }
4797 
4803  public function setSurveyId($survey_id)
4804  {
4805  $this->survey_id = $survey_id;
4806  }
4807 
4814  public function &getUserData($ids)
4815  {
4816  $ilDB = $this->db;
4817 
4818  if (!is_array($ids) || count($ids) == 0) {
4819  return array();
4820  }
4821 
4822  $result = $ilDB->query("SELECT usr_id, login, lastname, firstname FROM usr_data WHERE " . $ilDB->in('usr_id', $ids, false, 'integer') . " ORDER BY login");
4823  $result_array = array();
4824  while ($row = $ilDB->fetchAssoc($result)) {
4825  $result_array[$row["usr_id"]] = $row;
4826  }
4827  return $result_array;
4828  }
4829 
4830  public function getMailNotification()
4831  {
4832  return $this->mailnotification;
4833  }
4834 
4835  public function setMailNotification($a_notification)
4836  {
4837  $this->mailnotification = ($a_notification) ? true : false;
4838  }
4839 
4840  public function getMailAddresses()
4841  {
4842  return $this->mailaddresses;
4843  }
4844 
4845  public function setMailAddresses($a_addresses)
4846  {
4847  $this->mailaddresses = $a_addresses;
4848  }
4849 
4850  public function getMailParticipantData()
4851  {
4853  }
4854 
4855  public function setMailParticipantData($a_data)
4856  {
4857  $this->mailparticipantdata = $a_data;
4858  }
4859 
4860  public function setStartTime($finished_id, $first_question)
4861  {
4862  $ilDB = $this->db;
4863  $time = time();
4864  //primary for table svy_times
4865  $id = $ilDB->nextId('svy_times');
4866  $_SESSION['svy_entered_page'] = $time;
4867  $affectedRows = $ilDB->manipulateF(
4868  "INSERT INTO svy_times (id, finished_fi, entered_page, left_page, first_question) VALUES (%s, %s, %s, %s,%s)",
4869  array('integer','integer', 'integer', 'integer', 'integer'),
4870  array($id, $finished_id, $time, null, $first_question)
4871  );
4872  }
4873 
4874  public function setEndTime($finished_id)
4875  {
4876  $ilDB = $this->db;
4877  $time = time();
4878  $affectedRows = $ilDB->manipulateF(
4879  "UPDATE svy_times SET left_page = %s WHERE finished_fi = %s AND entered_page = %s",
4880  array('integer', 'integer', 'integer'),
4881  array($time, $finished_id, $_SESSION['svy_entered_page'])
4882  );
4883  unset($_SESSION['svy_entered_page']);
4884  }
4885 
4886  public function getWorkingtimeForParticipant($finished_id)
4887  {
4888  $ilDB = $this->db;
4889 
4890  $result = $ilDB->queryF(
4891  "SELECT * FROM svy_times WHERE finished_fi = %s",
4892  array('integer'),
4893  array($finished_id)
4894  );
4895  $total = 0;
4896  while ($row = $ilDB->fetchAssoc($result)) {
4897  if ($row['left_page'] > 0 && $row['entered_page'] > 0) {
4898  $total += $row['left_page'] - $row['entered_page'];
4899  }
4900  }
4901  return $total;
4902  }
4903 
4904  public function setTemplate($template_id)
4905  {
4906  $this->template_id = (int) $template_id;
4907  }
4908 
4909  public function getTemplate()
4910  {
4911  return $this->template_id;
4912  }
4913 
4914  public function updateOrder(array $a_order)
4915  {
4916  if (sizeof($this->questions) == sizeof($a_order)) {
4917  $this->questions = array_flip($a_order);
4918  $this->saveQuestionsToDB();
4919  }
4920  }
4921 
4922  public function getPoolUsage()
4923  {
4924  return $this->pool_usage;
4925  }
4926 
4927  public function setPoolUsage($a_value)
4928  {
4929  $this->pool_usage = (bool) $a_value;
4930  }
4931 
4937  public function isPoolActive()
4938  {
4939  $use_pool = (bool) $this->getPoolUsage();
4940  $template_settings = $this->getTemplate();
4941  if ($template_settings) {
4942  include_once "Services/Administration/classes/class.ilSettingsTemplate.php";
4943  $template_settings = new ilSettingsTemplate($template_settings);
4944  $template_settings = $template_settings->getSettings();
4945  $template_settings = $template_settings["use_pool"];
4946  if ($template_settings && $template_settings["hide"]) {
4947  $use_pool = (bool) $template_settings["value"];
4948  }
4949  }
4950  return $use_pool;
4951  }
4952 
4959  {
4960  if (!$template_id) {
4961  return;
4962  }
4963 
4964  include_once "Services/Administration/classes/class.ilSettingsTemplate.php";
4966  $template_settings = $template->getSettings();
4967  //ilUtil::dumpVar($template_settings); exit;
4968  if ($template_settings) {
4969  if ($template_settings["show_question_titles"] !== null) {
4970  if ($template_settings["show_question_titles"]["value"]) {
4971  $this->setShowQuestionTitles(true);
4972  } else {
4973  $this->setShowQuestionTitles(false);
4974  }
4975  }
4976 
4977  if ($template_settings["use_pool"] !== null) {
4978  if ($template_settings["use_pool"]["value"]) {
4979  $this->setPoolUsage(true);
4980  } else {
4981  $this->setPoolUsage(false);
4982  }
4983  }
4984 
4985 
4986  /* see #0021719
4987  if($template_settings["anonymization_options"]["value"])
4988  {
4989  $anon_map = array('personalized' => self::ANONYMIZE_OFF,
4990  'anonymize_with_code' => self::ANONYMIZE_ON,
4991  'anonymize_without_code' => self::ANONYMIZE_FREEACCESS);
4992  $this->setAnonymize($anon_map[$template_settings["anonymization_options"]["value"]]);
4993  }*/
4994 
4995  // see #0021719 and ilObjectSurveyGUI::savePropertiesObject
4996  $this->setEvaluationAccess($template_settings["evaluation_access"]["value"]);
4997  $codes = (bool) $template_settings["acc_codes"]["value"];
4998  $anon = (bool) $template_settings["anonymization_options"]["value"];
4999  if (!$anon) {
5000  if (!$codes) {
5002  } else {
5004  }
5005  } else {
5006  if ($codes) {
5008  } else {
5010  }
5011 
5012  $this->setAnonymousUserList($_POST["anon_list"]);
5013  }
5014 
5015 
5016 
5017  /* other settings: not needed here
5018  * - enabled_end_date
5019  * - enabled_start_date
5020  * - rte_switch
5021  */
5022  }
5023 
5024  $this->setTemplate($template_id);
5025  $this->saveToDb();
5026  }
5027 
5028  public function updateCode($a_id, $a_email, $a_last_name, $a_first_name, $a_sent)
5029  {
5030  $ilDB = $this->db;
5031 
5032  $a_email = trim($a_email);
5033 
5034  // :TODO:
5035  if (($a_email && !ilUtil::is_email($a_email)) || $a_email == "") {
5036  return false;
5037  }
5038 
5039  $data = array("email" => $a_email,
5040  "lastname" => trim($a_last_name),
5041  "firstname" => trim($a_first_name));
5042 
5043  $fields = array(
5044  "externaldata" => array("text", serialize($data)),
5045  "sent" => array("integer", $a_sent)
5046  );
5047 
5048  $ilDB->update(
5049  "svy_anonymous",
5050  $fields,
5051  array("anonymous_id" => array("integer", $a_id))
5052  );
5053 
5054  return true;
5055  }
5056 
5057 
5058  //
5059  // 360°
5060  //
5061 
5062  public function get360Mode()
5063  {
5064  if ($this->getMode() == ilObjSurvey::MODE_360) {
5065  return true;
5066  }
5067  return false;
5068  }
5069 
5070  public function set360SelfEvaluation($a_value)
5071  {
5072  $this->mode_360_self_eval = (bool) $a_value;
5073  }
5074 
5075  public function get360SelfEvaluation()
5076  {
5077  return (bool) $this->mode_360_self_eval;
5078  }
5079 
5080  public function set360SelfAppraisee($a_value)
5081  {
5082  $this->mode_360_self_appr = (bool) $a_value;
5083  }
5084 
5085  public function get360SelfAppraisee()
5086  {
5087  return (bool) $this->mode_360_self_appr;
5088  }
5089 
5090  public function set360SelfRaters($a_value)
5091  {
5092  $this->mode_360_self_rate = (bool) $a_value;
5093  }
5094 
5095  public function get360SelfRaters()
5096  {
5097  return (bool) $this->mode_360_self_rate;
5098  }
5099 
5100  public function set360Results($a_value)
5101  {
5102  $this->mode_360_results = (int) $a_value;
5103  }
5104 
5105  public function get360Results()
5106  {
5107  return (int) $this->mode_360_results;
5108  }
5109 
5110  public function addAppraisee($a_user_id)
5111  {
5112  global $DIC;
5113 
5114  $ilDB = $DIC->database();
5115  $access = $DIC->access();
5116 
5117  if (!$this->isAppraisee($a_user_id) &&
5118  $a_user_id != ANONYMOUS_USER_ID) {
5119  $fields = array(
5120  "obj_id" => array("integer", $this->getSurveyId()),
5121  "user_id" => array("integer", $a_user_id)
5122  );
5123  $ilDB->insert("svy_360_appr", $fields);
5124 
5125  // send notification and add to desktop
5126  if ($access->checkAccessOfUser($a_user_id, "read", "", $this->getRefId())) {
5127  $this->sendAppraiseeNotification($a_user_id);
5128  $type = ilObject::_lookupType($this->getRefId(), true);
5129  ilObjUser::_addDesktopItem($a_user_id, $this->getRefId(), $type);
5130  }
5131  }
5132  }
5133 
5139  public function sendAppraiseeNotification($a_user_id)
5140  {
5141  include_once "./Services/Notification/classes/class.ilSystemNotification.php";
5142  $ntf = new ilSystemNotification();
5143  $ntf->setLangModules(array("svy", "survey"));
5144  $ntf->setRefId($this->getRefId());
5145  $ntf->setGotoLangId('url');
5146 
5147  // user specific language
5148  $lng = $ntf->getUserLanguage($a_user_id);
5149 
5150  $ntf->setIntroductionLangId("svy_user_added_360_appraisee_mail");
5151  $subject = str_replace("%1", $this->getTitle(), $lng->txt("svy_user_added_360_appraisee"));
5152 
5153  // #10044
5154  $mail = new ilMail(ANONYMOUS_USER_ID);
5155  //$mail->enableSOAP(false); // #10410
5156  $mail->sendMail(
5157  ilObjUser::_lookupLogin($a_user_id),
5158  null,
5159  null,
5160  $subject,
5161  $ntf->composeAndGetMessage($a_user_id, null, "read", true),
5162  null,
5163  array("system")
5164  );
5165  }
5166 
5172  public function sendAppraiseeCloseNotification($a_user_id)
5173  {
5174  include_once "./Services/Notification/classes/class.ilSystemNotification.php";
5175  $ntf = new ilSystemNotification();
5176  $ntf->setLangModules(array("svy", "survey"));
5177  $ntf->setRefId($this->getRefId());
5178  $ntf->setGotoLangId('url');
5179 
5180  // user specific language
5181  $lng = $ntf->getUserLanguage($a_user_id);
5182 
5183  $ntf->setIntroductionLangId("svy_user_added_360_appraisee_close_mail");
5184  $subject = str_replace("%1", $this->getTitle(), $lng->txt("svy_user_added_360_appraisee"));
5185 
5186  // #10044
5187  $mail = new ilMail(ANONYMOUS_USER_ID);
5188  //$mail->enableSOAP(false); // #10410
5189  $mail->sendMail(
5190  ilObjUser::_lookupLogin($a_user_id),
5191  null,
5192  null,
5193  $subject,
5194  $ntf->composeAndGetMessage($a_user_id, null, "read", true),
5195  null,
5196  array("system")
5197  );
5198  }
5199 
5205  public function sendRaterNotification($a_user_id, $a_appraisee_id)
5206  {
5207  include_once "./Services/Notification/classes/class.ilSystemNotification.php";
5208  $ntf = new ilSystemNotification();
5209  $ntf->setLangModules(array("svy", "survey"));
5210  $ntf->setRefId($this->getRefId());
5211  $ntf->setGotoLangId('url');
5212 
5213  // user specific language
5214  $lng = $ntf->getUserLanguage($a_user_id);
5215 
5216  $ntf->setIntroductionLangId("svy_user_added_360_rater_mail");
5217  $subject = str_replace("%1", $this->getTitle(), $lng->txt("svy_user_added_360_rater"));
5218  $ntf->addAdditionalInfo("survey_360_appraisee", ilUserUtil::getNamePresentation($a_appraisee_id, false, false, "", true));
5219 
5220  // #10044
5221  $mail = new ilMail(ANONYMOUS_USER_ID);
5222  //$mail->enableSOAP(false); // #10410
5223  $mail->sendMail(
5224  ilObjUser::_lookupLogin($a_user_id),
5225  null,
5226  null,
5227  $subject,
5228  $ntf->composeAndGetMessage($a_user_id, null, "read", true),
5229  null,
5230  array("system")
5231  );
5232  }
5233 
5234  public function isAppraisee($a_user_id)
5235  {
5236  $ilDB = $this->db;
5237 
5238  $set = $ilDB->query("SELECT user_id" .
5239  " FROM svy_360_appr" .
5240  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5241  " AND user_id = " . $ilDB->quote($a_user_id, "integer"));
5242  return (bool) $ilDB->numRows($set);
5243  }
5244 
5245  public function isAppraiseeClosed($a_user_id)
5246  {
5247  $ilDB = $this->db;
5248 
5249  $set = $ilDB->query("SELECT has_closed" .
5250  " FROM svy_360_appr" .
5251  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5252  " AND user_id = " . $ilDB->quote($a_user_id, "integer"));
5253  $row = $ilDB->fetchAssoc($set);
5254  return $row["has_closed"];
5255  }
5256 
5257  public function deleteAppraisee($a_user_id)
5258  {
5259  $ilDB = $this->db;
5260 
5261  $ilDB->manipulate("DELETE FROM svy_360_appr" .
5262  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5263  " AND user_id = " . $ilDB->quote($a_user_id, "integer"));
5264 
5265  $set = $ilDB->query("SELECT user_id" .
5266  " FROM svy_360_rater" .
5267  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5268  " AND appr_id = " . $ilDB->quote($a_user_id, "integer"));
5269  while ($row = $ilDB->fetchAssoc($set)) {
5270  $this->deleteRater($a_user_id, $row["user_id"]);
5271  }
5272  // appraisee will not be part of raters table
5273  if ($this->get360SelfEvaluation()) {
5274  $this->deleteRater($a_user_id, $a_user_id);
5275  }
5276  }
5277 
5278  public function getAppraiseesData()
5279  {
5280  $ilDB = $this->db;
5281 
5282  $res = array();
5283 
5284  $set = $ilDB->query("SELECT * FROM svy_360_appr" .
5285  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer"));
5286  while ($row = $ilDB->fetchAssoc($set)) {
5287  $name = ilObjUser::_lookupName($row["user_id"]);
5288  $name["email"] = ilObjUser::_lookupEmail($row["user_id"]);
5289  $name["name"] = $name["lastname"] . ", " . $name["firstname"];
5290  $res[$row["user_id"]] = $name;
5291 
5292  $finished = 0;
5293  $raters = $this->getRatersData($row["user_id"]);
5294  foreach ($raters as $rater) {
5295  if ($rater["finished"]) {
5296  $finished++;
5297  }
5298  }
5299  $res[$row["user_id"]]["finished"] = $finished . "/" . sizeof($raters);
5300  $res[$row["user_id"]]["closed"] = $row["has_closed"];
5301  }
5302 
5303  return $res;
5304  }
5305 
5306  public function addRater($a_appraisee_id, $a_user_id, $a_anonymous_id = 0)
5307  {
5308  global $DIC;
5309 
5310  $ilDB = $DIC->database();
5311  $access = $DIC->access();
5312 
5313  if ($this->isAppraisee($a_appraisee_id) &&
5314  !$this->isRater($a_appraisee_id, $a_user_id, $a_anonymous_id)) {
5315  $fields = array(
5316  "obj_id" => array("integer", $this->getSurveyId()),
5317  "appr_id" => array("integer", $a_appraisee_id),
5318  "user_id" => array("integer", $a_user_id),
5319  "anonymous_id" => array("integer", $a_anonymous_id)
5320  );
5321  $ilDB->insert("svy_360_rater", $fields);
5322 
5323  // send notification and add to desktop
5324  if ($access->checkAccessOfUser($a_user_id, "read", "", $this->getRefId())) {
5325  $this->sendRaterNotification($a_user_id, $a_appraisee_id);
5326  $type = ilObject::_lookupType($this->getRefId(), true);
5327  ilObjUser::_addDesktopItem($a_user_id, $this->getRefId(), $type);
5328  }
5329  }
5330  }
5331 
5332  public function isRater($a_appraisee_id, $a_user_id, $a_anonymous_id = 0)
5333  {
5334  $ilDB = $this->db;
5335 
5336  // user is rater if already appraisee and active self-evaluation
5337  if ($this->isAppraisee($a_user_id) &&
5338  $this->get360SelfEvaluation() &&
5339  (!$a_appraisee_id || $a_appraisee_id == $a_user_id)) {
5340  return true;
5341  }
5342 
5343  // :TODO: should we get rid of code as well?
5344 
5345  $sql = "SELECT user_id" .
5346  " FROM svy_360_rater" .
5347  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5348  " AND user_id = " . $ilDB->quote($a_user_id, "integer") .
5349  " AND anonymous_id = " . $ilDB->quote($a_anonymous_id, "integer");
5350  if ($a_appraisee_id) {
5351  $sql .= " AND appr_id = " . $ilDB->quote($a_appraisee_id, "integer");
5352  }
5353  $set = $ilDB->query($sql);
5354  return (bool) $ilDB->numRows($set);
5355  }
5356 
5357  public function deleteRater($a_appraisee_id, $a_user_id, $a_anonymous_id = 0)
5358  {
5359  $ilDB = $this->db;
5360 
5361  $finished_id = $this->getFinishedIdForAppraiseeIdAndRaterId($a_appraisee_id, $a_user_id);
5362  if ($finished_id) {
5363  $this->removeSelectedSurveyResults(array($finished_id));
5364  }
5365 
5366  $ilDB->manipulate("DELETE FROM svy_360_rater" .
5367  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5368  " AND appr_id = " . $ilDB->quote($a_appraisee_id, "integer") .
5369  " AND user_id = " . $ilDB->quote($a_user_id, "integer") .
5370  " AND anonymous_id = " . $ilDB->quote($a_anonymous_id, "integer"));
5371  }
5372 
5373  public function getRatersData($a_appraisee_id)
5374  {
5375  $ilDB = $this->db;
5376 
5377  $res = $anonymous_ids = array();
5378 
5379  $set = $ilDB->query("SELECT * FROM svy_360_rater" .
5380  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5381  " AND appr_id = " . $ilDB->quote($a_appraisee_id, "integer"));
5382  while ($row = $ilDB->fetchAssoc($set)) {
5383  if ($row["anonymous_id"]) {
5384  $res["a" . $row["anonymous_id"]] = array(
5385  "lastname" => "unknown code " . $row["anonymous_id"],
5386  "sent" => $row["mail_sent"],
5387  "finished" => null
5388  );
5389  $anonymous_ids[] = $row["anonymous_id"];
5390  } else {
5391  $name = ilObjUser::_lookupName($row["user_id"]);
5392  $name["name"] = $name["lastname"] . ", " . $name["firstname"];
5393  $name["user_id"] = "u" . $name["user_id"];
5394  $name["email"] = ilObjUser::_lookupEmail($row["user_id"]);
5395  $name["sent"] = $row["mail_sent"];
5396  $name["finished"] = (bool) $this->is360SurveyStarted($a_appraisee_id, $row["user_id"]);
5397  $res["u" . $row["user_id"]] = $name;
5398  }
5399  }
5400 
5401  if (sizeof($anonymous_ids)) {
5402  $data = $this->getSurveyCodesTableData($anonymous_ids);
5403  foreach ($data as $item) {
5404  if (isset($res["a" . $item["id"]])) {
5405  $res["a" . $item["id"]] = array(
5406  "user_id" => "a" . $item["id"],
5407  "lastname" => $item["last_name"],
5408  "firstname" => $item["first_name"],
5409  "name" => $item["last_name"] . ", " . $item["first_name"],
5410  "login" => "",
5411  "email" => $item["email"],
5412  "code" => $item["code"],
5413  "href" => $item["href"],
5414  "sent" => $res["a" . $item["id"]]["sent"],
5415  "finished" => (bool) $this->is360SurveyStarted($a_appraisee_id, null, $item["code"])
5416  );
5417  }
5418  }
5419  }
5420 
5421  return $res;
5422  }
5423 
5424  public function getAppraiseesToRate($a_user_id, $a_anonymous_id = null)
5425  {
5426  $ilDB = $this->db;
5427 
5428  $res = array();
5429 
5430  $sql = "SELECT appr_id FROM svy_360_rater" .
5431  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer");
5432 
5433  if ($a_user_id) {
5434  $sql .= " AND user_id = " . $ilDB->quote($a_user_id, "integer");
5435  } else {
5436  $sql .= " AND anonymous_id = " . $ilDB->quote($a_anonymous_id, "integer");
5437  }
5438 
5439  $set = $ilDB->query($sql);
5440  while ($row = $ilDB->fetchAssoc($set)) {
5441  $res[] = $row["appr_id"];
5442  }
5443 
5444  // user may evaluate himself if already appraisee
5445  if ($this->get360SelfEvaluation() &&
5446  $this->isAppraisee($a_user_id) &&
5447  !in_array($a_user_id, $res)) {
5448  $res[] = $a_user_id;
5449  }
5450 
5451  return $res;
5452  }
5453 
5454  public function getAnonymousIdByCode($a_code)
5455  {
5456  $ilDB = $this->db;
5457 
5458  $set = $ilDB->query("SELECT anonymous_id FROM svy_anonymous" .
5459  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
5460  " AND survey_key = " . $ilDB->quote($a_code, "text"));
5461  $res = $ilDB->fetchAssoc($set);
5462  return $res["anonymous_id"];
5463  }
5464 
5465  public function is360SurveyStarted($appr_id, $user_id, $anonymous_code = null)
5466  {
5467  $ilDB = $this->db;
5468 
5469  $sql = "SELECT * FROM svy_finished" .
5470  " WHERE survey_fi =" . $ilDB->quote($this->getSurveyId(), "integer") .
5471  " AND appr_id = " . $ilDB->quote($appr_id, "integer");
5472  if ($user_id) {
5473  $sql .= " AND user_fi = " . $ilDB->quote($user_id, "integer");
5474  } else {
5475  $sql .= " AND anonymous_id = " . $ilDB->quote($anonymous_code, "text");
5476  }
5477  $result = $ilDB->query($sql);
5478  if ($result->numRows() == 0) {
5479  return false;
5480  } else {
5481  $row = $ilDB->fetchAssoc($result);
5482  return (int) $row["state"];
5483  }
5484  }
5485 
5486  public function getUserSurveyExecutionStatus($a_code = null)
5487  {
5488  $ilUser = $this->user;
5489  $ilDB = $this->db;
5490 
5491  $user_id = $ilUser->getId();
5492 
5493  // code is obligatory?
5494  if (!$this->isAccessibleWithoutCode()) {
5495  if (!$a_code) {
5496  // registered raters do not need code
5497  if ($this->get360Mode() &&
5498  $user_id != ANONYMOUS_USER_ID &&
5499  $this->isRater(0, $user_id)) {
5500  // auto-generate code
5501  $a_code = $this->createNewAccessCode();
5502  $this->saveUserAccessCode($user_id, $a_code);
5503  } else {
5504  return null;
5505  }
5506  }
5507  } elseif ($user_id == ANONYMOUS_USER_ID ||
5508  $this->getAnonymize() == self::ANONYMIZE_FREEACCESS) {
5509  if (!$a_code) {
5510  // auto-generate code
5511  $a_code = $this->createNewAccessCode();
5512  $this->saveUserAccessCode($user_id, $a_code);
5513  }
5514  } else {
5515  $a_code = null;
5516  }
5517 
5518  $res = array();
5519 
5520  $sql = "SELECT * FROM svy_finished" .
5521  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer");
5522  // if proper user id is given, use it or current code
5523  if ($user_id != ANONYMOUS_USER_ID) {
5524  $sql .= " AND (user_fi = " . $ilDB->quote($user_id, "integer") .
5525  " OR anonymous_id = " . $ilDB->quote($a_code, "text") . ")";
5526  }
5527  // use anonymous code to find finished id(s)
5528  else {
5529  $sql .= " AND anonymous_id = " . $ilDB->quote($a_code, "text");
5530  }
5531  $set = $ilDB->query($sql);
5532  while ($row = $ilDB->fetchAssoc($set)) {
5533  $res[$row["finished_id"]] = array("appr_id" => $row["appr_id"],
5534  "user_id" => $row["user_fi"],
5535  "code" => $row["anonymous_id"],
5536  "finished" => (bool) $row["state"]);
5537  }
5538 
5539  return array("code" => $a_code, "runs" => $res);
5540  }
5541 
5542  public function findCodeForUser($a_user_id)
5543  {
5544  $ilDB = $this->db;
5545 
5546  if ($a_user_id != ANONYMOUS_USER_ID) {
5547  $set = $ilDB->query("SELECT sf.anonymous_id FROM svy_finished sf" .
5548  " WHERE sf.survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
5549  " AND sf.user_fi = " . $ilDB->quote($a_user_id, "integer"));
5550  $a_code = $ilDB->fetchAssoc($set);
5551  return $a_code["anonymous_id"];
5552  }
5553  }
5554 
5555  public function isUnusedCode($a_code, $a_user_id)
5556  {
5557  $ilDB = $this->db;
5558 
5559  $set = $ilDB->query("SELECT user_fi FROM svy_finished" .
5560  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
5561  " AND anonymous_id = " . $ilDB->quote($a_code, "text"));
5562  $user_id = $ilDB->fetchAssoc($set);
5563  $user_id = $user_id["user_fi"];
5564 
5565  if ($user_id && ($user_id != $a_user_id || $user_id == ANONYMOUS_USER_ID)) {
5566  return false;
5567  }
5568  return true;
5569  }
5570 
5571  public function getFinishedIdsForAppraiseeId($a_appr_id, $a_exclude_appraisee = false)
5572  {
5573  $ilDB = $this->db;
5574 
5575  $res = array();
5576 
5577  $set = $ilDB->query("SELECT finished_id, user_fi FROM svy_finished" .
5578  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
5579  " AND appr_id = " . $ilDB->quote($a_appr_id, "integer"));
5580  while ($row = $ilDB->fetchAssoc($set)) {
5581  if ($a_exclude_appraisee && $row["user_fi"] == $a_appr_id) {
5582  continue;
5583  }
5584  $res[] = $row["finished_id"];
5585  }
5586 
5587  return $res;
5588  }
5589 
5597  public function getFinishedIdForAppraiseeIdAndRaterId($a_appr_id, $a_rat_id)
5598  {
5599  $ilDB = $this->db;
5600 
5601  $set = $ilDB->query("SELECT finished_id, user_fi FROM svy_finished" .
5602  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
5603  " AND appr_id = " . $ilDB->quote($a_appr_id, "integer") .
5604  " AND user_fi = " . $ilDB->quote($a_rat_id, "integer"));
5605  $row = $ilDB->fetchAssoc($set);
5606  return $row["finished_id"];
5607  }
5608 
5609 
5610  // 360° using competence/skill service
5611 
5617  public function setSkillService($a_val)
5618  {
5619  $this->mode_skill_service = $a_val;
5620  }
5621 
5627  public function getSkillService()
5628  {
5630  }
5631 
5632  public function set360RaterSent($a_appraisee_id, $a_user_id, $a_anonymous_id, $a_tstamp = null)
5633  {
5634  $ilDB = $this->db;
5635 
5636  if (!$a_tstamp) {
5637  $a_tstamp = time();
5638  }
5639 
5640  $ilDB->manipulate("UPDATE svy_360_rater" .
5641  " SET mail_sent = " . $ilDB->quote($a_tstamp, "integer") .
5642  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5643  " AND appr_id = " . $ilDB->quote($a_appraisee_id, "integer") .
5644  " AND user_id = " . $ilDB->quote($a_user_id, "integer") .
5645  " AND anonymous_id = " . $ilDB->quote($a_anonymous_id, "integer"));
5646  }
5647 
5648  public function closeAppraisee($a_user_id)
5649  {
5650  global $DIC;
5651 
5652  $ilDB = $DIC->database();
5653  $user = $DIC->user();
5654 
5655  // close the appraisee
5656  $ilDB->manipulate("UPDATE svy_360_appr" .
5657  " SET has_closed = " . $ilDB->quote(time(), "integer") .
5658  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5659  " AND user_id = " . $ilDB->quote($a_user_id, "integer"));
5660 
5661  // write competences
5662  include_once("./Services/Skill/classes/class.ilSkillManagementSettings.php");
5663  $skmg_set = new ilSkillManagementSettings();
5664  if ($this->getSkillService() && $skmg_set->isActivated()) {
5665  include_once("./Modules/Survey/classes/class.ilSurveySkill.php");
5666  $sskill = new ilSurveySkill($this);
5667  $sskill->writeAppraiseeSkills($a_user_id);
5668  }
5669 
5670  // send notification
5671  if ($user->getId() != $a_user_id) {
5672  $this->sendAppraiseeCloseNotification($a_user_id);
5673  }
5674  }
5675 
5676  public function openAllAppraisees()
5677  {
5678  $ilDB = $this->db;
5679 
5680  $ilDB->manipulate("UPDATE svy_360_appr" .
5681  " SET has_closed = " . $ilDB->quote(null, "integer") .
5682  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer"));
5683  }
5684 
5685  public static function validateExternalRaterCode($a_ref_id, $a_code)
5686  {
5687  if (!isset($_SESSION["360_extrtr"][$a_ref_id])) {
5688  $svy = new self($a_ref_id);
5689  $svy->loadFromDB();
5690 
5691  if ($svy->canStartSurvey(null, true) &&
5692  $svy->get360Mode() &&
5693  $svy->isAnonymousKey($a_code)) {
5694  $anonymous_id = $svy->getAnonymousIdByCode($a_code);
5695  if ($anonymous_id) {
5696  if (sizeof($svy->getAppraiseesToRate(null, $anonymous_id))) {
5697  $_SESSION["360_extrtr"][$a_ref_id] = true;
5698  return true;
5699  }
5700  }
5701  }
5702 
5703  $_SESSION["360_extrtr"][$a_ref_id] = false;
5704  return false;
5705  }
5706 
5707  return $_SESSION["360_extrtr"][$a_ref_id];
5708  }
5709 
5710 
5711  //
5712  // reminder/notification
5713  //
5714 
5715  public function getReminderStatus()
5716  {
5717  return (bool) $this->reminder_status;
5718  }
5719 
5720  public function setReminderStatus($a_value)
5721  {
5722  $this->reminder_status = (bool) $a_value;
5723  }
5724 
5725  public function getReminderStart()
5726  {
5727  return $this->reminder_start;
5728  }
5729 
5730  public function setReminderStart(ilDate $a_value = null)
5731  {
5732  $this->reminder_start = $a_value;
5733  }
5734 
5735  public function getReminderEnd()
5736  {
5737  return $this->reminder_end;
5738  }
5739 
5740  public function setReminderEnd(ilDate $a_value = null)
5741  {
5742  $this->reminder_end = $a_value;
5743  }
5744 
5745  public function getReminderFrequency()
5746  {
5748  }
5749 
5750  public function setReminderFrequency($a_value)
5751  {
5752  $this->reminder_frequency = (int) $a_value;
5753  }
5754 
5755  public function getReminderTarget()
5756  {
5757  return $this->reminder_target;
5758  }
5759 
5760  public function setReminderTarget($a_value)
5761  {
5762  $this->reminder_target = (int) $a_value;
5763  }
5764 
5765  public function getReminderLastSent()
5766  {
5768  }
5769 
5770  public function setReminderLastSent($a_value)
5771  {
5772  $this->reminder_last_sent = $a_value;
5773  }
5774 
5779  public function getReminderTemplate($selectDefault = false)
5780  {
5781  if ($selectDefault) {
5782  $defaultTemplateId = 0;
5783  $this->getReminderMailTemplates($defaultTemplateId);
5784 
5785  if ($defaultTemplateId > 0) {
5786  return $defaultTemplateId;
5787  }
5788  }
5789 
5790  return $this->reminder_tmpl;
5791  }
5792 
5793  public function setReminderTemplate($a_value)
5794  {
5795  $this->reminder_tmpl = $a_value;
5796  }
5797 
5798  public function getTutorNotificationStatus()
5799  {
5800  return (bool) $this->tutor_ntf_status;
5801  }
5802 
5803  public function setTutorNotificationStatus($a_value)
5804  {
5805  $this->tutor_ntf_status = (bool) $a_value;
5806  }
5807 
5809  {
5811  }
5812 
5813  public function setTutorNotificationRecipients(array $a_value)
5814  {
5815  $this->tutor_ntf_recipients = $a_value;
5816  }
5817 
5818  public function getTutorNotificationTarget()
5819  {
5820  return $this->tutor_ntf_target;
5821  }
5822 
5823  public function setTutorNotificationTarget($a_value)
5824  {
5825  $this->tutor_ntf_target = (int) $a_value;
5826  }
5827 
5828  protected function checkTutorNotification()
5829  {
5830  $ilDB = $this->db;
5831 
5832  if ($this->getTutorNotificationStatus()) {
5833  $user_ids = $this->getNotificationTargetUserIds(($this->getTutorNotificationTarget() == self::NOTIFICATION_INVITED_USERS));
5834  if ($user_ids) {
5835  $set = $ilDB->query("SELECT COUNT(*) numall FROM svy_finished" .
5836  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
5837  " AND state = " . $ilDB->quote(1, "integer") .
5838  " AND " . $ilDB->in("user_fi", $user_ids, "", "integer"));
5839  $row = $ilDB->fetchAssoc($set);
5840  if ($row["numall"] == sizeof($user_ids)) {
5841  $this->sendTutorNotification();
5842  }
5843  }
5844  }
5845  }
5846 
5853  public function sent360Reminders()
5854  {
5855  global $DIC;
5856 
5857  $access = $DIC->access();
5858 
5859  // collect all open ratings
5860  $rater_ids = array();
5861  foreach ($this->getAppraiseesData() as $app) {
5862  $this->log->debug("Handle appraisee " . $app['user_id']);
5863 
5864  if (!$this->isAppraiseeClosed($app['user_id'])) {
5865  $this->log->debug("Check self evaluation, self: " . $this->get360SelfAppraisee() . ", target: " . $this->getReminderTarget());
5866 
5867  // self evaluation?
5868  if ($this->get360SelfEvaluation() &&
5870  $this->log->debug("...1");
5871  // did user already finished self evaluation?
5872  if (!$this->is360SurveyStarted($app['user_id'], $app['user_id'])) {
5873  $this->log->debug("...2");
5874  if (!is_array($rater_ids[$app['user_id']])) {
5875  $rater_ids[$app['user_id']] = array();
5876  }
5877  if (!in_array($app["user_id"], $rater_ids[$app['user_id']])) {
5878  $rater_ids[$app['user_id']][] = $app["user_id"];
5879  }
5880  }
5881  }
5882 
5883  $this->log->debug("Check raters.");
5884 
5885  // should raters be notified?
5887  foreach ($this->getRatersData($app['user_id']) as $rater) {
5888  // is rater not anonymous and did not rate yet?
5889  if (!$rater["anonymous_id"] && !$rater["finished"]) {
5890  if (!is_array($rater_ids[$rater["user_id"]])) {
5891  $rater_ids[$rater["user_id"]] = array();
5892  }
5893  if (!in_array($app["user_id"], $rater_ids[$rater["user_id"]])) {
5894  $rater_ids[$rater["user_id"]][] = $app["user_id"];
5895  }
5896  }
5897  }
5898  }
5899  }
5900  }
5901 
5902  $this->log->debug("Found raters:" . count($rater_ids));
5903 
5904  foreach ($rater_ids as $id => $app) {
5905  if ($access->checkAccessOfUser($id, "read", "", $this->getRefId())) {
5906  $this->send360ReminderToUser($id, $app);
5907  }
5908  }
5909  }
5910 
5916  public function send360ReminderToUser($a_user_id, $a_appraisee_ids)
5917  {
5918  $this->log->debug("Send mail to:" . $a_user_id);
5919 
5920  include_once "./Services/Notification/classes/class.ilSystemNotification.php";
5921  $ntf = new ilSystemNotification();
5922  $ntf->setLangModules(array("svy", "survey"));
5923  $ntf->setRefId($this->getRefId());
5924  $ntf->setGotoLangId('url');
5925 
5926  // user specific language
5927  $lng = $ntf->getUserLanguage($a_user_id);
5928 
5929  $ntf->setIntroductionLangId("svy_user_added_360_rater_reminder_mail");
5930  $subject = str_replace("%1", $this->getTitle(), $lng->txt("svy_user_added_360_rater"));
5931 
5932  foreach ($a_appraisee_ids as $appraisee_id) {
5933  $ntf->addAdditionalInfo("survey_360_appraisee", ilUserUtil::getNamePresentation($appraisee_id, false, false, "", true));
5934  }
5935 
5936  // #10044
5937  $mail = new ilMail(ANONYMOUS_USER_ID);
5938  $mail->enableSOAP(false); // #10410
5939  $mail->sendMail(
5940  ilObjUser::_lookupLogin($a_user_id),
5941  null,
5942  null,
5943  $subject,
5944  $ntf->composeAndGetMessage($a_user_id, null, "read", true),
5945  null,
5946  array("system")
5947  );
5948  }
5949 
5950 
5951  public function getNotificationTargetUserIds($a_use_invited)
5952  {
5953  $tree = $this->tree;
5954 
5955  if ((bool) $a_use_invited) {
5956  $user_ids = $this->getInvitedUsers();
5957  } else {
5958  $parent_grp_ref_id = $tree->checkForParentType($this->getRefId(), "grp");
5959  if ($parent_grp_ref_id) {
5960  include_once "Modules/Group/classes/class.ilGroupParticipants.php";
5961  $part = new ilGroupParticipants(ilObject::_lookupObjId($parent_grp_ref_id));
5962  $user_ids = $part->getMembers();
5963  } else {
5964  $parent_crs_ref_id = $tree->checkForParentType($this->getRefId(), "crs");
5965  if ($parent_crs_ref_id) {
5966  include_once "Modules/Course/classes/class.ilCourseParticipants.php";
5967  $part = new ilCourseParticipants(ilObject::_lookupObjId($parent_crs_ref_id));
5968  $user_ids = $part->getMembers();
5969  }
5970  }
5971  }
5972  return $user_ids;
5973  }
5974 
5975  protected function sendTutorNotification()
5976  {
5977  include_once "./Services/Mail/classes/class.ilMail.php";
5978  include_once "./Services/User/classes/class.ilObjUser.php";
5979  include_once "./Services/Language/classes/class.ilLanguageFactory.php";
5980  include_once "./Services/User/classes/class.ilUserUtil.php";
5981  include_once "./Services/Link/classes/class.ilLink.php";
5982  $link = ilLink::_getStaticLink($this->getRefId(), "svy");
5983 
5984  foreach ($this->getTutorNotificationRecipients() as $user_id) {
5985  // use language of recipient to compose message
5986  $ulng = ilLanguageFactory::_getLanguageOfUser($user_id);
5987  $ulng->loadLanguageModule('survey');
5988 
5989  $subject = sprintf($ulng->txt('survey_notification_tutor_subject'), $this->getTitle());
5990  $message = sprintf($ulng->txt('survey_notification_tutor_salutation'), ilObjUser::_lookupFullname($user_id)) . "\n\n";
5991 
5992  $message .= $ulng->txt('survey_notification_tutor_body') . ":\n\n";
5993  $message .= $ulng->txt('obj_svy') . ": " . $this->getTitle() . "\n";
5994  $message .= "\n" . $ulng->txt('survey_notification_tutor_link') . ": " . $link;
5995 
5996  $mail_obj = new ilMail(ANONYMOUS_USER_ID);
5997  $mail_obj->appendInstallationSignature(true);
5998  $mail_obj->sendMail(
5999  ilObjUser::_lookupLogin($user_id),
6000  "",
6001  "",
6002  $subject,
6003  $message,
6004  array(),
6005  array("system")
6006  );
6007  }
6008  }
6009 
6010  public function checkReminder()
6011  {
6012  $ilDB = $this->db;
6013  $ilAccess = $this->access;
6014 
6015  $now = time();
6016  $now_with_format = date("YmdHis", $now);
6017  $today = date("Y-m-d");
6018 
6019  $this->log->debug("Check status and dates.");
6020 
6021  // object settings / participation period
6022  if (
6023  $this->getOfflineStatus() ||
6024  !$this->getReminderStatus() ||
6025  ($this->getStartDate() && $now_with_format < $this->getStartDate()) ||
6026  ($this->getEndDate() && $now_with_format > $this->getEndDate())) {
6027  return false;
6028  }
6029 
6030  // reminder period
6031  $start = $this->getReminderStart();
6032  if ($start) {
6033  $start = $start->get(IL_CAL_DATE);
6034  }
6035  $end = $this->getReminderEnd();
6036  if ($end) {
6037  $end = $end->get(IL_CAL_DATE);
6038  }
6039  if ($today < $start ||
6040  ($end && $today > $end)) {
6041  return false;
6042  }
6043 
6044  $this->log->debug("Check access period.");
6045 
6046  // object access period
6047  include_once "Services/Object/classes/class.ilObjectActivation.php";
6048  $item_data = ilObjectActivation::getItem($this->getRefId());
6049  if ($item_data["timing_type"] == ilObjectActivation::TIMINGS_ACTIVATION &&
6050  ($now < $item_data["timing_start"] ||
6051  $now > $item_data["timing_end"])) {
6052  return false;
6053  }
6054 
6055  $this->log->debug("Check frequency.");
6056 
6057  // check frequency
6058  $cut = new ilDate($today, IL_CAL_DATE);
6059  $cut->increment(IL_CAL_DAY, $this->getReminderFrequency() * -1);
6060  if (!$this->getReminderLastSent() ||
6061  $cut->get(IL_CAL_DATE) >= substr($this->getReminderLastSent(), 0, 10)) {
6062  $missing_ids = array();
6063 
6064  if (!$this->get360Mode()) {
6065  $this->log->debug("Entering survey mode.");
6066 
6067  // #16871
6068  $user_ids = $this->getNotificationTargetUserIds(($this->getReminderTarget() == self::NOTIFICATION_INVITED_USERS));
6069  if ($user_ids) {
6070  // gather participants who already finished
6071  $finished_ids = array();
6072  $set = $ilDB->query("SELECT user_fi FROM svy_finished" .
6073  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
6074  " AND state = " . $ilDB->quote(1, "text") .
6075  " AND " . $ilDB->in("user_fi", $user_ids, "", "integer"));
6076  while ($row = $ilDB->fetchAssoc($set)) {
6077  $finished_ids[] = $row["user_fi"];
6078  }
6079 
6080  // some users missing out?
6081  $missing_ids = array_diff($user_ids, $finished_ids);
6082  if ($missing_ids) {
6083  foreach ($missing_ids as $idx => $user_id) {
6084  // should be able to participate
6085  if (!$ilAccess->checkAccessOfUser($user_id, "read", "", $this->getRefId(), "svy", $this->getId())) {
6086  unset($missing_ids[$idx]);
6087  }
6088  }
6089  }
6090  if ($missing_ids) {
6091  $this->sentReminder($missing_ids);
6092  }
6093  }
6094  } else {
6095  $this->log->debug("Entering 360 mode.");
6096 
6097  $this->sent360Reminders();
6098  }
6099 
6100 
6101  $this->setReminderLastSent($today);
6102  $this->saveToDb();
6103 
6104  return sizeof($missing_ids);
6105  }
6106 
6107  return false;
6108  }
6109 
6110  protected function sentReminder(array $a_recipient_ids)
6111  {
6112  global $DIC;
6113 
6114  // use mail template
6115  if ($this->getReminderTemplate() &&
6116  array_key_exists($this->getReminderTemplate(), $this->getReminderMailTemplates())) {
6118  $templateService = $DIC['mail.texttemplates.service'];
6119  $tmpl = $templateService->loadTemplateForId((int) $this->getReminderTemplate());
6120 
6121  $tmpl_params = array(
6122  "ref_id" => $this->getRefId(),
6123  "ts" => time()
6124  );
6125  } else {
6126  $tmpl = null;
6127 
6128  include_once "./Services/Link/classes/class.ilLink.php";
6129  $link = ilLink::_getStaticLink($this->getRefId(), "svy");
6130 
6131  include_once "./Services/Language/classes/class.ilLanguageFactory.php";
6132  }
6133 
6134  foreach ($a_recipient_ids as $user_id) {
6135  if ($tmpl) {
6136  $subject = $tmpl->getSubject();
6137  $message = $this->sentReminderPlaceholders($tmpl->getMessage(), $user_id, $tmpl_params);
6138  }
6139  // use lng
6140  else {
6141  // use language of recipient to compose message
6142  $ulng = ilLanguageFactory::_getLanguageOfUser($user_id);
6143  $ulng->loadLanguageModule('survey');
6144 
6145  $subject = sprintf($ulng->txt('survey_reminder_subject'), $this->getTitle());
6146  $message = sprintf($ulng->txt('survey_reminder_salutation'), ilObjUser::_lookupFullname($user_id)) . "\n\n";
6147 
6148  $message .= $ulng->txt('survey_reminder_body') . ":\n\n";
6149  $message .= $ulng->txt('obj_svy') . ": " . $this->getTitle() . "\n";
6150  $message .= "\n" . $ulng->txt('survey_reminder_link') . ": " . $link;
6151  }
6152 
6153  $mail_obj = new ilMail(ANONYMOUS_USER_ID);
6154  $mail_obj->appendInstallationSignature(true);
6155  $mail_obj->sendMail(
6156  ilObjUser::_lookupLogin($user_id),
6157  "",
6158  "",
6159  $subject,
6160  $message,
6161  array(),
6162  array("system")
6163  );
6164  }
6165  }
6166 
6167  public function setActivationStartDate($starting_time = null)
6168  {
6169  $this->activation_starting_time = $starting_time;
6170  }
6171 
6172  public function setActivationEndDate($ending_time = null)
6173  {
6174  $this->activation_ending_time = $ending_time;
6175  }
6176 
6177  public function getActivationStartDate()
6178  {
6179  return (strlen($this->activation_starting_time)) ? $this->activation_starting_time : null;
6180  }
6181 
6182  public function getActivationEndDate()
6183  {
6184  return (strlen($this->activation_ending_time)) ? $this->activation_ending_time : null;
6185  }
6186 
6187  public function setViewOwnResults($a_value)
6188  {
6189  $this->view_own_results = (bool) $a_value;
6190  }
6191 
6192  public function hasViewOwnResults()
6193  {
6194  return $this->view_own_results;
6195  }
6196 
6197  public function setMailOwnResults($a_value)
6198  {
6199  $this->mail_own_results = (bool) $a_value;
6200  }
6201 
6202  public function hasMailOwnResults()
6203  {
6204  return $this->mail_own_results;
6205  }
6206 
6207  public function setMailConfirmation($a_value)
6208  {
6209  $this->mail_confirmation = (bool) $a_value;
6210  }
6211 
6212  public function hasMailConfirmation()
6213  {
6214  return $this->mail_confirmation;
6215  }
6216 
6217  public function setAnonymousUserList($a_value)
6218  {
6219  $this->anon_user_list = (bool) $a_value;
6220  }
6221 
6222  public function hasAnonymousUserList()
6223  {
6224  return $this->anon_user_list;
6225  }
6226 
6227  public static function getSurveySkippedValue()
6228  {
6229  global $DIC;
6230 
6231  $lng = $DIC->language();
6232 
6233  // #13541
6234 
6235  include_once "./Services/Administration/classes/class.ilSetting.php";
6236  $surveySetting = new ilSetting("survey");
6237  if (!$surveySetting->get("skipped_is_custom", false)) {
6238  return $lng->txt("skipped");
6239  } else {
6240  return $surveySetting->get("skipped_custom_value", "");
6241  }
6242  }
6243 
6248  public function getReminderMailTemplates(&$defaultTemplateId = null)
6249  {
6250  global $DIC;
6251 
6252  $res = array();
6253 
6255  $templateService = $DIC['mail.texttemplates.service'];
6256  foreach ($templateService->loadTemplatesForContextId((string) ilSurveyMailTemplateReminderContext::ID) as $tmpl) {
6257  $res[$tmpl->getTplId()] = $tmpl->getTitle();
6258  if (null !== $defaultTemplateId && $tmpl->isDefault()) {
6259  $defaultTemplateId = $tmpl->getTplId();
6260  }
6261  }
6262 
6263  return $res;
6264  }
6265 
6266  protected function sentReminderPlaceholders($a_message, $a_user_id, array $a_context_params)
6267  {
6268  // see ilMail::replacePlaceholders()
6269  try {
6271 
6272  $user = new \ilObjUser($a_user_id);
6273 
6274  $processor = new \ilMailTemplatePlaceholderResolver($context, $a_message);
6275  $a_message = $processor->resolve($user, $a_context_params);
6276  } catch (\Exception $e) {
6277  ilLoggerFactory::getLogger('mail')->error(__METHOD__ . ' has been called with invalid context.');
6278  }
6279 
6280  return $a_message;
6281  }
6282 
6283  public function setMode($a_value)
6284  {
6285  $this->mode = $a_value;
6286  }
6287 
6288  public function getMode()
6289  {
6290  return $this->mode;
6291  }
6292 
6293  public function setSelfEvaluationResults($a_value)
6294  {
6295  $this->mode_self_eval_results = $a_value;
6296  }
6297 
6298  public function getSelfEvaluationResults()
6299  {
6301  }
6302 } // END class.ilObjSurvey
createSurveyCodes($nrOfCodes)
showQuestionTitles()
Sets the question titles visible during the query.
static _lookupLogin($a_user_id)
lookup login
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.
setInvitationAndMode($invitation=0, $invitation_mode=0)
Sets the invitation status and mode (a more performant solution if you change both) ...
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:25
$files
Definition: metarefresh.php:49
deleteRater($a_appraisee_id, $a_user_id, $a_anonymous_id=0)
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"]
$config
Definition: bootstrap.php:15
$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.
$template
& getSurveyFinishedIds()
Get the finished id&#39;s of all survey participants.
global $DIC
Definition: saml.php:7
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)
disinviteAllUsers()
Disinvite all users.
& getSurveyParticipants($finished_ids=null, $force_non_anonymous=false)
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"]
setTutorNotificationTarget($a_value)
$h
static getSurveySkippedValue()
static _lookupFullname($a_user_id)
Lookup Full Name.
deleteSurveyCode($survey_code)
Deletes a given survey access code.
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.
$code
Definition: example_050.php:99
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)
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.
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
$s
Definition: pwgen.php:45
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)
$index
Definition: metadata.php:60
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.
$metadata['__DYNAMIC:1__']
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.
const INVITATION_ON
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.
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.
$start
Definition: bench.php:8
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.
getInvitationMode()
Gets the invitation mode.
removeSelectedSurveyResults($finished_ids)
Deletes the user data of a given array of survey participants.
getEndDate()
Gets the end date of the survey.
$time
Definition: cron.php:21
$messages
Definition: en.php:5
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)
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
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.
catch(Exception $e) $message
setAnonymousUserList($a_value)
disinviteUser($user_id)
Disinvites a user from a survey.
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.
setInvitationMode($invitation_mode=0)
Sets the invitation mode.
inviteUser($user_id)
Invites a user to a survey.
getNextPage($active_page_question_id, $direction)
Returns the next "page" of a running test.
setReminderTemplate($a_value)
Class for single dates.
$y
Definition: example_007.php:83
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)
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)
setInvitation($invitation=0)
Sets the invitation status.
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)
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.
$text
Definition: errorreport.php:18
setMailOwnResults($a_value)
setReminderStart(ilDate $a_value=null)
setTutorNotificationRecipients(array $a_value)
setIntroduction($introduction="")
Sets the introduction text.
getTitle()
get object title public
static _dropDesktopItem($a_usr_id, $a_item_id, $a_type)
drop an item from user&#39;s personal desktop
getDescription()
get object description
const IL_COMP_MODULE
Date and time handling
$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.
& getInvitedUsers()
Returns a list of all invited users in a survey.
addConstraintToQuestion($to_question_id, $constraint_id)
Adds a constraint to a question.
importSurveyCode($a_anonymize_key, $a_created, $a_data)
Class ilObjMediaObject.
const MODE_PREDEFINED_USERS
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
getInvitation()
Gets the invitation status.
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)
const INVITATION_OFF
setEvaluationAccess($evaluation_access=self::EVALUATION_ACCESS_OFF)
Sets the learners evaluation access.
static _lookupType($a_id, $a_reference=false)
lookup object type
$users
Definition: authpage.php:44
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.
$row
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
update($pash, $contents, Config $config)
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.
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.
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.
static _addDesktopItem($a_usr_id, $a_item_id, $a_type, $a_par="")
add an item to user&#39;s personal desktop
& 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.
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
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
for($i=1; $i<=count($kw_cases_sel); $i+=1) $lang
Definition: langwiz.php:349
$i
Definition: disco.tpl.php:19
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
deleteMetaData()
delete meta data entry
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.
$source
Definition: linkback.php:22
getUserSettings($usr_id, $key)
const IL_CAL_TIMESTAMP
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
$key
Definition: croninfo.php:18
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)
$GLOBALS['JPEG_Segment_Names']
Global Variable: XMP_tag_captions.
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.
$data
Definition: bench.php:6
getPrecondition($id)
Returns a precondition with a given id.
addQuestionToBlock($question_id, $questionblock_id)