ILIAS  Release_4_4_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  $cl = $this->getClassNameByType($pageObjectType, true);
706  require_once 'Modules/TestQuestionPool/classes/feedback/class.'.$cl.'.php';
707 
708  $this->ensurePageObjectExists($pageObjectType, $pageObjectId);
709 
710  $pageObjectGUI = new $cl($pageObjectId);
711  $pageObjectGUI->setOutputMode($this->getPageObjectOutputMode());
712  return $pageObjectGUI->presentation($this->getPageObjectOutputMode());
713  }
714 
724  final protected function getPageObjectXML($pageObjectType, $pageObjectId)
725  {
726  $cl = $this->getClassNameByType($pageObjectType);
727  require_once 'Modules/TestQuestionPool/classes/feedback/class.'.$cl.'.php';
728 
729  $this->ensurePageObjectExists($pageObjectType, $pageObjectId);
730 
731  $pageObject = new $cl($pageObjectId);
732  return $pageObject->getXMLContent();
733  }
734 
743  final private function ensurePageObjectExists($pageObjectType, $pageObjectId)
744  {
746  {
747  include_once("./Modules/TestQuestionPool/classes/feedback/class.ilAssGenFeedbackPage.php");
748  if( !ilAssGenFeedbackPage::_exists($pageObjectType, $pageObjectId) )
749  {
750  $pageObject = new ilAssGenFeedbackPage();
751  $pageObject->setParentId($this->questionOBJ->getId());
752  $pageObject->setId($pageObjectId);
753  $pageObject->createFromXML();
754  }
755  }
757  {
758  include_once("./Modules/TestQuestionPool/classes/feedback/class.ilAssSpecFeedbackPage.php");
759  if( !ilAssSpecFeedbackPage::_exists($pageObjectType, $pageObjectId) )
760  {
761  $pageObject = new ilAssSpecFeedbackPage();
762  $pageObject->setParentId($this->questionOBJ->getId());
763  $pageObject->setId($pageObjectId);
764  $pageObject->createFromXML();
765  }
766  }
767  }
768 
779  final protected function createPageObject($pageObjectType, $pageObjectId, $pageObjectContent)
780  {
781  $cl = $this->getClassNameByType($pageObjectType);
782  require_once 'Modules/TestQuestionPool/classes/feedback/class.'.$cl.'.php';
783 
784  $pageObject = new $cl();
785  $pageObject->setParentId($this->questionOBJ->getId());
786  $pageObject->setId($pageObjectId);
787  $pageObject->setXMLContent($pageObjectContent);
788  $pageObject->createFromXML();
789  }
790 
802  final protected function duplicatePageObject($pageObjectType, $originalPageObjectId, $duplicatePageObjectId, $duplicatePageObjectParentId)
803  {
804  $cl = $this->getClassNameByType($pageObjectType);
805  require_once 'Modules/TestQuestionPool/classes/feedback/class.'.$cl.'.php';
806 
807  $pageObject = new $cl($originalPageObjectId);
808  $pageObject->setParentId($duplicatePageObjectParentId);
809  $pageObject->setId($duplicatePageObjectId);
810  $pageObject->createFromXML();
811  }
812 
821  final protected function ensurePageObjectDeleted($pageObjectType, $pageObjectId)
822  {
824  {
825  include_once("./Modules/TestQuestionPool/classes/feedback/class.ilAssGenFeedbackPage.php");
826  if( ilAssGenFeedbackPage::_exists($pageObjectType, $pageObjectId) )
827  {
828  $pageObject = new ilAssGenFeedbackPage($pageObjectId);
829  $pageObject->delete();
830  }
831  }
833  {
834  include_once("./Modules/TestQuestionPool/classes/feedback/class.ilAssSpecFeedbackPage.php");
835  if( ilAssSpecFeedbackPage::_exists($pageObjectType, $pageObjectId) )
836  {
837  $pageObject = new ilAssSpecFeedbackPage($pageObjectId);
838  $pageObject->delete();
839  }
840  }
841  }
842 
851  final protected function getGenericFeedbackPageObjectType()
852  {
854  }
855 
864  final protected function getSpecificAnswerFeedbackPageObjectType()
865  {
867  }
868 
879  final public static function isValidFeedbackPageObjectType($feedbackPageObjectType)
880  {
881  switch( $feedbackPageObjectType )
882  {
883  case self::PAGE_OBJECT_TYPE_GENERIC_FEEDBACK:
884  case self::PAGE_OBJECT_TYPE_SPECIFIC_FEEDBACK:
885 
886  return true;
887  }
888 
889  return false;
890  }
891 
903  final protected function getGenericFeedbackPageObjectId($questionId, $solutionCompleted)
904  {
905  $pageObjectId = $this->getGenericFeedbackId($questionId, $solutionCompleted);
906 
907  if( !$pageObjectId )
908  {
909  $pageObjectId = $this->saveGenericFeedbackContent($questionId, $solutionCompleted, null);
910  }
911 
912  return $pageObjectId;
913  }
914 
924  public function getGenericFeedbackExportPresentation($questionId, $solutionCompleted)
925  {
926  if( $this->questionOBJ->isAdditionalContentEditingModePageObject() )
927  {
928  $genericFeedbackExportPresentation = $this->getPageObjectXML(
930  $this->getGenericFeedbackPageObjectId($questionId, $solutionCompleted)
931  );
932  }
933  else
934  {
935  $genericFeedbackExportPresentation = $this->getGenericFeedbackContent($questionId, $solutionCompleted);
936  }
937 
938  return $genericFeedbackExportPresentation;
939  }
940 
951  abstract public function getSpecificAnswerFeedbackExportPresentation($questionId, $answerIndex);
952 
962  public function importGenericFeedback($questionId, $solutionCompleted, $feedbackContent)
963  {
964  if( $this->questionOBJ->isAdditionalContentEditingModePageObject() )
965  {
966  $pageObjectId = $this->getGenericFeedbackPageObjectId($questionId, $solutionCompleted);
967  $pageObjectType = $this->getGenericFeedbackPageObjectType();
968 
969  $this->createPageObject($pageObjectType, $pageObjectId, $feedbackContent);
970  }
971  else
972  {
973  $this->saveGenericFeedbackContent($questionId, $solutionCompleted, $feedbackContent);
974  }
975  }
976 
987  abstract public function importSpecificAnswerFeedback($questionId, $answerIndex, $feedbackContent);
988 }