ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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 
32  const STATUS_OFFLINE = 0;
33  const STATUS_ONLINE = 1;
34 
38 
39  const INVITATION_OFF = 0;
40  const INVITATION_ON = 1;
41 
42  const MODE_UNLIMITED = 0;
44 
45  const ANONYMIZE_OFF = 0; // personalized, no codes
46  const ANONYMIZE_ON = 1; // anonymized, codes
47  const ANONYMIZE_FREEACCESS = 2; // anonymized, no codes
48  const ANONYMIZE_CODE_ALL = 3; // personalized, codes
49 
52 
53  // constants to define the print view values.
54  const PRINT_HIDE_LABELS = 1; // Show only the titles in "print" and "PDF Export"
55  const PRINT_SHOW_LABELS = 3; // Show titles and labels in "print" and "PDF Export"
56 
63  public $survey_id;
64 
71  public $author;
72 
78  public $introduction;
79 
85  public $outro;
86 
92  public $status;
93 
100 
106  public $start_date;
107 
113  public $end_date;
114 
120  public $questions;
121 
127  public $invitation;
128 
135 
140  public $anonymize;
141 
147 
154 
158  public $template_id;
159  public $pool_usage;
160 
164  protected $log;
165 
169 
170  // 360°
171  protected $mode_360; // [bool]
172  protected $mode_360_self_eval; // [bool]
173  protected $mode_360_self_appr; // [bool]
174  protected $mode_360_self_rate; // [bool]
175  protected $mode_360_results; // [int]
176  protected $mode_360_skill_service; // [bool]
177 
178  const RESULTS_360_NONE = 0;
179  const RESULTS_360_OWN = 1;
180  const RESULTS_360_ALL = 2;
181 
182  // reminder/notification
183  protected $reminder_status; // [bool]
184  protected $reminder_start; // [ilDate]
185  protected $reminder_end; // [ilDate]
186  protected $reminder_frequency; // [int]
187  protected $reminder_target; // [int]
188  protected $reminder_last_sent; // [bool]
189  protected $reminder_tmpl; // [int]
190  protected $tutor_ntf_status; // [bool]
191  protected $tutor_ntf_recipients; // [array]
192  protected $tutor_ntf_target; // [int]
193 
194  protected $view_own_results; // [bool]
195  protected $mail_own_results; // [bool]
196  protected $mail_confirmation; // [bool]
197 
198  protected $anon_user_list; // [bool]
199 
205 
206 
213  public function __construct($a_id = 0, $a_call_by_reference = true)
214  {
215  global $DIC;
216 
217  $this->user = $DIC->user();
218  $this->lng = $DIC->language();
219  $this->db = $DIC->database();
220  $this->access = $DIC->access();
221  $this->log = $DIC["ilLog"];
222  $this->plugin_admin = $DIC["ilPluginAdmin"];
223  $this->tree = $DIC->repositoryTree();
224  $ilUser = $DIC->user();
225  $lng = $DIC->language();
226 
227  $this->type = "svy";
228  $this->survey_id = -1;
229  $this->introduction = "";
230  $this->outro = $lng->txt("survey_finished");
231  $this->author = $ilUser->getFullname();
232  $this->status = self::STATUS_OFFLINE;
233  $this->evaluation_access = self::EVALUATION_ACCESS_OFF;
234  $this->questions = array();
235  $this->invitation = self::INVITATION_OFF;
236  $this->invitation_mode = self::MODE_PREDEFINED_USERS;
237  $this->anonymize = self::ANONYMIZE_OFF;
238  $this->display_question_titles = self::QUESTIONTITLES_VISIBLE;
239  $this->surveyCodeSecurity = true;
240  $this->template_id = null;
241  $this->pool_usage = true;
242  $this->log = ilLoggerFactory::getLogger("svy");
243 
244  parent::__construct($a_id, $a_call_by_reference);
245  }
246 
250  public function create($a_upload = false)
251  {
252  parent::create();
253  if (!$a_upload) {
254  $this->createMetaData();
255  }
256  }
257 
263  public function createMetaData()
264  {
265  parent::createMetaData();
266  $this->saveAuthorToMetadata();
267  }
268 
275  public function update()
276  {
277  $this->updateMetaData();
278 
279  if (!parent::update()) {
280  return false;
281  }
282 
283  // put here object specific stuff
284 
285  return true;
286  }
287 
288  public function createReference()
289  {
290  $result = parent::createReference();
291  $this->saveToDb();
292  return $result;
293  }
294 
299  public function read()
300  {
301  parent::read();
302  $this->loadFromDb();
303  }
304 
311  public function addQuestion($question_id)
312  {
313  array_push($this->questions, $question_id);
314  }
315 
322  public function delete()
323  {
324  if ($this->countReferences() == 1) {
325  $this->deleteMetaData();
326 
327  // Delete all survey questions, constraints and materials
328  foreach ($this->questions as $question_id) {
329  $this->removeQuestion($question_id);
330  }
331  $this->deleteSurveyRecord();
332 
334  }
335 
336  $remove = parent::delete();
337 
338  // always call parent delete function first!!
339  if (!$remove) {
340  return false;
341  }
342  return true;
343  }
344 
350  public function deleteSurveyRecord()
351  {
352  $ilDB = $this->db;
353 
354  $affectedRows = $ilDB->manipulateF(
355  "DELETE FROM svy_svy WHERE survey_id = %s",
356  array('integer'),
357  array($this->getSurveyId())
358  );
359 
360  $result = $ilDB->queryF(
361  "SELECT questionblock_fi FROM svy_qblk_qst WHERE survey_fi = %s",
362  array('integer'),
363  array($this->getSurveyId())
364  );
365  $questionblocks = array();
366  while ($row = $ilDB->fetchAssoc($result)) {
367  array_push($questionblocks, $row["questionblock_fi"]);
368  }
369  if (count($questionblocks)) {
370  $affectedRows = $ilDB->manipulate("DELETE FROM svy_qblk WHERE " . $ilDB->in('questionblock_id', $questionblocks, false, 'integer'));
371  }
372  $affectedRows = $ilDB->manipulateF(
373  "DELETE FROM svy_qblk_qst WHERE survey_fi = %s",
374  array('integer'),
375  array($this->getSurveyId())
376  );
377  $this->deleteAllUserData();
378 
379  $affectedRows = $ilDB->manipulateF(
380  "DELETE FROM svy_anonymous WHERE survey_fi = %s",
381  array('integer'),
382  array($this->getSurveyId())
383  );
384 
385  // delete export files
386  $svy_data_dir = ilUtil::getDataDir() . "/svy_data";
387  $directory = $svy_data_dir . "/svy_" . $this->getId();
388  if (is_dir($directory)) {
389  ilUtil::delDir($directory);
390  }
391 
392  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
393  $mobs = ilObjMediaObject::_getMobsOfObject("svy:html", $this->getId());
394  // remaining usages are not in text anymore -> delete them
395  // and media objects (note: delete method of ilObjMediaObject
396  // checks whether object is used in another context; if yes,
397  // the object is not deleted!)
398  foreach ($mobs as $mob) {
399  ilObjMediaObject::_removeUsage($mob, "svy:html", $this->getId());
400  $mob_obj = new ilObjMediaObject($mob);
401  $mob_obj->delete();
402  }
403  }
404 
410  public function deleteAllUserData()
411  {
412  $ilDB = $this->db;
413 
414  $result = $ilDB->queryF(
415  "SELECT finished_id FROM svy_finished WHERE survey_fi = %s",
416  array('integer'),
417  array($this->getSurveyId())
418  );
419  $active_array = array();
420  while ($row = $ilDB->fetchAssoc($result)) {
421  array_push($active_array, $row["finished_id"]);
422  }
423 
424  $affectedRows = $ilDB->manipulateF(
425  "DELETE FROM svy_finished WHERE survey_fi = %s",
426  array('integer'),
427  array($this->getSurveyId())
428  );
429 
430  foreach ($active_array as $active_fi) {
431  $affectedRows = $ilDB->manipulateF(
432  "DELETE FROM svy_answer WHERE active_fi = %s",
433  array('integer'),
434  array($active_fi)
435  );
436  $affectedRows = $ilDB->manipulateF(
437  "DELETE FROM svy_times WHERE finished_fi = %s",
438  array('integer'),
439  array($active_fi)
440  );
441  }
442 
443  include_once "Services/Object/classes/class.ilObjectLP.php";
444  $lp_obj = ilObjectLP::getInstance($this->getId());
445  $lp_obj->resetLPDataForCompleteObject();
446  }
447 
453  public function removeSelectedSurveyResults($finished_ids)
454  {
455  $ilDB = $this->db;
456 
457  $user_ids[] = array();
458 
459  foreach ($finished_ids as $finished_id) {
460  $result = $ilDB->queryF(
461  "SELECT finished_id FROM svy_finished WHERE finished_id = %s",
462  array('integer'),
463  array($finished_id)
464  );
465  $row = $ilDB->fetchAssoc($result);
466 
467  if ($row["user_fi"]) {
468  $user_ids[] = $row["user_fi"];
469  }
470 
471  $affectedRows = $ilDB->manipulateF(
472  "DELETE FROM svy_answer WHERE active_fi = %s",
473  array('integer'),
474  array($row["finished_id"])
475  );
476 
477  $affectedRows = $ilDB->manipulateF(
478  "DELETE FROM svy_finished WHERE finished_id = %s",
479  array('integer'),
480  array($finished_id)
481  );
482 
483  $affectedRows = $ilDB->manipulateF(
484  "DELETE FROM svy_times WHERE finished_fi = %s",
485  array('integer'),
486  array($row["finished_id"])
487  );
488  }
489 
490  if (sizeof($user_ids)) {
491  include_once "Services/Object/classes/class.ilObjectLP.php";
492  $lp_obj = ilObjectLP::getInstance($this->getId());
493  $lp_obj->resetLPDataForUserIds($user_ids);
494  }
495  }
496 
497  public function &getSurveyParticipants($finished_ids = null, $force_non_anonymous = false)
498  {
499  $ilDB = $this->db;
500 
501  $sql = "SELECT * FROM svy_finished" .
502  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer");
503  if ($finished_ids) {
504  $sql .= " AND " . $ilDB->in("finished_id", $finished_ids, "", "integer");
505  }
506 
507  $result = $ilDB->query($sql);
508  $participants = array();
509  if ($result->numRows() > 0) {
510  while ($row = $ilDB->fetchAssoc($result)) {
511  $userdata = $this->getUserDataFromActiveId($row["finished_id"], $force_non_anonymous);
512  $userdata["finished"] = (bool) $row["state"];
513  $userdata["finished_tstamp"] = $row["tstamp"];
514  $participants[$userdata["sortname"] . $userdata["active_id"]] = $userdata;
515  }
516  }
517  return $participants;
518  }
519 
526  public function isComplete()
527  {
528  if (($this->getTitle()) and (count($this->questions))) {
529  return 1;
530  } else {
531  return 0;
532  }
533  }
534 
540  public function saveCompletionStatus()
541  {
542  $ilDB = $this->db;
543 
544  $complete = 0;
545  if ($this->isComplete()) {
546  $complete = 1;
547  }
548  if ($this->getSurveyId() > 0) {
549  $affectedRows = $ilDB->manipulateF(
550  "UPDATE svy_svy SET complete = %s, tstamp = %s WHERE survey_id = %s",
551  array('text','integer','integer'),
552  array($this->isComplete(), time(), $this->getSurveyId())
553  );
554  }
555  }
556 
564  public function duplicateQuestionForSurvey($question_id, $a_force = false)
565  {
567 
568  $questiontype = $this->getQuestionType($question_id);
569  $question_gui = $this->getQuestionGUI($questiontype, $question_id);
570 
571  // check if question is a pool question at all, if not do nothing
572  if ($this->getId() == $question_gui->object->getObjId() && !$a_force) {
573  return $question_id;
574  }
575 
576  $duplicate_id = $question_gui->object->duplicate(true, "", "", "", $this->getId());
577  return $duplicate_id;
578  }
579 
585  public function insertQuestion($question_id)
586  {
587  $ilDB = $this->db;
588 
589  $this->log->debug("insert question, id:" . $question_id);
590 
591  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
592  if (!SurveyQuestion::_isComplete($question_id)) {
593  $this->log->debug("question is not complete");
594  return false;
595  } else {
596  // get maximum sequence index in test
597  // @todo: refactor this
598  $result = $ilDB->queryF(
599  "SELECT survey_question_id FROM svy_svy_qst WHERE survey_fi = %s",
600  array('integer'),
601  array($this->getSurveyId())
602  );
603  $sequence = $result->numRows();
604  $duplicate_id = $this->duplicateQuestionForSurvey($question_id);
605  $this->log->debug("duplicate, id: " . $question_id . ", duplicate id: " . $duplicate_id);
606 
607  // check if question is not already in the survey, see #22018
608  if ($this->isQuestionInSurvey($duplicate_id)) {
609  return false;
610  }
611 
612  $next_id = $ilDB->nextId('svy_svy_qst');
613  $affectedRows = $ilDB->manipulateF(
614  "INSERT INTO svy_svy_qst (survey_question_id, survey_fi, question_fi, sequence, tstamp) VALUES (%s, %s, %s, %s, %s)",
615  array('integer', 'integer', 'integer', 'integer', 'integer'),
616  array($next_id, $this->getSurveyId(), $duplicate_id, $sequence, time())
617  );
618 
619  $this->log->debug("added entry to svy_svy_qst, id: " . $next_id . ", question id: " . $duplicate_id . ", sequence: " . $sequence);
620 
621  $this->loadQuestionsFromDb();
622  return true;
623  }
624  }
625 
632  public function isQuestionInSurvey($a_question_fi)
633  {
634  global $DIC;
635  //return false;
636  $ilDB = $DIC->database();
637 
638  $set = $ilDB->query("SELECT * FROM svy_svy_qst " .
639  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
640  " AND question_fi = " . $ilDB->quote($a_question_fi, "integer"));
641  if ($rec = $ilDB->fetchAssoc($set)) {
642  return true;
643  }
644  return false;
645  }
646 
647 
648 
654  public function insertQuestionblock($questionblock_id)
655  {
656  $ilDB = $this->db;
657  $result = $ilDB->queryF(
658  "SELECT svy_qblk.title, svy_qblk.show_questiontext, svy_qblk.show_blocktitle," .
659  " svy_qblk_qst.question_fi FROM svy_qblk, svy_qblk_qst, svy_svy_qst" .
660  " WHERE svy_qblk.questionblock_id = svy_qblk_qst.questionblock_fi" .
661  " AND svy_svy_qst.question_fi = svy_qblk_qst.question_fi" .
662  " AND svy_qblk.questionblock_id = %s" .
663  " ORDER BY svy_svy_qst.sequence",
664  array('integer'),
665  array($questionblock_id)
666  );
667  $questions = array();
668  $show_questiontext = 0;
669  $show_blocktitle = 0;
670  while ($row = $ilDB->fetchAssoc($result)) {
671  $duplicate_id = $this->duplicateQuestionForSurvey($row["question_fi"]);
672  array_push($questions, $duplicate_id);
673  $title = $row["title"];
674  $show_questiontext = $row["show_questiontext"];
675  $show_blocktitle = $row["show_blocktitle"];
676  }
677  $this->createQuestionblock($title, $show_questiontext, $show_blocktitle, $questions);
678  }
679 
680  public function saveUserSettings($usr_id, $key, $title, $value)
681  {
682  $ilDB = $this->db;
683 
684  $next_id = $ilDB->nextId('svy_settings');
685  $affectedRows = $ilDB->insert("svy_settings", array(
686  "settings_id" => array("integer", $next_id),
687  "usr_id" => array("integer", $usr_id),
688  "keyword" => array("text", $key),
689  "title" => array("text", $title),
690  "value" => array("clob", $value)
691  ));
692  }
693 
694  public function deleteUserSettings($id)
695  {
696  $ilDB = $this->db;
697 
698  $affectedRows = $ilDB->manipulateF(
699  "DELETE FROM svy_settings WHERE settings_id = %s",
700  array('integer'),
701  array($id)
702  );
703  return $affectedRows;
704  }
705 
706  public function getUserSettings($usr_id, $key)
707  {
708  $ilDB = $this->db;
709 
710  $result = $ilDB->queryF(
711  "SELECT * FROM svy_settings WHERE usr_id = %s AND keyword = %s",
712  array('integer', 'text'),
713  array($usr_id, $key)
714  );
715  $found = array();
716  if ($result->numRows()) {
717  while ($row = $ilDB->fetchAssoc($result)) {
718  $found[$row['settings_id']] = $row;
719  }
720  }
721  return $found;
722  }
723 
729  public function saveToDb()
730  {
731  $ilDB = $this->db;
732 
733  // date handling
734  $rmd_start = $this->getReminderStart();
735  if (is_object($rmd_start)) {
736  $rmd_start = $rmd_start->get(IL_CAL_DATE);
737  }
738  $rmd_end = $this->getReminderEnd();
739  if (is_object($rmd_end)) {
740  $rmd_end = $rmd_end->get(IL_CAL_DATE);
741  }
742 
743  include_once("./Services/RTE/classes/class.ilRTE.php");
744  if ($this->getSurveyId() < 1) {
745  $next_id = $ilDB->nextId('svy_svy');
746  $affectedRows = $ilDB->insert("svy_svy", array(
747  "survey_id" => array("integer", $next_id),
748  "obj_fi" => array("integer", $this->getId()),
749  "author" => array("text", $this->getAuthor()),
750  "introduction" => array("clob", ilRTE::_replaceMediaObjectImageSrc($this->getIntroduction(), 0)),
751  "outro" => array("clob", ilRTE::_replaceMediaObjectImageSrc($this->getOutro(), 0)),
752  "status" => array("text", $this->getStatus()),
753  "startdate" => array("text", $this->getStartDate()),
754  "enddate" => array("text", $this->getEndDate()),
755  "evaluation_access" => array("text", $this->getEvaluationAccess()),
756  "invitation" => array("text", $this->getInvitation()),
757  "invitation_mode" => array("text", $this->getInvitationMode()),
758  "complete" => array("text", $this->isComplete()),
759  "created" => array("integer", time()),
760  "anonymize" => array("text", $this->getAnonymize()),
761  "show_question_titles" => array("text", $this->getShowQuestionTitles()),
762  "mailnotification" => array('integer', ($this->getMailNotification()) ? 1 : 0),
763  "mailaddresses" => array('text', strlen($this->getMailAddresses()) ? $this->getMailAddresses() : null),
764  "mailparticipantdata" => array('text', strlen($this->getMailParticipantData()) ? $this->getMailParticipantData() : null),
765  "tstamp" => array("integer", time()),
766  "template_id" => array("integer", $this->getTemplate()),
767  "pool_usage" => array("integer", $this->getPoolUsage()),
768  // 360°
769  "mode_360" => array("integer", $this->get360Mode()),
770  "mode_360_self_eval" => array("integer", $this->get360SelfEvaluation()),
771  "mode_360_self_rate" => array("integer", $this->get360SelfRaters()),
772  "mode_360_self_appr" => array("integer", $this->get360SelfAppraisee()),
773  "mode_360_results" => array("integer", $this->get360Results()),
774  "mode_360_skill_service" => array("integer", (int) $this->get360SkillService()),
775  // reminder/notification
776  "reminder_status" => array("integer", (int) $this->getReminderStatus()),
777  "reminder_start" => array("datetime", $rmd_start),
778  "reminder_end" => array("datetime", $rmd_end),
779  "reminder_frequency" => array("integer", (int) $this->getReminderFrequency()),
780  "reminder_target" => array("integer", (int) $this->getReminderTarget()),
781  "reminder_last_sent" => array("datetime", $this->getReminderLastSent()),
782  "reminder_tmpl" => array("text", $this->getReminderTemplate()),
783  "tutor_ntf_status" => array("integer", (int) $this->getTutorNotificationStatus()),
784  "tutor_ntf_reci" => array("text", implode(";", (array) $this->getTutorNotificationRecipients())),
785  "tutor_ntf_target" => array("integer", (int) $this->getTutorNotificationTarget()),
786  "own_results_view" => array("integer", $this->hasViewOwnResults()),
787  "own_results_mail" => array("integer", $this->hasMailOwnResults()),
788  "confirmation_mail" => array("integer", $this->hasMailConfirmation()),
789  "anon_user_list" => array("integer", $this->hasAnonymousUserList())
790  ));
791  $this->setSurveyId($next_id);
792  } else {
793  $affectedRows = $ilDB->update("svy_svy", array(
794  "author" => array("text", $this->getAuthor()),
795  "introduction" => array("clob", ilRTE::_replaceMediaObjectImageSrc($this->getIntroduction(), 0)),
796  "outro" => array("clob", ilRTE::_replaceMediaObjectImageSrc($this->getOutro(), 0)),
797  "status" => array("text", $this->getStatus()),
798  "startdate" => array("text", $this->getStartDate()),
799  "enddate" => array("text", $this->getEndDate()),
800  "evaluation_access" => array("text", $this->getEvaluationAccess()),
801  "invitation" => array("text", $this->getInvitation()),
802  "invitation_mode" => array("text", $this->getInvitationMode()),
803  "complete" => array("text", $this->isComplete()),
804  "anonymize" => array("text", $this->getAnonymize()),
805  "show_question_titles" => array("text", $this->getShowQuestionTitles()),
806  "mailnotification" => array('integer', ($this->getMailNotification()) ? 1 : 0),
807  "mailaddresses" => array('text', strlen($this->getMailAddresses()) ? $this->getMailAddresses() : null),
808  "mailparticipantdata" => array('text', strlen($this->getMailParticipantData()) ? $this->getMailParticipantData() : null),
809  "tstamp" => array("integer", time()),
810  "template_id" => array("integer", $this->getTemplate()),
811  "pool_usage" => array("integer", $this->getPoolUsage()),
812  // 360°
813  "mode_360" => array("integer", $this->get360Mode()),
814  "mode_360_self_eval" => array("integer", $this->get360SelfEvaluation()),
815  "mode_360_self_rate" => array("integer", $this->get360SelfRaters()),
816  "mode_360_self_appr" => array("integer", $this->get360SelfAppraisee()),
817  "mode_360_results" => array("integer", $this->get360Results()),
818  "mode_360_skill_service" => array("integer", (int) $this->get360SkillService()),
819  // reminder/notification
820  "reminder_status" => array("integer", $this->getReminderStatus()),
821  "reminder_start" => array("datetime", $rmd_start),
822  "reminder_end" => array("datetime", $rmd_end),
823  "reminder_frequency" => array("integer", $this->getReminderFrequency()),
824  "reminder_target" => array("integer", $this->getReminderTarget()),
825  "reminder_last_sent" => array("datetime", $this->getReminderLastSent()),
826  "reminder_tmpl" => array("text", $this->getReminderTemplate()),
827  "tutor_ntf_status" => array("integer", $this->getTutorNotificationStatus()),
828  "tutor_ntf_reci" => array("text", implode(";", (array) $this->getTutorNotificationRecipients())),
829  "tutor_ntf_target" => array("integer", $this->getTutorNotificationTarget()),
830  "own_results_view" => array("integer", $this->hasViewOwnResults()),
831  "own_results_mail" => array("integer", $this->hasMailOwnResults()),
832  "confirmation_mail" => array("integer", $this->hasMailConfirmation()),
833  "anon_user_list" => array("integer", $this->hasAnonymousUserList())
834  ), array(
835  "survey_id" => array("integer", $this->getSurveyId())
836  ));
837  }
838  if ($affectedRows) {
839  // save questions to db
840  $this->saveQuestionsToDb();
841  }
842 
843  // moved activation to ilObjectActivation
844  if ($this->ref_id) {
845  include_once "./Services/Object/classes/class.ilObjectActivation.php";
846  ilObjectActivation::getItem($this->ref_id);
847 
848  $item = new ilObjectActivation;
849  if (!$this->isActivationLimited()) {
851  } else {
852  $item->setTimingType(ilObjectActivation::TIMINGS_ACTIVATION);
853  $item->setTimingStart($this->getActivationStartDate());
854  $item->setTimingEnd($this->getActivationEndDate());
855  $item->toggleVisible($this->getActivationVisibility());
856  }
857 
858  $item->update($this->ref_id);
859  }
860  }
861 
868  public function saveQuestionsToDb()
869  {
870  $ilDB = $this->db;
871 
872  $this->log->debug("save questions");
873 
874  // gather old questions state
875  $old_questions = array();
876  $result = $ilDB->queryF(
877  "SELECT survey_question_id,question_fi,sequence" .
878  " FROM svy_svy_qst WHERE survey_fi = %s",
879  array('integer'),
880  array($this->getSurveyId())
881  );
882  while ($row = $ilDB->fetchAssoc($result)) {
883  $old_questions[$row["question_fi"]] = $row; // problem, as soon as duplicates exist, they will be hidden here
884  }
885 
886  // #15231 - diff with current questions state
887  $insert = $update = $delete = array();
888  foreach ($this->questions as $seq => $fi) {
889  if (!array_key_exists($fi, $old_questions)) { // really new fi IDs
890  $insert[] = $fi; // this should be ok, should not create duplicates here
891  } elseif ($old_questions[$fi]["sequence"] != $seq) { // we are updating one of the duplicates (if any)
892  $update[$fi] = $old_questions[$fi]["survey_question_id"];
893  }
894  // keep track of still relevant questions
895  unset($old_questions[$fi]); // deleting old question, if they are not in current array
896  }
897 
898  // delete obsolete question relations
899  if (sizeof($old_questions)) {
900  $del_ids = array();
901  foreach ($old_questions as $fi => $old) {
902  $del_ids[] = $old["survey_question_id"];
903  }
904  $ilDB->manipulate($q = "DELETE FROM svy_svy_qst" .
905  " WHERE " . $ilDB->in("survey_question_id", $del_ids, "", "integer"));
906  $this->log->debug("delete: " . $q);
907  }
908  unset($old_questions);
909 
910  // create/update question relations
911  foreach ($this->questions as $seq => $fi) {
912  if (in_array($fi, $insert)) {
913  // check if question is not already in the survey, see #22018
914  if (!$this->isQuestionInSurvey($fi)) {
915  $next_id = $ilDB->nextId('svy_svy_qst');
916  $ilDB->manipulateF(
917  "INSERT INTO svy_svy_qst" .
918  " (survey_question_id, survey_fi, question_fi, heading, sequence, tstamp)" .
919  " VALUES (%s, %s, %s, %s, %s, %s)",
920  array('integer', 'integer', 'integer', 'text', 'integer', 'integer'),
921  array($next_id, $this->getSurveyId(), $fi, null, $seq, time())
922  );
923  $this->log->debug("insert svy_svy_qst, id:" . $next_id . ", fi: " . $fi . ", seq:" . $seq);
924  }
925  } elseif (array_key_exists($fi, $update)) {
926  $ilDB->manipulate("UPDATE svy_svy_qst" .
927  " SET sequence = " . $ilDB->quote($seq, "integer") .
928  ", tstamp = " . $ilDB->quote(time(), "integer") .
929  " WHERE survey_question_id = " . $ilDB->quote($update[$fi], "integer"));
930  $this->log->debug("update svy_svy_qst, id:" . $update[$fi] . ", fi: " . $fi . ", seq:" . $seq);
931  }
932  }
933  }
934 
942  public function getAnonymousId($id)
943  {
944  $ilDB = $this->db;
945  $result = $ilDB->queryF(
946  "SELECT anonymous_id FROM svy_finished WHERE anonymous_id = %s",
947  array('text'),
948  array($id)
949  );
950  if ($result->numRows()) {
951  $row = $ilDB->fetchAssoc($result);
952  return $row["anonymous_id"];
953  } else {
954  return "";
955  }
956  }
957 
964  public function getQuestionGUI($questiontype, $question_id)
965  {
966  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestionGUI.php";
967  return SurveyQuestionGUI::_getQuestionGUI($questiontype, $question_id);
968  }
969 
977  public function getQuestionType($question_id)
978  {
979  $ilDB = $this->db;
980  if ($question_id < 1) {
981  return -1;
982  }
983  $result = $ilDB->queryF(
984  "SELECT type_tag FROM svy_question, svy_qtype WHERE svy_question.question_id = %s AND " .
985  "svy_question.questiontype_fi = svy_qtype.questiontype_id",
986  array('integer'),
987  array($question_id)
988  );
989  if ($result->numRows() == 1) {
990  $data = $ilDB->fetchAssoc($result);
991  return $data["type_tag"];
992  } else {
993  return "";
994  }
995  }
996 
1003  public function getSurveyId()
1004  {
1005  return $this->survey_id;
1006  }
1007 
1011  public function setAnonymize($a_anonymize)
1012  {
1013  switch ($a_anonymize) {
1014  case self::ANONYMIZE_OFF:
1015  case self::ANONYMIZE_ON:
1016  case self::ANONYMIZE_FREEACCESS:
1017  case self::ANONYMIZE_CODE_ALL:
1018  $this->anonymize = $a_anonymize;
1019  break;
1020  default:
1021  $this->anonymize = self::ANONYMIZE_OFF;
1022  break;
1023  }
1024  }
1025 
1031  public function getAnonymize()
1032  {
1033  return ($this->anonymize) ? $this->anonymize : 0;
1034  }
1035 
1041  public function isAccessibleWithoutCode()
1042  {
1043  return ($this->getAnonymize() == self::ANONYMIZE_OFF ||
1044  $this->getAnonymize() == self::ANONYMIZE_FREEACCESS);
1045  }
1046 
1052  public function hasAnonymizedResults()
1053  {
1054  return ($this->getAnonymize() == self::ANONYMIZE_ON ||
1055  $this->getAnonymize() == self::ANONYMIZE_FREEACCESS);
1056  }
1057 
1063  public function loadFromDb()
1064  {
1065  $ilDB = $this->db;
1066  $result = $ilDB->queryF(
1067  "SELECT * FROM svy_svy WHERE obj_fi = %s",
1068  array('integer'),
1069  array($this->getId())
1070  );
1071  if ($result->numRows() == 1) {
1072  $data = $ilDB->fetchAssoc($result);
1073  $this->setSurveyId($data["survey_id"]);
1074  $this->setAuthor($data["author"]);
1075  include_once("./Services/RTE/classes/class.ilRTE.php");
1076  $this->setIntroduction(ilRTE::_replaceMediaObjectImageSrc($data["introduction"], 1));
1077  if (strcmp($data["outro"], "survey_finished") == 0) {
1078  $this->setOutro($this->lng->txt("survey_finished"));
1079  } else {
1080  $this->setOutro(ilRTE::_replaceMediaObjectImageSrc($data["outro"], 1));
1081  }
1082  $this->setInvitation($data["invitation"]);
1083  $this->setInvitationMode($data["invitation_mode"]);
1084  $this->setShowQuestionTitles($data["show_question_titles"]);
1085  $this->setStartDate($data["startdate"]);
1086  $this->setEndDate($data["enddate"]);
1087  $this->setAnonymize($data["anonymize"]);
1088  $this->setEvaluationAccess($data["evaluation_access"]);
1089  $this->loadQuestionsFromDb();
1090  $this->setStatus($data["status"]);
1091  $this->setMailNotification($data['mailnotification']);
1092  $this->setMailAddresses($data['mailaddresses']);
1093  $this->setMailParticipantData($data['mailparticipantdata']);
1094  $this->setTemplate($data['template_id']);
1095  $this->setPoolUsage($data['pool_usage']);
1096  // 360°
1097  $this->set360Mode($data['mode_360']);
1098  $this->set360SelfEvaluation($data['mode_360_self_eval']);
1099  $this->set360SelfRaters($data['mode_360_self_rate']);
1100  $this->set360SelfAppraisee($data['mode_360_self_appr']);
1101  $this->set360Results($data['mode_360_results']);
1102  $this->set360SkillService($data['mode_360_skill_service']);
1103  // reminder/notification
1104  $this->setReminderStatus($data["reminder_status"]);
1105  $this->setReminderStart($data["reminder_start"] ? new ilDate($data["reminder_start"], IL_CAL_DATE) : null);
1106  $this->setReminderEnd($data["reminder_end"] ? new ilDate($data["reminder_end"], IL_CAL_DATE) : null);
1107  $this->setReminderFrequency($data["reminder_frequency"]);
1108  $this->setReminderTarget($data["reminder_target"]);
1109  $this->setReminderLastSent($data["reminder_last_sent"]);
1110  $this->setReminderTemplate($data["reminder_tmpl"]);
1111  $this->setTutorNotificationStatus($data["tutor_ntf_status"]);
1112  $this->setTutorNotificationRecipients(explode(";", $data["tutor_ntf_reci"]));
1113  $this->setTutorNotificationTarget($data["tutor_ntf_target"]);
1114 
1115  $this->setViewOwnResults($data["own_results_view"]);
1116  $this->setMailOwnResults($data["own_results_mail"]);
1117  $this->setMailConfirmation($data["confirmation_mail"]);
1118 
1119  $this->setAnonymousUserList($data["anon_user_list"]);
1120  }
1121 
1122  // moved activation to ilObjectActivation
1123  if ($this->ref_id) {
1124  include_once "./Services/Object/classes/class.ilObjectActivation.php";
1125  $activation = ilObjectActivation::getItem($this->ref_id);
1126  switch ($activation["timing_type"]) {
1128  $this->setActivationLimited(true);
1129  $this->setActivationStartDate($activation["timing_start"]);
1130  $this->setActivationEndDate($activation["timing_end"]);
1131  $this->setActivationVisibility($activation["visible"]);
1132  break;
1133 
1134  default:
1135  $this->setActivationLimited(false);
1136  break;
1137  }
1138  }
1139  }
1140 
1147  public function loadQuestionsFromDb()
1148  {
1149  $ilDB = $this->db;
1150  $this->questions = array();
1151  $result = $ilDB->queryF(
1152  "SELECT * FROM svy_svy_qst WHERE survey_fi = %s ORDER BY sequence",
1153  array('integer'),
1154  array($this->getSurveyId())
1155  );
1156  while ($data = $ilDB->fetchAssoc($result)) {
1157  $this->questions[$data["sequence"]] = $data["question_fi"];
1158  }
1159  }
1160 
1164  public function fixSequenceStructure()
1165  {
1166  global $DIC;
1167 
1168  $ilDB = $DIC->database();
1169  //return;
1170  // we keep all survey question ids with their lowest sequence
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 
1177  // step 1: find duplicates -> $to_delete_ids
1178  $fis = array();
1179  $to_delete_ids = array();
1180  while ($data = $ilDB->fetchAssoc($result)) {
1181  if (in_array($data["question_fi"], $fis)) { // found a duplicate
1182  $to_delete_ids[] = $data["survey_question_id"];
1183  } else {
1184  $fis[] = $data["question_fi"];
1185  }
1186  }
1187 
1188  // step 2: we delete the duplicates
1189  if (count($to_delete_ids) > 0) {
1190  $ilDB->manipulate($q = "DELETE FROM svy_svy_qst" .
1191  " WHERE " . $ilDB->in("survey_question_id", $to_delete_ids, false, "integer") .
1192  " AND survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer"));
1193  $this->log->debug("delete: " . $q);
1194 
1195  $ilDB->manipulate($q = "DELETE FROM svy_qblk_qst " .
1196  " WHERE " . $ilDB->in("question_fi", $fis, true, "integer") .
1197  " AND survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer"));
1198  $this->log->debug("delete: " . $q);
1199  }
1200 
1201  // step 3: we fix the sequence
1202  $set = $ilDB->query("SELECT * FROM svy_svy_qst " .
1203  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") . " ORDER BY sequence");
1204  $seq = 0;
1205  while ($rec = $ilDB->fetchAssoc($set)) {
1206  $ilDB->manipulate(
1207  $q = "UPDATE svy_svy_qst SET " .
1208  " sequence = " . $ilDB->quote($seq++, "integer") .
1209  " WHERE survey_question_id = " . $ilDB->quote($rec["survey_question_id"], "integer")
1210  );
1211  $this->log->debug("update: " . $q);
1212  }
1213  }
1214 
1215 
1223  public function setAuthor($author = "")
1224  {
1225  $this->author = $author;
1226  }
1227 
1237  public function saveAuthorToMetadata($a_author = "")
1238  {
1239  $md = new ilMD($this->getId(), 0, $this->getType());
1240  $md_life =&$md->getLifecycle();
1241  if (!$md_life) {
1242  if (strlen($a_author) == 0) {
1243  $ilUser = $this->user;
1244  $a_author = $ilUser->getFullname();
1245  }
1246 
1247  $md_life =&$md->addLifecycle();
1248  $md_life->save();
1249  $con =&$md_life->addContribute();
1250  $con->setRole("Author");
1251  $con->save();
1252  $ent =&$con->addEntity();
1253  $ent->setEntity($a_author);
1254  $ent->save();
1255  }
1256  }
1257 
1265  public function getAuthor()
1266  {
1267  $author = array();
1268  include_once "./Services/MetaData/classes/class.ilMD.php";
1269  $md = new ilMD($this->getId(), 0, $this->getType());
1270  $md_life =&$md->getLifecycle();
1271  if ($md_life) {
1272  $ids =&$md_life->getContributeIds();
1273  foreach ($ids as $id) {
1274  $md_cont =&$md_life->getContribute($id);
1275  if (strcmp($md_cont->getRole(), "Author") == 0) {
1276  $entids =&$md_cont->getEntityIds();
1277  foreach ($entids as $entid) {
1278  $md_ent =&$md_cont->getEntity($entid);
1279  array_push($author, $md_ent->getEntity());
1280  }
1281  }
1282  }
1283  }
1284  return join($author, ",");
1285  }
1286 
1293  public function getShowQuestionTitles()
1294  {
1295  return ($this->display_question_titles) ? 1 : 0;
1296  }
1297 
1304  public function setShowQuestionTitles($a_show)
1305  {
1306  $this->display_question_titles = ($a_show) ? 1 : 0;
1307  }
1308 
1315  public function showQuestionTitles()
1316  {
1317  $this->display_question_titles = 1;
1318  }
1319 
1326  public function hideQuestionTitles()
1327  {
1328  $this->display_question_titles = 0;
1329  }
1330 
1338  public function setInvitation($invitation = 0)
1339  {
1340  $ilDB = $this->db;
1341  $ilAccess = $this->access;
1342 
1343  $this->invitation = $invitation;
1345  $this->disinviteAllUsers();
1346  } elseif ($invitation == self::INVITATION_ON) {
1347  if ($this->getInvitationMode() == self::MODE_UNLIMITED) {
1348  $result = $ilDB->query("SELECT usr_id FROM usr_data");
1349  while ($row = $ilDB->fetchAssoc($result)) {
1350  if ($ilAccess->checkAccessOfUser($row["usr_id"], "read", "", $this->getRefId(), "svy", $this->getId())) {
1351  $this->inviteUser($row['usr_id']);
1352  }
1353  }
1354  }
1355  }
1356  }
1357 
1366  {
1367  $this->invitation_mode = $invitation_mode;
1368  }
1369 
1379  {
1380  $this->invitation_mode = $invitation_mode;
1381  $this->setInvitation($invitation);
1382  }
1383 
1390  public function setIntroduction($introduction = "")
1391  {
1392  $this->introduction = $introduction;
1393  }
1394 
1401  public function setOutro($outro = "")
1402  {
1403  $this->outro = $outro;
1404  }
1405 
1413  public function getInvitation()
1414  {
1415  return ($this->invitation) ? $this->invitation : self::INVITATION_OFF;
1416  }
1417 
1425  public function getInvitationMode()
1426  {
1427  include_once "./Services/Administration/classes/class.ilSetting.php";
1428  $surveySetting = new ilSetting("survey");
1429  $unlimited_invitation = $surveySetting->get("unlimited_invitation");
1430  if (!$unlimited_invitation && $this->invitation_mode == self::MODE_UNLIMITED) {
1431  return self::MODE_PREDEFINED_USERS;
1432  } else {
1433  return ($this->invitation_mode) ? $this->invitation_mode : self::MODE_UNLIMITED;
1434  }
1435  }
1436 
1444  public function getStatus()
1445  {
1446  return ($this->status) ? $this->status : self::STATUS_OFFLINE;
1447  }
1448 
1456  public function isOnline()
1457  {
1458  return ($this->status == self::STATUS_ONLINE) ? true : false;
1459  }
1460 
1468  public function isOffline()
1469  {
1470  return ($this->status == self::STATUS_OFFLINE) ? true : false;
1471  }
1472 
1481  public function setStatus($status = self::STATUS_OFFLINE)
1482  {
1483  $result = "";
1484  if (($status == self::STATUS_ONLINE) && (count($this->questions) == 0)) {
1485  $this->status = self::STATUS_OFFLINE;
1486  $result = $this->lng->txt("cannot_switch_to_online_no_questions");
1487  } else {
1488  $this->status = $status;
1489  }
1490  return $result;
1491  }
1492 
1500  public function getStartDate()
1501  {
1502  return (strlen($this->start_date)) ? $this->start_date : null;
1503  }
1504 
1511  public function canStartSurvey($anonymous_id = null, $a_no_rbac = false)
1512  {
1513  $ilAccess = $this->access;
1514 
1515  $result = true;
1516  $messages = array();
1517  $edit_settings = false;
1518  // check start date
1519  if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getStartDate(), $matches)) {
1520  $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
1521  $now = time();
1522  if ($now < $epoch_time) {
1523  array_push($messages, $this->lng->txt('start_date_not_reached') . ' (' .
1525  $result = false;
1526  $edit_settings = true;
1527  }
1528  }
1529  // check end date
1530  if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndDate(), $matches)) {
1531  $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
1532  $now = time();
1533  if ($now > $epoch_time) {
1534  array_push($messages, $this->lng->txt('end_date_reached') . ' (' .
1536  $result = false;
1537  $edit_settings = true;
1538  }
1539  }
1540 
1541  // check online status
1542  if ($this->getStatus() == self::STATUS_OFFLINE) {
1543  array_push($messages, $this->lng->txt("survey_is_offline"));
1544  $result = false;
1545  $edit_settings = true;
1546  }
1547  // check rbac permissions
1548  if (!$a_no_rbac && !$ilAccess->checkAccess("read", "", $this->ref_id)) {
1549  array_push($messages, $this->lng->txt("cannot_participate_survey"));
1550  $result = false;
1551  }
1552  /*
1553  // 2. check previous access
1554  if (!$result["error"])
1555  {
1556  $ilUser = $this->user;
1557  $survey_started = $this->isSurveyStarted($ilUser->getId(), $anonymous_id);
1558  if ($survey_started === 1)
1559  {
1560  array_push($messages, $this->lng->txt("already_completed_survey"));
1561  $result = FALSE;
1562  }
1563  }
1564  */
1565  return array(
1566  "result" => $result,
1567  "messages" => $messages,
1568  "edit_settings" => $edit_settings
1569  );
1570  }
1571 
1579  public function setStartDate($start_date = "")
1580  {
1581  $this->start_date = $start_date;
1582  }
1583 
1592  public function setStartDateAndTime($start_date = "", $start_time)
1593  {
1594  $y = '';
1595  $m = '';
1596  $d = '';
1597  $h = '';
1598  $i = '';
1599  $s = '';
1600  if (preg_match("/(\d{4})-(\d{2})-(\d{2})/", $start_date, $matches)) {
1601  $y = $matches[1];
1602  $m = $matches[2];
1603  $d = $matches[3];
1604  }
1605  if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $start_time, $matches)) {
1606  $h = $matches[1];
1607  $i = $matches[2];
1608  $s = $matches[3];
1609  }
1610  $this->start_date = sprintf('%04d%02d%02d%02d%02d%02d', $y, $m, $d, $h, $i, $s);
1611  }
1612 
1620  public function getEndDate()
1621  {
1622  return (strlen($this->end_date)) ? $this->end_date : null;
1623  }
1624 
1632  public function setEndDate($end_date = "")
1633  {
1634  $this->end_date = $end_date;
1635  }
1636 
1645  public function setEndDateAndTime($end_date = "", $end_time)
1646  {
1647  $y = '';
1648  $m = '';
1649  $d = '';
1650  $h = '';
1651  $i = '';
1652  $s = '';
1653  if (preg_match("/(\d{4})-(\d{2})-(\d{2})/", $end_date, $matches)) {
1654  $y = $matches[1];
1655  $m = $matches[2];
1656  $d = $matches[3];
1657  }
1658  if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $end_time, $matches)) {
1659  $h = $matches[1];
1660  $i = $matches[2];
1661  $s = $matches[3];
1662  }
1663  $this->end_date = sprintf('%04d%02d%02d%02d%02d%02d', $y, $m, $d, $h, $i, $s);
1664  }
1665 
1673  public function getEvaluationAccess()
1674  {
1675  return ($this->evaluation_access) ? $this->evaluation_access : self::EVALUATION_ACCESS_OFF;
1676  }
1677 
1685  public function setEvaluationAccess($evaluation_access = self::EVALUATION_ACCESS_OFF)
1686  {
1687  $this->evaluation_access = ($evaluation_access) ? $evaluation_access : self::EVALUATION_ACCESS_OFF;
1688  }
1689 
1690  public function setActivationVisibility($a_value)
1691  {
1692  $this->activation_visibility = (bool) $a_value;
1693  }
1694 
1695  public function getActivationVisibility()
1696  {
1698  }
1699 
1700  public function isActivationLimited()
1701  {
1702  return (bool) $this->activation_limited;
1703  }
1704 
1705  public function setActivationLimited($a_value)
1706  {
1707  $this->activation_limited = (bool) $a_value;
1708  }
1709 
1717  public function getIntroduction()
1718  {
1719  return (strlen($this->introduction)) ? $this->introduction : null;
1720  }
1721 
1729  public function getOutro()
1730  {
1731  return (strlen($this->outro)) ? $this->outro : null;
1732  }
1733 
1740  public function &getExistingQuestions()
1741  {
1742  $ilDB = $this->db;
1743  $existing_questions = array();
1744  $result = $ilDB->queryF(
1745  "SELECT svy_question.original_id FROM svy_question, svy_svy_qst WHERE " .
1746  "svy_svy_qst.survey_fi = %s AND svy_svy_qst.question_fi = svy_question.question_id",
1747  array('integer'),
1748  array($this->getSurveyId())
1749  );
1750  while ($data = $ilDB->fetchAssoc($result)) {
1751  if ($data["original_id"]) {
1752  array_push($existing_questions, $data["original_id"]);
1753  }
1754  }
1755  return $existing_questions;
1756  }
1757 
1764  public function &getQuestionpoolTitles($could_be_offline = false, $showPath = false)
1765  {
1766  include_once "./Modules/SurveyQuestionPool/classes/class.ilObjSurveyQuestionPool.php";
1767  return ilObjSurveyQuestionPool::_getAvailableQuestionpools($use_object_id = true, $could_be_offline, $showPath);
1768  }
1769 
1778  public function moveQuestions($move_questions, $target_index, $insert_mode)
1779  {
1780  $array_pos = array_search($target_index, $this->questions);
1781  if ($insert_mode == 0) {
1782  $part1 = array_slice($this->questions, 0, $array_pos);
1783  $part2 = array_slice($this->questions, $array_pos);
1784  } elseif ($insert_mode == 1) {
1785  $part1 = array_slice($this->questions, 0, $array_pos + 1);
1786  $part2 = array_slice($this->questions, $array_pos + 1);
1787  }
1788  foreach ($move_questions as $question_id) {
1789  if (!(array_search($question_id, $part1) === false)) {
1790  unset($part1[array_search($question_id, $part1)]);
1791  }
1792  if (!(array_search($question_id, $part2) === false)) {
1793  unset($part2[array_search($question_id, $part2)]);
1794  }
1795  }
1796  $part1 = array_values($part1);
1797  $part2 = array_values($part2);
1798  $this->questions = array_values(array_merge($part1, $move_questions, $part2));
1799  foreach ($move_questions as $question_id) {
1800  $constraints = $this->getConstraints($question_id);
1801  foreach ($constraints as $idx => $constraint) {
1802  foreach ($part2 as $next_question_id) {
1803  if ($constraint["question"] == $next_question_id) {
1804  // constraint concerning a question that follows -> delete constraint
1805  $this->deleteConstraint($constraint["id"]);
1806  }
1807  }
1808  }
1809  }
1810  $this->saveQuestionsToDb();
1811  }
1812 
1819  public function removeQuestion($question_id)
1820  {
1821  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
1822  $question = self::_instanciateQuestion($question_id);
1823  #20610 if no question found, do nothing.
1824  if ($question) {
1825  $question->delete($question_id);
1826  $this->removeConstraintsConcerningQuestion($question_id);
1827  }
1828  }
1829 
1836  public function removeConstraintsConcerningQuestion($question_id)
1837  {
1838  $ilDB = $this->db;
1839  $result = $ilDB->queryF(
1840  "SELECT constraint_fi FROM svy_qst_constraint WHERE question_fi = %s AND survey_fi = %s",
1841  array('integer','integer'),
1842  array($question_id, $this->getSurveyId())
1843  );
1844  if ($result->numRows() > 0) {
1845  $remove_constraints = array();
1846  while ($row = $ilDB->fetchAssoc($result)) {
1847  array_push($remove_constraints, $row["constraint_fi"]);
1848  }
1849  $affectedRows = $ilDB->manipulateF(
1850  "DELETE FROM svy_qst_constraint WHERE question_fi = %s AND survey_fi = %s",
1851  array('integer','integer'),
1852  array($question_id, $this->getSurveyId())
1853  );
1854  foreach ($remove_constraints as $key => $constraint_id) {
1855  $affectedRows = $ilDB->manipulateF(
1856  "DELETE FROM svy_constraint WHERE constraint_id = %s",
1857  array('integer'),
1858  array($constraint_id)
1859  );
1860  }
1861  }
1862  }
1863 
1871  public function removeQuestions($remove_questions, $remove_questionblocks)
1872  {
1873  $ilDB = $this->db;
1874 
1875  $block_sizes = array();
1876  foreach ($this->getSurveyQuestions() as $question_id => $data) {
1877  if (in_array($question_id, $remove_questions) or in_array($data["questionblock_id"], $remove_questionblocks)) {
1878  unset($this->questions[array_search($question_id, $this->questions)]);
1879  $this->removeQuestion($question_id);
1880  } elseif ($data["questionblock_id"]) {
1881  $block_sizes[$data["questionblock_id"]]++;
1882  }
1883  }
1884 
1885  // blocks with just 1 question need to be deleted
1886  foreach ($block_sizes as $block_id => $size) {
1887  if ($size < 2) {
1888  $remove_questionblocks[] = $block_id;
1889  }
1890  }
1891 
1892  foreach (array_unique($remove_questionblocks) as $questionblock_id) {
1893  $affectedRows = $ilDB->manipulateF(
1894  "DELETE FROM svy_qblk WHERE questionblock_id = %s",
1895  array('integer'),
1896  array($questionblock_id)
1897  );
1898  $affectedRows = $ilDB->manipulateF(
1899  "DELETE FROM svy_qblk_qst WHERE questionblock_fi = %s AND survey_fi = %s",
1900  array('integer','integer'),
1901  array($questionblock_id, $this->getSurveyId())
1902  );
1903  }
1904 
1905  $this->questions = array_values($this->questions);
1906  $this->saveQuestionsToDb();
1907  }
1908 
1915  public function unfoldQuestionblocks($questionblocks)
1916  {
1917  $ilDB = $this->db;
1918  foreach ($questionblocks as $index) {
1919  $affectedRows = $ilDB->manipulateF(
1920  "DELETE FROM svy_qblk WHERE questionblock_id = %s",
1921  array('integer'),
1922  array($index)
1923  );
1924  $affectedRows = $ilDB->manipulateF(
1925  "DELETE FROM svy_qblk_qst WHERE questionblock_fi = %s AND survey_fi = %s",
1926  array('integer','integer'),
1927  array($index, $this->getSurveyId())
1928  );
1929  }
1930  }
1931 
1932  public function removeQuestionFromBlock($question_id, $questionblock_id)
1933  {
1934  $ilDB = $this->db;
1935 
1936  $affectedRows = $ilDB->manipulateF(
1937  "DELETE FROM svy_qblk_qst WHERE questionblock_fi = %s AND survey_fi = %s AND question_fi = %s",
1938  array('integer','integer','integer'),
1939  array($questionblock_id, $this->getSurveyId(), $question_id)
1940  );
1941  }
1942 
1943  public function addQuestionToBlock($question_id, $questionblock_id)
1944  {
1945  $ilDB = $this->db;
1946 
1947  // see #22018
1948  if (!$this->isQuestionInAnyBlock($question_id)) {
1949  $next_id = $ilDB->nextId('svy_qblk_qst');
1950  $affectedRows = $ilDB->manipulateF(
1951  "INSERT INTO svy_qblk_qst (qblk_qst_id, survey_fi, questionblock_fi, " .
1952  "question_fi) VALUES (%s, %s, %s, %s)",
1953  array('integer', 'integer', 'integer', 'integer'),
1954  array($next_id, $this->getSurveyId(), $questionblock_id, $question_id)
1955  );
1956 
1957  $this->deleteConstraints($question_id); // #13713
1958  }
1959  }
1960 
1967  public function isQuestionInAnyBlock($a_question_fi)
1968  {
1969  global $DIC;
1970 
1971  $ilDB = $DIC->database();
1972 
1973  $set = $ilDB->query("SELECT * FROM svy_qblk_qst " .
1974  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
1975  " AND question_fi = " . $ilDB->quote($a_question_fi, "integer"));
1976  if ($rec = $ilDB->fetchAssoc($set)) {
1977  return true;
1978  }
1979  return false;
1980  }
1981 
1982 
1989  public function &getQuestionblockQuestions($questionblock_id)
1990  {
1991  $ilDB = $this->db;
1992  $titles = array();
1993  $result = $ilDB->queryF(
1994  "SELECT svy_question.title, svy_qblk_qst.question_fi, svy_qblk_qst.survey_fi FROM " .
1995  "svy_qblk, svy_qblk_qst, svy_question WHERE svy_qblk.questionblock_id = svy_qblk_qst.questionblock_fi AND " .
1996  "svy_question.question_id = svy_qblk_qst.question_fi AND svy_qblk.questionblock_id = %s",
1997  array('integer'),
1998  array($questionblock_id)
1999  );
2000  $survey_id = "";
2001  while ($row = $ilDB->fetchAssoc($result)) {
2002  $titles[$row["question_fi"]] = $row["title"];
2003  $survey_id = $row["survey_fi"];
2004  }
2005  $result = $ilDB->queryF(
2006  "SELECT question_fi, sequence FROM svy_svy_qst WHERE survey_fi = %s ORDER BY sequence",
2007  array('integer'),
2008  array($survey_id)
2009  );
2010  $resultarray = array();
2011  $counter = 1;
2012  while ($row = $ilDB->fetchAssoc($result)) {
2013  if (array_key_exists($row["question_fi"], $titles)) {
2014  $resultarray[$counter++] = $titles[$row["question_fi"]];
2015  }
2016  }
2017  return $resultarray;
2018  }
2019 
2026  public function &getQuestionblockQuestionIds($questionblock_id)
2027  {
2028  $ilDB = $this->db;
2029 
2030  // we need a correct order here, see #22011
2031  $result = $ilDB->queryF(
2032  "SELECT a.question_fi FROM svy_qblk_qst a JOIN svy_svy_qst b ON (a.question_fi = b.question_fi) " .
2033  " WHERE a.questionblock_fi = %s ORDER BY b.sequence",
2034  array("integer"),
2035  array($questionblock_id)
2036  );
2037  $ids = array();
2038  if ($result->numRows()) {
2039  while ($data = $ilDB->fetchAssoc($result)) {
2040  if (!in_array($data['question_fi'], $ids)) { // no duplicates, see #22018
2041  array_push($ids, $data['question_fi']);
2042  }
2043  }
2044  }
2045 
2046  return $ids;
2047  }
2048 
2056  public static function _getQuestionblock($questionblock_id)
2057  {
2058  global $DIC;
2059 
2060  $ilDB = $DIC->database();
2061  $result = $ilDB->queryF(
2062  "SELECT * FROM svy_qblk WHERE questionblock_id = %s",
2063  array('integer'),
2064  array($questionblock_id)
2065  );
2066  $row = $ilDB->fetchAssoc($result);
2067  return $row;
2068  }
2069 
2078  public static function _addQuestionblock($title = "", $owner = 0, $show_questiontext = true, $show_blocktitle = false)
2079  {
2080  global $DIC;
2081 
2082  $ilDB = $DIC->database();
2083  $next_id = $ilDB->nextId('svy_qblk');
2084  $ilDB->manipulateF(
2085  "INSERT INTO svy_qblk (questionblock_id, title, show_questiontext," .
2086  " show_blocktitle, owner_fi, tstamp) " .
2087  "VALUES (%s, %s, %s, %s, %s, %s)",
2088  array('integer','text','integer','integer','integer','integer'),
2089  array($next_id, $title, $show_questiontext, $show_blocktitle, $owner, time())
2090  );
2091  return $next_id;
2092  }
2093 
2101  public function createQuestionblock($title, $show_questiontext, $show_blocktitle, $questions)
2102  {
2103  $ilDB = $this->db;
2104 
2105  // if the selected questions are not in a continous selection, move all questions of the
2106  // questionblock at the position of the first selected question
2107  $this->moveQuestions($questions, $questions[0], 0);
2108 
2109  // now save the question block
2110  $ilUser = $this->user;
2111  $next_id = $ilDB->nextId('svy_qblk');
2112  $affectedRows = $ilDB->manipulateF(
2113  "INSERT INTO svy_qblk (questionblock_id, title, show_questiontext," .
2114  " show_blocktitle, owner_fi, tstamp) VALUES (%s, %s, %s, %s, %s, %s)",
2115  array('integer','text','text','text','integer','integer'),
2116  array($next_id, $title, $show_questiontext, $show_blocktitle, $ilUser->getId(), time())
2117  );
2118  if ($affectedRows) {
2119  $questionblock_id = $next_id;
2120  foreach ($questions as $index) {
2121  if (!$this->isQuestionInAnyBlock($index)) {
2122  $next_id = $ilDB->nextId('svy_qblk_qst'); // #22018
2123  $affectedRows = $ilDB->manipulateF(
2124  "INSERT INTO svy_qblk_qst (qblk_qst_id, survey_fi, questionblock_fi, " .
2125  "question_fi) VALUES (%s, %s, %s, %s)",
2126  array('integer', 'integer', 'integer', 'integer'),
2127  array($next_id, $this->getSurveyId(), $questionblock_id, $index)
2128  );
2129  $this->deleteConstraints($index);
2130  }
2131  }
2132  }
2133  }
2134 
2142  public function modifyQuestionblock($questionblock_id, $title, $show_questiontext, $show_blocktitle)
2143  {
2144  $ilDB = $this->db;
2145  $affectedRows = $ilDB->manipulateF(
2146  "UPDATE svy_qblk SET title = %s, show_questiontext = %s," .
2147  " show_blocktitle = %s WHERE questionblock_id = %s",
2148  array('text','text','text','integer'),
2149  array($title, $show_questiontext, $show_blocktitle, $questionblock_id)
2150  );
2151  }
2152 
2159  public function deleteConstraints($question_id)
2160  {
2161  $ilDB = $this->db;
2162  $result = $ilDB->queryF(
2163  "SELECT constraint_fi FROM svy_qst_constraint WHERE question_fi = %s AND survey_fi = %s",
2164  array('integer','integer'),
2165  array($question_id, $this->getSurveyId())
2166  );
2167  $constraints = array();
2168  while ($row = $ilDB->fetchAssoc($result)) {
2169  array_push($constraints, $row["constraint_fi"]);
2170  }
2171  foreach ($constraints as $constraint_id) {
2172  $this->deleteConstraint($constraint_id);
2173  }
2174  }
2175 
2183  public function deleteConstraint($constraint_id)
2184  {
2185  $ilDB = $this->db;
2186  $affectedRows = $ilDB->manipulateF(
2187  "DELETE FROM svy_constraint WHERE constraint_id = %s",
2188  array('integer'),
2189  array($constraint_id)
2190  );
2191  $affectedRows = $ilDB->manipulateF(
2192  "DELETE FROM svy_qst_constraint WHERE constraint_fi = %s",
2193  array('integer'),
2194  array($constraint_id)
2195  );
2196  }
2197 
2203  public function &getSurveyQuestions($with_answers = false)
2204  {
2205  $ilDB = $this->db;
2206  // get questionblocks
2207  $all_questions = array();
2208  $result = $ilDB->queryF(
2209  "SELECT svy_qtype.type_tag, svy_qtype.plugin, svy_question.question_id, " .
2210  "svy_svy_qst.heading FROM svy_qtype, svy_question, svy_svy_qst WHERE svy_svy_qst.survey_fi = %s AND " .
2211  "svy_svy_qst.question_fi = svy_question.question_id AND svy_question.questiontype_fi = svy_qtype.questiontype_id " .
2212  "ORDER BY svy_svy_qst.sequence",
2213  array('integer'),
2214  array($this->getSurveyId())
2215  );
2216  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
2217  while ($row = $ilDB->fetchAssoc($result)) {
2218  $add = true;
2219  if ($row["plugin"]) {
2220  if (!$this->isPluginActive($row["type_tag"])) {
2221  $add = false;
2222  }
2223  }
2224  if ($add) {
2225  $question = self::_instanciateQuestion($row["question_id"]);
2226  $questionrow = $question->getQuestionDataArray($row["question_id"]);
2227  foreach ($row as $key => $value) {
2228  $questionrow[$key] = $value;
2229  }
2230  $all_questions[$row["question_id"]] = $questionrow;
2231  $all_questions[$row["question_id"]]["usableForPrecondition"] = $question->usableForPrecondition();
2232  $all_questions[$row["question_id"]]["availableRelations"] = $question->getAvailableRelations();
2233  }
2234  }
2235  // get all questionblocks
2236  $questionblocks = array();
2237  if (count($all_questions)) {
2238  $result = $ilDB->queryF(
2239  "SELECT svy_qblk.*, svy_qblk_qst.question_fi FROM svy_qblk, svy_qblk_qst WHERE " .
2240  "svy_qblk.questionblock_id = svy_qblk_qst.questionblock_fi AND svy_qblk_qst.survey_fi = %s " .
2241  "AND " . $ilDB->in('svy_qblk_qst.question_fi', array_keys($all_questions), false, 'integer'),
2242  array('integer'),
2243  array($this->getSurveyId())
2244  );
2245  while ($row = $ilDB->fetchAssoc($result)) {
2246  $questionblocks[$row['question_fi']] = $row;
2247  }
2248  }
2249 
2250  foreach ($all_questions as $question_id => $row) {
2251  $constraints = $this->getConstraints($question_id);
2252  if (isset($questionblocks[$question_id])) {
2253  $all_questions[$question_id]["questionblock_title"] = $questionblocks[$question_id]['title'];
2254  $all_questions[$question_id]["questionblock_id"] = $questionblocks[$question_id]['questionblock_id'];
2255  $all_questions[$question_id]["constraints"] = $constraints;
2256  } else {
2257  $all_questions[$question_id]["questionblock_title"] = "";
2258  $all_questions[$question_id]["questionblock_id"] = "";
2259  $all_questions[$question_id]["constraints"] = $constraints;
2260  }
2261  if ($with_answers) {
2262  $answers = array();
2263  $result = $ilDB->queryF(
2264  "SELECT svy_variable.*, svy_category.title FROM svy_variable, svy_category " .
2265  "WHERE svy_variable.question_fi = %s AND svy_variable.category_fi = svy_category.category_id " .
2266  "ORDER BY sequence ASC",
2267  array('integer'),
2268  array($question_id)
2269  );
2270  if ($result->numRows() > 0) {
2271  while ($data = $ilDB->fetchAssoc($result)) {
2272  array_push($answers, $data["title"]);
2273  }
2274  }
2275  $all_questions[$question_id]["answers"] = $answers;
2276  }
2277  }
2278  return $all_questions;
2279  }
2280 
2287  public function setObligatoryStates($obligatory_questions)
2288  {
2289  $ilDB = $this->db;
2290  $result = $ilDB->queryF(
2291  "SELECT * FROM svy_svy_qst WHERE survey_fi = %s",
2292  array('integer'),
2293  array($this->getSurveyId())
2294  );
2295  if ($result->numRows()) {
2296  while ($row = $ilDB->fetchAssoc($result)) {
2297  if (!array_key_exists($row["question_fi"], $obligatory_questions)) {
2298  $obligatory_questions[$row["question_fi"]] = 0;
2299  }
2300  }
2301  }
2302 
2303  // set the obligatory states in the database
2304  foreach ($obligatory_questions as $question_fi => $obligatory) {
2305  // #12420
2306  $ilDB->manipulate("UPDATE svy_question" .
2307  " SET obligatory = " . $ilDB->quote($obligatory, "integer") .
2308  " WHERE question_id = " . $ilDB->quote($question_fi, "integer"));
2309  }
2310  }
2311 
2317  public function &getSurveyPages()
2318  {
2319  $ilDB = $this->db;
2320  // get questionblocks
2321  $all_questions = array();
2322  $result = $ilDB->queryF(
2323  "SELECT svy_question.*, svy_qtype.type_tag, svy_svy_qst.heading FROM " .
2324  "svy_question, svy_qtype, svy_svy_qst WHERE svy_svy_qst.survey_fi = %s AND " .
2325  "svy_svy_qst.question_fi = svy_question.question_id AND svy_question.questiontype_fi = svy_qtype.questiontype_id " .
2326  "ORDER BY svy_svy_qst.sequence",
2327  array('integer'),
2328  array($this->getSurveyId())
2329  );
2330  while ($row = $ilDB->fetchAssoc($result)) {
2331  $all_questions[$row["question_id"]] = $row;
2332  }
2333  // get all questionblocks
2334  $questionblocks = array();
2335  if (count($all_questions)) {
2336  $result = $ilDB->queryF(
2337  "SELECT svy_qblk.*, svy_qblk_qst.question_fi FROM svy_qblk, svy_qblk_qst " .
2338  "WHERE svy_qblk.questionblock_id = svy_qblk_qst.questionblock_fi AND svy_qblk_qst.survey_fi = %s " .
2339  "AND " . $ilDB->in('svy_qblk_qst.question_fi', array_keys($all_questions), false, 'integer'),
2340  array('integer'),
2341  array($this->getSurveyId())
2342  );
2343  while ($row = $ilDB->fetchAssoc($result)) {
2344  $questionblocks[$row['question_fi']] = $row;
2345  }
2346  }
2347 
2348  $all_pages = array();
2349  $pageindex = -1;
2350  $currentblock = "";
2351  foreach ($all_questions as $question_id => $row) {
2352  $constraints = array();
2353  if (isset($questionblocks[$question_id])) {
2354  if (!$currentblock or ($currentblock != $questionblocks[$question_id]['questionblock_id'])) {
2355  $pageindex++;
2356  }
2357  $all_questions[$question_id]['page'] = $pageindex;
2358  $all_questions[$question_id]["questionblock_title"] = $questionblocks[$question_id]['title'];
2359  $all_questions[$question_id]["questionblock_id"] = $questionblocks[$question_id]['questionblock_id'];
2360  $all_questions[$question_id]["questionblock_show_questiontext"] = $questionblocks[$question_id]['show_questiontext'];
2361  $all_questions[$question_id]["questionblock_show_blocktitle"] = $questionblocks[$question_id]['show_blocktitle'];
2362  $currentblock = $questionblocks[$question_id]['questionblock_id'];
2363  $constraints = $this->getConstraints($question_id);
2364  $all_questions[$question_id]["constraints"] = $constraints;
2365  } else {
2366  $pageindex++;
2367  $all_questions[$question_id]['page'] = $pageindex;
2368  $all_questions[$question_id]["questionblock_title"] = "";
2369  $all_questions[$question_id]["questionblock_id"] = "";
2370  $all_questions[$question_id]["questionblock_show_questiontext"] = 1;
2371  $all_questions[$question_id]["questionblock_show_blocktitle"] = 1;
2372  $currentblock = "";
2373  $constraints = $this->getConstraints($question_id);
2374  $all_questions[$question_id]["constraints"] = $constraints;
2375  }
2376  if (!isset($all_pages[$pageindex])) {
2377  $all_pages[$pageindex] = array();
2378  }
2379  array_push($all_pages[$pageindex], $all_questions[$question_id]);
2380  }
2381  // calculate position percentage for every page
2382  $max = count($all_pages);
2383  $counter = 1;
2384  foreach ($all_pages as $index => $block) {
2385  foreach ($block as $blockindex => $question) {
2386  $all_pages[$index][$blockindex]["position"] = $counter / $max;
2387  }
2388  $counter++;
2389  }
2390 
2391  return $all_pages;
2392  }
2393 
2402  public function getNextPage($active_page_question_id, $direction)
2403  {
2404  $foundpage = -1;
2405  $pages =&$this->getSurveyPages();
2406  if (strcmp($active_page_question_id, "") == 0) {
2407  return $pages[0];
2408  }
2409  foreach ($pages as $key => $question_array) {
2410  foreach ($question_array as $question) {
2411  if ($active_page_question_id == $question["question_id"]) {
2412  $foundpage = $key;
2413  }
2414  }
2415  }
2416  if ($foundpage == -1) {
2417  // error: page not found
2418  } else {
2419  $foundpage += $direction;
2420  if ($foundpage < 0) {
2421  return 0;
2422  }
2423  if ($foundpage >= count($pages)) {
2424  return 1;
2425  }
2426  return $pages[$foundpage];
2427  }
2428  }
2429 
2436  public function &getAvailableQuestionpools($use_obj_id = false, $could_be_offline = false, $showPath = false, $permission = "read")
2437  {
2438  include_once "./Modules/SurveyQuestionPool/classes/class.ilObjSurveyQuestionPool.php";
2439  return ilObjSurveyQuestionPool::_getAvailableQuestionpools($use_obj_id, $could_be_offline, $showPath, $permission);
2440  }
2441 
2447  public function getPrecondition($id)
2448  {
2449  $ilDB = $this->db;
2450 
2451  $result_array = array();
2452  $result = $ilDB->queryF(
2453  "SELECT svy_constraint.*, svy_relation.*, svy_qst_constraint.question_fi ref_question_fi FROM svy_qst_constraint, svy_constraint, " .
2454  "svy_relation WHERE svy_constraint.relation_fi = svy_relation.relation_id AND " .
2455  "svy_qst_constraint.constraint_fi = svy_constraint.constraint_id AND svy_constraint.constraint_id = %s",
2456  array('integer'),
2457  array($id)
2458  );
2459  $pc = array();
2460  if ($result->numRows()) {
2461  $pc = $ilDB->fetchAssoc($result);
2462  }
2463  return $pc;
2464  }
2465 
2471  public function getConstraints($question_id)
2472  {
2473  $ilDB = $this->db;
2474 
2475  $result_array = array();
2476  $result = $ilDB->queryF(
2477  "SELECT svy_constraint.*, svy_relation.* FROM svy_qst_constraint, svy_constraint, svy_relation " .
2478  "WHERE svy_constraint.relation_fi = svy_relation.relation_id AND " .
2479  "svy_qst_constraint.constraint_fi = svy_constraint.constraint_id AND svy_qst_constraint.question_fi = %s " .
2480  "AND svy_qst_constraint.survey_fi = %s",
2481  array('integer','integer'),
2482  array($question_id, $this->getSurveyId())
2483  );
2484  while ($row = $ilDB->fetchAssoc($result)) {
2485  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
2486  $question_type = SurveyQuestion::_getQuestionType($row["question_fi"]);
2487  SurveyQuestion::_includeClass($question_type);
2488  $question = new $question_type();
2489  $question->loadFromDb($row["question_fi"]);
2490  $valueoutput = $question->getPreconditionValueOutput($row["value"]);
2491  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));
2492  }
2493  return $result_array;
2494  }
2495 
2501  public static function _getConstraints($survey_id)
2502  {
2503  global $DIC;
2504 
2505  $ilDB = $DIC->database();
2506  $result_array = array();
2507  $result = $ilDB->queryF(
2508  "SELECT svy_qst_constraint.question_fi as for_question, svy_constraint.*, svy_relation.* " .
2509  "FROM svy_qst_constraint, svy_constraint, svy_relation WHERE svy_constraint.relation_fi = svy_relation.relation_id " .
2510  "AND svy_qst_constraint.constraint_fi = svy_constraint.constraint_id AND svy_qst_constraint.survey_fi = %s",
2511  array('integer'),
2512  array($survey_id)
2513  );
2514  while ($row = $ilDB->fetchAssoc($result)) {
2515  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']));
2516  }
2517  return $result_array;
2518  }
2519 
2520 
2526  public function &getVariables($question_id)
2527  {
2528  $ilDB = $this->db;
2529 
2530  $result_array = array();
2531  $result = $ilDB->queryF(
2532  "SELECT svy_variable.*, svy_category.title FROM svy_variable LEFT JOIN " .
2533  "svy_category ON svy_variable.category_fi = svy_category.category_id WHERE svy_variable.question_fi = %s " .
2534  "ORDER BY svy_variable.sequence",
2535  array('integer'),
2536  array($question_id)
2537  );
2538  while ($row = $ilDB->fetchObject($result)) {
2539  $result_array[$row->sequence] = $row;
2540  }
2541  return $result_array;
2542  }
2543 
2552  public function addConstraint($if_question_id, $relation, $value, $conjunction)
2553  {
2554  $ilDB = $this->db;
2555 
2556  $next_id = $ilDB->nextId('svy_constraint');
2557  $affectedRows = $ilDB->manipulateF(
2558  "INSERT INTO svy_constraint (constraint_id, question_fi, relation_fi, value, conjunction) VALUES " .
2559  "(%s, %s, %s, %s, %s)",
2560  array('integer','integer','integer','float', 'integer'),
2561  array($next_id, $if_question_id, $relation, $value, $conjunction)
2562  );
2563  if ($affectedRows) {
2564  return $next_id;
2565  } else {
2566  return null;
2567  }
2568  }
2569 
2570 
2577  public function addConstraintToQuestion($to_question_id, $constraint_id)
2578  {
2579  $ilDB = $this->db;
2580 
2581  $next_id = $ilDB->nextId('svy_qst_constraint');
2582  $affectedRows = $ilDB->manipulateF(
2583  "INSERT INTO svy_qst_constraint (question_constraint_id, survey_fi, question_fi, " .
2584  "constraint_fi) VALUES (%s, %s, %s, %s)",
2585  array('integer','integer','integer','integer'),
2586  array($next_id, $this->getSurveyId(), $to_question_id, $constraint_id)
2587  );
2588  }
2589 
2600  public function updateConstraint($precondition_id, $if_question_id, $relation, $value, $conjunction)
2601  {
2602  $ilDB = $this->db;
2603  $affectedRows = $ilDB->manipulateF(
2604  "UPDATE svy_constraint SET question_fi = %s, relation_fi = %s, value = %s, conjunction = %s " .
2605  "WHERE constraint_id = %s",
2606  array('integer','integer','float','integer','integer'),
2607  array($if_question_id, $relation, $value, $conjunction, $precondition_id)
2608  );
2609  }
2610 
2611  public function updateConjunctionForQuestions($questions, $conjunction)
2612  {
2613  $ilDB = $this->db;
2614  foreach ($questions as $question_id) {
2615  $affectedRows = $ilDB->manipulateF(
2616  "UPDATE svy_constraint SET conjunction = %s " .
2617  "WHERE constraint_id IN (SELECT constraint_fi FROM svy_qst_constraint WHERE svy_qst_constraint.question_fi = %s)",
2618  array('integer','integer'),
2619  array($conjunction, $question_id)
2620  );
2621  }
2622  }
2623 
2629  public function getAllRelations($short_as_key = false)
2630  {
2631  $ilDB = $this->db;
2632 
2633  // #7987
2634  $custom_order = array("equal", "not_equal", "less", "less_or_equal", "more", "more_or_equal");
2635  $custom_order = array_flip($custom_order);
2636 
2637  $result_array = array();
2638  $result = $ilDB->query("SELECT * FROM svy_relation");
2639  while ($row = $ilDB->fetchAssoc($result)) {
2640  if ($short_as_key) {
2641  $result_array[$row["shortname"]] = array("short" => $row["shortname"], "long" => $row["longname"], "id" => $row["relation_id"], "order" => $custom_order[$row["longname"]]);
2642  } else {
2643  $result_array[$row["relation_id"]] = array("short" => $row["shortname"], "long" => $row["longname"], "order" => $custom_order[$row["longname"]]);
2644  }
2645  }
2646 
2647  $result_array = ilUtil::sortArray($result_array, "order", "ASC", true, true);
2648  foreach ($result_array as $idx => $item) {
2649  unset($result_array[$idx]["order"]);
2650  }
2651 
2652  return $result_array;
2653  }
2654 
2658  public function disinviteAllUsers()
2659  {
2660  $ilDB = $this->db;
2661  $result = $ilDB->queryF(
2662  "SELECT user_fi FROM svy_inv_usr WHERE survey_fi = %s",
2663  array('integer'),
2664  array($this->getSurveyId())
2665  );
2666  while ($row = $ilDB->fetchAssoc($result)) {
2667  $this->disinviteUser($row['user_fi']);
2668  }
2669  }
2670 
2676  public function disinviteUser($user_id)
2677  {
2678  $ilDB = $this->db;
2679 
2680  $affectedRows = $ilDB->manipulateF(
2681  "DELETE FROM svy_inv_usr WHERE survey_fi = %s AND user_fi = %s",
2682  array('integer','integer'),
2683  array($this->getSurveyId(), $user_id)
2684  );
2685  include_once './Services/User/classes/class.ilObjUser.php';
2686  ilObjUser::_dropDesktopItem($user_id, $this->getRefId(), "svy");
2687  }
2688 
2695  public function inviteUser($user_id)
2696  {
2697  $ilDB = $this->db;
2698 
2699  $result = $ilDB->queryF(
2700  "SELECT user_fi FROM svy_inv_usr WHERE user_fi = %s AND survey_fi = %s",
2701  array('integer','integer'),
2702  array($user_id, $this->getSurveyId())
2703  );
2704  if ($result->numRows() < 1) {
2705  $next_id = $ilDB->nextId('svy_inv_usr');
2706  $affectedRows = $ilDB->manipulateF(
2707  "INSERT INTO svy_inv_usr (invited_user_id, survey_fi, user_fi, tstamp) " .
2708  "VALUES (%s, %s, %s, %s)",
2709  array('integer','integer','integer','integer'),
2710  array($next_id, $this->getSurveyId(), $user_id, time())
2711  );
2712  }
2713  if ($this->getInvitation() == self::INVITATION_ON) {
2714  include_once './Services/User/classes/class.ilObjUser.php';
2715  ilObjUser::_addDesktopItem($user_id, $this->getRefId(), "svy");
2716  }
2717  }
2718 
2725  public function &getInvitedUsers()
2726  {
2727  $ilDB = $this->db;
2728 
2729  $result_array = array();
2730  $result = $ilDB->queryF(
2731  "SELECT user_fi FROM svy_inv_usr WHERE survey_fi = %s",
2732  array('integer'),
2733  array($this->getSurveyId())
2734  );
2735  while ($row = $ilDB->fetchAssoc($result)) {
2736  array_push($result_array, $row["user_fi"]);
2737  }
2738  return $result_array;
2739  }
2740 
2748  public function deleteWorkingData($question_id, $active_id)
2749  {
2750  $ilDB = $this->db;
2751 
2752  $affectedRows = $ilDB->manipulateF(
2753  "DELETE FROM svy_answer WHERE question_fi = %s AND active_fi = %s",
2754  array('integer','integer'),
2755  array($question_id, $active_id)
2756  );
2757  }
2758 
2767  public function loadWorkingData($question_id, $active_id)
2768  {
2769  $ilDB = $this->db;
2770  $result_array = array();
2771  $result = $ilDB->queryF(
2772  "SELECT * FROM svy_answer WHERE question_fi = %s AND active_fi = %s",
2773  array('integer','integer'),
2774  array($question_id, $active_id)
2775  );
2776  if ($result->numRows() >= 1) {
2777  while ($row = $ilDB->fetchAssoc($result)) {
2778  array_push($result_array, $row);
2779  }
2780  return $result_array;
2781  } else {
2782  return $result_array;
2783  }
2784  }
2785 
2792  public function startSurvey($user_id, $anonymous_id, $appraisee_id)
2793  {
2794  $ilDB = $this->db;
2795 
2796  if ($this->getAnonymize() && (strlen($anonymous_id) == 0)) {
2797  return;
2798  }
2799 
2800  if (strcmp($user_id, "") == 0) {
2801  if ($user_id == ANONYMOUS_USER_ID) {
2802  $user_id = 0;
2803  }
2804  }
2805  $next_id = $ilDB->nextId('svy_finished');
2806  $affectedRows = $ilDB->manipulateF(
2807  "INSERT INTO svy_finished (finished_id, survey_fi, user_fi, anonymous_id, state, tstamp, appr_id) " .
2808  "VALUES (%s, %s, %s, %s, %s, %s, %s)",
2809  array('integer','integer','integer','text','text','integer','integer'),
2810  array($next_id, $this->getSurveyId(), $user_id, $anonymous_id, 0, time(), $appraisee_id)
2811  );
2812  return $next_id;
2813  }
2814 
2821  public function finishSurvey($finished_id)
2822  {
2823  $ilDB = $this->db;
2824 
2825  $ilDB->manipulateF(
2826  "UPDATE svy_finished SET state = %s, tstamp = %s" .
2827  " WHERE survey_fi = %s AND finished_id = %s",
2828  array('text','integer','integer','integer'),
2829  array(1, time(), $this->getSurveyId(), $finished_id)
2830  );
2831 
2832  $this->checkTutorNotification();
2833  }
2834 
2842  public function setPage($finished_id, $page_id)
2843  {
2844  $ilDB = $this->db;
2845 
2846  $affectedRows = $ilDB->manipulateF(
2847  "UPDATE svy_finished SET lastpage = %s WHERE finished_id = %s",
2848  array('integer','integer'),
2849  array(($page_id) ? $page_id : 0, $finished_id)
2850  );
2851  }
2852 
2853  public function sendNotificationMail($user_id, $anonymize_id, $appr_id)
2854  {
2855  include_once "./Services/User/classes/class.ilObjUser.php";
2856  include_once "./Services/User/classes/class.ilUserUtil.php";
2857 
2858  // #12755
2859  $placeholders = array(
2860  "FIRST_NAME" => "firstname",
2861  "LAST_NAME" => "lastname",
2862  "LOGIN" => "login",
2863  // old style
2864  "firstname" => "firstname"
2865  );
2866 
2867  $recipients = preg_split('/,/', $this->mailaddresses);
2868  foreach ($recipients as $recipient) {
2869  // #11298
2870  include_once "./Services/Notification/classes/class.ilSystemNotification.php";
2871  $ntf = new ilSystemNotification();
2872  $ntf->setLangModules(array("survey"));
2873  $ntf->setRefId($this->getRefId());
2874  $ntf->setSubjectLangId('finished_mail_subject');
2875 
2876  $messagetext = $this->mailparticipantdata;
2877  if (trim($messagetext)) {
2878  if (!$this->hasAnonymizedResults()) {
2879  $data = ilObjUser::_getUserData(array($user_id));
2880  $data = $data[0];
2881  }
2882  foreach ($placeholders as $key => $mapping) {
2883  if ($this->hasAnonymizedResults()) { // #16480
2884  $messagetext = str_replace('[' . $key . ']', '', $messagetext);
2885  } else {
2886  $messagetext = str_replace('[' . $key . ']', trim($data[$mapping]), $messagetext);
2887  }
2888  }
2889  $ntf->setIntroductionDirect($messagetext);
2890  } else {
2891  $ntf->setIntroductionLangId('survey_notification_finished_introduction');
2892  }
2893 
2894  // 360°? add appraisee data
2895  if ($appr_id) {
2896  $ntf->addAdditionalInfo(
2897  'survey_360_appraisee',
2899  );
2900  }
2901 
2902  $active_id = $this->getActiveID($user_id, $anonymize_id, $appr_id);
2903  $ntf->addAdditionalInfo(
2904  'results',
2905  $this->getParticipantTextResults($active_id),
2906  true
2907  );
2908 
2909  $ntf->setGotoLangId('survey_notification_tutor_link');
2910  $ntf->setReasonLangId('survey_notification_finished_reason');
2911 
2912  $ntf->sendMail(array($recipient), null, null);
2913  }
2914  }
2915 
2916  protected function getParticipantTextResults($active_id)
2917  {
2918  $textresult = "";
2919  $userResults =&$this->getUserSpecificResults(array($active_id));
2920  $questions =&$this->getSurveyQuestions(true);
2921  $questioncounter = 1;
2922  foreach ($questions as $question_id => $question_data) {
2923  $textresult .= $questioncounter++ . ". " . $question_data["title"] . "\n";
2924  $found = $userResults[$question_id][$active_id];
2925  $text = "";
2926  if (is_array($found)) {
2927  $text = implode("\n", $found);
2928  } else {
2929  $text = $found;
2930  }
2931  if (strlen($text) == 0) {
2932  $text = self::getSurveySkippedValue();
2933  }
2934  $text = str_replace("<br />", "\n", $text);
2935  $textresult .= $text . "\n\n";
2936  }
2937  return $textresult;
2938  }
2939 
2947  public function isSurveyStarted($user_id, $anonymize_id, $appr_id = 0)
2948  {
2949  $ilDB = $this->db;
2950 
2951  // #15031 - should not matter if code was used by registered or anonymous (each code must be unique)
2952  if ($anonymize_id) {
2953  $result = $ilDB->queryF(
2954  "SELECT * FROM svy_finished" .
2955  " WHERE survey_fi = %s AND anonymous_id = %s AND appr_id = %s",
2956  array('integer','text','integer'),
2957  array($this->getSurveyId(), $anonymize_id, $appr_id)
2958  );
2959  } else {
2960  $result = $ilDB->queryF(
2961  "SELECT * FROM svy_finished" .
2962  " WHERE survey_fi = %s AND user_fi = %s AND appr_id = %s",
2963  array('integer','integer','integer'),
2964  array($this->getSurveyId(), $user_id, $appr_id)
2965  );
2966  }
2967  if ($result->numRows() == 0) {
2968  return false;
2969  } else {
2970  $row = $ilDB->fetchAssoc($result);
2971  // yes, we are doing it this way
2972  $_SESSION["finished_id"][$this->getId()] = $row["finished_id"];
2973 
2974  return (int) $row["state"];
2975  }
2976  }
2977 
2985  public function getActiveID($user_id, $anonymize_id, $appr_id)
2986  {
2987  $ilDB = $this->db;
2988 
2989  // see self::isSurveyStarted()
2990 
2991  // #15031 - should not matter if code was used by registered or anonymous (each code must be unique)
2992  if ($anonymize_id) {
2993  $result = $ilDB->queryF(
2994  "SELECT finished_id FROM svy_finished" .
2995  " WHERE survey_fi = %s AND anonymous_id = %s AND appr_id = %s",
2996  array('integer','text','integer'),
2997  array($this->getSurveyId(), $anonymize_id, $appr_id)
2998  );
2999  } else {
3000  $result = $ilDB->queryF(
3001  "SELECT finished_id FROM svy_finished" .
3002  " WHERE survey_fi = %s AND user_fi = %s AND appr_id = %s",
3003  array('integer','integer','integer'),
3004  array($this->getSurveyId(), $user_id, $appr_id)
3005  );
3006  }
3007  if ($result->numRows() == 0) {
3008  return false;
3009  } else {
3010  $row = $ilDB->fetchAssoc($result);
3011  return $row["finished_id"];
3012  }
3013  }
3014 
3022  public function getLastActivePage($active_id)
3023  {
3024  $ilDB = $this->db;
3025  $result = $ilDB->queryF(
3026  "SELECT lastpage FROM svy_finished WHERE finished_id = %s",
3027  array('integer'),
3028  array($active_id)
3029  );
3030  if ($result->numRows() == 0) {
3031  return "";
3032  } else {
3033  $row = $ilDB->fetchAssoc($result);
3034  return ($row["lastpage"]) ? $row["lastpage"] : '';
3035  }
3036  }
3037 
3046  public function checkConstraint($constraint_data, $working_data)
3047  {
3048  if (count($working_data) == 0) {
3049  return 0;
3050  }
3051 
3052  if ((count($working_data) == 1) and (strcmp($working_data[0]["value"], "") == 0)) {
3053  return 0;
3054  }
3055 
3056  $found = false;
3057  foreach ($working_data as $data) {
3058  switch ($constraint_data["short"]) {
3059  case "<":
3060  if ($data["value"] < $constraint_data["value"]) {
3061  $found = true;
3062  }
3063  break;
3064 
3065  case "<=":
3066  if ($data["value"] <= $constraint_data["value"]) {
3067  $found = true;
3068  }
3069  break;
3070 
3071  case "=":
3072  if ($data["value"] == $constraint_data["value"]) {
3073  $found = true;
3074  }
3075  break;
3076 
3077  case "<>":
3078  if ($data["value"] <> $constraint_data["value"]) {
3079  $found = true;
3080  }
3081  break;
3082 
3083  case ">=":
3084  if ($data["value"] >= $constraint_data["value"]) {
3085  $found = true;
3086  }
3087  break;
3088 
3089  case ">":
3090  if ($data["value"] > $constraint_data["value"]) {
3091  $found = true;
3092  }
3093  break;
3094  }
3095  if ($found) {
3096  break;
3097  }
3098  }
3099 
3100  return (int) $found;
3101  }
3102 
3103  public static function _hasDatasets($survey_id)
3104  {
3105  global $DIC;
3106 
3107  $ilDB = $DIC->database();
3108 
3109  $result = $ilDB->queryF(
3110  "SELECT finished_id FROM svy_finished WHERE survey_fi = %s",
3111  array('integer'),
3112  array($survey_id)
3113  );
3114  return ($result->numRows()) ? true : false;
3115  }
3116 
3123  public function &getSurveyFinishedIds()
3124  {
3125  $ilDB = $this->db;
3126  $ilLog = $this->log;
3127 
3128  $users = array();
3129  $result = $ilDB->queryF(
3130  "SELECT * FROM svy_finished WHERE survey_fi = %s",
3131  array('integer'),
3132  array($this->getSurveyId())
3133  );
3134  if ($result->numRows()) {
3135  while ($row = $ilDB->fetchAssoc($result)) {
3136  array_push($users, $row["finished_id"]);
3137  }
3138  }
3139  return $users;
3140  }
3141 
3148  public function getUserSpecificResults($finished_ids)
3149  {
3150  $evaluation = array();
3151 
3152  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
3153  foreach (array_keys($this->getSurveyQuestions()) as $question_id) {
3154  // get question instance
3155  $question_type = SurveyQuestion::_getQuestionType($question_id);
3156  SurveyQuestion::_includeClass($question_type);
3157  $question = new $question_type();
3158  $question->loadFromDb($question_id);
3159 
3160  $q_eval = SurveyQuestion::_instanciateQuestionEvaluation($question_id, $finished_ids);
3161  $q_res = $q_eval->getResults();
3162 
3163  $data = array();
3164  foreach ($finished_ids as $user_id) {
3165  $data[$user_id] = $q_eval->parseUserSpecificResults($q_res, $user_id);
3166  }
3167 
3168  $evaluation[$question_id] = $data;
3169  }
3170 
3171  return $evaluation;
3172  }
3173 
3181  public function getUserDataFromActiveId($active_id, $force_non_anonymous = false)
3182  {
3183  $ilDB = $this->db;
3184 
3185  $surveySetting = new ilSetting("survey");
3186  $use_anonymous_id = array_key_exists("use_anonymous_id", $_GET) ? $_GET["use_anonymous_id"] : $surveySetting->get("use_anonymous_id");
3187  $result = $ilDB->queryF(
3188  "SELECT * FROM svy_finished WHERE finished_id = %s",
3189  array('integer'),
3190  array($active_id)
3191  );
3192  $row = array();
3193  $foundrows = $result->numRows();
3194  if ($foundrows) {
3195  $row = $ilDB->fetchAssoc($result);
3196  }
3197  $name = ($use_anonymous_id) ? $row["anonymous_id"] : $this->lng->txt("anonymous");
3198  $userdata = array(
3199  "fullname" => $name,
3200  "sortname" => $name,
3201  "firstname" => "",
3202  "lastname" => "",
3203  "login" => "",
3204  "gender" => "",
3205  "active_id" => "$active_id"
3206  );
3207  if ($foundrows) {
3208  if (($row["user_fi"] > 0) &&
3209  (($row["user_fi"] != ANONYMOUS_USER_ID &&
3210  !$this->hasAnonymizedResults() &&
3211  !$this->get360Mode()) || // 360° uses ANONYMIZE_CODE_ALL which is wrong - see ilObjSurveyGUI::afterSave()
3212  (bool) $force_non_anonymous)) {
3213  include_once './Services/User/classes/class.ilObjUser.php';
3214  if (strlen(ilObjUser::_lookupLogin($row["user_fi"])) == 0) {
3215  $userdata["fullname"] = $userdata["sortname"] = $this->lng->txt("deleted_user");
3216  } else {
3217  $user = new ilObjUser($row["user_fi"]);
3218  $userdata["fullname"] = $user->getFullname();
3219  $gender = $user->getGender();
3220  if (strlen($gender) == 1) {
3221  $gender = $this->lng->txt("gender_$gender");
3222  }
3223  $userdata["gender"] = $gender;
3224  $userdata["firstname"] = $user->getFirstname();
3225  $userdata["lastname"] = $user->getLastname();
3226  $userdata["sortname"] = $user->getLastname() . ", " . $user->getFirstname();
3227  $userdata["login"] = $user->getLogin();
3228  }
3229  }
3230  }
3231  return $userdata;
3232  }
3233 
3243  public function &getEvaluationByUser($questions, $active_id)
3244  {
3245  $ilDB = $this->db;
3246 
3247  // collect all answers
3248  $answers = array();
3249  $result = $ilDB->queryF(
3250  "SELECT * FROM svy_answer WHERE active_fi = %s",
3251  array('integer'),
3252  array($active_id)
3253  );
3254  while ($row = $ilDB->fetchAssoc($result)) {
3255  if (!is_array($answers[$row["question_fi"]])) {
3256  $answers[$row["question_fi"]] = array();
3257  }
3258  array_push($answers[$row["question_fi"]], $row);
3259  }
3260  $userdata = $this->getUserDataFromActiveId($active_id);
3261  $resultset = array(
3262  "name" => $userdata["fullname"],
3263  "firstname" => $userdata["firstname"],
3264  "lastname" => $userdata["lastname"],
3265  "login" => $userdata["login"],
3266  "gender" => $userdata["gender"],
3267  "answers" => array()
3268  );
3269  foreach ($questions as $key => $question) {
3270  if (array_key_exists($key, $answers)) {
3271  $resultset["answers"][$key] = $answers[$key];
3272  } else {
3273  $resultset["answers"][$key] = array();
3274  }
3275  sort($resultset["answers"][$key]);
3276  }
3277  return $resultset;
3278  }
3279 
3285  public function getQuestionsTable($arrFilter)
3286  {
3287  $ilUser = $this->user;
3288  $ilDB = $this->db;
3289  $where = "";
3290  if (is_array($arrFilter)) {
3291  if (array_key_exists('title', $arrFilter) && strlen($arrFilter['title'])) {
3292  $where .= " AND " . $ilDB->like('svy_question.title', 'text', "%%" . $arrFilter['title'] . "%%");
3293  }
3294  if (array_key_exists('description', $arrFilter) && strlen($arrFilter['description'])) {
3295  $where .= " AND " . $ilDB->like('svy_question.description', 'text', "%%" . $arrFilter['description'] . "%%");
3296  }
3297  if (array_key_exists('author', $arrFilter) && strlen($arrFilter['author'])) {
3298  $where .= " AND " . $ilDB->like('svy_question.author', 'text', "%%" . $arrFilter['author'] . "%%");
3299  }
3300  if (array_key_exists('type', $arrFilter) && strlen($arrFilter['type'])) {
3301  $where .= " AND svy_qtype.type_tag = " . $ilDB->quote($arrFilter['type'], 'text');
3302  }
3303  if (array_key_exists('spl', $arrFilter) && strlen($arrFilter['spl'])) {
3304  $where .= " AND svy_question.obj_fi = " . $ilDB->quote($arrFilter['spl'], 'integer');
3305  }
3306  }
3307 
3308  $spls =&$this->getAvailableQuestionpools($use_obj_id = true, $could_be_offline = false, $showPath = false);
3309  $forbidden = "";
3310  $forbidden = " AND " . $ilDB->in('svy_question.obj_fi', array_keys($spls), false, 'integer');
3311  $forbidden .= " AND svy_question.complete = " . $ilDB->quote("1", 'text');
3312  $existing = "";
3313  $existing_questions =&$this->getExistingQuestions();
3314  if (count($existing_questions)) {
3315  $existing = " AND " . $ilDB->in('svy_question.question_id', $existing_questions, true, 'integer');
3316  }
3317 
3318  include_once "./Modules/SurveyQuestionPool/classes/class.ilObjSurveyQuestionPool.php";
3320 
3321  $query_result = $ilDB->query("SELECT svy_question.*, svy_qtype.type_tag, svy_qtype.plugin, object_reference.ref_id" .
3322  " FROM svy_question, svy_qtype, object_reference" .
3323  " WHERE svy_question.original_id IS NULL" . $forbidden . $existing .
3324  " AND svy_question.obj_fi = object_reference.obj_id AND svy_question.tstamp > 0" .
3325  " AND svy_question.questiontype_fi = svy_qtype.questiontype_id " . $where);
3326 
3327  $rows = array();
3328  if ($query_result->numRows()) {
3329  while ($row = $ilDB->fetchAssoc($query_result)) {
3330  if (array_key_exists('spl_txt', $arrFilter) && strlen($arrFilter['spl_txt'])) {
3331  if (!stristr($spls[$row["obj_fi"]], $arrFilter['spl_txt'])) {
3332  continue;
3333  }
3334  }
3335 
3336  $row['ttype'] = $trans[$row['type_tag']];
3337  if ($row["plugin"]) {
3338  if ($this->isPluginActive($row["type_tag"])) {
3339  array_push($rows, $row);
3340  }
3341  } else {
3342  array_push($rows, $row);
3343  }
3344  }
3345  }
3346  return $rows;
3347  }
3348 
3354  public function getQuestionblocksTable($arrFilter)
3355  {
3356  $ilUser = $this->user;
3357  $ilDB = $this->db;
3358 
3359  $where = "";
3360  if (is_array($arrFilter)) {
3361  if (array_key_exists('title', $arrFilter) && strlen($arrFilter['title'])) {
3362  $where .= " AND " . $ilDB->like('svy_qblk.title', 'text', "%%" . $arrFilter['title'] . "%%");
3363  }
3364  }
3365 
3366  $query_result = $ilDB->query("SELECT svy_qblk.*, svy_svy.obj_fi FROM svy_qblk , svy_qblk_qst, svy_svy WHERE " .
3367  "svy_qblk.questionblock_id = svy_qblk_qst.questionblock_fi AND svy_svy.survey_id = svy_qblk_qst.survey_fi " .
3368  "$where GROUP BY svy_qblk.questionblock_id, svy_qblk.title, svy_qblk.show_questiontext, svy_qblk.show_blocktitle, " .
3369  "svy_qblk.owner_fi, svy_qblk.tstamp, svy_svy.obj_fi");
3370  $rows = array();
3371  if ($query_result->numRows()) {
3372  $survey_ref_ids = ilUtil::_getObjectsByOperations("svy", "write");
3373  $surveytitles = array();
3374  foreach ($survey_ref_ids as $survey_ref_id) {
3375  $survey_id = ilObject::_lookupObjId($survey_ref_id);
3376  $surveytitles[$survey_id] = ilObject::_lookupTitle($survey_id);
3377  }
3378  while ($row = $ilDB->fetchAssoc($query_result)) {
3379  $questions_array =&$this->getQuestionblockQuestions($row["questionblock_id"]);
3380  $counter = 1;
3381  foreach ($questions_array as $key => $value) {
3382  $questions_array[$key] = "$counter. $value";
3383  $counter++;
3384  }
3385  if (strlen($surveytitles[$row["obj_fi"]])) { // only questionpools which are not in trash
3386  $rows[$row["questionblock_id"]] = array(
3387  "questionblock_id" => $row["questionblock_id"],
3388  "title" => $row["title"],
3389  "svy" => $surveytitles[$row["obj_fi"]],
3390  "contains" => join($questions_array, ", "),
3391  "owner" => $row["owner_fi"]
3392  );
3393  }
3394  }
3395  }
3396  return $rows;
3397  }
3398 
3405  public function toXML()
3406  {
3407  include_once("./Services/Xml/classes/class.ilXmlWriter.php");
3408  $a_xml_writer = new ilXmlWriter;
3409  // set xml header
3410  $a_xml_writer->xmlHeader();
3411  $attrs = array(
3412  "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
3413  "xsi:noNamespaceSchemaLocation" => "http://www.ilias.de/download/xsd/ilias_survey_4_2.xsd"
3414  );
3415  $a_xml_writer->xmlStartTag("surveyobject", $attrs);
3416  $attrs = array(
3417  "id" => $this->getSurveyId(),
3418  "title" => $this->getTitle()
3419  );
3420  $a_xml_writer->xmlStartTag("survey", $attrs);
3421 
3422  $a_xml_writer->xmlElement("description", null, $this->getDescription());
3423  $a_xml_writer->xmlElement("author", null, $this->getAuthor());
3424  $a_xml_writer->xmlStartTag("objectives");
3425  $attrs = array(
3426  "label" => "introduction"
3427  );
3428  $this->addMaterialTag($a_xml_writer, $this->getIntroduction(), true, true, $attrs);
3429  $attrs = array(
3430  "label" => "outro"
3431  );
3432  $this->addMaterialTag($a_xml_writer, $this->getOutro(), true, true, $attrs);
3433  $a_xml_writer->xmlEndTag("objectives");
3434 
3435  if ($this->getAnonymize()) {
3436  $attribs = array("enabled" => "1");
3437  } else {
3438  $attribs = array("enabled" => "0");
3439  }
3440  $a_xml_writer->xmlElement("anonymisation", $attribs);
3441  $a_xml_writer->xmlStartTag("restrictions");
3442  if ($this->getAnonymize() == 2) {
3443  $attribs = array("type" => "free");
3444  } else {
3445  $attribs = array("type" => "restricted");
3446  }
3447  $a_xml_writer->xmlElement("access", $attribs);
3448  if ($this->getStartDate()) {
3449  $attrs = array("type" => "date");
3450  preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getStartDate(), $matches);
3451  $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]));
3452  }
3453  if ($this->getEndDate()) {
3454  $attrs = array("type" => "date");
3455  preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndDate(), $matches);
3456  $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]));
3457  }
3458  $a_xml_writer->xmlEndTag("restrictions");
3459 
3460  // constraints
3461  $pages =&$this->getSurveyPages();
3462  $hasconstraints = false;
3463  foreach ($pages as $question_array) {
3464  foreach ($question_array as $question) {
3465  if (count($question["constraints"])) {
3466  $hasconstraints = true;
3467  }
3468  }
3469  }
3470 
3471  if ($hasconstraints) {
3472  $a_xml_writer->xmlStartTag("constraints");
3473  foreach ($pages as $question_array) {
3474  foreach ($question_array as $question) {
3475  if (count($question["constraints"])) {
3476  // found constraints
3477  foreach ($question["constraints"] as $constraint) {
3478  $attribs = array(
3479  "sourceref" => $question["question_id"],
3480  "destref" => $constraint["question"],
3481  "relation" => $constraint["short"],
3482  "value" => $constraint["value"],
3483  "conjunction" => $constraint["conjunction"]
3484  );
3485  $a_xml_writer->xmlElement("constraint", $attribs);
3486  }
3487  }
3488  }
3489  }
3490  $a_xml_writer->xmlEndTag("constraints");
3491  }
3492 
3493  // add the rest of the preferences in qtimetadata tags, because there is no correspondent definition in QTI
3494  $a_xml_writer->xmlStartTag("metadata");
3495 
3496  $custom_properties = array();
3497  $custom_properties["evaluation_access"] = $this->getEvaluationAccess();
3498  $custom_properties["status"] = $this->getStatus();
3499  $custom_properties["display_question_titles"] = $this->getShowQuestionTitles();
3500  $custom_properties["pool_usage"] = (int) $this->getPoolUsage();
3501 
3502  $custom_properties["own_results_view"] = (int) $this->hasViewOwnResults();
3503  $custom_properties["own_results_mail"] = (int) $this->hasMailOwnResults();
3504  $custom_properties["confirmation_mail"] = (int) $this->hasMailConfirmation();
3505 
3506  $custom_properties["anon_user_list"] = (int) $this->hasAnonymousUserList();
3507 
3508  $custom_properties["mode_360"] = (int) $this->get360Mode();
3509  $custom_properties["mode_360_self_eval"] = (int) $this->get360SelfEvaluation();
3510  $custom_properties["mode_360_self_rate"] = (int) $this->get360SelfRaters();
3511  $custom_properties["mode_360_self_appr"] = (int) $this->get360SelfAppraisee();
3512  $custom_properties["mode_360_results"] = $this->get360Results();
3513  $custom_properties["mode_360_skill_service"] = (int) $this->get360SkillService();
3514 
3515 
3516  // :TODO: skills?
3517 
3518  // reminder/tutor notification are (currently?) not exportable
3519 
3520  foreach ($custom_properties as $label => $value) {
3521  $a_xml_writer->xmlStartTag("metadatafield");
3522  $a_xml_writer->xmlElement("fieldlabel", null, $label);
3523  $a_xml_writer->xmlElement("fieldentry", null, $value);
3524  $a_xml_writer->xmlEndTag("metadatafield");
3525  }
3526 
3527  $a_xml_writer->xmlStartTag("metadatafield");
3528  $a_xml_writer->xmlElement("fieldlabel", null, "SCORM");
3529  include_once "./Services/MetaData/classes/class.ilMD.php";
3530  $md = new ilMD($this->getId(), 0, $this->getType());
3531  $writer = new ilXmlWriter();
3532  $md->toXml($writer);
3533  $metadata = $writer->xmlDumpMem();
3534  $a_xml_writer->xmlElement("fieldentry", null, $metadata);
3535  $a_xml_writer->xmlEndTag("metadatafield");
3536 
3537  $a_xml_writer->xmlEndTag("metadata");
3538  $a_xml_writer->xmlEndTag("survey");
3539 
3540  $attribs = array("id" => $this->getId());
3541  $a_xml_writer->xmlStartTag("surveyquestions", $attribs);
3542  // add questionblock descriptions
3543  foreach ($pages as $question_array) {
3544  if (count($question_array) > 1) {
3545  $attribs = array("id" => $question_array[0]["question_id"]);
3546  $attribs = array("showQuestiontext" => $question_array[0]["questionblock_show_questiontext"],
3547  "showBlocktitle" => $question_array[0]["questionblock_show_blocktitle"]);
3548  $a_xml_writer->xmlStartTag("questionblock", $attribs);
3549  if (strlen($question_array[0]["questionblock_title"])) {
3550  $a_xml_writer->xmlElement("questionblocktitle", null, $question_array[0]["questionblock_title"]);
3551  }
3552  }
3553  foreach ($question_array as $question) {
3554  if (strlen($question["heading"])) {
3555  $a_xml_writer->xmlElement("textblock", null, $question["heading"]);
3556  }
3557  $questionObject = self::_instanciateQuestion($question["question_id"]);
3558  //questionObject contains all the fields from the database. (loadFromDb)
3559  //we don't need the value from svy_qst_oblig table, we already have the values from svy_question table.
3560  //if ($questionObject !== FALSE) $questionObject->insertXML($a_xml_writer, FALSE, $obligatory_states[$question["question_id"]]);
3561  if ($questionObject !== false) {
3562  $questionObject->insertXML($a_xml_writer, false);
3563  }
3564  }
3565  if (count($question_array) > 1) {
3566  $a_xml_writer->xmlEndTag("questionblock");
3567  }
3568  }
3569 
3570  $a_xml_writer->xmlEndTag("surveyquestions");
3571  $a_xml_writer->xmlEndTag("surveyobject");
3572  $xml = $a_xml_writer->xmlDumpMem(false);
3573  return $xml;
3574  }
3575 
3583  public static function _instanciateQuestion($question_id)
3584  {
3585  if ($question_id < 1) {
3586  return false;
3587  }
3588  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
3589  $question_type = SurveyQuestion::_getQuestionType($question_id);
3590  if (strlen($question_type) == 0) {
3591  return false;
3592  }
3593  SurveyQuestion::_includeClass($question_type);
3594  $question = new $question_type();
3595  $question->loadFromDb($question_id);
3596  return $question;
3597  }
3598 
3605  public function locateImportFiles($a_dir)
3606  {
3607  if (!is_dir($a_dir) || is_int(strpos($a_dir, ".."))) {
3608  return;
3609  }
3610  $importDirectory = "";
3611  $xmlFile = "";
3612 
3613  $current_dir = opendir($a_dir);
3614  $files = array();
3615  while ($entryname = readdir($current_dir)) {
3616  $files[] = $entryname;
3617  }
3618 
3619  foreach ($files as $file) {
3620  if (is_dir($a_dir . "/" . $file) and ($file != "." and $file!="..")) {
3621  // found directory created by zip
3622  $importDirectory = $a_dir . "/" . $file;
3623  }
3624  }
3625  closedir($current_dir);
3626  if (strlen($importDirectory)) {
3627  // find the xml file
3628  $current_dir = opendir($importDirectory);
3629  $files = array();
3630  while ($entryname = readdir($current_dir)) {
3631  $files[] = $entryname;
3632  }
3633  foreach ($files as $file) {
3634  if (@is_file($importDirectory . "/" . $file) &&
3635  ($file != "." && $file!="..") &&
3636  (preg_match("/^[0-9]{10}__[0-9]+__(svy_)*[0-9]+\.[A-Za-z]{1,3}$/", $file) ||
3637  preg_match("/^[0-9]{10}__[0-9]+__(survey__)*[0-9]+\.[A-Za-z]{1,3}$/", $file))) {
3638  // found xml file
3639  $xmlFile = $importDirectory . "/" . $file;
3640  }
3641  }
3642  }
3643  return array("dir" => $importDirectory, "xml" => $xmlFile);
3644  }
3645 
3654  public function importObject($file_info, $svy_qpl_id)
3655  {
3656  if ($svy_qpl_id < 1) {
3657  $svy_qpl_id = -1;
3658  }
3659  // check if file was uploaded
3660  $source = $file_info["tmp_name"];
3661  $error = "";
3662  if (($source == 'none') || (!$source) || $file_info["error"] > UPLOAD_ERR_OK) {
3663  $error = $this->lng->txt("import_no_file_selected");
3664  }
3665  // check correct file type
3666  $isXml = false;
3667  $isZip = false;
3668  if ((strcmp($file_info["type"], "text/xml") == 0) || (strcmp($file_info["type"], "application/xml") == 0)) {
3669  $this->log->debug("isXML");
3670  $isXml = true;
3671  }
3672  // too many different mime-types, so we use the suffix
3673  $suffix = pathinfo($file_info["name"]);
3674  if (strcmp(strtolower($suffix["extension"]), "zip") == 0) {
3675  $this->log->debug("isZip");
3676  $isZip = true;
3677  }
3678  if (!$isXml && !$isZip) {
3679  $error = $this->lng->txt("import_wrong_file_type");
3680  $this->log->debug("Survey: Import error. Filetype was \"" . $file_info["type"] . "\"");
3681  }
3682  if (strlen($error) == 0) {
3683  // import file as a survey
3684  $import_dir = $this->getImportDirectory();
3685  $import_subdir = "";
3686  $importfile = "";
3687  if ($isZip) {
3688  $importfile = $import_dir . "/" . $file_info["name"];
3689  ilUtil::moveUploadedFile($source, $file_info["name"], $importfile);
3690  ilUtil::unzip($importfile);
3691  $found = $this->locateImportFiles($import_dir);
3692  if (!((strlen($found["dir"]) > 0) && (strlen($found["xml"]) > 0))) {
3693  $error = $this->lng->txt("wrong_import_file_structure");
3694  return $error;
3695  }
3696  $importfile = $found["xml"];
3697  $import_subdir = $found["dir"];
3698  } else {
3699  $importfile = tempnam($import_dir, "survey_import");
3700  ilUtil::moveUploadedFile($source, $file_info["name"], $importfile);
3701  }
3702 
3703  $this->log->debug("Import file = $importfile");
3704  $this->log->debug("Import subdir = $import_subdir");
3705 
3706  $fh = fopen($importfile, "r");
3707  if (!$fh) {
3708  $error = $this->lng->txt("import_error_opening_file");
3709  return $error;
3710  }
3711  $xml = fread($fh, filesize($importfile));
3712  $result = fclose($fh);
3713  if (!$result) {
3714  $error = $this->lng->txt("import_error_closing_file");
3715  return $error;
3716  }
3717 
3718  unset($_SESSION["import_mob_xhtml"]);
3719  if (strpos($xml, "questestinterop")) {
3720  include_once("./Modules/Survey/exceptions/class.ilInvalidSurveyImportFileException.php");
3721  throw new ilInvalidSurveyImportFileException("Unsupported survey version (< 3.8) found.");
3722  /*
3723  include_once "./Services/Survey/classes/class.SurveyImportParserPre38.php";
3724  $import = new SurveyImportParserPre38($svy_qpl_id, "", TRUE);
3725  $import->setSurveyObject($this);
3726  $import->setXMLContent($xml);
3727  $import->startParsing();*/
3728  } else {
3729  $this->log->debug("survey id = " . $this->getId());
3730  $this->log->debug("question pool id = " . $svy_qpl_id);
3731 
3732  include_once("./Services/Export/classes/class.ilImport.php");
3733  $imp = new ilImport();
3734  $config = $imp->getConfig("Modules/Survey");
3735  $config->setQuestionPoolID($svy_qpl_id);
3736  $imp->getMapping()->addMapping("Modules/Survey", "svy", 0, $this->getId());
3737  $imp->importFromDirectory($import_subdir, "svy", "Modules/Survey");
3738  $this->log->debug("config(Modules/survey)->getQuestionPoolId =" . $config->getQuestionPoolID());
3739  return "";
3740 
3741  //old code
3742  include_once "./Services/Survey/classes/class.SurveyImportParser.php";
3743  $import = new SurveyImportParser($svy_qpl_id, "", true);
3744  $import->setSurveyObject($this);
3745  $import->setXMLContent($xml);
3746  $import->startParsing();
3747  }
3748 
3749  if (is_array($_SESSION["import_mob_xhtml"])) {
3750  include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
3751  include_once "./Services/RTE/classes/class.ilRTE.php";
3752  include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
3753  foreach ($_SESSION["import_mob_xhtml"] as $mob) {
3754  $importfile = $import_subdir . "/" . $mob["uri"];
3755  if (file_exists($importfile)) {
3756  if (!$mob["type"]) {
3757  $mob["type"] = "svy:html";
3758  }
3759 
3760  $media_object = ilObjMediaObject::_saveTempFileAsMediaObject(basename($importfile), $importfile, false);
3761 
3762  // survey mob
3763  if ($mob["type"] == "svy:html") {
3764  ilObjMediaObject::_saveUsage($media_object->getId(), "svy:html", $this->getId());
3765  $this->setIntroduction(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getIntroduction()));
3766  $this->setOutro(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getOutro()));
3767  }
3768  // question mob
3769  elseif ($import->questions[$mob["id"]]) {
3770  $new_qid = $import->questions[$mob["id"]];
3771  ilObjMediaObject::_saveUsage($media_object->getId(), $mob["type"], $new_qid);
3772  $new_question = SurveyQuestion::_instanciateQuestion($new_qid);
3773  $qtext = $new_question->getQuestiontext();
3774  $qtext = ilRTE::_replaceMediaObjectImageSrc($qtext, 0);
3775  $qtext = str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $qtext);
3776  $qtext = ilRTE::_replaceMediaObjectImageSrc($qtext, 1);
3777  $new_question->setQuestiontext($qtext);
3778  $new_question->saveToDb();
3779 
3780  // also fix existing original in pool
3781  if ($new_question->getOriginalId()) {
3782  $pool_question = SurveyQuestion::_instanciateQuestion($new_question->getOriginalId());
3783  $pool_question->setQuestiontext($qtext);
3784  $pool_question->saveToDb();
3785  }
3786  }
3787  } else {
3788  $ilLog = $this->log;
3789  $ilLog->write("Error: Could not open XHTML mob file for test introduction during test import. File $importfile does not exist!");
3790  }
3791  }
3794  $this->saveToDb();
3795  }
3796 
3797  // delete import directory
3799  }
3800  return $error;
3801  }
3802 
3811  public function cloneObject($a_target_id, $a_copy_id = 0, $a_omit_tree = false)
3812  {
3813  $ilDB = $this->db;
3814 
3815  $this->loadFromDb();
3816 
3817  // Copy settings
3818  $newObj = parent::cloneObject($a_target_id, $a_copy_id, $a_omit_tree);
3819  $this->cloneMetaData($newObj);
3820  $newObj->updateMetaData();
3821 
3822  $newObj->setAuthor($this->getAuthor());
3823  $newObj->setIntroduction($this->getIntroduction());
3824  $newObj->setOutro($this->getOutro());
3825  $newObj->setEvaluationAccess($this->getEvaluationAccess());
3826  $newObj->setStartDate($this->getStartDate());
3827  $newObj->setEndDate($this->getEndDate());
3828  $newObj->setInvitation($this->getInvitation());
3829  $newObj->setInvitationMode($this->getInvitationMode());
3830  $newObj->setAnonymize($this->getAnonymize());
3831  $newObj->setShowQuestionTitles($this->getShowQuestionTitles());
3832  $newObj->setTemplate($this->getTemplate());
3833  $newObj->setPoolUsage($this->getPoolUsage());
3834  $newObj->setViewOwnResults($this->hasViewOwnResults());
3835  $newObj->setMailOwnResults($this->hasMailOwnResults());
3836  $newObj->setMailConfirmation($this->hasMailConfirmation());
3837  $newObj->setAnonymousUserList($this->hasAnonymousUserList());
3838 
3839  // #12661
3840  if ($this->get360Mode()) {
3841  $newObj->set360Mode(true);
3842  $newObj->set360SelfEvaluation($this->get360SelfEvaluation());
3843  $newObj->set360SelfAppraisee($this->get360SelfAppraisee());
3844  $newObj->set360SelfRaters($this->get360SelfRaters());
3845  $newObj->set360Results($this->get360Results());
3846  $newObj->set360SkillService($this->get360SkillService());
3847  }
3848 
3849  // reminder/notification
3850  $newObj->setReminderStatus($this->getReminderStatus());
3851  $newObj->setReminderStart($this->getReminderStart());
3852  $newObj->setReminderEnd($this->getReminderEnd());
3853  $newObj->setReminderFrequency($this->getReminderFrequency());
3854  $newObj->setReminderTarget($this->getReminderTarget());
3855  $newObj->setReminderTemplate($this->getReminderTemplate());
3856  // reminder_last_sent must not be copied!
3857  $newObj->setTutorNotificationStatus($this->getTutorNotificationStatus());
3858  $newObj->setTutorNotificationRecipients($this->getTutorNotificationRecipients());
3859  $newObj->setTutorNotificationTarget($this->getTutorNotificationTarget());
3860 
3861  $newObj->setMailNotification($this->getMailNotification());
3862  $newObj->setMailAddresses($this->getMailAddresses());
3863  $newObj->setMailParticipantData($this->getMailParticipantData());
3864 
3865  $question_pointer = array();
3866  // clone the questions
3867  $mapping = array();
3868  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
3869 
3870  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->saveToDb($original_id);
3876  $newObj->questions[$key] = $question->getId();
3877  $question_pointer[$question_id] = $question->getId();
3878  $mapping[$question_id] = $question->getId();
3879  }
3880  }
3881 
3882  //copy online status if object is not the root copy object
3883  $cp_options = ilCopyWizardOptions::_getInstance($a_copy_id);
3884 
3885  if (!$cp_options->isRootNode($this->getRefId())) {
3886  $newObj->setStatus($this->isOnline()?self::STATUS_ONLINE: self::STATUS_OFFLINE);
3887  }
3888 
3889  $newObj->saveToDb();
3890  $newObj->cloneTextblocks($mapping);
3891 
3892  // #14929
3893  if ($this->get360Mode() &&
3894  $this->get360SkillService()) {
3895  include_once "./Modules/Survey/classes/class.ilSurveySkill.php";
3896  $src_skills = new ilSurveySkill($this);
3897  $tgt_skills = new ilSurveySkill($newObj);
3898 
3899  foreach ($mapping as $src_qst_id => $tgt_qst_id) {
3900  $qst_skill = $src_skills->getSkillForQuestion($src_qst_id);
3901  if ($qst_skill) {
3902  $tgt_skills->addQuestionSkillAssignment($tgt_qst_id, $qst_skill["base_skill_id"], $qst_skill["tref_id"]);
3903  }
3904  }
3905  }
3906 
3907  // clone the questionblocks
3908  $questionblocks = array();
3909  $questionblock_questions = array();
3910  $result = $ilDB->queryF(
3911  "SELECT * FROM svy_qblk_qst WHERE survey_fi = %s",
3912  array('integer'),
3913  array($this->getSurveyId())
3914  );
3915  if ($result->numRows() > 0) {
3916  while ($row = $ilDB->fetchAssoc($result)) {
3917  array_push($questionblock_questions, $row);
3918  $questionblocks[$row["questionblock_fi"]] = $row["questionblock_fi"];
3919  }
3920  }
3921  // create new questionblocks
3922  foreach ($questionblocks as $key => $value) {
3923  $questionblock = self::_getQuestionblock($key);
3924  $questionblock_id = self::_addQuestionblock($questionblock["title"], $questionblock["owner_fi"], $questionblock["show_questiontext"], $questionblock["show_blocktitle"]);
3925  $questionblocks[$key] = $questionblock_id;
3926  }
3927  // create new questionblock questions
3928  foreach ($questionblock_questions as $key => $value) {
3929  if ($questionblocks[$value["questionblock_fi"]] &&
3930  $question_pointer[$value["question_fi"]]) {
3931  $next_id = $ilDB->nextId('svy_qblk_qst');
3932  $affectedRows = $ilDB->manipulateF(
3933  "INSERT INTO svy_qblk_qst (qblk_qst_id, survey_fi, questionblock_fi, question_fi) " .
3934  "VALUES (%s, %s, %s, %s)",
3935  array('integer','integer','integer','integer'),
3936  array($next_id, $newObj->getSurveyId(), $questionblocks[$value["questionblock_fi"]], $question_pointer[$value["question_fi"]])
3937  );
3938  }
3939  }
3940 
3941  // clone the constraints
3942  $constraints = self::_getConstraints($this->getSurveyId());
3943  $newConstraints = array();
3944  foreach ($constraints as $key => $constraint) {
3945  if ($question_pointer[$constraint["for_question"]] &&
3946  $question_pointer[$constraint["question"]]) {
3947  if (!array_key_exists($constraint['id'], $newConstraints)) {
3948  $constraint_id = $newObj->addConstraint($question_pointer[$constraint["question"]], $constraint["relation_id"], $constraint["value"], $constraint['conjunction']);
3949  $newConstraints[$constraint['id']] = $constraint_id;
3950  }
3951  $newObj->addConstraintToQuestion($question_pointer[$constraint["for_question"]], $newConstraints[$constraint['id']]);
3952  }
3953  }
3954 
3955  // #16210 - clone LP settings
3956  include_once('./Services/Tracking/classes/class.ilLPObjSettings.php');
3957  $obj_settings = new ilLPObjSettings($this->getId());
3958  $obj_settings->cloneSettings($newObj->getId());
3959  unset($obj_settings);
3960 
3961  return $newObj;
3962  }
3963 
3964  public function getTextblock($question_id)
3965  {
3966  $ilDB = $this->db;
3967  $result = $ilDB->queryF(
3968  "SELECT * FROM svy_svy_qst WHERE question_fi = %s",
3969  array('integer'),
3970  array($question_id)
3971  );
3972  if ($result->numRows()) {
3973  $row = $ilDB->fetchAssoc($result);
3974  return $row["heading"];
3975  } else {
3976  return "";
3977  }
3978  }
3979 
3985  public function cloneTextblocks($mapping)
3986  {
3987  foreach ($mapping as $original_id => $new_id) {
3988  $textblock = $this->getTextblock($original_id);
3989  include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
3990  $this->saveHeading(ilUtil::stripSlashes($textblock, true, ilObjAdvancedEditing::_getUsedHTMLTagsAsString("survey")), $new_id);
3991  }
3992  }
3993 
4001  public function createExportDirectory()
4002  {
4003  $svy_data_dir = ilUtil::getDataDir() . "/svy_data";
4004  ilUtil::makeDir($svy_data_dir);
4005  if (!is_writable($svy_data_dir)) {
4006  include_once "Modules/Survey/exceptions/class.ilSurveyException.php";
4007  throw new ilSurveyException("Survey Data Directory (" . $svy_data_dir . ") not writeable.");
4008  }
4009 
4010  // create learning module directory (data_dir/lm_data/lm_<id>)
4011  $svy_dir = $svy_data_dir . "/svy_" . $this->getId();
4012  ilUtil::makeDir($svy_dir);
4013  if (!@is_dir($svy_dir)) {
4014  include_once "Modules/Survey/exceptions/class.ilSurveyException.php";
4015  throw new ilSurveyException("Creation of Survey Directory failed.");
4016  }
4017  // create Export subdirectory (data_dir/lm_data/lm_<id>/Export)
4018  $export_dir = $svy_dir . "/export";
4019  ilUtil::makeDir($export_dir);
4020  if (!@is_dir($export_dir)) {
4021  include_once "Modules/Survey/exceptions/class.ilSurveyException.php";
4022  throw new ilSurveyException("Creation of Export Directory failed.");
4023  }
4024  }
4025 
4029  public function getExportDirectory()
4030  {
4031  $export_dir = ilUtil::getDataDir() . "/svy_data" . "/svy_" . $this->getId() . "/export";
4032 
4033  return $export_dir;
4034  }
4035 
4043  public function createImportDirectory()
4044  {
4045  $svy_data_dir = ilUtil::getDataDir() . "/svy_data";
4046  ilUtil::makeDir($svy_data_dir);
4047 
4048  if (!is_writable($svy_data_dir)) {
4049  include_once "Modules/Survey/exceptions/class.ilSurveyException.php";
4050  throw new ilSurveyException("Survey Data Directory (" . $svy_data_dir . ") not writeable.");
4051  }
4052 
4053  // create test directory (data_dir/svy_data/svy_<id>)
4054  $svy_dir = $svy_data_dir . "/svy_" . $this->getId();
4055  ilUtil::makeDir($svy_dir);
4056  if (!@is_dir($svy_dir)) {
4057  include_once "Modules/Survey/exceptions/class.ilSurveyException.php";
4058  throw new ilSurveyException("Creation of Survey Directory failed.");
4059  }
4060 
4061  // create import subdirectory (data_dir/svy_data/svy_<id>/import)
4062  $import_dir = $svy_dir . "/import";
4063  ilUtil::makeDir($import_dir);
4064  if (!@is_dir($import_dir)) {
4065  include_once "Modules/Survey/exceptions/class.ilSurveyException.php";
4066  throw new ilSurveyException("Creation of Import Directory failed.");
4067  }
4068  }
4069 
4073  public function getImportDirectory()
4074  {
4075  $import_dir = ilUtil::getDataDir() . "/svy_data" .
4076  "/svy_" . $this->getId() . "/import";
4077  if (!is_dir($import_dir)) {
4078  ilUtil::makeDirParents($import_dir);
4079  }
4080  if (@is_dir($import_dir)) {
4081  return $import_dir;
4082  } else {
4083  return false;
4084  }
4085  }
4086 
4087  public function saveHeading($heading = "", $insertbefore)
4088  {
4089  $ilDB = $this->db;
4090  if ($heading) {
4091  $affectedRows = $ilDB->manipulateF(
4092  "UPDATE svy_svy_qst SET heading=%s WHERE survey_fi=%s AND question_fi=%s",
4093  array('text','integer','integer'),
4094  array($heading, $this->getSurveyId(), $insertbefore)
4095  );
4096  } else {
4097  $affectedRows = $ilDB->manipulateF(
4098  "UPDATE svy_svy_qst SET heading=%s WHERE survey_fi=%s AND question_fi=%s",
4099  array('text','integer','integer'),
4100  array(null, $this->getSurveyId(), $insertbefore)
4101  );
4102  }
4103  }
4104 
4105  public function isAnonymousKey($key)
4106  {
4107  $ilDB = $this->db;
4108 
4109  $result = $ilDB->queryF(
4110  "SELECT anonymous_id FROM svy_anonymous WHERE survey_key = %s AND survey_fi = %s",
4111  array('text','integer'),
4112  array($key, $this->getSurveyId())
4113  );
4114  return ($result->numRows() == 1) ? true : false;
4115  }
4116 
4117  public function bindSurveyCodeToUser($user_id, $code)
4118  {
4119  $ilDB = $this->db;
4120 
4121  if ($user_id == ANONYMOUS_USER_ID) {
4122  return;
4123  }
4124 
4125  if ($this->checkSurveyCode($code)) {
4126  $ilDB->manipulate("UPDATE svy_anonymous" .
4127  " SET user_key = " . $ilDB->quote(md5($user_id), "text") .
4128  " WHERE survey_key = " . $ilDB->quote($code, "text"));
4129  }
4130  }
4131 
4133  {
4134  $ilDB = $this->db;
4135 
4136  $result = $ilDB->queryF(
4137  "SELECT finished_id FROM svy_finished WHERE anonymous_id = %s AND survey_fi = %s",
4138  array('text','integer'),
4139  array($key, $this->getSurveyId())
4140  );
4141  return ($result->numRows() == 1) ? true : false;
4142  }
4143 
4144  public function checkSurveyCode($code)
4145  {
4146  if ($this->isAnonymousKey($code)) {
4147  if ($this->isSurveyStarted("", $code) == 1) {
4148  return false;
4149  } else {
4150  return true;
4151  }
4152  } else {
4153  return false;
4154  }
4155  }
4156 
4164  public function getSurveyCodesForExport(array $a_codes = null, array $a_ids = null)
4165  {
4166  $ilDB = $this->db;
4167  $ilUser = $this->user;
4168  $lng = $this->lng;
4169 
4170  include_once "./Services/Link/classes/class.ilLink.php";
4171 
4172  $sql = "SELECT svy_anonymous.*, svy_finished.state" .
4173  " FROM svy_anonymous" .
4174  " LEFT JOIN svy_finished ON (svy_anonymous.survey_key = svy_finished.anonymous_id)" .
4175  " WHERE svy_anonymous.survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
4176  " AND svy_anonymous.user_key IS NULL";
4177 
4178  if ($a_codes) {
4179  $sql .= " AND " . $ilDB->in("svy_anonymous.survey_key", $a_codes, "", "text");
4180  } elseif ($a_ids) {
4181  $sql .= " AND " . $ilDB->in("svy_anonymous.anonymous_id", $a_ids, "", "text");
4182  }
4183 
4184  $export = array();
4185 
4186  // #14905
4187  $titles = array();
4188  $titles[] = '"' . $lng->txt("survey_code") . '"';
4189  $titles[] = '"' . $lng->txt("email") . '"';
4190  $titles[] = '"' . $lng->txt("lastname") . '"';
4191  $titles[] = '"' . $lng->txt("firstname") . '"';
4192  $titles[] = '"' . $lng->txt("create_date") . '"';
4193  $titles[] = '"' . $lng->txt("used") . '"';
4194  $titles[] = '"' . $lng->txt("mail_sent_short") . '"';
4195  $titles[] = '"' . $lng->txt("survey_code_url") . '"';
4196  $export[] = implode(";", $titles);
4197 
4198  $result = $ilDB->query($sql);
4199  $default_lang = $ilUser->getPref("survey_code_language");
4200  while ($row = $ilDB->fetchAssoc($result)) {
4201  $item = array();
4202  $item[] = $row["survey_key"];
4203 
4204  if ($row["externaldata"]) {
4205  $ext = unserialize($row["externaldata"]);
4206  $item[] = $ext["email"];
4207  $item[] = $ext["lastname"];
4208  $item[] = $ext["firstname"];
4209  } else {
4210  $item[] = "";
4211  $item[] = "";
4212  $item[] = "";
4213  }
4214 
4215  // No relative (today, tomorrow...) dates in export.
4216  $date = new ilDateTime($row['tstamp'], IL_CAL_UNIX);
4217  $item[] = $date->get(IL_CAL_DATETIME);
4218 
4219  $item[] = ($this->isSurveyCodeUsed($row["survey_key"])) ? 1 : 0;
4220  $item[] = ($row["sent"]) ? 1 : 0;
4221 
4222  $params = array("accesscode" => $row["survey_key"]);
4223  if ($default_lang) {
4224  $params["lang"] = $default_lang;
4225  }
4226  $item[] = ilLink::_getLink($this->getRefId(), "svy", $params);
4227 
4228  $export[] = '"' . implode('";"', $item) . '"';
4229  }
4230  return implode("\n", $export);
4231  }
4232 
4240  public function getSurveyCodesTableData(array $ids = null, $lang = null)
4241  {
4242  $ilDB = $this->db;
4243 
4244  include_once "./Services/Link/classes/class.ilLink.php";
4245 
4246  $codes = array();
4247 
4248  $sql = "SELECT svy_anonymous.*, svy_finished.state" .
4249  " FROM svy_anonymous" .
4250  " LEFT JOIN svy_finished ON (svy_anonymous.survey_key = svy_finished.anonymous_id)" .
4251  " WHERE svy_anonymous.survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") /*.
4252  " AND svy_anonymous.user_key IS NULL" */; // #15860
4253 
4254  if ($ids) {
4255  $sql .= " AND " . $ilDB->in("svy_anonymous.anonymous_id", $ids, "", "integer");
4256  }
4257 
4258  $sql .= " ORDER BY tstamp, survey_key ASC";
4259  $result = $ilDB->query($sql);
4260  if ($result->numRows() > 0) {
4261  while ($row = $ilDB->fetchAssoc($result)) {
4262  $href = "";
4263  $used = false;
4264  if ($this->isSurveyCodeUsed($row["survey_key"])) {
4265  $used = true;
4266  } else {
4267  $params = array("accesscode" => $row["survey_key"]);
4268  if ($lang) {
4269  $params["lang"] = $lang;
4270  }
4271  $href = ilLink::_getLink($this->getRefId(), "svy", $params);
4272  }
4273 
4274 
4275  $item = array(
4276  'id' => $row["anonymous_id"],
4277  'code' => $row["survey_key"],
4278  'date' => $row["tstamp"],
4279  'used' => $used,
4280  'sent' => $row['sent'],
4281  'href' => $href,
4282  'email' => '',
4283  'last_name' => '',
4284  'first_name' => ''
4285  );
4286 
4287  if ($row["externaldata"]) {
4288  $ext = unserialize($row["externaldata"]);
4289  $item['email'] = $ext['email'];
4290  $item['last_name'] = $ext['lastname'];
4291  $item['first_name'] = $ext['firstname'];
4292  }
4293 
4294  array_push($codes, $item);
4295  }
4296  }
4297  return $codes;
4298  }
4299 
4300  public function isSurveyCodeUsed($code)
4301  {
4302  $ilDB = $this->db;
4303  $result = $ilDB->queryF(
4304  "SELECT finished_id FROM svy_finished WHERE survey_fi = %s AND anonymous_id = %s",
4305  array('integer','text'),
4306  array($this->getSurveyId(), $code)
4307  );
4308  return ($result->numRows() > 0) ? true : false;
4309  }
4310 
4311  public function isSurveyCodeUnique($code)
4312  {
4313  $ilDB = $this->db;
4314  $result = $ilDB->queryF(
4315  "SELECT anonymous_id FROM svy_anonymous WHERE survey_fi = %s AND survey_key = %s",
4316  array('integer','text'),
4317  array($this->getSurveyId(), $code)
4318  );
4319  return ($result->numRows() > 0) ? false : true;
4320  }
4321 
4322  public function createSurveyCodes($nrOfCodes)
4323  {
4324  $ilDB = $this->db;
4325 
4326  $res = array();
4327 
4328  for ($i = 0; $i < $nrOfCodes; $i++) {
4329  $next_id = $ilDB->nextId('svy_anonymous');
4330  $ilDB->manipulateF(
4331  "INSERT INTO svy_anonymous (anonymous_id, survey_key, survey_fi, tstamp) " .
4332  "VALUES (%s, %s, %s, %s)",
4333  array('integer','text','integer','integer'),
4334  array($next_id, $this->createNewAccessCode(), $this->getSurveyId(), time())
4335  );
4336  $res[] = $next_id;
4337  }
4338 
4339  return $res;
4340  }
4341 
4342  public function importSurveyCode($a_anonymize_key, $a_created, $a_data)
4343  {
4344  $ilDB = $this->db;
4345 
4346  $next_id = $ilDB->nextId('svy_anonymous');
4347  $ilDB->manipulateF(
4348  "INSERT INTO svy_anonymous (anonymous_id, survey_key, survey_fi, externaldata, tstamp) " .
4349  "VALUES (%s, %s, %s, %s, %s)",
4350  array('integer','text','integer','text','integer'),
4351  array($next_id, $a_anonymize_key, $this->getSurveyId(), serialize($a_data), $a_created)
4352  );
4353  }
4354 
4356  {
4357  $ilDB = $this->db;
4358 
4359  $ids = array();
4360  foreach ($data as $dataset) {
4361  $anonymize_key = $this->createNewAccessCode();
4362  $next_id = $ilDB->nextId('svy_anonymous');
4363  $affectedRows = $ilDB->manipulateF(
4364  "INSERT INTO svy_anonymous (anonymous_id, survey_key, survey_fi, externaldata, tstamp) " .
4365  "VALUES (%s, %s, %s, %s, %s)",
4366  array('integer','text','integer','text','integer'),
4367  array($next_id, $anonymize_key, $this->getSurveyId(), serialize($dataset), time())
4368  );
4369  $ids[] = $next_id;
4370  }
4371  return $ids;
4372  }
4373 
4374  public function sendCodes($not_sent, $subject, $message, $lang)
4375  {
4376  global $DIC;
4377  /*
4378  * 0 = all
4379  * 1 = not sent
4380  * 2 = finished
4381  * 3 = not finished
4382  */
4383  $check_finished = ($not_sent > 1);
4384 
4385  include_once "./Services/Mail/classes/class.ilMail.php";
4386  include_once "./Services/Link/classes/class.ilLink.php";
4387 
4388  #19956
4389  $user_id = $DIC->user()->getId();
4390  $mail = new ilMail($user_id);
4391  $recipients = $this->getExternalCodeRecipients($check_finished);
4392  foreach ($recipients as $data) {
4393  if ($data['email'] && $data['code']) {
4394  $do_send = false;
4395  switch ((int) $not_sent) {
4396  case 1:
4397  $do_send = !(bool) $data['sent'];
4398  break;
4399 
4400  case 2:
4401  $do_send = $data['finished'];
4402  break;
4403 
4404  case 3:
4405  $do_send = !$data['finished'];
4406  break;
4407 
4408  default:
4409  $do_send = true;
4410  break;
4411  }
4412  if ($do_send) {
4413  // build text
4414  $messagetext = $message;
4416  $this->getRefId(),
4417  "svy",
4418  array(
4419  "accesscode" => $data["code"],
4420  "lang" => $lang
4421  )
4422  );
4423  $messagetext = str_replace('[url]', $url, $messagetext);
4424  foreach ($data as $key => $value) {
4425  $messagetext = str_replace('[' . $key . ']', $value, $messagetext);
4426  }
4427 
4428  // send mail
4429  $mail->sendMail(
4430  $data['email'], // to
4431  "", // cc
4432  "", // bcc
4433  $subject, // subject
4434  $messagetext, // message
4435  array(), // attachments
4436  array('normal') // type
4437  );
4438  }
4439  }
4440  }
4441 
4442  $ilDB = $this->db;
4443  $ilDB->manipulateF(
4444  "UPDATE svy_anonymous SET sent = %s WHERE survey_fi = %s AND externaldata IS NOT NULL",
4445  array('integer','integer'),
4446  array(1, $this->getSurveyId())
4447  );
4448  }
4449 
4450  public function getExternalCodeRecipients($a_check_finished = false)
4451  {
4452  $ilDB = $this->db;
4453  $result = $ilDB->queryF(
4454  "SELECT survey_key code, externaldata, sent FROM svy_anonymous WHERE survey_fi = %s",
4455  array('integer'),
4456  array($this->getSurveyId())
4457  );
4458  $res = array();
4459  while ($row = $ilDB->fetchAssoc($result)) {
4460  if (!$row['externaldata']) {
4461  continue;
4462  }
4463 
4464  $externaldata = unserialize($row['externaldata']);
4465  if (!$externaldata['email']) {
4466  continue;
4467  }
4468 
4469  $externaldata['code'] = $row['code'];
4470  $externaldata['sent'] = $row['sent'];
4471 
4472  if ($a_check_finished) {
4473  #23294
4474  //$externaldata['finished'] = $this->isSurveyCodeUsed($row['code']);
4475  $externaldata['finished'] = $this->isSurveyFinishedByCode($row['code']);
4476  }
4477 
4478  array_push($res, $externaldata);
4479  }
4480  return $res;
4481  }
4482 
4488  public function isSurveyFinishedByCode($a_code)
4489  {
4490  $result = $this->db->queryF(
4491  "SELECT state FROM svy_finished WHERE survey_fi = %s AND anonymous_id = %s",
4492  array('integer','text'),
4493  array($this->getSurveyId(), $a_code)
4494  );
4495 
4496  $row = $this->db->fetchAssoc($result);
4497 
4498  return $row['state'];
4499  }
4500 
4506  public function deleteSurveyCode($survey_code)
4507  {
4508  $ilDB = $this->db;
4509 
4510  if (strlen($survey_code) > 0) {
4511  $affectedRows = $ilDB->manipulateF(
4512  "DELETE FROM svy_anonymous WHERE survey_fi = %s AND survey_key = %s",
4513  array('integer', 'text'),
4514  array($this->getSurveyId(), $survey_code)
4515  );
4516  }
4517  }
4518 
4525  public function getUserAccessCode($user_id)
4526  {
4527  $ilDB = $this->db;
4528  $access_code = "";
4529  $result = $ilDB->queryF(
4530  "SELECT survey_key FROM svy_anonymous WHERE survey_fi = %s AND user_key = %s",
4531  array('integer','text'),
4532  array($this->getSurveyId(), md5($user_id))
4533  );
4534  if ($result->numRows()) {
4535  $row = $ilDB->fetchAssoc($result);
4536  $access_code = $row["survey_key"];
4537  }
4538  return $access_code;
4539  }
4540 
4547  public function saveUserAccessCode($user_id, $access_code)
4548  {
4549  $ilDB = $this->db;
4550 
4551  // not really sure what to do about ANONYMOUS_USER_ID
4552 
4553  $next_id = $ilDB->nextId('svy_anonymous');
4554  $affectedRows = $ilDB->manipulateF(
4555  "INSERT INTO svy_anonymous (anonymous_id, survey_key, survey_fi, user_key, tstamp) " .
4556  "VALUES (%s, %s, %s, %s, %s)",
4557  array('integer','text', 'integer', 'text', 'integer'),
4558  array($next_id, $access_code, $this->getSurveyId(), md5($user_id), time())
4559  );
4560  }
4561 
4567  public function createNewAccessCode()
4568  {
4569  // create a 5 character code
4570  $codestring = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
4571  mt_srand();
4572  $code = "";
4573  for ($i = 1; $i <=5; $i++) {
4574  $index = mt_rand(0, strlen($codestring)-1);
4575  $code .= substr($codestring, $index, 1);
4576  }
4577  // verify it against the database
4578  while (!$this->isSurveyCodeUnique($code)) {
4579  $code = $this->createNewAccessCode();
4580  }
4581  return $code;
4582  }
4583 
4584  public function getLastAccess($finished_id)
4585  {
4586  $ilDB = $this->db;
4587 
4588  $result = $ilDB->queryF(
4589  "SELECT tstamp FROM svy_answer WHERE active_fi = %s ORDER BY tstamp DESC",
4590  array('integer'),
4591  array($finished_id)
4592  );
4593  if ($result->numRows()) {
4594  $row = $ilDB->fetchAssoc($result);
4595  return $row["tstamp"];
4596  } else {
4597  $result = $ilDB->queryF(
4598  "SELECT tstamp FROM svy_finished WHERE finished_id = %s",
4599  array('integer'),
4600  array($finished_id)
4601  );
4602  if ($result->numRows()) {
4603  $row = $ilDB->fetchAssoc($result);
4604  return $row["tstamp"];
4605  }
4606  }
4607  return "";
4608  }
4609 
4616  public function prepareTextareaOutput($txt_output)
4617  {
4618  return ilUtil::prepareTextareaOutput($txt_output, $prepare_for_latex_output);
4619  }
4620 
4628  public function isHTML($a_text)
4629  {
4630  if (preg_match("/<[^>]*?>/", $a_text)) {
4631  return true;
4632  } else {
4633  return false;
4634  }
4635  }
4636 
4645  public function addMaterialTag(&$a_xml_writer, $a_material, $close_material_tag = true, $add_mobs = true, $attribs = null)
4646  {
4647  include_once "./Services/RTE/classes/class.ilRTE.php";
4648  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
4649 
4650  $a_xml_writer->xmlStartTag("material", $attribs);
4651  $attrs = array(
4652  "type" => "text/plain"
4653  );
4654  if ($this->isHTML($a_material)) {
4655  $attrs["type"] = "text/xhtml";
4656  }
4657  $mattext = ilRTE::_replaceMediaObjectImageSrc($a_material, 0);
4658  $a_xml_writer->xmlElement("mattext", $attrs, $mattext);
4659 
4660  if ($add_mobs) {
4661  $mobs = ilObjMediaObject::_getMobsOfObject("svy:html", $this->getId());
4662  foreach ($mobs as $mob) {
4663  $mob_id = "il_" . IL_INST_ID . "_mob_" . $mob;
4664  if (strpos($mattext, $mob_id) !== false) {
4665  $mob_obj = new ilObjMediaObject($mob);
4666  $imgattrs = array(
4667  "label" => $mob_id,
4668  "uri" => "objects/" . "il_" . IL_INST_ID . "_mob_" . $mob . "/" . $mob_obj->getTitle(),
4669  "type" => "svy:html",
4670  "id" => $this->getId()
4671  );
4672  $a_xml_writer->xmlElement("matimage", $imgattrs, null);
4673  }
4674  }
4675  }
4676  if ($close_material_tag) {
4677  $a_xml_writer->xmlEndTag("material");
4678  }
4679  }
4680 
4689  public function canExportSurveyCode()
4690  {
4691  if ($this->getAnonymize() != self::ANONYMIZE_OFF) {
4692  if ($this->surveyCodeSecurity == false) {
4693  return true;
4694  }
4695  }
4696  return false;
4697  }
4698 
4706  public function processPrintoutput2FO($print_output)
4707  {
4708  if (extension_loaded("tidy")) {
4709  $config = array(
4710  "indent" => false,
4711  "output-xml" => true,
4712  "numeric-entities" => true
4713  );
4714  $tidy = new tidy();
4715  $tidy->parseString($print_output, $config, 'utf8');
4716  $tidy->cleanRepair();
4717  $print_output = tidy_get_output($tidy);
4718  $print_output = preg_replace("/^.*?(<html)/", "\\1", $print_output);
4719  } else {
4720  $print_output = str_replace("&nbsp;", "&#160;", $print_output);
4721  $print_output = str_replace("&otimes;", "X", $print_output);
4722 
4723  // #17680 - metric questions use &#160; in print view
4724  $print_output = str_replace("&gt;", "~|gt|~", $print_output); // see #21550
4725  $print_output = str_replace("&lt;", "~|lt|~", $print_output);
4726  $print_output = str_replace("&#160;", "~|nbsp|~", $print_output);
4727  $print_output = preg_replace('/&(?!amp)/', '&amp;', $print_output);
4728  $print_output = str_replace("~|nbsp|~", "&#160;", $print_output);
4729  $print_output = str_replace("~|gt|~", "&gt;", $print_output);
4730  $print_output = str_replace("~|lt|~", "&lt;", $print_output);
4731  }
4732  $xsl = file_get_contents("./Modules/Survey/xml/question2fo.xsl");
4733 
4734  // additional font support
4735  $xsl = str_replace(
4736  'font-family="Helvetica, unifont"',
4737  'font-family="' . $GLOBALS['ilSetting']->get('rpc_pdf_font', 'Helvetica, unifont') . '"',
4738  $xsl
4739  );
4740  $args = array( '/_xml' => $print_output, '/_xsl' => $xsl );
4741  $xh = xslt_create();
4742  $params = array();
4743  try {
4744  $output = xslt_process($xh, "arg:/_xml", "arg:/_xsl", null, $args, $params);
4745  } catch (Exception $e) {
4746  $this->log->error("Print XSLT failed:");
4747  $this->log->error("Content: " . $print_output);
4748  $this->log->error("Xsl: " . $xsl);
4749  throw ($e);
4750  }
4751  xslt_error($xh);
4752  xslt_free($xh);
4753 
4754  return $output;
4755  }
4756 
4763  public function deliverPDFfromFO($fo)
4764  {
4765  $ilLog = $this->log;
4766 
4767  $fo_file = ilUtil::ilTempnam() . ".fo";
4768  $fp = fopen($fo_file, "w");
4769  fwrite($fp, $fo);
4770  fclose($fp);
4771 
4772  include_once './Services/WebServices/RPC/classes/class.ilRpcClientFactory.php';
4773  try {
4774  $pdf_base64 = ilRpcClientFactory::factory('RPCTransformationHandler')->ilFO2PDF($fo);
4775  ilUtil::deliverData($pdf_base64->scalar, ilUtil::getASCIIFilename($this->getTitle()) . ".pdf", "application/pdf");
4776  return true;
4777  } catch (Exception $e) {
4778  $ilLog->write(__METHOD__ . ': ' . $e->getMessage());
4779  return false;
4780  }
4781  }
4782 
4789  public function isPluginActive($a_pname)
4790  {
4791  $ilPluginAdmin = $this->plugin_admin;
4792  if ($ilPluginAdmin->isActive(IL_COMP_MODULE, "SurveyQuestionPool", "svyq", $a_pname)) {
4793  return true;
4794  } else {
4795  return false;
4796  }
4797  }
4798 
4804  public function setSurveyId($survey_id)
4805  {
4806  $this->survey_id = $survey_id;
4807  }
4808 
4815  public function &getUserData($ids)
4816  {
4817  $ilDB = $this->db;
4818 
4819  if (!is_array($ids) || count($ids) ==0) {
4820  return array();
4821  }
4822 
4823  $result = $ilDB->query("SELECT usr_id, login, lastname, firstname FROM usr_data WHERE " . $ilDB->in('usr_id', $ids, false, 'integer') . " ORDER BY login");
4824  $result_array = array();
4825  while ($row = $ilDB->fetchAssoc($result)) {
4826  $result_array[$row["usr_id"]]= $row;
4827  }
4828  return $result_array;
4829  }
4830 
4831  public function getMailNotification()
4832  {
4833  return $this->mailnotification;
4834  }
4835 
4836  public function setMailNotification($a_notification)
4837  {
4838  $this->mailnotification = ($a_notification) ? true : false;
4839  }
4840 
4841  public function getMailAddresses()
4842  {
4843  return $this->mailaddresses;
4844  }
4845 
4846  public function setMailAddresses($a_addresses)
4847  {
4848  $this->mailaddresses = $a_addresses;
4849  }
4850 
4851  public function getMailParticipantData()
4852  {
4854  }
4855 
4856  public function setMailParticipantData($a_data)
4857  {
4858  $this->mailparticipantdata = $a_data;
4859  }
4860 
4861  public function setStartTime($finished_id, $first_question)
4862  {
4863  $ilDB = $this->db;
4864  $time = time();
4865  //primary for table svy_times
4866  $id = $ilDB->nextId('svy_times');
4867  $_SESSION['svy_entered_page'] = $time;
4868  $affectedRows = $ilDB->manipulateF(
4869  "INSERT INTO svy_times (id, finished_fi, entered_page, left_page, first_question) VALUES (%s, %s, %s, %s,%s)",
4870  array('integer','integer', 'integer', 'integer', 'integer'),
4871  array($id, $finished_id, $time, null, $first_question)
4872  );
4873  }
4874 
4875  public function setEndTime($finished_id)
4876  {
4877  $ilDB = $this->db;
4878  $time = time();
4879  $affectedRows = $ilDB->manipulateF(
4880  "UPDATE svy_times SET left_page = %s WHERE finished_fi = %s AND entered_page = %s",
4881  array('integer', 'integer', 'integer'),
4882  array($time, $finished_id, $_SESSION['svy_entered_page'])
4883  );
4884  unset($_SESSION['svy_entered_page']);
4885  }
4886 
4887  public function getWorkingtimeForParticipant($finished_id)
4888  {
4889  $ilDB = $this->db;
4890 
4891  $result = $ilDB->queryF(
4892  "SELECT * FROM svy_times WHERE finished_fi = %s",
4893  array('integer'),
4894  array($finished_id)
4895  );
4896  $total = 0;
4897  while ($row = $ilDB->fetchAssoc($result)) {
4898  if ($row['left_page'] > 0 && $row['entered_page'] > 0) {
4899  $total += $row['left_page'] - $row['entered_page'];
4900  }
4901  }
4902  return $total;
4903  }
4904 
4905  public function setTemplate($template_id)
4906  {
4907  $this->template_id = (int) $template_id;
4908  }
4909 
4910  public function getTemplate()
4911  {
4912  return $this->template_id;
4913  }
4914 
4915  public function updateOrder(array $a_order)
4916  {
4917  if (sizeof($this->questions) == sizeof($a_order)) {
4918  $this->questions = array_flip($a_order);
4919  $this->saveQuestionsToDB();
4920  }
4921  }
4922 
4923  public function getPoolUsage()
4924  {
4925  return $this->pool_usage;
4926  }
4927 
4928  public function setPoolUsage($a_value)
4929  {
4930  $this->pool_usage = (bool) $a_value;
4931  }
4932 
4938  public function isPoolActive()
4939  {
4940  $use_pool = (bool) $this->getPoolUsage();
4941  $template_settings = $this->getTemplate();
4942  if ($template_settings) {
4943  include_once "Services/Administration/classes/class.ilSettingsTemplate.php";
4944  $template_settings = new ilSettingsTemplate($template_settings);
4945  $template_settings = $template_settings->getSettings();
4946  $template_settings = $template_settings["use_pool"];
4947  if ($template_settings && $template_settings["hide"]) {
4948  $use_pool = (bool) $template_settings["value"];
4949  }
4950  }
4951  return $use_pool;
4952  }
4953 
4960  {
4961  if (!$template_id) {
4962  return;
4963  }
4964 
4965  include_once "Services/Administration/classes/class.ilSettingsTemplate.php";
4967  $template_settings = $template->getSettings();
4968  //ilUtil::dumpVar($template_settings); exit;
4969  if ($template_settings) {
4970  if ($template_settings["show_question_titles"] !== null) {
4971  if ($template_settings["show_question_titles"]["value"]) {
4972  $this->setShowQuestionTitles(true);
4973  } else {
4974  $this->setShowQuestionTitles(false);
4975  }
4976  }
4977 
4978  if ($template_settings["use_pool"] !== null) {
4979  if ($template_settings["use_pool"]["value"]) {
4980  $this->setPoolUsage(true);
4981  } else {
4982  $this->setPoolUsage(false);
4983  }
4984  }
4985 
4986 
4987  /* see #0021719
4988  if($template_settings["anonymization_options"]["value"])
4989  {
4990  $anon_map = array('personalized' => self::ANONYMIZE_OFF,
4991  'anonymize_with_code' => self::ANONYMIZE_ON,
4992  'anonymize_without_code' => self::ANONYMIZE_FREEACCESS);
4993  $this->setAnonymize($anon_map[$template_settings["anonymization_options"]["value"]]);
4994  }*/
4995 
4996  // see #0021719 and ilObjectSurveyGUI::savePropertiesObject
4997  $this->setEvaluationAccess($template_settings["evaluation_access"]["value"]);
4998  $codes = (bool) $template_settings["acc_codes"]["value"];
4999  $anon = (bool) $template_settings["anonymization_options"]["value"];
5000  if (!$anon) {
5001  if (!$codes) {
5003  } else {
5005  }
5006  } else {
5007  if ($codes) {
5009  } else {
5011  }
5012 
5013  $this->setAnonymousUserList($_POST["anon_list"]);
5014  }
5015 
5016 
5017 
5018  /* other settings: not needed here
5019  * - enabled_end_date
5020  * - enabled_start_date
5021  * - rte_switch
5022  */
5023  }
5024 
5025  $this->setTemplate($template_id);
5026  $this->saveToDb();
5027  }
5028 
5029  public function updateCode($a_id, $a_email, $a_last_name, $a_first_name, $a_sent)
5030  {
5031  $ilDB = $this->db;
5032 
5033  $a_email = trim($a_email);
5034 
5035  // :TODO:
5036  if (($a_email && !ilUtil::is_email($a_email)) || $a_email == "") {
5037  return false;
5038  }
5039 
5040  $data = array("email" => $a_email,
5041  "lastname" => trim($a_last_name),
5042  "firstname" => trim($a_first_name));
5043 
5044  $fields = array(
5045  "externaldata" => array("text", serialize($data)),
5046  "sent" => array("integer", $a_sent)
5047  );
5048 
5049  $ilDB->update(
5050  "svy_anonymous",
5051  $fields,
5052  array("anonymous_id" => array("integer", $a_id))
5053  );
5054 
5055  return true;
5056  }
5057 
5058 
5059  //
5060  // 360°
5061  //
5062 
5063  public function set360Mode($a_value)
5064  {
5065  $this->mode_360 = (bool) $a_value;
5066  }
5067 
5068  public function get360Mode()
5069  {
5070  return (bool) $this->mode_360;
5071  }
5072 
5073  public function set360SelfEvaluation($a_value)
5074  {
5075  $this->mode_360_self_eval = (bool) $a_value;
5076  }
5077 
5078  public function get360SelfEvaluation()
5079  {
5080  return (bool) $this->mode_360_self_eval;
5081  }
5082 
5083  public function set360SelfAppraisee($a_value)
5084  {
5085  $this->mode_360_self_appr = (bool) $a_value;
5086  }
5087 
5088  public function get360SelfAppraisee()
5089  {
5090  return (bool) $this->mode_360_self_appr;
5091  }
5092 
5093  public function set360SelfRaters($a_value)
5094  {
5095  $this->mode_360_self_rate = (bool) $a_value;
5096  }
5097 
5098  public function get360SelfRaters()
5099  {
5100  return (bool) $this->mode_360_self_rate;
5101  }
5102 
5103  public function set360Results($a_value)
5104  {
5105  $this->mode_360_results = (int) $a_value;
5106  }
5107 
5108  public function get360Results()
5109  {
5110  return (int) $this->mode_360_results;
5111  }
5112 
5113  public function addAppraisee($a_user_id)
5114  {
5115  global $DIC;
5116 
5117  $ilDB = $DIC->database();
5118  $access = $DIC->access();
5119 
5120  if (!$this->isAppraisee($a_user_id) &&
5121  $a_user_id != ANONYMOUS_USER_ID) {
5122  $fields = array(
5123  "obj_id" => array("integer", $this->getSurveyId()),
5124  "user_id" => array("integer", $a_user_id)
5125  );
5126  $ilDB->insert("svy_360_appr", $fields);
5127 
5128  // send notification and add to desktop
5129  if ($access->checkAccessOfUser($a_user_id, "read", "", $this->getRefId())) {
5130  $this->sendAppraiseeNotification($a_user_id);
5131  $type = ilObject::_lookupType($this->getRefId(), true);
5132  ilObjUser::_addDesktopItem($a_user_id, $this->getRefId(), $type);
5133  }
5134  }
5135  }
5136 
5142  public function sendAppraiseeNotification($a_user_id)
5143  {
5144  include_once "./Services/Notification/classes/class.ilSystemNotification.php";
5145  $ntf = new ilSystemNotification();
5146  $ntf->setLangModules(array("svy", "survey"));
5147  $ntf->setRefId($this->getRefId());
5148  $ntf->setGotoLangId('url');
5149 
5150  // user specific language
5151  $lng = $ntf->getUserLanguage($a_user_id);
5152 
5153  $ntf->setIntroductionLangId("svy_user_added_360_appraisee_mail");
5154  $subject = str_replace("%1", $this->getTitle(), $lng->txt("svy_user_added_360_appraisee"));
5155 
5156  // #10044
5157  $mail = new ilMail(ANONYMOUS_USER_ID);
5158  //$mail->enableSOAP(false); // #10410
5159  $mail->sendMail(
5160  ilObjUser::_lookupLogin($a_user_id),
5161  null,
5162  null,
5163  $subject,
5164  $ntf->composeAndGetMessage($a_user_id, null, "read", true),
5165  null,
5166  array("system")
5167  );
5168  }
5169 
5175  public function sendAppraiseeCloseNotification($a_user_id)
5176  {
5177  include_once "./Services/Notification/classes/class.ilSystemNotification.php";
5178  $ntf = new ilSystemNotification();
5179  $ntf->setLangModules(array("svy", "survey"));
5180  $ntf->setRefId($this->getRefId());
5181  $ntf->setGotoLangId('url');
5182 
5183  // user specific language
5184  $lng = $ntf->getUserLanguage($a_user_id);
5185 
5186  $ntf->setIntroductionLangId("svy_user_added_360_appraisee_close_mail");
5187  $subject = str_replace("%1", $this->getTitle(), $lng->txt("svy_user_added_360_appraisee"));
5188 
5189  // #10044
5190  $mail = new ilMail(ANONYMOUS_USER_ID);
5191  //$mail->enableSOAP(false); // #10410
5192  $mail->sendMail(
5193  ilObjUser::_lookupLogin($a_user_id),
5194  null,
5195  null,
5196  $subject,
5197  $ntf->composeAndGetMessage($a_user_id, null, "read", true),
5198  null,
5199  array("system")
5200  );
5201  }
5202 
5208  public function sendRaterNotification($a_user_id, $a_appraisee_id)
5209  {
5210  include_once "./Services/Notification/classes/class.ilSystemNotification.php";
5211  $ntf = new ilSystemNotification();
5212  $ntf->setLangModules(array("svy", "survey"));
5213  $ntf->setRefId($this->getRefId());
5214  $ntf->setGotoLangId('url');
5215 
5216  // user specific language
5217  $lng = $ntf->getUserLanguage($a_user_id);
5218 
5219  $ntf->setIntroductionLangId("svy_user_added_360_rater_mail");
5220  $subject = str_replace("%1", $this->getTitle(), $lng->txt("svy_user_added_360_rater"));
5221  $ntf->addAdditionalInfo("survey_360_appraisee", ilUserUtil::getNamePresentation($a_appraisee_id, false, false, "", true));
5222 
5223  // #10044
5224  $mail = new ilMail(ANONYMOUS_USER_ID);
5225  //$mail->enableSOAP(false); // #10410
5226  $mail->sendMail(
5227  ilObjUser::_lookupLogin($a_user_id),
5228  null,
5229  null,
5230  $subject,
5231  $ntf->composeAndGetMessage($a_user_id, null, "read", true),
5232  null,
5233  array("system")
5234  );
5235  }
5236 
5237  public function isAppraisee($a_user_id)
5238  {
5239  $ilDB = $this->db;
5240 
5241  $set = $ilDB->query("SELECT user_id" .
5242  " FROM svy_360_appr" .
5243  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5244  " AND user_id = " . $ilDB->quote($a_user_id, "integer"));
5245  return (bool) $ilDB->numRows($set);
5246  }
5247 
5248  public function isAppraiseeClosed($a_user_id)
5249  {
5250  $ilDB = $this->db;
5251 
5252  $set = $ilDB->query("SELECT has_closed" .
5253  " FROM svy_360_appr" .
5254  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5255  " AND user_id = " . $ilDB->quote($a_user_id, "integer"));
5256  $row = $ilDB->fetchAssoc($set);
5257  return $row["has_closed"];
5258  }
5259 
5260  public function deleteAppraisee($a_user_id)
5261  {
5262  $ilDB = $this->db;
5263 
5264  $ilDB->manipulate("DELETE FROM svy_360_appr" .
5265  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5266  " AND user_id = " . $ilDB->quote($a_user_id, "integer"));
5267 
5268  $set = $ilDB->query("SELECT user_id" .
5269  " FROM svy_360_rater" .
5270  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5271  " AND appr_id = " . $ilDB->quote($a_user_id, "integer"));
5272  while ($row = $ilDB->fetchAssoc($set)) {
5273  $this->deleteRater($a_user_id, $row["user_id"]);
5274  }
5275  // appraisee will not be part of raters table
5276  if ($this->get360SelfEvaluation()) {
5277  $this->deleteRater($a_user_id, $a_user_id);
5278  }
5279  }
5280 
5281  public function getAppraiseesData()
5282  {
5283  $ilDB = $this->db;
5284 
5285  $res = array();
5286 
5287  $set = $ilDB->query("SELECT * FROM svy_360_appr" .
5288  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer"));
5289  while ($row = $ilDB->fetchAssoc($set)) {
5290  $name = ilObjUser::_lookupName($row["user_id"]);
5291  $name["email"] = ilObjUser::_lookupEmail($row["user_id"]);
5292  $name["name"] = $name["lastname"] . ", " . $name["firstname"];
5293  $res[$row["user_id"]] = $name;
5294 
5295  $finished = 0;
5296  $raters = $this->getRatersData($row["user_id"]);
5297  foreach ($raters as $rater) {
5298  if ($rater["finished"]) {
5299  $finished++;
5300  }
5301  }
5302  $res[$row["user_id"]]["finished"] = $finished . "/" . sizeof($raters);
5303  $res[$row["user_id"]]["closed"] = $row["has_closed"];
5304  }
5305 
5306  return $res;
5307  }
5308 
5309  public function addRater($a_appraisee_id, $a_user_id, $a_anonymous_id = 0)
5310  {
5311  global $DIC;
5312 
5313  $ilDB = $DIC->database();
5314  $access = $DIC->access();
5315 
5316  if ($this->isAppraisee($a_appraisee_id) &&
5317  !$this->isRater($a_appraisee_id, $a_user_id, $a_anonymous_id)) {
5318  $fields = array(
5319  "obj_id" => array("integer", $this->getSurveyId()),
5320  "appr_id" => array("integer", $a_appraisee_id),
5321  "user_id" => array("integer", $a_user_id),
5322  "anonymous_id" => array("integer", $a_anonymous_id)
5323  );
5324  $ilDB->insert("svy_360_rater", $fields);
5325 
5326  // send notification and add to desktop
5327  if ($access->checkAccessOfUser($a_user_id, "read", "", $this->getRefId())) {
5328  $this->sendRaterNotification($a_user_id, $a_appraisee_id);
5329  $type = ilObject::_lookupType($this->getRefId(), true);
5330  ilObjUser::_addDesktopItem($a_user_id, $this->getRefId(), $type);
5331  }
5332  }
5333  }
5334 
5335  public function isRater($a_appraisee_id, $a_user_id, $a_anonymous_id = 0)
5336  {
5337  $ilDB = $this->db;
5338 
5339  // user is rater if already appraisee and active self-evaluation
5340  if ($this->isAppraisee($a_user_id) &&
5341  $this->get360SelfEvaluation() &&
5342  (!$a_appraisee_id || $a_appraisee_id == $a_user_id)) {
5343  return true;
5344  }
5345 
5346  // :TODO: should we get rid of code as well?
5347 
5348  $sql = "SELECT user_id" .
5349  " FROM svy_360_rater" .
5350  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5351  " AND user_id = " . $ilDB->quote($a_user_id, "integer") .
5352  " AND anonymous_id = " . $ilDB->quote($a_anonymous_id, "integer");
5353  if ($a_appraisee_id) {
5354  $sql .= " AND appr_id = " . $ilDB->quote($a_appraisee_id, "integer");
5355  }
5356  $set = $ilDB->query($sql);
5357  return (bool) $ilDB->numRows($set);
5358  }
5359 
5360  public function deleteRater($a_appraisee_id, $a_user_id, $a_anonymous_id = 0)
5361  {
5362  $ilDB = $this->db;
5363 
5364  $finished_id = $this->getFinishedIdForAppraiseeIdAndRaterId($a_appraisee_id, $a_user_id);
5365  if ($finished_id) {
5366  $this->removeSelectedSurveyResults(array($finished_id));
5367  }
5368 
5369  $ilDB->manipulate("DELETE FROM svy_360_rater" .
5370  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5371  " AND appr_id = " . $ilDB->quote($a_appraisee_id, "integer") .
5372  " AND user_id = " . $ilDB->quote($a_user_id, "integer") .
5373  " AND anonymous_id = " . $ilDB->quote($a_anonymous_id, "integer"));
5374  }
5375 
5376  public function getRatersData($a_appraisee_id)
5377  {
5378  $ilDB = $this->db;
5379 
5380  $res = $anonymous_ids = array();
5381 
5382  $set = $ilDB->query("SELECT * FROM svy_360_rater" .
5383  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5384  " AND appr_id = " . $ilDB->quote($a_appraisee_id, "integer"));
5385  while ($row = $ilDB->fetchAssoc($set)) {
5386  if ($row["anonymous_id"]) {
5387  $res["a" . $row["anonymous_id"]] = array(
5388  "lastname" => "unknown code " . $row["anonymous_id"],
5389  "sent" => $row["mail_sent"],
5390  "finished" => null
5391  );
5392  $anonymous_ids[] = $row["anonymous_id"];
5393  } else {
5394  $name = ilObjUser::_lookupName($row["user_id"]);
5395  $name["name"] = $name["lastname"] . ", " . $name["firstname"];
5396  $name["user_id"] = "u" . $name["user_id"];
5397  $name["email"] = ilObjUser::_lookupEmail($row["user_id"]);
5398  $name["sent"] = $row["mail_sent"];
5399  $name["finished"] = (bool) $this->is360SurveyStarted($a_appraisee_id, $row["user_id"]);
5400  $res["u" . $row["user_id"]] = $name;
5401  }
5402  }
5403 
5404  if (sizeof($anonymous_ids)) {
5405  $data = $this->getSurveyCodesTableData($anonymous_ids);
5406  foreach ($data as $item) {
5407  if (isset($res["a" . $item["id"]])) {
5408  $res["a" . $item["id"]] = array(
5409  "user_id" => "a" . $item["id"],
5410  "lastname" => $item["last_name"],
5411  "firstname" => $item["first_name"],
5412  "name" => $item["last_name"] . ", " . $item["first_name"],
5413  "login" => "",
5414  "email" => $item["email"],
5415  "code" => $item["code"],
5416  "href" => $item["href"],
5417  "sent" => $res["a" . $item["id"]]["sent"],
5418  "finished" => (bool) $this->is360SurveyStarted($a_appraisee_id, null, $item["code"])
5419  );
5420  }
5421  }
5422  }
5423 
5424  return $res;
5425  }
5426 
5427  public function getAppraiseesToRate($a_user_id, $a_anonymous_id = null)
5428  {
5429  $ilDB = $this->db;
5430 
5431  $res = array();
5432 
5433  $sql = "SELECT appr_id FROM svy_360_rater" .
5434  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer");
5435 
5436  if ($a_user_id) {
5437  $sql .= " AND user_id = " . $ilDB->quote($a_user_id, "integer");
5438  } else {
5439  $sql .= " AND anonymous_id = " . $ilDB->quote($a_anonymous_id, "integer");
5440  }
5441 
5442  $set = $ilDB->query($sql);
5443  while ($row = $ilDB->fetchAssoc($set)) {
5444  $res[] = $row["appr_id"];
5445  }
5446 
5447  // user may evaluate himself if already appraisee
5448  if ($this->get360SelfEvaluation() &&
5449  $this->isAppraisee($a_user_id) &&
5450  !in_array($a_user_id, $res)) {
5451  $res[] = $a_user_id;
5452  }
5453 
5454  return $res;
5455  }
5456 
5457  public function getAnonymousIdByCode($a_code)
5458  {
5459  $ilDB = $this->db;
5460 
5461  $set = $ilDB->query("SELECT anonymous_id FROM svy_anonymous" .
5462  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
5463  " AND survey_key = " . $ilDB->quote($a_code, "text"));
5464  $res = $ilDB->fetchAssoc($set);
5465  return $res["anonymous_id"];
5466  }
5467 
5468  public function is360SurveyStarted($appr_id, $user_id, $anonymous_code = null)
5469  {
5470  $ilDB = $this->db;
5471 
5472  $sql = "SELECT * FROM svy_finished" .
5473  " WHERE survey_fi =" . $ilDB->quote($this->getSurveyId(), "integer") .
5474  " AND appr_id = " . $ilDB->quote($appr_id, "integer");
5475  if ($user_id) {
5476  $sql .= " AND user_fi = " . $ilDB->quote($user_id, "integer");
5477  } else {
5478  $sql .= " AND anonymous_id = " . $ilDB->quote($anonymous_code, "text");
5479  }
5480  $result = $ilDB->query($sql);
5481  if ($result->numRows() == 0) {
5482  return false;
5483  } else {
5484  $row = $ilDB->fetchAssoc($result);
5485  return (int) $row["state"];
5486  }
5487  }
5488 
5489  public function getUserSurveyExecutionStatus($a_code = null)
5490  {
5491  $ilUser = $this->user;
5492  $ilDB = $this->db;
5493 
5494  $user_id = $ilUser->getId();
5495 
5496  // code is obligatory?
5497  if (!$this->isAccessibleWithoutCode()) {
5498  if (!$a_code) {
5499  // registered raters do not need code
5500  if ($this->get360Mode() &&
5501  $user_id != ANONYMOUS_USER_ID &&
5502  $this->isRater(0, $user_id)) {
5503  // auto-generate code
5504  $a_code = $this->createNewAccessCode();
5505  $this->saveUserAccessCode($user_id, $a_code);
5506  } else {
5507  return null;
5508  }
5509  }
5510  } elseif ($user_id == ANONYMOUS_USER_ID ||
5511  $this->getAnonymize() == self::ANONYMIZE_FREEACCESS) {
5512  if (!$a_code) {
5513  // auto-generate code
5514  $a_code = $this->createNewAccessCode();
5515  $this->saveUserAccessCode($user_id, $a_code);
5516  }
5517  } else {
5518  $a_code = null;
5519  }
5520 
5521  $res = array();
5522 
5523  $sql = "SELECT * FROM svy_finished" .
5524  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer");
5525  // if proper user id is given, use it or current code
5526  if ($user_id != ANONYMOUS_USER_ID) {
5527  $sql .= " AND (user_fi = " . $ilDB->quote($user_id, "integer") .
5528  " OR anonymous_id = " . $ilDB->quote($a_code, "text") . ")";
5529  }
5530  // use anonymous code to find finished id(s)
5531  else {
5532  $sql .= " AND anonymous_id = " . $ilDB->quote($a_code, "text");
5533  }
5534  $set = $ilDB->query($sql);
5535  while ($row = $ilDB->fetchAssoc($set)) {
5536  $res[$row["finished_id"]] = array("appr_id" => $row["appr_id"],
5537  "user_id" => $row["user_fi"],
5538  "code" => $row["anonymous_id"],
5539  "finished" => (bool) $row["state"]);
5540  }
5541 
5542  return array("code"=>$a_code, "runs"=>$res);
5543  }
5544 
5545  public function findCodeForUser($a_user_id)
5546  {
5547  $ilDB = $this->db;
5548 
5549  if ($a_user_id != ANONYMOUS_USER_ID) {
5550  $set = $ilDB->query("SELECT sf.anonymous_id FROM svy_finished sf" .
5551  " WHERE sf.survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
5552  " AND sf.user_fi = " . $ilDB->quote($a_user_id, "integer"));
5553  $a_code = $ilDB->fetchAssoc($set);
5554  return $a_code["anonymous_id"];
5555  }
5556  }
5557 
5558  public function isUnusedCode($a_code, $a_user_id)
5559  {
5560  $ilDB = $this->db;
5561 
5562  $set = $ilDB->query("SELECT user_fi FROM svy_finished" .
5563  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
5564  " AND anonymous_id = " . $ilDB->quote($a_code, "text"));
5565  $user_id = $ilDB->fetchAssoc($set);
5566  $user_id = $user_id["user_fi"];
5567 
5568  if ($user_id && ($user_id != $a_user_id || $user_id == ANONYMOUS_USER_ID)) {
5569  return false;
5570  }
5571  return true;
5572  }
5573 
5574  public function getFinishedIdsForAppraiseeId($a_appr_id, $a_exclude_appraisee = false)
5575  {
5576  $ilDB = $this->db;
5577 
5578  $res = array();
5579 
5580  $set = $ilDB->query("SELECT finished_id, user_fi FROM svy_finished" .
5581  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
5582  " AND appr_id = " . $ilDB->quote($a_appr_id, "integer"));
5583  while ($row = $ilDB->fetchAssoc($set)) {
5584  if ($a_exclude_appraisee && $row["user_fi"] == $a_appr_id) {
5585  continue;
5586  }
5587  $res[] = $row["finished_id"];
5588  }
5589 
5590  return $res;
5591  }
5592 
5600  public function getFinishedIdForAppraiseeIdAndRaterId($a_appr_id, $a_rat_id)
5601  {
5602  $ilDB = $this->db;
5603 
5604  $set = $ilDB->query("SELECT finished_id, user_fi FROM svy_finished" .
5605  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
5606  " AND appr_id = " . $ilDB->quote($a_appr_id, "integer") .
5607  " AND user_fi = " . $ilDB->quote($a_rat_id, "integer"));
5608  $row = $ilDB->fetchAssoc($set);
5609  return $row["finished_id"];
5610  }
5611 
5612 
5613  // 360° using competence/skill service
5614 
5620  public function set360SkillService($a_val)
5621  {
5622  $this->mode_360_skill_service = $a_val;
5623  }
5624 
5630  public function get360SkillService()
5631  {
5633  }
5634 
5635  public function set360RaterSent($a_appraisee_id, $a_user_id, $a_anonymous_id, $a_tstamp = null)
5636  {
5637  $ilDB = $this->db;
5638 
5639  if (!$a_tstamp) {
5640  $a_tstamp = time();
5641  }
5642 
5643  $ilDB->manipulate("UPDATE svy_360_rater" .
5644  " SET mail_sent = " . $ilDB->quote($a_tstamp, "integer") .
5645  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5646  " AND appr_id = " . $ilDB->quote($a_appraisee_id, "integer") .
5647  " AND user_id = " . $ilDB->quote($a_user_id, "integer") .
5648  " AND anonymous_id = " . $ilDB->quote($a_anonymous_id, "integer"));
5649  }
5650 
5651  public function closeAppraisee($a_user_id)
5652  {
5653  global $DIC;
5654 
5655  $ilDB = $DIC->database();
5656  $user = $DIC->user();
5657 
5658  // close the appraisee
5659  $ilDB->manipulate("UPDATE svy_360_appr" .
5660  " SET has_closed = " . $ilDB->quote(time(), "integer") .
5661  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer") .
5662  " AND user_id = " . $ilDB->quote($a_user_id, "integer"));
5663 
5664  // write competences
5665  include_once("./Services/Skill/classes/class.ilSkillManagementSettings.php");
5666  $skmg_set = new ilSkillManagementSettings();
5667  if ($this->get360SkillService() && $skmg_set->isActivated()) {
5668  include_once("./Modules/Survey/classes/class.ilSurveySkill.php");
5669  $sskill = new ilSurveySkill($this);
5670  $sskill->writeAppraiseeSkills($a_user_id);
5671  }
5672 
5673  // send notification
5674  if ($user->getId() != $a_user_id) {
5675  $this->sendAppraiseeCloseNotification($a_user_id);
5676  }
5677  }
5678 
5679  public function openAllAppraisees()
5680  {
5681  $ilDB = $this->db;
5682 
5683  $ilDB->manipulate("UPDATE svy_360_appr" .
5684  " SET has_closed = " . $ilDB->quote(null, "integer") .
5685  " WHERE obj_id = " . $ilDB->quote($this->getSurveyId(), "integer"));
5686  }
5687 
5688  public static function validateExternalRaterCode($a_ref_id, $a_code)
5689  {
5690  if (!isset($_SESSION["360_extrtr"][$a_ref_id])) {
5691  $svy = new self($a_ref_id);
5692  $svy->loadFromDB();
5693 
5694  if ($svy->canStartSurvey(null, true) &&
5695  $svy->get360Mode() &&
5696  $svy->isAnonymousKey($a_code)) {
5697  $anonymous_id = $svy->getAnonymousIdByCode($a_code);
5698  if ($anonymous_id) {
5699  if (sizeof($svy->getAppraiseesToRate(null, $anonymous_id))) {
5700  $_SESSION["360_extrtr"][$a_ref_id] = true;
5701  return true;
5702  }
5703  }
5704  }
5705 
5706  $_SESSION["360_extrtr"][$a_ref_id] = false;
5707  return false;
5708  }
5709 
5710  return $_SESSION["360_extrtr"][$a_ref_id];
5711  }
5712 
5713 
5714  //
5715  // reminder/notification
5716  //
5717 
5718  public function getReminderStatus()
5719  {
5720  return (bool) $this->reminder_status;
5721  }
5722 
5723  public function setReminderStatus($a_value)
5724  {
5725  $this->reminder_status = (bool) $a_value;
5726  }
5727 
5728  public function getReminderStart()
5729  {
5730  return $this->reminder_start;
5731  }
5732 
5733  public function setReminderStart(ilDate $a_value = null)
5734  {
5735  $this->reminder_start = $a_value;
5736  }
5737 
5738  public function getReminderEnd()
5739  {
5740  return $this->reminder_end;
5741  }
5742 
5743  public function setReminderEnd(ilDate $a_value = null)
5744  {
5745  $this->reminder_end = $a_value;
5746  }
5747 
5748  public function getReminderFrequency()
5749  {
5751  }
5752 
5753  public function setReminderFrequency($a_value)
5754  {
5755  $this->reminder_frequency = (int) $a_value;
5756  }
5757 
5758  public function getReminderTarget()
5759  {
5760  return $this->reminder_target;
5761  }
5762 
5763  public function setReminderTarget($a_value)
5764  {
5765  $this->reminder_target = (int) $a_value;
5766  }
5767 
5768  public function getReminderLastSent()
5769  {
5771  }
5772 
5773  public function setReminderLastSent($a_value)
5774  {
5775  $this->reminder_last_sent = $a_value;
5776  }
5777 
5778  public function getReminderTemplate()
5779  {
5780  return $this->reminder_tmpl;
5781  }
5782 
5783  public function setReminderTemplate($a_value)
5784  {
5785  $this->reminder_tmpl = $a_value;
5786  }
5787 
5788  public function getTutorNotificationStatus()
5789  {
5790  return (bool) $this->tutor_ntf_status;
5791  }
5792 
5793  public function setTutorNotificationStatus($a_value)
5794  {
5795  $this->tutor_ntf_status = (bool) $a_value;
5796  }
5797 
5799  {
5801  }
5802 
5803  public function setTutorNotificationRecipients(array $a_value)
5804  {
5805  $this->tutor_ntf_recipients = $a_value;
5806  }
5807 
5808  public function getTutorNotificationTarget()
5809  {
5810  return $this->tutor_ntf_target;
5811  }
5812 
5813  public function setTutorNotificationTarget($a_value)
5814  {
5815  $this->tutor_ntf_target = (int) $a_value;
5816  }
5817 
5818  protected function checkTutorNotification()
5819  {
5820  $ilDB = $this->db;
5821 
5822  if ($this->getTutorNotificationStatus()) {
5823  $user_ids = $this->getNotificationTargetUserIds(($this->getTutorNotificationTarget() == self::NOTIFICATION_INVITED_USERS));
5824  if ($user_ids) {
5825  $set = $ilDB->query("SELECT COUNT(*) numall FROM svy_finished" .
5826  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
5827  " AND state = " . $ilDB->quote(1, "integer") .
5828  " AND " . $ilDB->in("user_fi", $user_ids, "", "integer"));
5829  $row = $ilDB->fetchAssoc($set);
5830  if ($row["numall"] == sizeof($user_ids)) {
5831  $this->sendTutorNotification();
5832  }
5833  }
5834  }
5835  }
5836 
5843  public function sent360Reminders()
5844  {
5845  global $DIC;
5846 
5847  $access = $DIC->access();
5848 
5849  // collect all open ratings
5850  $rater_ids = array();
5851  foreach ($this->getAppraiseesData() as $app) {
5852  $this->log->debug("Handle appraisee " . $app['user_id']);
5853 
5854  if (!$this->isAppraiseeClosed($app['user_id'])) {
5855  $this->log->debug("Check self evaluation, self: " . $this->get360SelfAppraisee() . ", target: " . $this->getReminderTarget());
5856 
5857  // self evaluation?
5858  if ($this->get360SelfEvaluation() &&
5860  $this->log->debug("...1");
5861  // did user already finished self evaluation?
5862  if (!$this->is360SurveyStarted($app['user_id'], $app['user_id'])) {
5863  $this->log->debug("...2");
5864  if (!is_array($rater_ids[$app['user_id']])) {
5865  $rater_ids[$app['user_id']] = array();
5866  }
5867  if (!in_array($app["user_id"], $rater_ids[$app['user_id']])) {
5868  $rater_ids[$app['user_id']][] = $app["user_id"];
5869  }
5870  }
5871  }
5872 
5873  $this->log->debug("Check raters.");
5874 
5875  // should raters be notified?
5877  foreach ($this->getRatersData($app['user_id']) as $rater) {
5878  // is rater not anonymous and did not rate yet?
5879  if (!$rater["anonymous_id"] && !$rater["finished"]) {
5880  if (!is_array($rater_ids[$rater["user_id"]])) {
5881  $rater_ids[$rater["user_id"]] = array();
5882  }
5883  if (!in_array($app["user_id"], $rater_ids[$rater["user_id"]])) {
5884  $rater_ids[$rater["user_id"]][] = $app["user_id"];
5885  }
5886  }
5887  }
5888  }
5889  }
5890  }
5891 
5892  $this->log->debug("Found raters:" . count($rater_ids));
5893 
5894  foreach ($rater_ids as $id => $app) {
5895  if ($access->checkAccessOfUser($id, "read", "", $this->getRefId())) {
5896  $this->send360ReminderToUser($id, $app);
5897  }
5898  }
5899  }
5900 
5906  public function send360ReminderToUser($a_user_id, $a_appraisee_ids)
5907  {
5908  $this->log->debug("Send mail to:" . $a_user_id);
5909 
5910  include_once "./Services/Notification/classes/class.ilSystemNotification.php";
5911  $ntf = new ilSystemNotification();
5912  $ntf->setLangModules(array("svy", "survey"));
5913  $ntf->setRefId($this->getRefId());
5914  $ntf->setGotoLangId('url');
5915 
5916  // user specific language
5917  $lng = $ntf->getUserLanguage($a_user_id);
5918 
5919  $ntf->setIntroductionLangId("svy_user_added_360_rater_reminder_mail");
5920  $subject = str_replace("%1", $this->getTitle(), $lng->txt("svy_user_added_360_rater"));
5921 
5922  foreach ($a_appraisee_ids as $appraisee_id) {
5923  $ntf->addAdditionalInfo("survey_360_appraisee", ilUserUtil::getNamePresentation($appraisee_id, false, false, "", true));
5924  }
5925 
5926  // #10044
5927  $mail = new ilMail(ANONYMOUS_USER_ID);
5928  $mail->enableSOAP(false); // #10410
5929  $mail->sendMail(
5930  ilObjUser::_lookupLogin($a_user_id),
5931  null,
5932  null,
5933  $subject,
5934  $ntf->composeAndGetMessage($a_user_id, null, "read", true),
5935  null,
5936  array("system")
5937  );
5938  }
5939 
5940 
5941  public function getNotificationTargetUserIds($a_use_invited)
5942  {
5943  $tree = $this->tree;
5944 
5945  if ((bool) $a_use_invited) {
5946  $user_ids = $this->getInvitedUsers();
5947  } else {
5948  $parent_grp_ref_id = $tree->checkForParentType($this->getRefId(), "grp");
5949  if ($parent_grp_ref_id) {
5950  include_once "Modules/Group/classes/class.ilGroupParticipants.php";
5951  $part = new ilGroupParticipants(ilObject::_lookupObjId($parent_grp_ref_id));
5952  $user_ids = $part->getMembers();
5953  } else {
5954  $parent_crs_ref_id = $tree->checkForParentType($this->getRefId(), "crs");
5955  if ($parent_crs_ref_id) {
5956  include_once "Modules/Course/classes/class.ilCourseParticipants.php";
5957  $part = new ilCourseParticipants(ilObject::_lookupObjId($parent_crs_ref_id));
5958  $user_ids = $part->getMembers();
5959  }
5960  }
5961  }
5962  return $user_ids;
5963  }
5964 
5965  protected function sendTutorNotification()
5966  {
5967  include_once "./Services/Mail/classes/class.ilMail.php";
5968  include_once "./Services/User/classes/class.ilObjUser.php";
5969  include_once "./Services/Language/classes/class.ilLanguageFactory.php";
5970  include_once "./Services/User/classes/class.ilUserUtil.php";
5971  include_once "./Services/Link/classes/class.ilLink.php";
5972  $link = ilLink::_getStaticLink($this->getRefId(), "svy");
5973 
5974  foreach ($this->getTutorNotificationRecipients() as $user_id) {
5975  // use language of recipient to compose message
5976  $ulng = ilLanguageFactory::_getLanguageOfUser($user_id);
5977  $ulng->loadLanguageModule('survey');
5978 
5979  $subject = sprintf($ulng->txt('survey_notification_tutor_subject'), $this->getTitle());
5980  $message = sprintf($ulng->txt('survey_notification_tutor_salutation'), ilObjUser::_lookupFullname($user_id)) . "\n\n";
5981 
5982  $message .= $ulng->txt('survey_notification_tutor_body') . ":\n\n";
5983  $message .= $ulng->txt('obj_svy') . ": " . $this->getTitle() . "\n";
5984  $message .= "\n" . $ulng->txt('survey_notification_tutor_link') . ": " . $link;
5985 
5986  $mail_obj = new ilMail(ANONYMOUS_USER_ID);
5987  $mail_obj->appendInstallationSignature(true);
5988  $mail_obj->sendMail(
5989  ilObjUser::_lookupLogin($user_id),
5990  "",
5991  "",
5992  $subject,
5993  $message,
5994  array(),
5995  array("system")
5996  );
5997  }
5998  }
5999 
6000  public function checkReminder()
6001  {
6002  $ilDB = $this->db;
6003  $ilAccess = $this->access;
6004 
6005  $now = time();
6006  $now_with_format = date("YmdHis", $now);
6007  $today = date("Y-m-d");
6008 
6009  $this->log->debug("Check status and dates.");
6010 
6011  // object settings / participation period
6012  if ($this->isOffline() ||
6013  !$this->getReminderStatus() ||
6014  ($this->getStartDate() && $now_with_format < $this->getStartDate()) ||
6015  ($this->getEndDate() && $now_with_format > $this->getEndDate())) {
6016  return false;
6017  }
6018 
6019  // reminder period
6020  $start = $this->getReminderStart();
6021  if ($start) {
6022  $start = $start->get(IL_CAL_DATE);
6023  }
6024  $end = $this->getReminderEnd();
6025  if ($end) {
6026  $end = $end->get(IL_CAL_DATE);
6027  }
6028  if ($today < $start ||
6029  ($end && $today > $end)) {
6030  return false;
6031  }
6032 
6033  $this->log->debug("Check access period.");
6034 
6035  // object access period
6036  include_once "Services/Object/classes/class.ilObjectActivation.php";
6037  $item_data = ilObjectActivation::getItem($this->getRefId());
6038  if ($item_data["timing_type"] == ilObjectActivation::TIMINGS_ACTIVATION &&
6039  ($now < $item_data["timing_start"] ||
6040  $now > $item_data["timing_end"])) {
6041  return false;
6042  }
6043 
6044  $this->log->debug("Check frequency.");
6045 
6046  // check frequency
6047  $cut = new ilDate($today, IL_CAL_DATE);
6048  $cut->increment(IL_CAL_DAY, $this->getReminderFrequency()*-1);
6049  if (!$this->getReminderLastSent() ||
6050  $cut->get(IL_CAL_DATE) >= substr($this->getReminderLastSent(), 0, 10)) {
6051  $missing_ids = array();
6052 
6053  if (!$this->get360Mode()) {
6054  $this->log->debug("Entering survey mode.");
6055 
6056  // #16871
6057  $user_ids = $this->getNotificationTargetUserIds(($this->getReminderTarget() == self::NOTIFICATION_INVITED_USERS));
6058  if ($user_ids) {
6059  // gather participants who already finished
6060  $finished_ids = array();
6061  $set = $ilDB->query("SELECT user_fi FROM svy_finished" .
6062  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer") .
6063  " AND state = " . $ilDB->quote(1, "text") .
6064  " AND " . $ilDB->in("user_fi", $user_ids, "", "integer"));
6065  while ($row = $ilDB->fetchAssoc($set)) {
6066  $finished_ids[] = $row["user_fi"];
6067  }
6068 
6069  // some users missing out?
6070  $missing_ids = array_diff($user_ids, $finished_ids);
6071  if ($missing_ids) {
6072  foreach ($missing_ids as $idx => $user_id) {
6073  // should be able to participate
6074  if (!$ilAccess->checkAccessOfUser($user_id, "read", "", $this->getRefId(), "svy", $this->getId())) {
6075  unset($missing_ids[$idx]);
6076  }
6077  }
6078  }
6079  if ($missing_ids) {
6080  $this->sentReminder($missing_ids);
6081  }
6082  }
6083  } else {
6084  $this->log->debug("Entering 360 mode.");
6085 
6086  $this->sent360Reminders();
6087  }
6088 
6089 
6090  $this->setReminderLastSent($today);
6091  $this->saveToDb();
6092 
6093  return sizeof($missing_ids);
6094  }
6095 
6096  return false;
6097  }
6098 
6099  protected function sentReminder(array $a_recipient_ids)
6100  {
6101  include_once "./Services/Mail/classes/class.ilMail.php";
6102 
6103  // use mail template
6104  if ($this->getReminderTemplate() &&
6105  array_key_exists($this->getReminderTemplate(), $this->getReminderMailTemplates())) {
6106  $prov = new ilMailTemplateDataProvider();
6107  $tmpl = $prov->getTemplateById($this->getReminderTemplate());
6108 
6109  $tmpl_params = array(
6110  "ref_id" => $this->getRefId(),
6111  "ts" => time()
6112  );
6113  } else {
6114  $tmpl = null;
6115 
6116  include_once "./Services/Link/classes/class.ilLink.php";
6117  $link = ilLink::_getStaticLink($this->getRefId(), "svy");
6118 
6119  include_once "./Services/Language/classes/class.ilLanguageFactory.php";
6120  }
6121 
6122  foreach ($a_recipient_ids as $user_id) {
6123  if ($tmpl) {
6124  $subject = $tmpl->getSubject();
6125  $message = $this->sentReminderPlaceholders($tmpl->getMessage(), $user_id, $tmpl_params);
6126  }
6127  // use lng
6128  else {
6129  // use language of recipient to compose message
6130  $ulng = ilLanguageFactory::_getLanguageOfUser($user_id);
6131  $ulng->loadLanguageModule('survey');
6132 
6133  $subject = sprintf($ulng->txt('survey_reminder_subject'), $this->getTitle());
6134  $message = sprintf($ulng->txt('survey_reminder_salutation'), ilObjUser::_lookupFullname($user_id)) . "\n\n";
6135 
6136  $message .= $ulng->txt('survey_reminder_body') . ":\n\n";
6137  $message .= $ulng->txt('obj_svy') . ": " . $this->getTitle() . "\n";
6138  $message .= "\n" . $ulng->txt('survey_reminder_link') . ": " . $link;
6139  }
6140 
6141  $mail_obj = new ilMail(ANONYMOUS_USER_ID);
6142  $mail_obj->appendInstallationSignature(true);
6143  $mail_obj->sendMail(
6144  ilObjUser::_lookupLogin($user_id),
6145  "",
6146  "",
6147  $subject,
6148  $message,
6149  array(),
6150  array("system")
6151  );
6152  }
6153  }
6154 
6155  public function setActivationStartDate($starting_time = null)
6156  {
6157  $this->activation_starting_time = $starting_time;
6158  }
6159 
6160  public function setActivationEndDate($ending_time = null)
6161  {
6162  $this->activation_ending_time = $ending_time;
6163  }
6164 
6165  public function getActivationStartDate()
6166  {
6167  return (strlen($this->activation_starting_time)) ? $this->activation_starting_time : null;
6168  }
6169 
6170  public function getActivationEndDate()
6171  {
6172  return (strlen($this->activation_ending_time)) ? $this->activation_ending_time : null;
6173  }
6174 
6175  public function setViewOwnResults($a_value)
6176  {
6177  $this->view_own_results = (bool) $a_value;
6178  }
6179 
6180  public function hasViewOwnResults()
6181  {
6182  return $this->view_own_results;
6183  }
6184 
6185  public function setMailOwnResults($a_value)
6186  {
6187  $this->mail_own_results = (bool) $a_value;
6188  }
6189 
6190  public function hasMailOwnResults()
6191  {
6192  return $this->mail_own_results;
6193  }
6194 
6195  public function setMailConfirmation($a_value)
6196  {
6197  $this->mail_confirmation = (bool) $a_value;
6198  }
6199 
6200  public function hasMailConfirmation()
6201  {
6202  return $this->mail_confirmation;
6203  }
6204 
6205  public function setAnonymousUserList($a_value)
6206  {
6207  $this->anon_user_list = (bool) $a_value;
6208  }
6209 
6210  public function hasAnonymousUserList()
6211  {
6212  return $this->anon_user_list;
6213  }
6214 
6215  public static function getSurveySkippedValue()
6216  {
6217  global $DIC;
6218 
6219  $lng = $DIC->language();
6220 
6221  // #13541
6222 
6223  include_once "./Services/Administration/classes/class.ilSetting.php";
6224  $surveySetting = new ilSetting("survey");
6225  if (!$surveySetting->get("skipped_is_custom", false)) {
6226  return $lng->txt("skipped");
6227  } else {
6228  return $surveySetting->get("skipped_custom_value", "");
6229  }
6230  }
6231 
6232  public function getReminderMailTemplates()
6233  {
6234  $res = array();
6235 
6236  include_once "Services/Mail/classes/class.ilMailTemplateDataProvider.php";
6237  include_once "Modules/Survey/classes/class.ilSurveyMailTemplateReminderContext.php";
6238  $mprov = new ilMailTemplateDataProvider();
6239  foreach ($mprov->getTemplateByContextId(ilSurveyMailTemplateReminderContext::ID) as $tmpl) {
6240  $res[$tmpl->getTplId()] = $tmpl->getTitle();
6241  }
6242 
6243  return $res;
6244  }
6245 
6246  protected function sentReminderPlaceholders($a_message, $a_user_id, array $a_context_params)
6247  {
6248  // see ilMail::replacePlaceholders()
6249  include_once "Modules/Survey/classes/class.ilSurveyMailTemplateReminderContext.php";
6250 
6251  try {
6252  require_once 'Services/Mail/classes/class.ilMailTemplateService.php';
6254 
6255  $user = new ilObjUser($a_user_id);
6256 
6257  require_once 'Services/Mail/classes/class.ilMailTemplatePlaceholderResolver.php';
6258  require_once 'Services/Mail/classes/class.ilMailFormCall.php';
6259  $processor = new ilMailTemplatePlaceholderResolver($context, $a_message);
6260  $a_message = $processor->resolve($user, ilMailFormCall::getContextParameters());
6261  } catch (Exception $e) {
6262  require_once './Services/Logging/classes/public/class.ilLoggerFactory.php';
6263  ilLoggerFactory::getLogger('mail')->error(__METHOD__ . ' has been called with invalid context.');
6264  }
6265 
6266  return $a_message;
6267  }
6268 } // END class.ilObjSurvey
createSurveyCodes($nrOfCodes)
$files
Definition: add-vimline.php:18
$params
Definition: disable.php:11
showQuestionTitles()
Sets the question titles visible during the query.
sendNotificationMail($user_id, $anonymize_id, $appr_id)
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()
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)
deleteRater($a_appraisee_id, $a_user_id, $a_anonymous_id=0)
const IL_CAL_DATETIME
& getEvaluationByUser($questions, $active_id)
Calculates the evaluation data for a given user or anonymous id.
processPrintoutput2FO($print_output)
Convert a print output to XSL-FO.
setReminderLastSent($a_value)
$_SESSION["AccountId"]
$result
static _getUsedHTMLTagsAsString($a_module="")
Returns a string of all allowed HTML tags for text editing.
set360Results($a_value)
const EVALUATION_ACCESS_OFF
getParticipantTextResults($active_id)
applySettingsTemplate($template_id)
Apply settings template.
$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"]
isOffline()
Gets the survey status.
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)
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.
static formatDate(ilDateTime $date, $a_skip_day=false, $a_include_wd=false)
Format a date public.
$dataset
Definition: showstats.php:45
setReminderFrequency($a_value)
removeQuestion($question_id)
Remove a question from the survey.
static getItem($a_ref_id)
Get item data.
$end
Definition: saml1-acs.php:18
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.
$GLOBALS['loaded']
Global hash that tracks already loaded includes.
deleteConstraint($constraint_id)
Deletes a constraint of a question.
setAuthor($author="")
Sets the authors name of the ilObjSurvey object.
const NOTIFICATION_APPRAISEES
isOnline()
Gets the survey status.
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.
cloneObject($a_target_id, $a_copy_id=0, $a_omit_tree=false)
Clone object.
XML writer class.
getUserDataFromActiveId($active_id, $force_non_anonymous=false)
Returns the user information from an active_id (survey_finished.finished_id)
$userdata
Definition: demo.php:48
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.
& 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...
set360Mode($a_value)
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)
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__']
set360SkillService($a_val)
Set skill service.
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...
Survey exception class.
const INVITATION_ON
Class ilMailTemplateDataProvider.
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.
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.
$counter
getEndDate()
Gets the end date of the survey.
$time
Definition: cron.php:21
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.
$xml
Definition: metadata.php:240
isHTML($a_text)
Checks if a given string contains HTML or not.
hideQuestionTitles()
Sets the question titles hidden during the query.
if(!is_dir( $entity_dir)) exit("Fatal Error ([A-Za-z0-9]+)\+" &#(? foreach( $entity_files as $file) $output
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
if($format !==null) $name
Definition: metadata.php:146
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.
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 NOTIFICATION_APPRAISEES_AND_RATERS
getFinishedIdsForAppraiseeId($a_appr_id, $a_exclude_appraisee=false)
This class handles base functions for mail handling.
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
date( 'd-M-Y', $objPHPExcel->getProperties() ->getCreated())
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)
setStatus($status=self::STATUS_OFFLINE)
Sets the survey status.
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.
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
$old
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.
Create styles array
The data for the language used.
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.
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.
getStatus()
Gets the survey status.
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)
Create a temporary file in an ILIAS writable 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.
$messages
Definition: en-x-test.php:7
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)
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.
update()
update object data
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.
global $ilDB
saveAuthorToMetadata($a_author="")
Saves an authors name into the lifecycle metadata if no lifecycle metadata exists This will only be c...
$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
get360SkillService()
Get skill service.
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
Add data(end) time
Method that wraps PHPs time in order to allow simulations with the workflow.
if(!file_exists("$old.txt")) if($old===$new) if(file_exists("$new.txt")) $file
getOutro()
Gets the outro text.
$source
Definition: linkback.php:22
getUserSettings($usr_id, $key)
const IL_CAL_TIMESTAMP
sentReminder(array $a_recipient_ids)
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"]
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.
deleteAllUserData()
Deletes all user data of a survey.
isSurveyStarted($user_id, $anonymize_id, $appr_id=0)
Checks if a user already started a survey.
loadQuestionsFromDb()
Loads the survey questions from the database.
sent360Reminders()
Send 360 reminders.
deleteAppraisee($a_user_id)
for($i=6; $i< 13; $i++) for($i=1; $i< 13; $i++) $d
Definition: date.php:296
setOutro($outro="")
Sets the outro text.
fixSequenceStructure()
Remove duplicate sequence entries, see #22018.
getPrecondition($id)
Returns a precondition with a given id.
addQuestionToBlock($question_id, $questionblock_id)
$insert