ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
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 {
17  const STATUS_OFFLINE = 0;
18  const STATUS_ONLINE = 1;
19 
23 
24  const INVITATION_OFF = 0;
25  const INVITATION_ON = 1;
26 
27  const MODE_UNLIMITED = 0;
29 
30  const ANONYMIZE_OFF = 0; // personalized, no codes
31  const ANONYMIZE_ON = 1; // anonymized, codes
32  const ANONYMIZE_FREEACCESS = 2; // anonymized, no codes
33  const ANONYMIZE_CODE_ALL = 3; // personalized, codes
34 
37 
45 
52  var $author;
53 
60 
66  var $outro;
67 
73  var $status;
74 
81 
88 
94  var $end_date;
95 
102 
109 
116 
122 
128 
135 
141 
145  protected $log;
146 
150 
151  // 360°
152  protected $mode_360; // [bool]
153  protected $mode_360_self_eval; // [bool]
154  protected $mode_360_self_appr; // [bool]
155  protected $mode_360_self_rate; // [bool]
156  protected $mode_360_results; // [int]
157  protected $mode_360_skill_service; // [bool]
158 
159  const RESULTS_360_NONE = 0;
160  const RESULTS_360_OWN = 1;
161  const RESULTS_360_ALL = 2;
162 
163  // reminder/notification
164  protected $reminder_status; // [bool]
165  protected $reminder_start; // [ilDate]
166  protected $reminder_end; // [ilDate]
167  protected $reminder_frequency; // [int]
168  protected $reminder_target; // [int]
169  protected $reminder_last_sent; // [bool]
170  protected $reminder_tmpl; // [int]
171  protected $tutor_ntf_status; // [bool]
172  protected $tutor_ntf_recipients; // [array]
173  protected $tutor_ntf_target; // [int]
174 
175  protected $view_own_results; // [bool]
176  protected $mail_own_results; // [bool]
177  protected $mail_confirmation; // [bool]
178 
179  protected $anon_user_list; // [bool]
180 
183 
184 
191  function __construct($a_id = 0,$a_call_by_reference = true)
192  {
193  global $ilUser, $lng;
194 
195  $this->type = "svy";
196  $this->survey_id = -1;
197  $this->introduction = "";
198  $this->outro = $lng->txt("survey_finished");
199  $this->author = $ilUser->getFullname();
200  $this->status = self::STATUS_OFFLINE;
201  $this->evaluation_access = self::EVALUATION_ACCESS_OFF;
202  $this->questions = array();
203  $this->invitation = self::INVITATION_OFF;
204  $this->invitation_mode = self::MODE_PREDEFINED_USERS;
205  $this->anonymize = self::ANONYMIZE_OFF;
206  $this->display_question_titles = self::QUESTIONTITLES_VISIBLE;
207  $this->surveyCodeSecurity = TRUE;
208  $this->template_id = NULL;
209  $this->pool_usage = true;
210  $this->log = ilLoggerFactory::getLogger("svy");
211 
212  parent::__construct($a_id,$a_call_by_reference);
213  }
214 
218  function create($a_upload = false)
219  {
220  parent::create();
221  if(!$a_upload)
222  {
223  $this->createMetaData();
224  }
225  }
226 
232  function createMetaData()
233  {
234  parent::createMetaData();
235  $this->saveAuthorToMetadata();
236  }
237 
244  function update()
245  {
246  $this->updateMetaData();
247 
248  if (!parent::update())
249  {
250  return false;
251  }
252 
253  // put here object specific stuff
254 
255  return true;
256  }
257 
258  function createReference()
259  {
260  $result = parent::createReference();
261  $this->saveToDb();
262  return $result;
263  }
264 
269  public function read()
270  {
271  parent::read();
272  $this->loadFromDb();
273  }
274 
281  function addQuestion($question_id)
282  {
283  array_push($this->questions, $question_id);
284  }
285 
292  function delete()
293  {
294  if ($this->countReferences() == 1)
295  {
296  $this->deleteMetaData();
297 
298  // Delete all survey questions, constraints and materials
299  foreach ($this->questions as $question_id)
300  {
301  $this->removeQuestion($question_id);
302  }
303  $this->deleteSurveyRecord();
304 
306  }
307 
308  $remove = parent::delete();
309 
310  // always call parent delete function first!!
311  if (!$remove)
312  {
313  return false;
314  }
315  return true;
316  }
317 
324  {
325  global $ilDB;
326 
327  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_svy WHERE survey_id = %s",
328  array('integer'),
329  array($this->getSurveyId())
330  );
331 
332  $result = $ilDB->queryF("SELECT questionblock_fi FROM svy_qblk_qst WHERE survey_fi = %s",
333  array('integer'),
334  array($this->getSurveyId())
335  );
336  $questionblocks = array();
337  while ($row = $ilDB->fetchAssoc($result))
338  {
339  array_push($questionblocks, $row["questionblock_fi"]);
340  }
341  if (count($questionblocks))
342  {
343  $affectedRows = $ilDB->manipulate("DELETE FROM svy_qblk WHERE " . $ilDB->in('questionblock_id', $questionblocks, false, 'integer'));
344  }
345  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_qblk_qst WHERE survey_fi = %s",
346  array('integer'),
347  array($this->getSurveyId())
348  );
349  $this->deleteAllUserData();
350 
351  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_anonymous WHERE survey_fi = %s",
352  array('integer'),
353  array($this->getSurveyId())
354  );
355 
356  // delete export files
357  $svy_data_dir = ilUtil::getDataDir()."/svy_data";
358  $directory = $svy_data_dir."/svy_".$this->getId();
359  if (is_dir($directory))
360  {
361  ilUtil::delDir($directory);
362  }
363 
364  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
365  $mobs = ilObjMediaObject::_getMobsOfObject("svy:html", $this->getId());
366  // remaining usages are not in text anymore -> delete them
367  // and media objects (note: delete method of ilObjMediaObject
368  // checks whether object is used in another context; if yes,
369  // the object is not deleted!)
370  foreach($mobs as $mob)
371  {
372  ilObjMediaObject::_removeUsage($mob, "svy:html", $this->getId());
373  $mob_obj = new ilObjMediaObject($mob);
374  $mob_obj->delete();
375  }
376  }
377 
383  function deleteAllUserData()
384  {
385  global $ilDB;
386 
387  $result = $ilDB->queryF("SELECT finished_id FROM svy_finished WHERE survey_fi = %s",
388  array('integer'),
389  array($this->getSurveyId())
390  );
391  $active_array = array();
392  while ($row = $ilDB->fetchAssoc($result))
393  {
394  array_push($active_array, $row["finished_id"]);
395  }
396 
397  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_finished WHERE survey_fi = %s",
398  array('integer'),
399  array($this->getSurveyId())
400  );
401 
402  foreach ($active_array as $active_fi)
403  {
404  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_answer WHERE active_fi = %s",
405  array('integer'),
406  array($active_fi)
407  );
408  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_times WHERE finished_fi = %s",
409  array('integer'),
410  array($active_fi)
411  );
412  }
413 
414  include_once "Services/Object/classes/class.ilObjectLP.php";
415  $lp_obj = ilObjectLP::getInstance($this->getId());
416  $lp_obj->resetLPDataForCompleteObject();
417  }
418 
424  function removeSelectedSurveyResults($finished_ids)
425  {
426  global $ilDB;
427 
428  $user_ids[] = array();
429 
430  foreach ($finished_ids as $finished_id)
431  {
432  $result = $ilDB->queryF("SELECT finished_id FROM svy_finished WHERE finished_id = %s",
433  array('integer'),
434  array($finished_id)
435  );
436  $row = $ilDB->fetchAssoc($result);
437 
438  if($row["user_fi"])
439  {
440  $user_ids[] = $row["user_fi"];
441  }
442 
443  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_answer WHERE active_fi = %s",
444  array('integer'),
445  array($row["finished_id"])
446  );
447 
448  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_finished WHERE finished_id = %s",
449  array('integer'),
450  array($finished_id)
451  );
452 
453  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_times WHERE finished_fi = %s",
454  array('integer'),
455  array($row["finished_id"])
456  );
457  }
458 
459  if(sizeof($user_ids))
460  {
461  include_once "Services/Object/classes/class.ilObjectLP.php";
462  $lp_obj = ilObjectLP::getInstance($this->getId());
463  $lp_obj->resetLPDataForUserIds($user_ids);
464  }
465  }
466 
467  function &getSurveyParticipants($finished_ids = null, $force_non_anonymous = false)
468  {
469  global $ilDB;
470 
471  $sql = "SELECT * FROM svy_finished".
472  " WHERE survey_fi = ".$ilDB->quote($this->getSurveyId(), "integer");
473  if($finished_ids)
474  {
475  $sql .= " AND ".$ilDB->in("finished_id", $finished_ids, "", "integer");
476  }
477 
478  $result = $ilDB->query($sql);
479  $participants = array();
480  if ($result->numRows() > 0)
481  {
482  while ($row = $ilDB->fetchAssoc($result))
483  {
484  $userdata = $this->getUserDataFromActiveId($row["finished_id"], $force_non_anonymous);
485  $userdata["finished"] = (bool)$row["state"];
486  $userdata["finished_tstamp"] = $row["tstamp"];
487  $participants[$userdata["sortname"] . $userdata["active_id"]] = $userdata;
488  }
489  }
490  return $participants;
491  }
492 
499  function isComplete()
500  {
501  if (($this->getTitle()) and (count($this->questions)))
502  {
503  return 1;
504  }
505  else
506  {
507  return 0;
508  }
509  }
510 
517  {
518  global $ilDB;
519 
520  $complete = 0;
521  if ($this->isComplete())
522  {
523  $complete = 1;
524  }
525  if ($this->getSurveyId() > 0)
526  {
527  $affectedRows = $ilDB->manipulateF("UPDATE svy_svy SET complete = %s, tstamp = %s WHERE survey_id = %s",
528  array('text','integer','integer'),
529  array($this->isComplete(), time(), $this->getSurveyId())
530  );
531  }
532  }
533 
541  function duplicateQuestionForSurvey($question_id, $a_force = false)
542  {
543  global $ilUser;
544 
545  $questiontype = $this->getQuestionType($question_id);
546  $question_gui = $this->getQuestionGUI($questiontype, $question_id);
547 
548  // check if question is a pool question at all, if not do nothing
549  if($this->getId() == $question_gui->object->getObjId() && !$a_force)
550  {
551  return $question_id;
552  }
553 
554  $duplicate_id = $question_gui->object->duplicate(true, "", "", "", $this->getId());
555  return $duplicate_id;
556  }
557 
563  function insertQuestion($question_id)
564  {
565  global $ilDB;
566 
567  $this->log->debug("insert question, id:".$question_id);
568 
569  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
570  if (!SurveyQuestion::_isComplete($question_id))
571  {
572  $this->log->debug("question is not complete");
573  return FALSE;
574  }
575  else
576  {
577  // get maximum sequence index in test
578  // @todo: refactor this
579  $result = $ilDB->queryF("SELECT survey_question_id FROM svy_svy_qst WHERE survey_fi = %s",
580  array('integer'),
581  array($this->getSurveyId())
582  );
583  $sequence = $result->numRows();
584  $duplicate_id = $this->duplicateQuestionForSurvey($question_id);
585  $this->log->debug("duplicate, id: ".$question_id.", duplicate id: ".$duplicate_id);
586 
587  // check if question is not already in the survey, see #22018
588  if ($this->isQuestionInSurvey($duplicate_id))
589  {
590  return false;
591  }
592 
593  $next_id = $ilDB->nextId('svy_svy_qst');
594  $affectedRows = $ilDB->manipulateF("INSERT INTO svy_svy_qst (survey_question_id, survey_fi, question_fi, sequence, tstamp) VALUES (%s, %s, %s, %s, %s)",
595  array('integer', 'integer', 'integer', 'integer', 'integer'),
596  array($next_id, $this->getSurveyId(), $duplicate_id, $sequence, time())
597  );
598 
599  $this->log->debug("added entry to svy_svy_qst, id: ".$next_id.", question id: ".$duplicate_id.", sequence: ".$sequence);
600 
601  $this->loadQuestionsFromDb();
602  return TRUE;
603  }
604  }
605 
612  function isQuestionInSurvey($a_question_fi)
613  {
614  global $DIC;
615 //return false;
616  $ilDB = $DIC->database();
617 
618  $set = $ilDB->query("SELECT * FROM svy_svy_qst ".
619  " WHERE survey_fi = ".$ilDB->quote($this->getSurveyId(), "integer").
620  " AND question_fi = ".$ilDB->quote($a_question_fi, "integer"));
621  if ($rec = $ilDB->fetchAssoc($set))
622  {
623  return true;
624  }
625  return false;
626  }
627 
628 
629 
635  function insertQuestionblock($questionblock_id)
636  {
637  global $ilDB;
638  $result = $ilDB->queryF("SELECT svy_qblk.title, svy_qblk.show_questiontext, svy_qblk.show_blocktitle,".
639  " svy_qblk_qst.question_fi FROM svy_qblk, svy_qblk_qst, svy_svy_qst".
640  " WHERE svy_qblk.questionblock_id = svy_qblk_qst.questionblock_fi".
641  " AND svy_svy_qst.question_fi = svy_qblk_qst.question_fi".
642  " AND svy_qblk.questionblock_id = %s".
643  " ORDER BY svy_svy_qst.sequence",
644  array('integer'),
645  array($questionblock_id)
646  );
647  $questions = array();
648  $show_questiontext = 0;
649  $show_blocktitle = 0;
650  while ($row = $ilDB->fetchAssoc($result))
651  {
652  $duplicate_id = $this->duplicateQuestionForSurvey($row["question_fi"]);
653  array_push($questions, $duplicate_id);
654  $title = $row["title"];
655  $show_questiontext = $row["show_questiontext"];
656  $show_blocktitle = $row["show_blocktitle"];
657  }
658  $this->createQuestionblock($title, $show_questiontext, $show_blocktitle, $questions);
659  }
660 
661  public function saveUserSettings($usr_id, $key, $title, $value)
662  {
663  global $ilDB;
664 
665  $next_id = $ilDB->nextId('svy_settings');
666  $affectedRows = $ilDB->insert("svy_settings", array(
667  "settings_id" => array("integer", $next_id),
668  "usr_id" => array("integer", $usr_id),
669  "keyword" => array("text", $key),
670  "title" => array("text", $title),
671  "value" => array("clob", $value)
672  ));
673  }
674 
675  public function deleteUserSettings($id)
676  {
677  global $ilDB;
678 
679  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_settings WHERE settings_id = %s",
680  array('integer'),
681  array($id)
682  );
683  return $affectedRows;
684  }
685 
686  public function getUserSettings($usr_id, $key)
687  {
688  global $ilDB;
689 
690  $result = $ilDB->queryF("SELECT * FROM svy_settings WHERE usr_id = %s AND keyword = %s",
691  array('integer', 'text'),
692  array($usr_id, $key)
693  );
694  $found = array();
695  if ($result->numRows())
696  {
697  while ($row = $ilDB->fetchAssoc($result))
698  {
699  $found[$row['settings_id']] = $row;
700  }
701  }
702  return $found;
703  }
704 
710  function saveToDb()
711  {
712  global $ilDB;
713 
714  // date handling
715  $rmd_start = $this->getReminderStart();
716  if(is_object($rmd_start))
717  {
718  $rmd_start = $rmd_start->get(IL_CAL_DATE);
719  }
720  $rmd_end = $this->getReminderEnd();
721  if(is_object($rmd_end))
722  {
723  $rmd_end = $rmd_end->get(IL_CAL_DATE);
724  }
725 
726  include_once("./Services/RTE/classes/class.ilRTE.php");
727  if ($this->getSurveyId() < 1)
728  {
729  $next_id = $ilDB->nextId('svy_svy');
730  $affectedRows = $ilDB->insert("svy_svy", array(
731  "survey_id" => array("integer", $next_id),
732  "obj_fi" => array("integer", $this->getId()),
733  "author" => array("text", $this->getAuthor()),
734  "introduction" => array("clob", ilRTE::_replaceMediaObjectImageSrc($this->getIntroduction(), 0)),
735  "outro" => array("clob", ilRTE::_replaceMediaObjectImageSrc($this->getOutro(), 0)),
736  "status" => array("text", $this->getStatus()),
737  "startdate" => array("text", $this->getStartDate()),
738  "enddate" => array("text", $this->getEndDate()),
739  "evaluation_access" => array("text", $this->getEvaluationAccess()),
740  "invitation" => array("text", $this->getInvitation()),
741  "invitation_mode" => array("text", $this->getInvitationMode()),
742  "complete" => array("text", $this->isComplete()),
743  "created" => array("integer", time()),
744  "anonymize" => array("text", $this->getAnonymize()),
745  "show_question_titles" => array("text", $this->getShowQuestionTitles()),
746  "mailnotification" => array('integer', ($this->getMailNotification()) ? 1 : 0),
747  "mailaddresses" => array('text', strlen($this->getMailAddresses()) ? $this->getMailAddresses() : NULL),
748  "mailparticipantdata" => array('text', strlen($this->getMailParticipantData()) ? $this->getMailParticipantData() : NULL),
749  "tstamp" => array("integer", time()),
750  "template_id" => array("integer", $this->getTemplate()),
751  "pool_usage" => array("integer", $this->getPoolUsage()),
752  // 360°
753  "mode_360" => array("integer", $this->get360Mode()),
754  "mode_360_self_eval" => array("integer", $this->get360SelfEvaluation()),
755  "mode_360_self_rate" => array("integer", $this->get360SelfRaters()),
756  "mode_360_self_appr" => array("integer", $this->get360SelfAppraisee()),
757  "mode_360_results" => array("integer", $this->get360Results()),
758  "mode_360_skill_service" => array("integer", (int) $this->get360SkillService()),
759  // reminder/notification
760  "reminder_status" => array("integer", (int)$this->getReminderStatus()),
761  "reminder_start" => array("datetime", $rmd_start),
762  "reminder_end" => array("datetime", $rmd_end),
763  "reminder_frequency" => array("integer", (int)$this->getReminderFrequency()),
764  "reminder_target" => array("integer", (int)$this->getReminderTarget()),
765  "reminder_last_sent" => array("datetime", $this->getReminderLastSent()),
766  "reminder_tmpl" => array("text", $this->getReminderTemplate()),
767  "tutor_ntf_status" => array("integer", (int)$this->getTutorNotificationStatus()),
768  "tutor_ntf_reci" => array("text", implode(";", (array)$this->getTutorNotificationRecipients())),
769  "tutor_ntf_target" => array("integer", (int)$this->getTutorNotificationTarget()),
770  "own_results_view" => array("integer", $this->hasViewOwnResults()),
771  "own_results_mail" => array("integer", $this->hasMailOwnResults()),
772  "confirmation_mail" => array("integer", $this->hasMailConfirmation()),
773  "anon_user_list" => array("integer", $this->hasAnonymousUserList())
774  ));
775  $this->setSurveyId($next_id);
776  }
777  else
778  {
779  $affectedRows = $ilDB->update("svy_svy", array(
780  "author" => array("text", $this->getAuthor()),
781  "introduction" => array("clob", ilRTE::_replaceMediaObjectImageSrc($this->getIntroduction(), 0)),
782  "outro" => array("clob", ilRTE::_replaceMediaObjectImageSrc($this->getOutro(), 0)),
783  "status" => array("text", $this->getStatus()),
784  "startdate" => array("text", $this->getStartDate()),
785  "enddate" => array("text", $this->getEndDate()),
786  "evaluation_access" => array("text", $this->getEvaluationAccess()),
787  "invitation" => array("text", $this->getInvitation()),
788  "invitation_mode" => array("text", $this->getInvitationMode()),
789  "complete" => array("text", $this->isComplete()),
790  "anonymize" => array("text", $this->getAnonymize()),
791  "show_question_titles" => array("text", $this->getShowQuestionTitles()),
792  "mailnotification" => array('integer', ($this->getMailNotification()) ? 1 : 0),
793  "mailaddresses" => array('text', strlen($this->getMailAddresses()) ? $this->getMailAddresses() : NULL),
794  "mailparticipantdata" => array('text', strlen($this->getMailParticipantData()) ? $this->getMailParticipantData() : NULL),
795  "tstamp" => array("integer", time()),
796  "template_id" => array("integer", $this->getTemplate()),
797  "pool_usage" => array("integer", $this->getPoolUsage()),
798  // 360°
799  "mode_360" => array("integer", $this->get360Mode()),
800  "mode_360_self_eval" => array("integer", $this->get360SelfEvaluation()),
801  "mode_360_self_rate" => array("integer", $this->get360SelfRaters()),
802  "mode_360_self_appr" => array("integer", $this->get360SelfAppraisee()),
803  "mode_360_results" => array("integer", $this->get360Results()),
804  "mode_360_skill_service" => array("integer", (int) $this->get360SkillService()),
805  // reminder/notification
806  "reminder_status" => array("integer", $this->getReminderStatus()),
807  "reminder_start" => array("datetime", $rmd_start),
808  "reminder_end" => array("datetime", $rmd_end),
809  "reminder_frequency" => array("integer", $this->getReminderFrequency()),
810  "reminder_target" => array("integer", $this->getReminderTarget()),
811  "reminder_last_sent" => array("datetime", $this->getReminderLastSent()),
812  "reminder_tmpl" => array("text", $this->getReminderTemplate()),
813  "tutor_ntf_status" => array("integer", $this->getTutorNotificationStatus()),
814  "tutor_ntf_reci" => array("text", implode(";", (array)$this->getTutorNotificationRecipients())),
815  "tutor_ntf_target" => array("integer", $this->getTutorNotificationTarget()),
816  "own_results_view" => array("integer", $this->hasViewOwnResults()),
817  "own_results_mail" => array("integer", $this->hasMailOwnResults()),
818  "confirmation_mail" => array("integer", $this->hasMailConfirmation()),
819  "anon_user_list" => array("integer", $this->hasAnonymousUserList())
820  ), array(
821  "survey_id" => array("integer", $this->getSurveyId())
822  ));
823  }
824  if ($affectedRows)
825  {
826  // save questions to db
827  $this->saveQuestionsToDb();
828  }
829 
830  // moved activation to ilObjectActivation
831  if($this->ref_id)
832  {
833  include_once "./Services/Object/classes/class.ilObjectActivation.php";
834  ilObjectActivation::getItem($this->ref_id);
835 
836  $item = new ilObjectActivation;
837  if(!$this->isActivationLimited())
838  {
840  }
841  else
842  {
843  $item->setTimingType(ilObjectActivation::TIMINGS_ACTIVATION);
844  $item->setTimingStart($this->getActivationStartDate());
845  $item->setTimingEnd($this->getActivationEndDate());
846  $item->toggleVisible($this->getActivationVisibility());
847  }
848 
849  $item->update($this->ref_id);
850  }
851  }
852 
859  function saveQuestionsToDb()
860  {
861  global $ilDB;
862 
863  $this->log->debug("save questions");
864 
865  // gather old questions state
866  $old_questions = array();
867  $result = $ilDB->queryF("SELECT survey_question_id,question_fi,sequence".
868  " FROM svy_svy_qst WHERE survey_fi = %s",
869  array('integer'),
870  array($this->getSurveyId())
871  );
872  while($row = $ilDB->fetchAssoc($result))
873  {
874  $old_questions[$row["question_fi"]] = $row; // problem, as soon as duplicates exist, they will be hidden here
875  }
876 
877  // #15231 - diff with current questions state
878  $insert = $update = $delete = array();
879  foreach($this->questions as $seq => $fi)
880  {
881  if(!array_key_exists($fi, $old_questions)) // really new fi IDs
882  {
883  $insert[] = $fi; // this should be ok, should not create duplicates here
884  }
885  else if($old_questions[$fi]["sequence"] != $seq) // we are updating one of the duplicates (if any)
886  {
887  $update[$fi] = $old_questions[$fi]["survey_question_id"];
888  }
889  // keep track of still relevant questions
890  unset($old_questions[$fi]); // deleting old question, if they are not in current array
891  }
892 
893  // delete obsolete question relations
894  if(sizeof($old_questions))
895  {
896  $del_ids = array();
897  foreach($old_questions as $fi => $old)
898  {
899  $del_ids[] = $old["survey_question_id"];
900  }
901  $ilDB->manipulate($q = "DELETE FROM svy_svy_qst".
902  " WHERE ".$ilDB->in("survey_question_id", $del_ids, "", "integer"));
903  $this->log->debug("delete: ".$q);
904  }
905  unset($old_questions);
906 
907  // create/update question relations
908  foreach($this->questions as $seq => $fi)
909  {
910  if(in_array($fi, $insert))
911  {
912  // check if question is not already in the survey, see #22018
913  if (!$this->isQuestionInSurvey($fi))
914  {
915  $next_id = $ilDB->nextId('svy_svy_qst');
916  $ilDB->manipulateF("INSERT INTO svy_svy_qst" .
917  " (survey_question_id, survey_fi, question_fi, heading, sequence, tstamp)" .
918  " VALUES (%s, %s, %s, %s, %s, %s)",
919  array('integer', 'integer', 'integer', 'text', 'integer', 'integer'),
920  array($next_id, $this->getSurveyId(), $fi, null, $seq, time())
921  );
922  $this->log->debug("insert svy_svy_qst, id:" . $next_id . ", fi: " . $fi . ", seq:" . $seq);
923  }
924  }
925  else if(array_key_exists($fi, $update))
926  {
927  $ilDB->manipulate("UPDATE svy_svy_qst".
928  " SET sequence = ".$ilDB->quote($seq, "integer").
929  ", tstamp = ".$ilDB->quote(time(), "integer").
930  " WHERE survey_question_id = ".$ilDB->quote($update[$fi], "integer"));
931  $this->log->debug("update svy_svy_qst, id:".$update[$fi].", fi: ".$fi.", seq:".$seq);
932  }
933  }
934  }
935 
943  function getAnonymousId($id)
944  {
945  global $ilDB;
946  $result = $ilDB->queryF("SELECT anonymous_id FROM svy_finished WHERE anonymous_id = %s",
947  array('text'),
948  array($id)
949  );
950  if ($result->numRows())
951  {
952  $row = $ilDB->fetchAssoc($result);
953  return $row["anonymous_id"];
954  }
955  else
956  {
957  return "";
958  }
959  }
960 
967  function getQuestionGUI($questiontype, $question_id)
968  {
969  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestionGUI.php";
970  return SurveyQuestionGUI::_getQuestionGUI($questiontype, $question_id);
971  }
972 
980  function getQuestionType($question_id)
981  {
982  global $ilDB;
983  if ($question_id < 1) return -1;
984  $result = $ilDB->queryF("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  {
991  $data = $ilDB->fetchAssoc($result);
992  return $data["type_tag"];
993  }
994  else
995  {
996  return "";
997  }
998  }
999 
1006  function getSurveyId()
1007  {
1008  return $this->survey_id;
1009  }
1010 
1014  function setAnonymize($a_anonymize)
1015  {
1016  switch ($a_anonymize)
1017  {
1018  case self::ANONYMIZE_OFF:
1019  case self::ANONYMIZE_ON:
1020  case self::ANONYMIZE_FREEACCESS:
1021  case self::ANONYMIZE_CODE_ALL:
1022  $this->anonymize = $a_anonymize;
1023  break;
1024  default:
1025  $this->anonymize = self::ANONYMIZE_OFF;
1026  break;
1027  }
1028  }
1029 
1035  function getAnonymize()
1036  {
1037  return ($this->anonymize) ? $this->anonymize : 0;
1038  }
1039 
1046  {
1047  return ($this->getAnonymize() == self::ANONYMIZE_OFF ||
1048  $this->getAnonymize() == self::ANONYMIZE_FREEACCESS);
1049  }
1050 
1057  {
1058  return ($this->getAnonymize() == self::ANONYMIZE_ON ||
1059  $this->getAnonymize() == self::ANONYMIZE_FREEACCESS);
1060  }
1061 
1067  function loadFromDb()
1068  {
1069  global $ilDB;
1070  $result = $ilDB->queryF("SELECT * FROM svy_svy WHERE obj_fi = %s",
1071  array('integer'),
1072  array($this->getId())
1073  );
1074  if ($result->numRows() == 1)
1075  {
1076  $data = $ilDB->fetchAssoc($result);
1077  $this->setSurveyId($data["survey_id"]);
1078  $this->setAuthor($data["author"]);
1079  include_once("./Services/RTE/classes/class.ilRTE.php");
1080  $this->setIntroduction(ilRTE::_replaceMediaObjectImageSrc($data["introduction"], 1));
1081  if (strcmp($data["outro"], "survey_finished") == 0)
1082  {
1083  $this->setOutro($this->lng->txt("survey_finished"));
1084  }
1085  else
1086  {
1087  $this->setOutro(ilRTE::_replaceMediaObjectImageSrc($data["outro"], 1));
1088  }
1089  $this->setInvitation($data["invitation"]);
1090  $this->setInvitationMode($data["invitation_mode"]);
1091  $this->setShowQuestionTitles($data["show_question_titles"]);
1092  $this->setStartDate($data["startdate"]);
1093  $this->setEndDate($data["enddate"]);
1094  $this->setAnonymize($data["anonymize"]);
1095  $this->setEvaluationAccess($data["evaluation_access"]);
1096  $this->loadQuestionsFromDb();
1097  $this->setStatus($data["status"]);
1098  $this->setMailNotification($data['mailnotification']);
1099  $this->setMailAddresses($data['mailaddresses']);
1100  $this->setMailParticipantData($data['mailparticipantdata']);
1101  $this->setTemplate($data['template_id']);
1102  $this->setPoolUsage($data['pool_usage']);
1103  // 360°
1104  $this->set360Mode($data['mode_360']);
1105  $this->set360SelfEvaluation($data['mode_360_self_eval']);
1106  $this->set360SelfRaters($data['mode_360_self_rate']);
1107  $this->set360SelfAppraisee($data['mode_360_self_appr']);
1108  $this->set360Results($data['mode_360_results']);
1109  $this->set360SkillService($data['mode_360_skill_service']);
1110  // reminder/notification
1111  $this->setReminderStatus($data["reminder_status"]);
1112  $this->setReminderStart($data["reminder_start"] ? new ilDate($data["reminder_start"], IL_CAL_DATE) : null);
1113  $this->setReminderEnd($data["reminder_end"] ? new ilDate($data["reminder_end"], IL_CAL_DATE) : null);
1114  $this->setReminderFrequency($data["reminder_frequency"]);
1115  $this->setReminderTarget($data["reminder_target"]);
1116  $this->setReminderLastSent($data["reminder_last_sent"]);
1117  $this->setReminderTemplate($data["reminder_tmpl"]);
1118  $this->setTutorNotificationStatus($data["tutor_ntf_status"]);
1119  $this->setTutorNotificationRecipients(explode(";", $data["tutor_ntf_reci"]));
1120  $this->setTutorNotificationTarget($data["tutor_ntf_target"]);
1121 
1122  $this->setViewOwnResults($data["own_results_view"]);
1123  $this->setMailOwnResults($data["own_results_mail"]);
1124  $this->setMailConfirmation($data["confirmation_mail"]);
1125 
1126  $this->setAnonymousUserList($data["anon_user_list"]);
1127  }
1128 
1129  // moved activation to ilObjectActivation
1130  if($this->ref_id)
1131  {
1132  include_once "./Services/Object/classes/class.ilObjectActivation.php";
1133  $activation = ilObjectActivation::getItem($this->ref_id);
1134  switch($activation["timing_type"])
1135  {
1137  $this->setActivationLimited(true);
1138  $this->setActivationStartDate($activation["timing_start"]);
1139  $this->setActivationEndDate($activation["timing_end"]);
1140  $this->setActivationVisibility($activation["visible"]);
1141  break;
1142 
1143  default:
1144  $this->setActivationLimited(false);
1145  break;
1146  }
1147  }
1148  }
1149 
1157  {
1158  global $ilDB;
1159  $this->questions = array();
1160  $result = $ilDB->queryF("SELECT * FROM svy_svy_qst WHERE survey_fi = %s ORDER BY sequence",
1161  array('integer'),
1162  array($this->getSurveyId())
1163  );
1164  while ($data = $ilDB->fetchAssoc($result))
1165  {
1166  $this->questions[$data["sequence"]] = $data["question_fi"];
1167  }
1168  }
1169 
1174  {
1175  global $DIC;
1176 
1177  $ilDB = $DIC->database();
1178 //return;
1179  // we keep all survey question ids with their lowest sequence
1180  $result = $ilDB->queryF("SELECT * FROM svy_svy_qst WHERE survey_fi = %s ORDER BY sequence",
1181  array('integer'),
1182  array($this->getSurveyId())
1183  );
1184 
1185  // step 1: find duplicates -> $to_delete_ids
1186  $fis = array();
1187  $to_delete_ids = array();
1188  while ($data = $ilDB->fetchAssoc($result))
1189  {
1190  if (in_array($data["question_fi"], $fis)) // found a duplicate
1191  {
1192  $to_delete_ids[] = $data["survey_question_id"];
1193  }
1194  else
1195  {
1196  $fis[] = $data["question_fi"];
1197  }
1198  }
1199 
1200  // step 2: we delete the duplicates
1201  if (count($to_delete_ids) > 0)
1202  {
1203  $ilDB->manipulate($q = "DELETE FROM svy_svy_qst" .
1204  " WHERE " . $ilDB->in("survey_question_id", $to_delete_ids, false, "integer") .
1205  " AND survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer"));
1206  $this->log->debug("delete: " . $q);
1207 
1208  $ilDB->manipulate($q = "DELETE FROM svy_qblk_qst " .
1209  " WHERE " . $ilDB->in("question_fi", $fis, true, "integer") .
1210  " AND survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer"));
1211  $this->log->debug("delete: " . $q);
1212  }
1213 
1214  // step 3: we fix the sequence
1215  $set = $ilDB->query("SELECT * FROM svy_svy_qst ".
1216  " WHERE survey_fi = " . $ilDB->quote($this->getSurveyId(), "integer")." ORDER BY sequence");
1217  $seq = 0;
1218  while ($rec = $ilDB->fetchAssoc($set))
1219  {
1220  $ilDB->manipulate($q = "UPDATE svy_svy_qst SET ".
1221  " sequence = ".$ilDB->quote($seq++ , "integer").
1222  " WHERE survey_question_id = ".$ilDB->quote($rec["survey_question_id"], "integer")
1223  );
1224  $this->log->debug("update: " . $q);
1225  }
1226  }
1227 
1228 
1236  function setAuthor($author = "")
1237  {
1238  $this->author = $author;
1239  }
1240 
1250  function saveAuthorToMetadata($a_author = "")
1251  {
1252  $md = new ilMD($this->getId(), 0, $this->getType());
1253  $md_life =& $md->getLifecycle();
1254  if (!$md_life)
1255  {
1256  if (strlen($a_author) == 0)
1257  {
1258  global $ilUser;
1259  $a_author = $ilUser->getFullname();
1260  }
1261 
1262  $md_life =& $md->addLifecycle();
1263  $md_life->save();
1264  $con =& $md_life->addContribute();
1265  $con->setRole("Author");
1266  $con->save();
1267  $ent =& $con->addEntity();
1268  $ent->setEntity($a_author);
1269  $ent->save();
1270  }
1271  }
1272 
1280  function getAuthor()
1281  {
1282  $author = array();
1283  include_once "./Services/MetaData/classes/class.ilMD.php";
1284  $md = new ilMD($this->getId(), 0, $this->getType());
1285  $md_life =& $md->getLifecycle();
1286  if ($md_life)
1287  {
1288  $ids =& $md_life->getContributeIds();
1289  foreach ($ids as $id)
1290  {
1291  $md_cont =& $md_life->getContribute($id);
1292  if (strcmp($md_cont->getRole(), "Author") == 0)
1293  {
1294  $entids =& $md_cont->getEntityIds();
1295  foreach ($entids as $entid)
1296  {
1297  $md_ent =& $md_cont->getEntity($entid);
1298  array_push($author, $md_ent->getEntity());
1299  }
1300  }
1301  }
1302  }
1303  return join($author, ",");
1304  }
1305 
1312  public function getShowQuestionTitles()
1313  {
1314  return ($this->display_question_titles) ? 1 : 0;
1315  }
1316 
1323  public function setShowQuestionTitles($a_show)
1324  {
1325  $this->display_question_titles = ($a_show) ? 1 : 0;
1326  }
1327 
1335  {
1336  $this->display_question_titles = 1;
1337  }
1338 
1346  {
1347  $this->display_question_titles = 0;
1348  }
1349 
1357  function setInvitation($invitation = 0)
1358  {
1359  global $ilDB, $ilAccess;
1360 
1361  $this->invitation = $invitation;
1362  if ($invitation == self::INVITATION_OFF)
1363  {
1364  $this->disinviteAllUsers();
1365  }
1366  else if ($invitation == self::INVITATION_ON)
1367  {
1368  if ($this->getInvitationMode() == self::MODE_UNLIMITED)
1369  {
1370  $result = $ilDB->query("SELECT usr_id FROM usr_data");
1371  while ($row = $ilDB->fetchAssoc($result))
1372  {
1373  if ($ilAccess->checkAccessOfUser($row["usr_id"], "read", "", $this->getRefId(), "svy", $this->getId()))
1374  {
1375  $this->inviteUser($row['usr_id']);
1376  }
1377  }
1378  }
1379  }
1380  }
1381 
1389  function setInvitationMode($invitation_mode = 0)
1390  {
1391  $this->invitation_mode = $invitation_mode;
1392  }
1393 
1402  function setInvitationAndMode($invitation = 0, $invitation_mode = 0)
1403  {
1404  $this->invitation_mode = $invitation_mode;
1405  $this->setInvitation($invitation);
1406  }
1407 
1414  public function setIntroduction($introduction = "")
1415  {
1416  $this->introduction = $introduction;
1417  }
1418 
1425  public function setOutro($outro = "")
1426  {
1427  $this->outro = $outro;
1428  }
1429 
1437  function getInvitation()
1438  {
1439  return ($this->invitation) ? $this->invitation : self::INVITATION_OFF;
1440  }
1441 
1449  function getInvitationMode()
1450  {
1451  include_once "./Services/Administration/classes/class.ilSetting.php";
1452  $surveySetting = new ilSetting("survey");
1453  $unlimited_invitation = $surveySetting->get("unlimited_invitation");
1454  if (!$unlimited_invitation && $this->invitation_mode == self::MODE_UNLIMITED)
1455  {
1456  return self::MODE_PREDEFINED_USERS;
1457  }
1458  else
1459  {
1460  return ($this->invitation_mode) ? $this->invitation_mode : self::MODE_UNLIMITED;
1461  }
1462  }
1463 
1471  function getStatus()
1472  {
1473  return ($this->status) ? $this->status : self::STATUS_OFFLINE;
1474  }
1475 
1483  function isOnline()
1484  {
1485  return ($this->status == self::STATUS_ONLINE) ? true : false;
1486  }
1487 
1495  function isOffline()
1496  {
1497  return ($this->status == self::STATUS_OFFLINE) ? true : false;
1498  }
1499 
1508  function setStatus($status = self::STATUS_OFFLINE)
1509  {
1510  $result = "";
1511  if (($status == self::STATUS_ONLINE) && (count($this->questions) == 0))
1512  {
1513  $this->status = self::STATUS_OFFLINE;
1514  $result = $this->lng->txt("cannot_switch_to_online_no_questions");
1515  }
1516  else
1517  {
1518  $this->status = $status;
1519  }
1520  return $result;
1521  }
1522 
1530  function getStartDate()
1531  {
1532  return (strlen($this->start_date)) ? $this->start_date : NULL;
1533  }
1534 
1541  function canStartSurvey($anonymous_id = NULL, $a_no_rbac = false)
1542  {
1543  global $ilAccess;
1544 
1545  $result = TRUE;
1546  $messages = array();
1547  $edit_settings = false;
1548  // check start date
1549  if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getStartDate(), $matches))
1550  {
1551  $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
1552  $now = time();
1553  if ($now < $epoch_time)
1554  {
1555  array_push($messages,$this->lng->txt('start_date_not_reached').' ('.
1557  $result = FALSE;
1558  $edit_settings = true;
1559  }
1560  }
1561  // check end date
1562  if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndDate(), $matches))
1563  {
1564  $epoch_time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
1565  $now = time();
1566  if ($now > $epoch_time)
1567  {
1568  array_push($messages,$this->lng->txt('end_date_reached').' ('.
1570  $result = FALSE;
1571  $edit_settings = true;
1572  }
1573  }
1574 
1575  // check online status
1576  if ($this->getStatus() == self::STATUS_OFFLINE)
1577  {
1578  array_push($messages, $this->lng->txt("survey_is_offline"));
1579  $result = FALSE;
1580  $edit_settings = true;
1581  }
1582  // check rbac permissions
1583  if (!$a_no_rbac && !$ilAccess->checkAccess("read", "", $this->ref_id))
1584  {
1585  array_push($messages, $this->lng->txt("cannot_participate_survey"));
1586  $result = FALSE;
1587  }
1588  /*
1589  // 2. check previous access
1590  if (!$result["error"])
1591  {
1592  global $ilUser;
1593  $survey_started = $this->isSurveyStarted($ilUser->getId(), $anonymous_id);
1594  if ($survey_started === 1)
1595  {
1596  array_push($messages, $this->lng->txt("already_completed_survey"));
1597  $result = FALSE;
1598  }
1599  }
1600  */
1601  return array(
1602  "result" => $result,
1603  "messages" => $messages,
1604  "edit_settings" => $edit_settings
1605  );
1606  }
1607 
1615  function setStartDate($start_date = "")
1616  {
1617  $this->start_date = $start_date;
1618  }
1619 
1628  function setStartDateAndTime($start_date = "", $start_time)
1629  {
1630  $y = ''; $m = ''; $d = ''; $h = ''; $i = ''; $s = '';
1631  if (preg_match("/(\d{4})-(\d{2})-(\d{2})/", $start_date, $matches))
1632  {
1633  $y = $matches[1];
1634  $m = $matches[2];
1635  $d = $matches[3];
1636  }
1637  if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $start_time, $matches))
1638  {
1639  $h = $matches[1];
1640  $i = $matches[2];
1641  $s = $matches[3];
1642  }
1643  $this->start_date = sprintf('%04d%02d%02d%02d%02d%02d', $y, $m, $d, $h, $i, $s);
1644  }
1645 
1653  function getEndDate()
1654  {
1655  return (strlen($this->end_date)) ? $this->end_date : NULL;
1656  }
1657 
1665  function setEndDate($end_date = "")
1666  {
1667  $this->end_date = $end_date;
1668  }
1669 
1678  function setEndDateAndTime($end_date = "", $end_time)
1679  {
1680  $y = ''; $m = ''; $d = ''; $h = ''; $i = ''; $s = '';
1681  if (preg_match("/(\d{4})-(\d{2})-(\d{2})/", $end_date, $matches))
1682  {
1683  $y = $matches[1];
1684  $m = $matches[2];
1685  $d = $matches[3];
1686  }
1687  if (preg_match("/(\d{2}):(\d{2}):(\d{2})/", $end_time, $matches))
1688  {
1689  $h = $matches[1];
1690  $i = $matches[2];
1691  $s = $matches[3];
1692  }
1693  $this->end_date = sprintf('%04d%02d%02d%02d%02d%02d', $y, $m, $d, $h, $i, $s);
1694  }
1695 
1704  {
1705  return ($this->evaluation_access) ? $this->evaluation_access : self::EVALUATION_ACCESS_OFF;
1706  }
1707 
1715  function setEvaluationAccess($evaluation_access = self::EVALUATION_ACCESS_OFF)
1716  {
1717  $this->evaluation_access = ($evaluation_access) ? $evaluation_access : self::EVALUATION_ACCESS_OFF;
1718  }
1719 
1720  function setActivationVisibility($a_value)
1721  {
1722  $this->activation_visibility = (bool) $a_value;
1723  }
1724 
1726  {
1728  }
1729 
1731  {
1732  return (bool)$this->activation_limited;
1733  }
1734 
1735  function setActivationLimited($a_value)
1736  {
1737  $this->activation_limited = (bool)$a_value;
1738  }
1739 
1747  function getIntroduction()
1748  {
1749  return (strlen($this->introduction)) ? $this->introduction : NULL;
1750  }
1751 
1759  function getOutro()
1760  {
1761  return (strlen($this->outro)) ? $this->outro : NULL;
1762  }
1763 
1771  {
1772  global $ilDB;
1773  $existing_questions = array();
1774  $result = $ilDB->queryF("SELECT svy_question.original_id FROM svy_question, svy_svy_qst WHERE " .
1775  "svy_svy_qst.survey_fi = %s AND svy_svy_qst.question_fi = svy_question.question_id",
1776  array('integer'),
1777  array($this->getSurveyId())
1778  );
1779  while ($data = $ilDB->fetchAssoc($result))
1780  {
1781  if($data["original_id"])
1782  {
1783  array_push($existing_questions, $data["original_id"]);
1784  }
1785  }
1786  return $existing_questions;
1787  }
1788 
1795  function &getQuestionpoolTitles($could_be_offline = FALSE, $showPath = FALSE)
1796  {
1797  include_once "./Modules/SurveyQuestionPool/classes/class.ilObjSurveyQuestionPool.php";
1798  return ilObjSurveyQuestionPool::_getAvailableQuestionpools($use_object_id = TRUE, $could_be_offline, $showPath);
1799  }
1800 
1809  function moveQuestions($move_questions, $target_index, $insert_mode)
1810  {
1811  $array_pos = array_search($target_index, $this->questions);
1812  if ($insert_mode == 0)
1813  {
1814  $part1 = array_slice($this->questions, 0, $array_pos);
1815  $part2 = array_slice($this->questions, $array_pos);
1816  }
1817  else if ($insert_mode == 1)
1818  {
1819  $part1 = array_slice($this->questions, 0, $array_pos + 1);
1820  $part2 = array_slice($this->questions, $array_pos + 1);
1821  }
1822  foreach ($move_questions as $question_id)
1823  {
1824  if (!(array_search($question_id, $part1) === FALSE))
1825  {
1826  unset($part1[array_search($question_id, $part1)]);
1827  }
1828  if (!(array_search($question_id, $part2) === FALSE))
1829  {
1830  unset($part2[array_search($question_id, $part2)]);
1831  }
1832  }
1833  $part1 = array_values($part1);
1834  $part2 = array_values($part2);
1835  $this->questions = array_values(array_merge($part1, $move_questions, $part2));
1836  foreach ($move_questions as $question_id)
1837  {
1838  $constraints = $this->getConstraints($question_id);
1839  foreach ($constraints as $idx => $constraint)
1840  {
1841  foreach ($part2 as $next_question_id)
1842  {
1843  if ($constraint["question"] == $next_question_id)
1844  {
1845  // constraint concerning a question that follows -> delete constraint
1846  $this->deleteConstraint($constraint["id"]);
1847  }
1848  }
1849  }
1850  }
1851  $this->saveQuestionsToDb();
1852  }
1853 
1860  function removeQuestion($question_id)
1861  {
1862  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
1863  $question = self::_instanciateQuestion($question_id);
1864  #20610 if no question found, do nothing.
1865  if($question)
1866  {
1867  $question->delete($question_id);
1868  $this->removeConstraintsConcerningQuestion($question_id);
1869  }
1870  }
1871 
1879  {
1880  global $ilDB;
1881  $result = $ilDB->queryF("SELECT constraint_fi FROM svy_qst_constraint WHERE question_fi = %s AND survey_fi = %s",
1882  array('integer','integer'),
1883  array($question_id, $this->getSurveyId())
1884  );
1885  if ($result->numRows() > 0)
1886  {
1887  $remove_constraints = array();
1888  while ($row = $ilDB->fetchAssoc($result))
1889  {
1890  array_push($remove_constraints, $row["constraint_fi"]);
1891  }
1892  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_qst_constraint WHERE question_fi = %s AND survey_fi = %s",
1893  array('integer','integer'),
1894  array($question_id, $this->getSurveyId())
1895  );
1896  foreach ($remove_constraints as $key => $constraint_id)
1897  {
1898  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_constraint WHERE constraint_id = %s",
1899  array('integer'),
1900  array($constraint_id)
1901  );
1902  }
1903  }
1904  }
1905 
1913  function removeQuestions($remove_questions, $remove_questionblocks)
1914  {
1915  global $ilDB;
1916 
1917  $block_sizes = array();
1918  foreach ($this->getSurveyQuestions() as $question_id => $data)
1919  {
1920  if (in_array($question_id, $remove_questions) or in_array($data["questionblock_id"], $remove_questionblocks))
1921  {
1922  unset($this->questions[array_search($question_id, $this->questions)]);
1923  $this->removeQuestion($question_id);
1924  }
1925  else if($data["questionblock_id"])
1926  {
1927  $block_sizes[$data["questionblock_id"]]++;
1928  }
1929  }
1930 
1931  // blocks with just 1 question need to be deleted
1932  foreach($block_sizes as $block_id => $size)
1933  {
1934  if($size < 2)
1935  {
1936  $remove_questionblocks[] = $block_id;
1937  }
1938  }
1939 
1940  foreach (array_unique($remove_questionblocks) as $questionblock_id)
1941  {
1942  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_qblk WHERE questionblock_id = %s",
1943  array('integer'),
1944  array($questionblock_id)
1945  );
1946  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_qblk_qst WHERE questionblock_fi = %s AND survey_fi = %s",
1947  array('integer','integer'),
1948  array($questionblock_id, $this->getSurveyId())
1949  );
1950  }
1951 
1952  $this->questions = array_values($this->questions);
1953  $this->saveQuestionsToDb();
1954  }
1955 
1962  function unfoldQuestionblocks($questionblocks)
1963  {
1964  global $ilDB;
1965  foreach ($questionblocks as $index)
1966  {
1967  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_qblk WHERE questionblock_id = %s",
1968  array('integer'),
1969  array($index)
1970  );
1971  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_qblk_qst WHERE questionblock_fi = %s AND survey_fi = %s",
1972  array('integer','integer'),
1973  array($index, $this->getSurveyId())
1974  );
1975  }
1976  }
1977 
1978  function removeQuestionFromBlock($question_id, $questionblock_id)
1979  {
1980  global $ilDB;
1981 
1982  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_qblk_qst WHERE questionblock_fi = %s AND survey_fi = %s AND question_fi = %s",
1983  array('integer','integer','integer'),
1984  array($questionblock_id, $this->getSurveyId(), $question_id)
1985  );
1986  }
1987 
1988  function addQuestionToBlock($question_id, $questionblock_id)
1989  {
1990  global $ilDB;
1991 
1992  // see #22018
1993  if (!$this->isQuestionInAnyBlock($question_id))
1994  {
1995  $next_id = $ilDB->nextId('svy_qblk_qst');
1996  $affectedRows = $ilDB->manipulateF("INSERT INTO svy_qblk_qst (qblk_qst_id, survey_fi, questionblock_fi, " .
1997  "question_fi) VALUES (%s, %s, %s, %s)",
1998  array('integer', 'integer', 'integer', 'integer'),
1999  array($next_id, $this->getSurveyId(), $questionblock_id, $question_id)
2000  );
2001 
2002  $this->deleteConstraints($question_id); // #13713
2003  }
2004  }
2005 
2012  function isQuestionInAnyBlock($a_question_fi)
2013  {
2014  global $DIC;
2015 
2016  $ilDB = $DIC->database();
2017 
2018  $set = $ilDB->query("SELECT * FROM svy_qblk_qst ".
2019  " WHERE survey_fi = ".$ilDB->quote($this->getSurveyId(), "integer").
2020  " AND question_fi = ".$ilDB->quote($a_question_fi, "integer"));
2021  if ($rec = $ilDB->fetchAssoc($set))
2022  {
2023  return true;
2024  }
2025  return false;
2026  }
2027 
2028 
2035  function &getQuestionblockQuestions($questionblock_id)
2036  {
2037  global $ilDB;
2038  $titles = array();
2039  $result = $ilDB->queryF("SELECT svy_question.title, svy_qblk_qst.question_fi, svy_qblk_qst.survey_fi FROM ".
2040  "svy_qblk, svy_qblk_qst, svy_question WHERE svy_qblk.questionblock_id = svy_qblk_qst.questionblock_fi AND " .
2041  "svy_question.question_id = svy_qblk_qst.question_fi AND svy_qblk.questionblock_id = %s",
2042  array('integer'),
2043  array($questionblock_id)
2044  );
2045  $survey_id = "";
2046  while ($row = $ilDB->fetchAssoc($result))
2047  {
2048  $titles[$row["question_fi"]] = $row["title"];
2049  $survey_id = $row["survey_fi"];
2050  }
2051  $result = $ilDB->queryF("SELECT question_fi, sequence FROM svy_svy_qst WHERE survey_fi = %s ORDER BY sequence",
2052  array('integer'),
2053  array($survey_id)
2054  );
2055  $resultarray = array();
2056  $counter = 1;
2057  while ($row = $ilDB->fetchAssoc($result))
2058  {
2059  if (array_key_exists($row["question_fi"], $titles))
2060  {
2061  $resultarray[$counter++] = $titles[$row["question_fi"]];
2062  }
2063  }
2064  return $resultarray;
2065  }
2066 
2073  function &getQuestionblockQuestionIds($questionblock_id)
2074  {
2075  global $ilDB;
2076 
2077  // we need a correct order here, see #22011
2078  $result = $ilDB->queryF("SELECT a.question_fi FROM svy_qblk_qst a JOIN svy_svy_qst b ON (a.question_fi = b.question_fi) ".
2079  " WHERE a.questionblock_fi = %s ORDER BY b.sequence",
2080  array("integer"),
2081  array($questionblock_id)
2082  );
2083  $ids = array();
2084  if ($result->numRows())
2085  {
2086  while ($data = $ilDB->fetchAssoc($result))
2087  {
2088  if (!in_array($data['question_fi'], $ids)) // no duplicates, see #22018
2089  {
2090  array_push($ids, $data['question_fi']);
2091  }
2092  }
2093  }
2094 
2095  return $ids;
2096  }
2097 
2105  static function _getQuestionblock($questionblock_id)
2106  {
2107  global $ilDB;
2108  $result = $ilDB->queryF("SELECT * FROM svy_qblk WHERE questionblock_id = %s",
2109  array('integer'),
2110  array($questionblock_id)
2111  );
2112  $row = $ilDB->fetchAssoc($result);
2113  return $row;
2114  }
2115 
2124  static function _addQuestionblock($title = "", $owner = 0, $show_questiontext = true, $show_blocktitle = false)
2125  {
2126  global $ilDB;
2127  $next_id = $ilDB->nextId('svy_qblk');
2128  $ilDB->manipulateF("INSERT INTO svy_qblk (questionblock_id, title, show_questiontext,".
2129  " show_blocktitle, owner_fi, tstamp) " .
2130  "VALUES (%s, %s, %s, %s, %s, %s)",
2131  array('integer','text','integer','integer','integer','integer'),
2132  array($next_id, $title, $show_questiontext, $show_blocktitle, $owner, time())
2133  );
2134  return $next_id;
2135  }
2136 
2144  function createQuestionblock($title, $show_questiontext, $show_blocktitle, $questions)
2145  {
2146  global $ilDB;
2147 
2148  // if the selected questions are not in a continous selection, move all questions of the
2149  // questionblock at the position of the first selected question
2150  $this->moveQuestions($questions, $questions[0], 0);
2151 
2152  // now save the question block
2153  global $ilUser;
2154  $next_id = $ilDB->nextId('svy_qblk');
2155  $affectedRows = $ilDB->manipulateF("INSERT INTO svy_qblk (questionblock_id, title, show_questiontext,".
2156  " show_blocktitle, owner_fi, tstamp) VALUES (%s, %s, %s, %s, %s, %s)",
2157  array('integer','text','text','text','integer','integer'),
2158  array($next_id, $title, $show_questiontext, $show_blocktitle, $ilUser->getId(), time())
2159  );
2160  if ($affectedRows)
2161  {
2162  $questionblock_id = $next_id;
2163  foreach ($questions as $index)
2164  {
2165  if (!$this->isQuestionInAnyBlock($index))
2166  {
2167  $next_id = $ilDB->nextId('svy_qblk_qst'); // #22018
2168  $affectedRows = $ilDB->manipulateF("INSERT INTO svy_qblk_qst (qblk_qst_id, survey_fi, questionblock_fi, " .
2169  "question_fi) VALUES (%s, %s, %s, %s)",
2170  array('integer', 'integer', 'integer', 'integer'),
2171  array($next_id, $this->getSurveyId(), $questionblock_id, $index)
2172  );
2173  $this->deleteConstraints($index);
2174  }
2175  }
2176  }
2177  }
2178 
2186  function modifyQuestionblock($questionblock_id, $title, $show_questiontext, $show_blocktitle)
2187  {
2188  global $ilDB;
2189  $affectedRows = $ilDB->manipulateF("UPDATE svy_qblk SET title = %s, show_questiontext = %s,".
2190  " show_blocktitle = %s WHERE questionblock_id = %s",
2191  array('text','text','text','integer'),
2192  array($title, $show_questiontext, $show_blocktitle, $questionblock_id)
2193  );
2194  }
2195 
2202  function deleteConstraints($question_id)
2203  {
2204  global $ilDB;
2205  $result = $ilDB->queryF("SELECT constraint_fi FROM svy_qst_constraint WHERE question_fi = %s AND survey_fi = %s",
2206  array('integer','integer'),
2207  array($question_id, $this->getSurveyId())
2208  );
2209  $constraints = array();
2210  while ($row = $ilDB->fetchAssoc($result))
2211  {
2212  array_push($constraints, $row["constraint_fi"]);
2213  }
2214  foreach ($constraints as $constraint_id)
2215  {
2216  $this->deleteConstraint($constraint_id);
2217  }
2218  }
2219 
2227  function deleteConstraint($constraint_id)
2228  {
2229  global $ilDB;
2230  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_constraint WHERE constraint_id = %s",
2231  array('integer'),
2232  array($constraint_id)
2233  );
2234  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_qst_constraint WHERE constraint_fi = %s",
2235  array('integer'),
2236  array($constraint_id)
2237  );
2238  }
2239 
2245  public function &getSurveyQuestions($with_answers = false)
2246  {
2247  global $ilDB;
2248  // get questionblocks
2249  $all_questions = array();
2250  $result = $ilDB->queryF("SELECT svy_qtype.type_tag, svy_qtype.plugin, svy_question.question_id, ".
2251  "svy_svy_qst.heading FROM svy_qtype, svy_question, svy_svy_qst WHERE svy_svy_qst.survey_fi = %s AND " .
2252  "svy_svy_qst.question_fi = svy_question.question_id AND svy_question.questiontype_fi = svy_qtype.questiontype_id " .
2253  "ORDER BY svy_svy_qst.sequence",
2254  array('integer'),
2255  array($this->getSurveyId())
2256  );
2257  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
2258  while ($row = $ilDB->fetchAssoc($result))
2259  {
2260  $add = true;
2261  if ($row["plugin"])
2262  {
2263  if (!$this->isPluginActive($row["type_tag"]))
2264  {
2265  $add = false;
2266  }
2267  }
2268  if ($add)
2269  {
2270  $question = self::_instanciateQuestion($row["question_id"]);
2271  $questionrow = $question->getQuestionDataArray($row["question_id"]);
2272  foreach ($row as $key => $value)
2273  {
2274  $questionrow[$key] = $value;
2275  }
2276  $all_questions[$row["question_id"]] = $questionrow;
2277  $all_questions[$row["question_id"]]["usableForPrecondition"] = $question->usableForPrecondition();
2278  $all_questions[$row["question_id"]]["availableRelations"] = $question->getAvailableRelations();
2279  }
2280  }
2281  // get all questionblocks
2282  $questionblocks = array();
2283  if (count($all_questions))
2284  {
2285  $result = $ilDB->queryF("SELECT svy_qblk.*, svy_qblk_qst.question_fi FROM svy_qblk, svy_qblk_qst WHERE " .
2286  "svy_qblk.questionblock_id = svy_qblk_qst.questionblock_fi AND svy_qblk_qst.survey_fi = %s " .
2287  "AND " . $ilDB->in('svy_qblk_qst.question_fi', array_keys($all_questions), false, 'integer'),
2288  array('integer'),
2289  array($this->getSurveyId())
2290  );
2291  while ($row = $ilDB->fetchAssoc($result))
2292  {
2293  $questionblocks[$row['question_fi']] = $row;
2294  }
2295  }
2296 
2297  foreach ($all_questions as $question_id => $row)
2298  {
2299  $constraints = $this->getConstraints($question_id);
2300  if (isset($questionblocks[$question_id]))
2301  {
2302  $all_questions[$question_id]["questionblock_title"] = $questionblocks[$question_id]['title'];
2303  $all_questions[$question_id]["questionblock_id"] = $questionblocks[$question_id]['questionblock_id'];
2304  $all_questions[$question_id]["constraints"] = $constraints;
2305  }
2306  else
2307  {
2308  $all_questions[$question_id]["questionblock_title"] = "";
2309  $all_questions[$question_id]["questionblock_id"] = "";
2310  $all_questions[$question_id]["constraints"] = $constraints;
2311  }
2312  if ($with_answers)
2313  {
2314  $answers = array();
2315  $result = $ilDB->queryF("SELECT svy_variable.*, svy_category.title FROM svy_variable, svy_category " .
2316  "WHERE svy_variable.question_fi = %s AND svy_variable.category_fi = svy_category.category_id ".
2317  "ORDER BY sequence ASC",
2318  array('integer'),
2319  array($question_id)
2320  );
2321  if ($result->numRows() > 0)
2322  {
2323  while ($data = $ilDB->fetchAssoc($result))
2324  {
2325  array_push($answers, $data["title"]);
2326  }
2327  }
2328  $all_questions[$question_id]["answers"] = $answers;
2329  }
2330  }
2331  return $all_questions;
2332  }
2333 
2340  function setObligatoryStates($obligatory_questions)
2341  {
2342  global $ilDB;
2343  $result = $ilDB->queryF("SELECT * FROM svy_svy_qst WHERE survey_fi = %s",
2344  array('integer'),
2345  array($this->getSurveyId())
2346  );
2347  if ($result->numRows())
2348  {
2349  while ($row = $ilDB->fetchAssoc($result))
2350  {
2351  if (!array_key_exists($row["question_fi"], $obligatory_questions))
2352  {
2353  $obligatory_questions[$row["question_fi"]] = 0;
2354  }
2355  }
2356  }
2357 
2358  // set the obligatory states in the database
2359  foreach ($obligatory_questions as $question_fi => $obligatory)
2360  {
2361  // #12420
2362  $ilDB->manipulate("UPDATE svy_question".
2363  " SET obligatory = ".$ilDB->quote($obligatory, "integer").
2364  " WHERE question_id = ".$ilDB->quote($question_fi, "integer"));
2365  }
2366  }
2367 
2373  function &getSurveyPages()
2374  {
2375  global $ilDB;
2376  // get questionblocks
2377  $all_questions = array();
2378  $result = $ilDB->queryF("SELECT svy_question.*, svy_qtype.type_tag, svy_svy_qst.heading FROM " .
2379  "svy_question, svy_qtype, svy_svy_qst WHERE svy_svy_qst.survey_fi = %s AND " .
2380  "svy_svy_qst.question_fi = svy_question.question_id AND svy_question.questiontype_fi = svy_qtype.questiontype_id ".
2381  "ORDER BY svy_svy_qst.sequence",
2382  array('integer'),
2383  array($this->getSurveyId())
2384  );
2385  while ($row = $ilDB->fetchAssoc($result))
2386  {
2387  $all_questions[$row["question_id"]] = $row;
2388  }
2389  // get all questionblocks
2390  $questionblocks = array();
2391  if (count($all_questions))
2392  {
2393  $result = $ilDB->queryF("SELECT svy_qblk.*, svy_qblk_qst.question_fi FROM svy_qblk, svy_qblk_qst ".
2394  "WHERE svy_qblk.questionblock_id = svy_qblk_qst.questionblock_fi AND svy_qblk_qst.survey_fi = %s ".
2395  "AND " . $ilDB->in('svy_qblk_qst.question_fi', array_keys($all_questions), false, 'integer'),
2396  array('integer'),
2397  array($this->getSurveyId())
2398  );
2399  while ($row = $ilDB->fetchAssoc($result))
2400  {
2401  $questionblocks[$row['question_fi']] = $row;
2402  }
2403  }
2404 
2405  $all_pages = array();
2406  $pageindex = -1;
2407  $currentblock = "";
2408  foreach ($all_questions as $question_id => $row)
2409  {
2410  $constraints = array();
2411  if (isset($questionblocks[$question_id]))
2412  {
2413  if (!$currentblock or ($currentblock != $questionblocks[$question_id]['questionblock_id']))
2414  {
2415  $pageindex++;
2416  }
2417  $all_questions[$question_id]['page'] = $pageindex;
2418  $all_questions[$question_id]["questionblock_title"] = $questionblocks[$question_id]['title'];
2419  $all_questions[$question_id]["questionblock_id"] = $questionblocks[$question_id]['questionblock_id'];
2420  $all_questions[$question_id]["questionblock_show_questiontext"] = $questionblocks[$question_id]['show_questiontext'];
2421  $all_questions[$question_id]["questionblock_show_blocktitle"] = $questionblocks[$question_id]['show_blocktitle'];
2422  $currentblock = $questionblocks[$question_id]['questionblock_id'];
2423  $constraints = $this->getConstraints($question_id);
2424  $all_questions[$question_id]["constraints"] = $constraints;
2425  }
2426  else
2427  {
2428  $pageindex++;
2429  $all_questions[$question_id]['page'] = $pageindex;
2430  $all_questions[$question_id]["questionblock_title"] = "";
2431  $all_questions[$question_id]["questionblock_id"] = "";
2432  $all_questions[$question_id]["questionblock_show_questiontext"] = 1;
2433  $all_questions[$question_id]["questionblock_show_blocktitle"] = 1;
2434  $currentblock = "";
2435  $constraints = $this->getConstraints($question_id);
2436  $all_questions[$question_id]["constraints"] = $constraints;
2437  }
2438  if (!isset($all_pages[$pageindex]))
2439  {
2440  $all_pages[$pageindex] = array();
2441  }
2442  array_push($all_pages[$pageindex], $all_questions[$question_id]);
2443  }
2444  // calculate position percentage for every page
2445  $max = count($all_pages);
2446  $counter = 1;
2447  foreach ($all_pages as $index => $block)
2448  {
2449  foreach ($block as $blockindex => $question)
2450  {
2451  $all_pages[$index][$blockindex]["position"] = $counter / $max;
2452  }
2453  $counter++;
2454  }
2455 
2456  return $all_pages;
2457  }
2458 
2467  function getNextPage($active_page_question_id, $direction)
2468  {
2469  $foundpage = -1;
2470  $pages =& $this->getSurveyPages();
2471  if (strcmp($active_page_question_id, "") == 0)
2472  {
2473  return $pages[0];
2474  }
2475  foreach ($pages as $key => $question_array)
2476  {
2477  foreach ($question_array as $question)
2478  {
2479  if ($active_page_question_id == $question["question_id"])
2480  {
2481  $foundpage = $key;
2482  }
2483  }
2484  }
2485  if ($foundpage == -1)
2486  {
2487  // error: page not found
2488  }
2489  else
2490  {
2491  $foundpage += $direction;
2492  if ($foundpage < 0)
2493  {
2494  return 0;
2495  }
2496  if ($foundpage >= count($pages))
2497  {
2498  return 1;
2499  }
2500  return $pages[$foundpage];
2501  }
2502  }
2503 
2510  function &getAvailableQuestionpools($use_obj_id = false, $could_be_offline = false, $showPath = FALSE, $permission = "read")
2511  {
2512  include_once "./Modules/SurveyQuestionPool/classes/class.ilObjSurveyQuestionPool.php";
2513  return ilObjSurveyQuestionPool::_getAvailableQuestionpools($use_obj_id, $could_be_offline, $showPath, $permission);
2514  }
2515 
2522  {
2523  global $ilDB;
2524 
2525  $result_array = array();
2526  $result = $ilDB->queryF("SELECT svy_constraint.*, svy_relation.*, svy_qst_constraint.question_fi ref_question_fi FROM svy_qst_constraint, svy_constraint, ".
2527  "svy_relation WHERE svy_constraint.relation_fi = svy_relation.relation_id AND ".
2528  "svy_qst_constraint.constraint_fi = svy_constraint.constraint_id AND svy_constraint.constraint_id = %s",
2529  array('integer'),
2530  array($id)
2531  );
2532  $pc = array();
2533  if ($result->numRows())
2534  {
2535  $pc = $ilDB->fetchAssoc($result);
2536  }
2537  return $pc;
2538  }
2539 
2545  function getConstraints($question_id)
2546  {
2547  global $ilDB;
2548 
2549  $result_array = array();
2550  $result = $ilDB->queryF("SELECT svy_constraint.*, svy_relation.* FROM svy_qst_constraint, svy_constraint, svy_relation ".
2551  "WHERE svy_constraint.relation_fi = svy_relation.relation_id AND ".
2552  "svy_qst_constraint.constraint_fi = svy_constraint.constraint_id AND svy_qst_constraint.question_fi = %s ".
2553  "AND svy_qst_constraint.survey_fi = %s",
2554  array('integer','integer'),
2555  array($question_id, $this->getSurveyId())
2556  );
2557  while ($row = $ilDB->fetchAssoc($result))
2558  {
2559  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
2560  $question_type = SurveyQuestion::_getQuestionType($row["question_fi"]);
2561  SurveyQuestion::_includeClass($question_type);
2562  $question = new $question_type();
2563  $question->loadFromDb($row["question_fi"]);
2564  $valueoutput = $question->getPreconditionValueOutput($row["value"]);
2565  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));
2566  }
2567  return $result_array;
2568  }
2569 
2575  static function _getConstraints($survey_id)
2576  {
2577  global $ilDB;
2578  $result_array = array();
2579  $result = $ilDB->queryF("SELECT svy_qst_constraint.question_fi as for_question, svy_constraint.*, svy_relation.* ".
2580  "FROM svy_qst_constraint, svy_constraint, svy_relation WHERE svy_constraint.relation_fi = svy_relation.relation_id ".
2581  "AND svy_qst_constraint.constraint_fi = svy_constraint.constraint_id AND svy_qst_constraint.survey_fi = %s",
2582  array('integer'),
2583  array($survey_id)
2584  );
2585  while ($row = $ilDB->fetchAssoc($result))
2586  {
2587  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']));
2588  }
2589  return $result_array;
2590  }
2591 
2592 
2598  function &getVariables($question_id)
2599  {
2600  global $ilDB;
2601 
2602  $result_array = array();
2603  $result = $ilDB->queryF("SELECT svy_variable.*, svy_category.title FROM svy_variable LEFT JOIN ".
2604  "svy_category ON svy_variable.category_fi = svy_category.category_id WHERE svy_variable.question_fi = %s ".
2605  "ORDER BY svy_variable.sequence",
2606  array('integer'),
2607  array($question_id)
2608  );
2609  while ($row = $ilDB->fetchObject($result))
2610  {
2611  $result_array[$row->sequence] = $row;
2612  }
2613  return $result_array;
2614  }
2615 
2624  function addConstraint($if_question_id, $relation, $value, $conjunction)
2625  {
2626  global $ilDB;
2627 
2628  $next_id = $ilDB->nextId('svy_constraint');
2629  $affectedRows = $ilDB->manipulateF("INSERT INTO svy_constraint (constraint_id, question_fi, relation_fi, value, conjunction) VALUES ".
2630  "(%s, %s, %s, %s, %s)",
2631  array('integer','integer','integer','float', 'integer'),
2632  array($next_id, $if_question_id, $relation, $value, $conjunction)
2633  );
2634  if ($affectedRows)
2635  {
2636  return $next_id;
2637  }
2638  else
2639  {
2640  return null;
2641  }
2642  }
2643 
2644 
2651  public function addConstraintToQuestion($to_question_id, $constraint_id)
2652  {
2653  global $ilDB;
2654 
2655  $next_id = $ilDB->nextId('svy_qst_constraint');
2656  $affectedRows = $ilDB->manipulateF("INSERT INTO svy_qst_constraint (question_constraint_id, survey_fi, question_fi, ".
2657  "constraint_fi) VALUES (%s, %s, %s, %s)",
2658  array('integer','integer','integer','integer'),
2659  array($next_id, $this->getSurveyId(), $to_question_id, $constraint_id)
2660  );
2661  }
2662 
2673  function updateConstraint($precondition_id, $if_question_id, $relation, $value, $conjunction)
2674  {
2675  global $ilDB;
2676  $affectedRows = $ilDB->manipulateF("UPDATE svy_constraint SET question_fi = %s, relation_fi = %s, value = %s, conjunction = %s ".
2677  "WHERE constraint_id = %s",
2678  array('integer','integer','float','integer','integer'),
2679  array($if_question_id, $relation, $value, $conjunction, $precondition_id)
2680  );
2681  }
2682 
2683  public function updateConjunctionForQuestions($questions, $conjunction)
2684  {
2685  global $ilDB;
2686  foreach ($questions as $question_id)
2687  {
2688  $affectedRows = $ilDB->manipulateF("UPDATE svy_constraint SET conjunction = %s ".
2689  "WHERE constraint_id IN (SELECT constraint_fi FROM svy_qst_constraint WHERE svy_qst_constraint.question_fi = %s)",
2690  array('integer','integer'),
2691  array($conjunction, $question_id)
2692  );
2693  }
2694  }
2695 
2701  function getAllRelations($short_as_key = false)
2702  {
2703  global $ilDB;
2704 
2705  // #7987
2706  $custom_order = array("equal", "not_equal", "less", "less_or_equal", "more", "more_or_equal");
2707  $custom_order = array_flip($custom_order);
2708 
2709  $result_array = array();
2710  $result = $ilDB->query("SELECT * FROM svy_relation");
2711  while ($row = $ilDB->fetchAssoc($result))
2712  {
2713  if ($short_as_key)
2714  {
2715  $result_array[$row["shortname"]] = array("short" => $row["shortname"], "long" => $row["longname"], "id" => $row["relation_id"], "order" => $custom_order[$row["longname"]]);
2716  }
2717  else
2718  {
2719  $result_array[$row["relation_id"]] = array("short" => $row["shortname"], "long" => $row["longname"], "order" => $custom_order[$row["longname"]]);
2720  }
2721  }
2722 
2723  $result_array = ilUtil::sortArray($result_array, "order", "ASC", true, true);
2724  foreach($result_array as $idx => $item)
2725  {
2726  unset($result_array[$idx]["order"]);
2727  }
2728 
2729  return $result_array;
2730  }
2731 
2735  public function disinviteAllUsers()
2736  {
2737  global $ilDB;
2738  $result = $ilDB->queryF("SELECT user_fi FROM svy_inv_usr WHERE survey_fi = %s",
2739  array('integer'),
2740  array($this->getSurveyId())
2741  );
2742  while ($row = $ilDB->fetchAssoc($result))
2743  {
2744  $this->disinviteUser($row['user_fi']);
2745  }
2746  }
2747 
2753  public function disinviteUser($user_id)
2754  {
2755  global $ilDB;
2756 
2757  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_inv_usr WHERE survey_fi = %s AND user_fi = %s",
2758  array('integer','integer'),
2759  array($this->getSurveyId(), $user_id)
2760  );
2761  include_once './Services/User/classes/class.ilObjUser.php';
2762  ilObjUser::_dropDesktopItem($user_id, $this->getRefId(), "svy");
2763  }
2764 
2771  function inviteUser($user_id)
2772  {
2773  global $ilDB;
2774 
2775  $result = $ilDB->queryF("SELECT user_fi FROM svy_inv_usr WHERE user_fi = %s AND survey_fi = %s",
2776  array('integer','integer'),
2777  array($user_id, $this->getSurveyId())
2778  );
2779  if ($result->numRows() < 1)
2780  {
2781  $next_id = $ilDB->nextId('svy_inv_usr');
2782  $affectedRows = $ilDB->manipulateF("INSERT INTO svy_inv_usr (invited_user_id, survey_fi, user_fi, tstamp) " .
2783  "VALUES (%s, %s, %s, %s)",
2784  array('integer','integer','integer','integer'),
2785  array($next_id, $this->getSurveyId(), $user_id, time())
2786  );
2787  }
2788  if ($this->getInvitation() == self::INVITATION_ON)
2789  {
2790  include_once './Services/User/classes/class.ilObjUser.php';
2791  ilObjUser::_addDesktopItem($user_id, $this->getRefId(), "svy");
2792  }
2793  }
2794 
2801  function &getInvitedUsers()
2802  {
2803  global $ilDB;
2804 
2805  $result_array = array();
2806  $result = $ilDB->queryF("SELECT user_fi FROM svy_inv_usr WHERE survey_fi = %s",
2807  array('integer'),
2808  array($this->getSurveyId())
2809  );
2810  while ($row = $ilDB->fetchAssoc($result))
2811  {
2812  array_push($result_array, $row["user_fi"]);
2813  }
2814  return $result_array;
2815  }
2816 
2824  function deleteWorkingData($question_id, $active_id)
2825  {
2826  global $ilDB;
2827 
2828  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_answer WHERE question_fi = %s AND active_fi = %s",
2829  array('integer','integer'),
2830  array($question_id, $active_id)
2831  );
2832  }
2833 
2842  function loadWorkingData($question_id, $active_id)
2843  {
2844  global $ilDB;
2845  $result_array = array();
2846  $result = $ilDB->queryF("SELECT * FROM svy_answer WHERE question_fi = %s AND active_fi = %s",
2847  array('integer','integer'),
2848  array($question_id, $active_id)
2849  );
2850  if ($result->numRows() >= 1)
2851  {
2852  while ($row = $ilDB->fetchAssoc($result))
2853  {
2854  array_push($result_array, $row);
2855  }
2856  return $result_array;
2857  }
2858  else
2859  {
2860  return $result_array;
2861  }
2862  }
2863 
2870  function startSurvey($user_id, $anonymous_id, $appraisee_id)
2871  {
2872  global $ilDB;
2873 
2874  if ($this->getAnonymize() && (strlen($anonymous_id) == 0)) return;
2875 
2876  if (strcmp($user_id, "") == 0)
2877  {
2878  if ($user_id == ANONYMOUS_USER_ID)
2879  {
2880  $user_id = 0;
2881  }
2882  }
2883  $next_id = $ilDB->nextId('svy_finished');
2884  $affectedRows = $ilDB->manipulateF("INSERT INTO svy_finished (finished_id, survey_fi, user_fi, anonymous_id, state, tstamp, appr_id) ".
2885  "VALUES (%s, %s, %s, %s, %s, %s, %s)",
2886  array('integer','integer','integer','text','text','integer','integer'),
2887  array($next_id, $this->getSurveyId(), $user_id, $anonymous_id, 0, time(), $appraisee_id)
2888  );
2889  return $next_id;
2890  }
2891 
2898  function finishSurvey($finished_id)
2899  {
2900  global $ilDB;
2901 
2902  $ilDB->manipulateF("UPDATE svy_finished SET state = %s, tstamp = %s".
2903  " WHERE survey_fi = %s AND finished_id = %s",
2904  array('text','integer','integer','integer'),
2905  array(1, time(), $this->getSurveyId(), $finished_id)
2906  );
2907 
2908  $this->checkTutorNotification();
2909  }
2910 
2918  function setPage($finished_id, $page_id)
2919  {
2920  global $ilDB;
2921 
2922  $affectedRows = $ilDB->manipulateF("UPDATE svy_finished SET lastpage = %s WHERE finished_id = %s",
2923  array('integer','integer'),
2924  array(($page_id) ? $page_id : 0, $finished_id)
2925  );
2926  }
2927 
2928  function sendNotificationMail($user_id, $anonymize_id, $appr_id)
2929  {
2930  include_once "./Services/User/classes/class.ilObjUser.php";
2931  include_once "./Services/User/classes/class.ilUserUtil.php";
2932 
2933  // #12755
2934  $placeholders = array(
2935  "FIRST_NAME" => "firstname",
2936  "LAST_NAME" => "lastname",
2937  "LOGIN" => "login",
2938  // old style
2939  "firstname" => "firstname"
2940  );
2941 
2942  $recipients = preg_split('/,/', $this->mailaddresses);
2943  foreach ($recipients as $recipient)
2944  {
2945  // #11298
2946  include_once "./Services/Notification/classes/class.ilSystemNotification.php";
2947  $ntf = new ilSystemNotification();
2948  $ntf->setLangModules(array("survey"));
2949  $ntf->setRefId($this->getRefId());
2950  $ntf->setSubjectLangId('finished_mail_subject');
2951 
2952  $messagetext = $this->mailparticipantdata;
2953  if(trim($messagetext))
2954  {
2955  if (!$this->hasAnonymizedResults())
2956  {
2957  $data = ilObjUser::_getUserData(array($user_id));
2958  $data = $data[0];
2959  }
2960  foreach ($placeholders as $key => $mapping)
2961  {
2962  if ($this->hasAnonymizedResults()) // #16480
2963  {
2964  $messagetext = str_replace('[' . $key . ']', '', $messagetext);
2965  }
2966  else
2967  {
2968  $messagetext = str_replace('[' . $key . ']', trim($data[$mapping]), $messagetext);
2969  }
2970  }
2971  $ntf->setIntroductionDirect($messagetext);
2972  }
2973  else
2974  {
2975  $ntf->setIntroductionLangId('survey_notification_finished_introduction');
2976  }
2977 
2978  // 360°? add appraisee data
2979  if($appr_id)
2980  {
2981  $ntf->addAdditionalInfo('survey_360_appraisee',
2983  }
2984 
2985  $active_id = $this->getActiveID($user_id, $anonymize_id, $appr_id);
2986  $ntf->addAdditionalInfo('results',
2987  $this->getParticipantTextResults($active_id), true);
2988 
2989  $ntf->setGotoLangId('survey_notification_tutor_link');
2990  $ntf->setReasonLangId('survey_notification_finished_reason');
2991 
2992  $ntf->sendMail(array($recipient), null, null);
2993  }
2994  }
2995 
2996  protected function getParticipantTextResults($active_id)
2997  {
2998  $textresult = "";
2999  $userResults =& $this->getUserSpecificResults(array($active_id));
3000  $questions =& $this->getSurveyQuestions(true);
3001  $questioncounter = 1;
3002  foreach ($questions as $question_id => $question_data)
3003  {
3004  $textresult .= $questioncounter++ . ". " . $question_data["title"] . "\n";
3005  $found = $userResults[$question_id][$active_id];
3006  $text = "";
3007  if (is_array($found))
3008  {
3009  $text = implode("\n", $found);
3010  }
3011  else
3012  {
3013  $text = $found;
3014  }
3015  if (strlen($text) == 0) $text = self::getSurveySkippedValue();
3016  $text = str_replace("<br />", "\n", $text);
3017  $textresult .= $text . "\n\n";
3018  }
3019  return $textresult;
3020  }
3021 
3029  function isSurveyStarted($user_id, $anonymize_id, $appr_id = 0)
3030  {
3031  global $ilDB;
3032 
3033  // #15031 - should not matter if code was used by registered or anonymous (each code must be unique)
3034  if($anonymize_id)
3035  {
3036  $result = $ilDB->queryF("SELECT * FROM svy_finished".
3037  " WHERE survey_fi = %s AND anonymous_id = %s AND appr_id = %s",
3038  array('integer','text','integer'),
3039  array($this->getSurveyId(), $anonymize_id, $appr_id)
3040  );
3041  }
3042  else
3043  {
3044  $result = $ilDB->queryF("SELECT * FROM svy_finished".
3045  " WHERE survey_fi = %s AND user_fi = %s AND appr_id = %s",
3046  array('integer','integer','integer'),
3047  array($this->getSurveyId(), $user_id, $appr_id)
3048  );
3049  }
3050  if ($result->numRows() == 0)
3051  {
3052  return false;
3053  }
3054  else
3055  {
3056  $row = $ilDB->fetchAssoc($result);
3057  // yes, we are doing it this way
3058  $_SESSION["finished_id"][$this->getId()] = $row["finished_id"];
3059 
3060  return (int)$row["state"];
3061  }
3062  }
3063 
3071  function getActiveID($user_id, $anonymize_id, $appr_id)
3072  {
3073  global $ilDB;
3074 
3075  // see self::isSurveyStarted()
3076 
3077  // #15031 - should not matter if code was used by registered or anonymous (each code must be unique)
3078  if($anonymize_id)
3079  {
3080  $result = $ilDB->queryF("SELECT finished_id FROM svy_finished".
3081  " WHERE survey_fi = %s AND anonymous_id = %s AND appr_id = %s",
3082  array('integer','text','integer'),
3083  array($this->getSurveyId(), $anonymize_id, $appr_id)
3084  );
3085  }
3086  else
3087  {
3088  $result = $ilDB->queryF("SELECT finished_id FROM svy_finished".
3089  " WHERE survey_fi = %s AND user_fi = %s AND appr_id = %s",
3090  array('integer','integer','integer'),
3091  array($this->getSurveyId(), $user_id, $appr_id)
3092  );
3093  }
3094  if ($result->numRows() == 0)
3095  {
3096  return false;
3097  }
3098  else
3099  {
3100  $row = $ilDB->fetchAssoc($result);
3101  return $row["finished_id"];
3102  }
3103  }
3104 
3112  function getLastActivePage($active_id)
3113  {
3114  global $ilDB;
3115  $result = $ilDB->queryF("SELECT lastpage FROM svy_finished WHERE finished_id = %s",
3116  array('integer'),
3117  array($active_id)
3118  );
3119  if ($result->numRows() == 0)
3120  {
3121  return "";
3122  }
3123  else
3124  {
3125  $row = $ilDB->fetchAssoc($result);
3126  return ($row["lastpage"]) ? $row["lastpage"] : '';
3127  }
3128  }
3129 
3138  function checkConstraint($constraint_data, $working_data)
3139  {
3140  if (count($working_data) == 0)
3141  {
3142  return 0;
3143  }
3144 
3145  if ((count($working_data) == 1) and (strcmp($working_data[0]["value"], "") == 0))
3146  {
3147  return 0;
3148  }
3149 
3150  $found = false;
3151  foreach ($working_data as $data)
3152  {
3153  switch ($constraint_data["short"])
3154  {
3155  case "<":
3156  if ($data["value"] < $constraint_data["value"])
3157  {
3158  $found = true;
3159  }
3160  break;
3161 
3162  case "<=":
3163  if ($data["value"] <= $constraint_data["value"])
3164  {
3165  $found = true;
3166  }
3167  break;
3168 
3169  case "=":
3170  if ($data["value"] == $constraint_data["value"])
3171  {
3172  $found = true;
3173  }
3174  break;
3175 
3176  case "<>":
3177  if ($data["value"] <> $constraint_data["value"])
3178  {
3179  $found = true;
3180  }
3181  break;
3182 
3183  case ">=":
3184  if ($data["value"] >= $constraint_data["value"])
3185  {
3186  $found = true;
3187  }
3188  break;
3189 
3190  case ">":
3191  if ($data["value"] > $constraint_data["value"])
3192  {
3193  $found = true;
3194  }
3195  break;
3196  }
3197  if ($found)
3198  {
3199  break;
3200  }
3201  }
3202 
3203  return (int)$found;
3204  }
3205 
3206  static function _hasDatasets($survey_id)
3207  {
3208  global $ilDB;
3209 
3210  $result = $ilDB->queryF("SELECT finished_id FROM svy_finished WHERE survey_fi = %s",
3211  array('integer'),
3212  array($survey_id)
3213  );
3214  return ($result->numRows()) ? true : false;
3215  }
3216 
3224  {
3225  global $ilDB, $ilLog;
3226 
3227  $users = array();
3228  $result = $ilDB->queryF("SELECT * FROM svy_finished WHERE survey_fi = %s",
3229  array('integer'),
3230  array($this->getSurveyId())
3231  );
3232  if ($result->numRows())
3233  {
3234  while ($row = $ilDB->fetchAssoc($result))
3235  {
3236  array_push($users, $row["finished_id"]);
3237  }
3238  }
3239  return $users;
3240  }
3241 
3248  function getUserSpecificResults($finished_ids)
3249  {
3250  $evaluation = array();
3251 
3252  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
3253  foreach (array_keys($this->getSurveyQuestions()) as $question_id)
3254  {
3255  // get question instance
3256  $question_type = SurveyQuestion::_getQuestionType($question_id);
3257  SurveyQuestion::_includeClass($question_type);
3258  $question = new $question_type();
3259  $question->loadFromDb($question_id);
3260 
3261  $q_eval = SurveyQuestion::_instanciateQuestionEvaluation($question_id, $finished_ids);
3262  $q_res = $q_eval->getResults();
3263 
3264  $data = array();
3265  foreach($finished_ids as $user_id)
3266  {
3267  $data[$user_id] = $q_eval->parseUserSpecificResults($q_res, $user_id);
3268  }
3269 
3270  $evaluation[$question_id] = $data;
3271  }
3272 
3273  return $evaluation;
3274  }
3275 
3283  function getUserDataFromActiveId($active_id, $force_non_anonymous = false)
3284  {
3285  global $ilDB;
3286 
3287  $surveySetting = new ilSetting("survey");
3288  $use_anonymous_id = array_key_exists("use_anonymous_id", $_GET) ? $_GET["use_anonymous_id"] : $surveySetting->get("use_anonymous_id");
3289  $result = $ilDB->queryF("SELECT * FROM svy_finished WHERE finished_id = %s",
3290  array('integer'),
3291  array($active_id)
3292  );
3293  $row = array();
3294  $foundrows = $result->numRows();
3295  if ($foundrows)
3296  {
3297  $row = $ilDB->fetchAssoc($result);
3298  }
3299  $name = ($use_anonymous_id) ? $row["anonymous_id"] : $this->lng->txt("anonymous");
3300  $userdata = array(
3301  "fullname" => $name,
3302  "sortname" => $name,
3303  "firstname" => "",
3304  "lastname" => "",
3305  "login" => "",
3306  "gender" => "",
3307  "active_id" => "$active_id"
3308  );
3309  if ($foundrows)
3310  {
3311  if (($row["user_fi"] > 0) &&
3312  (($row["user_fi"] != ANONYMOUS_USER_ID &&
3313  !$this->hasAnonymizedResults() &&
3314  !$this->get360Mode()) || // 360° uses ANONYMIZE_CODE_ALL which is wrong - see ilObjSurveyGUI::afterSave()
3315  (bool)$force_non_anonymous))
3316  {
3317  include_once './Services/User/classes/class.ilObjUser.php';
3318  if (strlen(ilObjUser::_lookupLogin($row["user_fi"])) == 0)
3319  {
3320  $userdata["fullname"] = $userdata["sortname"] = $this->lng->txt("deleted_user");
3321  }
3322  else
3323  {
3324  $user = new ilObjUser($row["user_fi"]);
3325  $userdata["fullname"] = $user->getFullname();
3326  $gender = $user->getGender();
3327  if (strlen($gender) == 1) $gender = $this->lng->txt("gender_$gender");
3328  $userdata["gender"] = $gender;
3329  $userdata["firstname"] = $user->getFirstname();
3330  $userdata["lastname"] = $user->getLastname();
3331  $userdata["sortname"] = $user->getLastname() . ", " . $user->getFirstname();
3332  $userdata["login"] = $user->getLogin();
3333  }
3334  }
3335  }
3336  return $userdata;
3337  }
3338 
3348  function &getEvaluationByUser($questions, $active_id)
3349  {
3350  global $ilDB;
3351 
3352  // collect all answers
3353  $answers = array();
3354  $result = $ilDB->queryF("SELECT * FROM svy_answer WHERE active_fi = %s",
3355  array('integer'),
3356  array($active_id)
3357  );
3358  while ($row = $ilDB->fetchAssoc($result))
3359  {
3360  if (!is_array($answers[$row["question_fi"]]))
3361  {
3362  $answers[$row["question_fi"]] = array();
3363  }
3364  array_push($answers[$row["question_fi"]], $row);
3365  }
3366  $userdata = $this->getUserDataFromActiveId($active_id);
3367  $resultset = array(
3368  "name" => $userdata["fullname"],
3369  "firstname" => $userdata["firstname"],
3370  "lastname" => $userdata["lastname"],
3371  "login" => $userdata["login"],
3372  "gender" => $userdata["gender"],
3373  "answers" => array()
3374  );
3375  foreach ($questions as $key => $question)
3376  {
3377  if (array_key_exists($key, $answers))
3378  {
3379  $resultset["answers"][$key] = $answers[$key];
3380  }
3381  else
3382  {
3383  $resultset["answers"][$key] = array();
3384  }
3385  sort($resultset["answers"][$key]);
3386  }
3387  return $resultset;
3388  }
3389 
3395  function getQuestionsTable($arrFilter)
3396  {
3397  global $ilUser;
3398  global $ilDB;
3399  $where = "";
3400  if (is_array($arrFilter))
3401  {
3402  if (array_key_exists('title', $arrFilter) && strlen($arrFilter['title']))
3403  {
3404  $where .= " AND " . $ilDB->like('svy_question.title', 'text', "%%" . $arrFilter['title'] . "%%");
3405  }
3406  if (array_key_exists('description', $arrFilter) && strlen($arrFilter['description']))
3407  {
3408  $where .= " AND " . $ilDB->like('svy_question.description', 'text', "%%" . $arrFilter['description'] . "%%");
3409  }
3410  if (array_key_exists('author', $arrFilter) && strlen($arrFilter['author']))
3411  {
3412  $where .= " AND " . $ilDB->like('svy_question.author', 'text', "%%" . $arrFilter['author'] . "%%");
3413  }
3414  if (array_key_exists('type', $arrFilter) && strlen($arrFilter['type']))
3415  {
3416  $where .= " AND svy_qtype.type_tag = " . $ilDB->quote($arrFilter['type'], 'text');
3417  }
3418  if (array_key_exists('spl', $arrFilter) && strlen($arrFilter['spl']))
3419  {
3420  $where .= " AND svy_question.obj_fi = " . $ilDB->quote($arrFilter['spl'], 'integer');
3421  }
3422  }
3423 
3424  $spls =& $this->getAvailableQuestionpools($use_obj_id = TRUE, $could_be_offline = FALSE, $showPath = FALSE);
3425  $forbidden = "";
3426  $forbidden = " AND " . $ilDB->in('svy_question.obj_fi', array_keys($spls), false, 'integer');
3427  $forbidden .= " AND svy_question.complete = " . $ilDB->quote("1", 'text');
3428  $existing = "";
3429  $existing_questions =& $this->getExistingQuestions();
3430  if (count($existing_questions))
3431  {
3432  $existing = " AND " . $ilDB->in('svy_question.question_id', $existing_questions, true, 'integer');
3433  }
3434 
3435  include_once "./Modules/SurveyQuestionPool/classes/class.ilObjSurveyQuestionPool.php";
3437 
3438  $query_result = $ilDB->query("SELECT svy_question.*, svy_qtype.type_tag, svy_qtype.plugin, object_reference.ref_id".
3439  " FROM svy_question, svy_qtype, object_reference".
3440  " WHERE svy_question.original_id IS NULL".$forbidden.$existing.
3441  " AND svy_question.obj_fi = object_reference.obj_id AND svy_question.tstamp > 0".
3442  " AND svy_question.questiontype_fi = svy_qtype.questiontype_id " . $where);
3443 
3444  $rows = array();
3445  if ($query_result->numRows())
3446  {
3447  while ($row = $ilDB->fetchAssoc($query_result))
3448  {
3449  if (array_key_exists('spl_txt', $arrFilter) && strlen($arrFilter['spl_txt']))
3450  {
3451  if(!stristr($spls[$row["obj_fi"]], $arrFilter['spl_txt']))
3452  {
3453  continue;
3454  }
3455  }
3456 
3457  $row['ttype'] = $trans[$row['type_tag']];
3458  if ($row["plugin"])
3459  {
3460  if ($this->isPluginActive($row["type_tag"]))
3461  {
3462  array_push($rows, $row);
3463  }
3464  }
3465  else
3466  {
3467  array_push($rows, $row);
3468  }
3469  }
3470  }
3471  return $rows;
3472  }
3473 
3479  function getQuestionblocksTable($arrFilter)
3480  {
3481  global $ilUser, $ilDB;
3482 
3483  $where = "";
3484  if (is_array($arrFilter))
3485  {
3486  if (array_key_exists('title', $arrFilter) && strlen($arrFilter['title']))
3487  {
3488  $where .= " AND " . $ilDB->like('svy_qblk.title', 'text', "%%" . $arrFilter['title'] . "%%");
3489  }
3490  }
3491 
3492  $query_result = $ilDB->query("SELECT svy_qblk.*, svy_svy.obj_fi FROM svy_qblk , svy_qblk_qst, svy_svy WHERE ".
3493  "svy_qblk.questionblock_id = svy_qblk_qst.questionblock_fi AND svy_svy.survey_id = svy_qblk_qst.survey_fi ".
3494  "$where GROUP BY svy_qblk.questionblock_id, svy_qblk.title, svy_qblk.show_questiontext, svy_qblk.show_blocktitle, ".
3495  "svy_qblk.owner_fi, svy_qblk.tstamp, svy_svy.obj_fi");
3496  $rows = array();
3497  if ($query_result->numRows())
3498  {
3499  $survey_ref_ids = ilUtil::_getObjectsByOperations("svy", "write");
3500  $surveytitles = array();
3501  foreach ($survey_ref_ids as $survey_ref_id)
3502  {
3503  $survey_id = ilObject::_lookupObjId($survey_ref_id);
3504  $surveytitles[$survey_id] = ilObject::_lookupTitle($survey_id);
3505  }
3506  while ($row = $ilDB->fetchAssoc($query_result))
3507  {
3508  $questions_array =& $this->getQuestionblockQuestions($row["questionblock_id"]);
3509  $counter = 1;
3510  foreach ($questions_array as $key => $value)
3511  {
3512  $questions_array[$key] = "$counter. $value";
3513  $counter++;
3514  }
3515  if (strlen($surveytitles[$row["obj_fi"]])) // only questionpools which are not in trash
3516  {
3517  $rows[$row["questionblock_id"]] = array(
3518  "questionblock_id" => $row["questionblock_id"],
3519  "title" => $row["title"],
3520  "svy" => $surveytitles[$row["obj_fi"]],
3521  "contains" => join($questions_array, ", "),
3522  "owner" => $row["owner_fi"]
3523  );
3524  }
3525  }
3526  }
3527  return $rows;
3528  }
3529 
3536  function toXML()
3537  {
3538  include_once("./Services/Xml/classes/class.ilXmlWriter.php");
3539  $a_xml_writer = new ilXmlWriter;
3540  // set xml header
3541  $a_xml_writer->xmlHeader();
3542  $attrs = array(
3543  "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
3544  "xsi:noNamespaceSchemaLocation" => "http://www.ilias.de/download/xsd/ilias_survey_4_2.xsd"
3545  );
3546  $a_xml_writer->xmlStartTag("surveyobject", $attrs);
3547  $attrs = array(
3548  "id" => $this->getSurveyId(),
3549  "title" => $this->getTitle()
3550  );
3551  $a_xml_writer->xmlStartTag("survey", $attrs);
3552 
3553  $a_xml_writer->xmlElement("description", NULL, $this->getDescription());
3554  $a_xml_writer->xmlElement("author", NULL, $this->getAuthor());
3555  $a_xml_writer->xmlStartTag("objectives");
3556  $attrs = array(
3557  "label" => "introduction"
3558  );
3559  $this->addMaterialTag($a_xml_writer, $this->getIntroduction(), TRUE, TRUE, $attrs);
3560  $attrs = array(
3561  "label" => "outro"
3562  );
3563  $this->addMaterialTag($a_xml_writer, $this->getOutro(), TRUE, TRUE, $attrs);
3564  $a_xml_writer->xmlEndTag("objectives");
3565 
3566  if ($this->getAnonymize())
3567  {
3568  $attribs = array("enabled" => "1");
3569  }
3570  else
3571  {
3572  $attribs = array("enabled" => "0");
3573  }
3574  $a_xml_writer->xmlElement("anonymisation", $attribs);
3575  $a_xml_writer->xmlStartTag("restrictions");
3576  if ($this->getAnonymize() == 2)
3577  {
3578  $attribs = array("type" => "free");
3579  }
3580  else
3581  {
3582  $attribs = array("type" => "restricted");
3583  }
3584  $a_xml_writer->xmlElement("access", $attribs);
3585  if ($this->getStartDate())
3586  {
3587  $attrs = array("type" => "date");
3588  preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getStartDate(), $matches);
3589  $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]));
3590  }
3591  if ($this->getEndDate())
3592  {
3593  $attrs = array("type" => "date");
3594  preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $this->getEndDate(), $matches);
3595  $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]));
3596 
3597  }
3598  $a_xml_writer->xmlEndTag("restrictions");
3599 
3600  // constraints
3601  $pages =& $this->getSurveyPages();
3602  $hasconstraints = FALSE;
3603  foreach ($pages as $question_array)
3604  {
3605  foreach ($question_array as $question)
3606  {
3607  if (count($question["constraints"]))
3608  {
3609  $hasconstraints = TRUE;
3610  }
3611  }
3612  }
3613 
3614  if ($hasconstraints)
3615  {
3616  $a_xml_writer->xmlStartTag("constraints");
3617  foreach ($pages as $question_array)
3618  {
3619  foreach ($question_array as $question)
3620  {
3621  if (count($question["constraints"]))
3622  {
3623  // found constraints
3624  foreach ($question["constraints"] as $constraint)
3625  {
3626  $attribs = array(
3627  "sourceref" => $question["question_id"],
3628  "destref" => $constraint["question"],
3629  "relation" => $constraint["short"],
3630  "value" => $constraint["value"],
3631  "conjunction" => $constraint["conjunction"]
3632  );
3633  $a_xml_writer->xmlElement("constraint", $attribs);
3634  }
3635  }
3636  }
3637  }
3638  $a_xml_writer->xmlEndTag("constraints");
3639  }
3640 
3641  // add the rest of the preferences in qtimetadata tags, because there is no correspondent definition in QTI
3642  $a_xml_writer->xmlStartTag("metadata");
3643 
3644  $custom_properties = array();
3645  $custom_properties["evaluation_access"] = $this->getEvaluationAccess();
3646  $custom_properties["status"] = $this->getStatus();
3647  $custom_properties["display_question_titles"] = $this->getShowQuestionTitles();
3648  $custom_properties["pool_usage"] = (int)$this->getPoolUsage();
3649 
3650  $custom_properties["own_results_view"] = (int)$this->hasViewOwnResults();
3651  $custom_properties["own_results_mail"] = (int)$this->hasMailOwnResults();
3652  $custom_properties["confirmation_mail"] = (int)$this->hasMailConfirmation();
3653 
3654  $custom_properties["anon_user_list"] = (int)$this->hasAnonymousUserList();
3655 
3656  $custom_properties["mode_360"] = (int)$this->get360Mode();
3657  $custom_properties["mode_360_self_eval"] = (int)$this->get360SelfEvaluation();
3658  $custom_properties["mode_360_self_rate"] = (int)$this->get360SelfRaters();
3659  $custom_properties["mode_360_self_appr"] = (int)$this->get360SelfAppraisee();
3660  $custom_properties["mode_360_results"] = $this->get360Results();
3661  $custom_properties["mode_360_skill_service"] = (int)$this->get360SkillService();
3662 
3663 
3664  // :TODO: skills?
3665 
3666  // reminder/tutor notification are (currently?) not exportable
3667 
3668  foreach($custom_properties as $label => $value)
3669  {
3670  $a_xml_writer->xmlStartTag("metadatafield");
3671  $a_xml_writer->xmlElement("fieldlabel", NULL, $label);
3672  $a_xml_writer->xmlElement("fieldentry", NULL, $value);
3673  $a_xml_writer->xmlEndTag("metadatafield");
3674  }
3675 
3676  $a_xml_writer->xmlStartTag("metadatafield");
3677  $a_xml_writer->xmlElement("fieldlabel", NULL, "SCORM");
3678  include_once "./Services/MetaData/classes/class.ilMD.php";
3679  $md = new ilMD($this->getId(),0, $this->getType());
3680  $writer = new ilXmlWriter();
3681  $md->toXml($writer);
3682  $metadata = $writer->xmlDumpMem();
3683  $a_xml_writer->xmlElement("fieldentry", NULL, $metadata);
3684  $a_xml_writer->xmlEndTag("metadatafield");
3685 
3686  $a_xml_writer->xmlEndTag("metadata");
3687  $a_xml_writer->xmlEndTag("survey");
3688 
3689  $attribs = array("id" => $this->getId());
3690  $a_xml_writer->xmlStartTag("surveyquestions", $attribs);
3691  // add questionblock descriptions
3692  foreach ($pages as $question_array)
3693  {
3694  if (count($question_array) > 1)
3695  {
3696  $attribs = array("id" => $question_array[0]["question_id"]);
3697  $attribs = array("showQuestiontext" => $question_array[0]["questionblock_show_questiontext"],
3698  "showBlocktitle" => $question_array[0]["questionblock_show_blocktitle"]);
3699  $a_xml_writer->xmlStartTag("questionblock", $attribs);
3700  if (strlen($question_array[0]["questionblock_title"]))
3701  {
3702  $a_xml_writer->xmlElement("questionblocktitle", NULL, $question_array[0]["questionblock_title"]);
3703  }
3704  }
3705  foreach ($question_array as $question)
3706  {
3707  if (strlen($question["heading"]))
3708  {
3709  $a_xml_writer->xmlElement("textblock", NULL, $question["heading"]);
3710  }
3711  $questionObject = self::_instanciateQuestion($question["question_id"]);
3712  //questionObject contains all the fields from the database. (loadFromDb)
3713  //we don't need the value from svy_qst_oblig table, we already have the values from svy_question table.
3714  //if ($questionObject !== FALSE) $questionObject->insertXML($a_xml_writer, FALSE, $obligatory_states[$question["question_id"]]);
3715  if ($questionObject !== FALSE) $questionObject->insertXML($a_xml_writer, FALSE);
3716  }
3717  if (count($question_array) > 1)
3718  {
3719  $a_xml_writer->xmlEndTag("questionblock");
3720  }
3721  }
3722 
3723  $a_xml_writer->xmlEndTag("surveyquestions");
3724  $a_xml_writer->xmlEndTag("surveyobject");
3725  $xml = $a_xml_writer->xmlDumpMem(FALSE);
3726  return $xml;
3727  }
3728 
3736  static function _instanciateQuestion($question_id)
3737  {
3738  if ($question_id < 1) return FALSE;
3739  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
3740  $question_type = SurveyQuestion::_getQuestionType($question_id);
3741  if (strlen($question_type) == 0) return FALSE;
3742  SurveyQuestion::_includeClass($question_type);
3743  $question = new $question_type();
3744  $question->loadFromDb($question_id);
3745  return $question;
3746  }
3747 
3754  function locateImportFiles($a_dir)
3755  {
3756  if (!is_dir($a_dir) || is_int(strpos($a_dir, "..")))
3757  {
3758  return;
3759  }
3760  $importDirectory = "";
3761  $xmlFile = "";
3762 
3763  $current_dir = opendir($a_dir);
3764  $files = array();
3765  while($entryname = readdir($current_dir))
3766  {
3767  $files[] = $entryname;
3768  }
3769 
3770  foreach($files as $file)
3771  {
3772  if(is_dir($a_dir."/".$file) and ($file != "." and $file!=".."))
3773  {
3774  // found directory created by zip
3775  $importDirectory = $a_dir."/".$file;
3776  }
3777  }
3778  closedir($current_dir);
3779  if (strlen($importDirectory))
3780  {
3781  // find the xml file
3782  $current_dir = opendir($importDirectory);
3783  $files = array();
3784  while($entryname = readdir($current_dir))
3785  {
3786  $files[] = $entryname;
3787  }
3788  foreach($files as $file)
3789  {
3790  if(@is_file($importDirectory."/".$file) &&
3791  ($file != "." && $file!="..") &&
3792  (preg_match("/^[0-9]{10}__[0-9]+__(svy_)*[0-9]+\.[A-Za-z]{1,3}$/", $file) ||
3793  preg_match("/^[0-9]{10}__[0-9]+__(survey__)*[0-9]+\.[A-Za-z]{1,3}$/", $file)))
3794  {
3795  // found xml file
3796  $xmlFile = $importDirectory."/".$file;
3797  }
3798  }
3799  }
3800  return array("dir" => $importDirectory, "xml" => $xmlFile);
3801  }
3802 
3811  function importObject($file_info, $svy_qpl_id)
3812  {
3813  if ($svy_qpl_id < 1) $svy_qpl_id = -1;
3814  // check if file was uploaded
3815  $source = $file_info["tmp_name"];
3816  $error = "";
3817  if (($source == 'none') || (!$source) || $file_info["error"] > UPLOAD_ERR_OK)
3818  {
3819  $error = $this->lng->txt("import_no_file_selected");
3820  }
3821  // check correct file type
3822  $isXml = FALSE;
3823  $isZip = FALSE;
3824  if ((strcmp($file_info["type"], "text/xml") == 0) || (strcmp($file_info["type"], "application/xml") == 0))
3825  {
3826  $this->log->debug("isXML");
3827  $isXml = TRUE;
3828  }
3829  // too many different mime-types, so we use the suffix
3830  $suffix = pathinfo($file_info["name"]);
3831  if (strcmp(strtolower($suffix["extension"]), "zip") == 0)
3832  {
3833  $this->log->debug("isZip");
3834  $isZip = TRUE;
3835  }
3836  if (!$isXml && !$isZip)
3837  {
3838  $error = $this->lng->txt("import_wrong_file_type");
3839  $this->log->debug("Survey: Import error. Filetype was \"" . $file_info["type"] ."\"");
3840  }
3841  if (strlen($error) == 0)
3842  {
3843  // import file as a survey
3844  $import_dir = $this->getImportDirectory();
3845  $import_subdir = "";
3846  $importfile = "";
3847  if ($isZip)
3848  {
3849  $importfile = $import_dir."/".$file_info["name"];
3850  ilUtil::moveUploadedFile($source, $file_info["name"], $importfile);
3851  ilUtil::unzip($importfile);
3852  $found = $this->locateImportFiles($import_dir);
3853  if (!((strlen($found["dir"]) > 0) && (strlen($found["xml"]) > 0)))
3854  {
3855  $error = $this->lng->txt("wrong_import_file_structure");
3856  return $error;
3857  }
3858  $importfile = $found["xml"];
3859  $import_subdir = $found["dir"];
3860  }
3861  else
3862  {
3863  $importfile = tempnam($import_dir, "survey_import");
3864  ilUtil::moveUploadedFile($source, $file_info["name"], $importfile);
3865  }
3866 
3867  $this->log->debug("Import file = $importfile");
3868  $this->log->debug("Import subdir = $import_subdir");
3869 
3870  $fh = fopen($importfile, "r");
3871  if (!$fh)
3872  {
3873  $error = $this->lng->txt("import_error_opening_file");
3874  return $error;
3875  }
3876  $xml = fread($fh, filesize($importfile));
3877  $result = fclose($fh);
3878  if (!$result)
3879  {
3880  $error = $this->lng->txt("import_error_closing_file");
3881  return $error;
3882  }
3883 
3884  unset($_SESSION["import_mob_xhtml"]);
3885  if (strpos($xml, "questestinterop"))
3886  {
3887  include_once("./Modules/Survey/exceptions/class.ilInvalidSurveyImportFileException.php");
3888  throw new ilInvalidSurveyImportFileException("Unsupported survey version (< 3.8) found.");
3889  /*
3890  include_once "./Services/Survey/classes/class.SurveyImportParserPre38.php";
3891  $import = new SurveyImportParserPre38($svy_qpl_id, "", TRUE);
3892  $import->setSurveyObject($this);
3893  $import->setXMLContent($xml);
3894  $import->startParsing();*/
3895  }
3896  else
3897  {
3898  $this->log->debug("survey id = ".$this->getId());
3899  $this->log->debug("question pool id = ".$svy_qpl_id);
3900 
3901  include_once("./Services/Export/classes/class.ilImport.php");
3902  $imp = new ilImport();
3903  $config = $imp->getConfig("Modules/Survey");
3904  $config->setQuestionPoolID($svy_qpl_id);
3905  $imp->getMapping()->addMapping("Modules/Survey", "svy", 0, $this->getId());
3906  $imp->importFromDirectory($import_subdir, "svy", "Modules/Survey");
3907  $this->log->debug("config(Modules/survey)->getQuestionPoolId =".$config->getQuestionPoolID());
3908  return "";
3909 
3910  //old code
3911  include_once "./Services/Survey/classes/class.SurveyImportParser.php";
3912  $import = new SurveyImportParser($svy_qpl_id, "", TRUE);
3913  $import->setSurveyObject($this);
3914  $import->setXMLContent($xml);
3915  $import->startParsing();
3916  }
3917 
3918  if (is_array($_SESSION["import_mob_xhtml"]))
3919  {
3920  include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
3921  include_once "./Services/RTE/classes/class.ilRTE.php";
3922  include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
3923  foreach ($_SESSION["import_mob_xhtml"] as $mob)
3924  {
3925  $importfile = $import_subdir . "/" . $mob["uri"];
3926  if (file_exists($importfile))
3927  {
3928  if (!$mob["type"])
3929  {
3930  $mob["type"] = "svy:html";
3931  }
3932 
3933  $media_object = ilObjMediaObject::_saveTempFileAsMediaObject(basename($importfile), $importfile, FALSE);
3934 
3935  // survey mob
3936  if ($mob["type"] == "svy:html")
3937  {
3938  ilObjMediaObject::_saveUsage($media_object->getId(), "svy:html", $this->getId());
3939  $this->setIntroduction(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getIntroduction()));
3940  $this->setOutro(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $this->getOutro()));
3941  }
3942  // question mob
3943  else if($import->questions[$mob["id"]])
3944  {
3945  $new_qid = $import->questions[$mob["id"]];
3946  ilObjMediaObject::_saveUsage($media_object->getId(), $mob["type"], $new_qid);
3947  $new_question = SurveyQuestion::_instanciateQuestion($new_qid);
3948  $qtext = $new_question->getQuestiontext();
3949  $qtext = ilRTE::_replaceMediaObjectImageSrc($qtext, 0);
3950  $qtext = str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $qtext);
3951  $qtext = ilRTE::_replaceMediaObjectImageSrc($qtext, 1);
3952  $new_question->setQuestiontext($qtext);
3953  $new_question->saveToDb();
3954 
3955  // also fix existing original in pool
3956  if($new_question->getOriginalId())
3957  {
3958  $pool_question = SurveyQuestion::_instanciateQuestion($new_question->getOriginalId());
3959  $pool_question->setQuestiontext($qtext);
3960  $pool_question->saveToDb();
3961  }
3962  }
3963  }
3964  else
3965  {
3966  global $ilLog;
3967  $ilLog->write("Error: Could not open XHTML mob file for test introduction during test import. File $importfile does not exist!");
3968  }
3969  }
3972  $this->saveToDb();
3973  }
3974 
3975  // delete import directory
3977  }
3978  return $error;
3979  }
3980 
3989  public function cloneObject($a_target_id,$a_copy_id = 0, $a_omit_tree = false)
3990  {
3991  global $ilDB;
3992 
3993  $this->loadFromDb();
3994 
3995  // Copy settings
3996  $newObj = parent::cloneObject($a_target_id,$a_copy_id, $a_omit_tree);
3997  $this->cloneMetaData($newObj);
3998  $newObj->updateMetaData();
3999 
4000  $newObj->setAuthor($this->getAuthor());
4001  $newObj->setIntroduction($this->getIntroduction());
4002  $newObj->setOutro($this->getOutro());
4003  $newObj->setEvaluationAccess($this->getEvaluationAccess());
4004  $newObj->setStartDate($this->getStartDate());
4005  $newObj->setEndDate($this->getEndDate());
4006  $newObj->setInvitation($this->getInvitation());
4007  $newObj->setInvitationMode($this->getInvitationMode());
4008  $newObj->setAnonymize($this->getAnonymize());
4009  $newObj->setShowQuestionTitles($this->getShowQuestionTitles());
4010  $newObj->setTemplate($this->getTemplate());
4011  $newObj->setPoolUsage($this->getPoolUsage());
4012  $newObj->setViewOwnResults($this->hasViewOwnResults());
4013  $newObj->setMailOwnResults($this->hasMailOwnResults());
4014  $newObj->setMailConfirmation($this->hasMailConfirmation());
4015  $newObj->setAnonymousUserList($this->hasAnonymousUserList());
4016 
4017  // #12661
4018  if($this->get360Mode())
4019  {
4020  $newObj->set360Mode(true);
4021  $newObj->set360SelfEvaluation($this->get360SelfEvaluation());
4022  $newObj->set360SelfAppraisee($this->get360SelfAppraisee());
4023  $newObj->set360SelfRaters($this->get360SelfRaters());
4024  $newObj->set360Results($this->get360Results());
4025  $newObj->set360SkillService($this->get360SkillService());
4026  }
4027 
4028  // reminder/notification
4029  $newObj->setReminderStatus($this->getReminderStatus());
4030  $newObj->setReminderStart($this->getReminderStart());
4031  $newObj->setReminderEnd($this->getReminderEnd());
4032  $newObj->setReminderFrequency($this->getReminderFrequency());
4033  $newObj->setReminderTarget($this->getReminderTarget());
4034  $newObj->setReminderTemplate($this->getReminderTemplate());
4035  // reminder_last_sent must not be copied!
4036  $newObj->setTutorNotificationStatus($this->getTutorNotificationStatus());
4037  $newObj->setTutorNotificationRecipients($this->getTutorNotificationRecipients());
4038  $newObj->setTutorNotificationTarget($this->getTutorNotificationTarget());
4039 
4040  $question_pointer = array();
4041  // clone the questions
4042  $mapping = array();
4043  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
4044 
4045  foreach ($this->questions as $key => $question_id)
4046  {
4047  $question = self::_instanciateQuestion($question_id);
4048  if($question) // #10824
4049  {
4050  $question->id = -1;
4051  $original_id = SurveyQuestion::_getOriginalId($question_id, false);
4052  $question->saveToDb($original_id);
4053  $newObj->questions[$key] = $question->getId();
4054  $question_pointer[$question_id] = $question->getId();
4055  $mapping[$question_id] = $question->getId();
4056  }
4057  }
4058 
4059  //copy online status if object is not the root copy object
4060  $cp_options = ilCopyWizardOptions::_getInstance($a_copy_id);
4061 
4062  if(!$cp_options->isRootNode($this->getRefId()))
4063  {
4064  $newObj->setStatus($this->isOnline()?self::STATUS_ONLINE: self::STATUS_OFFLINE);
4065  }
4066 
4067  $newObj->saveToDb();
4068  $newObj->cloneTextblocks($mapping);
4069 
4070  // #14929
4071  if($this->get360Mode() &&
4072  $this->get360SkillService())
4073  {
4074  include_once "./Modules/Survey/classes/class.ilSurveySkill.php";
4075  $src_skills = new ilSurveySkill($this);
4076  $tgt_skills = new ilSurveySkill($newObj);
4077 
4078  foreach($mapping as $src_qst_id => $tgt_qst_id)
4079  {
4080  $qst_skill = $src_skills->getSkillForQuestion($src_qst_id);
4081  if($qst_skill)
4082  {
4083  $tgt_skills->addQuestionSkillAssignment($tgt_qst_id, $qst_skill["base_skill_id"], $qst_skill["tref_id"]);
4084  }
4085  }
4086  }
4087 
4088  // clone the questionblocks
4089  $questionblocks = array();
4090  $questionblock_questions = array();
4091  $result = $ilDB->queryF("SELECT * FROM svy_qblk_qst WHERE survey_fi = %s",
4092  array('integer'),
4093  array($this->getSurveyId())
4094  );
4095  if ($result->numRows() > 0)
4096  {
4097  while ($row = $ilDB->fetchAssoc($result))
4098  {
4099  array_push($questionblock_questions, $row);
4100  $questionblocks[$row["questionblock_fi"]] = $row["questionblock_fi"];
4101  }
4102  }
4103  // create new questionblocks
4104  foreach ($questionblocks as $key => $value)
4105  {
4106  $questionblock = self::_getQuestionblock($key);
4107  $questionblock_id = self::_addQuestionblock($questionblock["title"], $questionblock["owner_fi"], $questionblock["show_questiontext"], $questionblock["show_blocktitle"]);
4108  $questionblocks[$key] = $questionblock_id;
4109  }
4110  // create new questionblock questions
4111  foreach ($questionblock_questions as $key => $value)
4112  {
4113  if($questionblocks[$value["questionblock_fi"]] &&
4114  $question_pointer[$value["question_fi"]])
4115  {
4116  $next_id = $ilDB->nextId('svy_qblk_qst');
4117  $affectedRows = $ilDB->manipulateF("INSERT INTO svy_qblk_qst (qblk_qst_id, survey_fi, questionblock_fi, question_fi) ".
4118  "VALUES (%s, %s, %s, %s)",
4119  array('integer','integer','integer','integer'),
4120  array($next_id, $newObj->getSurveyId(), $questionblocks[$value["questionblock_fi"]], $question_pointer[$value["question_fi"]])
4121  );
4122  }
4123  }
4124 
4125  // clone the constraints
4126  $constraints = self::_getConstraints($this->getSurveyId());
4127  $newConstraints = array();
4128  foreach ($constraints as $key => $constraint)
4129  {
4130  if ($question_pointer[$constraint["for_question"]] &&
4131  $question_pointer[$constraint["question"]])
4132  {
4133  if (!array_key_exists($constraint['id'], $newConstraints))
4134  {
4135  $constraint_id = $newObj->addConstraint($question_pointer[$constraint["question"]], $constraint["relation_id"], $constraint["value"], $constraint['conjunction']);
4136  $newConstraints[$constraint['id']] = $constraint_id;
4137  }
4138  $newObj->addConstraintToQuestion($question_pointer[$constraint["for_question"]], $newConstraints[$constraint['id']]);
4139  }
4140  }
4141 
4142  // #16210 - clone LP settings
4143  include_once('./Services/Tracking/classes/class.ilLPObjSettings.php');
4144  $obj_settings = new ilLPObjSettings($this->getId());
4145  $obj_settings->cloneSettings($newObj->getId());
4146  unset($obj_settings);
4147 
4148  return $newObj;
4149  }
4150 
4151  function getTextblock($question_id)
4152  {
4153  global $ilDB;
4154  $result = $ilDB->queryF("SELECT * FROM svy_svy_qst WHERE question_fi = %s",
4155  array('integer'),
4156  array($question_id)
4157  );
4158  if ($result->numRows())
4159  {
4160  $row = $ilDB->fetchAssoc($result);
4161  return $row["heading"];
4162  }
4163  else
4164  {
4165  return "";
4166  }
4167  }
4168 
4174  function cloneTextblocks($mapping)
4175  {
4176  foreach ($mapping as $original_id => $new_id)
4177  {
4178  $textblock = $this->getTextblock($original_id);
4179  include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
4180  $this->saveHeading(ilUtil::stripSlashes($textblock, TRUE, ilObjAdvancedEditing::_getUsedHTMLTagsAsString("survey")), $new_id);
4181  }
4182  }
4183 
4192  {
4193  $svy_data_dir = ilUtil::getDataDir()."/svy_data";
4194  ilUtil::makeDir($svy_data_dir);
4195  if(!is_writable($svy_data_dir))
4196  {
4197  include_once "Modules/Survey/exceptions/class.ilSurveyException.php";
4198  throw new ilSurveyException("Survey Data Directory (".$svy_data_dir.") not writeable.");
4199  }
4200 
4201  // create learning module directory (data_dir/lm_data/lm_<id>)
4202  $svy_dir = $svy_data_dir."/svy_".$this->getId();
4203  ilUtil::makeDir($svy_dir);
4204  if(!@is_dir($svy_dir))
4205  {
4206  include_once "Modules/Survey/exceptions/class.ilSurveyException.php";
4207  throw new ilSurveyException("Creation of Survey Directory failed.");
4208  }
4209  // create Export subdirectory (data_dir/lm_data/lm_<id>/Export)
4210  $export_dir = $svy_dir."/export";
4211  ilUtil::makeDir($export_dir);
4212  if(!@is_dir($export_dir))
4213  {
4214  include_once "Modules/Survey/exceptions/class.ilSurveyException.php";
4215  throw new ilSurveyException("Creation of Export Directory failed.");
4216  }
4217  }
4218 
4223  {
4224  $export_dir = ilUtil::getDataDir()."/svy_data"."/svy_".$this->getId()."/export";
4225 
4226  return $export_dir;
4227  }
4228 
4237  {
4238  $svy_data_dir = ilUtil::getDataDir()."/svy_data";
4239  ilUtil::makeDir($svy_data_dir);
4240 
4241  if(!is_writable($svy_data_dir))
4242  {
4243  include_once "Modules/Survey/exceptions/class.ilSurveyException.php";
4244  throw new ilSurveyException("Survey Data Directory (".$svy_data_dir.") not writeable.");
4245  }
4246 
4247  // create test directory (data_dir/svy_data/svy_<id>)
4248  $svy_dir = $svy_data_dir."/svy_".$this->getId();
4249  ilUtil::makeDir($svy_dir);
4250  if(!@is_dir($svy_dir))
4251  {
4252  include_once "Modules/Survey/exceptions/class.ilSurveyException.php";
4253  throw new ilSurveyException("Creation of Survey Directory failed.");
4254  }
4255 
4256  // create import subdirectory (data_dir/svy_data/svy_<id>/import)
4257  $import_dir = $svy_dir."/import";
4258  ilUtil::makeDir($import_dir);
4259  if(!@is_dir($import_dir))
4260  {
4261  include_once "Modules/Survey/exceptions/class.ilSurveyException.php";
4262  throw new ilSurveyException("Creation of Import Directory failed.");
4263  }
4264  }
4265 
4270  {
4271  $import_dir = ilUtil::getDataDir()."/svy_data".
4272  "/svy_".$this->getId()."/import";
4273  if (!is_dir($import_dir))
4274  {
4275  ilUtil::makeDirParents($import_dir);
4276  }
4277  if(@is_dir($import_dir))
4278  {
4279  return $import_dir;
4280  }
4281  else
4282  {
4283  return false;
4284  }
4285  }
4286 
4287  function saveHeading($heading = "", $insertbefore)
4288  {
4289  global $ilDB;
4290  if ($heading)
4291  {
4292  $affectedRows = $ilDB->manipulateF("UPDATE svy_svy_qst SET heading=%s WHERE survey_fi=%s AND question_fi=%s",
4293  array('text','integer','integer'),
4294  array($heading, $this->getSurveyId(), $insertbefore)
4295  );
4296  }
4297  else
4298  {
4299  $affectedRows = $ilDB->manipulateF("UPDATE svy_svy_qst SET heading=%s WHERE survey_fi=%s AND question_fi=%s",
4300  array('text','integer','integer'),
4301  array(NULL, $this->getSurveyId(), $insertbefore)
4302  );
4303  }
4304  }
4305 
4306  function isAnonymousKey($key)
4307  {
4308  global $ilDB;
4309 
4310  $result = $ilDB->queryF("SELECT anonymous_id FROM svy_anonymous WHERE survey_key = %s AND survey_fi = %s",
4311  array('text','integer'),
4312  array($key, $this->getSurveyId())
4313  );
4314  return ($result->numRows() == 1) ? true : false;
4315  }
4316 
4317  function bindSurveyCodeToUser($user_id, $code)
4318  {
4319  global $ilDB;
4320 
4321  if($user_id == ANONYMOUS_USER_ID)
4322  {
4323  return;
4324  }
4325 
4326  if($this->checkSurveyCode($code))
4327  {
4328  $ilDB->manipulate("UPDATE svy_anonymous".
4329  " SET user_key = ".$ilDB->quote(md5($user_id), "text").
4330  " WHERE survey_key = ".$ilDB->quote($code, "text"));
4331  }
4332  }
4333 
4335  {
4336  global $ilDB;
4337 
4338  $result = $ilDB->queryF("SELECT finished_id FROM svy_finished WHERE anonymous_id = %s AND survey_fi = %s",
4339  array('text','integer'),
4340  array($key, $this->getSurveyId())
4341  );
4342  return ($result->numRows() == 1) ? true : false;
4343  }
4344 
4346  {
4347  if ($this->isAnonymousKey($code))
4348  {
4349  if ($this->isSurveyStarted("", $code) == 1)
4350  {
4351  return false;
4352  }
4353  else
4354  {
4355  return true;
4356  }
4357  }
4358  else
4359  {
4360  return false;
4361  }
4362  }
4363 
4371  function getSurveyCodesForExport(array $a_codes = null, array $a_ids = null)
4372  {
4373  global $ilDB, $ilUser, $lng;
4374 
4375  include_once "./Services/Link/classes/class.ilLink.php";
4376 
4377  $sql = "SELECT svy_anonymous.*, svy_finished.state".
4378  " FROM svy_anonymous".
4379  " LEFT JOIN svy_finished ON (svy_anonymous.survey_key = svy_finished.anonymous_id)".
4380  " WHERE svy_anonymous.survey_fi = ".$ilDB->quote($this->getSurveyId(), "integer").
4381  " AND svy_anonymous.user_key IS NULL";
4382 
4383  if($a_codes)
4384  {
4385  $sql .= " AND ".$ilDB->in("svy_anonymous.survey_key", $a_codes, "", "text");
4386  }
4387  else if($a_ids)
4388  {
4389  $sql .= " AND ".$ilDB->in("svy_anonymous.anonymous_id", $a_ids, "", "text");
4390  }
4391 
4392  $export = array();
4393 
4394  // #14905
4395  $titles = array();
4396  $titles[] = '"'.$lng->txt("survey_code").'"';
4397  $titles[] = '"'.$lng->txt("email").'"';
4398  $titles[] = '"'.$lng->txt("lastname").'"';
4399  $titles[] = '"'.$lng->txt("firstname").'"';
4400  $titles[] = '"'.$lng->txt("create_date").'"';
4401  $titles[] = '"'.$lng->txt("used").'"';
4402  $titles[] = '"'.$lng->txt("mail_sent_short").'"';
4403  $titles[] = '"'.$lng->txt("survey_code_url").'"';
4404  $export[] = implode(";", $titles);
4405 
4406  $result = $ilDB->query($sql);
4407  $default_lang = $ilUser->getPref("survey_code_language");
4408  while ($row = $ilDB->fetchAssoc($result))
4409  {
4410  $item = array();
4411  $item[] = $row["survey_key"];
4412 
4413  if($row["externaldata"])
4414  {
4415  $ext = unserialize($row["externaldata"]);
4416  $item[] = $ext["email"];
4417  $item[] = $ext["lastname"];
4418  $item[] = $ext["firstname"];
4419  }
4420  else
4421  {
4422  $item[] = "";
4423  $item[] = "";
4424  $item[] = "";
4425  }
4426 
4427  // No relative (today, tomorrow...) dates in export.
4428  $date = new ilDateTime($row['tstamp'],IL_CAL_UNIX);
4429  $item[] = $date->get(IL_CAL_DATETIME);
4430 
4431  $item[] = ($this->isSurveyCodeUsed($row["survey_key"])) ? 1 : 0;
4432  $item[] = ($row["sent"]) ? 1 : 0;
4433 
4434  $params = array("accesscode" => $row["survey_key"]);
4435  if ($default_lang)
4436  {
4437  $params["lang"] = $default_lang;
4438  }
4439  $item[] = ilLink::_getLink($this->getRefId(), "svy", $params);
4440 
4441  $export[] = '"'.implode('";"', $item).'"';
4442  }
4443  return implode("\n", $export);
4444  }
4445 
4453  public function getSurveyCodesTableData(array $ids = null, $lang = null)
4454  {
4455  global $ilDB;
4456 
4457  include_once "./Services/Link/classes/class.ilLink.php";
4458 
4459  $codes = array();
4460 
4461  $sql = "SELECT svy_anonymous.*, svy_finished.state".
4462  " FROM svy_anonymous".
4463  " LEFT JOIN svy_finished ON (svy_anonymous.survey_key = svy_finished.anonymous_id)".
4464  " WHERE svy_anonymous.survey_fi = ".$ilDB->quote($this->getSurveyId(), "integer") /*.
4465  " AND svy_anonymous.user_key IS NULL" */; // #15860
4466 
4467  if($ids)
4468  {
4469  $sql .= " AND ".$ilDB->in("svy_anonymous.anonymous_id", $ids, "", "integer");
4470  }
4471 
4472  $sql .= " ORDER BY tstamp, survey_key ASC";
4473  $result = $ilDB->query($sql);
4474  if ($result->numRows() > 0)
4475  {
4476  while ($row = $ilDB->fetchAssoc($result))
4477  {
4478  $href = "";
4479  $used = false;
4480  if ($this->isSurveyCodeUsed($row["survey_key"]))
4481  {
4482  $used = true;
4483  }
4484  else
4485  {
4486  $params = array("accesscode" => $row["survey_key"]);
4487  if ($lang)
4488  {
4489  $params["lang"] = $lang;
4490  }
4491  $href = ilLink::_getLink($this->getRefId(), "svy", $params);
4492  }
4493 
4494 
4495  $item = array(
4496  'id' => $row["anonymous_id"],
4497  'code' => $row["survey_key"],
4498  'date' => $row["tstamp"],
4499  'used' => $used,
4500  'sent' => $row['sent'],
4501  'href' => $href,
4502  'email' => '',
4503  'last_name' => '',
4504  'first_name' => ''
4505  );
4506 
4507  if($row["externaldata"])
4508  {
4509  $ext = unserialize($row["externaldata"]);
4510  $item['email'] = $ext['email'];
4511  $item['last_name'] = $ext['lastname'];
4512  $item['first_name'] = $ext['firstname'];
4513  }
4514 
4515  array_push($codes, $item);
4516  }
4517  }
4518  return $codes;
4519  }
4520 
4522  {
4523  global $ilDB;
4524  $result = $ilDB->queryF("SELECT finished_id FROM svy_finished WHERE survey_fi = %s AND anonymous_id = %s",
4525  array('integer','text'),
4526  array($this->getSurveyId(), $code)
4527  );
4528  return ($result->numRows() > 0) ? true : false;
4529  }
4530 
4532  {
4533  global $ilDB;
4534  $result = $ilDB->queryF("SELECT anonymous_id FROM svy_anonymous WHERE survey_fi = %s AND survey_key = %s",
4535  array('integer','text'),
4536  array($this->getSurveyId(), $code)
4537  );
4538  return ($result->numRows() > 0) ? false : true;
4539  }
4540 
4541  function createSurveyCodes($nrOfCodes)
4542  {
4543  global $ilDB;
4544 
4545  $res = array();
4546 
4547  for ($i = 0; $i < $nrOfCodes; $i++)
4548  {
4549  $next_id = $ilDB->nextId('svy_anonymous');
4550  $ilDB->manipulateF("INSERT INTO svy_anonymous (anonymous_id, survey_key, survey_fi, tstamp) ".
4551  "VALUES (%s, %s, %s, %s)",
4552  array('integer','text','integer','integer'),
4553  array($next_id, $this->createNewAccessCode(), $this->getSurveyId(), time())
4554  );
4555  $res[] = $next_id;
4556  }
4557 
4558  return $res;
4559  }
4560 
4561  function importSurveyCode($a_anonymize_key, $a_created, $a_data)
4562  {
4563  global $ilDB;
4564 
4565  $next_id = $ilDB->nextId('svy_anonymous');
4566  $ilDB->manipulateF("INSERT INTO svy_anonymous (anonymous_id, survey_key, survey_fi, externaldata, tstamp) ".
4567  "VALUES (%s, %s, %s, %s, %s)",
4568  array('integer','text','integer','text','integer'),
4569  array($next_id, $a_anonymize_key, $this->getSurveyId(), serialize($a_data), $a_created)
4570  );
4571  }
4572 
4574  {
4575  global $ilDB;
4576 
4577  $ids = array();
4578  foreach ($data as $dataset)
4579  {
4580  $anonymize_key = $this->createNewAccessCode();
4581  $next_id = $ilDB->nextId('svy_anonymous');
4582  $affectedRows = $ilDB->manipulateF("INSERT INTO svy_anonymous (anonymous_id, survey_key, survey_fi, externaldata, tstamp) ".
4583  "VALUES (%s, %s, %s, %s, %s)",
4584  array('integer','text','integer','text','integer'),
4585  array($next_id, $anonymize_key, $this->getSurveyId(), serialize($dataset), time())
4586  );
4587  $ids[] = $next_id;
4588  }
4589  return $ids;
4590  }
4591 
4592  function sendCodes($not_sent, $subject, $message, $lang)
4593  {
4594  global $DIC;
4595  /*
4596  * 0 = all
4597  * 1 = not sent
4598  * 2 = finished
4599  * 3 = not finished
4600  */
4601  $check_finished = ($not_sent > 1);
4602 
4603  include_once "./Services/Mail/classes/class.ilMail.php";
4604  include_once "./Services/Link/classes/class.ilLink.php";
4605 
4606  #19956
4607  $user_id = $DIC->user()->getId();
4608  $mail = new ilMail($user_id);
4609  $recipients = $this->getExternalCodeRecipients($check_finished);
4610  foreach ($recipients as $data)
4611  {
4612  if($data['email'] && $data['code'])
4613  {
4614  $do_send = false;
4615  switch ((int)$not_sent)
4616  {
4617  case 1:
4618  $do_send = !(bool)$data['sent'];
4619  break;
4620 
4621  case 2:
4622  $do_send = $data['finished'];
4623  break;
4624 
4625  case 3:
4626  $do_send = !$data['finished'];
4627  break;
4628 
4629  default:
4630  $do_send = true;
4631  break;
4632  }
4633  if ($do_send)
4634  {
4635  // build text
4636  $messagetext = $message;
4637  $url = ilLink::_getLink($this->getRefId(), "svy",
4638  array(
4639  "accesscode" => $data["code"],
4640  "lang" => $lang
4641  ));
4642  $messagetext = str_replace('[url]', $url, $messagetext);
4643  foreach ($data as $key => $value)
4644  {
4645  $messagetext = str_replace('[' . $key . ']', $value, $messagetext);
4646  }
4647 
4648  // send mail
4649  $mail->sendMail(
4650  $data['email'], // to
4651  "", // cc
4652  "", // bcc
4653  $subject, // subject
4654  $messagetext, // message
4655  array(), // attachments
4656  array('normal') // type
4657  );
4658  }
4659  }
4660  }
4661 
4662  global $ilDB;
4663  $ilDB->manipulateF("UPDATE svy_anonymous SET sent = %s WHERE survey_fi = %s AND externaldata IS NOT NULL",
4664  array('integer','integer'),
4665  array(1, $this->getSurveyId())
4666  );
4667  }
4668 
4669  function getExternalCodeRecipients($a_check_finished = false)
4670  {
4671  global $ilDB;
4672  $result = $ilDB->queryF("SELECT survey_key code, externaldata, sent FROM svy_anonymous WHERE survey_fi = %s",
4673  array('integer'),
4674  array($this->getSurveyId())
4675  );
4676  $res = array();
4677  while ($row = $ilDB->fetchAssoc($result))
4678  {
4679  if(!$row['externaldata'])
4680  {
4681  continue;
4682  }
4683 
4684  $externaldata = unserialize($row['externaldata']);
4685  if(!$externaldata['email'])
4686  {
4687  continue;
4688  }
4689 
4690  $externaldata['code'] = $row['code'];
4691  $externaldata['sent'] = $row['sent'];
4692 
4693  if($a_check_finished)
4694  {
4695  $externaldata['finished'] = $this->isSurveyCodeUsed($row['code']);
4696  }
4697 
4698  array_push($res, $externaldata);
4699  }
4700  return $res;
4701  }
4702 
4708  function deleteSurveyCode($survey_code)
4709  {
4710  global $ilDB;
4711 
4712  if (strlen($survey_code) > 0)
4713  {
4714  $affectedRows = $ilDB->manipulateF("DELETE FROM svy_anonymous WHERE survey_fi = %s AND survey_key = %s",
4715  array('integer', 'text'),
4716  array($this->getSurveyId(), $survey_code)
4717  );
4718  }
4719  }
4720 
4727  function getUserAccessCode($user_id)
4728  {
4729  global $ilDB;
4730  $access_code = "";
4731  $result = $ilDB->queryF("SELECT survey_key FROM svy_anonymous WHERE survey_fi = %s AND user_key = %s",
4732  array('integer','text'),
4733  array($this->getSurveyId(), md5($user_id))
4734  );
4735  if ($result->numRows())
4736  {
4737  $row = $ilDB->fetchAssoc($result);
4738  $access_code = $row["survey_key"];
4739  }
4740  return $access_code;
4741  }
4742 
4749  function saveUserAccessCode($user_id, $access_code)
4750  {
4751  global $ilDB;
4752 
4753  // not really sure what to do about ANONYMOUS_USER_ID
4754 
4755  $next_id = $ilDB->nextId('svy_anonymous');
4756  $affectedRows = $ilDB->manipulateF("INSERT INTO svy_anonymous (anonymous_id, survey_key, survey_fi, user_key, tstamp) ".
4757  "VALUES (%s, %s, %s, %s, %s)",
4758  array('integer','text', 'integer', 'text', 'integer'),
4759  array($next_id, $access_code, $this->getSurveyId(), md5($user_id), time())
4760  );
4761  }
4762 
4769  {
4770  // create a 5 character code
4771  $codestring = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
4772  mt_srand();
4773  $code = "";
4774  for ($i = 1; $i <=5; $i++)
4775  {
4776  $index = mt_rand(0, strlen($codestring)-1);
4777  $code .= substr($codestring, $index, 1);
4778  }
4779  // verify it against the database
4780  while (!$this->isSurveyCodeUnique($code))
4781  {
4782  $code = $this->createNewAccessCode();
4783  }
4784  return $code;
4785  }
4786 
4787  function getLastAccess($finished_id)
4788  {
4789  global $ilDB;
4790 
4791  $result = $ilDB->queryF("SELECT tstamp FROM svy_answer WHERE active_fi = %s ORDER BY tstamp DESC",
4792  array('integer'),
4793  array($finished_id)
4794  );
4795  if ($result->numRows())
4796  {
4797  $row = $ilDB->fetchAssoc($result);
4798  return $row["tstamp"];
4799  }
4800  else
4801  {
4802  $result = $ilDB->queryF("SELECT tstamp FROM svy_finished WHERE finished_id = %s",
4803  array('integer'),
4804  array($finished_id)
4805  );
4806  if ($result->numRows())
4807  {
4808  $row = $ilDB->fetchAssoc($result);
4809  return $row["tstamp"];
4810  }
4811  }
4812  return "";
4813  }
4814 
4821  function prepareTextareaOutput($txt_output)
4822  {
4823  return ilUtil::prepareTextareaOutput($txt_output, $prepare_for_latex_output);
4824  }
4825 
4833  function isHTML($a_text)
4834  {
4835  if (preg_match("/<[^>]*?>/", $a_text))
4836  {
4837  return TRUE;
4838  }
4839  else
4840  {
4841  return FALSE;
4842  }
4843  }
4844 
4853  function addMaterialTag(&$a_xml_writer, $a_material, $close_material_tag = TRUE, $add_mobs = TRUE, $attribs = NULL)
4854  {
4855  include_once "./Services/RTE/classes/class.ilRTE.php";
4856  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
4857 
4858  $a_xml_writer->xmlStartTag("material", $attribs);
4859  $attrs = array(
4860  "type" => "text/plain"
4861  );
4862  if ($this->isHTML($a_material))
4863  {
4864  $attrs["type"] = "text/xhtml";
4865  }
4866  $mattext = ilRTE::_replaceMediaObjectImageSrc($a_material, 0);
4867  $a_xml_writer->xmlElement("mattext", $attrs, $mattext);
4868 
4869  if ($add_mobs)
4870  {
4871  $mobs = ilObjMediaObject::_getMobsOfObject("svy:html", $this->getId());
4872  foreach ($mobs as $mob)
4873  {
4874  $mob_id = "il_" . IL_INST_ID . "_mob_" . $mob;
4875  if (strpos($mattext, $mob_id) !== FALSE)
4876  {
4877  $mob_obj = new ilObjMediaObject($mob);
4878  $imgattrs = array(
4879  "label" => $mob_id,
4880  "uri" => "objects/" . "il_" . IL_INST_ID . "_mob_" . $mob . "/" . $mob_obj->getTitle(),
4881  "type" => "svy:html",
4882  "id" => $this->getId()
4883  );
4884  $a_xml_writer->xmlElement("matimage", $imgattrs, NULL);
4885  }
4886  }
4887  }
4888  if ($close_material_tag) $a_xml_writer->xmlEndTag("material");
4889  }
4890 
4900  {
4901  if ($this->getAnonymize() != self::ANONYMIZE_OFF)
4902  {
4903  if ($this->surveyCodeSecurity == FALSE)
4904  {
4905  return TRUE;
4906  }
4907  }
4908  return FALSE;
4909  }
4910 
4918  function processPrintoutput2FO($print_output)
4919  {
4920  global $ilLog;
4921  if (extension_loaded("tidy"))
4922  {
4923  $config = array(
4924  "indent" => false,
4925  "output-xml" => true,
4926  "numeric-entities" => true
4927  );
4928  $tidy = new tidy();
4929  $tidy->parseString($print_output, $config, 'utf8');
4930  $tidy->cleanRepair();
4931  $print_output = tidy_get_output($tidy);
4932  $print_output = preg_replace("/^.*?(<html)/", "\\1", $print_output);
4933  }
4934  else
4935  {
4936  $print_output = str_replace("&nbsp;", "&#160;", $print_output);
4937  $print_output = str_replace("&otimes;", "X", $print_output);
4938 
4939  // #17680 - metric questions use &#160; in print view
4940  $print_output = str_replace("&gt;", "~|gt|~", $print_output); // see #21550
4941  $print_output = str_replace("&lt;", "~|lt|~", $print_output);
4942  $print_output = str_replace("&#160;", "~|nbsp|~", $print_output);
4943  $print_output = preg_replace('/&(?!amp)/', '&amp;', $print_output);
4944  $print_output = str_replace("~|nbsp|~", "&#160;", $print_output);
4945  $print_output = str_replace( "~|gt|~", "&gt;", $print_output);
4946  $print_output = str_replace( "~|lt|~", "&lt;", $print_output);
4947  }
4948  $xsl = file_get_contents("./Modules/Survey/xml/question2fo.xsl");
4949 
4950  // additional font support
4951  $xsl = str_replace(
4952  'font-family="Helvetica, unifont"',
4953  'font-family="'.$GLOBALS['ilSetting']->get('rpc_pdf_font','Helvetica, unifont').'"',
4954  $xsl
4955  );
4956  $args = array( '/_xml' => $print_output, '/_xsl' => $xsl );
4957  $xh = xslt_create();
4958  $params = array();
4959  try
4960  {
4961  $output = xslt_process($xh, "arg:/_xml", "arg:/_xsl", null, $args, $params);
4962  }
4963  catch (Exception $e)
4964  {
4965  $this->log->error("Print XSLT failed:");
4966  $this->log->error("Content: ".$print_output);
4967  $this->log->error("Xsl: ".$xsl);
4968  throw ($e);
4969  }
4970  xslt_error($xh);
4971  xslt_free($xh);
4972  $ilLog->write($output);
4973  return $output;
4974  }
4975 
4982  function deliverPDFfromFO($fo)
4983  {
4984  global $ilLog;
4985 
4986  $fo_file = ilUtil::ilTempnam() . ".fo";
4987  $fp = fopen($fo_file, "w"); fwrite($fp, $fo); fclose($fp);
4988 
4989  include_once './Services/WebServices/RPC/classes/class.ilRpcClientFactory.php';
4990  try
4991  {
4992  $pdf_base64 = ilRpcClientFactory::factory('RPCTransformationHandler')->ilFO2PDF($fo);
4993  ilUtil::deliverData($pdf_base64->scalar, ilUtil::getASCIIFilename($this->getTitle()) . ".pdf", "application/pdf");
4994  return true;
4995  }
4996  catch(Exception $e)
4997  {
4998  $ilLog->write(__METHOD__.': '.$e->getMessage());
4999  return false;
5000  }
5001  }
5002 
5009  function isPluginActive($a_pname)
5010  {
5011  global $ilPluginAdmin;
5012  if ($ilPluginAdmin->isActive(IL_COMP_MODULE, "SurveyQuestionPool", "svyq", $a_pname))
5013  {
5014  return TRUE;
5015  }
5016  else
5017  {
5018  return FALSE;
5019  }
5020  }
5021 
5027  public function setSurveyId($survey_id)
5028  {
5029  $this->survey_id = $survey_id;
5030  }
5031 
5038  public function &getUserData($ids)
5039  {
5040  global $ilDB;
5041 
5042  if (!is_array($ids) || count($ids) ==0) return array();
5043 
5044  $result = $ilDB->query("SELECT usr_id, login, lastname, firstname FROM usr_data WHERE " . $ilDB->in('usr_id', $ids, false, 'integer') . " ORDER BY login");
5045  $result_array = array();
5046  while ($row = $ilDB->fetchAssoc($result))
5047  {
5048  $result_array[$row["usr_id"]]= $row;
5049  }
5050  return $result_array;
5051  }
5052 
5054  {
5055  return $this->mailnotification;
5056  }
5057 
5058  function setMailNotification($a_notification)
5059  {
5060  $this->mailnotification = ($a_notification) ? true : false;
5061  }
5062 
5063  function getMailAddresses()
5064  {
5065  return $this->mailaddresses;
5066  }
5067 
5068  function setMailAddresses($a_addresses)
5069  {
5070  $this->mailaddresses = $a_addresses;
5071  }
5072 
5074  {
5076  }
5077 
5078  function setMailParticipantData($a_data)
5079  {
5080  $this->mailparticipantdata = $a_data;
5081  }
5082 
5083  function setStartTime($finished_id, $first_question)
5084  {
5085  global $ilDB;
5086  $time = time();
5087  //primary for table svy_times
5088  $id = $ilDB->nextId('svy_times');
5089  $_SESSION['svy_entered_page'] = $time;
5090  $affectedRows = $ilDB->manipulateF("INSERT INTO svy_times (id, finished_fi, entered_page, left_page, first_question) VALUES (%s, %s, %s, %s,%s)",
5091  array('integer','integer', 'integer', 'integer', 'integer'),
5092  array($id, $finished_id, $time, NULL, $first_question)
5093  );
5094  }
5095 
5096  function setEndTime($finished_id)
5097  {
5098  global $ilDB;
5099  $time = time();
5100  $affectedRows = $ilDB->manipulateF("UPDATE svy_times SET left_page = %s WHERE finished_fi = %s AND entered_page = %s",
5101  array('integer', 'integer', 'integer'),
5102  array($time, $finished_id, $_SESSION['svy_entered_page'])
5103  );
5104  unset($_SESSION['svy_entered_page']);
5105  }
5106 
5107  function getWorkingtimeForParticipant($finished_id)
5108  {
5109  global $ilDB;
5110 
5111  $result = $ilDB->queryF("SELECT * FROM svy_times WHERE finished_fi = %s",
5112  array('integer'),
5113  array($finished_id)
5114  );
5115  $total = 0;
5116  while ($row = $ilDB->fetchAssoc($result))
5117  {
5118  if ($row['left_page'] > 0 && $row['entered_page'] > 0)
5119  $total += $row['left_page'] - $row['entered_page'];
5120  }
5121  return $total;
5122  }
5123 
5124  function setTemplate($template_id)
5125  {
5126  $this->template_id = (int)$template_id;
5127  }
5128 
5129  function getTemplate()
5130  {
5131  return $this->template_id;
5132  }
5133 
5134  function updateOrder(array $a_order)
5135  {
5136  if(sizeof($this->questions) == sizeof($a_order))
5137  {
5138  $this->questions = array_flip($a_order);
5139  $this->saveQuestionsToDB();
5140  }
5141  }
5142 
5143  function getPoolUsage()
5144  {
5145  return $this->pool_usage;
5146  }
5147 
5148  function setPoolUsage($a_value)
5149  {
5150  $this->pool_usage = (bool)$a_value;
5151  }
5152 
5158  function isPoolActive()
5159  {
5160  $use_pool = (bool)$this->getPoolUsage();
5161  $template_settings = $this->getTemplate();
5162  if($template_settings)
5163  {
5164  include_once "Services/Administration/classes/class.ilSettingsTemplate.php";
5165  $template_settings = new ilSettingsTemplate($template_settings);
5166  $template_settings = $template_settings->getSettings();
5167  $template_settings = $template_settings["use_pool"];
5168  if($template_settings && $template_settings["hide"])
5169  {
5170  $use_pool = (bool)$template_settings["value"];
5171  }
5172  }
5173  return $use_pool;
5174  }
5175 
5181  function applySettingsTemplate($template_id)
5182  {
5183  if(!$template_id)
5184  {
5185  return;
5186  }
5187 
5188  include_once "Services/Administration/classes/class.ilSettingsTemplate.php";
5189  $template = new ilSettingsTemplate($template_id);
5190  $template_settings = $template->getSettings();
5191  if($template_settings)
5192  {
5193  if($template_settings["show_question_titles"] !== NULL)
5194  {
5195  if($template_settings["show_question_titles"]["value"])
5196  {
5197  $this->setShowQuestionTitles(true);
5198  }
5199  else
5200  {
5201  $this->setShowQuestionTitles(false);
5202  }
5203  }
5204 
5205  if($template_settings["use_pool"] !== NULL)
5206  {
5207  if($template_settings["use_pool"]["value"])
5208  {
5209  $this->setPoolUsage(true);
5210  }
5211  else
5212  {
5213  $this->setPoolUsage(false);
5214  }
5215  }
5216 
5217  if($template_settings["anonymization_options"]["value"])
5218  {
5219  $anon_map = array('personalized' => self::ANONYMIZE_OFF,
5220  'anonymize_with_code' => self::ANONYMIZE_ON,
5221  'anonymize_without_code' => self::ANONYMIZE_FREEACCESS);
5222  $this->setAnonymize($anon_map[$template_settings["anonymization_options"]["value"]]);
5223  }
5224 
5225  /* other settings: not needed here
5226  * - enabled_end_date
5227  * - enabled_start_date
5228  * - rte_switch
5229  */
5230  }
5231 
5232  $this->setTemplate($template_id);
5233  $this->saveToDb();
5234  }
5235 
5236  public function updateCode($a_id, $a_email, $a_last_name, $a_first_name, $a_sent)
5237  {
5238  global $ilDB;
5239 
5240  $a_email = trim($a_email);
5241 
5242  // :TODO:
5243  if(($a_email && !ilUtil::is_email($a_email)) || $a_email == "")
5244  {
5245  return false;
5246  }
5247 
5248  $data = array("email" => $a_email,
5249  "lastname" => trim($a_last_name),
5250  "firstname" => trim($a_first_name));
5251 
5252  $fields = array(
5253  "externaldata" => array("text", serialize($data)),
5254  "sent" => array("integer", $a_sent)
5255  );
5256 
5257  $ilDB->update("svy_anonymous", $fields,
5258  array("anonymous_id" => array("integer", $a_id)));
5259 
5260  return true;
5261  }
5262 
5263 
5264  //
5265  // 360°
5266  //
5267 
5268  public function set360Mode($a_value)
5269  {
5270  $this->mode_360 = (bool)$a_value;
5271  }
5272 
5273  public function get360Mode()
5274  {
5275  return (bool)$this->mode_360;
5276  }
5277 
5278  public function set360SelfEvaluation($a_value)
5279  {
5280  $this->mode_360_self_eval = (bool)$a_value;
5281  }
5282 
5283  public function get360SelfEvaluation()
5284  {
5285  return (bool)$this->mode_360_self_eval;
5286  }
5287 
5288  public function set360SelfAppraisee($a_value)
5289  {
5290  $this->mode_360_self_appr = (bool)$a_value;
5291  }
5292 
5293  public function get360SelfAppraisee()
5294  {
5295  return (bool)$this->mode_360_self_appr;
5296  }
5297 
5298  public function set360SelfRaters($a_value)
5299  {
5300  $this->mode_360_self_rate = (bool)$a_value;
5301  }
5302 
5303  public function get360SelfRaters()
5304  {
5305  return (bool)$this->mode_360_self_rate;
5306  }
5307 
5308  public function set360Results($a_value)
5309  {
5310  $this->mode_360_results = (int)$a_value;
5311  }
5312 
5313  public function get360Results()
5314  {
5315  return (int)$this->mode_360_results;
5316  }
5317 
5318  public function addAppraisee($a_user_id)
5319  {
5320  global $ilDB;
5321 
5322  if(!$this->isAppraisee($a_user_id) &&
5323  $a_user_id != ANONYMOUS_USER_ID)
5324  {
5325  $fields = array(
5326  "obj_id" => array("integer", $this->getSurveyId()),
5327  "user_id" => array("integer", $a_user_id)
5328  );
5329  $ilDB->insert("svy_360_appr", $fields);
5330  }
5331  }
5332 
5333  public function isAppraisee($a_user_id)
5334  {
5335  global $ilDB;
5336 
5337  $set = $ilDB->query("SELECT user_id".
5338  " FROM svy_360_appr".
5339  " WHERE obj_id = ".$ilDB->quote($this->getSurveyId(), "integer").
5340  " AND user_id = ".$ilDB->quote($a_user_id, "integer"));
5341  return (bool)$ilDB->numRows($set);
5342  }
5343 
5344  public function isAppraiseeClosed($a_user_id)
5345  {
5346  global $ilDB;
5347 
5348  $set = $ilDB->query("SELECT has_closed".
5349  " FROM svy_360_appr".
5350  " WHERE obj_id = ".$ilDB->quote($this->getSurveyId(), "integer").
5351  " AND user_id = ".$ilDB->quote($a_user_id, "integer"));
5352  $row = $ilDB->fetchAssoc($set);
5353  return $row["has_closed"];
5354  }
5355 
5356  public function deleteAppraisee($a_user_id)
5357  {
5358  global $ilDB;
5359 
5360  $ilDB->manipulate("DELETE FROM svy_360_appr".
5361  " WHERE obj_id = ".$ilDB->quote($this->getSurveyId(), "integer").
5362  " AND user_id = ".$ilDB->quote($a_user_id, "integer"));
5363 
5364  $set = $ilDB->query("SELECT user_id".
5365  " FROM svy_360_rater".
5366  " WHERE obj_id = ".$ilDB->quote($this->getSurveyId(), "integer").
5367  " AND appr_id = ".$ilDB->quote($a_user_id, "integer"));
5368  while($row = $ilDB->fetchAssoc($set))
5369  {
5370  $this->deleteRater($a_user_id, $row["user_id"]);
5371  }
5372  // appraisee will not be part of raters table
5373  if($this->get360SelfEvaluation())
5374  {
5375  $this->deleteRater($a_user_id, $a_user_id);
5376  }
5377  }
5378 
5379  public function getAppraiseesData()
5380  {
5381  global $ilDB;
5382 
5383  $res = array();
5384 
5385  $set = $ilDB->query("SELECT * FROM svy_360_appr".
5386  " WHERE obj_id = ".$ilDB->quote($this->getSurveyId(), "integer"));
5387  while($row = $ilDB->fetchAssoc($set))
5388  {
5389  $name = ilObjUser::_lookupName($row["user_id"]);
5390  $name["email"] = ilObjUser::_lookupEmail($row["user_id"]);
5391  $name["name"] = $name["lastname"].", ".$name["firstname"];
5392  $res[$row["user_id"]] = $name;
5393 
5394  $finished = 0;
5395  $raters = $this->getRatersData($row["user_id"]);
5396  foreach($raters as $rater)
5397  {
5398  if($rater["finished"])
5399  {
5400  $finished++;
5401  }
5402  }
5403  $res[$row["user_id"]]["finished"] = $finished."/".sizeof($raters);
5404  $res[$row["user_id"]]["closed"] = $row["has_closed"];
5405  }
5406 
5407  return $res;
5408  }
5409 
5410  public function addRater($a_appraisee_id, $a_user_id, $a_anonymous_id = 0)
5411  {
5412  global $ilDB;
5413 
5414  if($this->isAppraisee($a_appraisee_id) &&
5415  !$this->isRater($a_appraisee_id, $a_user_id, $a_anonymous_id))
5416  {
5417  $fields = array(
5418  "obj_id" => array("integer", $this->getSurveyId()),
5419  "appr_id" => array("integer", $a_appraisee_id),
5420  "user_id" => array("integer", $a_user_id),
5421  "anonymous_id" => array("integer", $a_anonymous_id)
5422  );
5423  $ilDB->insert("svy_360_rater", $fields);
5424  }
5425  }
5426 
5427  public function isRater($a_appraisee_id, $a_user_id, $a_anonymous_id = 0)
5428  {
5429  global $ilDB;
5430 
5431  // user is rater if already appraisee and active self-evaluation
5432  if($this->isAppraisee($a_user_id) &&
5433  $this->get360SelfEvaluation() &&
5434  (!$a_appraisee_id || $a_appraisee_id == $a_user_id))
5435  {
5436  return true;
5437  }
5438 
5439  // :TODO: should we get rid of code as well?
5440 
5441  $sql = "SELECT user_id".
5442  " FROM svy_360_rater".
5443  " WHERE obj_id = ".$ilDB->quote($this->getSurveyId(), "integer").
5444  " AND user_id = ".$ilDB->quote($a_user_id, "integer").
5445  " AND anonymous_id = ".$ilDB->quote($a_anonymous_id, "integer");
5446  if($a_appraisee_id)
5447  {
5448  $sql .= " AND appr_id = ".$ilDB->quote($a_appraisee_id, "integer");
5449  }
5450  $set = $ilDB->query($sql);
5451  return (bool)$ilDB->numRows($set);
5452  }
5453 
5454  public function deleteRater($a_appraisee_id, $a_user_id, $a_anonymous_id = 0)
5455  {
5456  global $ilDB;
5457 
5458  $finished_id = $this->getFinishedIdForAppraiseeIdAndRaterId($a_appraisee_id, $a_user_id);
5459  if($finished_id)
5460  {
5461  $this->removeSelectedSurveyResults(array($finished_id));
5462  }
5463 
5464  $ilDB->manipulate("DELETE FROM svy_360_rater".
5465  " WHERE obj_id = ".$ilDB->quote($this->getSurveyId(), "integer").
5466  " AND appr_id = ".$ilDB->quote($a_appraisee_id, "integer").
5467  " AND user_id = ".$ilDB->quote($a_user_id, "integer").
5468  " AND anonymous_id = ".$ilDB->quote($a_anonymous_id, "integer"));
5469  }
5470 
5471  public function getRatersData($a_appraisee_id)
5472  {
5473  global $ilDB;
5474 
5475  $res = $anonymous_ids = array();
5476 
5477  $set = $ilDB->query("SELECT * FROM svy_360_rater".
5478  " WHERE obj_id = ".$ilDB->quote($this->getSurveyId(), "integer").
5479  " AND appr_id = ".$ilDB->quote($a_appraisee_id, "integer"));
5480  while($row = $ilDB->fetchAssoc($set))
5481  {
5482  if($row["anonymous_id"])
5483  {
5484  $res["a".$row["anonymous_id"]] = array(
5485  "lastname" => "unknown code ".$row["anonymous_id"],
5486  "sent" => $row["mail_sent"],
5487  "finished" => null
5488  );
5489  $anonymous_ids[] = $row["anonymous_id"];
5490  }
5491  else
5492  {
5493  $name = ilObjUser::_lookupName($row["user_id"]);
5494  $name["name"] = $name["lastname"].", ".$name["firstname"];
5495  $name["user_id"] = "u".$name["user_id"];
5496  $name["email"] = ilObjUser::_lookupEmail($row["user_id"]);
5497  $name["sent"] = $row["mail_sent"];
5498  $name["finished"] = (bool)$this->is360SurveyStarted($a_appraisee_id, $row["user_id"]);
5499  $res["u".$row["user_id"]] = $name;
5500  }
5501  }
5502 
5503  if(sizeof($anonymous_ids))
5504  {
5505  $data = $this->getSurveyCodesTableData($anonymous_ids);
5506  foreach($data as $item)
5507  {
5508  if(isset($res["a".$item["id"]]))
5509  {
5510  $res["a".$item["id"]] = array(
5511  "user_id" => "a".$item["id"],
5512  "lastname" => $item["last_name"],
5513  "firstname" => $item["first_name"],
5514  "name" => $item["last_name"].", ".$item["first_name"],
5515  "login" => "",
5516  "email" => $item["email"],
5517  "code" => $item["code"],
5518  "href" => $item["href"],
5519  "sent" => $res["a".$item["id"]]["sent"],
5520  "finished" => (bool)$this->is360SurveyStarted($a_appraisee_id, null, $item["code"])
5521  );
5522  }
5523  }
5524  }
5525 
5526  return $res;
5527  }
5528 
5529  public function getAppraiseesToRate($a_user_id, $a_anonymous_id = null)
5530  {
5531  global $ilDB;
5532 
5533  $res = array();
5534 
5535  $sql = "SELECT appr_id FROM svy_360_rater".
5536  " WHERE obj_id = ".$ilDB->quote($this->getSurveyId(), "integer");
5537 
5538  if($a_user_id)
5539  {
5540  $sql .= " AND user_id = ".$ilDB->quote($a_user_id, "integer");
5541  }
5542  else
5543  {
5544  $sql .= " AND anonymous_id = ".$ilDB->quote($a_anonymous_id, "integer");
5545  }
5546 
5547  $set = $ilDB->query($sql);
5548  while($row = $ilDB->fetchAssoc($set))
5549  {
5550  $res[] = $row["appr_id"];
5551  }
5552 
5553  // user may evaluate himself if already appraisee
5554  if($this->get360SelfEvaluation() &&
5555  $this->isAppraisee($a_user_id) &&
5556  !in_array($a_user_id, $res))
5557  {
5558  $res[] = $a_user_id;
5559  }
5560 
5561  return $res;
5562  }
5563 
5564  public function getAnonymousIdByCode($a_code)
5565  {
5566  global $ilDB;
5567 
5568  $set = $ilDB->query("SELECT anonymous_id FROM svy_anonymous".
5569  " WHERE survey_fi = ".$ilDB->quote($this->getSurveyId(), "integer").
5570  " AND survey_key = ".$ilDB->quote($a_code, "text"));
5571  $res = $ilDB->fetchAssoc($set);
5572  return $res["anonymous_id"];
5573  }
5574 
5575  function is360SurveyStarted($appr_id, $user_id, $anonymous_code = null)
5576  {
5577  global $ilDB;
5578 
5579  $sql = "SELECT * FROM svy_finished".
5580  " WHERE survey_fi =".$ilDB->quote($this->getSurveyId(), "integer").
5581  " AND appr_id = ".$ilDB->quote($appr_id, "integer");
5582  if ($user_id)
5583  {
5584  $sql .= " AND user_fi = ".$ilDB->quote($user_id, "integer");
5585  }
5586  else
5587  {
5588  $sql .= " AND anonymous_id = ".$ilDB->quote($anonymous_code, "text");
5589  }
5590  $result = $ilDB->query($sql);
5591  if ($result->numRows() == 0)
5592  {
5593  return false;
5594  }
5595  else
5596  {
5597  $row = $ilDB->fetchAssoc($result);
5598  return (int)$row["state"];
5599  }
5600  }
5601 
5602  function getUserSurveyExecutionStatus($a_code = null)
5603  {
5604  global $ilUser, $ilDB;
5605 
5606  $user_id = $ilUser->getId();
5607 
5608  // code is obligatory?
5609  if(!$this->isAccessibleWithoutCode())
5610  {
5611  if(!$a_code)
5612  {
5613  // registered raters do not need code
5614  if($this->get360Mode() &&
5615  $user_id != ANONYMOUS_USER_ID &&
5616  $this->isRater(0, $user_id))
5617  {
5618  // auto-generate code
5619  $a_code = $this->createNewAccessCode();
5620  $this->saveUserAccessCode($user_id, $a_code);
5621  }
5622  else
5623  {
5624  return null;
5625  }
5626  }
5627  }
5628  else if($user_id == ANONYMOUS_USER_ID ||
5629  $this->getAnonymize() == self::ANONYMIZE_FREEACCESS)
5630  {
5631  if(!$a_code)
5632  {
5633  // auto-generate code
5634  $a_code = $this->createNewAccessCode();
5635  $this->saveUserAccessCode($user_id, $a_code);
5636  }
5637  }
5638  else
5639  {
5640  $a_code = null;
5641  }
5642 
5643  $res = array();
5644 
5645  $sql = "SELECT * FROM svy_finished".
5646  " WHERE survey_fi = ".$ilDB->quote($this->getSurveyId(), "integer");
5647  // if proper user id is given, use it or current code
5648  if($user_id != ANONYMOUS_USER_ID)
5649  {
5650  $sql .= " AND (user_fi = ".$ilDB->quote($user_id, "integer").
5651  " OR anonymous_id = ".$ilDB->quote($a_code, "text").")";
5652  }
5653  // use anonymous code to find finished id(s)
5654  else
5655  {
5656  $sql .= " AND anonymous_id = ".$ilDB->quote($a_code, "text");
5657  }
5658  $set = $ilDB->query($sql);
5659  while($row = $ilDB->fetchAssoc($set))
5660  {
5661  $res[$row["finished_id"]] = array("appr_id" => $row["appr_id"],
5662  "user_id" => $row["user_fi"],
5663  "code" => $row["anonymous_id"],
5664  "finished" => (bool)$row["state"]);
5665  }
5666 
5667  return array("code"=>$a_code, "runs"=>$res);
5668  }
5669 
5670  function findCodeForUser($a_user_id)
5671  {
5672  global $ilDB;
5673 
5674  if($a_user_id != ANONYMOUS_USER_ID)
5675  {
5676  $set = $ilDB->query("SELECT sf.anonymous_id FROM svy_finished sf".
5677  " WHERE sf.survey_fi = ".$ilDB->quote($this->getSurveyId(), "integer").
5678  " AND sf.user_fi = ".$ilDB->quote($a_user_id, "integer"));
5679  $a_code = $ilDB->fetchAssoc($set);
5680  return $a_code["anonymous_id"];
5681  }
5682  }
5683 
5684  function isUnusedCode($a_code, $a_user_id)
5685  {
5686  global $ilDB;
5687 
5688  $set = $ilDB->query("SELECT user_fi FROM svy_finished".
5689  " WHERE survey_fi = ".$ilDB->quote($this->getSurveyId(), "integer").
5690  " AND anonymous_id = ".$ilDB->quote($a_code, "text"));
5691  $user_id = $ilDB->fetchAssoc($set);
5692  $user_id = $user_id["user_fi"];
5693 
5694  if($user_id && ($user_id != $a_user_id || $user_id == ANONYMOUS_USER_ID))
5695  {
5696  return false;
5697  }
5698  return true;
5699  }
5700 
5701  function getFinishedIdsForAppraiseeId($a_appr_id, $a_exclude_appraisee = false)
5702  {
5703  global $ilDB;
5704 
5705  $res = array();
5706 
5707  $set = $ilDB->query("SELECT finished_id, user_fi FROM svy_finished".
5708  " WHERE survey_fi = ".$ilDB->quote($this->getSurveyId(), "integer").
5709  " AND appr_id = ".$ilDB->quote($a_appr_id, "integer"));
5710  while($row = $ilDB->fetchAssoc($set))
5711  {
5712  if ($a_exclude_appraisee && $row["user_fi"] == $a_appr_id)
5713  {
5714  continue;
5715  }
5716  $res[] = $row["finished_id"];
5717  }
5718 
5719  return $res;
5720  }
5721 
5729  function getFinishedIdForAppraiseeIdAndRaterId($a_appr_id, $a_rat_id)
5730  {
5731  global $ilDB;
5732 
5733  $set = $ilDB->query("SELECT finished_id, user_fi FROM svy_finished".
5734  " WHERE survey_fi = ".$ilDB->quote($this->getSurveyId(), "integer").
5735  " AND appr_id = ".$ilDB->quote($a_appr_id, "integer").
5736  " AND user_fi = ".$ilDB->quote($a_rat_id, "integer"));
5737  $row = $ilDB->fetchAssoc($set);
5738  return $row["finished_id"];
5739  }
5740 
5741 
5742  // 360° using competence/skill service
5743 
5749  function set360SkillService($a_val)
5750  {
5751  $this->mode_360_skill_service = $a_val;
5752  }
5753 
5760  {
5762  }
5763 
5764  function set360RaterSent($a_appraisee_id, $a_user_id, $a_anonymous_id, $a_tstamp = null)
5765  {
5766  global $ilDB;
5767 
5768  if(!$a_tstamp)
5769  {
5770  $a_tstamp = time();
5771  }
5772 
5773  $ilDB->manipulate("UPDATE svy_360_rater".
5774  " SET mail_sent = ".$ilDB->quote($a_tstamp, "integer").
5775  " WHERE obj_id = ".$ilDB->quote($this->getSurveyId(), "integer").
5776  " AND appr_id = ".$ilDB->quote($a_appraisee_id, "integer").
5777  " AND user_id = ".$ilDB->quote($a_user_id, "integer").
5778  " AND anonymous_id = ".$ilDB->quote($a_anonymous_id, "integer"));
5779  }
5780 
5781  function closeAppraisee($a_user_id)
5782  {
5783  global $ilDB;
5784 
5785  // close the appraisee
5786  $ilDB->manipulate("UPDATE svy_360_appr".
5787  " SET has_closed = ".$ilDB->quote(time(), "integer").
5788  " WHERE obj_id = ".$ilDB->quote($this->getSurveyId(), "integer").
5789  " AND user_id = ".$ilDB->quote($a_user_id, "integer"));
5790 
5791  // write competences
5792  include_once("./Services/Skill/classes/class.ilSkillManagementSettings.php");
5793  $skmg_set = new ilSkillManagementSettings();
5794  if ($this->get360SkillService() && $skmg_set->isActivated())
5795  {
5796  include_once("./Modules/Survey/classes/class.ilSurveySkill.php");
5797  $sskill = new ilSurveySkill($this);
5798  $sskill->writeAppraiseeSkills($a_user_id);
5799  }
5800  }
5801 
5803  {
5804  global $ilDB;
5805 
5806  $ilDB->manipulate("UPDATE svy_360_appr".
5807  " SET has_closed = ".$ilDB->quote(null, "integer").
5808  " WHERE obj_id = ".$ilDB->quote($this->getSurveyId(), "integer"));
5809  }
5810 
5811  public static function validateExternalRaterCode($a_ref_id, $a_code)
5812  {
5813  if(!isset($_SESSION["360_extrtr"][$a_ref_id]))
5814  {
5815  $svy = new self($a_ref_id);
5816  $svy->loadFromDB();
5817 
5818  if($svy->canStartSurvey(null, true) &&
5819  $svy->get360Mode() &&
5820  $svy->isAnonymousKey($a_code))
5821  {
5822  $anonymous_id = $svy->getAnonymousIdByCode($a_code);
5823  if($anonymous_id)
5824  {
5825  if(sizeof($svy->getAppraiseesToRate(null, $anonymous_id)))
5826  {
5827  $_SESSION["360_extrtr"][$a_ref_id] = true;
5828  return true;
5829  }
5830  }
5831  }
5832 
5833  $_SESSION["360_extrtr"][$a_ref_id] = false;
5834  return false;
5835  }
5836 
5837  return $_SESSION["360_extrtr"][$a_ref_id];
5838  }
5839 
5840 
5841  //
5842  // reminder/notification
5843  //
5844 
5845  public function getReminderStatus()
5846  {
5847  return (bool)$this->reminder_status;
5848  }
5849 
5850  public function setReminderStatus($a_value)
5851  {
5852  $this->reminder_status = (bool)$a_value;
5853  }
5854 
5855  public function getReminderStart()
5856  {
5857  return $this->reminder_start;
5858  }
5859 
5860  public function setReminderStart(ilDate $a_value = null)
5861  {
5862  $this->reminder_start = $a_value;
5863  }
5864 
5865  public function getReminderEnd()
5866  {
5867  return $this->reminder_end;
5868  }
5869 
5870  public function setReminderEnd(ilDate $a_value = null)
5871  {
5872  $this->reminder_end = $a_value;
5873  }
5874 
5875  public function getReminderFrequency()
5876  {
5878  }
5879 
5880  public function setReminderFrequency($a_value)
5881  {
5882  $this->reminder_frequency = (int)$a_value;
5883  }
5884 
5885  public function getReminderTarget()
5886  {
5887  return $this->reminder_target;
5888  }
5889 
5890  public function setReminderTarget($a_value)
5891  {
5892  $this->reminder_target = (int)$a_value;
5893  }
5894 
5895  public function getReminderLastSent()
5896  {
5898  }
5899 
5900  public function setReminderLastSent($a_value)
5901  {
5902  $this->reminder_last_sent = $a_value;
5903  }
5904 
5905  public function getReminderTemplate()
5906  {
5907  return $this->reminder_tmpl;
5908  }
5909 
5910  public function setReminderTemplate($a_value)
5911  {
5912  $this->reminder_tmpl = $a_value;
5913  }
5914 
5915  public function getTutorNotificationStatus()
5916  {
5917  return (bool)$this->tutor_ntf_status;
5918  }
5919 
5920  public function setTutorNotificationStatus($a_value)
5921  {
5922  $this->tutor_ntf_status = (bool)$a_value;
5923  }
5924 
5926  {
5928  }
5929 
5930  public function setTutorNotificationRecipients(array $a_value)
5931  {
5932  $this->tutor_ntf_recipients = $a_value;
5933  }
5934 
5935  public function getTutorNotificationTarget()
5936  {
5937  return $this->tutor_ntf_target;
5938  }
5939 
5940  public function setTutorNotificationTarget($a_value)
5941  {
5942  $this->tutor_ntf_target = (int)$a_value;
5943  }
5944 
5945  protected function checkTutorNotification()
5946  {
5947  global $ilDB;
5948 
5949  if($this->getTutorNotificationStatus())
5950  {
5951  $user_ids = $this->getNotificationTargetUserIds(($this->getTutorNotificationTarget() == self::NOTIFICATION_INVITED_USERS));
5952  if($user_ids)
5953  {
5954  $set = $ilDB->query("SELECT COUNT(*) numall FROM svy_finished".
5955  " WHERE survey_fi = ".$ilDB->quote($this->getSurveyId(), "integer").
5956  " AND state = ".$ilDB->quote(1, "integer").
5957  " AND ".$ilDB->in("user_fi", $user_ids, "", "integer"));
5958  $row = $ilDB->fetchAssoc($set);
5959  if($row["numall"] == sizeof($user_ids))
5960  {
5961  $this->sendTutorNotification();
5962  }
5963  }
5964  }
5965  }
5966 
5967  public function getNotificationTargetUserIds($a_use_invited)
5968  {
5969  global $tree;
5970 
5971  if((bool)$a_use_invited)
5972  {
5973  $user_ids = $this->getInvitedUsers();
5974  }
5975  else
5976  {
5977  $parent_grp_ref_id = $tree->checkForParentType($this->getRefId(), "grp");
5978  if($parent_grp_ref_id)
5979  {
5980  include_once "Modules/Group/classes/class.ilGroupParticipants.php";
5981  $part = new ilGroupParticipants(ilObject::_lookupObjId($parent_grp_ref_id));
5982  $user_ids = $part->getMembers();
5983  }
5984  else
5985  {
5986  $parent_crs_ref_id = $tree->checkForParentType($this->getRefId(), "crs");
5987  if($parent_crs_ref_id)
5988  {
5989  include_once "Modules/Course/classes/class.ilCourseParticipants.php";
5990  $part = new ilCourseParticipants(ilObject::_lookupObjId($parent_crs_ref_id));
5991  $user_ids = $part->getMembers();
5992  }
5993  }
5994  }
5995  return $user_ids;
5996  }
5997 
5998  protected function sendTutorNotification()
5999  {
6000  include_once "./Services/Mail/classes/class.ilMail.php";
6001  include_once "./Services/User/classes/class.ilObjUser.php";
6002  include_once "./Services/Language/classes/class.ilLanguageFactory.php";
6003  include_once "./Services/User/classes/class.ilUserUtil.php";
6004  include_once "./Services/Link/classes/class.ilLink.php";
6005  $link = ilLink::_getStaticLink($this->getRefId(), "svy");
6006 
6007  foreach($this->getTutorNotificationRecipients() as $user_id)
6008  {
6009  // use language of recipient to compose message
6010  $ulng = ilLanguageFactory::_getLanguageOfUser($user_id);
6011  $ulng->loadLanguageModule('survey');
6012 
6013  $subject = sprintf($ulng->txt('survey_notification_tutor_subject'), $this->getTitle());
6014  $message = sprintf($ulng->txt('survey_notification_tutor_salutation'), ilObjUser::_lookupFullname($user_id))."\n\n";
6015 
6016  $message .= $ulng->txt('survey_notification_tutor_body').":\n\n";
6017  $message .= $ulng->txt('obj_svy').": ". $this->getTitle()."\n";
6018  $message .= "\n".$ulng->txt('survey_notification_tutor_link').": ".$link;
6019 
6020  $mail_obj = new ilMail(ANONYMOUS_USER_ID);
6021  $mail_obj->appendInstallationSignature(true);
6022  $mail_obj->sendMail(ilObjUser::_lookupLogin($user_id),
6023  "", "", $subject, $message, array(), array("system"));
6024  }
6025  }
6026 
6027  public function checkReminder()
6028  {
6029  global $ilDB, $ilAccess;
6030 
6031  $now = time();
6032  $now_with_format = date("YmdHis", $now);
6033  $today = date("Y-m-d");
6034 
6035  // object settings / participation period
6036  if($this->isOffline() ||
6037  !$this->getReminderStatus() ||
6038  ($this->getStartDate() && $now_with_format < $this->getStartDate()) ||
6039  ($this->getEndDate() && $now_with_format > $this->getEndDate()))
6040  {
6041  return false;
6042  }
6043 
6044  // reminder period
6045  $start = $this->getReminderStart();
6046  if($start)
6047  {
6048  $start = $start->get(IL_CAL_DATE);
6049  }
6050  $end = $this->getReminderEnd();
6051  if($end)
6052  {
6053  $end = $end->get(IL_CAL_DATE);
6054  }
6055  if($today < $start ||
6056  ($end && $today > $end))
6057  {
6058  return false;
6059  }
6060 
6061  // object access period
6062  include_once "Services/Object/classes/class.ilObjectActivation.php";
6063  $item_data = ilObjectActivation::getItem($this->getRefId());
6064  if($item_data["timing_type"] == ilObjectActivation::TIMINGS_ACTIVATION &&
6065  ($now < $item_data["timing_start"] ||
6066  $now > $item_data["timing_end"]))
6067  {
6068  return false;
6069  }
6070 
6071  // check frequency
6072  $cut = new ilDate($today, IL_CAL_DATE);
6073  $cut->increment(IL_CAL_DAY, $this->getReminderFrequency()*-1);
6074  if(!$this->getReminderLastSent() ||
6075  $cut->get(IL_CAL_DATE) >= substr($this->getReminderLastSent(), 0, 10))
6076  {
6077  $missing_ids = array();
6078 
6079  // #16871
6080  $user_ids = $this->getNotificationTargetUserIds(($this->getReminderTarget() == self::NOTIFICATION_INVITED_USERS));
6081  if($user_ids)
6082  {
6083  // gather participants who already finished
6084  $finished_ids = array();
6085  $set = $ilDB->query("SELECT user_fi FROM svy_finished".
6086  " WHERE survey_fi = ".$ilDB->quote($this->getSurveyId(), "integer").
6087  " AND state = ".$ilDB->quote(1, "text").
6088  " AND ".$ilDB->in("user_fi", $user_ids, "", "integer"));
6089  while($row = $ilDB->fetchAssoc($set))
6090  {
6091  $finished_ids[] = $row["user_fi"];
6092  }
6093 
6094  // some users missing out?
6095  $missing_ids = array_diff($user_ids, $finished_ids);
6096  if($missing_ids)
6097  {
6098  foreach($missing_ids as $idx => $user_id)
6099  {
6100  // should be able to participate
6101  if(!$ilAccess->checkAccessOfUser($user_id, "read", "", $this->getRefId(), "svy", $this->getId()))
6102  {
6103  unset($missing_ids[$idx]);
6104  }
6105  }
6106  }
6107  if($missing_ids)
6108  {
6109  $this->sentReminder($missing_ids);
6110  }
6111  }
6112 
6113  $this->setReminderLastSent($today);
6114  $this->saveToDb();
6115 
6116  return sizeof($missing_ids);
6117  }
6118 
6119  return false;
6120  }
6121 
6122  protected function sentReminder(array $a_recipient_ids)
6123  {
6124  include_once "./Services/Mail/classes/class.ilMail.php";
6125 
6126  // use mail template
6127  if($this->getReminderTemplate() &&
6128  array_key_exists($this->getReminderTemplate(), $this->getReminderMailTemplates()))
6129  {
6130  $prov = new ilMailTemplateDataProvider();
6131  $tmpl = $prov->getTemplateById($this->getReminderTemplate());
6132 
6133  $tmpl_params = array(
6134  "ref_id" => $this->getRefId(),
6135  "ts" => time()
6136  );
6137  }
6138  else
6139  {
6140  $tmpl = null;
6141 
6142  include_once "./Services/Link/classes/class.ilLink.php";
6143  $link = ilLink::_getStaticLink($this->getRefId(), "svy");
6144 
6145  include_once "./Services/Language/classes/class.ilLanguageFactory.php";
6146  }
6147 
6148  foreach($a_recipient_ids as $user_id)
6149  {
6150  if($tmpl)
6151  {
6152  $subject = $tmpl->getSubject();
6153  $message = $this->sentReminderPlaceholders($tmpl->getMessage(), $user_id, $tmpl_params);
6154  }
6155  // use lng
6156  else
6157  {
6158  // use language of recipient to compose message
6159  $ulng = ilLanguageFactory::_getLanguageOfUser($user_id);
6160  $ulng->loadLanguageModule('survey');
6161 
6162  $subject = sprintf($ulng->txt('survey_reminder_subject'), $this->getTitle());
6163  $message = sprintf($ulng->txt('survey_reminder_salutation'), ilObjUser::_lookupFullname($user_id))."\n\n";
6164 
6165  $message .= $ulng->txt('survey_reminder_body').":\n\n";
6166  $message .= $ulng->txt('obj_svy').": ". $this->getTitle()."\n";
6167  $message .= "\n".$ulng->txt('survey_reminder_link').": ".$link;
6168  }
6169 
6170  $mail_obj = new ilMail(ANONYMOUS_USER_ID);
6171  $mail_obj->appendInstallationSignature(true);
6172  $mail_obj->sendMail(ilObjUser::_lookupLogin($user_id),
6173  "", "", $subject, $message, array(), array("system"));
6174  }
6175  }
6176 
6177  function setActivationStartDate($starting_time = NULL)
6178  {
6179  $this->activation_starting_time = $starting_time;
6180  }
6181 
6182  function setActivationEndDate($ending_time = NULL)
6183  {
6184  $this->activation_ending_time = $ending_time;
6185  }
6186 
6188  {
6189  return (strlen($this->activation_starting_time)) ? $this->activation_starting_time : NULL;
6190  }
6191 
6193  {
6194  return (strlen($this->activation_ending_time)) ? $this->activation_ending_time : NULL;
6195  }
6196 
6197  function setViewOwnResults($a_value)
6198  {
6199  $this->view_own_results = (bool)$a_value;
6200  }
6201 
6203  {
6204  return $this->view_own_results;
6205  }
6206 
6207  function setMailOwnResults($a_value)
6208  {
6209  $this->mail_own_results = (bool)$a_value;
6210  }
6211 
6213  {
6214  return $this->mail_own_results;
6215  }
6216 
6217  function setMailConfirmation($a_value)
6218  {
6219  $this->mail_confirmation = (bool)$a_value;
6220  }
6221 
6223  {
6224  return $this->mail_confirmation;
6225  }
6226 
6227  function setAnonymousUserList($a_value)
6228  {
6229  $this->anon_user_list = (bool)$a_value;
6230  }
6231 
6233  {
6234  return $this->anon_user_list;
6235  }
6236 
6237  public static function getSurveySkippedValue()
6238  {
6239  global $lng;
6240 
6241  // #13541
6242 
6243  include_once "./Services/Administration/classes/class.ilSetting.php";
6244  $surveySetting = new ilSetting("survey");
6245  if(!$surveySetting->get("skipped_is_custom", false))
6246  {
6247  return $lng->txt("skipped");
6248  }
6249  else
6250  {
6251  return $surveySetting->get("skipped_custom_value", "");
6252  }
6253  }
6254 
6255  public function getReminderMailTemplates()
6256  {
6257  $res = array();
6258 
6259  include_once "Services/Mail/classes/class.ilMailTemplateDataProvider.php";
6260  include_once "Modules/Survey/classes/class.ilSurveyMailTemplateReminderContext.php";
6261  $mprov = new ilMailTemplateDataProvider();
6262  foreach($mprov->getTemplateByContexId(ilSurveyMailTemplateReminderContext::ID) as $tmpl)
6263  {
6264  $res[$tmpl->getTplId()] = $tmpl->getTitle();
6265  }
6266 
6267  return $res;
6268  }
6269 
6270  protected function sentReminderPlaceholders($a_message, $a_user_id, array $a_context_params)
6271  {
6272  // see ilMail::replacePlaceholders()
6273  include_once "Modules/Survey/classes/class.ilSurveyMailTemplateReminderContext.php";
6274 
6275  try
6276  {
6277  require_once 'Services/Mail/classes/class.ilMailTemplateService.php';
6279 
6280  $user = new ilObjUser($a_user_id);
6281 
6282  require_once 'Services/Mail/classes/class.ilMailTemplatePlaceholderResolver.php';
6283  require_once 'Services/Mail/classes/class.ilMailFormCall.php';
6284  $processor = new ilMailTemplatePlaceholderResolver($context, $a_message);
6285  $a_message = $processor->resolve($user, ilMailFormCall::getContextParameters());
6286 
6287  }
6288  catch(Exception $e)
6289  {
6290  require_once './Services/Logging/classes/public/class.ilLoggerFactory.php';
6291  ilLoggerFactory::getLogger('mail')->error(__METHOD__ . ' has been called with invalid context.');
6292  }
6293 
6294  return $a_message;
6295  }
6296 
6297 } // END class.ilObjSurvey
6298 
6299 ?>
createSurveyCodes($nrOfCodes)
$files
Definition: add-vimline.php:18
showQuestionTitles()
Sets the question titles visible during the query.
sendNotificationMail($user_id, $anonymize_id, $appr_id)
static _lookupLogin($a_user_id)
lookup login
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.
$error
Definition: Error.php:17
static _instanciateQuestion($question_id)
Creates an instance of a question with a given question id.
ILIAS Setting Class.
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)
$size
Definition: RandomTest.php:79
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
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...
& getEvaluationByUser($questions, $active_id)
Calculates the evaluation data for a given user or anonymous id.
processPrintoutput2FO($print_output)
Convert a print output to XSL-FO.
setReminderLastSent($a_value)
$_SESSION["AccountId"]
$result
static _getUsedHTMLTagsAsString($a_module="")
Returns a string of all allowed HTML tags for text editing.
set360Results($a_value)
const EVALUATION_ACCESS_OFF
getParticipantTextResults($active_id)
applySettingsTemplate($template_id)
Apply settings template.
& getSurveyFinishedIds()
Get the finished id&#39;s of all survey participants.
getQuestionGUI($questiontype, $question_id)
Returns a question gui object to a given questiontype and question id.
static validateExternalRaterCode($a_ref_id, $a_code)
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
isComplete()
Returns 1, if a survey is complete for use.
removeQuestions($remove_questions, $remove_questionblocks)
Remove questions from the survey.
static _hasDatasets($survey_id)
getAnonymousIdByCode($a_code)
Class ilObject Basic functions for all objects.
isAccessibleWithoutCode()
Checks if the survey is accessable without a survey code.
read()
read object data from db into object public
static factory($a_package, $a_timeout=0)
Creates an ilRpcClient instance to our ilServer.
canStartSurvey($anonymous_id=NULL, $a_no_rbac=false)
Checks if the survey can be started.
setReminderFrequency($a_value)
removeQuestion($question_id)
Remove a question from the survey.
static getItem($a_ref_id)
Get item data.
static _getObjectsByOperations($a_obj_type, $a_operation, $a_usr_id=0, $limit=0)
Get all objects of a specific type and check access This function is not recursive, instead it parses the serialized rbac_pa entries.
$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.
isOnline()
Gets the survey status.
static is_email($a_email)
This preg-based function checks whether an e-mail address is formally valid.
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)
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
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)
$url
Definition: shib_logout.php:72
setTutorNotificationStatus($a_value)
Survey Question Import Parser.
setObligatoryStates($obligatory_questions)
Sets the obligatory states for questions in a survey from the questions form.
static _getAvailableQuestionpools($use_object_id=FALSE, $could_be_offline=FALSE, $showPath=FALSE, $permission="read")
Returns the available question pools for the active user.
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)
set360SkillService($a_val)
Set skill service.
static _getQuestionGUI($questiontype, $question_id=-1)
Creates a question gui representation.
static sortArray($array, $a_array_sortby, $a_array_sortorder=0, $a_numeric=false, $a_keep_keys=false)
sortArray
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.
for($col=0; $col< 50; $col++) $d
$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.
insertQuestionblock($questionblock_id)
Inserts a questionblock in the survey and saves the relation to the database.
setStartTime($finished_id, $first_question)
setReminderEnd(ilDate $a_value=null)
xslt_error(&$proc)
getAuthor()
Gets the authors name of the ilObjSurvey object.
isHTML($a_text)
Checks if a given string contains HTML or not.
hideQuestionTitles()
Sets the question titles hidden during the query.
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
deleteSurveyRecord()
Deletes the survey from the database.
updateConstraint($precondition_id, $if_question_id, $relation, $value, $conjunction)
Updates a precondition.
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)
Default behaviour is:
isPluginActive($a_pname)
Checks whether or not a question plugin with a given name is active.
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
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.
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.
const NOTIFICATION_PARENT_COURSE
setMailParticipantData($a_data)
static _saveTempFileAsMediaObject($name, $tmp_name, $upload=TRUE)
Create new media object and update page in db and return new media object.
setActivationStartDate($starting_time=NULL)
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)
static moveUploadedFile($a_file, $a_name, $a_target, $a_raise_errors=true, $a_mode="move_uploaded")
move uploaded file
updateOrder(array $a_order)
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.
setMailOwnResults($a_value)
setReminderStart(ilDate $a_value=null)
static formatDate(ilDateTime $date)
Format a date public.
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?
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.
createImportDirectory()
creates data directory for import files (data_dir/svy_data/svy_<id>/import, depending on data directo...
& getQuestionpoolTitles($could_be_offline=FALSE, $showPath=FALSE)
Get the titles of all available survey question pools.
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.
& 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.
const EVALUATION_ACCESS_ALL
getFinishedIdForAppraiseeIdAndRaterId($a_appr_id, $a_rat_id)
Get finished id for an appraisee and a rater.
deleteWorkingData($question_id, $active_id)
Deletes the working data of a question in the database.
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
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)
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
setActivationEndDate($ending_time=NULL)
saveAuthorToMetadata($a_author="")
Saves an authors name into the lifecycle metadata if no lifecycle metadata exists This will only be c...
for($i=1; $i<=count($kw_cases_sel); $i+=1) $lang
Definition: langwiz.php:349
& getAvailableQuestionpools($use_obj_id=false, $could_be_offline=false, $showPath=FALSE, $permission="read")
Returns the available question pools for the active user.
getRefId()
get reference id public
$text
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)
global $DIC
static getLogger($a_component_id)
Get component logger.
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.
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.
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 _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
Wrapper classes for system notifications.
isAppraiseeClosed($a_user_id)
startSurvey($user_id, $anonymous_id, $appraisee_id)
Starts the survey creating an entry in the database.
$params
Definition: example_049.php:96
setAnonymize($a_anonymize)
set anonymize status
Settings template application class.
& getQuestionblockQuestionIds($questionblock_id)
Returns the question id&#39;s of all questions of a question block.
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.
deleteAppraisee($a_user_id)
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