ILIAS  Release_5_0_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilAssQuestionFeedback.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
14 abstract class ilAssQuestionFeedback
15 {
20 
25 
30 
35 
39  const TABLE_NAME_GENERIC_FEEDBACK = 'qpl_fb_generic';
40 
47  protected $questionOBJ = null;
48 
55  protected $ctrl = null;
56 
63  protected $db = null;
64 
71  protected $lng = null;
72 
79  protected $page_obj_output_mode = "presentation";
80 
92  {
93  $this->questionOBJ = $questionOBJ;
94 
95  $this->ctrl = $ctrl;
96  $this->lng = $lng;
97  $this->db = $db;
98  }
99 
109  public function getGenericFeedbackTestPresentation($questionId, $solutionCompleted)
110  {
111  if( $this->questionOBJ->isAdditionalContentEditingModePageObject() )
112  {
113  $genericFeedbackTestPresentationHTML = $this->getPageObjectContent(
115  $this->getGenericFeedbackPageObjectId($questionId, $solutionCompleted)
116  );
117  }
118  else
119  {
120  $genericFeedbackTestPresentationHTML = $this->getGenericFeedbackContent($questionId, $solutionCompleted);
121  }
122 
123  return $genericFeedbackTestPresentationHTML;
124  }
125 
136  abstract public function getSpecificAnswerFeedbackTestPresentation($questionId, $answerIndex);
137 
147  {
149  $this->lng->txt('feedback_complete_solution'), 'feedback_complete',
150  $this->questionOBJ->isAdditionalContentEditingModePageObject()
151  ));
152 
154  $this->lng->txt('feedback_incomplete_solution'), 'feedback_incomplete',
155  $this->questionOBJ->isAdditionalContentEditingModePageObject()
156  ));
157  }
158 
167  abstract public function completeSpecificFormProperties(ilPropertyFormGUI $form);
168 
177  final public function initGenericFormProperties(ilPropertyFormGUI $form)
178  {
179  if( $this->questionOBJ->isAdditionalContentEditingModePageObject() )
180  {
181  $pageObjectType = $this->getGenericFeedbackPageObjectType();
182 
183  $valueFeedbackSolutionComplete = $this->getPageObjectNonEditableValueHTML(
184  $pageObjectType, $this->getGenericFeedbackPageObjectId($this->questionOBJ->getId(), true)
185  );
186 
187  $valueFeedbackSolutionIncomplete = $this->getPageObjectNonEditableValueHTML(
188  $pageObjectType, $this->getGenericFeedbackPageObjectId($this->questionOBJ->getId(), false)
189  );
190  }
191  else
192  {
193  $valueFeedbackSolutionComplete = $this->questionOBJ->prepareTextareaOutput(
194  $this->getGenericFeedbackContent($this->questionOBJ->getId(), true)
195  );
196 
197  $valueFeedbackSolutionIncomplete = $this->questionOBJ->prepareTextareaOutput(
198  $this->getGenericFeedbackContent($this->questionOBJ->getId(), false)
199  );
200  }
201 
202  $form->getItemByPostVar('feedback_complete')->setValue($valueFeedbackSolutionComplete);
203  $form->getItemByPostVar('feedback_incomplete')->setValue($valueFeedbackSolutionIncomplete);
204  }
205 
214  abstract public function initSpecificFormProperties(ilPropertyFormGUI $form);
215 
224  final public function saveGenericFormProperties(ilPropertyFormGUI $form)
225  {
226  if( !$this->questionOBJ->isAdditionalContentEditingModePageObject() )
227  {
228  $this->saveGenericFeedbackContent($this->questionOBJ->getId(), false, $form->getInput('feedback_incomplete'));
229  $this->saveGenericFeedbackContent($this->questionOBJ->getId(), true, $form->getInput('feedback_complete'));
230  }
231  }
232 
241  abstract public function saveSpecificFormProperties(ilPropertyFormGUI $form);
242 
252  {
253  return false;
254  }
255 
270  final protected function buildFeedbackContentFormProperty($label, $postVar, $asNonEditable)
271  {
272  if($asNonEditable)
273  {
274  require_once 'Services/Form/classes/class.ilNonEditableValueGUI.php';
275 
276  $property = new ilNonEditableValueGUI($label, $postVar, true);
277  }
278  else
279  {
280  require_once 'Services/Form/classes/class.ilTextAreaInputGUI.php';
281  require_once 'Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php';
282 
283  $property = new ilTextAreaInputGUI($label, $postVar);
284  $property->setRequired(false);
285  $property->setRows(10);
286  $property->setCols(80);
287 
288  if( !$this->questionOBJ->getPreventRteUsage() )
289  {
290  $property->setUseRte(true);
291  $property->setRteTags(ilObjAdvancedEditing::_getUsedHTMLTags("assessment"));
292  $property->addPlugin("latex");
293  $property->addButton("latex");
294  $property->addButton("pastelatex");
295  }
296 
297  $property->setRTESupport($this->questionOBJ->getId(), "qpl", "assessment");
298  }
299 
300  return $property;
301  }
302 
314  final public function getGenericFeedbackContent($questionId, $solutionCompleted)
315  {
316  require_once 'Services/RTE/classes/class.ilRTE.php';
317 
318  $correctness = $solutionCompleted ? 1 : 0;
319 
320  $res = $this->db->queryF(
321  "SELECT * FROM {$this->getGenericFeedbackTableName()} WHERE question_fi = %s AND correctness = %s",
322  array('integer', 'text'), array($questionId, $correctness)
323  );
324 
325  $feedbackContent = null;
326 
327  while( $row = $this->db->fetchAssoc($res) )
328  {
329  $feedbackContent = ilRTE::_replaceMediaObjectImageSrc($row['feedback'], 1);
330  break;
331  }
332 
333  return $feedbackContent;
334  }
335 
345  abstract public function getSpecificAnswerFeedbackContent($questionId, $answerIndex);
346 
359  final public function saveGenericFeedbackContent($questionId, $solutionCompleted, $feedbackContent)
360  {
361  require_once 'Services/RTE/classes/class.ilRTE.php';
362 
363  $correctness = $solutionCompleted ? 1 : 0;
364 
365  $feedbackId = $this->getGenericFeedbackId($questionId, $solutionCompleted);
366 
367  if( strlen($feedbackContent) )
368  {
369  $feedbackContent = ilRTE::_replaceMediaObjectImageSrc($feedbackContent, 0);
370  }
371 
372  if( $feedbackId )
373  {
374  $this->db->update(
376  array(
377  'feedback' => array('clob', $feedbackContent),
378  'tstamp' => array('integer', time())
379  ),
380  array(
381  'feedback_id' => array('integer', $feedbackId)
382  )
383  );
384  }
385  else
386  {
387  $feedbackId = $this->db->nextId($this->getGenericFeedbackTableName());
388 
389  $this->db->insert($this->getGenericFeedbackTableName(), array(
390  'feedback_id' => array('integer', $feedbackId),
391  'question_fi' => array('integer', $questionId),
392  'correctness' => array('text', $correctness), // text ?
393  'feedback' => array('clob', $feedbackContent),
394  'tstamp' => array('integer', time())
395  ));
396  }
397 
398  return $feedbackId;
399  }
400 
411  abstract public function saveSpecificAnswerFeedbackContent($questionId, $answerIndex, $feedbackContent);
412 
422  final public function deleteGenericFeedbacks($questionId, $isAdditionalContentEditingModePageObject)
423  {
424  if( $isAdditionalContentEditingModePageObject )
425  {
428  $this->getGenericFeedbackPageObjectId($questionId, true)
429  );
430 
433  $this->getGenericFeedbackPageObjectId($questionId, false)
434  );
435  }
436 
437  $this->db->manipulateF(
438  "DELETE FROM {$this->getGenericFeedbackTableName()} WHERE question_fi = %s", array('integer'), array($questionId)
439  );
440  }
441 
450  abstract public function deleteSpecificAnswerFeedbacks($questionId, $isAdditionalContentEditingModePageObject);
451 
461  final public function duplicateFeedback($originalQuestionId, $duplicateQuestionId)
462  {
463  $this->duplicateGenericFeedback($originalQuestionId, $duplicateQuestionId);
464  $this->duplicateSpecificFeedback($originalQuestionId, $duplicateQuestionId);
465  }
466 
476  final private function duplicateGenericFeedback($originalQuestionId, $duplicateQuestionId)
477  {
478  $res = $this->db->queryF(
479  "SELECT * FROM {$this->getGenericFeedbackTableName()} WHERE question_fi = %s",
480  array('integer'), array($originalQuestionId)
481  );
482 
483  while( $row = $this->db->fetchAssoc($res) )
484  {
485  $feedbackId = $this->db->nextId($this->getGenericFeedbackTableName());
486 
487  $this->db->insert($this->getGenericFeedbackTableName(), array(
488  'feedback_id' => array('integer', $feedbackId),
489  'question_fi' => array('integer', $duplicateQuestionId),
490  'correctness' => array('text', $row['correctness']),
491  'feedback' => array('clob', $row['feedback']),
492  'tstamp' => array('integer', time())
493  ));
494 
495  if( $this->questionOBJ->isAdditionalContentEditingModePageObject() )
496  {
497  $pageObjectType = $this->getGenericFeedbackPageObjectType();
498  $this->duplicatePageObject($pageObjectType, $row['feedback_id'], $feedbackId, $duplicateQuestionId);
499  }
500  }
501  }
502 
512  abstract protected function duplicateSpecificFeedback($originalQuestionId, $duplicateQuestionId);
513 
522  final public function syncFeedback($originalQuestionId, $duplicateQuestionId)
523  {
524  $this->syncGenericFeedback($originalQuestionId, $duplicateQuestionId);
525  $this->syncSpecificFeedback($originalQuestionId, $duplicateQuestionId);
526  }
527 
536  final private function syncGenericFeedback($originalQuestionId, $duplicateQuestionId)
537  {
538  // delete generic feedback of the original question
539  $this->db->manipulateF(
540  "DELETE FROM {$this->getGenericFeedbackTableName()} WHERE question_fi = %s", array('integer'), array($originalQuestionId)
541  );
542 
543  // get generic feedback of the actual (duplicated) question
544  $result = $this->db->queryF(
545  "SELECT * FROM {$this->getGenericFeedbackTableName()} WHERE question_fi = %s", array('integer'), array($duplicateQuestionId)
546  );
547 
548  // save generic feedback to the original question
549  while( $row = $this->db->fetchAssoc($result) )
550  {
551  $nextId = $this->db->nextId($this->getGenericFeedbackTableName());
552 
553  $this->db->insert($this->getGenericFeedbackTableName(), array(
554  'feedback_id' => array('integer', $nextId),
555  'question_fi' => array('integer', $originalQuestionId),
556  'correctness' => array('text', $row['correctness']),
557  'feedback' => array('clob', $row['feedback']),
558  'tstamp' => array('integer', time())
559  ));
560  }
561  }
562 
572  final protected function getGenericFeedbackId($questionId, $solutionCompleted)
573  {
574  $res = $this->db->queryF(
575  "SELECT feedback_id FROM {$this->getGenericFeedbackTableName()} WHERE question_fi = %s AND correctness = %s",
576  array('integer','text'), array($questionId, (int)$solutionCompleted)
577  );
578 
579  $feedbackId = null;
580 
581  while( $row = $this->db->fetchAssoc($res) )
582  {
583  $feedbackId = $row['feedback_id'];
584  break;
585  }
586 
587  return $feedbackId;
588  }
589 
598  abstract protected function syncSpecificFeedback($originalQuestionId, $duplicateQuestionId);
599 
606  final protected function getGenericFeedbackTableName()
607  {
609  }
610 
621  final protected function getPageObjectNonEditableValueHTML($pageObjectType, $pageObjectId)
622  {
623  $link = $this->getPageObjectEditingLink($pageObjectType, $pageObjectId);
624  $content = $this->getPageObjectContent($pageObjectType, $pageObjectId);
625 
626  return "$link<br /><br />$content";
627  }
628 
635  function getClassNameByType($a_type, $a_gui = false)
636  {
637  $gui = ($a_gui)
638  ? "GUI"
639  : "";
640  include_once("./Modules/TestQuestionPool/classes/feedback/class.ilAssQuestionFeedback.php");
642  {
643  return "ilAssGenFeedbackPage".$gui;
644  }
646  {
647  return "ilAssSpecFeedbackPage".$gui;
648  }
649  }
650 
651 
662  final private function getPageObjectEditingLink($pageObjectType, $pageObjectId)
663  {
664  $cl = $this->getClassNameByType($pageObjectType, true);
665  $this->ctrl->setParameterByClass($cl, 'feedback_type', $pageObjectType);
666  $this->ctrl->setParameterByClass($cl, 'feedback_id', $pageObjectId);
667 
668  $linkHREF = $this->ctrl->getLinkTargetByClass($cl, 'edit');
669  $linkTEXT = $this->lng->txt('tst_question_feedback_edit_page');
670 
671  return "<a href='$linkHREF'>$linkTEXT</a>";
672  }
673 
679  final public function setPageObjectOutputMode($a_val)
680  {
681  $this->page_obj_output_mode = $a_val;
682  }
683 
689  final public function getPageObjectOutputMode()
690  {
692  }
693 
703  final protected function getPageObjectContent($pageObjectType, $pageObjectId)
704  {
705  global $ilCtrl;
706 
707  $cl = $this->getClassNameByType($pageObjectType, true);
708  require_once 'Modules/TestQuestionPool/classes/feedback/class.'.$cl.'.php';
709 
710  $this->ensurePageObjectExists($pageObjectType, $pageObjectId);
711 
712  $mode = ($ilCtrl->isAsynch())
713  ? "presentation"
714  : $this->getPageObjectOutputMode();
715 
716  $pageObjectGUI = new $cl($pageObjectId);
717  $pageObjectGUI->setOutputMode($mode);
718 
719  return $pageObjectGUI->presentation($mode);
720  }
721 
731  final protected function getPageObjectXML($pageObjectType, $pageObjectId)
732  {
733  $cl = $this->getClassNameByType($pageObjectType);
734  require_once 'Modules/TestQuestionPool/classes/feedback/class.'.$cl.'.php';
735 
736  $this->ensurePageObjectExists($pageObjectType, $pageObjectId);
737 
738  $pageObject = new $cl($pageObjectId);
739  return $pageObject->getXMLContent();
740  }
741 
750  final private function ensurePageObjectExists($pageObjectType, $pageObjectId)
751  {
753  {
754  include_once("./Modules/TestQuestionPool/classes/feedback/class.ilAssGenFeedbackPage.php");
755  if( !ilAssGenFeedbackPage::_exists($pageObjectType, $pageObjectId) )
756  {
757  $pageObject = new ilAssGenFeedbackPage();
758  $pageObject->setParentId($this->questionOBJ->getId());
759  $pageObject->setId($pageObjectId);
760  $pageObject->createFromXML();
761  }
762  }
764  {
765  include_once("./Modules/TestQuestionPool/classes/feedback/class.ilAssSpecFeedbackPage.php");
766  if( !ilAssSpecFeedbackPage::_exists($pageObjectType, $pageObjectId) )
767  {
768  $pageObject = new ilAssSpecFeedbackPage();
769  $pageObject->setParentId($this->questionOBJ->getId());
770  $pageObject->setId($pageObjectId);
771  $pageObject->createFromXML();
772  }
773  }
774  }
775 
786  final protected function createPageObject($pageObjectType, $pageObjectId, $pageObjectContent)
787  {
788  $cl = $this->getClassNameByType($pageObjectType);
789  require_once 'Modules/TestQuestionPool/classes/feedback/class.'.$cl.'.php';
790 
791  $pageObject = new $cl();
792  $pageObject->setParentId($this->questionOBJ->getId());
793  $pageObject->setId($pageObjectId);
794  $pageObject->setXMLContent($pageObjectContent);
795  $pageObject->createFromXML();
796  }
797 
809  final protected function duplicatePageObject($pageObjectType, $originalPageObjectId, $duplicatePageObjectId, $duplicatePageObjectParentId)
810  {
811  $cl = $this->getClassNameByType($pageObjectType);
812  require_once 'Modules/TestQuestionPool/classes/feedback/class.'.$cl.'.php';
813 
814  $pageObject = new $cl($originalPageObjectId);
815  $pageObject->setParentId($duplicatePageObjectParentId);
816  $pageObject->setId($duplicatePageObjectId);
817  $pageObject->createFromXML();
818  }
819 
828  final protected function ensurePageObjectDeleted($pageObjectType, $pageObjectId)
829  {
831  {
832  include_once("./Modules/TestQuestionPool/classes/feedback/class.ilAssGenFeedbackPage.php");
833  if( ilAssGenFeedbackPage::_exists($pageObjectType, $pageObjectId) )
834  {
835  $pageObject = new ilAssGenFeedbackPage($pageObjectId);
836  $pageObject->delete();
837  }
838  }
840  {
841  include_once("./Modules/TestQuestionPool/classes/feedback/class.ilAssSpecFeedbackPage.php");
842  if( ilAssSpecFeedbackPage::_exists($pageObjectType, $pageObjectId) )
843  {
844  $pageObject = new ilAssSpecFeedbackPage($pageObjectId);
845  $pageObject->delete();
846  }
847  }
848  }
849 
858  final protected function getGenericFeedbackPageObjectType()
859  {
861  }
862 
871  final protected function getSpecificAnswerFeedbackPageObjectType()
872  {
874  }
875 
886  final public static function isValidFeedbackPageObjectType($feedbackPageObjectType)
887  {
888  switch( $feedbackPageObjectType )
889  {
890  case self::PAGE_OBJECT_TYPE_GENERIC_FEEDBACK:
891  case self::PAGE_OBJECT_TYPE_SPECIFIC_FEEDBACK:
892 
893  return true;
894  }
895 
896  return false;
897  }
898 
910  final protected function getGenericFeedbackPageObjectId($questionId, $solutionCompleted)
911  {
912  $pageObjectId = $this->getGenericFeedbackId($questionId, $solutionCompleted);
913 
914  if( !$pageObjectId )
915  {
916  $pageObjectId = $this->saveGenericFeedbackContent($questionId, $solutionCompleted, null);
917  }
918 
919  return $pageObjectId;
920  }
921 
931  public function getGenericFeedbackExportPresentation($questionId, $solutionCompleted)
932  {
933  if( $this->questionOBJ->isAdditionalContentEditingModePageObject() )
934  {
935  $genericFeedbackExportPresentation = $this->getPageObjectXML(
937  $this->getGenericFeedbackPageObjectId($questionId, $solutionCompleted)
938  );
939  }
940  else
941  {
942  $genericFeedbackExportPresentation = $this->getGenericFeedbackContent($questionId, $solutionCompleted);
943  }
944 
945  return $genericFeedbackExportPresentation;
946  }
947 
958  abstract public function getSpecificAnswerFeedbackExportPresentation($questionId, $answerIndex);
959 
969  public function importGenericFeedback($questionId, $solutionCompleted, $feedbackContent)
970  {
971  if( $this->questionOBJ->isAdditionalContentEditingModePageObject() )
972  {
973  $pageObjectId = $this->getGenericFeedbackPageObjectId($questionId, $solutionCompleted);
974  $pageObjectType = $this->getGenericFeedbackPageObjectType();
975 
976  $this->createPageObject($pageObjectType, $pageObjectId, $feedbackContent);
977  }
978  else
979  {
980  $this->saveGenericFeedbackContent($questionId, $solutionCompleted, $feedbackContent);
981  }
982  }
983 
994  abstract public function importSpecificAnswerFeedback($questionId, $answerIndex, $feedbackContent);
995 }