diff --git a/Modules/BookingManager/classes/class.ilBookingAssignObjectsTableGUI.php b/Modules/BookingManager/classes/class.ilBookingAssignObjectsTableGUI.php
new file mode 100644
index 000000000000..8c177022eb94
--- /dev/null
+++ b/Modules/BookingManager/classes/class.ilBookingAssignObjectsTableGUI.php
@@ -0,0 +1,191 @@
+
+ * @version $Id$
+ *
+ * @ingroup ModulesBookingManager
+ */
+class ilBookingAssignObjectsTableGUI extends ilTable2GUI
+{
+ /**
+ * @var ilAccessHandler
+ */
+ protected $access;
+
+ /**
+ * @var ilObjUser
+ */
+ protected $user;
+
+ /**
+ * @var int
+ */
+ protected $ref_id;
+
+ /**
+ * @var int
+ */
+ protected $pool_id;
+
+ /**
+ * @var int
+ */
+ protected $user_id_to_book;
+
+ /**
+ * @var ilObjBookingPool
+ */
+ //protected $bp_object;
+
+ /**
+ * @var int
+ */
+ protected $current_bookings; // [int]
+
+ /**
+ * @var array
+ */
+ protected $filter; // [array]
+
+ /**
+ * @var array
+ */
+ protected $objects; // array
+
+ //TODO clean unused vars.
+ protected $has_schedule; // [bool]
+ protected $may_edit; // [bool]
+ protected $may_assign; // [bool]
+ protected $overall_limit; // [int]
+ protected $reservations = array(); // [array]
+
+ /**
+ * Constructor
+ * @param ilBookingParticipantGUI $a_parent_obj
+ * @param string $a_parent_cmd
+ * @param int $a_ref_id
+ * @param int $a_pool_id
+ * @param int $a_user_id // user id to be assigned
+ */
+ function __construct(ilBookingParticipantGUI $a_parent_obj, $a_parent_cmd, $a_ref_id, $a_pool_id)
+ {
+ global $DIC;
+
+ $this->ctrl = $DIC->ctrl();
+ $this->lng = $DIC->language();
+ $this->user = $DIC->user();
+ $this->access = $DIC->access();
+ $this->ref_id = $a_ref_id;
+
+ $this->pool_id = $a_pool_id;
+
+ if($_GET['bkusr'])
+ {
+ $this->user_id_to_book = (int)$_GET['bkusr'];
+ if(!ilObjUser::_exists($this->user_id_to_book)) {
+ $this->ctrl->redirect($a_parent_obj, $a_parent_cmd);
+ }
+ $user_name_data = ilObjUser::_lookupName($this->user_id_to_book);
+ $user_name = $user_name_data['lastname'].", ".$user_name_data['firstname'];
+ } else {
+ $this->ctrl->redirect($a_parent_obj, 'render');
+ }
+
+ $this->setId("bkaobj".$a_ref_id);
+
+ parent::__construct($a_parent_obj, $a_parent_cmd);
+
+ $this->setTitle($this->lng->txt("book_assign_object").": ".$user_name);
+
+ $this->addColumn("", "");
+ $this->addColumn($this->lng->txt("title"), "title");
+ $this->addColumn($this->lng->txt("description"));
+ $this->addColumn($this->lng->txt("availability"));
+ $this->addColumn($this->lng->txt("action"));
+
+ //Fix this order field
+ //$this->setDefaultOrderField("title");
+ //$this->setDefaultOrderDirection("asc");
+
+ $this->setEnableHeader(true);
+ //$this->setFormAction($this->ctrl->getFormAction($a_parent_obj, $a_parent_cmd));
+ $this->setRowTemplate("tpl.booking_assign_object_row.html", "Modules/BookingManager");
+ //$this->setResetCommand("resetParticipantsFilter");
+ //$this->setFilterCommand("applyParticipantsFilter");
+ //$this->setDisableFilterHiding(true);
+
+ //$this->initFilter();
+
+ $this->getItems($this->getCurrentFilter());
+
+ }
+
+ //TODO implement the filters if any.
+ function initFilter()
+ {
+ return array();
+ }
+
+ /**
+ * Get current filter settings
+ * @return array
+ */
+ function getCurrentFilter()
+ {
+ $filter = array();
+ // filter for object if needed.
+ /*if($this->filter["user_id"])
+ {
+ $filter["user_id"] = $this->filter["user_id"];
+ }*/
+
+ return $filter;
+ }
+
+ /**
+ * Gather data and build rows
+ * @param array $filter
+ */
+ function getItems(array $filter = null)
+ {
+ $data = array();
+ $obj_items = ilBookingObject::getList($this->pool_id);
+ foreach($obj_items as $item)
+ {
+ if(empty(ilBookingReservation::getObjectReservationForUser($item['booking_object_id'], $this->user_id_to_book)))
+ {
+ $this->ctrl->setParameterByClass('ilbookingobjectgui', 'bkusr', $this->user_id_to_book);
+ $this->ctrl->setParameterByClass('ilbookingobjectgui', 'object_id', $item['booking_object_id']);
+ $data[] = array(
+ 'object_id' => $item['booking_object_id'],
+ 'title' => $item['title'],
+ 'description' => $item['description'],
+ 'nr_items' => $item['nr_items'],
+ 'url_assign'=> $this->ctrl->getLinkTargetByClass("ilbookingobjectgui", 'book')
+ );
+ $this->ctrl->setParameterByClass('ilbookingobjectgui', 'bkusr', '');
+ $this->ctrl->setParameterByClass('ilbookingobjectgui', 'object_id', '');
+ }
+ }
+ $this->setData($data);
+ }
+
+ /**
+ * Fill table row
+ * @param array $a_set
+ */
+ protected function fillRow($a_set)
+ {
+ $this->tpl->setVariable("TXT_TITLE", $a_set['title']);
+ $this->tpl->setVariable("TXT_DESCRIPTION", $a_set['description']);
+ $this->tpl->setVariable("TXT_AVAILABLE", $a_set['nr_items']);
+ $this->tpl->setVariable("TXT_ACTION", $this->lng->txt("book_assign"));
+ $this->tpl->setVariable("URL_ACTION", $a_set['url_assign']);
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/Modules/BookingManager/classes/class.ilBookingAssignParticipantsTableGUI.php b/Modules/BookingManager/classes/class.ilBookingAssignParticipantsTableGUI.php
new file mode 100644
index 000000000000..570dda263a5b
--- /dev/null
+++ b/Modules/BookingManager/classes/class.ilBookingAssignParticipantsTableGUI.php
@@ -0,0 +1,174 @@
+
+ * @version $Id$
+ *
+ * @ingroup ModulesBookingManager
+ */
+class ilBookingAssignParticipantsTableGUI extends ilTable2GUI
+{
+ /**
+ * @var ilAccessHandler
+ */
+ protected $access;
+
+ /**
+ * @var ilObjUser
+ */
+ protected $user;
+
+ /**
+ * @var int
+ */
+ protected $ref_id;
+
+ /**
+ * @var int
+ */
+ protected $pool_id;
+
+ /**
+ * @var int
+ */
+ protected $bp_object_id;
+
+ /**
+ * @var ilObjBookingPool
+ */
+ protected $bp_object;
+
+ /**
+ * @var int
+ */
+ protected $current_bookings; // [int]
+
+ /**
+ * @var array
+ */
+ protected $filter; // [array]
+
+ /**
+ * @var array
+ */
+ protected $objects; // array
+
+ //TODO clean unused vars.
+ protected $has_schedule; // [bool]
+ protected $may_edit; // [bool]
+ protected $may_assign; // [bool]
+ protected $overall_limit; // [int]
+ protected $reservations = array(); // [array]
+
+ /**
+ * Constructor
+ * @param ilBookingObjectGUI $a_parent_obj
+ * @param string $a_parent_cmd
+ * @param int $a_ref_id
+ * @param int $a_pool_id
+ * @param int $a_booking_obj_id //booking object to assign users.
+ */
+ function __construct(ilBookingObjectGUI $a_parent_obj, $a_parent_cmd, $a_ref_id, $a_pool_id, $a_booking_obj_id)
+ {
+ global $DIC;
+
+ $this->ctrl = $DIC->ctrl();
+ $this->lng = $DIC->language();
+ $this->user = $DIC->user();
+ $this->access = $DIC->access();
+ $this->ref_id = $a_ref_id;
+ $this->bp_object_id = $a_booking_obj_id;
+ $this->pool_id = $a_pool_id;
+ $this->bp_object = new ilBookingObject($a_booking_obj_id);
+
+ $this->setId("bkaprt".$a_ref_id);
+
+ parent::__construct($a_parent_obj, $a_parent_cmd);
+
+ $this->setTitle($this->lng->txt("book_assign_participant").": ".$this->bp_object->getTitle());
+
+ $this->addColumn("", "");
+ $this->addColumn($this->lng->txt("name"), "name");
+ $this->addColumn($this->lng->txt("book_bobj"));
+ $this->addColumn($this->lng->txt("action"));
+
+ $this->setDefaultOrderField("name");
+ $this->setDefaultOrderDirection("asc");
+
+ $this->setEnableHeader(true);
+ $this->setFormAction($this->ctrl->getFormAction($a_parent_obj, $a_parent_cmd));
+ $this->setRowTemplate("tpl.booking_assign_participant_row.html", "Modules/BookingManager");
+ //$this->setResetCommand("resetParticipantsFilter");
+ //$this->setFilterCommand("applyParticipantsFilter");
+ //$this->setDisableFilterHiding(true);
+
+ $this->initFilter();
+
+ $this->getItems($this->getCurrentFilter());
+
+ }
+
+ //TODO implement the filters if any.
+ function initFilter()
+ {
+ return array();
+ }
+
+ /**
+ * Get current filter settings
+ * @return array
+ */
+ function getCurrentFilter()
+ {
+ $filter = array();
+
+ if($this->filter["user_id"])
+ {
+ $filter["user_id"] = $this->filter["user_id"];
+ }
+
+ return $filter;
+ }
+
+ /**
+ * Gather data and build rows
+ * @param array $filter
+ */
+ function getItems(array $filter = null)
+ {
+ include_once "Modules/BookingManager/classes/class.ilBookingParticipant.php";
+ $data = ilBookingParticipant::getAssignableParticipants($this->bp_object_id);
+ $this->setMaxCount(sizeof($data));
+ $this->setData($data);
+ }
+
+ /**
+ * Fill table row
+ * @param array $a_set
+ */
+ protected function fillRow($a_set)
+ {
+ $this->tpl->setVariable("TXT_NAME", $a_set['name']);
+ $this->tpl->setCurrentBlock('object_titles');
+ foreach($a_set['object_title'] as $obj_title)
+ {
+ $this->tpl->setVariable("TXT_OBJECT", $obj_title);
+ $this->tpl->parseCurrentBlock();
+ }
+
+ $this->ctrl->setParameter($this->parent_obj, 'bkusr', $a_set['user_id']);
+ $this->ctrl->setParameter($this->parent_obj, 'object_id', $this->bp_object_id);
+
+ $this->tpl->setVariable("TXT_ACTION", $this->lng->txt("book_assign"));
+ $this->tpl->setVariable("URL_ACTION", $this->ctrl->getLinkTarget($this->parent_obj, 'book'));
+
+ $this->ctrl->setParameter($this->parent_obj, 'bkusr', '');
+ $this->ctrl->setParameter($this->parent_obj, 'object_id', '');
+
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/Modules/BookingManager/classes/class.ilBookingObjectGUI.php b/Modules/BookingManager/classes/class.ilBookingObjectGUI.php
index 8fb4bcccf6f0..19076951d05d 100644
--- a/Modules/BookingManager/classes/class.ilBookingObjectGUI.php
+++ b/Modules/BookingManager/classes/class.ilBookingObjectGUI.php
@@ -56,7 +56,7 @@ class ilBookingObjectGUI
protected $pool_id; // [int]
protected $pool_has_schedule; // [bool]
protected $pool_overall_limit; // [int]
-
+ protected $user_to_deasign;
/**
* @var int
*/
@@ -88,6 +88,7 @@ function __construct($a_parent_obj)
: $a_parent_obj->object->getOverallLimit();
$this->object_id = (int) $_REQUEST['object_id'];
+ $this->user_to_deasign = (int) $_REQUEST['bkusr'];
$this->rsv_ids = array_map('intval', explode(";", $_GET["rsv_ids"]));
}
@@ -524,6 +525,9 @@ function rsvConfirmCancelUser()
include_once 'Modules/BookingManager/classes/class.ilBookingObject.php';
$type = new ilBookingObject($id);
$conf->addItem('object_id', $id, $type->getTitle());
+ if($this->user_to_deasign) {
+ $conf->addHiddenItem('bkusr', $this->user_to_deasign);
+ }
$conf->setConfirm($lng->txt('book_set_cancel'), 'rsvCancelUser');
$conf->setCancel($lng->txt('cancel'), 'render');
@@ -533,19 +537,23 @@ function rsvConfirmCancelUser()
function rsvCancelUser()
{
$ilCtrl = $this->ctrl;
- $ilUser = $this->user;
$lng = $this->lng;
-
+
+ if($this->user_to_deasign) {
+ $user_id = $this->user_to_deasign;
+ } else {
+ $user_id = $this->user->getId();
+ }
+
$id = $this->object_id;
- if(!$id)
- {
+ if(!$id || !$user_id) {
return;
}
include_once 'Modules/BookingManager/classes/class.ilBookingReservation.php';
- $id = ilBookingReservation::getObjectReservationForUser($id, $ilUser->getId());
+ $id = ilBookingReservation::getObjectReservationForUser($id, $user_id);
$obj = new ilBookingReservation($id);
- if ($obj->getUserId() != $ilUser->getId())
+ if ($obj->getUserId() != $user_id)
{
ilUtil::sendFailure($lng->txt('permission_denied'), true);
$ilCtrl->redirect($this, 'render');
@@ -696,6 +704,19 @@ public function deliverPostFile()
ilUtil::deliverFile($file, $obj->getPostFile());
}
}
+
+ //Table to assing participants to an object.
+ //Todo move to a complete GUI class
+ function assignParticipants()
+ {
+ $this->tabs->clearTargets();
+ $this->tabs->setBackTarget($this->lng->txt('book_back_to_list'), $this->ctrl->getLinkTarget($this, 'render'));
+
+ include_once("./Modules/BookingManager/classes/class.ilBookingAssignParticipantsTableGUI.php");
+ $table = new ilBookingAssignParticipantsTableGUI($this, 'assignParticipants', $this->ref_id, $this->pool_id, $this->object_id);
+
+ $this->tpl->setContent($table->getHTML());
+ }
}
?>
\ No newline at end of file
diff --git a/Modules/BookingManager/classes/class.ilBookingObjectsTableGUI.php b/Modules/BookingManager/classes/class.ilBookingObjectsTableGUI.php
index 1fe218c43395..fa564c3c5eda 100644
--- a/Modules/BookingManager/classes/class.ilBookingObjectsTableGUI.php
+++ b/Modules/BookingManager/classes/class.ilBookingObjectsTableGUI.php
@@ -27,6 +27,7 @@ class ilBookingObjectsTableGUI extends ilTable2GUI
protected $pool_id; // [int]
protected $has_schedule; // [bool]
protected $may_edit; // [bool]
+ protected $may_assign; // [bool]
protected $overall_limit; // [int]
protected $reservations = array(); // [array]
protected $current_bookings; // [int]
@@ -59,6 +60,7 @@ function __construct($a_parent_obj, $a_parent_cmd, $a_ref_id, $a_pool_id, $a_poo
$this->has_schedule = $a_pool_has_schedule;
$this->overall_limit = $a_pool_overall_limit;
$this->may_edit = $ilAccess->checkAccess('write', '', $this->ref_id);
+ $this->may_assign = $ilAccess->checkAccess('edit_permission', '', $this->ref_id);
$this->advmd = ilObjBookingPool::getAdvancedMDFields($this->ref_id);
@@ -294,6 +296,7 @@ protected function fillRow($a_set)
$has_booking = false;
$booking_possible = true;
+ $assign_possible = true;
$has_reservations = false;
$selected = $this->getSelectedColumns();
@@ -316,7 +319,7 @@ protected function fillRow($a_set)
}
if(!$this->has_schedule)
- {
+ {
$cnt = 0;
foreach($this->reservations[$a_set["booking_object_id"]] as $item)
{
@@ -336,11 +339,14 @@ protected function fillRow($a_set)
$this->tpl->setVariable("VALUE_AVAIL", $a_set["nr_items"]-$cnt);
$this->tpl->setVariable("VALUE_AVAIL_ALL", $a_set["nr_items"]);
- if($a_set["nr_items"] <= $cnt || $has_booking
- || ($this->overall_limit && $this->current_bookings && $this->current_bookings >= $this->overall_limit))
+ if($a_set["nr_items"] <= $cnt || ($this->overall_limit && $this->current_bookings && $this->current_bookings >= $this->overall_limit))
{
+ $assign_possible = false;
$booking_possible = false;
- }
+ }
+ if($has_booking){
+ $booking_possible = false;
+ }
}
else if(!$this->may_edit)
{
@@ -388,6 +394,18 @@ protected function fillRow($a_set)
$ilCtrl->setParameterByClass('ilObjBookingPoolGUI', 'object_id', '');
}
+ if($this->may_assign && $assign_possible)
+ {
+ if(is_object($this->filter['period']['from']))
+ {
+ $ilCtrl->setParameter($this->parent_obj, 'sseed', $this->filter['period']['from']->get(IL_CAL_DATE));
+ }
+
+ $items['assign'] = array($lng->txt('book_assign_participant'), $ilCtrl->getLinkTarget($this->parent_obj, 'assignParticipants'));
+
+ $ilCtrl->setParameter($this->parent_obj, 'sseed', '');
+ }
+
if($a_set['info_file'])
{
$items['info'] = array($lng->txt('book_download_info'), $ilCtrl->getLinkTarget($this->parent_obj, 'deliverInfo'));
@@ -396,7 +414,7 @@ protected function fillRow($a_set)
if ($this->may_edit)
{
$items['edit'] = array($lng->txt('edit'), $ilCtrl->getLinkTarget($this->parent_obj, 'edit'));
-
+
// #10890
if(!$has_reservations)
{
diff --git a/Modules/BookingManager/classes/class.ilBookingParticipant.php b/Modules/BookingManager/classes/class.ilBookingParticipant.php
new file mode 100644
index 000000000000..935a347557d7
--- /dev/null
+++ b/Modules/BookingManager/classes/class.ilBookingParticipant.php
@@ -0,0 +1,254 @@
+lng = $DIC->language();
+ $this->db = $DIC->database();
+ $this->il_user = $DIC->user();
+
+ $this->participant_id = $a_user_id;
+ $this->booking_pool_id = $a_booking_pool_id;
+
+ // if read and not exists, store it in db.
+ if(!$this->read()){
+ $this->save();
+ $this->is_new = true;
+ } else {
+ $this->is_new = false;
+ }
+ }
+
+ protected function read()
+ {
+ $query = 'SELECT participant_id FROM il_booking_member'.
+ ' WHERE user_id = '.$this->db->quote($this->participant_id, 'integer').
+ ' AND booking_pool_id = '.$this->db->quote($this->booking_pool_id, 'integer');
+
+ $set = $this->db->query($query);
+ $row = $this->db->fetchAssoc($set);
+ if(empty($row)) {
+ return false;
+ } else {
+ return $row['participant_id'];
+ }
+ }
+
+ protected function save()
+ {
+
+ $assigner_id = $this->il_user->getId();
+ $next_id = $this->db->nextId('il_booking_member');
+
+ $query = 'INSERT INTO il_booking_member'.
+ ' (participant_id, user_id, booking_pool_id, assigner_user_id)'.
+ ' VALUES ('.$this->db->quote($next_id, 'integer').
+ ','.$this->db->quote($this->participant_id, 'integer').
+ ','.$this->db->quote($this->booking_pool_id, 'integer').
+ ','.$this->db->quote($assigner_id, 'integer').')';
+
+ $this->db->manipulate($query);
+ }
+
+ public function getIsNew()
+ {
+ return $this->is_new;
+ }
+
+ static function getAssignableParticipants($a_bp_object_id)
+ {
+ global $DIC;
+
+ $ilDB = $DIC->database();
+
+ $res = array();
+
+ $query = 'SELECT DISTINCT bm.user_id, br.object_id'.
+ ' FROM il_booking_member bm, booking_reservation br'.
+ ' WHERE bm.user_id NOT IN ('.
+ 'SELECT user_id FROM booking_reservation'.
+ ' WHERE object_id = '.$ilDB->quote($a_bp_object_id, 'integer').
+ ' AND (status IS NULL OR status <> '.ilBookingReservation::STATUS_CANCELLED.'))'.
+ ' AND br.object_id = '.$ilDB->quote($a_bp_object_id, 'integer');
+
+ $set = $ilDB->query($query);
+
+ while($row = $ilDB->fetchAssoc($set))
+ {
+ $user_name = ilObjUser::_lookupName($row['user_id']);
+ $name = $user_name['lastname'] . ", " . $user_name['firstname'];
+ $index = $a_bp_object_id."_".$row['user_id'];
+
+ $booking_object = new ilBookingObject($row['object_id']);
+
+ if(!isset($res[$index])) {
+ $res[$index] = array(
+ "user_id" => $row['user_id'],
+ "object_title" => array($booking_object->getTitle()),
+ "name" => $name
+ );
+ }
+ else {
+ if(!in_array($booking_object->getTitle(), $res[$index]['object_title'])) {
+ array_push($res[$index]['object_title'], $booking_object->getTitle());
+ }
+ }
+ }
+
+ return $res;
+ }
+
+ static function getList($a_booking_pool, array $a_filter = null, $a_object_id = null)
+ {
+ global $DIC;
+
+ $ilDB = $DIC->database();
+ $lng = $DIC->language();
+ $ctrl = $DIC->ctrl();
+
+ $res = array();
+
+ $query = 'SELECT bm.user_id, bm.booking_pool_id, br.object_id, bo.title'.
+ ' FROM il_booking_member bm'.
+ ' LEFT JOIN booking_reservation br ON (bm.user_id = br.user_id)'.
+ ' LEFT JOIN booking_object bo ON (br.object_id = bo.booking_object_id)';
+
+ $where = array('bm.booking_pool_id ='.$ilDB->quote($a_booking_pool, 'integer'));
+ if($a_object_id)
+ {
+ $where[] = 'br.object_id = '.$ilDB->quote($a_object_id, 'integer');
+ }
+ if($a_filter['title'])
+ {
+ $where[] = '('.$ilDB->like('title', 'text', '%'.$a_filter['title'].'%').
+ ' OR '.$ilDB->like('description', 'text', '%'.$a_filter['title'].'%').')';
+ }
+ if($a_filter['user_id'])
+ {
+ $where[] = 'bm.user_id = '.$ilDB->quote($a_filter['user_id'], 'integer');
+ }
+
+ $query .= ' WHERE '.implode(' AND ', $where);
+
+ $set = $ilDB->query($query);
+
+ while($row = $ilDB->fetchAssoc($set))
+ {
+ $user_name = ilObjUser::_lookupName($row['user_id']);
+ $name = $user_name['lastname'].", ".$user_name['firstname'];
+ $index = $a_booking_pool."_".$row['user_id'];
+ $actions = array();
+
+ if(!isset($res[$index]))
+ {
+ $ctrl->setParameterByClass('ilbookingobjectgui', 'bkusr', $row['user_id']);
+ $ctrl->setParameterByClass('ilbookingobjectgui', 'object_id', $row['object_id']);
+ //TODO action deassign
+ if($a_object_id){
+ $actions[] = array(
+ 'text' => $lng->txt("book_deassign"),
+ 'url' => $ctrl->getLinkTargetByClass("ilbookingobjectgui", 'rsvConfirmCancelUser')
+ );
+ }
+ $ctrl->setParameterByClass('ilbookingparticipantgui', 'bkusr', '');
+ $ctrl->setParameterByClass('ilbookingparticipantgui', 'object_id', '');
+
+ $ctrl->setParameterByClass('ilbookingparticipantgui', 'bkusr', $row['user_id']);
+ $actions[] = array(
+ 'text' => $lng->txt("book_assign_object"),
+ 'url' => $ctrl->getLinkTargetByClass("ilbookingparticipantgui", 'assignObjects')
+ );
+ $ctrl->setParameterByClass('ilbookingparticipantgui', 'bkusr', '');
+
+ $res[$index] = array(
+ "object_title" => array($row['title']),
+ "name" => $name,
+ "actions" => $actions
+ );
+ } else {
+ if(!in_array($row['title'], $res[$index]['object_title'])) {
+ array_push($res[$index]['object_title'], $row['title']);
+ }
+ }
+ }
+ return $res;
+ }
+
+ /**
+ * @param $a_booking_pool_id
+ * @return array
+ */
+ static function getBookingPoolParticipants(integer $a_booking_pool_id) : array
+ {
+ global $DIC;
+ $ilDB = $DIC->database();
+ $sql = 'SELECT * FROM il_booking_member WHERE booking_pool_id = '.$ilDB->quote($a_booking_pool_id, 'integer');
+
+ $set = $ilDB->query($sql);
+
+ $res = array();
+ while($row = $ilDB->fetchAssoc($set))
+ {
+ $res[] = $row['user_id'];
+ }
+
+ return $res;
+ }
+
+ /**
+ * Get all users who are participants in this booking pool.
+ *
+ * @param integer $a_pool_id
+ * @return array
+ */
+ public static function getUserFilter($a_pool_id)
+ {
+ global $DIC;
+
+ $ilDB = $DIC->database();
+
+ $res = array();
+
+ $sql = "SELECT ud.usr_id,ud.lastname,ud.firstname,ud.login".
+ " FROM usr_data ud ".
+ " RIGHT JOIN il_booking_member m ON (ud.usr_id = m.user_id)".
+ " WHERE ud.usr_id <> ".$ilDB->quote(ANONYMOUS_USER_ID, "integer").
+ " AND m.booking_pool_id = ".$ilDB->quote($a_pool_id, "integer").
+ " ORDER BY ud.lastname,ud.firstname";
+
+ $set = $ilDB->query($sql);
+ while($row = $ilDB->fetchAssoc($set))
+ {
+ $res[$row["usr_id"]] = $row["lastname"].", ".$row["firstname"].
+ " (".$row["login"].")";
+ }
+
+ return $res;
+ }
+
+ protected function isParticipantAssigned($a_booking_object_id, $a_participant_id)
+ {
+ if(!empty(ilBookingReservation::getObjectReservationForUser($a_booking_object_id, $a_participant_id))){
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Modules/BookingManager/classes/class.ilBookingParticipantGUI.php b/Modules/BookingManager/classes/class.ilBookingParticipantGUI.php
new file mode 100644
index 000000000000..d5afa683845c
--- /dev/null
+++ b/Modules/BookingManager/classes/class.ilBookingParticipantGUI.php
@@ -0,0 +1,253 @@
+
+ *
+ * @ilCtrl_Calls ilBookingParticipantGUI: ilRepositorySearchGUI
+ *
+ * @ingroup ModulesBookingManager
+ */
+class ilBookingParticipantGUI
+{
+ /**
+ * @var ilTemplate
+ */
+ protected $tpl;
+
+ /**
+ * @var ilTabsGUI
+ */
+ protected $tabs;
+
+ /**
+ * @var ilCtrl
+ */
+ protected $ctrl;
+
+ /**
+ * @var ilLanguage
+ */
+ protected $lng;
+
+ /**
+ * @var ilAccessHandler
+ */
+ protected $access;
+
+ /**
+ * @var ilToolbarGUI
+ */
+ protected $toolbar;
+
+ const FILTER_ACTION_APPLY = 1;
+ const FILTER_ACTION_RESET = 2;
+
+ /**
+ * Constructor
+ * @param object $a_parent_obj
+ */
+ function __construct(ilObjBookingPoolGUI $a_parent_obj)
+ {
+ global $DIC;
+
+ $this->tpl = $DIC["tpl"];
+ $this->tabs = $DIC->tabs();
+ $this->ctrl = $DIC->ctrl();
+ $this->lng = $DIC->language();
+ $this->access = $DIC->access();
+ $this->toolbar = $DIC->toolbar();
+
+ $this->ref_id = $a_parent_obj->ref_id;
+ $this->pool_id = $a_parent_obj->object->getId();
+
+ $this->lng->loadLanguageModule("book");
+ }
+
+ /**
+ * main switch
+ */
+ function executeCommand()
+ {
+ $ilCtrl = $this->ctrl;
+
+ $next_class = $ilCtrl->getNextClass($this);
+
+ switch($next_class)
+ {
+ case 'ilrepositorysearchgui':
+ include_once('./Services/Search/classes/class.ilRepositorySearchGUI.php');
+ $rep_search = new ilRepositorySearchGUI();
+ $ref_id = $this->ref_id;
+ $rep_search->addUserAccessFilterCallable(function ($a_user_id) use ($ref_id)
+ {
+ return $GLOBALS['DIC']->access()->filterUserIdsByRbacOrPositionOfCurrentUser(
+ 'render',
+ 'render',
+ $this->ref_id,
+ $a_user_id
+ );
+ });
+ $rep_search->setTitle($this->lng->txt("exc_add_participant"));
+ $rep_search->setCallback($this,'addParticipantObject');
+ $this->ctrl->setReturn($this,'render');
+ $this->ctrl->forwardCommand($rep_search);
+ break;
+
+ default:
+ $cmd = $ilCtrl->getCmd("render");
+ $this->$cmd();
+ break;
+ }
+ return true;
+ }
+
+ /**
+ * Render list of booking participants.
+ *
+ * uses ilBookingParticipantsTableGUI
+ */
+ function render()
+ {
+ if ($this->access->checkAccess('edit_permission', '', $this->ref_id))
+ {
+ ilRepositorySearchGUI::fillAutoCompleteToolbar(
+ $this,
+ $this->toolbar,
+ array(
+ 'auto_complete_name' => $this->lng->txt('user'),
+ 'submit_name' => $this->lng->txt('add'),
+ 'add_search' => true,
+ 'add_from_container' => $this->ref_id
+ )
+ );
+
+ include_once 'Modules/BookingManager/classes/class.ilBookingParticipantsTableGUI.php';
+ $table = new ilBookingParticipantsTableGUI($this, 'render', $this->ref_id, $this->pool_id);
+
+ $this->tpl->setContent($table->getHTML());
+ }
+ }
+
+ /**
+ * Add user as member
+ */
+ public function addUserFromAutoCompleteObject()
+ {
+ if(!strlen(trim($_POST['user_login'])))
+ {
+ ilUtil::sendFailure($this->lng->txt('msg_no_search_string'));
+ $this->render();
+ return false;
+ }
+
+ $users = explode(',', $_POST['user_login']);
+
+ $user_ids = array();
+ foreach($users as $user)
+ {
+ $user_id = ilObjUser::_lookupId($user);
+
+ if(!$user_id)
+ {
+ ilUtil::sendFailure($this->lng->txt('user_not_known'));
+ $this->render();
+ }
+ $user_ids[] = $user_id;
+ }
+
+ return $this->addParticipantObject($user_ids);
+ }
+
+ /**
+ * Add new partipant
+ * @param array $a_user_ids
+ * @return bool
+ */
+ function addParticipantObject(array $a_user_ids)
+ {
+ foreach($a_user_ids as $user_id)
+ {
+ if(ilObject::_lookupType($user_id) === "usr")
+ {
+ require_once("./Modules/BookingManager/classes/class.ilBookingParticipant.php");
+
+ $participant_obj = new ilBookingParticipant($user_id, $this->pool_id);
+ if($participant_obj->getIsNew()) {
+ ilUtil::sendSuccess($this->lng->txt("book_participant_assigned"),true);
+ } else {
+ ilUtil::sendFailure($this->lng->txt("book_participant_already_assigned"));
+ return false;
+ }
+ }
+ else
+ {
+ ilUtil::sendFailure("dummy error message, change me");
+ return false;
+ }
+ }
+
+ $this->ctrl->redirect($this, "render");
+ return true;
+ }
+
+ /**
+ * Apply filter from participants table gui
+ */
+ function applyParticipantsFilter()
+ {
+ $this->applyFilterAction(self::FILTER_ACTION_APPLY);
+ }
+
+ /**
+ * Reset filter in participants table gui
+ */
+ function resetParticipantsFilter()
+ {
+ $this->applyFilterAction(self::FILTER_ACTION_RESET);
+ }
+
+ protected function applyFilterAction($a_filter_action)
+ {
+ include_once 'Modules/BookingManager/classes/class.ilBookingParticipantsTableGUI.php';
+ $table = new ilBookingParticipantsTableGUI($this, 'render', $this->ref_id, $this->pool_id);
+ $table->resetOffset();
+ if($a_filter_action === self::FILTER_ACTION_RESET) {
+ $table->resetFilter();
+ } else {
+ $table->writeFilterToSession();
+ }
+
+ $this->render();
+ }
+
+ //TODO implement or remove
+ public function post()
+ {
+ ilLoggerFactory::getRootLogger()->debug("***** POST *****");
+ die("post");
+ }
+
+ //TODO implement or remove
+ public function addUser()
+ {
+ ilLoggerFactory::getRootLogger()->debug("*** ADD User");
+ die("add user");
+ }
+
+ function assignObjects()
+ {
+ $this->tabs->clearTargets();
+ $this->tabs->setBackTarget($this->lng->txt('book_back_to_list'), $this->ctrl->getLinkTarget($this, 'render'));
+
+ include_once("./Modules/BookingManager/classes/class.ilBookingAssignObjectsTableGUI.php");
+ $table = new ilBookingAssignObjectsTableGUI($this, 'assignObjects', $this->ref_id, $this->pool_id);
+
+ $this->tpl->setContent($table->getHTML());
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/Modules/BookingManager/classes/class.ilBookingParticipantsTableGUI.php b/Modules/BookingManager/classes/class.ilBookingParticipantsTableGUI.php
new file mode 100644
index 000000000000..e9f7fcf07a7d
--- /dev/null
+++ b/Modules/BookingManager/classes/class.ilBookingParticipantsTableGUI.php
@@ -0,0 +1,190 @@
+
+ * @version $Id$
+ *
+ * @ingroup ModulesBookingManager
+ */
+class ilBookingParticipantsTableGUI extends ilTable2GUI
+{
+ /**
+ * @var ilAccessHandler
+ */
+ protected $access;
+
+ /**
+ * @var ilObjUser
+ */
+ protected $user;
+
+ /**
+ * @var int
+ */
+ protected $ref_id; // [int]
+
+ /**
+ * @var int
+ */
+ protected $pool_id; // [int]
+
+ /**
+ * @var
+ */
+ protected $filter; // [array]
+
+ /**
+ * @var
+ */
+ protected $objects; // array
+
+ // todo we can get rid of this vars
+ protected $has_schedule; // [bool]
+ protected $may_edit; // [bool]
+ protected $may_assign; // [bool]
+ protected $overall_limit; // [int]
+ protected $reservations = array(); // [array]
+ protected $current_bookings; // [int]
+
+
+ /**
+ * Constructor
+ * @param ilBookingParticipantGUI $a_parent_obj
+ * @param string $a_parent_cmd
+ * @param int $a_ref_id
+ * @param int $a_pool_id
+ */
+ function __construct(ilBookingParticipantGUI $a_parent_obj, $a_parent_cmd, $a_ref_id, $a_pool_id)
+ {
+ global $DIC;
+
+ $this->ctrl = $DIC->ctrl();
+ $this->lng = $DIC->language();
+ $this->user = $DIC->user();
+ $this->access = $DIC->access();
+ $this->ref_id = $a_ref_id;
+ $this->pool_id = $a_pool_id;
+
+ $this->setId("bkprt".$a_ref_id);
+
+ parent::__construct($a_parent_obj, $a_parent_cmd);
+
+ $this->setTitle($this->lng->txt("participants"));
+
+ $this->addColumn($this->lng->txt("name"), "name");
+ $this->addColumn($this->lng->txt("book_bobj"));
+ $this->addColumn($this->lng->txt("action"));
+
+ $this->setDefaultOrderField("name");
+ $this->setDefaultOrderDirection("asc");
+
+ $this->setEnableHeader(true);
+ $this->setFormAction($this->ctrl->getFormAction($a_parent_obj, $a_parent_cmd));
+ $this->setRowTemplate("tpl.booking_participant_row.html", "Modules/BookingManager");
+ $this->setResetCommand("resetParticipantsFilter");
+ $this->setFilterCommand("applyParticipantsFilter");
+ $this->setDisableFilterHiding(true);
+
+ $this->initFilter();
+
+ $this->getItems($this->getCurrentFilter());
+ }
+
+ function initFilter()
+ {
+ //object
+ $this->objects = array();
+ foreach(ilBookingObject::getList($this->pool_id) as $item)
+ {
+ $this->objects[$item["booking_object_id"]] = $item["title"];
+ }
+ $item = $this->addFilterItemByMetaType("object", ilTable2GUI::FILTER_SELECT);
+ $item->setOptions(array(""=>$this->lng->txt('book_all'))+$this->objects);
+ $this->filter["object"] = $item->getValue();
+
+ $title = $this->addFilterItemByMetaType(
+ "title",
+ ilTable2GUI::FILTER_TEXT,
+ false,
+ $this->lng->txt("object")." ".$this->lng->txt("title")."/".$this->lng->txt("description")
+ );
+ $this->filter["title"] = $title->getValue();
+
+ //user
+ require_once("./Modules/BookingManager/classes/class.ilBookingParticipant.php");
+ $options = array(""=>$this->lng->txt('book_all'))+
+ ilBookingParticipant::getUserFilter($this->pool_id);
+ $item = $this->addFilterItemByMetaType("user", ilTable2GUI::FILTER_SELECT);
+ $item->setOptions($options);
+ $this->filter["user_id"] = $item->getValue();
+ }
+
+ /**
+ * Get current filter settings
+ * @return array
+ */
+ function getCurrentFilter()
+ {
+ $filter = array();
+ if($this->filter["object"])
+ {
+ $filter["object"] = $this->filter["object"];
+ }
+ if($this->filter["title"])
+ {
+ $filter["title"] = $this->filter["title"];
+ }
+ if($this->filter["user_id"])
+ {
+ $filter["user_id"] = $this->filter["user_id"];
+ }
+
+ return $filter;
+ }
+
+ /**
+ * Gather data and build rows
+ * @param array $filter
+ */
+ function getItems(array $filter)
+ {
+ include_once "Modules/BookingManager/classes/class.ilBookingParticipant.php";
+
+ if($filter["object"]) {
+ $data = ilBookingParticipant::getList($this->pool_id, $filter, $filter["object"]);
+ } else {
+ $data = ilBookingParticipant::getList($this->pool_id, $filter);
+ }
+
+ $this->setMaxCount(sizeof($data));
+ $this->setData($data);
+ }
+
+ /**
+ * Fill table row
+ * @param array $a_set
+ */
+ protected function fillRow($a_set)
+ {
+ $this->tpl->setVariable("TXT_NAME", $a_set['name']);
+ foreach($a_set['object_title'] as $obj_title)
+ {
+ $this->tpl->setCurrentBlock('object_titles');
+ $this->tpl->setVariable("TXT_OBJECT", $obj_title);
+ $this->tpl->parseCurrentBlock();
+ }
+
+ $this->tpl->setCurrentBlock('actions');
+ foreach($a_set['actions'] as $key => $action)
+ {
+ $this->tpl->setVariable("TXT_ACTION", $action['text']);
+ $this->tpl->setVariable("URL_ACTION", $action['url']);
+ $this->tpl->parseCurrentBlock();
+ }
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/Modules/BookingManager/classes/class.ilBookingReservation.php b/Modules/BookingManager/classes/class.ilBookingReservation.php
index 49149e213d58..c72a2405f5f3 100644
--- a/Modules/BookingManager/classes/class.ilBookingReservation.php
+++ b/Modules/BookingManager/classes/class.ilBookingReservation.php
@@ -23,6 +23,7 @@ class ilBookingReservation
protected $to; // timestamp
protected $status; // status
protected $group_id; // int
+ protected $assigner_id; // int
const STATUS_IN_USE = 2;
const STATUS_CANCELLED = 5;
@@ -88,6 +89,24 @@ function getUserId()
return $this->user_id;
}
+ /**
+ * Set assigner user id
+ * @param $a_assigner_id
+ */
+ function setAssignerId($a_assigner_id)
+ {
+ $this->assigner_id = (int)$a_assigner_id;
+ }
+
+ /**
+ * Get assigner user id
+ * @return int
+ */
+ function getAssignerId()
+ {
+ return $this->assigner_id;
+ }
+
/**
* Set booking from date
* @param int $a_from
@@ -195,6 +214,7 @@ protected function read()
' WHERE booking_reservation_id = '.$ilDB->quote($this->id, 'integer'));
$row = $ilDB->fetchAssoc($set);
$this->setUserId($row['user_id']);
+ $this->setAssignerId($row['assigner_id']);
$this->setObjectId($row['object_id']);
$this->setFrom($row['date_from']);
$this->setTo($row['date_to']);
@@ -219,9 +239,10 @@ function save()
$this->id = $ilDB->nextId('booking_reservation');
return $ilDB->manipulate('INSERT INTO booking_reservation'.
- ' (booking_reservation_id,user_id,object_id,date_from,date_to,status,group_id)'.
+ ' (booking_reservation_id,user_id,assigner_id,object_id,date_from,date_to,status,group_id)'.
' VALUES ('.$ilDB->quote($this->id, 'integer').
','.$ilDB->quote($this->getUserId(), 'integer').
+ ','.$ilDB->quote($this->getAssignerId(), 'integer').
','.$ilDB->quote($this->getObjectId(), 'integer').
','.$ilDB->quote($this->getFrom(), 'integer').
','.$ilDB->quote($this->getTo(), 'integer').
@@ -255,6 +276,7 @@ function update()
return $ilDB->manipulate('UPDATE booking_reservation'.
' SET object_id = '.$ilDB->quote($this->getObjectId(), 'text').
', user_id = '.$ilDB->quote($this->getUserId(), 'integer').
+ ', assigner_id = '.$ilDB->quote($this->getAssignerId(), 'integer').
', date_from = '.$ilDB->quote($this->getFrom(), 'integer').
', date_to = '.$ilDB->quote($this->getTo(), 'integer').
', status = '.$ilDB->quote($this->getStatus(), 'integer').
diff --git a/Modules/BookingManager/classes/class.ilObjBookingPoolAccess.php b/Modules/BookingManager/classes/class.ilObjBookingPoolAccess.php
index a89fe2c2a100..477fc46b80f3 100644
--- a/Modules/BookingManager/classes/class.ilObjBookingPoolAccess.php
+++ b/Modules/BookingManager/classes/class.ilObjBookingPoolAccess.php
@@ -101,7 +101,9 @@ function _checkAccess($a_cmd, $a_permission, $a_ref_id, $a_obj_id, $a_user_id =
// for all RBAC checks use checkAccessOfUser instead the normal checkAccess-method:
// $rbacsystem->checkAccessOfUser($a_user_id, $a_permission, $a_ref_id)
- if($a_permission == "visible" && !$rbacsystem->checkAccessOfUser($a_user_id,'write',$a_ref_id))
+ //TODO refactor this: first check if the object is online and then the permissions.
+ #22653
+ if(($a_permission == "visible" || $a_permission == "read") && !$rbacsystem->checkAccessOfUser($a_user_id,'write',$a_ref_id))
{
include_once "Modules/BookingManager/classes/class.ilObjBookingPool.php";
$pool = new ilObjBookingPool($a_ref_id);
diff --git a/Modules/BookingManager/classes/class.ilObjBookingPoolGUI.php b/Modules/BookingManager/classes/class.ilObjBookingPoolGUI.php
index e60055027740..d3949d7463b0 100644
--- a/Modules/BookingManager/classes/class.ilObjBookingPoolGUI.php
+++ b/Modules/BookingManager/classes/class.ilObjBookingPoolGUI.php
@@ -12,6 +12,7 @@
* @ilCtrl_Calls ilObjBookingPoolGUI: ilPermissionGUI, ilBookingObjectGUI
* @ilCtrl_Calls ilObjBookingPoolGUI: ilBookingScheduleGUI, ilInfoScreenGUI, ilPublicUserProfileGUI
* @ilCtrl_Calls ilObjBookingPoolGUI: ilCommonActionDispatcherGUI, ilObjectCopyGUI, ilObjectMetaDataGUI
+* @ilCtrl_Calls ilObjBookingPoolGUI: ilBookingParticipantGUI
* @ilCtrl_IsCalledBy ilObjBookingPoolGUI: ilRepositoryGUI, ilAdministrationGUI
*/
class ilObjBookingPoolGUI extends ilObjectGUI
@@ -31,6 +32,16 @@ class ilObjBookingPoolGUI extends ilObjectGUI
*/
protected $help;
+ /**
+ * @var int
+ */
+ protected $user_id_to_book; // user who is getting the reservation
+
+ /**
+ * @var int
+ */
+ protected $user_id_assigner; // user who performs the reservation.(self/another)
+
/**
* Constructor
*
@@ -55,6 +66,13 @@ function __construct($a_data, $a_id, $a_call_by_reference, $a_prepare_output = t
$this->sseed = ilUtil::stripSlashes($_GET['sseed']);
$this->reservation_id = (int) $_GET["reservation_id"];
$this->profile_user_id = (int) $_GET['user_id'];
+
+ $this->user_id_assigner = $this->user->getId();
+ if($_GET['bkusr']) {
+ $this->user_id_to_book = (int)$_GET['bkusr'];
+ } else {
+ $this->user_id_to_book = $this->user_id_assigner; // by default user books his own booking objects.
+ }
}
/**
@@ -149,6 +167,13 @@ function executeCommand()
$md_gui = new ilObjectMetaDataGUI($this->object, 'bobj');
$this->ctrl->forwardCommand($md_gui);
break;
+
+ case 'ilbookingparticipantgui':
+ $this->tabs_gui->setTabActive('participants');
+ include_once("Modules/BookingManager/classes/class.ilBookingParticipantGUI.php");
+ $object_gui = new ilBookingParticipantGUI($this);
+ $this->ctrl->forwardCommand($object_gui);
+ break;
default:
$cmd = $this->ctrl->getCmd();
@@ -353,6 +378,10 @@ function setTabs()
if($this->checkPermissionBool('edit_permission'))
{
+ $this->tabs_gui->addTab("participants",
+ $this->lng->txt("participants"),
+ $this->ctrl->getLinkTargetByClass("ilbookingparticipantgui", "render"));
+
$this->tabs_gui->addTab("perm_settings",
$this->lng->txt("perm_settings"),
$this->ctrl->getLinkTargetByClass("ilpermissiongui", "perm"));
@@ -389,7 +418,11 @@ function bookObject()
$this->lng->loadLanguageModule("dateplaner");
$this->ctrl->setParameter($this, 'object_id', $obj->getId());
-
+
+ if($this->user_id_to_book != $this->user_id_assigner) {
+ $this->ctrl->setParameter($this, 'bkusr', $this->user_id_to_book);
+ }
+
if($this->object->getScheduleType() == ilObjBookingPool::TYPE_FIX_SCHEDULE)
{
include_once 'Modules/BookingManager/classes/class.ilBookingSchedule.php';
@@ -785,9 +818,9 @@ function confirmedBookingObject()
if($object_id)
{
if(ilBookingReservation::isObjectAvailableNoSchedule($object_id) &&
- !ilBookingReservation::getObjectReservationForUser($object_id, $ilUser->getId())) // #18304
+ !ilBookingReservation::getObjectReservationForUser($object_id, $this->user_id_to_book)) // #18304
{
- $rsv_ids[] = $this->processBooking($object_id);
+ $rsv_ids[] = $this->processBooking($object_id);
$success = $object_id;
}
else
@@ -843,6 +876,7 @@ function confirmedBookingObject()
if($success)
{
+ $this->saveParticipant();
$this->handleBookingSuccess($success, $rsv_ids);
}
else
@@ -961,7 +995,14 @@ protected function initBookingNumbersForm(array $a_objects_counter, $a_group_id,
$grp->setValue($a_group_id);
$form->addItem($grp);
}
-
+
+ if($this->user_id_assigner != $this->user_id_to_book)
+ {
+ $usr = new ilHiddenInputGUI("bkusr");
+ $usr->setValue($this->user_id_to_book);
+ $form->addItem($usr);
+ }
+
$form->addCommandButton("confirmedBookingNumbers", $this->lng->txt("confirm"));
$form->addCommandButton("render", $this->lng->txt("cancel"));
@@ -1001,7 +1042,13 @@ public function confirmedBookingNumbersObject()
{
include_once 'Modules/BookingManager/classes/class.ilBookingReservation.php';
include_once 'Modules/BookingManager/classes/class.ilBookingObject.php';
-
+
+ //get the user who will get the booking.
+ if($_POST['bkusr'])
+ {
+ $this->user_id_to_book = (int)$_POST['bkusr'];
+ }
+
// convert post data to initial form config
$counter = array();
$current_first = $obj_id = null;
@@ -1097,6 +1144,7 @@ public function confirmedBookingNumbersObject()
}
if($success)
{
+ $this->saveParticipant();
$this->handleBookingSuccess($success, $rsv_ids);
}
else
@@ -1144,15 +1192,14 @@ public function confirmedBookingNumbersObject()
*/
function processBooking($a_object_id, $a_from = null, $a_to = null, $a_group_id = null)
{
- $ilUser = $this->user;
-
// #11995
$this->checkPermission('read');
include_once 'Modules/BookingManager/classes/class.ilBookingReservation.php';
$reservation = new ilBookingReservation();
$reservation->setObjectId($a_object_id);
- $reservation->setUserId($ilUser->getID());
+ $reservation->setUserId($this->user_id_to_book);
+ $reservation->setAssignerId($this->user_id_assigner);
$reservation->setFrom($a_from);
$reservation->setTo($a_to);
$reservation->setGroupId($a_group_id);
@@ -1163,7 +1210,7 @@ function processBooking($a_object_id, $a_from = null, $a_to = null, $a_group_id
$this->lng->loadLanguageModule('dateplaner');
include_once 'Services/Calendar/classes/class.ilCalendarUtil.php';
include_once 'Services/Calendar/classes/class.ilCalendarCategory.php';
- $def_cat = ilCalendarUtil::initDefaultCalendarByType(ilCalendarCategory::TYPE_BOOK,$ilUser->getId(),$this->lng->txt('cal_ch_personal_book'),true);
+ $def_cat = ilCalendarUtil::initDefaultCalendarByType(ilCalendarCategory::TYPE_BOOK,$this->user_id_to_book,$this->lng->txt('cal_ch_personal_book'),true);
include_once 'Modules/BookingManager/classes/class.ilBookingObject.php';
$object = new ilBookingObject($a_object_id);
@@ -1706,7 +1753,16 @@ public function addLocatorItems()
{
$ilLocator->addItem($this->object->getTitle(), $this->ctrl->getLinkTarget($this, "render"), "", $this->object->getRefId());
}
- }
+ }
+
+ /**
+ * save booking participant.
+ */
+ protected function saveParticipant()
+ {
+ include_once ("./Modules/BookingManager/classes/class.ilBookingParticipant.php");
+ $participant = new ilBookingParticipant($this->user_id_to_book, $this->object->getId());
+ }
}
?>
\ No newline at end of file
diff --git a/Modules/BookingManager/templates/default/tpl.booking_assign_object_row.html b/Modules/BookingManager/templates/default/tpl.booking_assign_object_row.html
new file mode 100644
index 000000000000..c5c1c047aff8
--- /dev/null
+++ b/Modules/BookingManager/templates/default/tpl.booking_assign_object_row.html
@@ -0,0 +1,17 @@
+
+ |
+
+ |
+
+ {TXT_TITLE}
+ |
+
+ {TXT_DESCRIPTION}
+ |
+
+ {TXT_AVAILABLE}
+ |
+
+ {TXT_ACTION}
+ |
+
diff --git a/Modules/BookingManager/templates/default/tpl.booking_assign_participant_row.html b/Modules/BookingManager/templates/default/tpl.booking_assign_participant_row.html
new file mode 100644
index 000000000000..8372d844c204
--- /dev/null
+++ b/Modules/BookingManager/templates/default/tpl.booking_assign_participant_row.html
@@ -0,0 +1,16 @@
+
+ |
+
+ |
+
+ {TXT_NAME}
+ |
+
+
+ {TXT_OBJECT}
+
+ |
+
+ {TXT_ACTION}
+ |
+
diff --git a/Modules/BookingManager/templates/default/tpl.booking_participant_row.html b/Modules/BookingManager/templates/default/tpl.booking_participant_row.html
new file mode 100644
index 000000000000..01fb3a062911
--- /dev/null
+++ b/Modules/BookingManager/templates/default/tpl.booking_participant_row.html
@@ -0,0 +1,15 @@
+
+ |
+ {TXT_NAME}
+ |
+
+
+ {TXT_OBJECT}
+
+ |
+
+
+ {TXT_ACTION}
+
+ |
+
diff --git a/Modules/Category/LuceneObjectDefinition.xml b/Modules/Category/LuceneObjectDefinition.xml
index 8049fb5bd888..a42256fa1bf9 100644
--- a/Modules/Category/LuceneObjectDefinition.xml
+++ b/Modules/Category/LuceneObjectDefinition.xml
@@ -2,6 +2,8 @@
+
+
diff --git a/Modules/Category/classes/class.ilObjCategoryAccess.php b/Modules/Category/classes/class.ilObjCategoryAccess.php
index 58725f177e16..70747fd0d702 100644
--- a/Modules/Category/classes/class.ilObjCategoryAccess.php
+++ b/Modules/Category/classes/class.ilObjCategoryAccess.php
@@ -51,8 +51,8 @@ static function _getCommands()
require_once ('Services/WebDAV/classes/class.ilDAVActivationChecker.php');
if (ilDAVActivationChecker::_isActive())
{
- include_once './Services/WebDAV/classes/class.ilDAVUtils.php';
- if(ilDAVUtils::getInstance()->isLocalPasswordInstructionRequired())
+ include_once './Services/WebDAV/classes/class.ilWebDAVUtil.php';
+ if(ilWebDAVUtil::getInstance()->isLocalPasswordInstructionRequired())
{
$commands[] = array('permission' => 'read', 'cmd' => 'showPasswordInstruction', 'lang_var' => 'mount_webfolder', 'enable_anonymous' => 'false');
}
diff --git a/Modules/Category/classes/class.ilObjCategoryGUI.php b/Modules/Category/classes/class.ilObjCategoryGUI.php
index 225b2140dbbb..b611625348cb 100755
--- a/Modules/Category/classes/class.ilObjCategoryGUI.php
+++ b/Modules/Category/classes/class.ilObjCategoryGUI.php
@@ -14,7 +14,7 @@
* @ilCtrl_Calls ilObjCategoryGUI: ilPermissionGUI, ilContainerPageGUI, ilContainerLinkListGUI, ilObjUserGUI, ilObjUserFolderGUI
* @ilCtrl_Calls ilObjCategoryGUI: ilInfoScreenGUI, ilObjStyleSheetGUI, ilCommonActionDispatcherGUI, ilObjectTranslationGUI
* @ilCtrl_Calls ilObjCategoryGUI: ilColumnGUI, ilObjectCopyGUI, ilUserTableGUI, ilDidacticTemplateGUI, ilExportGUI
-* @ilCtrl_Calls ilObjCategoryGUI: ilObjTaxonomyGUI, ilObjectMetaDataGUI
+* @ilCtrl_Calls ilObjCategoryGUI: ilObjTaxonomyGUI, ilObjectMetaDataGUI, ilObjectCustomIconConfigurationGUI
*
* @ingroup ModulesCategory
*/
@@ -249,6 +249,20 @@ function executeCommand()
$this->ctrl->forwardCommand($this->getObjectMetadataGUI());
break;
+ case 'ilobjectcustomiconconfigurationgui':
+ if (!$this->checkPermissionBool('write') || !$this->settings->get('custom_icons')) {
+ $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
+ }
+
+ $this->prepareOutput();
+
+ $this->setEditTabs('icons');
+
+ require_once 'Services/Object/Icon/classes/class.ilObjectCustomIconConfigurationGUI.php';
+ $gui = new \ilObjectCustomIconConfigurationGUI($GLOBALS['DIC'], $this, $this->object);
+ $this->ctrl->forwardCommand($gui);
+ break;
+
default:
if ($cmd == "infoScreen")
{
@@ -713,12 +727,12 @@ protected function setEditTabs($active_tab = "settings_misc")
$this->lng->txt("obj_multilinguality"),
$this->ctrl->getLinkTargetByClass("ilobjecttranslationgui", ""));
- // custom icon
- if ($ilSetting->get("custom_icons"))
- {
- $this->tabs_gui->addSubTab("icons",
- $this->lng->txt("icon_settings"),
- $this->ctrl->getLinkTarget($this,'editIcons'));
+ if ($ilSetting->get('custom_icons')) {
+ $this->tabs_gui->addSubTab(
+ 'icons',
+ $this->lng->txt('icon_settings'),
+ $this->ctrl->getLinkTargetByClass('ilobjectcustomiconconfigurationgui')
+ );
}
$this->tabs_gui->activateTab("settings");
@@ -1558,79 +1572,6 @@ public static function _goto($a_target)
}
-
- ////
- //// Icons
- ////
-
- /**
- * Edit folder icons
- */
- function editIconsObject($a_form = null)
- {
- $tpl = $this->tpl;
-
- $this->checkPermission('write');
-
- $this->tabs_gui->setTabActive('settings');
-
- if(!$a_form)
- {
- $a_form = $this->initIconsForm();
- }
-
- $tpl->setContent($a_form->getHTML());
- }
-
- function initIconsForm()
- {
- $this->setEditTabs("icons");
-
- include_once "Services/Form/classes/class.ilPropertyFormGUI.php";
- $form = new ilPropertyFormGUI();
- $form->setFormAction($this->ctrl->getFormAction($this));
-
- $this->showCustomIconsEditing(1, $form);
-
- // $form->setTitle($this->lng->txt('edit_grouping'));
- $form->addCommandButton('updateIcons', $this->lng->txt('save'));
-
- return $form;
- }
-
- /**
- * update container icons
- */
- function updateIconsObject()
- {
- $ilSetting = $this->settings;
-
- $this->checkPermission('write');
-
- $form = $this->initIconsForm();
- if($form->checkInput())
- {
- //save custom icons
- if ($ilSetting->get("custom_icons"))
- {
- if($_POST["cont_icon_delete"])
- {
- $this->object->removeCustomIcon();
- }
- $this->object->saveIcons($_FILES["cont_icon"]['tmp_name']);
- }
- if ($_FILES["cont_icon"]['tmp_name'] || $_POST["cont_icon_delete"])
- {
- ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"),true);
- }
- $this->ctrl->redirect($this,"editIcons");
- }
-
- $form->setValuesByPost();
- $this->editIconsObject($form);
- }
-
-
//
// taxonomy
//
diff --git a/Modules/Category/classes/class.ilObjCategoryListGUI.php b/Modules/Category/classes/class.ilObjCategoryListGUI.php
index 1e093c8529ea..b3de8951529f 100644
--- a/Modules/Category/classes/class.ilObjCategoryListGUI.php
+++ b/Modules/Category/classes/class.ilObjCategoryListGUI.php
@@ -127,15 +127,15 @@ function getCommandLink($a_cmd)
require_once ('Services/WebDAV/classes/class.ilDAVActivationChecker.php');
if (ilDAVActivationChecker::_isActive())
{
- require_once ('Services/WebDAV/classes/class.ilDAVServer.php');
- $davServer = ilDAVServer::getInstance();
+ require_once ('Services/WebDAV/classes/class.ilWebDAVUtil.php');
+ $dav_util = ilWebDAVUtil::getInstance();
// FIXME: The following is a very dirty, ugly trick.
// To mount URI needs to be put into two attributes:
// href and folder. This hack returns both attributes
// like this: http://...mount_uri..." folder="http://...folder_uri...
- $cmd_link = $davServer->getMountURI($this->ref_id).
- '" folder="'.$davServer->getFolderURI($this->ref_id);
+ $cmd_link = $dav_util->getMountURI($this->ref_id).
+ '" folder="'.$dav_util->getFolderURI($this->ref_id);
}
break;
default :
diff --git a/Modules/Chatroom/chat/package.json b/Modules/Chatroom/chat/package.json
index 0064a8ab6c95..2210ce821980 100644
--- a/Modules/Chatroom/chat/package.json
+++ b/Modules/Chatroom/chat/package.json
@@ -1,7 +1,7 @@
{
"name": "ILIAS-Chat",
"description": "ILIAS CHAT",
- "version": "1.0.1",
+ "version": "1.1.0",
"dependencies": {
"express": "3.4.x",
"mysql": "^2.7.0",
diff --git a/Modules/Chatroom/classes/class.ilChatroomXMLParser.php b/Modules/Chatroom/classes/class.ilChatroomXMLParser.php
index 754e40e187ed..8375e0d07eb8 100644
--- a/Modules/Chatroom/classes/class.ilChatroomXMLParser.php
+++ b/Modules/Chatroom/classes/class.ilChatroomXMLParser.php
@@ -318,6 +318,8 @@ public function handlerEndTag($a_xml_parser, $a_name)
case 'Chatroom':
$this->chat->update();
+ // Set imported chats to offline
+ $this->room->setSetting('online_status', 0);
$this->room->save();
break;
}
diff --git a/Modules/Chatroom/classes/gui/class.ilChatroomHistoryGUI.php b/Modules/Chatroom/classes/gui/class.ilChatroomHistoryGUI.php
index dc63bb035bd9..3a01d2bfc9fa 100644
--- a/Modules/Chatroom/classes/gui/class.ilChatroomHistoryGUI.php
+++ b/Modules/Chatroom/classes/gui/class.ilChatroomHistoryGUI.php
@@ -10,9 +10,6 @@
*/
class ilChatroomHistoryGUI extends ilChatroomGUIHandler
{
- /** @var ilTabsGUI */
- private $tabs;
-
/**
* {@inheritdoc}
*/
diff --git a/Modules/Chatroom/classes/gui/class.ilChatroomViewGUI.php b/Modules/Chatroom/classes/gui/class.ilChatroomViewGUI.php
index 0398d31e1b79..af0ba5267376 100644
--- a/Modules/Chatroom/classes/gui/class.ilChatroomViewGUI.php
+++ b/Modules/Chatroom/classes/gui/class.ilChatroomViewGUI.php
@@ -64,7 +64,6 @@ private function setupTemplate()
$this->mainTpl->addJavaScript('Modules/Chatroom/js/chat.js');
$this->mainTpl->addJavaScript('Modules/Chatroom/js/iliaschat.jquery.js');
$this->mainTpl->addJavaScript('libs/bower/bower_components/jquery-outside-events/jquery.ba-outside-events.min.js');
- $this->mainTpl->addJavaScript('Modules/Chatroom/js/json2.js');
$this->mainTpl->addJavaScript('./Services/UIComponent/AdvancedSelectionList/js/AdvancedSelectionList.js');
diff --git a/Modules/Chatroom/js/json2.js b/Modules/Chatroom/js/json2.js
deleted file mode 100644
index 36d3dc393950..000000000000
--- a/Modules/Chatroom/js/json2.js
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- http://www.JSON.org/json2.js
- 2011-01-18
-
- Public Domain.
-
- NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
-
- See http://www.JSON.org/js.html
-
-
- This code should be minified before deployment.
- See http://javascript.crockford.com/jsmin.html
-
- USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
- NOT CONTROL.
-
-
- This file creates a global JSON object containing two methods: stringify
- and parse.
-
- JSON.stringify(value, replacer, space)
- value any JavaScript value, usually an object or array.
-
- replacer an optional parameter that determines how object
- values are stringified for objects. It can be a
- function or an array of strings.
-
- space an optional parameter that specifies the indentation
- of nested structures. If it is omitted, the text will
- be packed without extra whitespace. If it is a number,
- it will specify the number of spaces to indent at each
- level. If it is a string (such as '\t' or ' '),
- it contains the characters used to indent at each level.
-
- This method produces a JSON text from a JavaScript value.
-
- When an object value is found, if the object contains a toJSON
- method, its toJSON method will be called and the result will be
- stringified. A toJSON method does not serialize: it returns the
- value represented by the name/value pair that should be serialized,
- or undefined if nothing should be serialized. The toJSON method
- will be passed the key associated with the value, and this will be
- bound to the value
-
- For example, this would serialize Dates as ISO strings.
-
- Date.prototype.toJSON = function (key) {
- function f(n) {
- // Format integers to have at least two digits.
- return n < 10 ? '0' + n : n;
- }
-
- return this.getUTCFullYear() + '-' +
- f(this.getUTCMonth() + 1) + '-' +
- f(this.getUTCDate()) + 'T' +
- f(this.getUTCHours()) + ':' +
- f(this.getUTCMinutes()) + ':' +
- f(this.getUTCSeconds()) + 'Z';
- };
-
- You can provide an optional replacer method. It will be passed the
- key and value of each member, with this bound to the containing
- object. The value that is returned from your method will be
- serialized. If your method returns undefined, then the member will
- be excluded from the serialization.
-
- If the replacer parameter is an array of strings, then it will be
- used to select the members to be serialized. It filters the results
- such that only members with keys listed in the replacer array are
- stringified.
-
- Values that do not have JSON representations, such as undefined or
- functions, will not be serialized. Such values in objects will be
- dropped; in arrays they will be replaced with null. You can use
- a replacer function to replace those with JSON values.
- JSON.stringify(undefined) returns undefined.
-
- The optional space parameter produces a stringification of the
- value that is filled with line breaks and indentation to make it
- easier to read.
-
- If the space parameter is a non-empty string, then that string will
- be used for indentation. If the space parameter is a number, then
- the indentation will be that many spaces.
-
- Example:
-
- text = JSON.stringify(['e', {pluribus: 'unum'}]);
- // text is '["e",{"pluribus":"unum"}]'
-
-
- text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
- // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
-
- text = JSON.stringify([new Date()], function (key, value) {
- return this[key] instanceof Date ?
- 'Date(' + this[key] + ')' : value;
- });
- // text is '["Date(---current time---)"]'
-
-
- JSON.parse(text, reviver)
- This method parses a JSON text to produce an object or array.
- It can throw a SyntaxError exception.
-
- The optional reviver parameter is a function that can filter and
- transform the results. It receives each of the keys and values,
- and its return value is used instead of the original value.
- If it returns what it received, then the structure is not modified.
- If it returns undefined then the member is deleted.
-
- Example:
-
- // Parse the text. Values that look like ISO date strings will
- // be converted to Date objects.
-
- myData = JSON.parse(text, function (key, value) {
- var a;
- if (typeof value === 'string') {
- a =
-/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
- if (a) {
- return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
- +a[5], +a[6]));
- }
- }
- return value;
- });
-
- myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
- var d;
- if (typeof value === 'string' &&
- value.slice(0, 5) === 'Date(' &&
- value.slice(-1) === ')') {
- d = new Date(value.slice(5, -1));
- if (d) {
- return d;
- }
- }
- return value;
- });
-
-
- This is a reference implementation. You are free to copy, modify, or
- redistribute.
-*/
-
-/*jslint evil: true, strict: false, regexp: false */
-
-/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
- call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
- getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
- lastIndex, length, parse, prototype, push, replace, slice, stringify,
- test, toJSON, toString, valueOf
-*/
-
-
-// Create a JSON object only if one does not already exist. We create the
-// methods in a closure to avoid creating global variables.
-
-var JSON;
-if (!JSON) {
- JSON = {};
-}
-
-(function () {
- "use strict";
-
- function f(n) {
- // Format integers to have at least two digits.
- return n < 10 ? '0' + n : n;
- }
-
- if (typeof Date.prototype.toJSON !== 'function') {
-
- Date.prototype.toJSON = function (key) {
-
- return isFinite(this.valueOf()) ?
- this.getUTCFullYear() + '-' +
- f(this.getUTCMonth() + 1) + '-' +
- f(this.getUTCDate()) + 'T' +
- f(this.getUTCHours()) + ':' +
- f(this.getUTCMinutes()) + ':' +
- f(this.getUTCSeconds()) + 'Z' : null;
- };
-
- String.prototype.toJSON =
- Number.prototype.toJSON =
- Boolean.prototype.toJSON = function (key) {
- return this.valueOf();
- };
- }
-
- var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
- escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
- gap,
- indent,
- meta = { // table of character substitutions
- '\b': '\\b',
- '\t': '\\t',
- '\n': '\\n',
- '\f': '\\f',
- '\r': '\\r',
- '"' : '\\"',
- '\\': '\\\\'
- },
- rep;
-
-
- function quote(string) {
-
-// If the string contains no control characters, no quote characters, and no
-// backslash characters, then we can safely slap some quotes around it.
-// Otherwise we must also replace the offending characters with safe escape
-// sequences.
-
- escapable.lastIndex = 0;
- return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
- var c = meta[a];
- return typeof c === 'string' ? c :
- '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
- }) + '"' : '"' + string + '"';
- }
-
-
- function str(key, holder) {
-
-// Produce a string from holder[key].
-
- var i, // The loop counter.
- k, // The member key.
- v, // The member value.
- length,
- mind = gap,
- partial,
- value = holder[key];
-
-// If the value has a toJSON method, call it to obtain a replacement value.
-
- if (value && typeof value === 'object' &&
- typeof value.toJSON === 'function') {
- value = value.toJSON(key);
- }
-
-// If we were called with a replacer function, then call the replacer to
-// obtain a replacement value.
-
- if (typeof rep === 'function') {
- value = rep.call(holder, key, value);
- }
-
-// What happens next depends on the value's type.
-
- switch (typeof value) {
- case 'string':
- return quote(value);
-
- case 'number':
-
-// JSON numbers must be finite. Encode non-finite numbers as null.
-
- return isFinite(value) ? String(value) : 'null';
-
- case 'boolean':
- case 'null':
-
-// If the value is a boolean or null, convert it to a string. Note:
-// typeof null does not produce 'null'. The case is included here in
-// the remote chance that this gets fixed someday.
-
- return String(value);
-
-// If the type is 'object', we might be dealing with an object or an array or
-// null.
-
- case 'object':
-
-// Due to a specification blunder in ECMAScript, typeof null is 'object',
-// so watch out for that case.
-
- if (!value) {
- return 'null';
- }
-
-// Make an array to hold the partial results of stringifying this object value.
-
- gap += indent;
- partial = [];
-
-// Is the value an array?
-
- if (Object.prototype.toString.apply(value) === '[object Array]') {
-
-// The value is an array. Stringify every element. Use null as a placeholder
-// for non-JSON values.
-
- length = value.length;
- for (i = 0; i < length; i += 1) {
- partial[i] = str(i, value) || 'null';
- }
-
-// Join all of the elements together, separated with commas, and wrap them in
-// brackets.
-
- v = partial.length === 0 ? '[]' : gap ?
- '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
- '[' + partial.join(',') + ']';
- gap = mind;
- return v;
- }
-
-// If the replacer is an array, use it to select the members to be stringified.
-
- if (rep && typeof rep === 'object') {
- length = rep.length;
- for (i = 0; i < length; i += 1) {
- k = rep[i];
- if (typeof k === 'string') {
- v = str(k, value);
- if (v) {
- partial.push(quote(k) + (gap ? ': ' : ':') + v);
- }
- }
- }
- } else {
-
-// Otherwise, iterate through all of the keys in the object.
-
- for (k in value) {
- if (Object.hasOwnProperty.call(value, k)) {
- v = str(k, value);
- if (v) {
- partial.push(quote(k) + (gap ? ': ' : ':') + v);
- }
- }
- }
- }
-
-// Join all of the member texts together, separated with commas,
-// and wrap them in braces.
-
- v = partial.length === 0 ? '{}' : gap ?
- '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
- '{' + partial.join(',') + '}';
- gap = mind;
- return v;
- }
- }
-
-// If the JSON object does not yet have a stringify method, give it one.
-
- if (typeof JSON.stringify !== 'function') {
- JSON.stringify = function (value, replacer, space) {
-
-// The stringify method takes a value and an optional replacer, and an optional
-// space parameter, and returns a JSON text. The replacer can be a function
-// that can replace values, or an array of strings that will select the keys.
-// A default replacer method can be provided. Use of the space parameter can
-// produce text that is more easily readable.
-
- var i;
- gap = '';
- indent = '';
-
-// If the space parameter is a number, make an indent string containing that
-// many spaces.
-
- if (typeof space === 'number') {
- for (i = 0; i < space; i += 1) {
- indent += ' ';
- }
-
-// If the space parameter is a string, it will be used as the indent string.
-
- } else if (typeof space === 'string') {
- indent = space;
- }
-
-// If there is a replacer, it must be a function or an array.
-// Otherwise, throw an error.
-
- rep = replacer;
- if (replacer && typeof replacer !== 'function' &&
- (typeof replacer !== 'object' ||
- typeof replacer.length !== 'number')) {
- throw new Error('JSON.stringify');
- }
-
-// Make a fake root object containing our value under the key of ''.
-// Return the result of stringifying the value.
-
- return str('', {'': value});
- };
- }
-
-
-// If the JSON object does not yet have a parse method, give it one.
-
- if (typeof JSON.parse !== 'function') {
- JSON.parse = function (text, reviver) {
-
-// The parse method takes a text and an optional reviver function, and returns
-// a JavaScript value if the text is a valid JSON text.
-
- var j;
-
- function walk(holder, key) {
-
-// The walk method is used to recursively walk the resulting structure so
-// that modifications can be made.
-
- var k, v, value = holder[key];
- if (value && typeof value === 'object') {
- for (k in value) {
- if (Object.hasOwnProperty.call(value, k)) {
- v = walk(value, k);
- if (v !== undefined) {
- value[k] = v;
- } else {
- delete value[k];
- }
- }
- }
- }
- return reviver.call(holder, key, value);
- }
-
-
-// Parsing happens in four stages. In the first stage, we replace certain
-// Unicode characters with escape sequences. JavaScript handles many characters
-// incorrectly, either silently deleting them, or treating them as line endings.
-
- text = String(text);
- cx.lastIndex = 0;
- if (cx.test(text)) {
- text = text.replace(cx, function (a) {
- return '\\u' +
- ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
- });
- }
-
-// In the second stage, we run the text against regular expressions that look
-// for non-JSON patterns. We are especially concerned with '()' and 'new'
-// because they can cause invocation, and '=' because it can cause mutation.
-// But just to be safe, we want to reject all unexpected forms.
-
-// We split the second stage into 4 regexp operations in order to work around
-// crippling inefficiencies in IE's and Safari's regexp engines. First we
-// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
-// replace all simple value tokens with ']' characters. Third, we delete all
-// open brackets that follow a colon or comma or that begin the text. Finally,
-// we look to see that the remaining characters are only whitespace or ']' or
-// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
-
- if (/^[\],:{}\s]*$/
- .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
- .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
- .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
-
-// In the third stage we use the eval function to compile the text into a
-// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
-// in JavaScript: it can begin a block or an object literal. We wrap the text
-// in parens to eliminate the ambiguity.
-
- j = eval('(' + text + ')');
-
-// In the optional fourth stage, we recursively walk the new structure, passing
-// each name/value pair to a reviver function for possible transformation.
-
- return typeof reviver === 'function' ?
- walk({'': j}, '') : j;
- }
-
-// If the text is not JSON parseable, then a SyntaxError is thrown.
-
- throw new SyntaxError('JSON.parse');
- };
- }
-}());
diff --git a/Modules/ContentPage/LuceneObjectDefinition.xml b/Modules/ContentPage/LuceneObjectDefinition.xml
new file mode 100644
index 000000000000..87b9fd58c11a
--- /dev/null
+++ b/Modules/ContentPage/LuceneObjectDefinition.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+ SELECT content FROM page_object
+ WHERE page_id = ? AND parent_id = page_id AND parent_type = 'copa'
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Modules/ContentPage/classes/class.ilContentPageDataSet.php b/Modules/ContentPage/classes/class.ilContentPageDataSet.php
new file mode 100644
index 000000000000..7a7e3152c187
--- /dev/null
+++ b/Modules/ContentPage/classes/class.ilContentPageDataSet.php
@@ -0,0 +1,155 @@
+ 'integer',
+ 'title' => 'text',
+ 'description' => 'text',
+ 'info-tab' => 'integer',
+ 'style-id' => 'integer',
+ ];
+
+ default:
+ return [];
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function readData($a_entity, $a_version, $a_ids)
+ {
+ $this->data = [];
+
+ if (!is_array($a_ids)) {
+ $a_ids = [$a_ids];
+ }
+
+ $this->readEntityData($a_entity, $a_ids);
+ }
+
+
+ /**
+ * @param string $entity
+ * @param array $ids
+ */
+ protected function readEntityData($entity, $ids)
+ {
+ switch ($entity) {
+ case self::OBJ_TYPE:
+ foreach ($ids as $objId) {
+ if (\ilObject::_lookupType($objId) == self::OBJ_TYPE) {
+ /** @var \ilObjContentPage $obj */
+ $obj = \ilObjectFactory::getInstanceByObjId($objId);
+
+ $this->data[] = [
+ 'id' => $obj->getId(),
+ 'title' => $obj->getTitle(),
+ 'description' => $obj->getDescription(),
+ 'info-tab' => (int)\ilContainer::_lookupContainerSetting(
+ $obj->getId(),
+ \ilObjectServiceSettingsGUI::INFO_TAB_VISIBILITY,
+ true
+ ),
+ 'style-id' => $obj->getStyleSheetId(),
+ ];
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /**
+ * @param $a_entity
+ * @param $a_types
+ * @param $a_rec
+ * @param \ilImportMapping $a_mapping
+ * @param $a_schema_version
+ */
+ public function importRecord($a_entity, $a_types, $a_rec, $a_mapping, $a_schema_version)
+ {
+ switch ($a_entity) {
+ case self::OBJ_TYPE:
+ if ($newObjId = $a_mapping->getMapping('Services/Container', 'objs', $a_rec['id'])) {
+ $newObject = \ilObjectFactory::getInstanceByObjId($newObjId, false);
+ } else {
+ $newObject = new \ilObjContentPage();
+ }
+
+ $newObject->setTitle(\ilUtil::stripSlashes($a_rec['title']));
+ $newObject->setDescription(\ilUtil::stripSlashes($a_rec['description']));
+ $newObject->setStyleSheetId((int)\ilUtil::stripSlashes($a_rec['style-id']));
+
+ if (!$newObject->getId()) {
+ $newObject->create();
+ }
+
+ \ilContainer::_writeContainerSetting(
+ $newObject->getId(),
+ \ilObjectServiceSettingsGUI::INFO_TAB_VISIBILITY,
+ (int)$a_rec['info-tab']
+ );
+
+ $a_mapping->addMapping('Modules/ContentPage', self::OBJ_TYPE, $a_rec['id'], $newObject->getId());
+ $a_mapping->addMapping('Modules/ContentPage', 'style', $newObject->getId(), $newObject->getStyleSheetId());
+ $a_mapping->addMapping(
+ 'Services/COPage',
+ 'pg',
+ self::OBJ_TYPE . ':' . $a_rec['id'],
+ self::OBJ_TYPE . ':' . $newObject->getId()
+ );
+ break;
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function getDependencies($a_entity, $a_version, $a_rec, $a_ids)
+ {
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/Modules/ContentPage/classes/class.ilContentPageExporter.php b/Modules/ContentPage/classes/class.ilContentPageExporter.php
new file mode 100644
index 000000000000..b2ae1531d903
--- /dev/null
+++ b/Modules/ContentPage/classes/class.ilContentPageExporter.php
@@ -0,0 +1,93 @@
+ds = new \ilContentPageDataSet();
+ $this->ds->setDSPrefix('ds');
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getXmlRepresentation($a_entity, $a_schema_version, $a_id)
+ {
+ \ilUtil::makeDirParents($this->getAbsoluteExportDirectory());
+ $this->ds->setExportDirectories($this->dir_relative, $this->dir_absolute);
+
+ return $this->ds->getXmlRepresentation($a_entity, $a_schema_version, $a_id, '', true, true);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getValidSchemaVersions($a_entity)
+ {
+ return array(
+ '5.4.0' => array(
+ 'namespace' => 'http://www.ilias.de/Modules/ContentPage/' . self::OBJ_TYPE . '/5_4',
+ 'xsd_file' => 'ilias_' . self::OBJ_TYPE . '_5_4.xsd',
+ 'uses_dataset' => true,
+ 'min' => '5.4.0',
+ 'max' => '',
+ ),
+ );
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getXmlExportTailDependencies($a_entity, $a_target_release, $a_ids) {
+ $pageObjectIds = [];
+ $styleIds = [];
+
+ foreach ($a_ids as $copaObjId) {
+ $copa = \ilObjectFactory::getInstanceByObjId($copaObjId, false);
+ if (!$copa || !($copa instanceof \ilObjContentPage)) {
+ continue;
+ }
+
+ $copaPageObjIds = $copa->getPageObjIds();
+ foreach ($copaPageObjIds as $copaPageObjId) {
+ $pageObjectIds[] = self::OBJ_TYPE . ':' . $copaPageObjId;
+ }
+
+ if ($copa->getStyleSheetId() > 0) {
+ $styleIds[$copa->getStyleSheetId()] = $copa->getStyleSheetId();
+ }
+ }
+
+ $deps = [];
+
+ if (count($pageObjectIds) > 0) {
+ $deps[] = [
+ 'component' => 'Services/COPage',
+ 'entity' => 'pg',
+ 'ids' => $pageObjectIds,
+ ];
+ }
+
+ if (count($styleIds) > 0) {
+ $deps[] = [
+ 'component' => 'Services/Style',
+ 'entity' => 'sty',
+ 'ids' => array_values($styleIds),
+ ];
+ }
+
+ return $deps;
+ }
+}
\ No newline at end of file
diff --git a/Modules/ContentPage/classes/class.ilContentPageImporter.php b/Modules/ContentPage/classes/class.ilContentPageImporter.php
new file mode 100644
index 000000000000..471dfc70a953
--- /dev/null
+++ b/Modules/ContentPage/classes/class.ilContentPageImporter.php
@@ -0,0 +1,59 @@
+ds = new \ilContentPageDataSet();
+ $this->ds->setDSPrefix('ds');
+ $this->ds->setImportDirectory($this->getImportDirectory());
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function importXmlRepresentation($a_entity, $a_id, $a_xml, $a_mapping)
+ {
+ $parser = new \ilDataSetImportParser($a_entity, $this->getSchemaVersion(), $a_xml, $this->ds, $a_mapping);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function finalProcessing($a_mapping)
+ {
+ parent::finalProcessing($a_mapping);
+
+ $copaMap = $a_mapping->getMappingsOfEntity('Services/COPage', 'pg');
+ foreach ($copaMap as $oldCopaId => $newCopaId) {
+ $newCopaId = substr($newCopaId, strlen(self::OBJ_TYPE) + 1);
+
+ \ilContentPagePage::_writeParentId(self::OBJ_TYPE, $newCopaId, $newCopaId);
+ }
+
+ $styleMapping = $a_mapping->getMappingsOfEntity('Modules/ContentPage', 'style');
+ foreach ($styleMapping as $newCopaId => $oldStyleId) {
+ $newStyleId = (int) $a_mapping->getMapping('Services/Style', 'sty', $oldStyleId);
+ if ($newCopaId > 0 && $newStyleId > 0) {
+ $copa = \ilObjectFactory::getInstanceByObjId($newCopaId, false);
+ if (!$copa || !($copa instanceof \ilObjContentPage)) {
+ continue;
+ }
+ $copa->writeStyleSheetId($newStyleId);
+ $copa->update();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Modules/ContentPage/classes/class.ilContentPageLP.php b/Modules/ContentPage/classes/class.ilContentPageLP.php
new file mode 100644
index 000000000000..7b5015ca6858
--- /dev/null
+++ b/Modules/ContentPage/classes/class.ilContentPageLP.php
@@ -0,0 +1,28 @@
+ctrl = $ctrl;
+ $this->tabs = $tabs;
+ $this->lng = $lng;
+ $this->parentObject = $parentObject;
+
+ $this->lng->loadLanguageModule('content');
+
+ $this->backUrl = $request->getQueryParams()['backurl'] ?? '';
+
+ if (strlen($this->backUrl) > 0) {
+ $this->ctrl->setParameterByClass('ilcontentpagepagegui', 'backurl', rawurlencode($this->backUrl));
+ }
+ }
+
+ /**
+ * @return \ilContentPagePageGUI
+ */
+ protected function getPageObjectGUI(): \ilContentPagePageGUI
+ {
+ $pageObjectGUI = new \ilContentPagePageGUI($this->parentObject->getId());
+ $pageObjectGUI->setStyleId(
+ \ilObjStyleSheet::getEffectiveContentStyleId(
+ $this->parentObject->getStyleSheetId(), $this->parentObject->getType())
+ );
+
+ $pageObjectGUI->obj->addUpdateListener($this->parentObject, 'update');
+
+ return $pageObjectGUI;
+ }
+
+ /**
+ *
+ */
+ protected function ensurePageObjectExists()
+ {
+ if (!\ilContentPagePage::_exists($this->parentObject->getType(), $this->parentObject->getId())) {
+ $pageObject = new \ilContentPagePage();
+ $pageObject->setParentId($this->parentObject->getId());
+ $pageObject->setId($this->parentObject->getId());
+ $pageObject->createFromXML();
+ }
+ }
+
+ /**
+ *
+ */
+ protected function setBackLinkTab()
+ {
+ $backUrl = $this->ctrl->getLinkTargetByClass('ilObjContentPageGUI', self::UI_CMD_VIEW);
+ if (strlen($this->backUrl) > 0) {
+ $backUrlParts = parse_url(\ilUtil::stripSlashes($this->backUrl));
+
+ $script = basename($backUrlParts['path']);
+
+ $backUrl = './' . implode('?', [
+ $script, $backUrlParts['query']
+ ]);
+ }
+
+ $this->tabs->setBackTarget($this->lng->txt('back'), $backUrl);
+ }
+
+ /**
+ * @return \ilContentPagePageGUI
+ */
+ protected function buildEditingPageObjectGUI(): \ilContentPagePageGUI
+ {
+ $this->tabs->clearTargets();
+
+ $this->setBackLinkTab();
+
+ $this->ensurePageObjectExists();
+
+ $pageObjectGUI = $this->getPageObjectGUI();
+ $pageObjectGUI->setEnabledTabs(true);
+
+ return $pageObjectGUI;
+ }
+
+ /**
+ * @return \ilContentPagePageGUI
+ */
+ protected function buildPresentationPageObjectGUI(): \ilContentPagePageGUI
+ {
+ $this->ensurePageObjectExists();
+
+ $pageObjectGUI = $this->getPageObjectGUI();
+ $pageObjectGUI->setEnabledTabs(false);
+
+ $pageObjectGUI->setStyleId(
+ \ilObjStyleSheet::getEffectiveContentStyleId(
+ $this->parentObject->getStyleSheetId(), $this->parentObject->getType()
+ )
+ );
+
+ return $pageObjectGUI;
+ }
+
+ /**
+ * @param string $presentationMode
+ */
+ public function setPresentationMode(string $presentationMode)
+ {
+ $this->presentationMode = $presentationMode;
+ }
+
+ /**
+ * @param string $ctrlLink
+ * @return string
+ * @throws ilCtrlException
+ * @throws ilException
+ */
+ public function forward(string $ctrlLink = ''): string
+ {
+ switch ($this->presentationMode) {
+ case self::PRESENTATION_MODE_EDITING:
+
+ $pageObjectGui = $this->buildEditingPageObjectGUI();
+ return (string)$this->ctrl->forwardCommand($pageObjectGui);
+
+ case self::PRESENTATION_MODE_PRESENTATION:
+ $pageObjectGUI = $this->buildPresentationPageObjectGUI();
+
+ if (is_string($ctrlLink) && strlen($ctrlLink) > 0) {
+ $pageObjectGUI->setFileDownloadLink($ctrlLink . '&cmd=' . self::UI_CMD_COPAGE_DOWNLOAD_FILE);
+ $pageObjectGUI->setFullscreenLink($ctrlLink . '&cmd=' . self::UI_CMD_COPAGE_DISPLAY_FULLSCREEN);
+ $pageObjectGUI->setSourcecodeDownloadScript($ctrlLink . '&cmd=' . self::UI_CMD_COPAGE_DOWNLOAD_PARAGRAPH);
+ }
+
+ return $this->ctrl->getHTML($pageObjectGUI);
+
+ default:
+ throw new \ilException('Unknown presentation mode given');
+ break;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Modules/ContentPage/classes/class.ilContentPagePageConfig.php b/Modules/ContentPage/classes/class.ilContentPagePageConfig.php
new file mode 100644
index 000000000000..47567f7df5a8
--- /dev/null
+++ b/Modules/ContentPage/classes/class.ilContentPagePageConfig.php
@@ -0,0 +1,19 @@
+setEnableInternalLinks(true);
+ $this->setIntLinkHelpDefaultType('RepositoryItem');
+ $this->setSinglePageMode(true);
+ $this->setEnablePermissionChecks(true);
+ }
+}
\ No newline at end of file
diff --git a/Modules/ContentPage/classes/class.ilContentPagePageGUI.php b/Modules/ContentPage/classes/class.ilContentPagePageGUI.php
new file mode 100644
index 000000000000..f05b157f9a23
--- /dev/null
+++ b/Modules/ContentPage/classes/class.ilContentPagePageGUI.php
@@ -0,0 +1,23 @@
+setTemplateTargetVar('ADM_CONTENT');
+ $this->setTemplateOutput(true);
+ }
+}
\ No newline at end of file
diff --git a/Modules/ContentPage/classes/class.ilObjContentPage.php b/Modules/ContentPage/classes/class.ilObjContentPage.php
new file mode 100644
index 000000000000..377f32f211f2
--- /dev/null
+++ b/Modules/ContentPage/classes/class.ilObjContentPage.php
@@ -0,0 +1,190 @@
+type = self::OBJ_TYPE;
+ }
+
+ /**
+ * @return int
+ */
+ public function getStyleSheetId(): int
+ {
+ return (int)$this->styleId;
+ }
+
+ /**
+ * @param int $styleId
+ */
+ public function setStyleSheetId(int $styleId)
+ {
+ $this->styleId = $styleId;
+ }
+
+ /**
+ * @param int $styleId
+ */
+ public function writeStyleSheetId(int $styleId)
+ {
+ $this->db->manipulateF(
+ 'UPDATE content_object SET stylesheet = %s WHERE id = %s',
+ ['integer', 'integer'],
+ [(int) $styleId, $this->getId()]
+ );
+
+ $this->setStyleSheetId($styleId);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function doCloneObject($new_obj, $a_target_id, $a_copy_id = null)
+ {
+ /**
+ * @var $new_obj self
+ */
+ parent::doCloneObject($new_obj, $a_target_id, $a_copy_id);
+
+ if (\ilContentPagePage::_exists($this->getType(), $this->getId())) {
+ $originalPageObject = new \ilContentPagePage($this->getId());
+ $originalXML = $originalPageObject->getXMLContent();
+
+ $duplicatePageObject = new \ilContentPagePage();
+ $duplicatePageObject->setId($new_obj->getId());
+ $duplicatePageObject->setParentId($new_obj->getId());
+ $duplicatePageObject->setXMLContent($originalXML);
+ $duplicatePageObject->createFromXML();
+ }
+
+ $styleId = $this->getStyleSheetId();
+ if ($styleId > 0 && !\ilObjStyleSheet::_lookupStandard($styleId)) {
+ $style = \ilObjectFactory::getInstanceByObjId($styleId, false);
+ if ($style) {
+ $new_id = $style->ilClone();
+ $new_obj->setStyleSheetId($new_id);
+ $new_obj->update();
+ }
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function doRead()
+ {
+ parent::doRead();
+
+ $res = $this->db->queryF(
+ 'SELECT * FROM content_page_data WHERE content_page_id = %s',
+ ['integer'],
+ [$this->getId()]
+ );
+
+ while($data = $this->db->fetchAssoc($res)) {
+ $this->setStyleSheetId((int)$data['stylesheet']);
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function doCreate()
+ {
+ parent::doCreate();
+
+ $this->db->manipulateF('
+ INSERT INTO content_page_data
+ (
+ content_page_id,
+ stylesheet
+ )
+ VALUES(%s, %s)',
+ ['integer', 'integer'],
+ [$this->getId(), 0]
+ );
+ }
+
+
+ /**
+ * @inheritdoc
+ */
+ protected function doUpdate()
+ {
+ parent::doUpdate();
+
+ $this->db->manipulateF('
+ UPDATE content_page_data
+ SET
+ stylesheet = %s
+ WHERE content_page_id = %s',
+ ['integer', 'integer'],
+ [$this->getStyleSheetId(), $this->getId()]
+ );
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function doDelete()
+ {
+ parent::doDelete();
+
+ if (\ilContentPagePage::_exists($this->getType(), $this->getId())) {
+ $originalPageObject = new \ilContentPagePage($this->getId());
+ $originalPageObject->delete();
+ }
+ }
+
+ /**
+ * @return int[]
+ */
+ public function getPageObjIds(): array
+ {
+ $pageObjIds = [];
+
+ $sql = "SELECT page_id FROM page_object WHERE parent_id = %s AND parent_type = %s";
+ $res = $this->db->queryF(
+ $sql,
+ ['integer', 'text'],
+ [$this->getId(), $this->getType()]
+ );
+
+ while ($row = $this->db->fetchAssoc($res)) {
+ $pageObjIds[] = $row['page_id'];
+ }
+
+ return $pageObjIds;
+ }
+
+ /**
+ * @param int $usrId
+ */
+ public function trackProgress(int $usrId)
+ {
+ \ilChangeEvent::_recordReadEvent(
+ $this->getType(),
+ $this->getRefId(),
+ $this->getId(),
+ $usrId
+ );
+
+ \ilLPStatusWrapper::_refreshStatus(
+ $this->getId(),
+ [$usrId]
+ );
+ }
+}
\ No newline at end of file
diff --git a/Modules/ContentPage/classes/class.ilObjContentPageAccess.php b/Modules/ContentPage/classes/class.ilObjContentPageAccess.php
new file mode 100644
index 000000000000..be88b5641138
--- /dev/null
+++ b/Modules/ContentPage/classes/class.ilObjContentPageAccess.php
@@ -0,0 +1,59 @@
+ 'read',
+ 'cmd' => self::UI_CMD_VIEW,
+ 'lang_var' => 'show',
+ 'default' => true
+ ],
+ [
+ 'permission'=> 'write',
+ 'cmd' => 'edit',
+ 'lang_var' => 'settings'
+ ],
+ ];
+
+ return $commands;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public static function _checkGoto($a_target) {
+ $targetAttributes = explode('_', $a_target);
+
+ if (2 != count($targetAttributes) || $targetAttributes[0] != self::OBJ_TYPE || ((int)$targetAttributes[1]) <= 0) {
+ return false;
+ }
+
+ return parent::_checkGoto($a_target);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public static function getConditionOperators()
+ {
+ return [];
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public static function checkCondition($a_trigger_obj_id, $a_operator, $a_value, $a_usr_id)
+ {
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/Modules/ContentPage/classes/class.ilObjContentPageGUI.php b/Modules/ContentPage/classes/class.ilObjContentPageGUI.php
new file mode 100644
index 000000000000..ca750cda1e42
--- /dev/null
+++ b/Modules/ContentPage/classes/class.ilObjContentPageGUI.php
@@ -0,0 +1,725 @@
+dic = $DIC;
+ $this->request = $this->dic->http()->request();
+ $this->settings = $this->dic->settings();
+ $this->access = $this->dic->access();
+ $this->ctrl = $this->dic->ctrl();
+ $this->tabs = $this->dic->tabs();
+ $this->user = $this->dic->user();
+ $this->navHistory = $this->dic['ilNavigationHistory'];
+ $this->error = $this->dic['ilErr'];
+
+ $this->lng->loadLanguageModule('copa');
+ $this->lng->loadLanguageModule('style');
+ $this->lng->loadLanguageModule('content');
+
+ if ($this->object instanceof \ilObjContentPage) {
+ $this->infoScreenEnabled = \ilContainer::_lookupContainerSetting(
+ $this->object->getId(),
+ \ilObjectServiceSettingsGUI::INFO_TAB_VISIBILITY,
+ true
+ );
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function afterSave(\ilObject $a_new_object)
+ {
+ \ilUtil::sendSuccess($this->lng->txt('object_added'), true);
+ $this->ctrl->redirect($this, 'edit');
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getType()
+ {
+ return self::OBJ_TYPE;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setTabs()
+ {
+ if ($this->checkPermissionBool('read')) {
+ $this->tabs->addTab(
+ self::UI_TAB_ID_CONTENT,
+ $this->lng->txt('content'),
+ $this->ctrl->getLinkTarget($this, self::UI_CMD_VIEW)
+ );
+ }
+
+ if ($this->infoScreenEnabled && ($this->checkPermissionBool('visible') || $this->checkPermissionBool('read'))) {
+ $this->tabs->addTab(
+ self::UI_TAB_ID_INFO,
+ $this->lng->txt('info_short'),
+ $this->ctrl->getLinkTargetByClass('ilinfoscreengui', 'showSummary')
+ );
+ }
+
+ if ($this->checkPermissionBool('write')) {
+ $this->tabs->addTab(
+ self::UI_TAB_ID_SETTINGS,
+ $this->lng->txt('settings'),
+ $this->ctrl->getLinkTarget($this, self::UI_CMD_EDIT)
+ );
+ }
+
+ if (\ilLearningProgressAccess::checkAccess($this->object->getRefId())) {
+ $this->tabs->addTab(
+ self::UI_TAB_ID_LP,
+ $this->lng->txt('learning_progress'),
+ $this->ctrl->getLinkTargetByClass('illearningprogressgui')
+ );
+ }
+
+ if ($this->checkPermissionBool('write')) {
+ $this->tabs->addTab(
+ self::UI_TAB_ID_EXPORT,
+ $this->lng->txt('export'),
+ $this->ctrl->getLinkTargetByClass('ilexportgui')
+ );
+ }
+
+ if ($this->checkPermissionBool('edit_permission')) {
+ $this->tabs->addTab(
+ self::UI_TAB_ID_PERMISSIONS,
+ $this->lng->txt('perm_settings'),
+ $this->ctrl->getLinkTargetByClass('ilpermissiongui', 'perm')
+ );
+ }
+ }
+
+ /**
+ * Sub tab configuration of the content area
+ */
+ protected function setContentSubTabs()
+ {
+ if ($this->checkPermissionBool('write')) {
+ $this->tabs->addSubTab(
+ self::UI_TAB_ID_CONTENT,
+ $this->lng->txt('view'),
+ $this->ctrl->getLinkTarget($this, self::UI_CMD_VIEW)
+ );
+
+ if (!$this->user->isAnonymous()) {
+ $this->lng->loadLanguageModule('cntr');
+ $this->tabs->addSubTab(
+ 'page_editor',
+ $this->lng->txt('cntr_text_media_editor'),
+ $this->ctrl->getLinkTargetByClass('ilContentPagePageGUI', 'edit')
+ );
+ }
+ }
+ }
+
+ /**
+ * Sub tab configuration of the settings area
+ * @param string $activeTab
+ */
+ protected function setSettingsSubTabs($activeTab)
+ {
+ if ($this->checkPermissionBool('write')) {
+ $this->tabs->addSubTab(
+ self::UI_TAB_ID_SETTINGS,
+ $this->lng->txt('settings'),
+ $this->ctrl->getLinkTarget($this, self::UI_CMD_EDIT)
+ );
+
+ if ($this->settings->get('custom_icons')) {
+ $this->tabs_gui->addSubTab(
+ self::UI_TAB_ID_ICON,
+ $this->lng->txt('icon_settings'),
+ $this->ctrl->getLinkTargetByClass('ilObjectCustomIconConfigurationGUI')
+ );
+ }
+
+ $this->tabs_gui->addSubTab(
+ self::UI_TAB_ID_STYLE,
+ $this->lng->txt('cont_style'),
+ $this->ctrl->getLinkTarget($this, 'editStyleProperties')
+ );
+
+ $this->tabs->setSubTabActive($activeTab);
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function setTitleAndDescription()
+ {
+ parent::setTitleAndDescription();
+
+ $icon = ilObject::_getIcon($this->object->getId(), 'big', $this->object->getType());
+ $this->tpl->setTitleIcon($icon, $this->lng->txt('obj_'.$this->object->getType()));
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function executeCommand()
+ {
+ $nextClass = $this->ctrl->getNextClass($this);
+ $cmd = $this->ctrl->getCmd(self::UI_CMD_VIEW);
+
+ $this->addToNavigationHistory();
+
+ if (strtolower($nextClass) !== 'ilobjstylesheetgui') {
+ $this->renderHeaderActions();
+ }
+
+ switch (strtolower($nextClass)) {
+ case 'ilobjstylesheetgui':
+ $this->checkPermission('write');
+
+ $this->setLocator();
+
+ $this->ctrl->setReturn($this, 'editStyleProperties');
+ $style_gui = new \ilObjStyleSheetGUI(
+ '',
+ $this->object->getStyleSheetId(),
+ false,
+ false
+ );
+ $style_gui->omitLocator();
+ if ($cmd == 'create' || $_GET['new_type'] == 'sty') {
+ $style_gui->setCreationMode(true);
+ }
+ $ret = $this->ctrl->forwardCommand($style_gui);
+
+ if ($cmd == 'save' || $cmd == 'copyStyle' || $cmd == 'importStyle') {
+ $styleId = $ret;
+ $this->object->setStyleSheetId($styleId);
+ $this->object->update();
+ $this->ctrl->redirectByClass('ilobjstylesheetgui', 'edit');
+ }
+ break;
+
+ case 'ilcontentpagepagegui':
+ if (!$this->checkPermissionBool('write') || $this->user->isAnonymous()) {
+ $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
+ }
+
+ $this->prepareOutput();
+
+ $this->tpl->setVariable('LOCATION_CONTENT_STYLESHEET', \ilObjStyleSheet::getContentStylePath($this->object->getStyleSheetId()));
+ $this->tpl->setCurrentBlock('SyntaxStyle');
+ $this->tpl->setVariable('LOCATION_SYNTAX_STYLESHEET', \ilObjStyleSheet::getSyntaxStylePath());
+ $this->tpl->parseCurrentBlock();
+
+ $forwarder = new \ilContentPagePageCommandForwarder($this->request, $this->ctrl, $this->tabs, $this->lng, $this->object);
+ $forwarder->forward();
+ break;
+
+ case 'ilinfoscreengui':
+ if (!$this->infoScreenEnabled) {
+ return;
+ }
+ $this->prepareOutput();
+
+ $this->infoScreenForward();
+ break;
+
+ case 'ilcommonactiondispatchergui':
+ $this->ctrl->forwardCommand(\ilCommonActionDispatcherGUI::getInstanceFromAjaxCall());
+ break;
+
+ case 'ilpermissiongui':
+ $this->checkPermission('edit_permission');
+
+ $this->prepareOutput();
+ $this->tabs->activateTab(self::UI_TAB_ID_PERMISSIONS);
+
+ $this->ctrl->forwardCommand(new \ilPermissionGUI($this));
+ break;
+
+ case 'illearningprogressgui':
+ if (!\ilLearningProgressAccess::checkAccess($this->object->getRefId())) {
+ $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
+ }
+
+ $this->prepareOutput();
+ $this->tabs->activateTab(self::UI_TAB_ID_LP);
+
+ $this->ctrl->forwardCommand(new \ilLearningProgressGUI(
+ \ilLearningProgressGUI::LP_CONTEXT_REPOSITORY,
+ $this->object->getRefId(),
+ isset($this->request->getQueryParams()['user_id']) && is_numeric($this->request->getQueryParams()['user_id']) ?
+ (int)$this->request->getQueryParams()['user_id'] :
+ $this->user->getId()
+ ));
+ break;
+
+ case 'ilexportgui':
+ $this->checkPermission('write');
+
+ $this->prepareOutput();
+ $this->tabs->activateTab(self::UI_TAB_ID_EXPORT);
+
+ $gui = new \ilExportGUI($this);
+ $gui->addFormat('xml');
+ $this->ctrl->forwardCommand($gui);
+ break;
+
+ case 'ilobjectcustomiconconfigurationgui':
+ if (!$this->checkPermissionBool('write') || !$this->settings->get('custom_icons')) {
+ $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
+ }
+
+ $this->prepareOutput();
+ $this->tabs->activateTab(self::UI_TAB_ID_SETTINGS);
+ $this->setSettingsSubTabs(self::UI_TAB_ID_ICON);
+
+ require_once 'Services/Object/Icon/classes/class.ilObjectCustomIconConfigurationGUI.php';
+ $gui = new \ilObjectCustomIconConfigurationGUI($this->dic, $this, $this->object);
+ $this->ctrl->forwardCommand($gui);
+ break;
+
+ case 'ilobjectcopygui':
+ $this->tpl->getStandardTemplate();
+
+ $gui = new \ilObjectCopyGUI($this);
+ $gui->setType(self::OBJ_TYPE);
+
+ $this->ctrl->forwardCommand($gui);
+ break;
+
+ default:
+ switch (true) {
+ case in_array(strtolower($cmd), array_map('strtolower', [self::UI_CMD_EDIT, self::UI_CMD_UPDATE])):
+ $this->setSettingsSubTabs(self::UI_TAB_ID_SETTINGS);
+ break;
+ }
+
+ if (in_array(strtolower($cmd), array_map('strtolower', ['addToDesk', 'removeFromDesk']))) {
+ $this->ctrl->setCmd($cmd . 'Object');
+ }
+
+ return parent::executeCommand();
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function addLocatorItems()
+ {
+ if ($this->object instanceof \ilObject) {
+ $this->locator->addItem(
+ $this->object->getTitle(),
+ $this->ctrl->getLinkTarget($this, self::UI_CMD_VIEW),
+ '',
+ $this->object->getRefId()
+ );
+ }
+ }
+
+ /**
+ *
+ */
+ public function addToNavigationHistory() {
+ if(!$this->getCreationMode()) {
+ if($this->checkPermissionBool('read')) {
+ $this->navHistory->addItem(
+ $this->object->getRefId(),
+ \ilLink::_getLink($this->object->getRefId(), $this->object->getType()),
+ $this->object->getType()
+ );
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ public function renderHeaderActions() {
+ if(!$this->getCreationMode()) {
+ if($this->checkPermissionBool('read')) {
+ $this->addHeaderAction();
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ public function infoScreen()
+ {
+ $this->ctrl->setCmd('showSummary');
+ $this->ctrl->setCmdClass('ilinfoscreengui');
+
+ $this->infoScreenForward();
+ }
+
+ /**
+ *
+ */
+ public function infoScreenForward()
+ {
+ if (!$this->infoScreenEnabled) {
+ return;
+ }
+
+ if (!$this->checkPermissionBool('visible') && !$this->checkPermissionBool('read')) {
+ $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
+ }
+
+ $this->tabs->activateTab(self::UI_TAB_ID_INFO);
+
+ $info = new \ilInfoScreenGUI($this);
+ $info->enableLearningProgress(true);
+ $info->enablePrivateNotes();
+ $info->addMetaDataSections($this->object->getId(), 0, $this->object->getType());
+
+ $this->ctrl->forwardCommand($info);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function initEditCustomForm(\ilPropertyFormGUI $a_form)
+ {
+ $sh = new ilFormSectionHeaderGUI();
+ $sh->setTitle($this->lng->txt('obj_features'));
+ $a_form->addItem($sh);
+
+ \ilObjectServiceSettingsGUI::initServiceSettingsForm(
+ $this->object->getId(),
+ $a_form,
+ array(
+ \ilObjectServiceSettingsGUI::INFO_TAB_VISIBILITY
+ )
+ );
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function getEditFormCustomValues(array &$a_values)
+ {
+ $a_values[\ilObjectServiceSettingsGUI::INFO_TAB_VISIBILITY] = $this->infoScreenEnabled;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function updateCustom(\ilPropertyFormGUI $a_form)
+ {
+ \ilObjectServiceSettingsGUI::updateServiceSettingsForm(
+ $this->object->getId(),
+ $a_form,
+ array(
+ \ilObjectServiceSettingsGUI::INFO_TAB_VISIBILITY
+ )
+ );
+ }
+
+ /**
+ * Deep link
+ * @param string $target
+ */
+ public static function _goto($target)
+ {
+ global $DIC;
+
+ $targetAttributes = explode('_', $target);
+ $refId = (int)$targetAttributes[0];
+
+ if ((int) $refId <= 0) {
+ $DIC['ilErr']->raiseError($DIC->language()->txt('msg_no_perm_read'), $DIC['ilErr']->FATAL);
+ }
+
+ if ($DIC->access()->checkAccess('read', '', $refId)) {
+ $DIC->ctrl()->setTargetScript('ilias.php');
+ $DIC->ctrl()->initBaseClass('ilRepositoryGUI');
+ $DIC->ctrl()->setParameterByClass(__CLASS__, 'ref_id', $refId);
+ $DIC->ctrl()->redirectByClass(array(
+ 'ilRepositoryGUI',
+ __CLASS__,
+ ), self::UI_CMD_VIEW);
+ } else if($DIC->access()->checkAccess('read', '', ROOT_FOLDER_ID)) {
+ \ilUtil::sendInfo(sprintf(
+ $DIC->language()->txt('msg_no_perm_read_item'), \ilObject::_lookupTitle(\ilObject::_lookupObjId($refId))
+ ), true);
+
+ $DIC->ctrl()->setTargetScript('ilias.php');
+ $DIC->ctrl()->initBaseClass('ilRepositoryGUI');
+ $DIC->ctrl()->setParameterByClass('ilRepositoryGUI', 'ref_id', ROOT_FOLDER_ID);
+ $DIC->ctrl()->redirectByClass('ilRepositoryGUI');
+ }
+
+ $DIC['ilErr']->raiseError($DIC->language()->txt('msg_no_perm_read'), $DIC['ilErr']->FATAL);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function addToDeskObject()
+ {
+ if ((int)$this->settings->get('disable_my_offers')) {
+ $this->ctrl->redirect($this, self::UI_CMD_VIEW);
+ }
+
+ \ilDesktopItemGUI::addToDesktop();
+ \ilUtil::sendSuccess($this->lng->txt('added_to_desktop'), true);
+ $this->ctrl->redirect($this, self::UI_CMD_VIEW);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function removeFromDeskObject()
+ {
+ if ((int)$this->settings->get('disable_my_offers')) {
+ $this->ctrl->redirect($this, self::UI_CMD_VIEW);
+ }
+
+ \ilDesktopItemGUI::removeFromDesktop();
+ \ilUtil::sendSuccess($this->lng->txt('removed_from_desktop'), true);
+ $this->ctrl->redirect($this, self::UI_CMD_VIEW);
+ }
+
+ protected function initStyleSheets()
+ {
+ $this->tpl->setVariable('LOCATION_CONTENT_STYLESHEET', \ilObjStyleSheet::getContentStylePath($this->object->getStyleSheetId()));
+ $this->tpl->setCurrentBlock('SyntaxStyle');
+ $this->tpl->setVariable('LOCATION_SYNTAX_STYLESHEET', \ilObjStyleSheet::getSyntaxStylePath());
+ $this->tpl->parseCurrentBlock();
+ }
+
+ /**
+ * @param string $ctrlLink A link which describes the target controller for all page object links/actions
+ * @return string
+ * @throws \ilException
+ */
+ public function getContent(string $ctrlLink = ''): string
+ {
+ if ($this->checkPermissionBool('read')) {
+ $this->object->trackProgress((int)$this->user->getId());
+
+ $this->initStyleSheets();
+
+ $forwarder = new \ilContentPagePageCommandForwarder(
+ $this->request, $this->ctrl, $this->tabs, $this->lng, $this->object
+ );
+ $forwarder->setPresentationMode(ilContentPagePageCommandForwarder::PRESENTATION_MODE_PRESENTATION);
+
+ return $forwarder->forward($ctrlLink);
+ }
+
+ return '';
+ }
+
+ /**
+ * Shows the content of the object
+ */
+ public function view()
+ {
+ $this->checkPermission('read');
+
+ $this->setContentSubTabs();
+
+ $this->tabs->activateTab(self::UI_TAB_ID_CONTENT);
+ $this->tabs->activateSubTab(self::UI_TAB_ID_CONTENT);
+
+ $this->tpl->setPermanentLink($this->object->getType(), $this->object->getRefId(), '', '_top');
+
+ $this->tpl->setContent($this->getContent());
+ }
+
+ /**
+ * @throws \ilObjectException
+ */
+ protected function editStyleProperties()
+ {
+ $this->checkPermission('write');
+
+ $this->tabs->activateTab(self::UI_TAB_ID_SETTINGS);
+ $this->setSettingsSubTabs(self::UI_TAB_ID_STYLE);
+
+ $form = $this->buildStylePropertiesForm();
+ $this->tpl->setContent($form->getHTML());
+ }
+
+ /**
+ * @return \ilPropertyFormGUI
+ */
+ protected function buildStylePropertiesForm(): \ilPropertyFormGUI
+ {
+ $form = new \ilPropertyFormGUI();
+
+ $fixedStyle = $this->settings->get('fixed_content_style_id');
+ $defaultStyle = $this->settings->get('default_content_style_id');
+ $styleId = $this->object->getStyleSheetId();
+
+ if ($fixedStyle > 0) {
+ $st = new ilNonEditableValueGUI($this->lng->txt("cont_current_style"));
+ $st->setValue(
+ \ilObject::_lookupTitle($fixedStyle) . " (" . $this->lng->txt("global_fixed") . ")"
+ );
+ $form->addItem($st);
+ } else {
+ $st_styles = \ilObjStyleSheet::_getStandardStyles(
+ true,
+ false,
+ (int)$_GET["ref_id"]
+ );
+
+ if ($defaultStyle > 0) {
+ $st_styles[0] = \ilObject::_lookupTitle($defaultStyle) . ' (' . $this->lng->txt('default') . ')';
+ } else {
+ $st_styles[0] = $this->lng->txt('default');
+ }
+ ksort($st_styles);
+
+ if ($styleId > 0) {
+ if (!\ilObjStyleSheet::_lookupStandard($styleId)) {
+ $st = new \ilNonEditableValueGUI($this->lng->txt('cont_current_style'));
+ $st->setValue(ilObject::_lookupTitle($styleId));
+ $form->addItem($st);
+
+ $form->addCommandButton('editStyle', $this->lng->txt('cont_edit_style'));
+ $form->addCommandButton('deleteStyle', $this->lng->txt('cont_delete_style'));
+ }
+ }
+
+ if ($styleId <= 0 || \ilObjStyleSheet::_lookupStandard($styleId)) {
+ $style_sel = new \ilSelectInputGUI($this->lng->txt('cont_current_style'), 'style_id');
+ $style_sel->setOptions($st_styles);
+ $style_sel->setValue($styleId);
+ $form->addItem($style_sel);
+ $form->addCommandButton('saveStyleSettings', $this->lng->txt('save'));
+ $form->addCommandButton('createStyle', $this->lng->txt('sty_create_ind_style'));
+ }
+ }
+
+ $form->setTitle($this->lng->txt("cont_style"));
+ $form->setFormAction($this->ctrl->getFormAction($this));
+
+ return $form;
+ }
+
+ /**
+ * Create Style
+ */
+ protected function createStyle()
+ {
+ $this->ctrl->redirectByClass('ilobjstylesheetgui', 'create');
+ }
+
+ /**
+ * Edit Style
+ */
+ protected function editStyle()
+ {
+ $this->ctrl->redirectByClass('ilobjstylesheetgui', 'edit');
+ }
+
+ /**
+ * Delete Style
+ */
+ protected function deleteStyle()
+ {
+ $this->ctrl->redirectByClass('ilobjstylesheetgui', 'delete');
+ }
+
+ /**
+ * Save style settings
+ */
+ protected function saveStyleSettings()
+ {
+ $this->checkPermission('write');
+
+ if (
+ $this->settings->get('fixed_content_style_id') <= 0 &&
+ (\ilObjStyleSheet::_lookupStandard($this->object->getStyleSheetId()) || $this->object->getStyleSheetId() == 0))
+ {
+ $this->object->setStyleSheetId(ilUtil::stripSlashes($_POST['style_id']));
+ $this->object->update();
+ ilUtil::sendSuccess($this->lng->txt('msg_obj_modified'), true);
+ }
+
+ $this->ctrl->redirect($this, 'editStyleProperties');
+ }
+}
\ No newline at end of file
diff --git a/Modules/ContentPage/classes/class.ilObjContentPageListGUI.php b/Modules/ContentPage/classes/class.ilObjContentPageListGUI.php
new file mode 100644
index 000000000000..a6e1ecba996e
--- /dev/null
+++ b/Modules/ContentPage/classes/class.ilObjContentPageListGUI.php
@@ -0,0 +1,43 @@
+static_link_enabled = true;
+ $this->delete_enabled = true;
+ $this->cut_enabled = true;
+ $this->copy_enabled = true;
+ $this->subscribe_enabled = true;
+ $this->link_enabled = true;
+ $this->info_screen_enabled = true;
+ $this->type = self::OBJ_TYPE;
+ $this->gui_class_name = 'ilObjContentPageGUI';
+
+ $this->commands = ilObjContentPageAccess::_getCommands();
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getInfoScreenStatus()
+ {
+ if (\ilContainer::_lookupContainerSetting(
+ $this->obj_id,
+ \ilObjectServiceSettingsGUI::INFO_TAB_VISIBILITY,
+ true
+ ))
+ {
+ return $this->info_screen_enabled;
+ }
+
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/Modules/ContentPage/interfaces/interface.ilContentPageObjectConstants.php b/Modules/ContentPage/interfaces/interface.ilContentPageObjectConstants.php
new file mode 100644
index 000000000000..977d310ba019
--- /dev/null
+++ b/Modules/ContentPage/interfaces/interface.ilContentPageObjectConstants.php
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Modules/Course/classes/Objectives/class.ilLOEditorGUI.php b/Modules/Course/classes/Objectives/class.ilLOEditorGUI.php
index cf8d34b575dd..cfea884868b8 100644
--- a/Modules/Course/classes/Objectives/class.ilLOEditorGUI.php
+++ b/Modules/Course/classes/Objectives/class.ilLOEditorGUI.php
@@ -28,6 +28,12 @@ class ilLOEditorGUI
const SETTINGS_TEMPLATE_QT = 'il_astpl_loc_qualified';
+ /**
+ * @var \ilLogger
+ */
+ private $logger = null;
+
+
private $parent_obj;
private $settings = NULL;
private $lng = NULL;
@@ -44,8 +50,10 @@ public function __construct($a_parent_obj)
{
$this->parent_obj = $a_parent_obj;
$this->settings = ilLOSettings::getInstanceByObjId($this->getParentObject()->getId());
+
$this->lng = $GLOBALS['DIC']['lng'];
$this->ctrl = $GLOBALS['DIC']['ilCtrl'];
+ $this->logger = $GLOBALS['DIC']->logger()->crs();
}
/**
@@ -968,7 +976,12 @@ protected function saveMultiTestAssignment()
$this->applySettingsTemplate($tst);
$tst->saveToDb();
}
-
+
+ // deassign as objective material
+ if($tst instanceof ilObjTest)
+ {
+ $this->updateMaterialAssignments($tst);
+ }
$this->updateStartObjects();
ilUtil::sendSuccess($this->lng->txt('settings_saved'));
@@ -981,6 +994,26 @@ protected function saveMultiTestAssignment()
$this->testAssignment($form);
}
+ /**
+ * @param \ilObjTest $test
+ */
+ protected function updateMaterialAssignments(ilObjTest $test)
+ {
+ include_once './Modules/Course/classes/class.ilCourseObjective.php';
+ foreach(ilCourseObjective::_getObjectiveIds($this->getParentObject()->getId()) as $objective_id)
+ {
+ include_once './Modules/Course/classes/class.ilCourseObjectiveMaterials.php';
+ $materials = new ilCourseObjectiveMaterials($objective_id);
+ foreach($materials->getMaterials() as $key => $material)
+ {
+ if($material['ref_id'] == $test->getRefId())
+ {
+ $materials->delete($material['lm_ass_id']);
+ }
+ }
+ }
+ }
+
/**
* Save Test
*/
@@ -1043,7 +1076,12 @@ protected function saveTest()
$this->applySettingsTemplate($tst);
$tst->saveToDb();
}
-
+
+ // deassign as objective material
+ if($tst instanceof ilObjTest)
+ {
+ $this->updateMaterialAssignments($tst);
+ }
$this->updateStartObjects();
ilUtil::sendSuccess($this->lng->txt('settings_saved'));
diff --git a/Modules/Course/classes/Objectives/class.ilLOMemberTestResultTableGUI.php b/Modules/Course/classes/Objectives/class.ilLOMemberTestResultTableGUI.php
index c84004b22b77..daa294933b99 100644
--- a/Modules/Course/classes/Objectives/class.ilLOMemberTestResultTableGUI.php
+++ b/Modules/Course/classes/Objectives/class.ilLOMemberTestResultTableGUI.php
@@ -120,7 +120,7 @@ public function fillRow($set)
$this->tpl->setVariable('VAL_TITLE', $set['title']);
if($this->getSettings()->worksWithInitialTest())
{
- if($set['tries_it'] or $set['res_it'])
+ if($set['has_result_it'])
{
$this->tpl->setCurrentBlock('it_has_result');
$this->tpl->setVariable('IT_LINK',$set['link_it']);
@@ -134,10 +134,10 @@ public function fillRow($set)
}
- if($set['tries_qt'] or $set['res_qt'])
+ if($set['has_result_qt'])
{
$this->tpl->setCurrentBlock('qt_has_result');
- $this->tpl->setVariable('QT_LINK',$set['link_qt']);
+ $this->tpl->setVariable('QT_LINK',$set['link_qt']);
$this->tpl->setVariable('QT_VAL',$set['res_qt'].'%');
$this->tpl->parseCurrentBlock();
}
@@ -177,6 +177,7 @@ public function parse()
$objective['tries_it'] = $results_it['tries'];
$objective['res_it'] = $results_it['result_perc'];
$objective['link_it'] = $this->createTestResultLink(ilLOSettings::TYPE_TEST_INITIAL, $objective_id);
+ $objective['has_result_it'] = (bool) $results_it['has_result'];
}
$results_qt = ilLOUserResults::lookupResult(
$this->getParentContainer()->getId(),
@@ -187,7 +188,8 @@ public function parse()
$objective['tries_qt'] = $results_qt['tries'];
$objective['res_qt'] = $results_qt['result_perc'];
$objective['link_qt'] = $this->createTestResultLink(ilLOSettings::TYPE_TEST_QUALIFIED, $objective_id);
-
+ $objective['has_result_qt'] = (bool) $results_qt['has_result'];
+
$tbl_data[] = $objective;
}
diff --git a/Modules/Course/classes/Objectives/class.ilLOUserResults.php b/Modules/Course/classes/Objectives/class.ilLOUserResults.php
index 8a1b4301897b..488872eeb5e5 100644
--- a/Modules/Course/classes/Objectives/class.ilLOUserResults.php
+++ b/Modules/Course/classes/Objectives/class.ilLOUserResults.php
@@ -53,7 +53,8 @@ public static function lookupResult($a_course_obj_id, $a_user_id, $a_objective_i
'result_perc' => 0,
'limit_perc' => 0,
'tries' => 0,
- 'is_final' => 0
+ 'is_final' => 0,
+ 'has_result' => false
);
while($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT))
{
@@ -62,6 +63,7 @@ public static function lookupResult($a_course_obj_id, $a_user_id, $a_objective_i
$ur['limit_perc'] = $row->limit_perc;
$ur['tries'] = $row->tries;
$ur['is_final'] = $row->is_final;
+ $ur['has_result'] = true;
}
return $ur;
}
diff --git a/Modules/Course/classes/class.ilCourseParticipantsGroupsTableGUI.php b/Modules/Course/classes/class.ilCourseParticipantsGroupsTableGUI.php
index 5aa67923a822..1be1a8999e73 100644
--- a/Modules/Course/classes/class.ilCourseParticipantsGroupsTableGUI.php
+++ b/Modules/Course/classes/class.ilCourseParticipantsGroupsTableGUI.php
@@ -34,7 +34,7 @@ function __construct($a_parent_obj, $a_parent_cmd, $ref_id)
$this->ref_id = $ref_id;
$this->obj_id = $ilObjDataCache->lookupObjId($this->ref_id);
- $this->setId("tblcrsprtgrp");
+ $this->setId('tblcrsprtgrp_'.$ref_id);
parent::__construct($a_parent_obj, $a_parent_cmd);
// $this->setTitle($lng->txt("tr_summary"));
diff --git a/Modules/Course/classes/class.ilObjCourseAccess.php b/Modules/Course/classes/class.ilObjCourseAccess.php
index 6afee2804d0a..8b57c9c100a8 100644
--- a/Modules/Course/classes/class.ilObjCourseAccess.php
+++ b/Modules/Course/classes/class.ilObjCourseAccess.php
@@ -236,8 +236,8 @@ static function _getCommands()
include_once ('Services/WebDAV/classes/class.ilDAVActivationChecker.php');
if (ilDAVActivationChecker::_isActive())
{
- include_once './Services/WebDAV/classes/class.ilDAVUtils.php';
- if(ilDAVUtils::getInstance()->isLocalPasswordInstructionRequired())
+ include_once './Services/WebDAV/classes/class.ilWebDAVUtil.php';
+ if(ilWebDAVUtil::getInstance()->isLocalPasswordInstructionRequired())
{
$commands[] = array('permission' => 'read', 'cmd' => 'showPasswordInstruction', 'lang_var' => 'mount_webfolder', 'enable_anonymous' => 'false');
}
diff --git a/Modules/Course/classes/class.ilObjCourseGUI.php b/Modules/Course/classes/class.ilObjCourseGUI.php
index f2ac3c7bf756..e9fded4c5ae0 100755
--- a/Modules/Course/classes/class.ilObjCourseGUI.php
+++ b/Modules/Course/classes/class.ilObjCourseGUI.php
@@ -24,7 +24,7 @@
* @ilCtrl_Calls ilObjCourseGUI: ilLOPageGUI, ilObjectMetaDataGUI, ilNewsTimelineGUI, ilContainerNewsSettingsGUI
* @ilCtrl_Calls ilObjCourseGUI: ilCourseMembershipGUI, ilPropertyFormGUI, ilContainerSkillGUI, ilCalendarPresentationGUI
* @ilCtrl_Calls ilObjCourseGUI: ilMemberExportSettingsGUI
- * @ilCtrl_Calls ilObjCourseGUI: ilLTIProviderObjectSettingGUI
+ * @ilCtrl_Calls ilObjCourseGUI: ilLTIProviderObjectSettingGUI, ilObjectCustomIconConfigurationGUI
*
* @extends ilContainerGUI
*/
@@ -1189,6 +1189,7 @@ protected function initEditForm()
$opt = new ilRadioOption($this->lng->txt('crs_subscription_options_password'),IL_CRS_SUBSCRIPTION_PASSWORD);
$pass = new ilTextInputGUI($this->lng->txt("password"),'subscription_password');
+ $pass->setRequired(true);
$pass->setInfo($this->lng->txt('crs_reg_password_info'));
$pass->setSubmitFormOnEnter(true);
$pass->setSize(32);
@@ -1517,43 +1518,6 @@ protected function getEditFormValues()
// values are done in initEditForm()
}
- /**
- * edit container icons
- */
- function editCourseIconsObject($a_form = null)
- {
- global $DIC;
-
- $tpl = $DIC['tpl'];
-
- $this->checkPermission('write');
-
- $this->setSubTabs("properties");
- $this->tabs_gui->setTabActive('settings');
- $this->tabs_gui->activateSubTab('icon_settings');
-
- if(!$a_form)
- {
- $a_form = $this->initCourseIconsForm();
- }
-
- $tpl->setContent($a_form->getHTML());
- }
-
- function initCourseIconsForm()
- {
- include_once "Services/Form/classes/class.ilPropertyFormGUI.php";
- $form = new ilPropertyFormGUI();
- $form->setFormAction($this->ctrl->getFormAction($this));
-
- $this->showCustomIconsEditing(1, $form);
-
- // $form->setTitle($this->lng->txt('edit_grouping'));
- $form->addCommandButton('updateCourseIcons', $this->lng->txt('save'));
-
- return $form;
- }
-
function sendFileObject()
{
include_once 'Modules/Course/classes/class.ilCourseFile.php';
@@ -1561,39 +1525,6 @@ function sendFileObject()
ilUtil::deliverFile($file->getAbsolutePath(),$file->getFileName(),$file->getFileType());
return true;
}
-
- /**
- * update container icons
- */
- function updateCourseIconsObject()
- {
- global $DIC;
-
- $ilSetting = $DIC['ilSetting'];
-
- $this->checkPermission('write');
-
- $form = $this->initCourseIconsForm();
- if($form->checkInput())
- {
- //save custom icons
- if ($ilSetting->get("custom_icons"))
- {
- if($_POST["cont_icon_delete"])
- {
- $this->object->removeCustomIcon();
- }
- $this->object->saveIcons($_FILES["cont_icon"]['tmp_name']);
- }
-
- ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"),true);
- $this->ctrl->redirect($this,"editCourseIcons");
- }
-
- $form->setValuesByPost();
- $this->editCourseIconsObject($form);
- }
-
/**
* set sub tabs
@@ -1639,12 +1570,12 @@ function setSubTabs($a_tab)
);
}
- // custom icon
- if ($this->ilias->getSetting("custom_icons"))
- {
- $this->tabs_gui->addSubTabTarget("icon_settings",
- $this->ctrl->getLinkTarget($this,'editCourseIcons'),
- "editCourseIcons", get_class($this));
+ if ($this->ilias->getSetting('custom_icons')) {
+ $this->tabs_gui->addSubTabTarget(
+ 'icon_settings',
+ $this->ctrl->getLinkTargetByClass('ilObjectCustomIconConfigurationGUI'),
+ 'editCourseIcons', get_class($this)
+ );
}
// map settings
@@ -1712,39 +1643,6 @@ function showPossibleSubObjects()
parent::showPossibleSubObjects();
}
- /**
- * remove small icon
- *
- * @access public
- */
- function removeSmallIconObject()
- {
- $this->object->removeSmallIcon();
- $this->ctrl->redirect($this,'editCourseIcons');
- }
-
- /**
- * remove big icon
- *
- * @access public
- */
- function removeBigIconObject()
- {
- $this->object->removeBigIcon();
- $this->ctrl->redirect($this,'editCourseIcons');
- }
-
-
- /**
- * remove small icon
- *
- * @access public
- */
- function removeTinyIconObject()
- {
- $this->object->removeTinyIcon();
- $this->ctrl->redirect($this,'editCourseIcons');
- }
/**
* save object
@@ -2106,15 +2004,15 @@ function getTabs()
{
// default activation
$this->tabs_gui->activateTab('view_content');
- if ($this->object->getNewsTimeline())
+ if ($this->object->isNewsTimelineEffective())
{
- if (!$this->object->getNewsTimelineLandingPage())
+ if (!$this->object->isNewsTimelineLandingPageEffective())
{
$this->addContentTab();
}
$this->tabs_gui->addTab("news_timeline", $lng->txt("cont_news_timeline_tab"),
$this->ctrl->getLinkTargetByClass("ilnewstimelinegui", "show"));
- if ($this->object->getNewsTimelineLandingPage())
+ if ($this->object->isNewsTimelineLandingPageEffective())
{
$this->addContentTab();
}
@@ -2686,6 +2584,20 @@ function executeCommand()
$this->ctrl->forwardCommand($gui);
break;
+ case 'ilobjectcustomiconconfigurationgui':
+ if (!$this->checkPermissionBool('write') || !$this->settings->get('custom_icons')) {
+ $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
+ }
+
+ $this->setSubTabs('properties');
+ $this->tabs_gui->activateTab('settings');
+ $this->tabs_gui->activateSubTab('icon_settings');
+
+ require_once 'Services/Object/Icon/classes/class.ilObjectCustomIconConfigurationGUI.php';
+ $gui = new \ilObjectCustomIconConfigurationGUI($GLOBALS['DIC'], $this, $this->object);
+ $this->ctrl->forwardCommand($gui);
+ break;
+
default:
/* if(!$this->creation_mode)
{
@@ -2765,7 +2677,7 @@ function executeCommand()
}
// if news timeline is landing page, redirect if necessary
- if ($cmd == "" && $this->object->getUseNews() && $this->object->getNewsTimelineLandingPage())
+ if ($cmd == "" && $this->object->isNewsTimelineLandingPageEffective())
{
$this->ctrl->redirectbyclass("ilnewstimelinegui");
}
diff --git a/Modules/Course/classes/class.ilObjCourseGrouping.php b/Modules/Course/classes/class.ilObjCourseGrouping.php
index 194f6a92e7d8..d5690be03964 100644
--- a/Modules/Course/classes/class.ilObjCourseGrouping.php
+++ b/Modules/Course/classes/class.ilObjCourseGrouping.php
@@ -602,7 +602,7 @@ public static function _checkGroupingDependencies(&$container_obj, $a_user_id =
if(!$assigned_message)
{
self::$assignedObjects[] = $condition['target_obj_id'];
- $assigned_message = $lng->txt('crs_grp_already_assigned');
+ $assigned_message = $lng->txt('grp_grp_already_assigned');
}
}
diff --git a/Modules/Exercise/classes/class.ilExAssignmentGUI.php b/Modules/Exercise/classes/class.ilExAssignmentGUI.php
index d4d6f2f7a10e..3c712edbfadb 100644
--- a/Modules/Exercise/classes/class.ilExAssignmentGUI.php
+++ b/Modules/Exercise/classes/class.ilExAssignmentGUI.php
@@ -367,6 +367,11 @@ protected function addSubmission(ilInfoScreenGUI $a_info, ilExAssignment $a_ass)
}
}
+ if ($this->exc->getShowSubmissions())
+ {
+ $this->addPublicSubmissions($a_info, $a_ass);
+ }
+
include_once "Modules/Exercise/classes/class.ilExPeerReviewGUI.php";
ilExPeerReviewGUI::getOverviewContent($a_info, $submission);
@@ -382,10 +387,6 @@ protected function addSubmission(ilInfoScreenGUI $a_info, ilExAssignment $a_ass)
$this->addSubmissionFeedback($a_info, $a_ass, $submission->getFeedbackId(), $show_global_feedback);
- if ($this->exc->getShowSubmissions())
- {
- $this->addPublicSubmissions($a_info, $a_ass);
- }
}
protected function addSubmissionFeedback(ilInfoScreenGUI $a_info, ilExAssignment $a_ass, $a_feedback_id, $a_show_global_feedback)
diff --git a/Modules/File/classes/class.ilFileLP.php b/Modules/File/classes/class.ilFileLP.php
index 49f701f014f1..a2366025534b 100644
--- a/Modules/File/classes/class.ilFileLP.php
+++ b/Modules/File/classes/class.ilFileLP.php
@@ -14,7 +14,7 @@ public static function getDefaultModes($a_lp_active)
{
return array(
ilLPObjSettings::LP_MODE_DEACTIVATED,
- ilLPObjSettings::LP_MODE_DOWNLOADED
+ ilLPObjSettings::LP_MODE_CONTENT_VISITED
);
}
@@ -27,7 +27,7 @@ public function getValidModes()
{
return array(
ilLPObjSettings::LP_MODE_DEACTIVATED,
- ilLPObjSettings::LP_MODE_DOWNLOADED
+ ilLPObjSettings::LP_MODE_CONTENT_VISITED
);
}
}
\ No newline at end of file
diff --git a/Modules/File/classes/class.ilObjFile.php b/Modules/File/classes/class.ilObjFile.php
index 736784085181..471ba2961a28 100755
--- a/Modules/File/classes/class.ilObjFile.php
+++ b/Modules/File/classes/class.ilObjFile.php
@@ -705,7 +705,7 @@ public function sendFile($a_hist_entry_id = null) {
$ilFileDelivery = new ilFileDelivery($file);
$ilFileDelivery->setDisposition($this->isInline() ? ilFileDelivery::DISP_INLINE : ilFileDelivery::DISP_ATTACHMENT);
$ilFileDelivery->setMimeType($this->guessFileType($file));
- $ilFileDelivery->setConvertFileNameToAsci(true);
+ $ilFileDelivery->setConvertFileNameToAsci((bool)!$ilClientIniFile->readVariable('file_access', 'disable_ascii'));
// also returning the 'real' filename if a history file is delivered
if ($ilClientIniFile->readVariable('file_access', 'download_with_uploaded_filename')
diff --git a/Modules/Folder/classes/class.ilObjFolderAccess.php b/Modules/Folder/classes/class.ilObjFolderAccess.php
index 075ca48c7c3b..f2ae8d09b312 100644
--- a/Modules/Folder/classes/class.ilObjFolderAccess.php
+++ b/Modules/Folder/classes/class.ilObjFolderAccess.php
@@ -64,8 +64,8 @@ static function _getCommands()
include_once ('Services/WebDAV/classes/class.ilDAVActivationChecker.php');
if (ilDAVActivationChecker::_isActive())
{
- include_once './Services/WebDAV/classes/class.ilDAVUtils.php';
- if(ilDAVUtils::getInstance()->isLocalPasswordInstructionRequired())
+ include_once './Services/WebDAV/classes/class.ilWebDAVUtil.php';
+ if(ilWebDAVUtil::getInstance()->isLocalPasswordInstructionRequired())
{
$commands[] = array('permission' => 'read', 'cmd' => 'showPasswordInstruction', 'lang_var' => 'mount_webfolder', 'enable_anonymous' => 'false');
}
diff --git a/Modules/Folder/classes/class.ilObjFolderGUI.php b/Modules/Folder/classes/class.ilObjFolderGUI.php
index 4babf6d22100..fa293c250123 100755
--- a/Modules/Folder/classes/class.ilObjFolderGUI.php
+++ b/Modules/Folder/classes/class.ilObjFolderGUI.php
@@ -13,7 +13,7 @@
* @ilCtrl_Calls ilObjFolderGUI: ilInfoScreenGUI, ilContainerPageGUI, ilColumnGUI
* @ilCtrl_Calls ilObjFolderGUI: ilObjectCopyGUI, ilObjStyleSheetGUI
* @ilCtrl_Calls ilObjFolderGUI: ilExportGUI, ilCommonActionDispatcherGUI, ilDidacticTemplateGUI
-* @ilCtrl_Calls ilObjFolderGUI: ilBackgroundTaskHub
+* @ilCtrl_Calls ilObjFolderGUI: ilBackgroundTaskHub, ilObjectCustomIconConfigurationGUI
*
* @extends ilObjectGUI
*/
@@ -113,6 +113,22 @@ function executeCommand()
$ret =& $this->ctrl->forwardCommand($perm_gui);
break;
+ case 'ilobjectcustomiconconfigurationgui':
+ if (!$this->checkPermissionBool('write') || !$this->settings->get('custom_icons')) {
+ $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
+ }
+
+ $this->prepareOutput();
+
+ $this->setSubTabs('settings');
+ $this->tabs_gui->activateTab('settings');
+ $this->tabs_gui->activateSubTab('icons');
+
+ require_once 'Services/Object/Icon/classes/class.ilObjectCustomIconConfigurationGUI.php';
+ $gui = new \ilObjectCustomIconConfigurationGUI($GLOBALS['DIC'], $this, $this->object);
+ $this->ctrl->forwardCommand($gui);
+ break;
+
case 'ilcoursecontentgui':
$this->prepareOutput();
include_once './Modules/Course/classes/class.ilCourseContentGUI.php';
@@ -562,92 +578,17 @@ function setSubTabs($a_tab)
$ilTabs->addSubTab("settings",
$lng->txt("fold_settings"),
$this->ctrl->getLinkTarget($this,'edit'));
-
- // custom icon
- if ($this->ilias->getSetting("custom_icons"))
- {
- $ilTabs->addSubTab("icons",
- $lng->txt("icon_settings"),
- $this->ctrl->getLinkTarget($this,'editIcons'));
- }
-
- $ilTabs->activateSubTab($a_tab);
- $ilTabs->activateTab("settings");
- }
-
-
- ////
- //// Icons
- ////
-
- /**
- * Edit folder icons
- */
- function editIconsObject($a_form = null)
- {
- $tpl = $this->tpl;
- $this->checkPermission('write');
-
- $this->tabs_gui->setTabActive('settings');
-
- if(!$a_form)
- {
- $a_form = $this->initIconsForm();
- }
-
- $tpl->setContent($a_form->getHTML());
- }
-
- function initIconsForm()
- {
- $this->setSubTabs("icons");
-
- include_once "Services/Form/classes/class.ilPropertyFormGUI.php";
- $form = new ilPropertyFormGUI();
- $form->setFormAction($this->ctrl->getFormAction($this));
-
- $this->showCustomIconsEditing(1, $form);
-
- // $form->setTitle($this->lng->txt('edit_grouping'));
- $form->addCommandButton('updateIcons', $this->lng->txt('save'));
-
- return $form;
- }
-
- /**
- * update container icons
- */
- function updateIconsObject()
- {
- $ilSetting = $this->settings;
-
- $this->checkPermission('write');
-
- $form = $this->initIconsForm();
- if($form->checkInput())
- {
- //save custom icons
- if ($ilSetting->get("custom_icons"))
- {
- if($_POST["cont_icon_delete"])
- {
- $this->object->removeCustomIcon();
- }
- $this->object->saveIcons($_FILES["cont_icon"]['tmp_name']);
- }
- if ($_FILES["cont_icon"]['tmp_name'] || $_POST["cont_icon_delete"])
- {
- ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"),true);
- }
- $this->ctrl->redirect($this,"editIcons");
+ if ($this->ilias->getSetting('custom_icons')) {
+ $ilTabs->addSubTab(
+ 'icons',
+ $lng->txt('icon_settings'),
+ $this->ctrl->getLinkTargetByClass('ilobjectcustomiconconfigurationgui')
+ );
}
- $form->setValuesByPost();
- $this->editIconsObject($form);
+ $ilTabs->activateSubTab($a_tab);
+ $ilTabs->activateTab("settings");
}
-
-
-
} // END class.ilObjFolderGUI
?>
diff --git a/Modules/Folder/classes/class.ilObjFolderListGUI.php b/Modules/Folder/classes/class.ilObjFolderListGUI.php
index 3c9143f214af..e8947f15cffc 100644
--- a/Modules/Folder/classes/class.ilObjFolderListGUI.php
+++ b/Modules/Folder/classes/class.ilObjFolderListGUI.php
@@ -89,15 +89,15 @@ function getCommandLink($a_cmd)
require_once ('Services/WebDAV/classes/class.ilDAVActivationChecker.php');
if (ilDAVActivationChecker::_isActive())
{
- require_once ('Services/WebDAV/classes/class.ilDAVServer.php');
- $davServer = ilDAVServer::getInstance();
+ require_once ('Services/WebDAV/classes/class.ilWebDAVUtil.php');
+ $dav_util = ilWebDAVUtil::getInstance();
// XXX: The following is a very dirty, ugly trick.
// To mount URI needs to be put into two attributes:
// href and folder. This hack returns both attributes
// like this: http://...mount_uri..." folder="http://...folder_uri...
- $cmd_link = $davServer->getMountURI($this->ref_id, $this->title, $this->parent).
- '" folder="'.$davServer->getFolderURI($this->ref_id, $this->title, $this->parent);
+ $cmd_link = $dav_util->getMountURI($this->ref_id, $this->title, $this->parent).
+ '" folder="'.$dav_util->getFolderURI($this->ref_id, $this->title, $this->parent);
break;
} // Fall through, when plugin is inactive.
default :
diff --git a/Modules/Group/classes/class.ilObjGroupAccess.php b/Modules/Group/classes/class.ilObjGroupAccess.php
index 92f96b63256a..ceeeda570ed2 100644
--- a/Modules/Group/classes/class.ilObjGroupAccess.php
+++ b/Modules/Group/classes/class.ilObjGroupAccess.php
@@ -158,8 +158,8 @@ static function _getCommands()
include_once ('Services/WebDAV/classes/class.ilDAVActivationChecker.php');
if (ilDAVActivationChecker::_isActive())
{
- include_once './Services/WebDAV/classes/class.ilDAVUtils.php';
- if(ilDAVUtils::getInstance()->isLocalPasswordInstructionRequired())
+ include_once './Services/WebDAV/classes/class.ilWebDAVUtil.php';
+ if(ilWebDAVUtil::getInstance()->isLocalPasswordInstructionRequired())
{
$commands[] = array('permission' => 'read', 'cmd' => 'showPasswordInstruction', 'lang_var' => 'mount_webfolder', 'enable_anonymous' => 'false');
}
diff --git a/Modules/Group/classes/class.ilObjGroupGUI.php b/Modules/Group/classes/class.ilObjGroupGUI.php
index 81930f23a40d..805e6ef9162c 100755
--- a/Modules/Group/classes/class.ilObjGroupGUI.php
+++ b/Modules/Group/classes/class.ilObjGroupGUI.php
@@ -20,7 +20,7 @@
* @ilCtrl_Calls ilObjGroupGUI: ilCommonActionDispatcherGUI, ilObjectServiceSettingsGUI, ilSessionOverviewGUI
* @ilCtrl_Calls ilObjGroupGUI: ilGroupMembershipGUI, ilBadgeManagementGUI, ilMailMemberSearchGUI, ilNewsTimelineGUI, ilContainerNewsSettingsGUI
* @ilCtrl_Calls ilObjGroupGUI: ilContainerSkillGUI, ilCalendarPresentationGUI
-* @ilCtrl_Calls ilObjGroupGUI: ilLTIProviderObjectSettingGUI
+* @ilCtrl_Calls ilObjGroupGUI: ilLTIProviderObjectSettingGUI, ilObjectCustomIconConfigurationGUI
*
*
*
@@ -73,7 +73,7 @@ function executeCommand()
}
// if news timeline is landing page, redirect if necessary
- if ($next_class == "" && $cmd == "" && $this->object->getUseNews() && $this->object->getNewsTimelineLandingPage()
+ if ($next_class == "" && $cmd == "" && $this->object->isNewsTimelineLandingPageEffective()
&& $ilAccess->checkAccess("read", "", $_GET["ref_id"]))
{
$this->ctrl->redirectbyclass("ilnewstimelinegui");
@@ -81,6 +81,20 @@ function executeCommand()
switch($next_class)
{
+ case 'ilobjectcustomiconconfigurationgui':
+ if (!$this->checkPermissionBool('write') || !$this->settings->get('custom_icons')) {
+ $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->MESSAGE);
+ }
+
+ $this->setSubTabs('settings');
+ $this->tabs_gui->activateTab('settings');
+ $this->tabs_gui->activateSubTab('grp_icon_settings');
+
+ require_once 'Services/Object/Icon/classes/class.ilObjectCustomIconConfigurationGUI.php';
+ $gui = new \ilObjectCustomIconConfigurationGUI($GLOBALS['DIC'], $this, $this->object);
+ $this->ctrl->forwardCommand($gui);
+ break;
+
case 'illtiproviderobjectsettinggui':
$this->setSubTabs('properties');
$this->tabs_gui->activateTab('settings');
@@ -691,78 +705,7 @@ public function updateObject()
return true;
}
}
-
- /**
- * edit container icons
- */
- public function editGroupIconsObject($a_form = null)
- {
- global $DIC;
-
- $tpl = $DIC['tpl'];
-
- $this->checkPermission('write');
-
- $this->setSubTabs("settings");
- $this->tabs_gui->setTabActive('settings');
- $this->tabs_gui->setSubTabActive('grp_icon_settings');
-
- if(!$a_form)
- {
- $a_form = $this->initGroupIconsForm();
- }
-
- $tpl->setContent($a_form->getHTML());
- }
-
- function initGroupIconsForm()
- {
- include_once "Services/Form/classes/class.ilPropertyFormGUI.php";
- $form = new ilPropertyFormGUI();
- $form->setFormAction($this->ctrl->getFormAction($this));
-
- $this->showCustomIconsEditing(1, $form);
-
- // $form->setTitle($this->lng->txt('edit_grouping'));
- $form->addCommandButton('updateGroupIcons', $this->lng->txt('save'));
-
- return $form;
- }
-
- /**
- * update group icons
- *
- * @access public
- * @return
- */
- public function updateGroupIconsObject()
- {
- global $DIC;
-
- $ilSetting = $DIC['ilSetting'];
- $this->checkPermission('write');
-
- $form = $this->initGroupIconsForm();
- if($form->checkInput())
- {
- //save custom icons
- if ($ilSetting->get("custom_icons"))
- {
- if($_POST["cont_icon_delete"])
- {
- $this->object->removeCustomIcon();
- }
- $this->object->saveIcons($_FILES["cont_icon"]['tmp_name']);
- }
- ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"),true);
- $this->ctrl->redirect($this,"editGroupIcons");
- }
-
- $form->setValuesByPost();
- $this->editGroupIconsObject($form);
- }
-
/**
* Edit Map Settings
*/
@@ -1103,17 +1046,20 @@ function getTabs()
$ilHelp->setScreenIdComponent("grp");
- if ($rbacsystem->checkAccess('read',$this->ref_id))
+ if ($ilAccess->checkAccess('read','',$this->ref_id))
{
- if ($this->object->getNewsTimeline())
+ if ($this->object->isNewsTimelineEffective())
{
- if (!$this->object->getNewsTimelineLandingPage())
+ if (!$this->object->isNewsTimelineLandingPageEffective())
{
$this->addContentTab();
}
- $this->tabs_gui->addTab("news_timeline", $lng->txt("cont_news_timeline_tab"),
- $this->ctrl->getLinkTargetByClass("ilnewstimelinegui", "show"));
- if ($this->object->getNewsTimelineLandingPage())
+ $this->tabs_gui->addTab(
+ "news_timeline",
+ $lng->txt("cont_news_timeline_tab"),
+ $this->ctrl->getLinkTargetByClass("ilnewstimelinegui", "show")
+ );
+ if ($this->object->isNewsTimelineLandingPageEffective())
{
$this->addContentTab();
}
@@ -1571,6 +1517,7 @@ public function initForm($a_mode = 'edit', $a_omit_form_action = false)
$opt_pass = new ilRadioOption($this->lng->txt('grp_pass_request'),GRP_REGISTRATION_PASSWORD);
$pass = new ilTextInputGUI($this->lng->txt("password"),'password');
+ $pass->setRequired(true);
$pass->setInfo($this->lng->txt('grp_reg_password_info'));
$pass->setValue($this->object->getPassword());
$pass->setSize(32);
@@ -1850,12 +1797,12 @@ protected function setSubTabs($a_tab)
$this->ctrl->getLinkTarget($this,'editInfo'),
"editInfo", get_class($this));
- // custom icon
- if ($this->ilias->getSetting("custom_icons"))
- {
- $this->tabs_gui->addSubTabTarget("grp_icon_settings",
- $this->ctrl->getLinkTarget($this,'editGroupIcons'),
- "editGroupIcons", get_class($this));
+ if ($this->ilias->getSetting('custom_icons')) {
+ $this->tabs_gui->addSubTabTarget(
+ 'grp_icon_settings',
+ $this->ctrl->getLinkTargetByClass('ilObjectCustomIconConfigurationGUI'),
+ 'editGroupIcons', get_class($this)
+ );
}
include_once("./Services/Maps/classes/class.ilMapUtil.php");
diff --git a/Modules/Group/classes/class.ilObjGroupListGUI.php b/Modules/Group/classes/class.ilObjGroupListGUI.php
index c473fd45eef6..ccef0d365b1d 100644
--- a/Modules/Group/classes/class.ilObjGroupListGUI.php
+++ b/Modules/Group/classes/class.ilObjGroupListGUI.php
@@ -79,15 +79,15 @@ function getCommandLink($a_cmd)
require_once ('Services/WebDAV/classes/class.ilDAVActivationChecker.php');
if (ilDAVActivationChecker::_isActive())
{
- require_once ('Services/WebDAV/classes/class.ilDAVServer.php');
- $davServer = ilDAVServer::getInstance();
+ require_once ('Services/WebDAV/classes/class.ilWebDAVUtil.php');
+ $dav_util = ilWebDAVUtil::getInstance();
// XXX: The following is a very dirty, ugly trick.
// To mount URI needs to be put into two attributes:
// href and folder. This hack returns both attributes
// like this: http://...mount_uri..." folder="http://...folder_uri...
- $cmd_link = $davServer->getMountURI($this->ref_id).
- '" folder="'.$davServer->getFolderURI($this->ref_id);
+ $cmd_link = $dav_util->getMountURI($this->ref_id).
+ '" folder="'.$dav_util->getFolderURI($this->ref_id);
break;
} // fall through if plugin is not active
// END Mount Webfolder.
diff --git a/Modules/LearningModule/classes/class.ilLearningModuleDataSet.php b/Modules/LearningModule/classes/class.ilLearningModuleDataSet.php
index d77ace0a1bf9..221e97a9c862 100644
--- a/Modules/LearningModule/classes/class.ilLearningModuleDataSet.php
+++ b/Modules/LearningModule/classes/class.ilLearningModuleDataSet.php
@@ -23,7 +23,20 @@ class ilLearningModuleDataSet extends ilDataSet
protected $transl_into_lm = null;
protected $transl_lang = "";
+ /**
+ * @var ilLogger
+ */
+ protected $lm_log;
+ /**
+ * Constructor
+ */
+ function __construct()
+ {
+ parent::__construct();
+
+ $this->lm_log = ilLoggerFactory::getLogger('lm');
+ }
/**
* Set master language only (export)
*
@@ -503,6 +516,7 @@ function importRecord($a_entity, $a_types, $a_rec, $a_mapping, $a_schema_version
$a_mapping->addMapping("Modules/LearningModule", "lm_tree", $a_rec["Child"],
$pg_obj->getId());
$a_mapping->addMapping("Modules/LearningModule", "pg", $a_rec["Child"], $pg_obj->getId());
+ $this->lm_log->debug("add pg map (1), old : ".$a_rec["Child"].", new: ".$pg_obj->getId());
$a_mapping->addMapping("Services/COPage", "pg", "lm:".$a_rec["Child"],
"lm:".$pg_obj->getId());
$a_mapping->addMapping("Services/MetaData", "md",
@@ -521,6 +535,7 @@ function importRecord($a_entity, $a_types, $a_rec, $a_mapping, $a_schema_version
$a_mapping->addMapping("Modules/LearningModule", "lm_tree", $a_rec["Child"],
$pg_obj->getId());
$a_mapping->addMapping("Modules/LearningModule", "pg", $a_rec["Child"], $pg_obj->getId());
+ $this->lm_log->debug("add pg map (2), old : ".$a_rec["Child"].", new: ".$pg_obj->getId());
$a_mapping->addMapping("Services/COPage", "pg", "lm:".$a_rec["Child"],
"lm:".$pg_obj->getId());
$a_mapping->addMapping("Services/MetaData", "md",
@@ -569,6 +584,7 @@ function importRecord($a_entity, $a_types, $a_rec, $a_mapping, $a_schema_version
$trans->setTitle($a_rec["Title"]);
$trans->save();
$a_mapping->addMapping("Modules/LearningModule", "pg", $a_rec["Child"], $pg_id);
+ $this->lm_log->debug("add pg map (3), old : ".$a_rec["Child"].", new: ".$pg_id);
$a_mapping->addMapping("Modules/LearningModule", "link",
"il_".$this->getCurrentInstallationId()."_".$a_rec["Type"]."_".$a_rec["Child"], $a_rec["ImportId"]);
$a_mapping->addMapping("Services/COPage", "pg", "lm:".$a_rec["Child"],
diff --git a/Modules/LearningModule/classes/class.ilLearningModuleImporter.php b/Modules/LearningModule/classes/class.ilLearningModuleImporter.php
index 4a1371b1561b..ae491df87f1a 100644
--- a/Modules/LearningModule/classes/class.ilLearningModuleImporter.php
+++ b/Modules/LearningModule/classes/class.ilLearningModuleImporter.php
@@ -126,10 +126,12 @@ function finalProcessing($a_mapping)
include_once("./Modules/LearningModule/classes/class.ilLMPage.php");
include_once("./Modules/LearningModule/classes/class.ilLMPageObject.php");
+ $this->log->debug("pg map entries: ".count($pg_map));
foreach ($pg_map as $pg_id)
{
$lm_id = ilLMPageObject::_lookupContObjID($pg_id);
ilLMPage::_writeParentId("lm", $pg_id, $lm_id);
+ $this->log->debug("write parent id, pg id: ".$pg_id.", lm id: ".$lm_id);
}
// header footer page
diff --git a/Modules/LearningModule/classes/class.ilObjContentObject.php b/Modules/LearningModule/classes/class.ilObjContentObject.php
index 5ee43f74b763..dcd2bd4987d0 100755
--- a/Modules/LearningModule/classes/class.ilObjContentObject.php
+++ b/Modules/LearningModule/classes/class.ilObjContentObject.php
@@ -1607,6 +1607,10 @@ function fixTree()
}
}
}
+
+ // missing check: no lm_tree entry but lm_data entry and no page_object entry (for lang "-")
+ // these pages are visible in the all pages list (as free pages), clicking them leads to error
+
}
@@ -3379,8 +3383,12 @@ public function cloneObject($a_target_id,$a_copy_id = 0, $a_omit_tree = false)
$style_obj = ilObjectFactory::getInstanceByObjId($style_id);
$new_id = $style_obj->ilClone();
$new_obj->setStyleSheetId($new_id);
- $new_obj->update();
}
+ else // or just set the same standard style
+ {
+ $new_obj->setStyleSheetId($style_id);
+ }
+ $new_obj->update();
// copy content
$copied_nodes = $this->copyAllPagesAndChapters($new_obj, $a_copy_id);
diff --git a/Modules/RootFolder/classes/class.ilObjRootFolderGUI.php b/Modules/RootFolder/classes/class.ilObjRootFolderGUI.php
index 5fbce96d0bd0..95bf6edb976d 100755
--- a/Modules/RootFolder/classes/class.ilObjRootFolderGUI.php
+++ b/Modules/RootFolder/classes/class.ilObjRootFolderGUI.php
@@ -343,15 +343,24 @@ function updateObject()
{
$this->saveSortingSettings($form);
- // save custom icons
- //save custom icons
- if ($ilSetting->get("custom_icons"))
- {
- if($_POST["cont_icon_delete"])
- {
- $this->object->removeCustomIcon();
+ if ($ilSetting->get('custom_icons')) {
+ global $DIC;
+ /** @var \ilObjectCustomIconFactory $customIconFactory */
+ $customIconFactory = $DIC['object.customicons.factory'];
+ $customIcon = $customIconFactory->getByObjId($this->object->getId(), $this->object->getType());
+
+ /** @var \ilImageFileInputGUI $item */
+ $fileData = (array)$form->getInput('cont_icon');
+ $item = $form->getItemByPostVar('cont_icon');
+
+ if ($item->getDeletionFlag()) {
+ $customIcon->remove();
+ }
+
+ if ($fileData['tmp_name']) {
+ $customIcon->saveFromHttpRequest();
}
- $this->object->saveIcons($_FILES["cont_icon"]['tmp_name']);
+ // cognos-blu-patch: end
}
// hide icon/title
diff --git a/Modules/Session/classes/class.ilObjSession.php b/Modules/Session/classes/class.ilObjSession.php
index 254fa0dd960d..f4ac220badf1 100644
--- a/Modules/Session/classes/class.ilObjSession.php
+++ b/Modules/Session/classes/class.ilObjSession.php
@@ -828,17 +828,26 @@ public function handleAutoFill()
if(in_array($user_id, $parts->getParticipants()))
{
$this->session_logger->notice('User on waiting list already session member: ' . $user_id);
+ continue;
}
if($this->enabledRegistration())
{
$this->session_logger->debug('Registration enabled: register user');
$parts->register($user_id);
+ $parts->sendNotification(
+ ilSessionMembershipMailNotification::TYPE_ACCEPTED_SUBSCRIPTION_MEMBER,
+ $user_id
+ );
}
else
{
$this->session_logger->debug('Registration disabled: set user status to participated.');
$parts->getEventParticipants()->updateParticipation($user_id, true);
+ $parts->sendNotification(
+ ilSessionMembershipMailNotification::TYPE_ACCEPTED_SUBSCRIPTION_MEMBER,
+ $user_id
+ );
}
$session_waiting_list->removeFromList($user_id);
diff --git a/Modules/Session/classes/class.ilObjSessionGUI.php b/Modules/Session/classes/class.ilObjSessionGUI.php
index 5998091bb271..f9970f9034f5 100644
--- a/Modules/Session/classes/class.ilObjSessionGUI.php
+++ b/Modules/Session/classes/class.ilObjSessionGUI.php
@@ -1874,7 +1874,31 @@ public function addLocatorItems()
$ilLocator->addItem($title, $this->ctrl->getLinkTarget($this, "infoScreen"), "", $_GET["ref_id"]);
}
}
-
+
+
+ /**
+ * Redirect to parent content page
+ */
+ protected function redirectToParentContentPageObject()
+ {
+ global $DIC;
+
+ $tree = $DIC->repositoryTree();
+ $ctrl = $DIC->ctrl();
+
+ $parent_id = $tree->getParentId($this->object->getRefId());
+
+ // #11650
+ $parent_type = ilObject::_lookupType($parent_id, true);
+ $parent_class = ($parent_type == "grp")
+ ? "ilObjGroupGUI"
+ : "ilObjCourseGUI";
+
+ $ctrl->setParameterByClass($parent_class, "ref_id", $parent_id);
+ $ctrl->redirectByClass($parent_class, "view");
+ }
+
+
/**
* Build tabs
*
@@ -1898,11 +1922,9 @@ public function getTabs()
// #11650
$parent_type = ilObject::_lookupType($parent_id, true);
- $ilCtrl->setParameterByClass("ilrepositorygui", "ref_id", $parent_id);
$this->tabs_gui->setBackTarget($this->lng->txt('back_to_'.$parent_type.'_content'),
- $ilCtrl->getLinkTargetByClass("ilrepositorygui", ""));
- $ilCtrl->setParameterByClass("ilrepositorygui", "ref_id", $_GET["ref_id"]);
-
+ $ilCtrl->getLinkTarget($this, "redirectToParentContentPage"));
+
$this->tabs_gui->addTarget('info_short',
$this->ctrl->getLinkTarget($this,'infoScreen'));
diff --git a/Modules/Session/classes/class.ilSessionParticipants.php b/Modules/Session/classes/class.ilSessionParticipants.php
index 74c6139d85e1..527e4d0c79c8 100644
--- a/Modules/Session/classes/class.ilSessionParticipants.php
+++ b/Modules/Session/classes/class.ilSessionParticipants.php
@@ -157,5 +157,31 @@ public function unregister($a_usr_id)
return false;
}
+
+ /**
+ * @param int $a_type
+ * @param int $a_usr_id
+ * @param bool $a_force_email
+ */
+ public function sendNotification($a_type, $a_usr_id, $a_force_email = false)
+ {
+ $mail = new ilSessionMembershipMailNotification();
+
+ switch($a_type)
+ {
+ case ilSessionMembershipMailNotification::TYPE_ACCEPTED_SUBSCRIPTION_MEMBER:
+ $mail->setType(ilSessionMembershipMailNotification::TYPE_ACCEPTED_SUBSCRIPTION_MEMBER);
+ $mail->setRefId($this->ref_id);
+ $mail->setRecipients([$a_usr_id]);
+ $mail->send();
+ break;
+
+ default:
+ $this->logger->warning('Invalid notfication type given: ' . $a_type);
+ $this->logger->logStack(ilLogLevel::WARNING);
+ break;
+ }
+ }
+
}
?>
\ No newline at end of file
diff --git a/Modules/StudyProgramme/classes/class.ilObjStudyProgramme.php b/Modules/StudyProgramme/classes/class.ilObjStudyProgramme.php
index 7caadfc0ca86..13a37db62bdd 100644
--- a/Modules/StudyProgramme/classes/class.ilObjStudyProgramme.php
+++ b/Modules/StudyProgramme/classes/class.ilObjStudyProgramme.php
@@ -1275,17 +1275,23 @@ public function getRawSettings() {
*
*/
public function updateCustomIcon() {
+ global $DIC;
+
+ /** @var \ilObjectCustomIconFactory $customIconFactory */
+ $customIconFactory = $DIC['object.customicons.factory'];
+ $customIcon = $customIconFactory->getByObjId($this->getId(), $this->getType());
+
$subtype = $this->getSubType();
if($subtype) {
if($this->webdir->has($subtype->getIconPath(true))) {
$icon = $subtype->getIconPath(true);
- $this->saveIcons($icon);
+ $customIcon->saveFromSourceFile($icon);
} else {
- $this->removeCustomIcon();
+ $customIcon->remove();
}
} else {
- $this->removeCustomIcon();
+ $customIcon->remove();
}
}
@@ -1328,49 +1334,6 @@ static public function getCreatableSubObjects($a_subobjects, $a_ref_id) {
throw new ilException("Undefined mode for study programme: '$mode'");
}
-
- ////////////////////////////////////
- // REWRITES FROM PARENT
- ////////////////////////////////////
-
- /**
- * save container icons
- */
- function saveIcons($a_custom_icon)
- {
- $this->createContainerDirectory();
- $cont_dir = $this->getContainerDirectory();
- $file_name = "";
- if ($a_custom_icon != "")
- {
- $file_name = $cont_dir."/icon_custom.svg";
- if($this->webdir->has($file_name))
- {
- $this->webdir->delete($file_name);
- }
-
- $this->webdir->copy($a_custom_icon, $file_name);
-
- if ($file_name != "" && $this->webdir->has($file_name))
- {
- ilContainer::_writeContainerSetting($this->getId(), "icon_custom", 1);
- }
- else
- {
- ilContainer::_writeContainerSetting($this->getId(), "icon_custom", 0);
- }
- }
- }
-
- /**
- * Get the container directory.
- *
- * @return string container directory
- */
- function getContainerDirectory()
- {
- return "container_data/obj_".$this->getId();
- }
}
?>
diff --git a/Modules/Survey/classes/class.ilSurveyImporter.php b/Modules/Survey/classes/class.ilSurveyImporter.php
index a45ef47718b3..fa9e241d95a0 100644
--- a/Modules/Survey/classes/class.ilSurveyImporter.php
+++ b/Modules/Survey/classes/class.ilSurveyImporter.php
@@ -34,6 +34,11 @@ function __construct()
*/
protected static $survey;
+ /**
+ * @var ilLogger
+ */
+ protected $svy_log;
+
/**
* Init
*
@@ -46,6 +51,8 @@ function init()
$this->ds = new ilSurveyDataSet();
$this->ds->setDSPrefix("ds");
$this->ds->setImport($this);
+
+ $this->svy_log = ilLoggerFactory::getLogger("svy");
}
@@ -109,7 +116,9 @@ function importXmlRepresentation($a_entity, $a_id, $a_xml, $a_mapping)
$import->setSurveyObject($newObj);
$import->startParsing();
+ $this->svy_log->debug("is array import_mob_xml: -".is_array($_SESSION["import_mob_xhtml"])."-");
+ // this is "written" by Services/Survey/classes/class.ilSurveyImportParser
if (is_array($_SESSION["import_mob_xhtml"]))
{
include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
@@ -117,12 +126,16 @@ function importXmlRepresentation($a_entity, $a_id, $a_xml, $a_mapping)
include_once "./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php";
foreach ($_SESSION["import_mob_xhtml"] as $mob)
{
+ $this->svy_log->debug("import mob xhtml, type: ".$mob["type"].", id: ".$mob["mob"]);
+
if (!$mob["type"])
{
$mob["type"] = "svy:html";
}
$importfile = dirname($xml_file) . "/" . $mob["uri"];
+ $this->svy_log->debug("import file: ".$importfile);
+
if (file_exists($importfile))
{
$media_object = ilObjMediaObject::_saveTempFileAsMediaObject(basename($importfile), $importfile, false);
@@ -131,8 +144,11 @@ function importXmlRepresentation($a_entity, $a_id, $a_xml, $a_mapping)
if ($mob["type"] == "svy:html")
{
ilObjMediaObject::_saveUsage($media_object->getId(), "svy:html", $newObj->getId());
+ $this->svy_log->debug("old introduction: ".$newObj->getIntroduction());
$newObj->setIntroduction(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $newObj->getIntroduction()));
$newObj->setOutro(str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $newObj->getOutro()));
+
+ $this->svy_log->debug("new introduction: ".$newObj->getIntroduction());
}
else if($import->questions[$mob["id"]])
{
@@ -140,12 +156,17 @@ function importXmlRepresentation($a_entity, $a_id, $a_xml, $a_mapping)
ilObjMediaObject::_saveUsage($media_object->getId(), $mob["type"], $new_qid);
$new_question = SurveyQuestion::_instanciateQuestion($new_qid);
$qtext = $new_question->getQuestiontext();
+
+ $this->svy_log->debug("old question text: ".$qtext);
+
$qtext = ilRTE::_replaceMediaObjectImageSrc($qtext, 0);
$qtext = str_replace("src=\"" . $mob["mob"] . "\"", "src=\"" . "il_" . IL_INST_ID . "_mob_" . $media_object->getId() . "\"", $qtext);
$qtext = ilRTE::_replaceMediaObjectImageSrc($qtext, 1);
$new_question->setQuestiontext($qtext);
$new_question->saveToDb();
+ $this->svy_log->debug("new question text: ".$qtext);
+
// also fix existing original in pool
if($new_question->getOriginalId())
{
@@ -157,8 +178,7 @@ function importXmlRepresentation($a_entity, $a_id, $a_xml, $a_mapping)
}
else
{
- $ilLog = $this->log;
- $ilLog->write("Error: Could not open XHTML mob file for test introduction during test import. File $importfile does not exist!");
+ $this->svy_log->error("Error: Could not open XHTML mob file for test introduction during test import. File $importfile does not exist!");
}
}
$newObj->setIntroduction(ilRTE::_replaceMediaObjectImageSrc($newObj->getIntroduction(), 1));
diff --git a/Modules/Survey/classes/class.ilSurveyPageGUI.php b/Modules/Survey/classes/class.ilSurveyPageGUI.php
index c83bb0388c94..bf18950ebc88 100644
--- a/Modules/Survey/classes/class.ilSurveyPageGUI.php
+++ b/Modules/Survey/classes/class.ilSurveyPageGUI.php
@@ -1539,6 +1539,12 @@ protected function renderPage()
include_once "./Services/AdvancedEditing/classes/class.ilObjAdvancedEditing.php";
$tags = ilObjAdvancedEditing::_getUsedHTMLTags("survey");
+ /**
+ * Alex Killing, 27 July 2018
+ * I removed a line $tpl->addJavascript("./Services/RTE/tiny_mce_.../tiny_mce_src.js"); at the end
+ * of this function. Currently I have no idea when this tiny will be presented...
+ * Maybe a bug will come out of this during 5.4 testing
+ */
include_once "./Services/RTE/classes/class.ilTinyMCE.php";
$tiny = new ilTinyMCE();
$ttpl->setVariable("WYSIWYG_BLOCKFORMATS", $tiny->_buildAdvancedBlockformatsFromHTMLTags($tags));
@@ -1582,7 +1588,6 @@ protected function renderPage()
include_once("./Services/YUI/classes/class.ilYuiUtil.php");
ilYuiUtil::initDragDrop();
$tpl->addJavascript("./Modules/Survey/js/SurveyPageView.js");
- $tpl->addJavascript("./Services/RTE/tiny_mce_3_5_11/tiny_mce_src.js");
}
}
diff --git a/Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php b/Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php
index 8bf0a9d70716..3cff66770786 100755
--- a/Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php
+++ b/Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php
@@ -1876,6 +1876,9 @@ function isHTML($a_text)
*/
function QTIMaterialToString($a_material)
{
+ $svy_log = ilLoggerFactory::getLogger("svy");
+ $svy_log->debug("material count: ".$a_material->getMaterialCount());
+
$result = "";
for ($i = 0; $i < $a_material->getMaterialCount(); $i++)
{
diff --git a/Modules/Test/classes/class.ilObjTest.php b/Modules/Test/classes/class.ilObjTest.php
index 21e2d4da6d8d..c9279af855e8 100755
--- a/Modules/Test/classes/class.ilObjTest.php
+++ b/Modules/Test/classes/class.ilObjTest.php
@@ -560,7 +560,12 @@ class ilObjTest extends ilObject implements ilMarkSchemaAware, ilEctsGradesEnabl
* @var bool
*/
protected $showGradingMarkEnabled;
-
+
+ /**
+ * @var bool
+ */
+ protected $followupQuestionAnswerFixationEnabled;
+
/**
* @var bool
*/
@@ -696,6 +701,7 @@ public function __construct($a_id = 0,$a_call_by_reference = true)
$this->showGradingStatusEnabled = true;
$this->showGradingMarkEnabled = true;
+ $this->followupQuestionAnswerFixationEnabled = false;
$this->instantFeedbackAnswerFixationEnabled = false;
$this->testFinalBroken = false;
@@ -1327,6 +1333,7 @@ public function saveToDb($properties_only = FALSE)
'result_tax_filters' => array('text', serialize((array)$this->getResultFilterTaxIds())),
'show_grading_status' => array('integer', (int)$this->isShowGradingStatusEnabled()),
'show_grading_mark' => array('integer', (int)$this->isShowGradingMarkEnabled()),
+ 'follow_qst_answer_fixation' => array('integer', (int)$this->isFollowupQuestionAnswerFixationEnabled()),
'inst_fb_answer_fixation' => array('integer', (int)$this->isInstantFeedbackAnswerFixationEnabled()),
'force_inst_fb' => array('integer', (int)$this->isForceInstantFeedbackEnabled()),
'broken' => array('integer', (int)$this->isTestFinalBroken()),
@@ -1449,6 +1456,7 @@ public function saveToDb($properties_only = FALSE)
'result_tax_filters' => array('text', serialize((array)$this->getResultFilterTaxIds())),
'show_grading_status' => array('integer', (int)$this->isShowGradingStatusEnabled()),
'show_grading_mark' => array('integer', (int)$this->isShowGradingMarkEnabled()),
+ 'follow_qst_answer_fixation' => array('integer', (int)$this->isFollowupQuestionAnswerFixationEnabled()),
'inst_fb_answer_fixation' => array('integer', (int)$this->isInstantFeedbackAnswerFixationEnabled()),
'force_inst_fb' => array('integer', (int)$this->isForceInstantFeedbackEnabled()),
'broken' => array('integer', (int)$this->isTestFinalBroken()),
@@ -1971,6 +1979,7 @@ public function loadFromDb()
$this->setResultFilterTaxIds(strlen($data->result_tax_filters) ? unserialize($data->result_tax_filters) : array());
$this->setShowGradingStatusEnabled((bool)$data->show_grading_status);
$this->setShowGradingMarkEnabled((bool)$data->show_grading_mark);
+ $this->setFollowupQuestionAnswerFixationEnabled((bool)$data->follow_qst_answer_fixation);
$this->setInstantFeedbackAnswerFixationEnabled((bool)$data->inst_fb_answer_fixation);
$this->setForceInstantFeedbackEnabled((bool)$data->force_inst_fb);
$this->setTestFinalBroken((bool)$data->broken);
@@ -5988,6 +5997,9 @@ public function fromXML(ilQTIAssessment $assessment)
case "instant_verification":
$this->setInstantFeedbackSolution($metadata["entry"]);
break;
+ case "follow_qst_answer_fixation":
+ $this->setFollowupQuestionAnswerFixationEnabled((bool)$metadata["entry"]);
+ break;
case "instant_feedback_answer_fixation":
$this->setInstantFeedbackAnswerFixationEnabled((bool)$metadata["entry"]);
break;
@@ -6429,6 +6441,12 @@ public function toXML()
$a_xml_writer->xmlElement("fieldentry", NULL, sprintf("%d", $this->getAnswerFeedbackPoints()));
$a_xml_writer->xmlEndTag("qtimetadatafield");
+ // followup question previous answer freezing
+ $a_xml_writer->xmlStartTag("qtimetadatafield");
+ $a_xml_writer->xmlElement("fieldlabel", NULL, "follow_qst_answer_fixation");
+ $a_xml_writer->xmlElement("fieldentry", NULL, (int)$this->isFollowupQuestionAnswerFixationEnabled());
+ $a_xml_writer->xmlEndTag("qtimetadatafield");
+
// instant response answer freezing
$a_xml_writer->xmlStartTag("qtimetadatafield");
$a_xml_writer->xmlElement("fieldlabel", NULL, "instant_feedback_answer_fixation");
@@ -7351,6 +7369,7 @@ public function cloneObject($a_target_id,$a_copy_id = 0, $a_omit_tree = false)
$newObj->setCharSelectorDefinition($this->getCharSelectorDefinition());
$newObj->setSkillServiceEnabled($this->isSkillServiceEnabled());
$newObj->setResultFilterTaxIds($this->getResultFilterTaxIds());
+ $newObj->setFollowupQuestionAnswerFixationEnabled($this->isFollowupQuestionAnswerFixationEnabled());
$newObj->setInstantFeedbackAnswerFixationEnabled($this->isInstantFeedbackAnswerFixationEnabled());
$newObj->setForceInstantFeedbackEnabled($this->isForceInstantFeedbackEnabled());
$newObj->setAutosave($this->getAutosave());
@@ -9974,6 +9993,7 @@ function addDefaults($a_name)
'show_grading_status' => (int)$this->isShowGradingStatusEnabled(),
'show_grading_mark' => (int)$this->isShowGradingMarkEnabled(),
+ 'follow_qst_answer_fixation' => $this->isFollowupQuestionAnswerFixationEnabled(),
'inst_fb_answer_fixation' => $this->isInstantFeedbackAnswerFixationEnabled(),
'force_inst_fb' => $this->isForceInstantFeedbackEnabled(),
'redirection_mode' => $this->getRedirectionMode(),
@@ -10137,6 +10157,7 @@ public function applyDefaults($test_defaults)
$this->setShowGradingStatusEnabled((bool)$testsettings['show_grading_status']);
$this->setShowGradingMarkEnabled((bool)$testsettings['show_grading_mark']);
+ $this->setFollowupQuestionAnswerFixationEnabled($testsettings['follow_qst_answer_fixation']);
$this->setInstantFeedbackAnswerFixationEnabled($testsettings['inst_fb_answer_fixation']);
$this->setForceInstantFeedbackEnabled($testsettings['force_inst_fb']);
$this->setRedirectionMode($testsettings['redirection_mode']);
@@ -10994,8 +11015,28 @@ public function moveQuestionAfterOLD($previous_question_id, $new_question_id) {
);
}
}
+
+ public function isAnyInstantFeedbackOptionEnabled()
+ {
+ return (
+ $this->getSpecificAnswerFeedback() || $this->getGenericAnswerFeedback() ||
+ $this->getAnswerFeedbackPoints() || $this->getInstantFeedbackSolution()
+ );
+ }
+
+ public function getInstantFeedbackOptionsAsArray()
+ {
+ $values = array();
+
+ if( $this->getSpecificAnswerFeedback() ) $values[] = 'instant_feedback_specific';
+ if( $this->getGenericAnswerFeedback() ) $values[] = 'instant_feedback_generic';
+ if( $this->getAnswerFeedbackPoints() ) $values[] = 'instant_feedback_points';
+ if( $this->getInstantFeedbackSolution() ) $values[] = 'instant_feedback_solution';
+
+ return $values;
+ }
- public function setScoringFeedbackOptionsByArray($options)
+ public function setInstantFeedbackOptionsByArray($options)
{
if (is_array($options))
{
@@ -12285,6 +12326,16 @@ public function isShowGradingMarkEnabled()
{
return $this->showGradingMarkEnabled;
}
+
+ public function setFollowupQuestionAnswerFixationEnabled($followupQuestionAnswerFixationEnabled)
+ {
+ $this->followupQuestionAnswerFixationEnabled = $followupQuestionAnswerFixationEnabled;
+ }
+
+ public function isFollowupQuestionAnswerFixationEnabled()
+ {
+ return $this->followupQuestionAnswerFixationEnabled;
+ }
public function setInstantFeedbackAnswerFixationEnabled($instantFeedbackAnswerFixationEnabled)
{
diff --git a/Modules/Test/classes/class.ilObjTestGUI.php b/Modules/Test/classes/class.ilObjTestGUI.php
index 0a232e780a3e..d3576f8ea665 100755
--- a/Modules/Test/classes/class.ilObjTestGUI.php
+++ b/Modules/Test/classes/class.ilObjTestGUI.php
@@ -3527,7 +3527,7 @@ function createQuestionpoolTargetObject($cmd)
}
// begin-patch lok
- public function applyTemplate($templateData, $object)
+ public function applyTemplate($templateData, ilObjTest $object)
// end-patch lok
{
// map formFieldName => setterName
@@ -3559,7 +3559,9 @@ public function applyTemplate($templateData, $object)
'autosave' => null, // handled specially in loop below
'chb_shuffle_questions' => 'setShuffleQuestions',
'offer_hints' => 'setOfferingQuestionHintsEnabled',
- 'instant_feedback' => 'setScoringFeedbackOptionsByArray',
+ 'instant_feedback_contents' => 'setInstantFeedbackOptionsByArray',
+ 'instant_feedback_trigger' => 'setForceInstantFeedbackEnabled',
+ 'answer_fixation_handling' => null, // handled specially in loop below
'obligations_enabled' => 'setObligationsEnabled',
// test sequence properties
@@ -3649,6 +3651,32 @@ public function applyTemplate($templateData, $object)
$object->setRedirectionMode(REDIRECT_NONE);
$object->setRedirectionUrl('');
}
+ break;
+
+ case 'answer_fixation_handling':
+ switch($templateData[$field]['value'])
+ {
+ case ilObjTestSettingsGeneralGUI::ANSWER_FIXATION_NONE:
+ $object->setInstantFeedbackAnswerFixationEnabled(false);
+ $object->setFollowupQuestionAnswerFixationEnabled(false);
+ break;
+
+ case ilObjTestSettingsGeneralGUI::ANSWER_FIXATION_ON_INSTANT_FEEDBACK:
+ $object->setInstantFeedbackAnswerFixationEnabled(true);
+ $object->setFollowupQuestionAnswerFixationEnabled(false);
+ break;
+
+ case ilObjTestSettingsGeneralGUI::ANSWER_FIXATION_ON_FOLLOWUP_QUESTION:
+ $object->setInstantFeedbackAnswerFixationEnabled(false);
+ $object->setFollowupQuestionAnswerFixationEnabled(true);
+ break;
+
+ case ilObjTestSettingsGeneralGUI::ANSWER_FIXATION_ON_IFB_OR_FUQST:
+ $object->setInstantFeedbackAnswerFixationEnabled(true);
+ $object->setFollowupQuestionAnswerFixationEnabled(true);
+ break;
+ }
+ break;
}
}
}
diff --git a/Modules/Test/classes/class.ilObjTestSettingsGeneralGUI.php b/Modules/Test/classes/class.ilObjTestSettingsGeneralGUI.php
index afeaf17ad463..f74dbd27fdc7 100644
--- a/Modules/Test/classes/class.ilObjTestSettingsGeneralGUI.php
+++ b/Modules/Test/classes/class.ilObjTestSettingsGeneralGUI.php
@@ -28,10 +28,13 @@ class ilObjTestSettingsGeneralGUI extends ilTestSettingsGUI
const CMD_SHOW_RESET_TPL_CONFIRM = 'showResetTemplateConfirmation';
const CMD_CONFIRMED_RESET_TPL = 'confirmedResetTemplate';
- const INST_FB_HANDLING_OPT_NONE = 'none';
- const INST_FB_HANDLING_OPT_FREEZE = 'freeze';
- const INST_FB_HANDLING_OPT_FORCE = 'force';
- const INST_FB_HANDLING_OPT_FORCE_AND_FREEZE = 'force_freeze';
+ const ANSWER_FIXATION_NONE = 'none';
+ const ANSWER_FIXATION_ON_INSTANT_FEEDBACK = 'instant_feedback';
+ const ANSWER_FIXATION_ON_FOLLOWUP_QUESTION = 'followup_question';
+ const ANSWER_FIXATION_ON_IFB_OR_FUQST = 'ifb_or_fuqst';
+
+ const INSTANT_FEEDBACK_TRIGGER_MANUAL = 0;
+ const INSTANT_FEEDBACK_TRIGGER_FORCED = 1;
/** @var ilCtrl $ctrl */
protected $ctrl = null;
@@ -233,6 +236,50 @@ private function saveFormCmd($isConfirmedSave = false)
ilUtil::sendFailure($this->lng->txt('form_input_not_valid'));
return $this->showFormCmd($form);
}
+
+ // avoid settings conflict "obligate questions" and "freeze answer"
+
+ $obligationsSetting = $form->getItemByPostVar('obligations_enabled');
+ $answerFixationSetting = $form->getItemByPostVar('answer_fixation_handling');
+
+ if( $obligationsSetting->getChecked() && $answerFixationSetting->getValue() != self::ANSWER_FIXATION_NONE )
+ {
+ $obligationsSetting->setAlert($this->lng->txt('tst_conflicting_setting'));
+ $answerFixationSetting->setAlert($this->lng->txt('tst_conflicting_setting'));
+
+ ilUtil::sendFailure($this->lng->txt('tst_settings_conflict_message'));
+ return $this->showFormCmd($form);
+ }
+
+ // avoid settings conflict "freeze answer on followup question" and "question postponing"
+
+ $postponeSetting = $form->getItemByPostVar('postpone');
+ $answerFixationSetting = $form->getItemByPostVar('answer_fixation_handling');
+ $conflictModes = array(self::ANSWER_FIXATION_ON_FOLLOWUP_QUESTION, self::ANSWER_FIXATION_ON_IFB_OR_FUQST);
+
+ if( $postponeSetting->getValue() && in_array($answerFixationSetting->getValue(), $conflictModes) )
+ {
+ $postponeSetting->setAlert($this->lng->txt('tst_conflicting_setting'));
+ $answerFixationSetting->setAlert($this->lng->txt('tst_conflicting_setting'));
+
+ ilUtil::sendFailure($this->lng->txt('tst_settings_conflict_message'));
+ return $this->showFormCmd($form);
+ }
+
+ // avoid settings conflict "freeze answer on followup question" and "question shuffling"
+
+ $shuffleSetting = $form->getItemByPostVar('chb_shuffle_questions');
+ $answerFixationSetting = $form->getItemByPostVar('answer_fixation_handling');
+ $conflictModes = array(self::ANSWER_FIXATION_ON_FOLLOWUP_QUESTION, self::ANSWER_FIXATION_ON_IFB_OR_FUQST);
+
+ if( $shuffleSetting->getChecked() && in_array($answerFixationSetting->getValue(), $conflictModes) )
+ {
+ $shuffleSetting->setAlert($this->lng->txt('tst_conflicting_setting'));
+ $answerFixationSetting->setAlert($this->lng->txt('tst_conflicting_setting'));
+
+ ilUtil::sendFailure($this->lng->txt('tst_settings_conflict_message'));
+ return $this->showFormCmd($form);
+ }
$infoMsg = array();
@@ -292,35 +339,13 @@ private function saveFormCmd($isConfirmedSave = false)
$newQuestionSetType = $oldQuestionSetType;
}
- // adjust settiue to desired question set type
+ // adjust settings due to chosen question set type
if( $newQuestionSetType != ilObjTest::QUESTION_SET_TYPE_FIXED )
{
$form->getItemByPostVar('chb_use_previous_answers')->setChecked(false);
}
- // avoid settings conflict "obligate questions" and "freeze answer"
-
- if( $form->getItemByPostVar('obligations_enabled')->getChecked() )
- {
- switch( $form->getItemByPostVar('instant_feedback_handling')->getValue() )
- {
- case self::INST_FB_HANDLING_OPT_FREEZE:
-
- $form->getItemByPostVar('instant_feedback_handling')->setValue(self::INST_FB_HANDLING_OPT_NONE);
- $infoMsg[] = $this->lng->txt("tst_conflict_fbh_oblig_quest");
- $infoMsg[] = $this->lng->txt("tst_conflict_reset_non_fbh");
- break;
-
- case self::INST_FB_HANDLING_OPT_FORCE_AND_FREEZE:
-
- $form->getItemByPostVar('instant_feedback_handling')->setValue(self::INST_FB_HANDLING_OPT_FORCE);
- $infoMsg[] = $this->lng->txt("tst_conflict_fbh_oblig_quest");
- $infoMsg[] = $this->lng->txt("tst_conflict_reset_fbh_force");
- break;
- }
- }
-
// perform saving the form data
$this->performSaveForm($form);
@@ -1109,7 +1134,8 @@ private function addQuestionBehaviourProperties(ilPropertyFormGUI $form)
{
$fields = array(
'title_output', 'autosave', 'chb_shuffle_questions', 'chb_shuffle_questions',
- 'offer_hints', 'instant_feedback', 'obligations_enabled',
+ 'offer_hints', 'instant_feedback_contents', 'instant_feedback_trigger',
+ 'answer_fixation_handling', 'obligations_enabled'
);
if( $this->isSectionHeaderRequired($fields) || $this->isCharSelectorPropertyRequired() )
@@ -1151,83 +1177,83 @@ private function addQuestionBehaviourProperties(ilPropertyFormGUI $form)
$checkBoxOfferHints = new ilCheckboxInputGUI($this->lng->txt('tst_setting_offer_hints_label'), 'offer_hints');
$checkBoxOfferHints->setChecked($this->testOBJ->isOfferingQuestionHintsEnabled());
$checkBoxOfferHints->setInfo($this->lng->txt('tst_setting_offer_hints_info'));
- if( $this->testOBJ->participantDataExist() )
- {
- $checkBoxOfferHints->setDisabled(true);
- }
$form->addItem($checkBoxOfferHints);
// instant feedback
- $instant_feedback = new ilCheckboxGroupInputGUI($this->lng->txt('tst_instant_feedback'), 'instant_feedback');
- $instant_feedback->addOption(new ilCheckboxOption(
+ $instant_feedback_enabled = new ilCheckboxInputGUI($this->lng->txt('tst_instant_feedback'), 'instant_feedback_enabled');
+ $instant_feedback_enabled->setInfo($this->lng->txt('tst_instant_feedback_desc'));
+ $instant_feedback_enabled->setChecked($this->testOBJ->isAnyInstantFeedbackOptionEnabled());
+ $form->addItem($instant_feedback_enabled);
+ $instant_feedback_contents = new ilCheckboxGroupInputGUI($this->lng->txt('tst_instant_feedback_contents'), 'instant_feedback_contents');
+ $instant_feedback_contents->setRequired(true);
+ $instant_feedback_contents->addOption(new ilCheckboxOption(
$this->lng->txt('tst_instant_feedback_results'), 'instant_feedback_points',
$this->lng->txt('tst_instant_feedback_results_desc')
));
- $instant_feedback->addOption(new ilCheckboxOption(
+ $instant_feedback_contents->addOption(new ilCheckboxOption(
$this->lng->txt('tst_instant_feedback_answer_generic'), 'instant_feedback_generic',
$this->lng->txt('tst_instant_feedback_answer_generic_desc')
));
- $instant_feedback->addOption(new ilCheckboxOption(
+ $instant_feedback_contents->addOption(new ilCheckboxOption(
$this->lng->txt('tst_instant_feedback_answer_specific'), 'instant_feedback_specific',
$this->lng->txt('tst_instant_feedback_answer_specific_desc')
));
- $instant_feedback->addOption(new ilCheckboxOption(
+ $instant_feedback_contents->addOption(new ilCheckboxOption(
$this->lng->txt('tst_instant_feedback_solution'), 'instant_feedback_solution',
$this->lng->txt('tst_instant_feedback_solution_desc')
));
- $values = array();
- if ($this->testOBJ->getSpecificAnswerFeedback()) array_push($values, 'instant_feedback_specific');
- if ($this->testOBJ->getGenericAnswerFeedback()) array_push($values, 'instant_feedback_generic');
- if ($this->testOBJ->getAnswerFeedbackPoints()) array_push($values, 'instant_feedback_points');
- if ($this->testOBJ->getInstantFeedbackSolution()) array_push($values, 'instant_feedback_solution');
- $instant_feedback->setValue($values);
- $form->addItem($instant_feedback);
+ $instant_feedback_contents->setValue($this->testOBJ->getInstantFeedbackOptionsAsArray());
+ $instant_feedback_enabled->addSubItem($instant_feedback_contents);
+ $instant_feedback_trigger = new ilRadioGroupInputGUI(
+ $this->lng->txt('tst_instant_feedback_trigger'), 'instant_feedback_trigger'
+ );
+ $ifbTriggerOpt = new ilRadioOption(
+ $this->lng->txt('tst_instant_feedback_trigger_manual'), self::INSTANT_FEEDBACK_TRIGGER_MANUAL
+ );
+ $ifbTriggerOpt->setInfo($this->lng->txt('tst_instant_feedback_trigger_manual_desc'));
+ $instant_feedback_trigger->addOption($ifbTriggerOpt);
+ $ifbTriggerOpt = new ilRadioOption(
+ $this->lng->txt('tst_instant_feedback_trigger_forced'), self::INSTANT_FEEDBACK_TRIGGER_FORCED
+ );
+ $ifbTriggerOpt->setInfo($this->lng->txt('tst_instant_feedback_trigger_forced_desc'));
+ $instant_feedback_trigger->addOption($ifbTriggerOpt);
+ $instant_feedback_trigger->setValue($this->testOBJ->isForceInstantFeedbackEnabled());
+ $instant_feedback_enabled->addSubItem($instant_feedback_trigger);
- $radioGroup = new ilRadioGroupInputGUI(
- $this->lng->txt('tst_instant_feedback_handling'), 'instant_feedback_handling'
+ $answerFixation = new ilRadioGroupInputGUI(
+ $this->lng->txt('tst_answer_fixation_handling'), 'answer_fixation_handling'
);
- if( $this->testOBJ->participantDataExist() )
- {
- $radioGroup->setDisabled(true);
- }
$radioOption = new ilRadioOption(
- $this->lng->txt('tst_instant_feedback_handling_none'),
- self::INST_FB_HANDLING_OPT_NONE
+ $this->lng->txt('tst_answer_fixation_none'),
+ self::ANSWER_FIXATION_NONE
);
- $radioOption->setInfo($this->lng->txt('tst_instant_feedback_handling_none_desc'));
- $radioGroup->addOption($radioOption);
+ $radioOption->setInfo($this->lng->txt('tst_answer_fixation_none_desc'));
+ $answerFixation->addOption($radioOption);
$radioOption = new ilRadioOption(
- $this->lng->txt('tst_instant_feedback_handling_freeze'),
- self::INST_FB_HANDLING_OPT_FREEZE
+ $this->lng->txt('tst_answer_fixation_on_instant_feedback'),
+ self::ANSWER_FIXATION_ON_INSTANT_FEEDBACK
);
- $radioOption->setInfo($this->lng->txt('tst_instant_feedback_handling_freeze_desc'));
- $radioGroup->addOption($radioOption);
+ $radioOption->setInfo($this->lng->txt('tst_answer_fixation_on_instant_feedback_desc'));
+ $answerFixation->addOption($radioOption);
$radioOption = new ilRadioOption(
- $this->lng->txt('tst_instant_feedback_handling_force_and_freeze'),
- self::INST_FB_HANDLING_OPT_FORCE_AND_FREEZE
+ $this->lng->txt('tst_answer_fixation_on_followup_question'),
+ self::ANSWER_FIXATION_ON_FOLLOWUP_QUESTION
);
- $radioOption->setInfo($this->lng->txt('tst_instant_feedback_handling_force_and_freeze_desc'));
- $radioGroup->addOption($radioOption);
+ $radioOption->setInfo($this->lng->txt('tst_answer_fixation_on_followup_question_desc'));
+ $answerFixation->addOption($radioOption);
$radioOption = new ilRadioOption(
- $this->lng->txt('tst_instant_feedback_handling_force'),
- self::INST_FB_HANDLING_OPT_FORCE
+ $this->lng->txt('tst_answer_fixation_on_instantfb_or_followupqst'),
+ self::ANSWER_FIXATION_ON_IFB_OR_FUQST
);
- $radioOption->setInfo($this->lng->txt('tst_instant_feedback_handling_force_desc'));
- $radioGroup->addOption($radioOption);
- $radioGroup->setValue($this->getInstFbHandlingValue(
- $this->testOBJ->isInstantFeedbackAnswerFixationEnabled(),
- $this->testOBJ->isForceInstantFeedbackEnabled()
- ));
- $form->addItem($radioGroup);
+ $radioOption->setInfo($this->lng->txt('tst_answer_fixation_on_instantfb_or_followupqst_desc'));
+ $answerFixation->addOption($radioOption);
+ $answerFixation->setValue($this->getAnswerFixationSettingsAsFormValue());
+ $form->addItem($answerFixation);
// enable obligations
$checkBoxEnableObligations = new ilCheckboxInputGUI($this->lng->txt('tst_setting_enable_obligations_label'), 'obligations_enabled');
$checkBoxEnableObligations->setChecked($this->testOBJ->areObligationsEnabled());
$checkBoxEnableObligations->setInfo($this->lng->txt('tst_setting_enable_obligations_info'));
- if( $this->testOBJ->participantDataExist() )
- {
- $checkBoxEnableObligations->setDisabled(true);
- }
$form->addItem($checkBoxEnableObligations);
// selector for unicode characters
@@ -1240,6 +1266,17 @@ private function addQuestionBehaviourProperties(ilPropertyFormGUI $form)
$char_selector->addFormProperties($form);
$char_selector->setFormValues($form);
}
+
+ if( $this->testOBJ->participantDataExist() )
+ {
+ $checkBoxOfferHints->setDisabled(true);
+ $instant_feedback_enabled->setDisabled(true);
+ $instant_feedback_trigger->setDisabled(true);
+ $instant_feedback_contents->setDisabled(true);
+ $answerFixation->setDisabled(true);
+ $checkBoxEnableObligations->setDisabled(true);
+ }
+
}
/**
@@ -1268,14 +1305,33 @@ private function saveQuestionBehaviourProperties(ilPropertyFormGUI $form)
$this->testOBJ->setOfferingQuestionHintsEnabled($form->getItemByPostVar('offer_hints')->getChecked());
}
- if ($this->formPropertyExists($form, 'instant_feedback'))
+ if (!$this->testOBJ->participantDataExist() && $this->formPropertyExists($form, 'instant_feedback_enabled'))
{
- $this->testOBJ->setScoringFeedbackOptionsByArray($form->getItemByPostVar('instant_feedback')->getValue());
+ if( $form->getItemByPostVar('instant_feedback_enabled')->getChecked() )
+ {
+ if( $this->formPropertyExists($form, 'instant_feedback_contents') )
+ {
+ $this->testOBJ->setInstantFeedbackOptionsByArray(
+ $form->getItemByPostVar('instant_feedback_contents')->getValue()
+ );
+ }
+ if( $this->formPropertyExists($form, 'instant_feedback_trigger') )
+ {
+ $this->testOBJ->setForceInstantFeedbackEnabled(
+ (bool)$form->getItemByPostVar('instant_feedback_trigger')->getValue()
+ );
+ }
+ }
+ else
+ {
+ $this->testOBJ->setInstantFeedbackOptionsByArray( array() );
+ $this->testOBJ->setForceInstantFeedbackEnabled(false);
+ }
}
- if (!$this->testOBJ->participantDataExist() && $this->formPropertyExists($form, 'instant_feedback_handling'))
+ if (!$this->testOBJ->participantDataExist() && $this->formPropertyExists($form, 'answer_fixation_handling'))
{
- $this->saveInstFbHandlingSettings($form->getItemByPostVar('instant_feedback_handling')->getValue());
+ $this->setAnswerFixationSettingsByFormValue($form->getItemByPostVar('answer_fixation_handling')->getValue());
}
if (!$this->testOBJ->participantDataExist() && $this->formPropertyExists($form, 'obligations_enabled'))
@@ -1530,40 +1586,46 @@ private function saveTestFinishProperties(ilPropertyFormGUI $form)
}
}
- private function saveInstFbHandlingSettings($instantFeedbackHandlingValue)
+ protected function setAnswerFixationSettingsByFormValue($formValue)
{
- switch($instantFeedbackHandlingValue)
+ switch($formValue)
{
- case self::INST_FB_HANDLING_OPT_NONE:
+ case self::ANSWER_FIXATION_NONE:
$this->testOBJ->setInstantFeedbackAnswerFixationEnabled(false);
- $this->testOBJ->setForceInstantFeedbackEnabled(false);
+ $this->testOBJ->setFollowupQuestionAnswerFixationEnabled(false);
break;
-
- case self::INST_FB_HANDLING_OPT_FREEZE:
+ case self::ANSWER_FIXATION_ON_INSTANT_FEEDBACK:
$this->testOBJ->setInstantFeedbackAnswerFixationEnabled(true);
- $this->testOBJ->setForceInstantFeedbackEnabled(false);
+ $this->testOBJ->setFollowupQuestionAnswerFixationEnabled(false);
break;
-
- case self::INST_FB_HANDLING_OPT_FORCE:
+ case self::ANSWER_FIXATION_ON_FOLLOWUP_QUESTION:
$this->testOBJ->setInstantFeedbackAnswerFixationEnabled(false);
- $this->testOBJ->setForceInstantFeedbackEnabled(true);
+ $this->testOBJ->setFollowupQuestionAnswerFixationEnabled(true);
break;
-
- case self::INST_FB_HANDLING_OPT_FORCE_AND_FREEZE:
+ case self::ANSWER_FIXATION_ON_IFB_OR_FUQST:
$this->testOBJ->setInstantFeedbackAnswerFixationEnabled(true);
- $this->testOBJ->setForceInstantFeedbackEnabled(true);
+ $this->testOBJ->setFollowupQuestionAnswerFixationEnabled(true);
break;
}
}
- private function getInstFbHandlingValue($freezeAnswersEnabled, $forceInstFbEnabled)
+ protected function getAnswerFixationSettingsAsFormValue()
{
- switch( true )
+ if( $this->testOBJ->isInstantFeedbackAnswerFixationEnabled() && $this->testOBJ->isFollowupQuestionAnswerFixationEnabled() )
+ {
+ return self::ANSWER_FIXATION_ON_IFB_OR_FUQST;
+ }
+
+ if( $this->testOBJ->isFollowupQuestionAnswerFixationEnabled() )
{
- case !$freezeAnswersEnabled && !$forceInstFbEnabled: return self::INST_FB_HANDLING_OPT_NONE;
- case $freezeAnswersEnabled && !$forceInstFbEnabled: return self::INST_FB_HANDLING_OPT_FREEZE;
- case !$freezeAnswersEnabled && $forceInstFbEnabled: return self::INST_FB_HANDLING_OPT_FORCE;
- case $freezeAnswersEnabled && $forceInstFbEnabled: return self::INST_FB_HANDLING_OPT_FORCE_AND_FREEZE;
+ return self::ANSWER_FIXATION_ON_FOLLOWUP_QUESTION;
}
+
+ if( $this->testOBJ->isInstantFeedbackAnswerFixationEnabled() )
+ {
+ return self::ANSWER_FIXATION_ON_INSTANT_FEEDBACK;
+ }
+
+ return self::ANSWER_FIXATION_NONE;
}
}
diff --git a/Modules/Test/classes/class.ilParticipantsTestResultsGUI.php b/Modules/Test/classes/class.ilParticipantsTestResultsGUI.php
index 4b5a87b0a0cd..c002cb1fec67 100644
--- a/Modules/Test/classes/class.ilParticipantsTestResultsGUI.php
+++ b/Modules/Test/classes/class.ilParticipantsTestResultsGUI.php
@@ -308,14 +308,7 @@ protected function deleteSingleUserResultsCmd()
$participantData = new ilTestParticipantData($DIC->database(), $DIC->language());
$participantData->setParticipantAccessFilter($accessFilter);
- if( $this->getTestObj()->getFixedParticipants() )
- {
- $participantData->setUserIdsFilter((array)$_POST["chbUser"]);
- }
- else
- {
- $participantData->setActiveIdsFilter((array)$_POST["chbUser"]);
- }
+ $participantData->setActiveIdsFilter((array)$_POST["chbUser"]);
$participantData->load($this->getTestObj()->getTestId());
@@ -337,19 +330,23 @@ protected function confirmDeleteSelectedUserDataCmd()
{
global $DIC; /* @var ILIAS\DI\Container $DIC */
- require_once 'Modules/Test/classes/class.ilTestParticipantAccessFilter.php';
- $accessFilter = ilTestParticipantAccessFilter::getManageParticipantsUserFilter($this->getTestObj()->getRefId());
-
- require_once 'Modules/Test/classes/class.ilTestParticipantData.php';
- $participantData = new ilTestParticipantData($DIC->database(), $DIC->language());
- $participantData->setParticipantAccessFilter($accessFilter);
- $participantData->setActiveIdsFilter($_POST["chbUser"]);
-
- $participantData->load($this->getTestObj()->getTestId());
-
- $this->getTestObj()->removeTestResults($participantData);
+ if( isset($_POST["chbUser"]) && is_array($_POST["chbUser"]) && count($_POST["chbUser"]) )
+ {
+ require_once 'Modules/Test/classes/class.ilTestParticipantAccessFilter.php';
+ $accessFilter = ilTestParticipantAccessFilter::getManageParticipantsUserFilter($this->getTestObj()->getRefId());
+
+ require_once 'Modules/Test/classes/class.ilTestParticipantData.php';
+ $participantData = new ilTestParticipantData($DIC->database(), $DIC->language());
+ $participantData->setParticipantAccessFilter($accessFilter);
+ $participantData->setActiveIdsFilter($_POST["chbUser"]);
+
+ $participantData->load($this->getTestObj()->getTestId());
+
+ $this->getTestObj()->removeTestResults($participantData);
+
+ ilUtil::sendSuccess($DIC->language()->txt("tst_selected_user_data_deleted"), true);
+ }
- ilUtil::sendSuccess($DIC->language()->txt("tst_selected_user_data_deleted"), true);
$DIC->ctrl()->redirect($this, self::CMD_SHOW_PARTICIPANTS);
}
diff --git a/Modules/Test/classes/class.ilTestOutputGUI.php b/Modules/Test/classes/class.ilTestOutputGUI.php
index 813669f7a791..1c89ef68454b 100755
--- a/Modules/Test/classes/class.ilTestOutputGUI.php
+++ b/Modules/Test/classes/class.ilTestOutputGUI.php
@@ -279,6 +279,12 @@ protected function showQuestionCmd()
{
$this->handleTearsAndAngerNoObjectiveOrientedQuestion();
}
+
+ if( !$this->testSequence->isQuestionPresented($questionId) )
+ {
+ $this->testSequence->setQuestionPresented($questionId);
+ $this->testSequence->saveToDb();
+ }
$isQuestionWorkedThrough = assQuestion::_isWorkedThrough(
$this->testSession->getActiveId(), $questionId, $this->testSession->getPass()
@@ -386,10 +392,10 @@ protected function showQuestionCmd()
}
// fau: testNav - add feedback modal
- if (!empty($_SESSION['forced_feedback_navigation_url']))
+ if ($this->isForcedFeedbackNavUrlRegistered())
{
- $this->populateInstantResponseModal($questionGui, $_SESSION['forced_feedback_navigation_url']);
- unset($_SESSION['forced_feedback_navigation_url']);
+ $this->populateInstantResponseModal($questionGui, $this->getRegisteredForcedFeedbackNavUrl());
+ $this->unregisterForcedFeedbackNavUrl();
}
// fau.
@@ -633,6 +639,13 @@ public function saveQuestionSolution($authorized = true, $force = false)
{
// but only if the ending time is not reached
$q_id = $this->testSequence->getQuestionForSequence($_GET["sequence"]);
+
+ if( $this->isParticipantsAnswerFixed($q_id) )
+ {
+ // should only be reached by firebugging the disabled form in ui
+ throw new ilTestException('not allowed request');
+ }
+
if (is_numeric($q_id) && (int)$q_id)
{
$questionOBJ = $this->getQuestionInstance($q_id);
@@ -701,7 +714,7 @@ protected function showInstantResponseCmd()
if ($this->getNavigationUrlParameter())
{
$this->saveNavigationPreventConfirmation();
- $_SESSION['forced_feedback_navigation_url'] = $this->getNavigationUrlParameter();
+ $this->registerForcedFeedbackNavUrl($this->getNavigationUrlParameter());
}
// fau.
$this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
diff --git a/Modules/Test/classes/class.ilTestPlayerAbstractGUI.php b/Modules/Test/classes/class.ilTestPlayerAbstractGUI.php
index 3af7e874b63e..cab602872ede 100755
--- a/Modules/Test/classes/class.ilTestPlayerAbstractGUI.php
+++ b/Modules/Test/classes/class.ilTestPlayerAbstractGUI.php
@@ -337,15 +337,18 @@ private function buildPreviousButtonInstance($disabled)
return $button;
}
- protected function populateSpecificFeedbackBlock($question_gui)
+ protected function populateSpecificFeedbackBlock(assQuestionGUI $question_gui)
{
- $this->tpl->setCurrentBlock( "specific_feedback" );
- $this->tpl->setVariable( "SPECIFIC_FEEDBACK",
- $question_gui->getSpecificFeedbackOutput(
- $this->testSession->getActiveId(),
- NULL
- )
+ $solutionValues = $question_gui->object->getSolutionValues(
+ $this->testSession->getActiveId(), NULL
+ );
+
+ $feedback = $question_gui->getSpecificFeedbackOutput(
+ $question_gui->object->fetchIndexedValuesFromValuePairs($solutionValues)
);
+
+ $this->tpl->setCurrentBlock( "specific_feedback" );
+ $this->tpl->setVariable( "SPECIFIC_FEEDBACK", $feedback);
$this->tpl->parseCurrentBlock();
}
@@ -1215,7 +1218,7 @@ protected function showQuestionEditable(assQuestionGUI $questionGui, $formAction
$questionGui->getQuestionHeaderBlockBuilder()->setQuestionAnswered(true);
// fau.
}
- else
+ elseif( $this->object->isPostponingEnabled() )
{
$questionNavigationGUI->setSkipQuestionLinkTarget(
$this->ctrl->getLinkTarget($this, ilTestPlayerCommands::SKIP_QUESTION)
@@ -1879,17 +1882,17 @@ protected function handlePasswordProtectionRedirect()
protected function isParticipantsAnswerFixed($questionId)
{
- if( !$this->object->isInstantFeedbackAnswerFixationEnabled() )
+ if( $this->object->isInstantFeedbackAnswerFixationEnabled() && $this->testSequence->isQuestionChecked($questionId) )
{
- return false;
+ return true;
}
- if( !$this->testSequence->isQuestionChecked($questionId) )
+ if( $this->object->isFollowupQuestionAnswerFixationEnabled() && $this->testSequence->isNextQuestionPresented($questionId) )
{
- return false;
+ return true;
}
- return true;
+ return false;
}
/**
@@ -2465,6 +2468,11 @@ protected function saveNavigationPreventConfirmation()
{
$_SESSION['save_on_navigation_prevent_confirmation'] = true;
}
+
+ if( !empty($_POST[self::FOLLOWUP_QST_LOCKS_PREVENT_CONFIRMATION_PARAM]) )
+ {
+ $_SESSION[self::FOLLOWUP_QST_LOCKS_PREVENT_CONFIRMATION_PARAM] = true;
+ }
}
// fau.
@@ -2613,6 +2621,13 @@ protected function populateModals()
$this->populateNavWhenChangedModal();
// fau.
+ if( $this->object->isFollowupQuestionAnswerFixationEnabled() )
+ {
+ $this->populateNextLocksChangedModal();
+
+ $this->populateNextLocksUnchangedModal();
+ }
+
if( $this->object->getKioskMode() )
{
$this->tpl->addJavaScript(ilUIFramework::BOWER_BOOTSTRAP_JS, true);
@@ -2756,7 +2771,7 @@ protected function populateNavWhenChangedModal()
$tpl->setCurrentBlock('checkbox');
$tpl->setVariable('CONFIRMATION_CHECKBOX_NAME','save_on_navigation_prevent_confirmation');
- $tpl->setVariable('CONFIRMATION_CHECKBOX_LABEL',$this->lng->txt('save_on_navigation_prevent_confirmation'));
+ $tpl->setVariable('CONFIRMATION_CHECKBOX_LABEL',$this->lng->txt('tst_dont_show_msg_again_in_current_session'));
$tpl->parseCurrentBlock();
$modal = ilModalGUI::getInstance();
@@ -2769,7 +2784,80 @@ protected function populateNavWhenChangedModal()
$this->tpl->parseCurrentBlock();
}
// fau.
+
+ protected function populateNextLocksUnchangedModal()
+ {
+ require_once 'Modules/Test/classes/class.ilTestPlayerConfirmationModal.php';
+ $modal = new ilTestPlayerConfirmationModal();
+ $modal->setModalId('tst_next_locks_unchanged_modal');
+ $modal->setHeaderText($this->lng->txt('tst_nav_next_locks_empty_answer_header'));
+ $modal->setConfirmationText($this->lng->txt('tst_nav_next_locks_empty_answer_confirm'));
+
+ $button = $modal->buildModalButtonInstance('tst_nav_next_empty_answer_button');
+ $button->setCaption('tst_proceed');
+ $button->setPrimary(false);
+ $modal->addButton($button);
+
+ $button = $modal->buildModalButtonInstance('tst_cancel_next_empty_answer_button');
+ $button->setCaption('cancel');
+ $button->setPrimary(true);
+ $modal->addButton($button);
+
+ $this->tpl->setCurrentBlock('next_locks_unchanged_modal');
+ $this->tpl->setVariable('NEXT_LOCKS_UNCHANGED_MODAL', $modal->getHTML());
+ $this->tpl->parseCurrentBlock();
+ }
+
+ protected function populateNextLocksChangedModal()
+ {
+ if( $this->isFollowUpQuestionLocksConfirmationPrevented() )
+ {
+ return;
+ }
+
+ require_once 'Modules/Test/classes/class.ilTestPlayerConfirmationModal.php';
+ $modal = new ilTestPlayerConfirmationModal();
+ $modal->setModalId('tst_next_locks_changed_modal');
+
+ $modal->setHeaderText($this->lng->txt('tst_nav_next_locks_current_answer_header'));
+ $modal->setConfirmationText($this->lng->txt('tst_nav_next_locks_current_answer_confirm'));
+
+ $modal->setConfirmationCheckboxName(self::FOLLOWUP_QST_LOCKS_PREVENT_CONFIRMATION_PARAM);
+ $modal->setConfirmationCheckboxLabel($this->lng->txt('tst_dont_show_msg_again_in_current_session'));
+
+ $button = $modal->buildModalButtonInstance('tst_nav_next_changed_answer_button');
+ $button->setCaption('tst_save_and_proceed');
+ $button->setPrimary(true);
+ $modal->addButton($button);
+
+ $button = $modal->buildModalButtonInstance('tst_cancel_next_changed_answer_button');
+ $button->setCaption('cancel');
+ $button->setPrimary(false);
+ $modal->addButton($button);
+
+ $this->tpl->setCurrentBlock('next_locks_changed_modal');
+ $this->tpl->setVariable('NEXT_LOCKS_CHANGED_MODAL', $modal->getHTML());
+ $this->tpl->parseCurrentBlock();
+ }
+
+ const FOLLOWUP_QST_LOCKS_PREVENT_CONFIRMATION_PARAM = 'followup_qst_locks_prevent_confirmation';
+
+ protected function setFollowUpQuestionLocksConfirmationPrevented()
+ {
+ $_SESSION[self::FOLLOWUP_QST_LOCKS_PREVENT_CONFIRMATION_PARAM] = true;
+ }
+
+ protected function isFollowUpQuestionLocksConfirmationPrevented()
+ {
+ if( !isset($_SESSION[self::FOLLOWUP_QST_LOCKS_PREVENT_CONFIRMATION_PARAM]) )
+ {
+ return false;
+ }
+
+ return $_SESSION[self::FOLLOWUP_QST_LOCKS_PREVENT_CONFIRMATION_PARAM];
+ }
+
// fau: testNav - new function populateQuestionEditControl
/**
* Populate the navigation and saving control for editable questions
@@ -2818,7 +2906,8 @@ protected function populateQuestionEditControl($questionGUI)
// Forced feedback will change the navigation saving command
$config['forcedInstantFeedback'] = $this->object->isForceInstantFeedbackEnabled();
-
+ $config['nextQuestionLocks'] = $this->object->isFollowupQuestionAnswerFixationEnabled();
+
$this->tpl->addJavascript('./Modules/Test/js/ilTestPlayerQuestionEditControl.js');
$this->tpl->addOnLoadCode('il.TestPlayerQuestionEditControl.init('.json_encode($config).')');
}
@@ -2848,4 +2937,42 @@ protected function buildFixedShufflerSeed($questionId)
return $fixedSeed;
}
+
+ protected function registerForcedFeedbackNavUrl($forcedFeedbackNavUrl)
+ {
+ if( !isset($_SESSION['forced_feedback_navigation_url']) )
+ {
+ $_SESSION['forced_feedback_navigation_url'] = array();
+ }
+
+ $_SESSION['forced_feedback_navigation_url'][$this->testSession->getActiveId()] = $forcedFeedbackNavUrl;
+ }
+
+ protected function getRegisteredForcedFeedbackNavUrl()
+ {
+ if( !isset($_SESSION['forced_feedback_navigation_url']) )
+ {
+ return null;
+ }
+
+ if( !isset($_SESSION['forced_feedback_navigation_url'][$this->testSession->getActiveId()]) )
+ {
+ return null;
+ }
+
+ return $_SESSION['forced_feedback_navigation_url'][$this->testSession->getActiveId()];
+ }
+
+ protected function isForcedFeedbackNavUrlRegistered()
+ {
+ return !empty($this->getRegisteredForcedFeedbackNavUrl());
+ }
+
+ protected function unregisterForcedFeedbackNavUrl()
+ {
+ if( isset($_SESSION['forced_feedback_navigation_url'][$this->testSession->getActiveId()]) )
+ {
+ unset($_SESSION['forced_feedback_navigation_url'][$this->testSession->getActiveId()]);
+ }
+ }
}
diff --git a/Modules/Test/classes/class.ilTestPlayerConfirmationModal.php b/Modules/Test/classes/class.ilTestPlayerConfirmationModal.php
new file mode 100644
index 000000000000..b1c5d35847d4
--- /dev/null
+++ b/Modules/Test/classes/class.ilTestPlayerConfirmationModal.php
@@ -0,0 +1,229 @@
+
+ * @version $Id$
+ *
+ * @package Modules/Test(QuestionPool)
+ */
+class ilTestPlayerConfirmationModal
+{
+ /**
+ * @var string
+ */
+ protected $modalId = '';
+
+ /**
+ * @var string
+ */
+ protected $headerText = '';
+
+ /**
+ * @var string
+ */
+ protected $confirmationText = '';
+
+ /**
+ * @var string
+ */
+ protected $confirmationCheckboxName = '';
+
+ /**
+ * @var string
+ */
+ protected $confirmationCheckboxLabel = '';
+
+ /**
+ * @var ilLinkButton[]
+ */
+ protected $buttons = array();
+
+ /**
+ * @var ilHiddenInputGUI[]
+ */
+ protected $parameters = array();
+
+ /**
+ * @return string
+ */
+ public function getModalId()
+ {
+ return $this->modalId;
+ }
+
+ /**
+ * @param string $modalId
+ */
+ public function setModalId($modalId)
+ {
+ $this->modalId = $modalId;
+ }
+
+ /**
+ * @return string
+ */
+ public function getHeaderText()
+ {
+ return $this->headerText;
+ }
+
+ /**
+ * @param string $headerText
+ */
+ public function setHeaderText($headerText)
+ {
+ $this->headerText = $headerText;
+ }
+
+ /**
+ * @return string
+ */
+ public function getConfirmationText()
+ {
+ return $this->confirmationText;
+ }
+
+ /**
+ * @param string $confirmationText
+ */
+ public function setConfirmationText($confirmationText)
+ {
+ $this->confirmationText = $confirmationText;
+ }
+
+ /**
+ * @return string
+ */
+ public function getConfirmationCheckboxName()
+ {
+ return $this->confirmationCheckboxName;
+ }
+
+ /**
+ * @param string $confirmationCheckboxName
+ */
+ public function setConfirmationCheckboxName($confirmationCheckboxName)
+ {
+ $this->confirmationCheckboxName = $confirmationCheckboxName;
+ }
+
+ /**
+ * @return string
+ */
+ public function getConfirmationCheckboxLabel()
+ {
+ return $this->confirmationCheckboxLabel;
+ }
+
+ /**
+ * @param string $confirmationCheckboxLabel
+ */
+ public function setConfirmationCheckboxLabel($confirmationCheckboxLabel)
+ {
+ $this->confirmationCheckboxLabel = $confirmationCheckboxLabel;
+ }
+
+ /**
+ * @return ilLinkButton[]
+ */
+ public function getButtons()
+ {
+ return $this->buttons;
+ }
+
+ /**
+ * @param ilLinkButton $button
+ */
+ public function addButton(ilLinkButton $button)
+ {
+ $this->buttons[] = $button;
+ }
+
+ /**
+ * @return ilHiddenInputGUI[]
+ */
+ public function getParameters()
+ {
+ return $this->parameters;
+ }
+
+ /**
+ * @param ilHiddenInputGUI $hiddenInputGUI
+ */
+ public function addParameter(ilHiddenInputGUI $hiddenInputGUI)
+ {
+ $this->parameters[] = $hiddenInputGUI;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isConfirmationCheckboxRequired()
+ {
+ return strlen($this->getConfirmationCheckboxName()) && strlen($this->getConfirmationCheckboxLabel());
+ }
+
+ /**
+ * @return string
+ */
+ public function buildBody()
+ {
+ $tpl = new ilTemplate('tpl.tst_player_confirmation_modal.html', true, true, 'Modules/Test');
+
+ if( $this->isConfirmationCheckboxRequired() )
+ {
+ $tpl->setCurrentBlock('checkbox');
+ $tpl->setVariable('CONFIRMATION_CHECKBOX_NAME', $this->getConfirmationCheckboxName());
+ $tpl->setVariable('CONFIRMATION_CHECKBOX_LABEL', $this->getConfirmationCheckboxLabel());
+ $tpl->parseCurrentBlock();
+ }
+
+ foreach($this->getParameters() as $parameter)
+ {
+ $tpl->setCurrentBlock('hidden_inputs');
+ $tpl->setVariable('HIDDEN_INPUT', $parameter->getToolbarHTML());
+ $tpl->parseCurrentBlock();
+ }
+
+ foreach($this->getButtons() as $button)
+ {
+ $tpl->setCurrentBlock('buttons');
+ $tpl->setVariable('BUTTON', $button->render());
+ $tpl->parseCurrentBlock();
+ }
+
+ $tpl->setVariable('CONFIRMATION_TEXT', $this->getConfirmationText());
+
+ return $tpl->get();
+ }
+
+ /**
+ * @return string
+ */
+ public function getHTML()
+ {
+ $modal = ilModalGUI::getInstance();
+ $modal->setId($this->getModalId());
+ $modal->setHeading($this->getHeaderText());
+ $modal->setBody($this->buildBody());
+ return $modal->getHTML();
+ }
+
+ /**
+ * @param string $buttonId
+ * @return ilLinkButton
+ */
+ public function buildModalButtonInstance($buttonId)
+ {
+ $button = ilLinkButton::getInstance();
+
+ $button->setUrl('#');
+ $button->setId($buttonId);
+
+ return $button;
+ }
+}
\ No newline at end of file
diff --git a/Modules/Test/classes/class.ilTestPlayerDynamicQuestionSetGUI.php b/Modules/Test/classes/class.ilTestPlayerDynamicQuestionSetGUI.php
index fb794cc4899e..81b7d7f1a864 100755
--- a/Modules/Test/classes/class.ilTestPlayerDynamicQuestionSetGUI.php
+++ b/Modules/Test/classes/class.ilTestPlayerDynamicQuestionSetGUI.php
@@ -627,10 +627,10 @@ protected function showQuestionCmd()
}
// fau: testNav - add feedback modal
- if (!empty($_SESSION['forced_feedback_navigation_url']))
+ if ($this->isForcedFeedbackNavUrlRegistered())
{
- $this->populateInstantResponseModal($questionGui, $_SESSION['forced_feedback_navigation_url']);
- unset($_SESSION['forced_feedback_navigation_url']);
+ $this->populateInstantResponseModal($questionGui, $this->getRegisteredForcedFeedbackNavUrl());
+ $this->unregisterForcedFeedbackNavUrl();
}
// fau.
}
@@ -691,7 +691,7 @@ protected function showInstantResponseCmd()
if ($this->getNavigationUrlParameter())
{
$this->saveNavigationPreventConfirmation();
- $_SESSION['forced_feedback_navigation_url'] = $this->getNavigationUrlParameter();
+ $this->registerForcedFeedbackNavUrl($this->getNavigationUrlParameter());
}
// fau.
$this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
diff --git a/Modules/Test/classes/class.ilTestQuestionNavigationGUI.php b/Modules/Test/classes/class.ilTestQuestionNavigationGUI.php
index a7cc5b9f57b3..ec3337d92934 100644
--- a/Modules/Test/classes/class.ilTestQuestionNavigationGUI.php
+++ b/Modules/Test/classes/class.ilTestQuestionNavigationGUI.php
@@ -10,6 +10,8 @@
*/
class ilTestQuestionNavigationGUI
{
+ const SHOW_DISABLED_COMMANDS = false;
+
const CSS_CLASS_SUBMIT_BUTTONS = 'ilc_qsubmit_Submit';
/**
@@ -415,7 +417,7 @@ public function getActionsHTML()
$actions->addEntry($this->lng->txt('postpone_question'), $this->getSkipQuestionLinkTarget(),
'','','ilTestQuestionAction','tst_skip_question_action');
}
- else
+ elseif( self::SHOW_DISABLED_COMMANDS )
{
$actions->addEntry($this->lng->txt('postpone_question'), '#',
'','','ilTestQuestionAction disabled','tst_skip_question_action');
diff --git a/Modules/Test/classes/class.ilTestQuestionSideListGUI.php b/Modules/Test/classes/class.ilTestQuestionSideListGUI.php
index dbc9dad43390..5821934de0f1 100644
--- a/Modules/Test/classes/class.ilTestQuestionSideListGUI.php
+++ b/Modules/Test/classes/class.ilTestQuestionSideListGUI.php
@@ -178,8 +178,16 @@ private function renderList()
$row['worked_through'] ? 'answered'.$active : 'unanswered'.$active
);
- /*
- if( $this->isDisabled() )
+ if ($row['marked'])
+ {
+ $tpl->setCurrentBlock("mark_icon");
+ $tpl->setVariable("ICON_SRC", ilUtil::getImagePath('marked.svg'));
+ $tpl->setVariable("ICON_TEXT", $this->lng->txt('tst_question_marked'));
+ $tpl->setVariable("ICON_CLASS", 'ilTestMarkQuestionIcon');
+ $tpl->parseCurrentBlock();
+ }
+
+ if( $this->isDisabled() || $row['disabled'] )
{
$tpl->setCurrentBlock('disabled_entry');
$tpl->setVariable('CLASS', $class);
@@ -189,16 +197,7 @@ private function renderList()
}
else
{
- */
// fau: testNav - show mark icon in side list
- if ($row['marked'])
- {
- $tpl->setCurrentBlock("mark_icon");
- $tpl->setVariable("ICON_SRC", ilUtil::getImagePath('marked.svg'));
- $tpl->setVariable("ICON_TEXT", $this->lng->txt('tst_question_marked'));
- $tpl->setVariable("ICON_CLASS", 'ilTestMarkQuestionIcon');
- $tpl->parseCurrentBlock();
- }
// fau.
$tpl->setCurrentBlock('linked_entry');
$tpl->setVariable('HREF', $this->buildLink($row['sequence']));
@@ -208,9 +207,7 @@ private function renderList()
$tpl->setVariable('ITEM', $title);
$tpl->setVariable("DESCRIPTION", $description);
$tpl->parseCurrentBlock();
- /*
}
- */
$tpl->setCurrentBlock('item');
}
diff --git a/Modules/Test/classes/class.ilTestSequence.php b/Modules/Test/classes/class.ilTestSequence.php
index 4f25babdc2fe..a09f09c20cf9 100644
--- a/Modules/Test/classes/class.ilTestSequence.php
+++ b/Modules/Test/classes/class.ilTestSequence.php
@@ -49,6 +49,16 @@ class ilTestSequence implements ilTestQuestionSequence, ilTestSequenceSummaryPro
* @var boolean
*/
var $isRandomTest;
+
+ /**
+ * @var integer[]
+ */
+ protected $alreadyPresentedQuestions = array();
+
+ /**
+ * @var int
+ */
+ protected $newlyPresentedQuestion = 0;
/**
* @var array
@@ -160,6 +170,7 @@ public function loadQuestions(ilTestQuestionSetConfig $testQuestionSetConfig = n
public function loadFromDb()
{
$this->loadQuestionSequence();
+ $this->loadPresentedQuestions();
$this->loadCheckedQuestions();
$this->loadOptionalQuestions();
}
@@ -187,6 +198,21 @@ private function loadQuestionSequence()
}
}
+ protected function loadPresentedQuestions()
+ {
+ global $DIC; /* @var ILIAS\DI\Container $DIC */
+
+ $res = $DIC->database()->queryF(
+ "SELECT question_fi FROM tst_seq_qst_presented WHERE active_fi = %s AND pass = %s",
+ array('integer','integer'), array($this->active_id, $this->pass)
+ );
+
+ while( $row = $DIC->database()->fetchAssoc($res) )
+ {
+ $this->alreadyPresentedQuestions[ $row['question_fi'] ] = $row['question_fi'];
+ }
+ }
+
private function loadCheckedQuestions()
{
global $ilDB;
@@ -223,6 +249,7 @@ private function loadOptionalQuestions()
public function saveToDb()
{
$this->saveQuestionSequence();
+ $this->saveNewlyPresentedQuestion();
$this->saveNewlyCheckedQuestion();
$this->saveOptionalQuestions();
}
@@ -257,6 +284,20 @@ private function saveQuestionSequence()
'ans_opt_confirmed' => array('integer', (int)$this->isAnsweringOptionalQuestionsConfirmed())
));
}
+
+ protected function saveNewlyPresentedQuestion()
+ {
+ if( (int)$this->newlyPresentedQuestion )
+ {
+ global $DIC; /* @var ILIAS\DI\Container $DIC */
+
+ $DIC->database()->replace('tst_seq_qst_presented', array(
+ 'active_fi' => array('integer', (int)$this->active_id),
+ 'pass' => array('integer', (int)$this->pass),
+ 'question_fi' => array('integer', (int)$this->newlyPresentedQuestion)
+ ), array());
+ }
+ }
/**
* @global ilDBInterface $ilDB
@@ -393,6 +434,29 @@ function hideSequence($sequence)
}
}
+ public function setQuestionPresented($questionId)
+ {
+ $this->newlyPresentedQuestion = $questionId;
+ }
+
+ public function isQuestionPresented($questionId)
+ {
+ return (
+ $this->newlyPresentedQuestion == $questionId || in_array($questionId, $this->alreadyPresentedQuestions)
+ );
+ }
+
+ public function isNextQuestionPresented($questionId)
+ {
+ $nextQstId = $this->getQuestionForSequence(
+ $this->getNextSequence( $this->getSequenceForQuestion($questionId) )
+ );
+
+ return (
+ $this->newlyPresentedQuestion == $nextQstId || in_array($nextQstId, $this->alreadyPresentedQuestions)
+ );
+ }
+
public function setQuestionChecked($questionId)
{
$this->newlyCheckedQuestion = $questionId;
@@ -660,6 +724,7 @@ public function getSequenceSummary($obligationsFilterEnabled = false)
"nr" => "$key",
"title" => $question->getTitle(),
"qid" => $question->getId(),
+ "presented" => $this->isQuestionPresented($question->getId()),
"visited" => $worked_through,
"solved" => (($solved)?"1":"0"),
"description" => $question->getComment(),
diff --git a/Modules/Test/classes/class.ilTestService.php b/Modules/Test/classes/class.ilTestService.php
index 562c3faf23d6..647ae0dab81c 100755
--- a/Modules/Test/classes/class.ilTestService.php
+++ b/Modules/Test/classes/class.ilTestService.php
@@ -268,9 +268,15 @@ public function getQuestionSummaryData(ilTestSequenceSummaryProvider $testSequen
}
$data = array();
+ $firstQuestion = true;
foreach($result_array as $key => $value)
{
+ $disableLink = (
+ $this->object->isFollowupQuestionAnswerFixationEnabled()
+ && !$value['presented'] && !$firstQuestion
+ );
+
$description = "";
if($this->object->getListOfQuestionsDescription())
{
@@ -297,7 +303,21 @@ public function getQuestionSummaryData(ilTestSequenceSummaryProvider $testSequen
}
// fau: testNav - add number parameter for getQuestionTitle()
- $data[] = array('order' => $value["nr"], 'title' => $this->object->getQuestionTitle($value["title"], $value["nr"]), 'description' => $description, 'worked_through' => $value["worked_through"], 'postponed' => $value["postponed"], 'points' => $points, 'marked' => $marked, 'sequence' => $value["sequence"], 'obligatory' => $value['obligatory'], 'isAnswered' => $value['isAnswered']);
+ $data[] = array(
+ 'order' => $value["nr"],
+ 'title' => $this->object->getQuestionTitle($value["title"], $value["nr"]),
+ 'description' => $description,
+ 'disabled' => $disableLink,
+ 'worked_through' => $value["worked_through"],
+ 'postponed' => $value["postponed"],
+ 'points' => $points,
+ 'marked' => $marked,
+ 'sequence' => $value["sequence"],
+ 'obligatory' => $value['obligatory'],
+ 'isAnswered' => $value['isAnswered']
+ );
+
+ $firstQuestion = false;
// fau.
}
diff --git a/Modules/Test/classes/class.ilTestServiceGUI.php b/Modules/Test/classes/class.ilTestServiceGUI.php
index 09db2720e65b..d0be6e37f663 100755
--- a/Modules/Test/classes/class.ilTestServiceGUI.php
+++ b/Modules/Test/classes/class.ilTestServiceGUI.php
@@ -756,7 +756,11 @@ function getCorrectSolutionOutput($question_id, $active_id, $pass, ilTestQuestio
$best_output = $question_gui->getSolutionOutput($active_id, $pass, FALSE, FALSE, $show_question_only, FALSE, TRUE, FALSE, FALSE);
if( $this->object->getShowSolutionFeedback() && $_GET['cmd'] != 'outCorrectSolution' )
{
- $specificAnswerFeedback = $question_gui->getSpecificFeedbackOutput($active_id, $pass);
+ $specificAnswerFeedback = $question_gui->getSpecificFeedbackOutput(
+ $question_gui->object->fetchIndexedValuesFromValuePairs(
+ $question_gui->object->getSolutionValues($active_id, $pass)
+ )
+ );
if( strlen($specificAnswerFeedback) )
{
$template->setCurrentBlock("outline_specific_feedback");
diff --git a/Modules/Test/classes/class.ilTestSettingsTemplateConfig.php b/Modules/Test/classes/class.ilTestSettingsTemplateConfig.php
index f30f3dc12141..1e45a3708074 100644
--- a/Modules/Test/classes/class.ilTestSettingsTemplateConfig.php
+++ b/Modules/Test/classes/class.ilTestSettingsTemplateConfig.php
@@ -226,7 +226,7 @@ private function addQuestionBehaviourProperties()
);
$this->addSetting(
- "instant_feedback",
+ "instant_feedback_contents",
ilSettingsTemplateConfig::CHECKBOX,
$this->lng->txt("tst_instant_feedback"),
true,
@@ -235,22 +235,33 @@ private function addQuestionBehaviourProperties()
'instant_feedback_points' => $this->lng->txt("tst_instant_feedback_results"),
'instant_feedback_generic' => $this->lng->txt("tst_instant_feedback_answer_generic"),
'instant_feedback_specific' => $this->lng->txt("tst_instant_feedback_answer_specific"),
- 'instant_feedback_solution' => $this->lng->txt("tst_instant_feedback_solution"),
- 'force_instant_feedback' => $this->lng->txt("tst_instant_feedback_forced")
+ 'instant_feedback_solution' => $this->lng->txt("tst_instant_feedback_solution")
)
);
$this->addSetting(
- 'instant_feedback_handling',
+ "instant_feedback_trigger",
ilSettingsTemplateConfig::SELECT,
- $this->lng->txt('tst_instant_feedback_handling'),
+ $this->lng->txt("tst_instant_feedback_trigger"),
true,
- ilObjTestSettingsGeneralGUI::INST_FB_HANDLING_OPT_NONE,
+ 0,
+ array(
+ ilObjTestSettingsGeneralGUI::INSTANT_FEEDBACK_TRIGGER_MANUAL => $this->lng->txt("tst_instant_feedback_trigger_manual"),
+ ilObjTestSettingsGeneralGUI::INSTANT_FEEDBACK_TRIGGER_FORCED => $this->lng->txt("tst_instant_feedback_trigger_forced")
+ )
+ );
+
+ $this->addSetting(
+ 'answer_fixation_handling',
+ ilSettingsTemplateConfig::SELECT,
+ $this->lng->txt('tst_answer_fixation_handling'),
+ true,
+ 0,
array(
- ilObjTestSettingsGeneralGUI::INST_FB_HANDLING_OPT_NONE => $this->lng->txt('tst_instant_feedback_handling_none'),
- ilObjTestSettingsGeneralGUI::INST_FB_HANDLING_OPT_FREEZE => $this->lng->txt('tst_instant_feedback_handling_freeze'),
- ilObjTestSettingsGeneralGUI::INST_FB_HANDLING_OPT_FORCE_AND_FREEZE => $this->lng->txt('tst_instant_feedback_handling_force_and_freeze'),
- ilObjTestSettingsGeneralGUI::INST_FB_HANDLING_OPT_FORCE => $this->lng->txt('tst_instant_feedback_handling_force'),
+ ilObjTestSettingsGeneralGUI::ANSWER_FIXATION_NONE => $this->lng->txt('tst_answer_fixation_none'),
+ ilObjTestSettingsGeneralGUI::ANSWER_FIXATION_ON_INSTANT_FEEDBACK => $this->lng->txt('tst_answer_fixation_on_instant_feedback'),
+ ilObjTestSettingsGeneralGUI::ANSWER_FIXATION_ON_FOLLOWUP_QUESTION => $this->lng->txt('tst_answer_fixation_on_followup_question'),
+ ilObjTestSettingsGeneralGUI::ANSWER_FIXATION_ON_IFB_OR_FUQST => $this->lng->txt('tst_answer_fixation_on_instantfb_or_followupqst')
)
);
diff --git a/Modules/Test/classes/tables/class.ilListOfQuestionsTableGUI.php b/Modules/Test/classes/tables/class.ilListOfQuestionsTableGUI.php
index bd2c417feb8c..14fbae8a65f6 100644
--- a/Modules/Test/classes/tables/class.ilListOfQuestionsTableGUI.php
+++ b/Modules/Test/classes/tables/class.ilListOfQuestionsTableGUI.php
@@ -172,17 +172,29 @@ public function fillRow($data)
$this->tpl->setVariable("QUESTION_OBLIGATORY", $OBLIGATORY);
}
- $this->ctrl->setParameter($this->parent_obj, 'sequence', $data['sequence']);
- $this->ctrl->setParameter($this->parent_obj, 'pmode', '');
- $href = $this->ctrl->getLinkTarget($this->parent_obj, ilTestPlayerCommands::SHOW_QUESTION);
-
$postponed = (
$data['postponed'] ? $this->lng->txt('postponed') : ''
);
+ if( $data['disabled'] )
+ {
+ $this->tpl->setCurrentBlock('static_title');
+ $this->tpl->setVariable("STATIC_TITLE", ilUtil::prepareFormOutput($data['title']));
+ $this->tpl->parseCurrentBlock();
+ }
+ else
+ {
+ $this->ctrl->setParameter($this->parent_obj, 'sequence', $data['sequence']);
+ $this->ctrl->setParameter($this->parent_obj, 'pmode', '');
+ $href = $this->ctrl->getLinkTarget($this->parent_obj, ilTestPlayerCommands::SHOW_QUESTION);
+
+ $this->tpl->setCurrentBlock('linked_title');
+ $this->tpl->setVariable("LINKED_TITLE", ilUtil::prepareFormOutput($data['title']));
+ $this->tpl->setVariable("HREF", $href);
+ $this->tpl->parseCurrentBlock();
+ }
+
$this->tpl->setVariable("ORDER", $data['order']);
- $this->tpl->setVariable("TITLE", ilUtil::prepareFormOutput($data['title']));
- $this->tpl->setVariable("HREF", $href);
$this->tpl->setVariable("POSTPONED", $postponed);
if ($data["worked_through"])
{
diff --git a/Modules/Test/js/ilTestPlayerQuestionEditControl.js b/Modules/Test/js/ilTestPlayerQuestionEditControl.js
index 354a8a0ab8c5..b12bf1bceaa2 100644
--- a/Modules/Test/js/ilTestPlayerQuestionEditControl.js
+++ b/Modules/Test/js/ilTestPlayerQuestionEditControl.js
@@ -43,7 +43,8 @@ il.TestPlayerQuestionEditControl = new function() {
withFormChangeDetection: true, // form changes should be detected
withBackgroundChangeDetection: false, // background changes should be polled from ILIAS
backgroundDetectorUrl: '', // url called by the background detector
- forcedInstantFeedback: false // forced feedback will change the submit command
+ forcedInstantFeedback: false, // forced feedback will change the submit command
+ nextQuestionLocks: false
};
/**
@@ -134,6 +135,17 @@ il.TestPlayerQuestionEditControl = new function() {
// the final action is done by a submit button in the modal
$('#tst_discard_solution_action').click(showDiscardSolutionModal);
$('#tst_cancel_discard_button').click(hideDiscardSolutionModal);
+
+ if( config.nextQuestionLocks )
+ {
+ // handle the buttons in next locks current answer confirmation modal
+ $('#tst_nav_next_changed_answer_button').click(saveWithNavigation);
+ $('#tst_cancel_next_changed_answer_button').click(hideFollowupQuestionLocksCurrentAnswerModal);
+
+ // handle the buttons in next locks empty answer confirmation modal
+ $('#tst_nav_next_empty_answer_button').click(saveWithNavigation);
+ $('#tst_cancel_next_empty_answer_button').click(hideFollowupQuestionLocksEmptyAnswerModal);
+ }
// the checkbox 'use unchanged answer' is only needed for initial empty answers
// it exists for few question types only
@@ -372,7 +384,30 @@ il.TestPlayerQuestionEditControl = new function() {
toggleQuestionMark();
return false;
}
- else if (answerChanged // answer has been changed
+ else if( config.nextQuestionLocks && $(this).attr('data-nextcmd') == 'nextQuestion' )
+ {
+ // remember the url for saveWithNavigation()
+ navUrl = href;
+
+ if( !answerChanged && !answered )
+ {
+ console.log('rubbel die katz x 2');
+
+ showFollowupQuestionLocksEmptyAnswerModal();
+ }
+ else if( $('#tst_next_locks_changed_modal').length > 0 )
+ {
+ showFollowupQuestionLocksCurrentAnswerModal();
+ }
+ else
+ {
+ saveWithNavigation();
+ }
+
+ return false; // prevent the default event handler
+ }
+
+ if (answerChanged // answer has been changed
&& href // link is not an anchor
&& href.charAt(0) != '#' // link is not a fragment
&& id != 'tst_discard_answer_action' // link is not the 'discard answer' button
@@ -430,6 +465,28 @@ il.TestPlayerQuestionEditControl = new function() {
function hideDiscardSolutionModal() {
$('#tst_discard_solution_modal').modal('hide');
}
+
+ function showFollowupQuestionLocksCurrentAnswerModal()
+ {
+ $('#tst_next_locks_changed_modal').modal('show');
+ $('#followup_qst_locks_prevent_confirmation').attr('checked',false);
+ }
+
+ function hideFollowupQuestionLocksCurrentAnswerModal()
+ {
+ $('#tst_next_locks_changed_modal').modal('hide');
+ }
+
+ function showFollowupQuestionLocksEmptyAnswerModal()
+ {
+ console.log($('#tst_next_locks_unchanged_modal'));
+ $('#tst_next_locks_unchanged_modal').modal('show');
+ }
+
+ function hideFollowupQuestionLocksEmptyAnswerModal()
+ {
+ $('#tst_next_locks_unchanged_modal').modal('hide');
+ }
/**
* Disable and uncheck the 'use unchanged answer' checkbox
diff --git a/Modules/Test/templates/default/tpl.il_as_tst_list_of_questions_row.html b/Modules/Test/templates/default/tpl.il_as_tst_list_of_questions_row.html
index 0be2a8ce73d8..f5058359014b 100644
--- a/Modules/Test/templates/default/tpl.il_as_tst_list_of_questions_row.html
+++ b/Modules/Test/templates/default/tpl.il_as_tst_list_of_questions_row.html
@@ -1,6 +1,10 @@
| {ORDER} |
- {TITLE} ({DESCRIPTION}) |
+
+ {STATIC_TITLE}
+ {LINKED_TITLE}
+ ({DESCRIPTION})
+ |
{QUESTION_OBLIGATORY} |
diff --git a/Modules/Test/templates/default/tpl.il_as_tst_output.html b/Modules/Test/templates/default/tpl.il_as_tst_output.html
index 6630df4603df..831f219e3752 100755
--- a/Modules/Test/templates/default/tpl.il_as_tst_output.html
+++ b/Modules/Test/templates/default/tpl.il_as_tst_output.html
@@ -33,6 +33,8 @@
{QUESTION_OUTPUT}
{DISCARD_SOLUTION_MODAL}
{NAV_WHILE_EDIT_MODAL}
+ {NEXT_LOCKS_CHANGED_MODAL}
+ {NEXT_LOCKS_UNCHANGED_MODAL}
id="{INSTANT_RESPONSE_FOCUS_ID}">
{INSTANT_RESPONSE_HEADER}
diff --git a/Modules/Test/templates/default/tpl.tst_player_response_modal.html b/Modules/Test/templates/default/tpl.tst_player_response_modal.html
index 81b8b34c13c6..bcf851189017 100644
--- a/Modules/Test/templates/default/tpl.tst_player_response_modal.html
+++ b/Modules/Test/templates/default/tpl.tst_player_response_modal.html
@@ -1,8 +1,8 @@
{QUESTION_OUTPUT}
-
-
-
+
+ id="{INSTANT_RESPONSE_FOCUS_ID}">
{INSTANT_RESPONSE_HEADER}
+
{RECEIVED_POINTS_INFORMATION}
diff --git a/Modules/TestQuestionPool/classes/class.assClozeGap.php b/Modules/TestQuestionPool/classes/class.assClozeGap.php
index afcdc44ba03b..e7aacf28bffb 100755
--- a/Modules/TestQuestionPool/classes/class.assClozeGap.php
+++ b/Modules/TestQuestionPool/classes/class.assClozeGap.php
@@ -17,7 +17,10 @@
*/
class assClozeGap
{
-
+ const TYPE_TEXT = 0;
+ const TYPE_SELECT = 1;
+ const TYPE_NUMERIC = 2;
+
/**
* Type of gap
*
@@ -89,7 +92,7 @@ public function setType($a_type = 0)
* Gets the items of a cloze gap
*
* @param ilArrayElementShuffler $shuffler
- * @return array The list of items
+ * @return assAnswerCloze[] The list of items
*/
public function getItems(ilArrayElementShuffler $shuffler)
{
@@ -252,16 +255,17 @@ function setItemUpperBound($order, $bound)
}
}
}
-
-/**
-* Gets the item with a given index
-*
-* Gets the item with a given index
-*
-* @param integer $a_index Item index
-* @access public
-* @see $items
-*/
+
+ /**
+ * Gets the item with a given index
+ *
+ * Gets the item with a given index
+ *
+ * @param integer $a_index Item index
+ * @access public
+ * @see $items
+ * @return assAnswerCloze|null
+ */
function getItem($a_index)
{
if (array_key_exists($a_index, $this->items))
@@ -431,4 +435,27 @@ public function getGapSize()
{
return $this->gap_size;
}
+
+ public function numericRangeExists()
+ {
+ if($this->getType() != CLOZE_NUMERIC)
+ {
+ return false;
+ }
+
+ require_once 'Services/Math/classes/class.EvalMath.php';
+ $math = new EvalMath();
+
+ $item = $this->getItem(0);
+ $lowerBound = $math->evaluate($item->getLowerBound());
+ $upperBound = $math->evaluate($item->getUpperBound());
+ $preciseValue = $math->evaluate($item->getAnswertext());
+
+ if( $lowerBound < $preciseValue || $upperBound > $preciseValue)
+ {
+ return true;
+ }
+
+ return false;
+ }
}
\ No newline at end of file
diff --git a/Modules/TestQuestionPool/classes/class.assClozeTest.php b/Modules/TestQuestionPool/classes/class.assClozeTest.php
index 0970f266d8f2..b78470e507e6 100755
--- a/Modules/TestQuestionPool/classes/class.assClozeTest.php
+++ b/Modules/TestQuestionPool/classes/class.assClozeTest.php
@@ -8,6 +8,7 @@
require_once './Modules/TestQuestionPool/interfaces/interface.ilObjAnswerScoringAdjustable.php';
require_once './Modules/TestQuestionPool/interfaces/interface.iQuestionCondition.php';
require_once './Modules/TestQuestionPool/classes/class.ilUserQuestionResult.php';
+require_once 'Modules/TestQuestionPool/classes/feedback/class.ilAssClozeTestFeedback.php';
/**
* Class for cloze tests
@@ -92,6 +93,13 @@ class assClozeTest extends assQuestion implements ilObjQuestionScoringAdjustable
var $fixedTextLength;
public $cloze_text;
+
+ /**
+ * @var ilAssClozeTestFeedback
+ */
+ public $feedbackOBJ;
+
+ protected $feedbackMode = ilAssClozeTestFeedback::FB_MODE_GAP_QUESTION;
/**
* assClozeTest constructor
@@ -187,6 +195,7 @@ public function loadFromDb($question_id)
$this->setClozeText($data['cloze_text']);
$this->setFixedTextLength($data["fixed_textlen"]);
$this->setIdenticalScoring(($data['tstamp'] == 0) ? true : $data["identical_scoring"]);
+ $this->setFeedbackMode($data['feedback_mode'] === null ? ilAssClozeTestFeedback::FB_MODE_GAP_QUESTION : $data['feedback_mode']);
// replacement of old syntax with new syntax
include_once("./Services/RTE/classes/class.ilRTE.php");
$this->question = ilRTE::_replaceMediaObjectImageSrc($this->question, 1);
@@ -317,30 +326,22 @@ public function saveAnswerSpecificDataToDb()
*/
public function saveAdditionalQuestionDataToDb()
{
- global $ilDB;
-
- $ilDB->manipulateF( "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
+ global $DIC; /* @var ILIAS\DI\Container $DIC */
+
+
+ $DIC->database()->manipulateF( "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
array( "integer" ),
array( $this->getId() )
);
-
- $ilDB->manipulateF( "INSERT INTO " . $this->getAdditionalTableName()
- . " (question_fi, textgap_rating, identical_scoring, fixed_textlen, cloze_text) VALUES (%s, %s, %s, %s, %s)",
- array(
- "integer",
- "text",
- "text",
- "integer",
- "text"
- ),
- array(
- $this->getId(),
- $this->getTextgapRating(),
- $this->getIdenticalScoring(),
- $this->getFixedTextLength() ? $this->getFixedTextLength() : NULL,
- ilRTE::_replaceMediaObjectImageSrc($this->getClozeText(), 0)
- )
- );
+
+ $DIC->database()->insert($this->getAdditionalTableName(), array(
+ 'question_fi' => array('integer', $this->getId()),
+ 'textgap_rating' => array('text', $this->getTextgapRating()),
+ 'identical_scoring' => array('text', $this->getIdenticalScoring()),
+ 'fixed_textlen' => array('integer', $this->getFixedTextLength() ? $this->getFixedTextLength() : NULL),
+ 'cloze_text' => array('text', ilRTE::_replaceMediaObjectImageSrc($this->getClozeText(), 0)),
+ 'feedback_mode' => array('text', $this->getFeedbackMode())
+ ));
}
/**
@@ -594,6 +595,22 @@ function setEndTag($end_tag = "[/gap]")
{
$this->end_tag = $end_tag;
}
+
+ /**
+ * @return string
+ */
+ public function getFeedbackMode()
+ {
+ return $this->feedbackMode;
+ }
+
+ /**
+ * @param string $feedbackMode
+ */
+ public function setFeedbackMode($feedbackMode)
+ {
+ $this->feedbackMode = $feedbackMode;
+ }
/**
* Create gap entries by parsing the question text
@@ -2022,4 +2039,20 @@ public function calculateReachedPointsFromPreviewSession(ilAssQuestionPreviewSes
return $this->calculateReachedPointsForSolution($userSolution);
}
+
+ public function fetchAnswerValueForGap($userSolution, $gapIndex)
+ {
+ $answerValue = '';
+
+ foreach($userSolution as $value1 => $value2)
+ {
+ if ($value1 == $gapIndex)
+ {
+ $answerValue = $value2;
+ break;
+ }
+ }
+
+ return $answerValue;
+ }
}
\ No newline at end of file
diff --git a/Modules/TestQuestionPool/classes/class.assClozeTestGUI.php b/Modules/TestQuestionPool/classes/class.assClozeTestGUI.php
index da0ba9f60632..4f372e5535be 100755
--- a/Modules/TestQuestionPool/classes/class.assClozeTestGUI.php
+++ b/Modules/TestQuestionPool/classes/class.assClozeTestGUI.php
@@ -1200,7 +1200,9 @@ function getSolutionOutput(
$feedback .= strlen($fb) ? $fb : '';
}
- $fb = $this->getSpecificFeedbackOutput($active_id, $pass);
+ $fb = $this->getSpecificFeedbackOutput(
+ $this->object->fetchIndexedValuesFromValuePairs($user_solution)
+ );
$feedback .= strlen($fb) ? $fb : '';
}
if (strlen($feedback))
@@ -1235,9 +1237,13 @@ function getSolutionOutput(
protected function getBestSolutionText($gap, $gap_index, $gap_combinations)
{
$combination = null;
- if(is_array($gap_combinations) && array_key_exists($gap_index, $gap_combinations))
+ foreach((array)$gap_combinations as $combiGapSolRow)
{
- $combination = $gap_combinations[$gap_index];
+ if($combiGapSolRow['gap_fi'] == $gap_index && $combiGapSolRow['best_solution'])
+ {
+ $combination = $combiGapSolRow;
+ break;
+ }
}
$best_solution_text = ilUtil::prepareFormOutput($gap->getBestSolutionOutput(
$this->object->getShuffler(), $combination
@@ -1467,27 +1473,27 @@ public function setQuestionTabs()
$this->addBackTab($ilTabs);
}
- function getSpecificFeedbackOutput($active_id, $pass)
+ function getSpecificFeedbackOutput($userSolution)
{
- if( !$this->object->feedbackOBJ->specificAnswerFeedbackExists(array_values($this->object->gaps)) )
+ if( !$this->object->feedbackOBJ->specificAnswerFeedbackExists() )
{
return '';
}
-
+
global $lng;
$feedback = '';
- foreach ($this->object->gaps as $index => $answer)
+ foreach ($this->object->gaps as $gapIndex => $gap)
{
- $caption = $lng->txt('gap').' '.($index+1) .': ';
-
+ $answerValue = $this->object->fetchAnswerValueForGap($userSolution, $gapIndex);
+ $answerIndex = $this->object->feedbackOBJ->determineAnswerIndexForAnswerValue($gap, $answerValue);
+ $fb = $this->object->feedbackOBJ->determineTestOutputGapFeedback($gapIndex, $answerIndex);
+
+ $caption = $lng->txt('gap').' '.($gapIndex+1) .': ';
$feedback .= '| ';
-
$feedback .= $caption .' | ';
- $feedback .= $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
- $this->object->getId(), $index
- ) . ' |
';
+ $feedback .= $fb . ' ';
}
$feedback .= '
';
@@ -1653,7 +1659,7 @@ public function removeIndizesFromGapText( $question_text )
*/
private function populateSolutiontextToGapTpl($gaptemplate, $gap, $solutiontext)
{
- if( $this->renderPurposeSupportsFormHtml() )
+ if( $this->renderPurposeSupportsFormHtml() || $this->isRenderPurposePrintPdf() )
{
$gaptemplate->setCurrentBlock('gap_span');
$gaptemplate->setVariable('SPAN_SOLUTION', $solutiontext);
diff --git a/Modules/TestQuestionPool/classes/class.assErrorTextGUI.php b/Modules/TestQuestionPool/classes/class.assErrorTextGUI.php
index 5ce2822cf7e8..da77c85072d5 100644
--- a/Modules/TestQuestionPool/classes/class.assErrorTextGUI.php
+++ b/Modules/TestQuestionPool/classes/class.assErrorTextGUI.php
@@ -286,7 +286,7 @@ function getSolutionOutput(
$feedback .= strlen($fb) ? $fb : '';
}
- $fb = $this->getSpecificFeedbackOutput($active_id, $pass);
+ $fb = $this->getSpecificFeedbackOutput(array());
$feedback .= strlen($fb) ? $fb : '';
}
if (strlen($feedback))
@@ -455,11 +455,11 @@ function setQuestionTabs()
$this->addBackTab($ilTabs);
}
- function getSpecificFeedbackOutput($active_id, $pass)
+ function getSpecificFeedbackOutput($userSolution)
{
$selection = $this->object->getBestSelection(false);
- if( !$this->object->feedbackOBJ->specificAnswerFeedbackExists(array_keys($selection)) )
+ if( !$this->object->feedbackOBJ->specificAnswerFeedbackExists() )
{
return '';
}
@@ -502,7 +502,7 @@ function getSpecificFeedbackOutput($active_id, $pass)
if ( preg_match('/'.preg_quote($ans->text_wrong, '/').'/', $element) )
{
$fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
- $this->object->getId(), $idx
+ $this->object->getId(), 0, $idx
);
$feedback .= ''. $fb . ' | ';
diff --git a/Modules/TestQuestionPool/classes/class.assFileUploadGUI.php b/Modules/TestQuestionPool/classes/class.assFileUploadGUI.php
index d7ff777f3310..ae466d95247f 100644
--- a/Modules/TestQuestionPool/classes/class.assFileUploadGUI.php
+++ b/Modules/TestQuestionPool/classes/class.assFileUploadGUI.php
@@ -520,7 +520,7 @@ function setQuestionTabs()
}
}
- function getSpecificFeedbackOutput($active_id, $pass)
+ function getSpecificFeedbackOutput($userSolution)
{
$output = "";
return $this->object->prepareTextareaOutput($output, TRUE);
diff --git a/Modules/TestQuestionPool/classes/class.assFlashQuestionGUI.php b/Modules/TestQuestionPool/classes/class.assFlashQuestionGUI.php
index 87bd6d55c264..e4eb86658c26 100644
--- a/Modules/TestQuestionPool/classes/class.assFlashQuestionGUI.php
+++ b/Modules/TestQuestionPool/classes/class.assFlashQuestionGUI.php
@@ -502,7 +502,7 @@ function setQuestionTabs()
$this->addBackTab($ilTabs);
}
- function getSpecificFeedbackOutput($active_id, $pass)
+ function getSpecificFeedbackOutput($userSolution)
{
$output = "";
return $this->object->prepareTextareaOutput($output, TRUE);
diff --git a/Modules/TestQuestionPool/classes/class.assFormulaQuestionGUI.php b/Modules/TestQuestionPool/classes/class.assFormulaQuestionGUI.php
index bd56b200242d..b770651b6e87 100755
--- a/Modules/TestQuestionPool/classes/class.assFormulaQuestionGUI.php
+++ b/Modules/TestQuestionPool/classes/class.assFormulaQuestionGUI.php
@@ -1232,7 +1232,7 @@ function getTestOutput($active_id, $pass, $is_postponed = FALSE, $use_post_solut
return $pageoutput;
}
- public function getSpecificFeedbackOutput($active_id, $pass)
+ public function getSpecificFeedbackOutput($userSolution)
{
return '';
}
diff --git a/Modules/TestQuestionPool/classes/class.assImagemapQuestion.php b/Modules/TestQuestionPool/classes/class.assImagemapQuestion.php
index 7d860679b571..298d3e7b7562 100755
--- a/Modules/TestQuestionPool/classes/class.assImagemapQuestion.php
+++ b/Modules/TestQuestionPool/classes/class.assImagemapQuestion.php
@@ -883,7 +883,7 @@ function getRTETextWithMediaObjects()
$text = parent::getRTETextWithMediaObjects();
foreach ($this->answers as $index => $answer)
{
- $text .= $this->feedbackOBJ->getSpecificAnswerFeedbackContent($this->getId(), $index);
+ $text .= $this->feedbackOBJ->getSpecificAnswerFeedbackContent($this->getId(),0, $index);
}
return $text;
}
@@ -960,7 +960,7 @@ public function toJSON()
"state" => $answer_obj->getState(),
"area" => $answer_obj->getArea(),
"feedback" => $this->formatSAQuestion(
- $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(), $key)
+ $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(),0, $key)
)
));
$order++;
diff --git a/Modules/TestQuestionPool/classes/class.assImagemapQuestionGUI.php b/Modules/TestQuestionPool/classes/class.assImagemapQuestionGUI.php
index 6e4c38287667..01713ee2226f 100755
--- a/Modules/TestQuestionPool/classes/class.assImagemapQuestionGUI.php
+++ b/Modules/TestQuestionPool/classes/class.assImagemapQuestionGUI.php
@@ -583,7 +583,7 @@ function getSolutionOutput(
if ($show_feedback)
{
$fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
- $this->object->getId(), $solution_id
+ $this->object->getId(),0, $solution_id
);
if (strlen($fb))
@@ -755,7 +755,7 @@ function getTestOutput($active_id, $pass, $is_postponed = FALSE, $use_post_solut
if(!$this->object->getIsMultipleChoice() && count($userSelection) && current($userSelection) == $answer_id)
{
$feedback = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
- $this->object->getId(), $answer_id
+ $this->object->getId(),0, $answer_id
);
if (strlen($feedback))
{
@@ -920,9 +920,9 @@ public function setQuestionTabs()
$this->addBackTab($ilTabs);
}
- function getSpecificFeedbackOutput($active_id, $pass)
+ function getSpecificFeedbackOutput($userSolution)
{
- if( !$this->object->feedbackOBJ->specificAnswerFeedbackExists(array_values($this->object->getAnswers())) )
+ if( !$this->object->feedbackOBJ->specificAnswerFeedbackExists() )
{
return '';
}
@@ -932,7 +932,7 @@ function getSpecificFeedbackOutput($active_id, $pass)
foreach($this->object->getAnswers() as $idx => $answer)
{
$feedback = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
- $this->object->getId(), $idx
+ $this->object->getId(),0, $idx
);
$output .= "
| {$answer->getAnswerText()} | {$feedback} |
";
diff --git a/Modules/TestQuestionPool/classes/class.assJavaAppletGUI.php b/Modules/TestQuestionPool/classes/class.assJavaAppletGUI.php
index 448ae7b658e2..8a353c6c119a 100755
--- a/Modules/TestQuestionPool/classes/class.assJavaAppletGUI.php
+++ b/Modules/TestQuestionPool/classes/class.assJavaAppletGUI.php
@@ -744,7 +744,7 @@ function setQuestionTabs()
$this->addBackTab($ilTabs);
}
- function getSpecificFeedbackOutput($active_id, $pass)
+ function getSpecificFeedbackOutput($userSolution)
{
$output = "";
return $this->object->prepareTextareaOutput($output, TRUE);
diff --git a/Modules/TestQuestionPool/classes/class.assKprimChoice.php b/Modules/TestQuestionPool/classes/class.assKprimChoice.php
index b65802cfcff6..4610797b1899 100644
--- a/Modules/TestQuestionPool/classes/class.assKprimChoice.php
+++ b/Modules/TestQuestionPool/classes/class.assKprimChoice.php
@@ -1011,7 +1011,7 @@ public function toJSON()
'order' => (int)$answer->getPosition(),
'image' => (string)$answer->getImageFile(),
'feedback' => $this->formatSAQuestion(
- $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(), $key)
+ $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(),0, $key)
)
);
}
diff --git a/Modules/TestQuestionPool/classes/class.assKprimChoiceGUI.php b/Modules/TestQuestionPool/classes/class.assKprimChoiceGUI.php
index 728ac0e91ba9..023fd97f5640 100644
--- a/Modules/TestQuestionPool/classes/class.assKprimChoiceGUI.php
+++ b/Modules/TestQuestionPool/classes/class.assKprimChoiceGUI.php
@@ -341,7 +341,7 @@ private function handleAnswerTextsSubmit($answers)
* @param integer $pass
* @return string
*/
- function getSpecificFeedbackOutput($active_id, $pass)
+ function getSpecificFeedbackOutput($userSolution)
{
return ''; // question type supports inline answer specific feedback
}
@@ -792,7 +792,7 @@ private function populateSpecificFeedbackInline($user_solution, $answer_id, $tem
{
if($user_solution[$answer_id])
{
- $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), $answer_id);
+ $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(),0, $answer_id);
if(strlen($fb))
{
$template->setCurrentBlock("feedback");
@@ -804,7 +804,7 @@ private function populateSpecificFeedbackInline($user_solution, $answer_id, $tem
if($this->object->getSpecificFeedbackSetting() == ilAssConfigurableMultiOptionQuestionFeedback::FEEDBACK_SETTING_ALL)
{
- $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), $answer_id);
+ $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(),0, $answer_id);
if(strlen($fb))
{
$template->setCurrentBlock("feedback");
@@ -819,7 +819,7 @@ private function populateSpecificFeedbackInline($user_solution, $answer_id, $tem
if($answer->getCorrectness())
{
- $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), $answer_id);
+ $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(),0, $answer_id);
if(strlen($fb))
{
$template->setCurrentBlock("feedback");
diff --git a/Modules/TestQuestionPool/classes/class.assLongMenuGUI.php b/Modules/TestQuestionPool/classes/class.assLongMenuGUI.php
index 7d2ccb43cf02..cdec4035543e 100644
--- a/Modules/TestQuestionPool/classes/class.assLongMenuGUI.php
+++ b/Modules/TestQuestionPool/classes/class.assLongMenuGUI.php
@@ -314,7 +314,7 @@ function getSolutionOutput(
$feedback .= strlen($fb) ? $fb : '';
}
- $fb = $this->getSpecificFeedbackOutput($active_id, $pass);
+ $fb = $this->getSpecificFeedbackOutput(array());
$feedback .= strlen($fb) ? $fb : '';
}
if (strlen($feedback))
@@ -481,9 +481,9 @@ function setQuestionTabs()
$this->addBackTab($this->ilTabs);
}
- function getSpecificFeedbackOutput($active_id, $pass)
+ function getSpecificFeedbackOutput($userSolution)
{
- if( !$this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), 0) )
+ if( !$this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(),0, 0) )
{
return '';
}
@@ -499,7 +499,7 @@ function getSpecificFeedbackOutput($active_id, $pass)
$feedback .= $caption .'';
$feedback .= $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
- $this->object->getId(), $index
+ $this->object->getId(),0, $index
) . ' | ';
}
$feedback .= '';
diff --git a/Modules/TestQuestionPool/classes/class.assMatchingQuestionGUI.php b/Modules/TestQuestionPool/classes/class.assMatchingQuestionGUI.php
index 1bfdf1aada9f..8140291e637f 100755
--- a/Modules/TestQuestionPool/classes/class.assMatchingQuestionGUI.php
+++ b/Modules/TestQuestionPool/classes/class.assMatchingQuestionGUI.php
@@ -593,7 +593,7 @@ function getSolutionOutput(
$feedback .= strlen($fb) ? $fb : '';
}
- $fb = $this->getSpecificFeedbackOutput($active_id, $pass);
+ $fb = $this->getSpecificFeedbackOutput(array());
$feedback .= strlen($fb) ? $fb : '';
}
if (strlen($feedback))
@@ -1050,11 +1050,11 @@ function setQuestionTabs()
$this->addBackTab($ilTabs);
}
- function getSpecificFeedbackOutput($active_id, $pass)
+ function getSpecificFeedbackOutput($userSolution)
{
$matches = array_values($this->object->getMaximumScoringMatchingPairs());
- if( !$this->object->feedbackOBJ->specificAnswerFeedbackExists($matches) )
+ if( !$this->object->feedbackOBJ->specificAnswerFeedbackExists() )
{
return '';
}
@@ -1064,7 +1064,7 @@ function getSpecificFeedbackOutput($active_id, $pass)
foreach ($matches as $idx => $ans)
{
$fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
- $this->object->getId(), $idx
+ $this->object->getId(),0, $idx
);
$feedback .= '| "' . $ans->definition->text . '" ' . $this->lng->txt("matches") . ' "';
$feedback .= $ans->term->text . '" | ';
diff --git a/Modules/TestQuestionPool/classes/class.assMultipleChoice.php b/Modules/TestQuestionPool/classes/class.assMultipleChoice.php
index cc9b918812bc..c1692f444bc2 100755
--- a/Modules/TestQuestionPool/classes/class.assMultipleChoice.php
+++ b/Modules/TestQuestionPool/classes/class.assMultipleChoice.php
@@ -1024,7 +1024,7 @@ function getRTETextWithMediaObjects()
$text = parent::getRTETextWithMediaObjects();
foreach ($this->answers as $index => $answer)
{
- $text .= $this->feedbackOBJ->getSpecificAnswerFeedbackContent($this->getId(), $index);
+ $text .= $this->feedbackOBJ->getSpecificAnswerFeedbackContent($this->getId(),0, $index);
$answer_obj = $this->answers[$index];
$text .= $answer_obj->getAnswertext();
}
@@ -1131,7 +1131,7 @@ public function toJSON()
"order" => (int) $answer_obj->getOrder(),
"image" => (string) $answer_obj->getImage(),
"feedback" => $this->formatSAQuestion(
- $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(), $key)
+ $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(),0, $key)
)
));
}
diff --git a/Modules/TestQuestionPool/classes/class.assMultipleChoiceGUI.php b/Modules/TestQuestionPool/classes/class.assMultipleChoiceGUI.php
index 541075c764e3..8e25ab8ad2b3 100755
--- a/Modules/TestQuestionPool/classes/class.assMultipleChoiceGUI.php
+++ b/Modules/TestQuestionPool/classes/class.assMultipleChoiceGUI.php
@@ -337,7 +337,7 @@ function getSolutionOutput(
if (strcmp($mc_solution, $answer_id) == 0)
{
$fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
- $this->object->getId(), $answer_id
+ $this->object->getId(),0, $answer_id
);
if (strlen($fb))
{
@@ -352,7 +352,7 @@ function getSolutionOutput(
if ($this->object->getSpecificFeedbackSetting() == 1)
{
$fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
- $this->object->getId(), $answer_id
+ $this->object->getId(),0, $answer_id
);
if (strlen($fb))
{
@@ -369,7 +369,7 @@ function getSolutionOutput(
if ($answer->getPoints() > 0)
{
$fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
- $this->object->getId(), $answer_id
+ $this->object->getId(),0, $answer_id
);
if (strlen($fb))
{
@@ -820,7 +820,7 @@ function getChoiceKeys()
return $choiceKeys;
}
- function getSpecificFeedbackOutput($active_id, $pass)
+ function getSpecificFeedbackOutput($userSolution)
{
// No return value, this question type supports inline specific feedback.
$output = "";
@@ -1082,7 +1082,7 @@ private function populateSpecificFeedbackInline($user_solution, $answer_id, $tem
{
if(strcmp($mc_solution, $answer_id) == 0)
{
- $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), $answer_id);
+ $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(),0, $answer_id);
if(strlen($fb))
{
$template->setCurrentBlock("feedback");
@@ -1095,7 +1095,7 @@ private function populateSpecificFeedbackInline($user_solution, $answer_id, $tem
if($this->object->getSpecificFeedbackSetting() == 1)
{
- $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), $answer_id);
+ $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(),0, $answer_id);
if(strlen($fb))
{
$template->setCurrentBlock("feedback");
@@ -1110,7 +1110,7 @@ private function populateSpecificFeedbackInline($user_solution, $answer_id, $tem
if($answer->getPoints() > 0)
{
- $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), $answer_id);
+ $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(),0, $answer_id);
if(strlen($fb))
{
$template->setCurrentBlock("feedback");
diff --git a/Modules/TestQuestionPool/classes/class.assNumericGUI.php b/Modules/TestQuestionPool/classes/class.assNumericGUI.php
index 731fe092c2b3..1f30c36fce2f 100755
--- a/Modules/TestQuestionPool/classes/class.assNumericGUI.php
+++ b/Modules/TestQuestionPool/classes/class.assNumericGUI.php
@@ -399,7 +399,7 @@ public function setQuestionTabs()
*
* @return mixed|string
*/
- public function getSpecificFeedbackOutput($active_id, $pass)
+ public function getSpecificFeedbackOutput($userSolution)
{
$output = "";
return $this->object->prepareTextareaOutput($output, TRUE);
diff --git a/Modules/TestQuestionPool/classes/class.assOrderingHorizontalGUI.php b/Modules/TestQuestionPool/classes/class.assOrderingHorizontalGUI.php
index 537b7d12c71d..12e576334b21 100644
--- a/Modules/TestQuestionPool/classes/class.assOrderingHorizontalGUI.php
+++ b/Modules/TestQuestionPool/classes/class.assOrderingHorizontalGUI.php
@@ -238,7 +238,7 @@ function getSolutionOutput(
$feedback .= strlen($fb) ? $fb : '';
}
- $fb = $this->getSpecificFeedbackOutput($active_id, $pass);
+ $fb = $this->getSpecificFeedbackOutput(array());
$feedback .= strlen($fb) ? $fb : '';
}
if (strlen($feedback))
@@ -447,7 +447,7 @@ function setQuestionTabs()
$this->addBackTab($ilTabs);
}
- function getSpecificFeedbackOutput($active_id, $pass)
+ function getSpecificFeedbackOutput($userSolution)
{
if(strpos($this->object->getOrderText(),'::'))
{
@@ -456,7 +456,7 @@ function getSpecificFeedbackOutput($active_id, $pass)
$answers = explode(' ', $this->object->getOrderText());
}
- if( !$this->object->feedbackOBJ->specificAnswerFeedbackExists(array_values($answers)) )
+ if( !$this->object->feedbackOBJ->specificAnswerFeedbackExists() )
{
return '';
}
@@ -466,7 +466,7 @@ function getSpecificFeedbackOutput($active_id, $pass)
foreach($answers as $idx => $answer)
{
$feedback = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
- $this->object->getId(), $idx
+ $this->object->getId(),0, $idx
);
$output .= " |
| {$answer} | {$feedback} |
";
diff --git a/Modules/TestQuestionPool/classes/class.assOrderingQuestion.php b/Modules/TestQuestionPool/classes/class.assOrderingQuestion.php
index 655ed1195200..3bce21bd1ba8 100755
--- a/Modules/TestQuestionPool/classes/class.assOrderingQuestion.php
+++ b/Modules/TestQuestionPool/classes/class.assOrderingQuestion.php
@@ -710,6 +710,12 @@ public function calculateReachedPoints($active_id, $pass = NULL, $authorizedSolu
}
$solutionValuePairs = $this->getSolutionValues($active_id, $pass, $authorizedSolution);
+
+ if( !count($solutionValuePairs) )
+ {
+ return 0;
+ }
+
$indexedSolutionValues = $this->fetchIndexedValuesFromValuePairs($solutionValuePairs);
$solutionOrderingElementList = $this->getSolutionOrderingElementList($indexedSolutionValues);
diff --git a/Modules/TestQuestionPool/classes/class.assOrderingQuestionGUI.php b/Modules/TestQuestionPool/classes/class.assOrderingQuestionGUI.php
index 030d0c57c7ac..3b3999dfe9c5 100755
--- a/Modules/TestQuestionPool/classes/class.assOrderingQuestionGUI.php
+++ b/Modules/TestQuestionPool/classes/class.assOrderingQuestionGUI.php
@@ -513,7 +513,7 @@ function getSolutionOutput(
$feedback .= strlen($fb) ? $fb : '';
}
- $fb = $this->getSpecificFeedbackOutput($active_id, $pass);
+ $fb = $this->getSpecificFeedbackOutput(array());
$feedback .= strlen($fb) ? $fb : '';
if (strlen($feedback))
@@ -703,9 +703,9 @@ function setQuestionTabs()
$this->addBackTab($ilTabs);
}
- function getSpecificFeedbackOutput($active_id, $pass)
+ function getSpecificFeedbackOutput($userSolution)
{
- if( !$this->object->feedbackOBJ->specificAnswerFeedbackExists($this->object->getOrderingElementList()) )
+ if( !$this->object->feedbackOBJ->specificAnswerFeedbackExists() )
{
return '';
}
@@ -715,7 +715,7 @@ function getSpecificFeedbackOutput($active_id, $pass)
foreach( $this->object->getOrderingElementList() as $element)
{
$feedback = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
- $this->object->getId(), $element->getPosition()
+ $this->object->getId(),0, $element->getPosition()
);
if( $this->object->isImageOrderingType() )
diff --git a/Modules/TestQuestionPool/classes/class.assQuestionGUI.php b/Modules/TestQuestionPool/classes/class.assQuestionGUI.php
index 8d87a4184eb4..9b73e15d1ef3 100755
--- a/Modules/TestQuestionPool/classes/class.assQuestionGUI.php
+++ b/Modules/TestQuestionPool/classes/class.assQuestionGUI.php
@@ -1410,12 +1410,11 @@ public function getGenericFeedbackOutputForIncorrectSolution()
* This method should be overwritten by the actual question.
*
* @todo Mark this method abstract!
- * @param integer $active_id Active ID of the user
- * @param integer $pass Active pass
+ * @param array $userSolution ($userSolution[] = )
* @return string HTML Code with the answer specific feedback
* @access public
*/
- abstract function getSpecificFeedbackOutput($active_id, $pass);
+ abstract function getSpecificFeedbackOutput($userSolution);
public function outQuestionType()
{
diff --git a/Modules/TestQuestionPool/classes/class.assSingleChoice.php b/Modules/TestQuestionPool/classes/class.assSingleChoice.php
index 5f4e542961d0..ed5dd0deaade 100755
--- a/Modules/TestQuestionPool/classes/class.assSingleChoice.php
+++ b/Modules/TestQuestionPool/classes/class.assSingleChoice.php
@@ -991,7 +991,7 @@ function getRTETextWithMediaObjects()
$text = parent::getRTETextWithMediaObjects();
foreach ($this->answers as $index => $answer)
{
- $text .= $this->feedbackOBJ->getSpecificAnswerFeedbackContent($this->getId(), $index);
+ $text .= $this->feedbackOBJ->getSpecificAnswerFeedbackContent($this->getId(),0, $index);
$answer_obj = $this->answers[$index];
$text .= $answer_obj->getAnswertext();
}
@@ -1094,7 +1094,7 @@ public function toJSON()
"order" => (int)$answer_obj->getOrder(),
"image" => (string) $answer_obj->getImage(),
"feedback" => $this->formatSAQuestion(
- $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(), $key)
+ $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(),0, $key)
)
));
}
diff --git a/Modules/TestQuestionPool/classes/class.assSingleChoiceGUI.php b/Modules/TestQuestionPool/classes/class.assSingleChoiceGUI.php
index a6d863d045e7..8d870706380d 100755
--- a/Modules/TestQuestionPool/classes/class.assSingleChoiceGUI.php
+++ b/Modules/TestQuestionPool/classes/class.assSingleChoiceGUI.php
@@ -562,7 +562,7 @@ function getTestOutput($active_id, $pass, $is_postponed = FALSE, $use_post_solut
if($feedbackOutputRequired)
{
$fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
- $this->object->getId(), $answer_id
+ $this->object->getId(),0, $answer_id
);
if (strlen($fb))
{
@@ -676,7 +676,7 @@ function getChoiceKeys()
return $choiceKeys;
}
- function getSpecificFeedbackOutput($active_id, $pass)
+ function getSpecificFeedbackOutput($userSolution)
{
// No return value, this question type supports inline specific feedback.
$output = "";
@@ -923,7 +923,7 @@ private function populateInlineFeedback($template, $answer_id, $user_solution)
if($feedbackOutputRequired)
{
- $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), $answer_id);
+ $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(),0, $answer_id);
if(strlen($fb))
{
$template->setCurrentBlock("feedback");
diff --git a/Modules/TestQuestionPool/classes/class.assTextQuestionGUI.php b/Modules/TestQuestionPool/classes/class.assTextQuestionGUI.php
index 64806a09b98d..1f2012cb8922 100755
--- a/Modules/TestQuestionPool/classes/class.assTextQuestionGUI.php
+++ b/Modules/TestQuestionPool/classes/class.assTextQuestionGUI.php
@@ -250,7 +250,10 @@ function getSolutionOutput(
$feedback .= strlen($fb) ? $fb : '';
}
- $fb = $this->getSpecificFeedbackOutput($active_id, $pass);
+ $fb = $this->getSpecificFeedbackOutput(
+ array($user_solution => '')
+ );
+
$feedback .= strlen($fb) ? $fb : '';
}
if (strlen($feedback))
@@ -550,18 +553,19 @@ function setQuestionTabs()
$this->addBackTab($ilTabs);
}
- function getSpecificFeedbackOutput($active_id, $pass)
+ function getSpecificFeedbackOutput($userSolution)
{
+ $firstValue1 = key($userSolution);
+
$feedback = '';
- $user_answers = $this->object->getSolutionValues($active_id);
- $user_answer = ' '. $user_answers[0]['value1'];
+ $user_answer = ' '. $firstValue1;
foreach ($this->object->getAnswers() as $idx => $ans)
{
if ($this->object->isKeywordMatching($user_answer, $ans->getAnswertext() ))
{
$fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
- $this->object->getId(), $idx
+ $this->object->getId(),0, $idx
);
$feedback .= '| ' . $ans->getAnswertext() . ' | ';
$feedback .= $fb . ' |
';
diff --git a/Modules/TestQuestionPool/classes/class.assTextSubsetGUI.php b/Modules/TestQuestionPool/classes/class.assTextSubsetGUI.php
index ddf0dd96a705..09ca95bd9040 100755
--- a/Modules/TestQuestionPool/classes/class.assTextSubsetGUI.php
+++ b/Modules/TestQuestionPool/classes/class.assTextSubsetGUI.php
@@ -398,7 +398,7 @@ function setQuestionTabs()
$this->addBackTab($ilTabs);
}
- function getSpecificFeedbackOutput($active_id, $pass)
+ function getSpecificFeedbackOutput($userSolution)
{
$output = "";
return $this->object->prepareTextareaOutput($output, TRUE);
diff --git a/Modules/TestQuestionPool/classes/class.ilAssQuestionPreviewGUI.php b/Modules/TestQuestionPool/classes/class.ilAssQuestionPreviewGUI.php
index 7db9ab8e1a2e..25d885ce200c 100644
--- a/Modules/TestQuestionPool/classes/class.ilAssQuestionPreviewGUI.php
+++ b/Modules/TestQuestionPool/classes/class.ilAssQuestionPreviewGUI.php
@@ -405,8 +405,12 @@ private function populateGenericQuestionFeedback(ilTemplate $tpl)
private function populateSpecificQuestionFeedback(ilTemplate $tpl)
{
+ $fb = $this->questionGUI->getSpecificFeedbackOutput(
+ (array)$this->previewSession->getParticipantsSolution()
+ );
+
$tpl->setCurrentBlock('instant_feedback_specific');
- $tpl->setVariable('ANSWER_FEEDBACK', $this->questionGUI->getSpecificFeedbackOutput(0, -1));
+ $tpl->setVariable('ANSWER_FEEDBACK', $fb);
$tpl->parseCurrentBlock();
}
diff --git a/Modules/TestQuestionPool/classes/export/qti12/class.assClozeTestExport.php b/Modules/TestQuestionPool/classes/export/qti12/class.assClozeTestExport.php
index e4bb6b7b50ec..14e090c13e23 100644
--- a/Modules/TestQuestionPool/classes/export/qti12/class.assClozeTestExport.php
+++ b/Modules/TestQuestionPool/classes/export/qti12/class.assClozeTestExport.php
@@ -81,6 +81,11 @@ function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle =
$a_xml_writer->xmlElement("fieldlabel", NULL, "identicalScoring");
$a_xml_writer->xmlElement("fieldentry", NULL, $this->object->getIdenticalScoring());
$a_xml_writer->xmlEndTag("qtimetadatafield");
+
+ $a_xml_writer->xmlStartTag("qtimetadatafield");
+ $a_xml_writer->xmlElement("fieldlabel", NULL, "feedback_mode");
+ $a_xml_writer->xmlElement("fieldentry", NULL, $this->object->getFeedbackMode());
+ $a_xml_writer->xmlEndTag("qtimetadatafield");
$a_xml_writer->xmlStartTag("qtimetadatafield");
$a_xml_writer->xmlElement("fieldlabel", NULL, "combinations");
@@ -292,7 +297,7 @@ function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle =
}
break;
case CLOZE_TEXT:
- foreach ($gap->getItems(new ilArrayElementShuffler) as $answer)
+ foreach ($gap->getItems(new ilArrayElementOrderKeeper()) as $answer)
{
$attrs = array(
"continue" => "Yes"
@@ -321,7 +326,7 @@ function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle =
}
break;
case CLOZE_NUMERIC:
- foreach ($gap->getItems(new ilArrayElementShuffler) as $answer)
+ foreach ($gap->getItems(new ilArrayElementOrderKeeper()) as $answer)
{
$attrs = array(
"continue" => "Yes"
@@ -584,7 +589,7 @@ function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle =
$a_xml_writer->xmlEndTag("flow_mat");
$a_xml_writer->xmlEndTag("itemfeedback");
}*/
-
+ /*
$attrs = array(
"ident" => $i,
"view" => "All"
@@ -596,12 +601,14 @@ function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle =
// $a_xml_writer->xmlElement("mattext");
// $a_xml_writer->xmlEndTag("material");
$fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation(
- $this->object->getId(), $i
+ $this->object->getId(), $i, 0
);
$this->object->addQTIMaterial($a_xml_writer, $fb);
$a_xml_writer->xmlEndTag("flow_mat");
$a_xml_writer->xmlEndTag("itemfeedback");
+ */
}
+ $this->exportAnswerSpecificFeedbacks($a_xml_writer);
if (strlen($feedback_allcorrect))
{
@@ -641,6 +648,40 @@ function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle =
}
return $xml;
}
+
+ /**
+ * @param ilXmlWriter $xmlWriter
+ */
+ protected function exportAnswerSpecificFeedbacks(ilXmlWriter $xmlWriter)
+ {
+ require_once 'Modules/TestQuestionPool/classes/feedback/class.ilAssSpecificFeedbackIdentifierList.php';
+ $feedbackIdentifierList = new ilAssSpecificFeedbackIdentifierList();
+ $feedbackIdentifierList->load($this->object->getId());
+
+ foreach($feedbackIdentifierList as $fbIdentifier)
+ {
+ $feedback = $this->object->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation(
+ $this->object->getId(), $fbIdentifier->getQuestionIndex(), $fbIdentifier->getAnswerIndex()
+ );
+
+ $xmlWriter->xmlStartTag("itemfeedback", array(
+ "ident" => $this->buildQtiExportIdent($fbIdentifier), "view" => "All"
+ ));
+
+ $xmlWriter->xmlStartTag("flow_mat");
+ $this->object->addQTIMaterial($xmlWriter, $feedback);
+ $xmlWriter->xmlEndTag("flow_mat");
+
+ $xmlWriter->xmlEndTag("itemfeedback");
+ }
+ }
+
+ /**
+ * @param ilAssSpecificFeedbackIdentifier $fbIdentifier
+ * @return string
+ */
+ public function buildQtiExportIdent(ilAssSpecificFeedbackIdentifier $fbIdentifier)
+ {
+ return "{$fbIdentifier->getQuestionIndex()}_{$fbIdentifier->getAnswerIndex()}";
+ }
}
-
-?>
diff --git a/Modules/TestQuestionPool/classes/export/qti12/class.assImagemapQuestionExport.php b/Modules/TestQuestionPool/classes/export/qti12/class.assImagemapQuestionExport.php
index 88f19edf59c2..d93004daa22a 100644
--- a/Modules/TestQuestionPool/classes/export/qti12/class.assImagemapQuestionExport.php
+++ b/Modules/TestQuestionPool/classes/export/qti12/class.assImagemapQuestionExport.php
@@ -456,7 +456,7 @@ function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle =
// qti flow_mat
$a_xml_writer->xmlStartTag("flow_mat");
$fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation(
- $this->object->getId(), $index
+ $this->object->getId(),0, $index
);
$this->object->addQTIMaterial($a_xml_writer, $fb);
$a_xml_writer->xmlEndTag("flow_mat");
diff --git a/Modules/TestQuestionPool/classes/export/qti12/class.assKprimChoiceExport.php b/Modules/TestQuestionPool/classes/export/qti12/class.assKprimChoiceExport.php
index 8a783f1e2a08..e469e2307a95 100644
--- a/Modules/TestQuestionPool/classes/export/qti12/class.assKprimChoiceExport.php
+++ b/Modules/TestQuestionPool/classes/export/qti12/class.assKprimChoiceExport.php
@@ -278,7 +278,7 @@ public function toXML($a_include_header = true, $a_include_binary = true, $a_shu
$xml->xmlStartTag('flow_mat');
$this->object->addQTIMaterial($xml, $this->object->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation(
- $this->object->getId(), $answer->getPosition()
+ $this->object->getId(),0, $answer->getPosition()
));
$xml->xmlEndTag('flow_mat');
diff --git a/Modules/TestQuestionPool/classes/export/qti12/class.assLongMenuExport.php b/Modules/TestQuestionPool/classes/export/qti12/class.assLongMenuExport.php
index a9cdfa8f9b89..01fc7c9bf1d2 100644
--- a/Modules/TestQuestionPool/classes/export/qti12/class.assLongMenuExport.php
+++ b/Modules/TestQuestionPool/classes/export/qti12/class.assLongMenuExport.php
@@ -227,7 +227,7 @@ public function toXML($a_include_header = true, $a_include_binary = true, $a_shu
// qti flow_mat
$xml->xmlStartTag("flow_mat");
$fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation(
- $this->object->getId(), $i
+ $this->object->getId(),0, $i
);
$this->object->addQTIMaterial($xml, $fb);
$xml->xmlEndTag("flow_mat");
diff --git a/Modules/TestQuestionPool/classes/export/qti12/class.assMultipleChoiceExport.php b/Modules/TestQuestionPool/classes/export/qti12/class.assMultipleChoiceExport.php
index f83d3e21f23d..863fcac0d0da 100644
--- a/Modules/TestQuestionPool/classes/export/qti12/class.assMultipleChoiceExport.php
+++ b/Modules/TestQuestionPool/classes/export/qti12/class.assMultipleChoiceExport.php
@@ -329,7 +329,7 @@ function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle =
// qti flow_mat
$a_xml_writer->xmlStartTag("flow_mat");
$fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation(
- $this->object->getId(), $index
+ $this->object->getId(),0, $index
);
$this->object->addQTIMaterial($a_xml_writer, $fb);
$a_xml_writer->xmlEndTag("flow_mat");
diff --git a/Modules/TestQuestionPool/classes/export/qti12/class.assQuestionExport.php b/Modules/TestQuestionPool/classes/export/qti12/class.assQuestionExport.php
index 70e40fae17b0..fa5fb135e24c 100644
--- a/Modules/TestQuestionPool/classes/export/qti12/class.assQuestionExport.php
+++ b/Modules/TestQuestionPool/classes/export/qti12/class.assQuestionExport.php
@@ -50,7 +50,7 @@ protected function addAnswerSpecificFeedback(ilXmlWriter $a_xml_writer, $answers
// qti flow_mat
$a_xml_writer->xmlStartTag("flow_mat");
$fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation(
- $this->object->getId(), $index
+ $this->object->getId(),0, $index
);
$this->object->addQTIMaterial($a_xml_writer, $fb);
$a_xml_writer->xmlEndTag("flow_mat");
diff --git a/Modules/TestQuestionPool/classes/export/qti12/class.assSingleChoiceExport.php b/Modules/TestQuestionPool/classes/export/qti12/class.assSingleChoiceExport.php
index 0efe85236b8b..14e25fcb617c 100644
--- a/Modules/TestQuestionPool/classes/export/qti12/class.assSingleChoiceExport.php
+++ b/Modules/TestQuestionPool/classes/export/qti12/class.assSingleChoiceExport.php
@@ -310,7 +310,7 @@ function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle =
// qti flow_mat
$a_xml_writer->xmlStartTag("flow_mat");
$fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation(
- $this->object->getId(), $index
+ $this->object->getId(),0, $index
);
$this->object->addQTIMaterial($a_xml_writer, $fb);
$a_xml_writer->xmlEndTag("flow_mat");
diff --git a/Modules/TestQuestionPool/classes/feedback/class.ilAssClozeTestFeedback.php b/Modules/TestQuestionPool/classes/feedback/class.ilAssClozeTestFeedback.php
index 6df89d3d1dfb..7c33f768962a 100644
--- a/Modules/TestQuestionPool/classes/feedback/class.ilAssClozeTestFeedback.php
+++ b/Modules/TestQuestionPool/classes/feedback/class.ilAssClozeTestFeedback.php
@@ -2,6 +2,7 @@
/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
require_once 'Modules/TestQuestionPool/classes/feedback/class.ilAssMultiOptionQuestionFeedback.php';
+require_once 'Services/Randomization/classes/class.ilArrayElementOrderKeeper.php';
/**
* feedback class for assClozeTest questions
@@ -13,38 +14,925 @@
*/
class ilAssClozeTestFeedback extends ilAssMultiOptionQuestionFeedback
{
+ /**
+ * constants for different feedback modes (per gap or per gap-answers/options)
+ */
+ const FB_MODE_GAP_QUESTION = 'gapQuestion';
+ const FB_MODE_GAP_ANSWERS = 'gapAnswers';
+
+ /**
+ * constants for answer indexes in case of FB_MODE_GAP_ANSWERS
+ */
+ const FB_TEXT_GAP_EMPTY_INDEX = -1;
+ const FB_TEXT_GAP_NOMATCH_INDEX = -2; // indexes for preset answers: 0 - n
+ const FB_SELECT_GAP_EMPTY_INDEX = -1; // indexes for given select options: 0 - n
+ const FB_NUMERIC_GAP_EMPTY_INDEX = -1;
+ const FB_NUMERIC_GAP_VALUE_HIT_INDEX = 0;
+ const FB_NUMERIC_GAP_RANGE_HIT_INDEX = 1;
+ const FB_NUMERIC_GAP_TOO_LOW_INDEX = 2;
+ const FB_NUMERIC_GAP_TOO_HIGH_INDEX = 3;
+
+ const SINGLE_GAP_FB_ANSWER_INDEX = -10;
+
+ /**
+ * object instance of current question
+ *
+ * @access protected
+ * @var assClozeTest
+ */
+ protected $questionOBJ = null;
+
/**
* returns the answer options mapped by answer index
* (overwrites parent method from ilAssMultiOptionQuestionFeedback)
*
- * @return array $answerOptionsByAnswerIndex
+ * @return assClozeGap[]
*/
- protected function getAnswerOptionsByAnswerIndex()
+ protected function getGapsByIndex()
{
return $this->questionOBJ->gaps;
}
+ /**
+ * @return boolean $isSaveableInPageObjectEditingMode
+ */
+ public function isSaveableInPageObjectEditingMode()
+ {
+ return true;
+ }
+
/**
* builds an answer option label from given (mixed type) index and answer
* (overwrites parent method from ilAssMultiOptionQuestionFeedback)
*
* @access protected
- * @param integer $index
- * @param mixed $answer
+ * @param integer $indexgapIndex
+ * @param assClozeGap $gap
* @return string $answerOptionLabel
*/
- protected function buildAnswerOptionLabel($index, $answer)
+ protected function buildGapFeedbackLabel($gapIndex, $gap)
+ {
+ global $DIC; /* @var ILIAS\DI\Container $DIC */
+
+ $answers = array();
+
+ foreach($gap->getItems(new ilArrayElementOrderKeeper()) as $item )
+ {
+ $answers[] = '"' . $item->getAnswertext().'"';
+ }
+
+ $answers = implode(' / ', $answers);
+
+ $label = sprintf($DIC->language()->txt('ass_cloze_gap_fb_gap_label'),
+ $gapIndex + 1, $answers
+ );
+
+ return $label;
+ }
+
+ /**
+ * @param integer $gapIndex
+ * @param assAnswerCloze $item
+ * @return string
+ */
+ protected function buildTextGapGivenAnswerFeedbackLabel($gapIndex, $item)
+ {
+ global $DIC; /* @var ILIAS\DI\Container $DIC */
+
+ return sprintf($DIC->language()->txt('ass_cloze_gap_fb_txt_match_label'),
+ $gapIndex + 1, $item->getAnswertext()
+ );
+ }
+
+ /**
+ * @param integer $gapIndex
+ * @return string
+ */
+ protected function buildTextGapWrongAnswerFeedbackLabel($gapIndex)
+ {
+ global $DIC; /* @var ILIAS\DI\Container $DIC */
+ return sprintf($DIC->language()->txt('ass_cloze_gap_fb_txt_nomatch_label'),$gapIndex + 1);
+ }
+
+ /**
+ * @param integer $gapIndex
+ * @return string
+ */
+ protected function buildTextGapEmptyFeedbackLabel($gapIndex)
+ {
+ global $DIC; /* @var ILIAS\DI\Container $DIC */
+ return sprintf($DIC->language()->txt('ass_cloze_gap_fb_txt_empty_label'), $gapIndex + 1);
+ }
+
+ /**
+ * @param integer $gapIndex
+ * @param assAnswerCloze $item
+ * @return string
+ */
+ protected function buildSelectGapOptionFeedbackLabel($gapIndex, $item)
+ {
+ global $DIC; /* @var ILIAS\DI\Container $DIC */
+
+ return sprintf($DIC->language()->txt('ass_cloze_gap_fb_sel_opt_label'),
+ $gapIndex + 1, $item->getAnswertext()
+ );
+ }
+
+ /**
+ * @param integer $gapIndex
+ * @return string
+ */
+ protected function buildSelectGapEmptyFeedbackLabel($gapIndex)
+ {
+ global $DIC; /* @var ILIAS\DI\Container $DIC */
+ return sprintf($DIC->language()->txt('ass_cloze_gap_fb_sel_empty_label'),$gapIndex + 1);
+ }
+
+ /**
+ * @param integer $gapIndex
+ * @return string
+ */
+ protected function buildNumericGapValueHitFeedbackLabel($gapIndex)
+ {
+ global $DIC; /* @var ILIAS\DI\Container $DIC */
+ return sprintf($DIC->language()->txt('ass_cloze_gap_fb_num_valuehit_label'),$gapIndex + 1);
+ }
+
+ /**
+ * @param integer $gapIndex
+ * @return string
+ */
+ protected function buildNumericGapRangeHitFeedbackLabel($gapIndex)
+ {
+ global $DIC; /* @var ILIAS\DI\Container $DIC */
+ return sprintf($DIC->language()->txt('ass_cloze_gap_fb_num_rangehit_label'),$gapIndex + 1);
+ }
+
+ /**
+ * @param integer $gapIndex
+ * @return string
+ */
+ protected function buildNumericGapTooLowFeedbackLabel($gapIndex)
+ {
+ global $DIC; /* @var ILIAS\DI\Container $DIC */
+ return sprintf($DIC->language()->txt('ass_cloze_gap_fb_num_toolow_label'),$gapIndex + 1);
+ }
+
+ /**
+ * @param integer $gapIndex
+ * @return string
+ */
+ protected function buildNumericGapTooHighFeedbackLabel($gapIndex)
+ {
+ global $DIC; /* @var ILIAS\DI\Container $DIC */
+ return sprintf($DIC->language()->txt('ass_cloze_gap_fb_num_toohigh_label'),$gapIndex + 1);
+ }
+
+ /**
+ * @param integer $gapIndex
+ * @return string
+ */
+ protected function buildNumericGapEmptyFeedbackLabel($gapIndex)
+ {
+ global $DIC; /* @var ILIAS\DI\Container $DIC */
+ return sprintf($DIC->language()->txt('ass_cloze_gap_fb_num_empty_label'),$gapIndex + 1);
+ }
+
+ public function completeSpecificFormProperties(ilPropertyFormGUI $form)
+ {
+ global $DIC; /* @var ILIAS\DI\Container $DIC */
+
+ if( !$this->questionOBJ->getSelfAssessmentEditingMode() )
+ {
+ $header = new ilFormSectionHeaderGUI();
+ $header->setTitle($this->lng->txt('feedback_answers'));
+ $form->addItem($header);
+
+ $feedbackMode = new ilRadioGroupInputGUI(
+ $DIC->language()->txt('ass_cloze_fb_mode'), 'feedback_mode'
+ );
+ $feedbackMode->setRequired(true);
+ $form->addItem($feedbackMode);
+
+ $fbModeGapQuestion = new ilRadioOption($DIC->language()->txt('ass_cloze_fb_mode_gap_qst'),
+ self::FB_MODE_GAP_QUESTION, $DIC->language()->txt('ass_cloze_fb_mode_gap_qst_info')
+ );
+ $this->completeFormPropsForFeedbackModeGapQuestion($fbModeGapQuestion);
+ $feedbackMode->addOption($fbModeGapQuestion);
+
+ $fbModeGapAnswers = new ilRadioOption($DIC->language()->txt('ass_cloze_fb_mode_gap_answ'),
+ self::FB_MODE_GAP_ANSWERS, $DIC->language()->txt('ass_cloze_fb_mode_gap_answ_info')
+ );
+ $this->completeFormPropsForFeedbackModeGapAnswers($fbModeGapAnswers);
+ $feedbackMode->addOption($fbModeGapAnswers);
+ }
+ }
+
+ protected function completeFormPropsForFeedbackModeGapQuestion(ilRadioOption $fbModeOpt)
+ {
+ foreach($this->getGapsByIndex() as $gapIndex => $gap )
+ {
+ $propertyLabel = $this->questionOBJ->prepareTextareaOutput(
+ $this->buildGapFeedbackLabel($gapIndex, $gap), true
+ );
+
+ $fbModeOpt->addSubItem($this->buildFeedbackContentFormProperty(
+ $propertyLabel , $this->buildPostVarForFbFieldPerGapQuestion($gapIndex),
+ $this->questionOBJ->isAdditionalContentEditingModePageObject()
+ ));
+ }
+ }
+
+ protected function completeFormPropsForFeedbackModeGapAnswers(ilRadioOption $fbModeOpt)
+ {
+ foreach($this->getGapsByIndex() as $gapIndex => $gap )
+ {
+ switch( $gap->getType() )
+ {
+ case assClozeGap::TYPE_TEXT:
+
+ $this->completeFbPropsForTextGap($fbModeOpt, $gap, $gapIndex);
+ break;
+
+ case assClozeGap::TYPE_SELECT:
+
+ $this->completeFbPropsForSelectGap($fbModeOpt, $gap, $gapIndex);
+ break;
+
+ case assClozeGap::TYPE_NUMERIC:
+
+ $this->completeFbPropsForNumericGap($fbModeOpt, $gapIndex, $gap);
+ break;
+ }
+ }
+ }
+
+ /**
+ * @param ilRadioOption $fbModeOpt
+ * @param assClozeGap $gap
+ * @param integer $gapIndex
+ */
+ protected function completeFbPropsForTextGap(ilRadioOption $fbModeOpt, assClozeGap $gap, $gapIndex)
+ {
+ foreach($gap->getItems(new ilArrayElementOrderKeeper()) as $answerIndex => $item)
+ {
+ $propertyLabel = $this->questionOBJ->prepareTextareaOutput(
+ $this->buildTextGapGivenAnswerFeedbackLabel($gapIndex, $item), true
+ );
+
+ $propertyPostVar = "feedback_answer_{$gapIndex}_{$answerIndex}";
+
+ $fbModeOpt->addSubItem($this->buildFeedbackContentFormProperty(
+ $propertyLabel, $propertyPostVar, $this->questionOBJ->isAdditionalContentEditingModePageObject()
+ ));
+ }
+
+ $propertyLabel = $this->questionOBJ->prepareTextareaOutput(
+ $this->buildTextGapWrongAnswerFeedbackLabel($gapIndex), true
+ );
+
+ $propertyPostVar = "feedback_answer_{$gapIndex}_".self::FB_TEXT_GAP_NOMATCH_INDEX;
+
+ $fbModeOpt->addSubItem($this->buildFeedbackContentFormProperty(
+ $propertyLabel, $propertyPostVar, $this->questionOBJ->isAdditionalContentEditingModePageObject()
+ ));
+
+ $propertyLabel = $this->questionOBJ->prepareTextareaOutput(
+ $this->buildTextGapEmptyFeedbackLabel($gapIndex), true
+ );
+
+ $propertyPostVar = "feedback_answer_{$gapIndex}_".self::FB_TEXT_GAP_EMPTY_INDEX;
+
+ $fbModeOpt->addSubItem($this->buildFeedbackContentFormProperty(
+ $propertyLabel, $propertyPostVar, $this->questionOBJ->isAdditionalContentEditingModePageObject()
+ ));
+ }
+
+ /**
+ * @param ilRadioOption $fbModeOpt
+ * @param assClozeGap $gap
+ * @param integer $gapIndex
+ */
+ protected function completeFbPropsForSelectGap(ilRadioOption $fbModeOpt, assClozeGap $gap, $gapIndex)
+ {
+ foreach ($gap->getItems(new ilArrayElementOrderKeeper()) as $optIndex => $item)
+ {
+ $propertyLabel = $this->questionOBJ->prepareTextareaOutput(
+ $this->buildSelectGapOptionFeedbackLabel($gapIndex, $item), true
+ );
+
+ $propertyPostVar = "feedback_answer_{$gapIndex}_{$optIndex}";
+
+ $fbModeOpt->addSubItem($this->buildFeedbackContentFormProperty(
+ $propertyLabel, $propertyPostVar, $this->questionOBJ->isAdditionalContentEditingModePageObject()
+ ));
+ }
+
+ $propertyLabel = $this->questionOBJ->prepareTextareaOutput(
+ $this->buildSelectGapEmptyFeedbackLabel($gapIndex), true
+ );
+
+ $propertyPostVar = "feedback_answer_{$gapIndex}_" . self::FB_SELECT_GAP_EMPTY_INDEX;
+
+ $fbModeOpt->addSubItem($this->buildFeedbackContentFormProperty(
+ $propertyLabel, $propertyPostVar, $this->questionOBJ->isAdditionalContentEditingModePageObject()
+ ));
+ }
+
+ /**
+ * @param ilRadioOption $fbModeOpt
+ * @param assClozeGap $gap
+ * @param integer $gapIndex
+ */
+ protected function completeFbPropsForNumericGap(ilRadioOption $fbModeOpt, $gapIndex, assClozeGap $gap)
+ {
+ $propertyLabel = $this->questionOBJ->prepareTextareaOutput(
+ $this->buildNumericGapValueHitFeedbackLabel($gapIndex), true
+ );
+
+ $propertyPostVar = "feedback_answer_{$gapIndex}_".self::FB_NUMERIC_GAP_VALUE_HIT_INDEX;
+
+ $fbModeOpt->addSubItem($this->buildFeedbackContentFormProperty(
+ $propertyLabel, $propertyPostVar, $this->questionOBJ->isAdditionalContentEditingModePageObject()
+ ));
+
+ if( $gap->numericRangeExists() )
+ {
+ $propertyLabel = $this->questionOBJ->prepareTextareaOutput(
+ $this->buildNumericGapRangeHitFeedbackLabel($gapIndex), true
+ );
+
+ $propertyPostVar = "feedback_answer_{$gapIndex}_".self::FB_NUMERIC_GAP_RANGE_HIT_INDEX;
+
+ $fbModeOpt->addSubItem($this->buildFeedbackContentFormProperty(
+ $propertyLabel, $propertyPostVar, $this->questionOBJ->isAdditionalContentEditingModePageObject()
+ ));
+ }
+
+ $propertyLabel = $this->questionOBJ->prepareTextareaOutput(
+ $this->buildNumericGapTooLowFeedbackLabel($gapIndex), true
+ );
+
+ $propertyPostVar = "feedback_answer_{$gapIndex}_".self::FB_NUMERIC_GAP_TOO_LOW_INDEX;
+
+ $fbModeOpt->addSubItem($this->buildFeedbackContentFormProperty(
+ $propertyLabel, $propertyPostVar, $this->questionOBJ->isAdditionalContentEditingModePageObject()
+ ));
+
+ $propertyLabel = $this->questionOBJ->prepareTextareaOutput(
+ $this->buildNumericGapTooHighFeedbackLabel($gapIndex), true
+ );
+
+ $propertyPostVar = "feedback_answer_{$gapIndex}_".self::FB_NUMERIC_GAP_TOO_HIGH_INDEX;
+
+ $fbModeOpt->addSubItem($this->buildFeedbackContentFormProperty(
+ $propertyLabel, $propertyPostVar, $this->questionOBJ->isAdditionalContentEditingModePageObject()
+ ));
+
+ $propertyLabel = $this->questionOBJ->prepareTextareaOutput(
+ $this->buildNumericGapEmptyFeedbackLabel($gapIndex), true
+ );
+
+ $propertyPostVar = "feedback_answer_{$gapIndex}_".self::FB_NUMERIC_GAP_EMPTY_INDEX;
+
+ $fbModeOpt->addSubItem($this->buildFeedbackContentFormProperty(
+ $propertyLabel, $propertyPostVar, $this->questionOBJ->isAdditionalContentEditingModePageObject()
+ ));
+ }
+
+ public function initSpecificFormProperties(ilPropertyFormGUI $form)
+ {
+ if( !$this->questionOBJ->getSelfAssessmentEditingMode() )
+ {
+ /* @var ilRadioGroupInputGUI $fbMode */
+ $fbMode = $form->getItemByPostVar('feedback_mode');
+ $fbMode->setValue($this->questionOBJ->getFeedbackMode());
+
+ if( $this->questionOBJ->isAdditionalContentEditingModePageObject() )
+ {
+ $this->initFeedbackFieldsPerGapQuestion($form);
+ $this->initFeedbackFieldsPerGapAnswers($form);
+ }
+ else
+ {
+ switch( $this->questionOBJ->getFeedbackMode() )
+ {
+ case self::FB_MODE_GAP_QUESTION:
+
+ $this->initFeedbackFieldsPerGapQuestion($form);
+ break;
+
+ case self::FB_MODE_GAP_ANSWERS:
+
+ $this->initFeedbackFieldsPerGapAnswers($form);
+ break;
+ }
+ }
+ }
+ }
+
+ protected function initFeedbackFieldsPerGapQuestion(ilPropertyFormGUI $form)
+ {
+ foreach( $this->getGapsByIndex() as $gapIndex => $gap )
+ {
+ $value = $this->getSpecificAnswerFeedbackFormValue($gapIndex, self::SINGLE_GAP_FB_ANSWER_INDEX);
+ $form->getItemByPostVar($this->buildPostVarForFbFieldPerGapQuestion($gapIndex))->setValue($value);
+ }
+ }
+
+ protected function initFeedbackFieldsPerGapAnswers(ilPropertyFormGUI $form)
+ {
+ foreach( $this->getGapsByIndex() as $gapIndex => $gap )
+ {
+ switch( $gap->getType() )
+ {
+ case assClozeGap::TYPE_TEXT:
+
+ $this->initFbPropsForTextGap($form, $gap, $gapIndex);
+ break;
+
+ case assClozeGap::TYPE_SELECT:
+
+ $this->initFbPropsForSelectGap($form, $gap, $gapIndex);
+ break;
+
+ case assClozeGap::TYPE_NUMERIC:
+
+ $this->initFbPropsForNumericGap($form, $gapIndex, $gap);
+ break;
+ }
+ }
+ }
+
+ protected function initFbPropsForTextGap(ilPropertyFormGUI $form, assClozeGap $gap, $gapIndex)
+ {
+ foreach($gap->getItems(new ilArrayElementOrderKeeper()) as $answerIndex => $item)
+ {
+ $value = $this->getSpecificAnswerFeedbackFormValue($gapIndex, $answerIndex);
+ $postVar = $this->buildPostVarForFbFieldPerGapAnswers($gapIndex, $answerIndex);
+ $form->getItemByPostVar($postVar)->setValue($value);
+ }
+
+ $value = $this->getSpecificAnswerFeedbackFormValue($gapIndex, self::FB_TEXT_GAP_NOMATCH_INDEX);
+ $postVar = $this->buildPostVarForFbFieldPerGapAnswers($gapIndex, self::FB_TEXT_GAP_NOMATCH_INDEX);
+ $form->getItemByPostVar($postVar)->setValue($value);
+
+ $value = $this->getSpecificAnswerFeedbackFormValue($gapIndex, self::FB_TEXT_GAP_EMPTY_INDEX);
+ $postVar = $this->buildPostVarForFbFieldPerGapAnswers($gapIndex, self::FB_TEXT_GAP_EMPTY_INDEX);
+ $form->getItemByPostVar($postVar)->setValue($value);
+ }
+
+ protected function initFbPropsForSelectGap(ilPropertyFormGUI $form, assClozeGap $gap, $gapIndex)
+ {
+ foreach ($gap->getItems(new ilArrayElementOrderKeeper()) as $optIndex => $item)
+ {
+ $value = $this->getSpecificAnswerFeedbackFormValue($gapIndex, $optIndex);
+ $postVar = $this->buildPostVarForFbFieldPerGapAnswers($gapIndex, $optIndex);
+ $form->getItemByPostVar($postVar)->setValue($value);
+ }
+
+ $value = $this->getSpecificAnswerFeedbackFormValue($gapIndex, self::FB_SELECT_GAP_EMPTY_INDEX);
+ $postVar = $this->buildPostVarForFbFieldPerGapAnswers($gapIndex, self::FB_SELECT_GAP_EMPTY_INDEX);
+ $form->getItemByPostVar($postVar)->setValue($value);
+ }
+
+ protected function initFbPropsForNumericGap(ilPropertyFormGUI $form, $gapIndex, assClozeGap $gap)
+ {
+ $value = $this->getSpecificAnswerFeedbackFormValue($gapIndex, self::FB_NUMERIC_GAP_VALUE_HIT_INDEX);
+ $postVar = $this->buildPostVarForFbFieldPerGapAnswers($gapIndex, self::FB_NUMERIC_GAP_VALUE_HIT_INDEX);
+ $form->getItemByPostVar($postVar)->setValue($value);
+
+ if( $gap->numericRangeExists() )
+ {
+ $value = $this->getSpecificAnswerFeedbackFormValue($gapIndex, self::FB_NUMERIC_GAP_RANGE_HIT_INDEX);
+ $postVar = $this->buildPostVarForFbFieldPerGapAnswers($gapIndex, self::FB_NUMERIC_GAP_RANGE_HIT_INDEX);
+ $form->getItemByPostVar($postVar)->setValue($value);
+ }
+
+ $value = $this->getSpecificAnswerFeedbackFormValue($gapIndex, self::FB_NUMERIC_GAP_TOO_LOW_INDEX);
+ $postVar = $this->buildPostVarForFbFieldPerGapAnswers($gapIndex, self::FB_NUMERIC_GAP_TOO_LOW_INDEX);
+ $form->getItemByPostVar($postVar)->setValue($value);
+
+ $value = $this->getSpecificAnswerFeedbackFormValue($gapIndex, self::FB_NUMERIC_GAP_TOO_HIGH_INDEX);
+ $postVar = $this->buildPostVarForFbFieldPerGapAnswers($gapIndex, self::FB_NUMERIC_GAP_TOO_HIGH_INDEX);
+ $form->getItemByPostVar($postVar)->setValue($value);
+
+ $value = $this->getSpecificAnswerFeedbackFormValue($gapIndex, self::FB_NUMERIC_GAP_EMPTY_INDEX);
+ $postVar = $this->buildPostVarForFbFieldPerGapAnswers($gapIndex, self::FB_NUMERIC_GAP_EMPTY_INDEX);
+ $form->getItemByPostVar($postVar)->setValue($value);
+ }
+
+ public function saveSpecificFormProperties(ilPropertyFormGUI $form)
+ {
+ if( !$this->questionOBJ->getSelfAssessmentEditingMode() )
+ {
+ $fbMode = $form->getItemByPostVar('feedback_mode')->getValue();
+
+ if( $fbMode != $this->questionOBJ->getFeedbackMode() )
+ {
+ $this->cleanupSpecificAnswerFeedbacks($this->questionOBJ->getFeedbackMode());
+ }
+
+ $this->saveSpecificFeedbackMode( $this->questionOBJ->getId(), $fbMode);
+
+ switch( $this->questionOBJ->getFeedbackMode() )
+ {
+ case self::FB_MODE_GAP_QUESTION:
+
+ $this->saveFeedbackFieldsPerGapQuestion($form);
+ break;
+
+ case self::FB_MODE_GAP_ANSWERS:
+
+ $this->saveFeedbackFieldsPerGapAnswers($form);
+ break;
+ }
+ }
+ }
+
+ protected function saveFeedbackFieldsPerGapQuestion(ilPropertyFormGUI $form)
+ {
+ foreach( $this->getGapsByIndex() as $gapIndex => $gap )
+ {
+ $postVar = $this->buildPostVarForFbFieldPerGapQuestion($gapIndex);
+ $value = $form->getItemByPostVar($postVar)->getValue();
+
+ $this->saveSpecificAnswerFeedbackContent(
+ $this->questionOBJ->getId(), $gapIndex, self::SINGLE_GAP_FB_ANSWER_INDEX, $value
+ );
+ }
+
+ }
+
+ protected function saveFeedbackFieldsPerGapAnswers(ilPropertyFormGUI $form)
+ {
+ foreach( $this->getGapsByIndex() as $gapIndex => $gap )
+ {
+ switch( $gap->getType() )
+ {
+ case assClozeGap::TYPE_TEXT:
+
+ $this->saveFbPropsForTextGap($form, $gap, $gapIndex);
+ break;
+
+ case assClozeGap::TYPE_SELECT:
+
+ $this->saveFbPropsForSelectGap($form, $gap, $gapIndex);
+ break;
+
+ case assClozeGap::TYPE_NUMERIC:
+
+ $this->saveFbPropsForNumericGap($form, $gapIndex, $gap);
+ break;
+ }
+ }
+ }
+
+ protected function saveFbPropsForTextGap(ilPropertyFormGUI $form, assClozeGap $gap, $gapIndex)
+ {
+ foreach($gap->getItems(new ilArrayElementOrderKeeper()) as $answerIndex => $item)
+ {
+ $postVar = $this->buildPostVarForFbFieldPerGapAnswers($gapIndex, $answerIndex);
+ $value = $form->getItemByPostVar($postVar)->getValue();
+ $this->saveSpecificAnswerFeedbackContent(
+ $this->questionOBJ->getId(), $gapIndex, $answerIndex, $value
+ );
+ }
+
+ $postVar = $this->buildPostVarForFbFieldPerGapAnswers($gapIndex, self::FB_TEXT_GAP_NOMATCH_INDEX);
+ $value = $form->getItemByPostVar($postVar)->getValue();
+ $this->saveSpecificAnswerFeedbackContent(
+ $this->questionOBJ->getId(), $gapIndex, self::FB_TEXT_GAP_NOMATCH_INDEX, $value
+ );
+
+ $postVar = $this->buildPostVarForFbFieldPerGapAnswers($gapIndex, self::FB_TEXT_GAP_EMPTY_INDEX);
+ $value = $form->getItemByPostVar($postVar)->getValue();
+ $this->saveSpecificAnswerFeedbackContent(
+ $this->questionOBJ->getId(), $gapIndex, self::FB_TEXT_GAP_EMPTY_INDEX, $value
+ );
+ }
+
+ protected function saveFbPropsForSelectGap(ilPropertyFormGUI $form, assClozeGap $gap, $gapIndex)
+ {
+ foreach ($gap->getItems(new ilArrayElementOrderKeeper()) as $optIndex => $item)
+ {
+ $postVar = $this->buildPostVarForFbFieldPerGapAnswers($gapIndex, $optIndex);
+ $value = $form->getItemByPostVar($postVar)->getValue();
+ $this->saveSpecificAnswerFeedbackContent(
+ $this->questionOBJ->getId(), $gapIndex, $optIndex, $value
+ );
+ }
+
+ $postVar = $this->buildPostVarForFbFieldPerGapAnswers($gapIndex, self::FB_SELECT_GAP_EMPTY_INDEX);
+ $value = $form->getItemByPostVar($postVar)->getValue();
+ $this->saveSpecificAnswerFeedbackContent(
+ $this->questionOBJ->getId(), $gapIndex, self::FB_SELECT_GAP_EMPTY_INDEX, $value
+ );
+ }
+
+ protected function saveFbPropsForNumericGap(ilPropertyFormGUI $form, $gapIndex, assClozeGap $gap)
+ {
+ $postVar = $this->buildPostVarForFbFieldPerGapAnswers($gapIndex, self::FB_NUMERIC_GAP_VALUE_HIT_INDEX);
+ $value = $form->getItemByPostVar($postVar)->getValue();
+ $this->saveSpecificAnswerFeedbackContent(
+ $this->questionOBJ->getId(), $gapIndex, self::FB_NUMERIC_GAP_VALUE_HIT_INDEX, $value
+ );
+
+ if( $gap->numericRangeExists() )
+ {
+ $postVar = $this->buildPostVarForFbFieldPerGapAnswers($gapIndex, self::FB_NUMERIC_GAP_RANGE_HIT_INDEX);
+ $value = $form->getItemByPostVar($postVar)->getValue();
+ $this->saveSpecificAnswerFeedbackContent(
+ $this->questionOBJ->getId(), $gapIndex, self::FB_NUMERIC_GAP_RANGE_HIT_INDEX, $value
+ );
+ }
+
+ $postVar = $this->buildPostVarForFbFieldPerGapAnswers($gapIndex, self::FB_NUMERIC_GAP_TOO_LOW_INDEX);
+ $value = $form->getItemByPostVar($postVar)->getValue();
+ $this->saveSpecificAnswerFeedbackContent(
+ $this->questionOBJ->getId(), $gapIndex, self::FB_NUMERIC_GAP_TOO_LOW_INDEX, $value
+ );
+
+ $postVar = $this->buildPostVarForFbFieldPerGapAnswers($gapIndex, self::FB_NUMERIC_GAP_TOO_HIGH_INDEX);
+ $value = $form->getItemByPostVar($postVar)->getValue();
+ $this->saveSpecificAnswerFeedbackContent(
+ $this->questionOBJ->getId(), $gapIndex, self::FB_NUMERIC_GAP_TOO_HIGH_INDEX, $value
+ );
+
+ $postVar = $this->buildPostVarForFbFieldPerGapAnswers($gapIndex, self::FB_NUMERIC_GAP_EMPTY_INDEX);
+ $value = $form->getItemByPostVar($postVar)->getValue();
+ $this->saveSpecificAnswerFeedbackContent(
+ $this->questionOBJ->getId(), $gapIndex, self::FB_NUMERIC_GAP_EMPTY_INDEX, $value
+ );
+ }
+
+ /**
+ * duplicates the SPECIFIC feedback relating to the given original question id
+ * and saves it for the given duplicate question id
+ *
+ * (overwrites the method from parent class, because of individual setting)
+ *
+ * @access protected
+ * @param integer $originalQuestionId
+ * @param integer $duplicateQuestionId
+ */
+ protected function duplicateSpecificFeedback($originalQuestionId, $duplicateQuestionId)
+ {
+ // sync specific feedback setting to duplicated question
+
+ $this->syncSpecificFeedbackSetting($originalQuestionId, $duplicateQuestionId);
+
+ parent::duplicateSpecificFeedback($originalQuestionId, $duplicateQuestionId);
+ }
+
+ private function syncSpecificFeedbackSetting($sourceQuestionId, $targetQuestionId)
+ {
+ $res = $this->db->queryF(
+ "SELECT feedback_mode FROM {$this->questionOBJ->getAdditionalTableName()} WHERE question_fi = %s",
+ array('integer'), array($sourceQuestionId)
+ );
+
+ $row = $this->db->fetchAssoc($res);
+
+ $this->db->update( $this->questionOBJ->getAdditionalTableName(),
+ array( 'feedback_mode' => array('text', $row['feedback_mode']) ),
+ array( 'question_fi' => array('integer', $targetQuestionId) )
+ );
+ }
+
+ protected function syncSpecificFeedback($originalQuestionId, $duplicateQuestionId)
+ {
+ $this->syncSpecificFeedbackSetting($originalQuestionId, $duplicateQuestionId);
+ parent::syncSpecificFeedback($originalQuestionId, $duplicateQuestionId);
+ }
+
+ /**
+ * saves the given specific feedback mode for the given question id to the db.
+ * (It's stored to dataset of question itself)
+ * @param integer $questionId
+ * @param string $feedbackMode
+ */
+ protected function saveSpecificFeedbackMode($questionId, $feedbackMode)
{
- $caption = 'Gap '.$ordinal = $index+1 .': ';
+ $this->questionOBJ->setFeedbackMode($feedbackMode);
- foreach( $answer->items as $item )
+ $this->db->update($this->questionOBJ->getAdditionalTableName(),
+ array('feedback_mode' => array('text', $feedbackMode)),
+ array('question_fi' => array('integer', $questionId))
+ );
+ }
+
+ /**
+ * @param integer $gapIndex
+ * @return string
+ */
+ protected function buildPostVarForFbFieldPerGapQuestion($gapIndex)
+ {
+ return "feedback_answer_{$gapIndex}";
+ }
+
+ /**
+ * @param integer $gapIndex
+ * @param integer $answerIndex
+ * @return string
+ */
+ protected function buildPostVarForFbFieldPerGapAnswers($gapIndex, $answerIndex)
+ {
+ return "feedback_answer_{$gapIndex}_{$answerIndex}";
+ }
+
+ /**
+ * @param $gapIndex
+ * @param $answerIndex
+ * @return mixed|string
+ */
+ protected function getSpecificAnswerFeedbackFormValue($gapIndex, $answerIndex)
+ {
+ if ($this->questionOBJ->isAdditionalContentEditingModePageObject())
{
- $caption .= '"' . $item->getAnswertext().'" / ';
+ $pageObjectId = $this->getSpecificAnswerFeedbackPageObjectId(
+ $this->questionOBJ->getId(), $gapIndex, $answerIndex
+ );
+
+ $value = $this->getPageObjectNonEditableValueHTML(
+ $this->getSpecificAnswerFeedbackPageObjectType(), $pageObjectId
+ );
+ }
+ else
+ {
+ $value = $this->questionOBJ->prepareTextareaOutput(
+ $this->getSpecificAnswerFeedbackContent($this->questionOBJ->getId(), $gapIndex, $answerIndex)
+ );
}
- $caption = substr($caption, 0, strlen($caption)-3);
- $caption .= '';
+ return $value;
+ }
+
+ protected function cleanupSpecificAnswerFeedbacks($fbMode)
+ {
+ switch($fbMode)
+ {
+ case self::FB_MODE_GAP_QUESTION:
+ $feedbackIds = $this->fetchFeedbackIdsForGapQuestionMode();
+ break;
+
+ case self::FB_MODE_GAP_ANSWERS:
+ $feedbackIds = $this->fetchFeedbackIdsForGapAnswersMode();
+ break;
+
+ default: $feedbackIds = array();
+ }
+
+ $this->deleteSpecificAnswerFeedbacksByIds($feedbackIds);
+ }
+
+ protected function fetchFeedbackIdsForGapQuestionMode()
+ {
+ require_once 'Modules/TestQuestionPool/classes/feedback/class.ilAssSpecificFeedbackIdentifierList.php';
+ $feedbackIdentifiers = new ilAssSpecificFeedbackIdentifierList();
+ $feedbackIdentifiers->load($this->questionOBJ->getId());
+
+ $feedbackIds = array();
+
+ foreach($feedbackIdentifiers as $identifier)
+ {
+ if( $identifier->getAnswerIndex() != self::SINGLE_GAP_FB_ANSWER_INDEX )
+ {
+ continue;
+ }
+
+ $feedbackIds[] = $identifier->getFeedbackId();
+ }
+
+ return $feedbackIds;
+ }
+
+ protected function fetchFeedbackIdsForGapAnswersMode()
+ {
+ require_once 'Modules/TestQuestionPool/classes/feedback/class.ilAssSpecificFeedbackIdentifierList.php';
+ $feedbackIdentifiers = new ilAssSpecificFeedbackIdentifierList();
+ $feedbackIdentifiers->load($this->questionOBJ->getId());
+
+ $feedbackIds = array();
+
+ foreach($feedbackIdentifiers as $identifier)
+ {
+ if( $identifier->getAnswerIndex() == self::SINGLE_GAP_FB_ANSWER_INDEX )
+ {
+ continue;
+ }
+
+ $feedbackIds[] = $identifier->getFeedbackId();
+ }
- return $caption;
+ return $feedbackIds;
+ }
+
+ protected function deleteSpecificAnswerFeedbacksByIds($feedbackIds)
+ {
+ if( $this->questionOBJ->isAdditionalContentEditingModePageObject() )
+ {
+ foreach( $feedbackIds as $fbId )
+ {
+ $this->ensurePageObjectDeleted($this->getSpecificAnswerFeedbackPageObjectType(), $fbId);
+ }
+ }
+
+ $IN_feedbackIds = $this->db->in('feedback_id', $feedbackIds, false, 'integer');
+ $this->db->manipulate("DELETE FROM {$this->getSpecificFeedbackTableName()} WHERE {$IN_feedbackIds}");
+ }
+
+ public function determineTestOutputGapFeedback($gapIndex, $answerIndex)
+ {
+ if( $this->questionOBJ->getFeedbackMode() == self::FB_MODE_GAP_QUESTION )
+ {
+ return $this->getSpecificAnswerFeedbackTestPresentation(
+ $this->questionOBJ->getId(), $gapIndex, self::SINGLE_GAP_FB_ANSWER_INDEX
+ );
+ }
+
+ return $this->getSpecificAnswerFeedbackTestPresentation($this->questionOBJ->getId(), $gapIndex, $answerIndex);
+ }
+
+ public function determineAnswerIndexForAnswerValue(assClozeGap $gap, $answerValue)
+ {
+ switch( $gap->getType() )
+ {
+ case CLOZE_TEXT:
+
+ if( !strlen($answerValue) )
+ {
+ return self::FB_TEXT_GAP_EMPTY_INDEX;
+ }
+
+ $items = $gap->getItems(new ilArrayElementOrderKeeper());
+
+ foreach($items as $answerIndex => $answer)
+ {
+ /* @var assAnswerCloze $answer */
+
+ if( $answer->getAnswertext() == $answerValue )
+ {
+ return $answerIndex;
+ }
+ }
+
+ return self::FB_TEXT_GAP_NOMATCH_INDEX;
+
+ case CLOZE_SELECT:
+
+ if( strlen($answerValue) )
+ {
+ return $answerValue;
+ }
+
+ return self::FB_SELECT_GAP_EMPTY_INDEX;
+
+ case CLOZE_NUMERIC:
+
+ if( !strlen($answerValue) )
+ {
+ return self::FB_NUMERIC_GAP_EMPTY_INDEX;
+ }
+
+ /* @var assAnswerCloze $item */
+
+ $item = current($gap->getItems(new ilArrayElementOrderKeeper()));
+
+ if( $answerValue == $item->getAnswertext() )
+ {
+ return self::FB_NUMERIC_GAP_VALUE_HIT_INDEX;
+ }
+
+ require_once 'Services/Math/classes/class.EvalMath.php';
+ $math = new EvalMath();
+
+ $item = $gap->getItem(0);
+ $lowerBound = $math->evaluate($item->getLowerBound());
+ $upperBound = $math->evaluate($item->getUpperBound());
+ $preciseValue = $math->evaluate($item->getAnswertext());
+
+ $solutionValue = $math->evaluate($answerValue);
+
+ if( $solutionValue == $preciseValue )
+ {
+ return self::FB_NUMERIC_GAP_VALUE_HIT_INDEX;
+ }
+
+ if( $solutionValue >= $lowerBound && $solutionValue <= $upperBound )
+ {
+ return self::FB_NUMERIC_GAP_RANGE_HIT_INDEX;
+ }
+
+ if( $solutionValue < $lowerBound )
+ {
+ return self::FB_NUMERIC_GAP_TOO_LOW_INDEX;
+ }
+
+ if( $solutionValue > $upperBound )
+ {
+ return self::FB_NUMERIC_GAP_TOO_HIGH_INDEX;
+ }
+ }
}
}
diff --git a/Modules/TestQuestionPool/classes/feedback/class.ilAssConfigurableMultiOptionQuestionFeedback.php b/Modules/TestQuestionPool/classes/feedback/class.ilAssConfigurableMultiOptionQuestionFeedback.php
index 8a9913d05411..c189640dbfa3 100644
--- a/Modules/TestQuestionPool/classes/feedback/class.ilAssConfigurableMultiOptionQuestionFeedback.php
+++ b/Modules/TestQuestionPool/classes/feedback/class.ilAssConfigurableMultiOptionQuestionFeedback.php
@@ -100,13 +100,13 @@ public function initSpecificFormProperties(ilPropertyFormGUI $form)
{
$value = $this->getPageObjectNonEditableValueHTML(
$this->getSpecificAnswerFeedbackPageObjectType(),
- $this->getSpecificAnswerFeedbackPageObjectId($this->questionOBJ->getId(), $index)
+ $this->getSpecificAnswerFeedbackPageObjectId($this->questionOBJ->getId(), 0, $index)
);
}
else
{
$value = $this->questionOBJ->prepareTextareaOutput(
- $this->getSpecificAnswerFeedbackContent($this->questionOBJ->getId(), $index)
+ $this->getSpecificAnswerFeedbackContent($this->questionOBJ->getId(), 0, $index)
);
}
@@ -133,7 +133,7 @@ public function saveSpecificFormProperties(ilPropertyFormGUI $form)
foreach( $this->getAnswerOptionsByAnswerIndex() as $index => $answer )
{
$this->saveSpecificAnswerFeedbackContent(
- $this->questionOBJ->getId(), $index, $form->getInput("feedback_answer_$index")
+ $this->questionOBJ->getId(), 0, $index, $form->getInput("feedback_answer_$index")
);
}
}
@@ -182,30 +182,7 @@ protected function duplicateSpecificFeedback($originalQuestionId, $duplicateQues
$this->syncSpecificFeedbackSetting($originalQuestionId, $duplicateQuestionId);
- // sync specific answer feedback to duplicated question
-
- $res = $this->db->queryF(
- "SELECT * FROM {$this->getSpecificFeedbackTableName()} WHERE question_fi = %s", array('integer'), array($originalQuestionId)
- );
-
- while( $row = $this->db->fetchAssoc($res) )
- {
- $nextId = $this->db->nextId($this->getSpecificFeedbackTableName());
-
- $this->db->insert($this->getSpecificFeedbackTableName(), array(
- 'feedback_id' => array('integer', $nextId),
- 'question_fi' => array('integer', $duplicateQuestionId),
- 'answer' => array('integer', $row['answer']),
- 'feedback' => array('text', $row['feedback']),
- 'tstamp' => array('integer', time())
- ));
-
- if( $this->questionOBJ->isAdditionalContentEditingModePageObject() )
- {
- $pageObjectType = $this->getSpecificAnswerFeedbackPageObjectType();
- $this->duplicatePageObject($pageObjectType, $row['feedback_id'], $nextId, $duplicateQuestionId);
- }
- }
+ parent::duplicateSpecificFeedback($originalQuestionId, $duplicateQuestionId);
}
/**
@@ -222,31 +199,7 @@ protected function syncSpecificFeedback($originalQuestionId, $duplicateQuestionI
// sync specific feedback setting to the original
$this->syncSpecificFeedbackSetting($duplicateQuestionId, $originalQuestionId);
- // delete specific feedback of the original
- $this->db->manipulateF(
- "DELETE FROM {$this->getSpecificFeedbackTableName()} WHERE question_fi = %s",
- array('integer'), array($originalQuestionId)
- );
-
- // get specific feedback of the actual question
- $res = $this->db->queryF(
- "SELECT * FROM {$this->getSpecificFeedbackTableName()} WHERE question_fi = %s",
- array('integer'), array($duplicateQuestionId)
- );
-
- // save specific feedback to the original
- while( $row = $this->db->fetchAssoc($res) )
- {
- $nextId = $this->db->nextId($this->getSpecificFeedbackTableName());
-
- $this->db->insert($this->getSpecificFeedbackTableName(), array(
- 'feedback_id' => array('integer', $nextId),
- 'question_fi' => array('integer', $originalQuestionId),
- 'answer' => array('integer',$row['answer']),
- 'feedback' => array('text',$row['feedback']),
- 'tstamp' => array('integer',time())
- ));
- }
+ parent::syncSpecificFeedback($originalQuestionId, $duplicateQuestionId);
}
private function syncSpecificFeedbackSetting($sourceQuestionId, $targetQuestionId)
diff --git a/Modules/TestQuestionPool/classes/feedback/class.ilAssMultiOptionQuestionFeedback.php b/Modules/TestQuestionPool/classes/feedback/class.ilAssMultiOptionQuestionFeedback.php
index 350bec9c6eec..e1d9f2257c82 100644
--- a/Modules/TestQuestionPool/classes/feedback/class.ilAssMultiOptionQuestionFeedback.php
+++ b/Modules/TestQuestionPool/classes/feedback/class.ilAssMultiOptionQuestionFeedback.php
@@ -27,22 +27,23 @@ abstract class ilAssMultiOptionQuestionFeedback extends ilAssQuestionFeedback
*
* @access public
* @param integer $questionId
+ * @param integer $questionIndex
* @param integer $answerIndex
* @return string $specificAnswerFeedbackTestPresentationHTML
*/
- public function getSpecificAnswerFeedbackTestPresentation($questionId, $answerIndex)
+ public function getSpecificAnswerFeedbackTestPresentation($questionId, $questionIndex, $answerIndex)
{
if( $this->questionOBJ->isAdditionalContentEditingModePageObject() )
{
$specificAnswerFeedbackTestPresentationHTML = $this->getPageObjectContent(
$this->getSpecificAnswerFeedbackPageObjectType(),
- $this->getSpecificAnswerFeedbackPageObjectId($questionId, $answerIndex)
+ $this->getSpecificAnswerFeedbackPageObjectId($questionId, $questionIndex, $answerIndex)
);
}
else
{
$specificAnswerFeedbackTestPresentationHTML = $this->getSpecificAnswerFeedbackContent(
- $questionId, $answerIndex
+ $questionId, $questionIndex, $answerIndex
);
}
@@ -96,13 +97,13 @@ public function initSpecificFormProperties(ilPropertyFormGUI $form)
{
$value = $this->getPageObjectNonEditableValueHTML(
$this->getSpecificAnswerFeedbackPageObjectType(),
- $this->getSpecificAnswerFeedbackPageObjectId($this->questionOBJ->getId(), $index)
+ $this->getSpecificAnswerFeedbackPageObjectId($this->questionOBJ->getId(), 0, $index)
);
}
else
{
$value = $this->questionOBJ->prepareTextareaOutput(
- $this->getSpecificAnswerFeedbackContent($this->questionOBJ->getId(), $index)
+ $this->getSpecificAnswerFeedbackContent($this->questionOBJ->getId(), 0, $index)
);
}
@@ -125,7 +126,7 @@ public function saveSpecificFormProperties(ilPropertyFormGUI $form)
foreach( $this->getAnswerOptionsByAnswerIndex() as $index => $answer )
{
$this->saveSpecificAnswerFeedbackContent(
- $this->questionOBJ->getId(), $index, $form->getInput("feedback_answer_$index")
+ $this->questionOBJ->getId(), 0, $index, $form->getInput("feedback_answer_$index")
);
}
}
@@ -136,16 +137,18 @@ public function saveSpecificFormProperties(ilPropertyFormGUI $form)
*
* @access public
* @param integer $questionId
- * @param boolean $answerIndex
+ * @param integer $questionIndex
+ * @param integer $answerIndex
* @return string $feedbackContent
*/
- public function getSpecificAnswerFeedbackContent($questionId, $answerIndex)
+ public function getSpecificAnswerFeedbackContent($questionId, $questionIndex, $answerIndex)
{
require_once 'Services/RTE/classes/class.ilRTE.php';
$res = $this->db->queryF(
- "SELECT * FROM {$this->getSpecificFeedbackTableName()} WHERE question_fi = %s AND answer = %s",
- array('integer','integer'), array($questionId, $answerIndex)
+ "SELECT * FROM {$this->getSpecificFeedbackTableName()}
+ WHERE question_fi = %s AND question = %s AND answer = %s",
+ array('integer','integer','integer'), array($questionId, $questionIndex, $answerIndex)
);
while( $row = $this->db->fetchAssoc($res) )
@@ -189,11 +192,12 @@ public function getAllSpecificAnswerFeedbackContents($questionId)
*
* @access public
* @param integer $questionId
+ * @param integer $questionIndex
* @param integer $answerIndex
* @param string $feedbackContent
* @return integer $feedbackId
*/
- public function saveSpecificAnswerFeedbackContent($questionId, $answerIndex, $feedbackContent)
+ public function saveSpecificAnswerFeedbackContent($questionId, $questionIndex, $answerIndex, $feedbackContent)
{
require_once 'Services/RTE/classes/class.ilRTE.php';
@@ -202,7 +206,7 @@ public function saveSpecificAnswerFeedbackContent($questionId, $answerIndex, $fe
$feedbackContent = ilRTE::_replaceMediaObjectImageSrc($feedbackContent, 0);
}
- $feedbackId = $this->getSpecificAnswerFeedbackId($questionId, $answerIndex);
+ $feedbackId = $this->getSpecificAnswerFeedbackId($questionId, $questionIndex, $answerIndex);
if( $feedbackId )
{
@@ -223,6 +227,7 @@ public function saveSpecificAnswerFeedbackContent($questionId, $answerIndex, $fe
$this->db->insert($this->getSpecificFeedbackTableName(), array(
'feedback_id' => array('integer', $feedbackId),
'question_fi' => array('integer', $questionId),
+ 'question' => array('integer', $questionIndex),
'answer' => array('integer', $answerIndex),
'feedback' => array('text', $feedbackContent),
'tstamp' => array('integer', time())
@@ -244,9 +249,15 @@ public function deleteSpecificAnswerFeedbacks($questionId, $isAdditionalContentE
{
if( $isAdditionalContentEditingModePageObject )
{
- foreach( $this->getSpecificAnswerFeedbackIdByAnswerIndexMap($questionId) as $answerIndex => $pageObjectId )
+ require_once 'Modules/TestQuestionPool/classes/feedback/class.ilAssSpecificFeedbackIdentifierList.php';
+ $feedbackIdentifiers = new ilAssSpecificFeedbackIdentifierList();
+ $feedbackIdentifiers->load($questionId);
+
+ foreach( $feedbackIdentifiers as $identifier )
{
- $this->ensurePageObjectDeleted($this->getSpecificAnswerFeedbackPageObjectType(), $pageObjectId);
+ $this->ensurePageObjectDeleted(
+ $this->getSpecificAnswerFeedbackPageObjectType(), $identifier->getFeedbackId()
+ );
}
}
@@ -255,6 +266,7 @@ public function deleteSpecificAnswerFeedbacks($questionId, $isAdditionalContentE
array('integer'), array($questionId)
);
}
+
/**
* duplicates the SPECIFIC feedback relating to the given original question id
* and saves it for the given duplicate question id
@@ -277,6 +289,7 @@ protected function duplicateSpecificFeedback($originalQuestionId, $duplicateQues
$this->db->insert($this->getSpecificFeedbackTableName(), array(
'feedback_id' => array('integer', $nextId),
'question_fi' => array('integer', $duplicateQuestionId),
+ 'question' => array('integer', $row['question']),
'answer' => array('integer', $row['answer']),
'feedback' => array('text', $row['feedback']),
'tstamp' => array('integer', time())
@@ -317,6 +330,7 @@ protected function syncSpecificFeedback($originalQuestionId, $duplicateQuestionI
$this->db->insert($this->getSpecificFeedbackTableName(), array(
'feedback_id' => array('integer', $nextId),
'question_fi' => array('integer', $originalQuestionId),
+ 'question' => array('integer',$row['question']),
'answer' => array('integer',$row['answer']),
'feedback' => array('text',$row['feedback']),
'tstamp' => array('integer',time())
@@ -333,11 +347,12 @@ protected function syncSpecificFeedback($originalQuestionId, $duplicateQuestionI
* @param boolean $answerIndex
* @return string $feedbackId
*/
- final protected function getSpecificAnswerFeedbackId($questionId, $answerIndex)
+ final protected function getSpecificAnswerFeedbackId($questionId, $questionIndex, $answerIndex)
{
$res = $this->db->queryF(
- "SELECT feedback_id FROM {$this->getSpecificFeedbackTableName()} WHERE question_fi = %s AND answer = %s",
- array('integer','integer'), array($questionId, $answerIndex)
+ "SELECT feedback_id FROM {$this->getSpecificFeedbackTableName()}
+ WHERE question_fi = %s AND question = %s AND answer = %s",
+ array('integer','integer','integer'), array($questionId, $questionIndex, $answerIndex)
);
$feedbackId = null;
@@ -350,32 +365,6 @@ final protected function getSpecificAnswerFeedbackId($questionId, $answerIndex)
return $feedbackId;
}
-
- /**
- * returns an array mapping feedback ids to answer indexes
- * for all answer options of question
- *
- * @final
- * @access protected
- * @param integer $questionId
- * @return array $feedbackIdByAnswerIndexMap
- */
- final protected function getSpecificAnswerFeedbackIdByAnswerIndexMap($questionId)
- {
- $res = $this->db->queryF(
- "SELECT feedback_id, answer FROM {$this->getSpecificFeedbackTableName()} WHERE question_fi = %s",
- array('integer'), array($questionId)
- );
-
- $feedbackIdByAnswerIndexMap = array();
-
- while( $row = $this->db->fetchAssoc($res) )
- {
- $feedbackIdByAnswerIndexMap[ $row['answer'] ] = $row['feedback_id'];
- }
-
- return $feedbackIdByAnswerIndexMap;
- }
/**
* returns the table name for specific feedback
@@ -421,16 +410,17 @@ protected function buildAnswerOptionLabel($index, $answer)
* @final
* @access protected
* @param integer $questionId
+ * @param integer $questionIndex
* @param integer $answerIndex
* @return integer $pageObjectId
*/
- final protected function getSpecificAnswerFeedbackPageObjectId($questionId, $answerIndex)
+ final protected function getSpecificAnswerFeedbackPageObjectId($questionId, $questionIndex, $answerIndex)
{
- $pageObjectId = $this->getSpecificAnswerFeedbackId($questionId, $answerIndex);
+ $pageObjectId = $this->getSpecificAnswerFeedbackId($questionId, $questionIndex, $answerIndex);
if( !$pageObjectId )
{
- $pageObjectId = $this->saveSpecificAnswerFeedbackContent($questionId, $answerIndex, null);
+ $pageObjectId = $this->saveSpecificAnswerFeedbackContent($questionId, $questionIndex, $answerIndex, null);
}
return $pageObjectId;
@@ -442,22 +432,23 @@ final protected function getSpecificAnswerFeedbackPageObjectId($questionId, $ans
*
* @access public
* @param integer $questionId
+ * @param integer $questionIndex
* @param integer $answerIndex
* @return string $specificAnswerFeedbackExportPresentation
*/
- public function getSpecificAnswerFeedbackExportPresentation($questionId, $answerIndex)
+ public function getSpecificAnswerFeedbackExportPresentation($questionId, $questionIndex, $answerIndex)
{
if( $this->questionOBJ->isAdditionalContentEditingModePageObject() )
{
$specificAnswerFeedbackExportPresentation = $this->getPageObjectXML(
$this->getSpecificAnswerFeedbackPageObjectType(),
- $this->getSpecificAnswerFeedbackPageObjectId($questionId, $answerIndex)
+ $this->getSpecificAnswerFeedbackPageObjectId($questionId, $questionIndex, $answerIndex)
);
}
else
{
$specificAnswerFeedbackExportPresentation = $this->getSpecificAnswerFeedbackContent(
- $questionId, $answerIndex
+ $questionId, $questionIndex, $answerIndex
);
}
@@ -470,36 +461,29 @@ public function getSpecificAnswerFeedbackExportPresentation($questionId, $answer
*
* @access public
* @param integer $questionId
+ * @param integer $questionIndex
* @param integer $answerIndex
* @param string $feedbackContent
*/
- public function importSpecificAnswerFeedback($questionId, $answerIndex, $feedbackContent)
+ public function importSpecificAnswerFeedback($questionId, $questionIndex, $answerIndex, $feedbackContent)
{
if( $this->questionOBJ->isAdditionalContentEditingModePageObject() )
{
- $pageObjectId = $this->getSpecificAnswerFeedbackPageObjectId($questionId, $answerIndex);
+ $pageObjectId = $this->getSpecificAnswerFeedbackPageObjectId($questionId, $questionIndex, $answerIndex);
$pageObjectType = $this->getSpecificAnswerFeedbackPageObjectType();
$this->createPageObject($pageObjectType, $pageObjectId, $feedbackContent);
}
else
{
- $this->saveSpecificAnswerFeedbackContent($questionId, $answerIndex, $feedbackContent);
+ $this->saveSpecificAnswerFeedbackContent($questionId, $questionIndex, $answerIndex, $feedbackContent);
}
}
- public function specificAnswerFeedbackExists($answerIndexes)
+ public function specificAnswerFeedbackExists()
{
- foreach($answerIndexes as $answerIndex)
- {
- $fb = $this->getSpecificAnswerFeedbackExportPresentation($this->questionOBJ->getId(), $answerIndex);
-
- if( strlen($fb) )
- {
- return true;
- }
- }
-
- return false;
+ return (bool)strlen(
+ $this->getAllSpecificAnswerFeedbackContents($this->questionOBJ->getId())
+ );
}
}
diff --git a/Modules/TestQuestionPool/classes/feedback/class.ilAssQuestionFeedback.php b/Modules/TestQuestionPool/classes/feedback/class.ilAssQuestionFeedback.php
index b6771690a3dc..e9da7f2c4459 100644
--- a/Modules/TestQuestionPool/classes/feedback/class.ilAssQuestionFeedback.php
+++ b/Modules/TestQuestionPool/classes/feedback/class.ilAssQuestionFeedback.php
@@ -133,10 +133,11 @@ public function getGenericFeedbackTestPresentation($questionId, $solutionComplet
* @abstract
* @access public
* @param integer $questionId
+ * @param integer $questionIndex
* @param integer $answerIndex
* @return string $specificAnswerFeedbackTestPresentationHTML
*/
- abstract public function getSpecificAnswerFeedbackTestPresentation($questionId, $answerIndex);
+ abstract public function getSpecificAnswerFeedbackTestPresentation($questionId, $questionIndex, $answerIndex);
/**
* completes a given form object with the GENERIC form properties
@@ -351,10 +352,11 @@ final public function getGenericFeedbackContent($questionId, $solutionCompleted)
* @abstract
* @access public
* @param integer $questionId
+ * @param integer $questionIndex
* @param integer $answerIndex
* @return string $feedbackContent
*/
- abstract public function getSpecificAnswerFeedbackContent($questionId, $answerIndex);
+ abstract public function getSpecificAnswerFeedbackContent($questionId, $questionIndex, $answerIndex);
/**
* returns the SPECIFIC feedback content for a given question id and answer index.
@@ -437,11 +439,12 @@ final public function saveGenericFeedbackContent($questionId, $solutionCompleted
* @abstract
* @access public
* @param integer $questionId
+ * @param integer $questionIndex
* @param integer $answerIndex
* @param string $feedbackContent
* @return integer $feedbackId
*/
- abstract public function saveSpecificAnswerFeedbackContent($questionId, $answerIndex, $feedbackContent);
+ abstract public function saveSpecificAnswerFeedbackContent($questionId, $questionIndex, $answerIndex, $feedbackContent);
/**
* deletes all GENERIC feedback contents (and page objects if required)
@@ -688,8 +691,8 @@ function getClassNameByType($a_type, $a_gui = false)
*
* @final
* @access private
- * @param type $pageObjectType
- * @param type $pageObjectId
+ * @param string $pageObjectType
+ * @param integer $pageObjectId
* @return string $pageObjectEditingLink
*/
final private function getPageObjectEditingLink($pageObjectType, $pageObjectId)
@@ -729,8 +732,8 @@ final public function getPageObjectOutputMode()
*
* @final
* @access protected
- * @param type $pageObjectType
- * @param type $pageObjectId
+ * @param string $pageObjectType
+ * @param integer $pageObjectId
* @return string $pageObjectContent
*/
final protected function getPageObjectContent($pageObjectType, $pageObjectId)
@@ -757,8 +760,8 @@ final protected function getPageObjectContent($pageObjectType, $pageObjectId)
*
* @final
* @access protected
- * @param type $pageObjectType
- * @param type $pageObjectId
+ * @param string $pageObjectType
+ * @param integer $pageObjectId
* @return string $pageObjectXML
*/
final protected function getPageObjectXML($pageObjectType, $pageObjectId)
@@ -777,8 +780,8 @@ final protected function getPageObjectXML($pageObjectType, $pageObjectId)
*
* @final
* @access private
- * @param type $pageObjectType
- * @param type $pageObjectId
+ * @param string $pageObjectType
+ * @param integer $pageObjectId
*/
final private function ensurePageObjectExists($pageObjectType, $pageObjectId)
{
@@ -855,8 +858,8 @@ final protected function duplicatePageObject($pageObjectType, $originalPageObjec
*
* @final
* @access protected
- * @param type $pageObjectType
- * @param type $pageObjectId
+ * @param string $pageObjectType
+ * @param integer $pageObjectId
*/
final protected function ensurePageObjectDeleted($pageObjectType, $pageObjectId)
{
@@ -985,10 +988,11 @@ public function getGenericFeedbackExportPresentation($questionId, $solutionCompl
* @abstract
* @access public
* @param integer $questionId
+ * @param integer $questionIndex
* @param integer $answerIndex
* @return string $specificFeedbackExportPresentation
*/
- abstract public function getSpecificAnswerFeedbackExportPresentation($questionId, $answerIndex);
+ abstract public function getSpecificAnswerFeedbackExportPresentation($questionId, $questionIndex, $answerIndex);
/**
* imports the given feedback content as generic feedback for the given question id
@@ -1021,10 +1025,11 @@ public function importGenericFeedback($questionId, $solutionCompleted, $feedback
* @abstract
* @access public
* @param integer $questionId
+ * @param integer $questionIndex
* @param integer $answerIndex
* @param string $feedbackContent
*/
- abstract public function importSpecificAnswerFeedback($questionId, $answerIndex, $feedbackContent);
+ abstract public function importSpecificAnswerFeedback($questionId, $questionIndex, $answerIndex, $feedbackContent);
/**
* @param ilAssSelfAssessmentMigrator $migrator
diff --git a/Modules/TestQuestionPool/classes/feedback/class.ilAssSingleOptionQuestionFeedback.php b/Modules/TestQuestionPool/classes/feedback/class.ilAssSingleOptionQuestionFeedback.php
index ceff1133b4a0..bdf212c85d8d 100644
--- a/Modules/TestQuestionPool/classes/feedback/class.ilAssSingleOptionQuestionFeedback.php
+++ b/Modules/TestQuestionPool/classes/feedback/class.ilAssSingleOptionQuestionFeedback.php
@@ -22,10 +22,11 @@ abstract class ilAssSingleOptionQuestionFeedback extends ilAssQuestionFeedback
*
* @access public
* @param integer $questionId
+ * @param integer $questionIndex
* @param integer $answerIndex
* @return string $specificAnswerFeedbackTestPresentationHTML
*/
- public function getSpecificAnswerFeedbackTestPresentation($questionId, $answerIndex)
+ public function getSpecificAnswerFeedbackTestPresentation($questionId, $questionIndex, $answerIndex)
{
return null;
}
@@ -68,10 +69,11 @@ public function saveSpecificFormProperties(ilPropertyFormGUI $form)
*
* @access public
* @param integer $questionId
+ * @param integer $questionIndex
* @param boolean $answerIndex
* @return string $feedbackContent
*/
- public function getSpecificAnswerFeedbackContent($questionId, $answerIndex)
+ public function getSpecificAnswerFeedbackContent($questionId, $questionIndex, $answerIndex)
{
return '';
}
@@ -94,11 +96,12 @@ public function getAllSpecificAnswerFeedbackContents($questionId)
*
* @access public
* @param integer $questionId
+ * @param integer $questionIndex
* @param integer $answerIndex
* @param string $feedbackContent
* @return integer $feedbackId
*/
- public function saveSpecificAnswerFeedbackContent($questionId, $answerIndex, $feedbackContent)
+ public function saveSpecificAnswerFeedbackContent($questionId, $questionIndex, $answerIndex, $feedbackContent)
{
return null;
}
@@ -144,10 +147,11 @@ protected function syncSpecificFeedback($originalQuestionId, $duplicateQuestionI
*
* @access public
* @param integer $questionId
+ * @param integer $questionIndex
* @param integer $answerIndex
* @return string $specificAnswerFeedbackExportPresentation
*/
- public function getSpecificAnswerFeedbackExportPresentation($questionId, $answerIndex)
+ public function getSpecificAnswerFeedbackExportPresentation($questionId, $questionIndex, $answerIndex)
{
return null;
}
@@ -158,10 +162,11 @@ public function getSpecificAnswerFeedbackExportPresentation($questionId, $answer
*
* @access public
* @param integer $questionId
+ * @param integer $questionIndex
* @param integer $answerIndex
* @param string $feedbackContent
*/
- public function importSpecificAnswerFeedback($questionId, $answerIndex, $feedbackContent)
+ public function importSpecificAnswerFeedback($questionId, $questionIndex, $answerIndex, $feedbackContent)
{
}
}
diff --git a/Modules/TestQuestionPool/classes/feedback/class.ilAssSpecificFeedbackIdentifier.php b/Modules/TestQuestionPool/classes/feedback/class.ilAssSpecificFeedbackIdentifier.php
new file mode 100644
index 000000000000..752a905c4b67
--- /dev/null
+++ b/Modules/TestQuestionPool/classes/feedback/class.ilAssSpecificFeedbackIdentifier.php
@@ -0,0 +1,98 @@
+
+ * @version $Id$
+ *
+ * @package Modules/TestQuestionPool
+ */
+class ilAssSpecificFeedbackIdentifier
+{
+ /**
+ * @var integer
+ */
+ protected $feedbackId;
+
+ /**
+ * @var integer
+ */
+ protected $questionId;
+
+ /**
+ * @var integer
+ */
+ protected $questionIndex;
+
+ /**
+ * @var integer
+ */
+ protected $answerIndex;
+
+ /**
+ * @return int
+ */
+ public function getFeedbackId()
+ {
+ return $this->feedbackId;
+ }
+
+ /**
+ * @param int $feedbackId
+ */
+ public function setFeedbackId($feedbackId)
+ {
+ $this->feedbackId = $feedbackId;
+ }
+
+ /**
+ * @return int
+ */
+ public function getQuestionId()
+ {
+ return $this->questionId;
+ }
+
+ /**
+ * @param int $questionId
+ */
+ public function setQuestionId($questionId)
+ {
+ $this->questionId = $questionId;
+ }
+
+ /**
+ * @return int
+ */
+ public function getQuestionIndex()
+ {
+ return $this->questionIndex;
+ }
+
+ /**
+ * @param int $questionIndex
+ */
+ public function setQuestionIndex($questionIndex)
+ {
+ $this->questionIndex = $questionIndex;
+ }
+
+ /**
+ * @return int
+ */
+ public function getAnswerIndex()
+ {
+ return $this->answerIndex;
+ }
+
+ /**
+ * @param int $answerIndex
+ */
+ public function setAnswerIndex($answerIndex)
+ {
+ $this->answerIndex = $answerIndex;
+ }
+}
\ No newline at end of file
diff --git a/Modules/TestQuestionPool/classes/feedback/class.ilAssSpecificFeedbackIdentifierList.php b/Modules/TestQuestionPool/classes/feedback/class.ilAssSpecificFeedbackIdentifierList.php
new file mode 100644
index 000000000000..56478ec6d521
--- /dev/null
+++ b/Modules/TestQuestionPool/classes/feedback/class.ilAssSpecificFeedbackIdentifierList.php
@@ -0,0 +1,104 @@
+
+ * @version $Id$
+ *
+ * @package Modules/TestQuestionPool
+ */
+class ilAssSpecificFeedbackIdentifierList implements Iterator
+{
+ /**
+ * @var ilAssSpecificFeedbackIdentifier[]
+ */
+ protected $map = array();
+
+ /**
+ * @param ilAssSpecificFeedbackIdentifier $identifier
+ */
+ protected function add(ilAssSpecificFeedbackIdentifier $identifier)
+ {
+ $this->map[] = $identifier;
+ }
+
+ /**
+ * @param integer $questionId
+ */
+ public function load($questionId)
+ {
+ global $DIC; /* @var ILIAS\DI\Container $DIC */
+
+ $res = $DIC->database()->queryF(
+ "SELECT feedback_id, question, answer FROM {$this->getSpecificFeedbackTableName()} WHERE question_fi = %s",
+ array('integer'), array($questionId)
+ );
+
+ $feedbackIdByAnswerIndexMap = array();
+
+ while( $row = $DIC->database()->fetchAssoc($res) )
+ {
+ $identifier = new ilAssSpecificFeedbackIdentifier();
+
+ $identifier->setQuestionId($questionId);
+
+ $identifier->setQuestionIndex($row['question']);
+ $identifier->setAnswerIndex($row['answer']);
+
+ $identifier->setFeedbackId($row['feedback_id']);
+
+ $this->add($identifier);
+ }
+ }
+
+ /**
+ * @return ilAssSpecificFeedbackIdentifier
+ */
+ public function current()
+ {
+ return current($this->map);
+ }
+
+ /**
+ * @return ilAssSpecificFeedbackIdentifier
+ */
+ public function next()
+ {
+ return next($this->map);
+ }
+
+ /**
+ * @return integer|null
+ */
+ public function key()
+ {
+ return key($this->map);
+ }
+
+ /**
+ * @return bool
+ */
+ public function valid()
+ {
+ return key($this->map) !== null;
+ }
+
+ /**
+ * @return ilAssSpecificFeedbackIdentifier
+ */
+ public function rewind()
+ {
+ return reset($this->map);
+ }
+
+ protected function getSpecificFeedbackTableName()
+ {
+ require_once 'Modules/TestQuestionPool/classes/feedback/class.ilAssClozeTestFeedback.php';
+ return ilAssClozeTestFeedback::TABLE_NAME_SPECIFIC_FEEDBACK;
+ }
+}
\ No newline at end of file
diff --git a/Modules/TestQuestionPool/classes/import/qti12/class.assClozeTestImport.php b/Modules/TestQuestionPool/classes/import/qti12/class.assClozeTestImport.php
index 718694c867b8..7808abca2623 100644
--- a/Modules/TestQuestionPool/classes/import/qti12/class.assClozeTestImport.php
+++ b/Modules/TestQuestionPool/classes/import/qti12/class.assClozeTestImport.php
@@ -299,6 +299,9 @@ function fromXML(&$item, $questionpool_id, &$tst_id, &$tst_object, &$question_co
$textgap_rating = $item->getMetadataEntry("textgaprating");
$this->object->setFixedTextLength($item->getMetadataEntry("fixedTextLength"));
$this->object->setIdenticalScoring($item->getMetadataEntry("identicalScoring"));
+ $this->object->setFeedbackMode( strlen($item->getMetadataEntry("feedback_mode")) ?
+ $item->getMetadataEntry("feedback_mode") : ilAssClozeTestFeedback::FB_MODE_GAP_QUESTION
+ );
$combination = json_decode(base64_decode($item->getMetadataEntry("combinations")));
if (strlen($textgap_rating) == 0) $textgap_rating = "ci";
$this->object->setTextgapRating($textgap_rating);
@@ -393,8 +396,10 @@ function fromXML(&$item, $questionpool_id, &$tst_id, &$tst_object, &$question_co
$this->object->setClozeTextValue(ilRTE::_replaceMediaObjectImageSrc($clozetext, 1));
foreach ($feedbacks as $ident => $material)
{
+ $fbIdentifier = $this->buildFeedbackIdentifier($ident);
$this->object->feedbackOBJ->importSpecificAnswerFeedback(
- $this->object->getId(), $ident, ilRTE::_replaceMediaObjectImageSrc($material, 1)
+ $this->object->getId(), $fbIdentifier->getQuestionIndex(), $fbIdentifier->getAnswerIndex(),
+ ilRTE::_replaceMediaObjectImageSrc($material, 1)
);
}
foreach ($feedbacksgeneric as $correctness => $material)
@@ -432,6 +437,29 @@ function fromXML(&$item, $questionpool_id, &$tst_id, &$tst_object, &$question_co
}
$this->object->saveToDb();
}
+
+ /**
+ * @param string $ident
+ * @return ilAssSpecificFeedbackIdentifier
+ */
+ protected function buildFeedbackIdentifier($ident)
+ {
+ require_once 'Modules/TestQuestionPool/classes/feedback/class.ilAssSpecificFeedbackIdentifier.php';
+ $fbIdentifier = new ilAssSpecificFeedbackIdentifier();
+
+ $ident = explode('_', $ident);
+
+ if( count($ident) > 1 )
+ {
+ $fbIdentifier->setQuestionIndex($ident[0]);
+ $fbIdentifier->setAnswerIndex($ident[1]);
+ }
+ else
+ {
+ $fbIdentifier->setQuestionIndex($ident[0]);
+ $fbIdentifier->setAnswerIndex(0);
+ }
+
+ return $fbIdentifier;
+ }
}
-
-?>
diff --git a/Modules/TestQuestionPool/classes/import/qti12/class.assErrorTextImport.php b/Modules/TestQuestionPool/classes/import/qti12/class.assErrorTextImport.php
index 435b210d76dc..82e2b7096fc1 100644
--- a/Modules/TestQuestionPool/classes/import/qti12/class.assErrorTextImport.php
+++ b/Modules/TestQuestionPool/classes/import/qti12/class.assErrorTextImport.php
@@ -104,7 +104,7 @@ function fromXML(&$item, $questionpool_id, &$tst_id, &$tst_object, &$question_co
foreach ($feedbacks as $ident => $material)
{
$this->object->feedbackOBJ->importSpecificAnswerFeedback(
- $this->object->getId(), $ident, ilRTE::_replaceMediaObjectImageSrc($material, 1)
+ $this->object->getId(),0, $ident, ilRTE::_replaceMediaObjectImageSrc($material, 1)
);
}
foreach ($feedbacksgeneric as $correctness => $material)
diff --git a/Modules/TestQuestionPool/classes/import/qti12/class.assImagemapQuestionImport.php b/Modules/TestQuestionPool/classes/import/qti12/class.assImagemapQuestionImport.php
index 89d0dbd9ee0f..3750ae2f8f44 100644
--- a/Modules/TestQuestionPool/classes/import/qti12/class.assImagemapQuestionImport.php
+++ b/Modules/TestQuestionPool/classes/import/qti12/class.assImagemapQuestionImport.php
@@ -314,7 +314,7 @@ function fromXML(&$item, $questionpool_id, &$tst_id, &$tst_object, &$question_co
foreach ($feedbacks as $ident => $material)
{
$this->object->feedbackOBJ->importSpecificAnswerFeedback(
- $this->object->getId(), $ident, ilRTE::_replaceMediaObjectImageSrc($material, 1)
+ $this->object->getId(),0, $ident, ilRTE::_replaceMediaObjectImageSrc($material, 1)
);
}
foreach ($feedbacksgeneric as $correctness => $material)
diff --git a/Modules/TestQuestionPool/classes/import/qti12/class.assKprimChoiceImport.php b/Modules/TestQuestionPool/classes/import/qti12/class.assKprimChoiceImport.php
index bbb7db57f172..b9ccaf13ae8f 100644
--- a/Modules/TestQuestionPool/classes/import/qti12/class.assKprimChoiceImport.php
+++ b/Modules/TestQuestionPool/classes/import/qti12/class.assKprimChoiceImport.php
@@ -354,7 +354,7 @@ public function fromXML(&$item, $questionpool_id, &$tst_id, &$tst_object, &$ques
foreach ($feedbacks as $ident => $material)
{
$this->object->feedbackOBJ->importSpecificAnswerFeedback(
- $this->object->getId(), $ident, ilRTE::_replaceMediaObjectImageSrc($material, 1)
+ $this->object->getId(),0, $ident, ilRTE::_replaceMediaObjectImageSrc($material, 1)
);
}
foreach ($feedbacksgeneric as $correctness => $material)
diff --git a/Modules/TestQuestionPool/classes/import/qti12/class.assLongMenuImport.php b/Modules/TestQuestionPool/classes/import/qti12/class.assLongMenuImport.php
index a7c2185bfcdc..dc90a9f223d1 100644
--- a/Modules/TestQuestionPool/classes/import/qti12/class.assLongMenuImport.php
+++ b/Modules/TestQuestionPool/classes/import/qti12/class.assLongMenuImport.php
@@ -213,7 +213,7 @@ public function fromXML(&$item, $questionpool_id, &$tst_id, &$tst_object, &$ques
foreach($feedbacks as $ident => $material)
{
$this->object->feedbackOBJ->importSpecificAnswerFeedback(
- $this->object->getId(), $ident, ilRTE::_replaceMediaObjectImageSrc($material, 1)
+ $this->object->getId(), 0, $ident, ilRTE::_replaceMediaObjectImageSrc($material, 1)
);
}
}
diff --git a/Modules/TestQuestionPool/classes/import/qti12/class.assMultipleChoiceImport.php b/Modules/TestQuestionPool/classes/import/qti12/class.assMultipleChoiceImport.php
index 9004241fea50..95edf7b09d4c 100644
--- a/Modules/TestQuestionPool/classes/import/qti12/class.assMultipleChoiceImport.php
+++ b/Modules/TestQuestionPool/classes/import/qti12/class.assMultipleChoiceImport.php
@@ -354,7 +354,7 @@ function fromXML(&$item, $questionpool_id, &$tst_id, &$tst_object, &$question_co
foreach ($feedbacks as $ident => $material)
{
$this->object->feedbackOBJ->importSpecificAnswerFeedback(
- $this->object->getId(), $ident, ilRTE::_replaceMediaObjectImageSrc($material, 1)
+ $this->object->getId(),0, $ident, ilRTE::_replaceMediaObjectImageSrc($material, 1)
);
}
foreach ($feedbacksgeneric as $correctness => $material)
diff --git a/Modules/TestQuestionPool/classes/import/qti12/class.assSingleChoiceImport.php b/Modules/TestQuestionPool/classes/import/qti12/class.assSingleChoiceImport.php
index b26cda878621..100a5c74eb22 100644
--- a/Modules/TestQuestionPool/classes/import/qti12/class.assSingleChoiceImport.php
+++ b/Modules/TestQuestionPool/classes/import/qti12/class.assSingleChoiceImport.php
@@ -348,7 +348,7 @@ function fromXML(&$item, $questionpool_id, &$tst_id, &$tst_object, &$question_co
foreach ($feedbacks as $ident => $material)
{
$this->object->feedbackOBJ->importSpecificAnswerFeedback(
- $this->object->getId(), $ident, ilRTE::_replaceMediaObjectImageSrc($material, 1)
+ $this->object->getId(),0, $ident, ilRTE::_replaceMediaObjectImageSrc($material, 1)
);
}
foreach ($feedbacksgeneric as $correctness => $material)
diff --git a/Services/AccessControl/classes/class.ilConditionHandler.php b/Services/AccessControl/classes/class.ilConditionHandler.php
index 34831e28f46d..0daeae07d7c4 100755
--- a/Services/AccessControl/classes/class.ilConditionHandler.php
+++ b/Services/AccessControl/classes/class.ilConditionHandler.php
@@ -448,7 +448,7 @@ function getTriggerTypes()
$objDefinition = $DIC['objDefinition'];
- $trigger_types = array('crs','exc','tst','sahs', 'svy', 'lm', 'iass', 'prg');
+ $trigger_types = array('crs','exc','tst','sahs', 'svy', 'lm', 'iass', 'prg', 'copa');
foreach($objDefinition->getPlugins() as $p_type => $p_info)
{
diff --git a/Services/AccessControl/classes/class.ilObjRoleGUI.php b/Services/AccessControl/classes/class.ilObjRoleGUI.php
index 8a1420d9c8d3..5fda1c59a91b 100755
--- a/Services/AccessControl/classes/class.ilObjRoleGUI.php
+++ b/Services/AccessControl/classes/class.ilObjRoleGUI.php
@@ -1489,9 +1489,6 @@ function __prepareOutput()
$this->tpl->addBlockFile("CONTENT", "content", "tpl.adm_content.html");
$this->tpl->addBlockFile("STATUSLINE", "statusline", "tpl.statusline.html");
- // output locator
- //$this->__setLocator();
-
// output message
if ($this->message)
{
@@ -1514,84 +1511,36 @@ function __setHeader()
$this->getTabs($this->tabs_gui);
}
- function __setLocator()
- {
- global $DIC;
-
- $tree = $DIC['tree'];
- $ilCtrl = $DIC['ilCtrl'];
-
- return;
-
- $this->tpl->addBlockFile("LOCATOR", "locator", "tpl.locator.html", "Services/Locator");
-
- $counter = 0;
-
- foreach ($tree->getPathFull($this->obj_ref_id) as $key => $row)
- {
- if ($counter++)
- {
- $this->tpl->touchBlock('locator_separator_prefix');
- }
-
- $this->tpl->setCurrentBlock("locator_item");
-
- if ($row["type"] == 'rolf')
- {
- $this->tpl->setVariable("ITEM",$this->object->getTitle());
- $this->tpl->setVariable("LINK_ITEM",$this->ctrl->getLinkTarget($this));
- }
- elseif ($row["child"] != $tree->getRootId())
- {
- $ilCtrl->setParameterByClass("ilrepositorygui", "ref_id", $row["child"]);
- $this->tpl->setVariable("ITEM", $row["title"]);
- $this->tpl->setVariable("LINK_ITEM",
- $ilCtrl->getLinkTargetByClass("ilrepositorygui", ""));
- }
- else
- {
- $ilCtrl->setParameterByClass("ilrepositorygui", "ref_id", $row["child"]);
- $this->tpl->setVariable("ITEM", $this->lng->txt("repository"));
- $this->tpl->setVariable("LINK_ITEM",
- $ilCtrl->getLinkTargetByClass("ilrepositorygui", ""));
- }
- $ilCtrl->setParameterByClass("ilrepositorygui", "ref_id", $_GET["ref_id"]);
-
- $this->tpl->parseCurrentBlock();
- }
- $this->tpl->setVariable("TXT_LOCATOR",$this->lng->txt("locator"));
- $this->tpl->parseCurrentBlock();
- }
-
/**
- * should be overwritten to add object specific items
- * (repository items are preloaded)
- */
- function addAdminLocatorItems($a_do_not_add_object = false)
+ * @inheritdoc
+ */
+ protected function addAdminLocatorItems($a_do_not_add_object = false)
{
global $DIC;
$ilLocator = $DIC['ilLocator'];
- if ($_GET["admin_mode"] == "settings"
+ if(
+ $_GET["admin_mode"] == "settings"
&& $_GET["ref_id"] == ROLE_FOLDER_ID) // system settings
{
parent::addAdminLocatorItems(true);
- $ilLocator->addItem($this->lng->txt("obj_".ilObject::_lookupType(
- ilObject::_lookupObjId($_GET["ref_id"]))),
- $this->ctrl->getLinkTargetByClass("ilobjrolefoldergui", "view"));
+ $ilLocator->addItem(
+ $this->lng->txt("obj_".ilObject::_lookupType(ilObject::_lookupObjId($_GET["ref_id"]))),
+ $this->ctrl->getLinkTargetByClass("ilobjrolefoldergui", 'view')
+ );
if ($_GET["obj_id"] > 0)
{
- $ilLocator->addItem($this->object->getTitle(),
- $this->ctrl->getLinkTarget($this, "view"));
+ $ilLocator->addItem(
+ $this->object->getTitle(),
+ $this->ctrl->getLinkTarget($this, 'perm'));
}
}
- else // repository administration
- {
- // ?
+ else {
+ parent::addAdminLocatorItems($a_do_not_add_object);
}
}
@@ -1893,8 +1842,34 @@ protected function addToClipboardObject()
ilUtil::sendSuccess($this->lng->txt('clipboard_user_added'),true);
$ilCtrl->redirect($this, 'userassignment');
}
-
-
-
+
+ /**
+ * @inheritdoc
+ */
+ protected function addLocatorItems()
+ {
+ global $DIC;
+
+ $ilLocator = $DIC['ilLocator'];
+
+ if($_GET["admin_mode"] == "")
+ {
+ $this->ctrl->setParameterByClass(
+ "ilobjrolegui",
+ "obj_id",
+ (int) $_GET["obj_id"]
+ );
+ $ilLocator->addItem(
+ ilObjRole::_getTranslation($this->object->getTitle()),
+ $this->ctrl->getLinkTargetByClass(
+ array(
+ "ilpermissiongui",
+ "ilobjrolegui"),
+ "perm")
+ );
+ }
+
+ }
+
} // END class.ilObjRoleGUI
?>
diff --git a/Services/AccessControl/classes/class.ilObjRoleTemplateGUI.php b/Services/AccessControl/classes/class.ilObjRoleTemplateGUI.php
index ede78d3061c0..3591677eb3ad 100755
--- a/Services/AccessControl/classes/class.ilObjRoleTemplateGUI.php
+++ b/Services/AccessControl/classes/class.ilObjRoleTemplateGUI.php
@@ -17,7 +17,6 @@
*/
class ilObjRoleTemplateGUI extends ilObjectGUI
{
-
const FORM_MODE_EDIT = 1;
const FORM_MODE_CREATE = 2;
@@ -184,6 +183,8 @@ public function editObject(ilPropertyFormGUI $form = null)
global $DIC;
$rbacsystem = $DIC['rbacsystem'];
+
+ $this->tabs_gui->activateTab('settings');
if (!$rbacsystem->checkAccess("write", $this->rolf_ref_id))
{
@@ -278,283 +279,124 @@ public function saveObject()
$this->createObject($form);
}
+
/**
- * display permissions
- *
- * @access public
- */
- function permObject()
+ * Show role template permissions
+ */
+ protected function permObject()
{
global $DIC;
- $rbacadmin = $DIC['rbacadmin'];
- $rbacreview = $DIC['rbacreview'];
- $rbacsystem = $DIC['rbacsystem'];
+ /**
+ * @var ilRbacSystem
+ */
+ $rbacsystem = $DIC->rbac()->system();
+
+ /**
+ * @var ilErrorHandling
+ */
+ $ilErr = $DIC['ilErr'];
+
+ /**
+ * @var ilObjectDefinition
+ */
$objDefinition = $DIC['objDefinition'];
- $ilSetting = $DIC['ilSetting'];
- if (!$rbacsystem->checkAccess('write',$this->rolf_ref_id))
+ if(!$rbacsystem->checkAccess('edit_permission', $this->ref_id))
{
- $this->ilias->raiseError($this->lng->txt("msg_no_perm_perm"),$this->ilias->error_obj->WARNING);
- exit();
+ $ilErr->raiseError($this->lng->txt('msg_no_perm_perm'),$ilErr->MESSAGE);
+ return true;
}
+ $this->tabs_gui->activateTab('perm');
- $to_filter = $objDefinition->getSubobjectsToFilter();
-
- $tpl_filter = array();
- $internal_tpl = false;
+ $this->tpl->addBlockFile(
+ 'ADM_CONTENT',
+ 'adm_content',
+ 'tpl.rbac_template_permissions.html',
+ 'Services/AccessControl'
+ );
- if (($internal_tpl = $this->object->isInternalTemplate()))
- {
- $tpl_filter = $this->object->getFilterOfInternalTemplate();
- }
- $op_order = array();
+ $this->tpl->setVariable('PERM_ACTION',$this->ctrl->getFormAction($this));
- foreach(ilRbacReview::_getOperationList() as $op)
- {
- $op_order[$op["ops_id"]] = $op["order"];
- }
+ include_once './Services/Accordion/classes/class.ilAccordionGUI.php';
+ $acc = new ilAccordionGUI();
+ $acc->setBehaviour(ilAccordionGUI::FORCE_ALL_OPEN);
+ $acc->setId('template_perm_'.$this->ref_id);
- $operation_info = $rbacreview->getOperationAssignment();
+ $subs = $objDefinition->getSubObjectsRecursively('root','true',false);
- foreach($operation_info as $info)
+ $sorted = array();
+ foreach($subs as $subtype => $def)
{
- if($objDefinition->getDevMode($info['type']))
- {
- continue;
- }
- // FILTER SUBOJECTS OF adm OBJECT
- if(in_array($info['type'],$to_filter))
- {
- continue;
- }
- if ($internal_tpl and $tpl_filter and !in_array($info['type'],$tpl_filter))
- {
- continue;
- }
- $rbac_objects[$info['typ_id']] = array("obj_id" => $info['typ_id'],
- "type" => $info['type']);
-
- $txt = $objDefinition->isPlugin($info['type'])
- ? ilObjectPlugin::lookupTxtById($info['type'], $info['type']."_".$info['operation'])
- : $this->lng->txt($info['type']."_".$info['operation']);
- if (substr($info['operation'], 0, 7) == "create_" &&
- $objDefinition->isPlugin(substr($info['operation'], 7)))
- {
- $txt = ilObjectPlugin::lookupTxtById(substr($info['operation'], 7), $info['type']."_".$info['operation']);
- }
- elseif(substr($info['operation'],0,6) == 'create')
+ if($objDefinition->isPlugin($subtype))
{
- $txt = $this->lng->txt('rbac_'.$info['operation']);
+ $translation = ilObjectPlugin::lookupTxtById($subtype,"obj_".$subtype);
}
-
- $order = $op_order[$info['ops_id']];
- if(substr($info['operation'],0,6) == 'create')
+ elseif($objDefinition->isSystemObject($subtype))
{
- $order = $objDefinition->getPositionByType($info['type']);
- }
-
- $rbac_operations[$info['typ_id']][$info['ops_id']] = array(
- "ops_id" => $info['ops_id'],
- "title" => $info['operation'],
- "name" => $txt,
- "order" => $order);
- }
-
- foreach ($rbac_objects as $key => $obj_data)
- {
- if ($objDefinition->isPlugin($obj_data["type"]))
- {
- $rbac_objects[$key]["name"] = ilObjectPlugin::lookupTxtById($obj_data["type"],
- "obj_".$obj_data["type"]);
+ $translation = $this->lng->txt("obj_".$subtype);
}
else
{
- $rbac_objects[$key]["name"] = $this->lng->txt("obj_".$obj_data["type"]);
+ $translation = $this->lng->txt('objs_'.$subtype);
}
- $rbac_objects[$key]["ops"] = $rbac_operations[$key];
- }
-
- sort($rbac_objects);
-
- foreach ($rbac_objects as $key => $obj_data)
- {
- sort($rbac_objects[$key]["ops"]);
+ $sorted[$subtype] = $def;
+ $sorted[$subtype]['translation'] = $translation;
}
-
- // sort by (translated) name of object type
- $rbac_objects = ilUtil::sortArray($rbac_objects,"name","asc");
- // BEGIN CHECK_PERM
- foreach ($rbac_objects as $key => $obj_data)
+ $sorted = ilUtil::sortArray($sorted, 'translation','asc',true,true);
+ foreach($sorted as $subtype => $def)
{
- $arr_selected = $rbacreview->getOperationsOfRole($this->object->getId(), $obj_data["type"], $this->rolf_ref_id);
- $arr_checked = array_intersect($arr_selected,array_keys($rbac_operations[$obj_data["obj_id"]]));
-
- foreach ($rbac_operations[$obj_data["obj_id"]] as $operation)
+ if($objDefinition->isPlugin($subtype))
{
- $checked = in_array($operation["ops_id"],$arr_checked);
- $disabled = false;
-
- // Es wird eine 2-dim Post Variable �bergeben: perm[rol_id][ops_id]
- $box = ilUtil::formCheckBox($checked,"template_perm[".$obj_data["type"]."][]",$operation["ops_id"],$disabled);
- $output["perm"][$obj_data["obj_id"]][$operation["ops_id"]] = $box;
+ $translation = ilObjectPlugin::lookupTxtById($subtype,"obj_".$subtype);
}
- }
- // END CHECK_PERM
-
- $output["col_anz"] = count($rbac_objects);
- $output["txt_save"] = $this->lng->txt("save");
- $output["check_protected"] = ilUtil::formCheckBox($rbacreview->isProtected($this->rolf_ref_id,$this->object->getId()),"protected",1);
- $output["text_protected"] = $this->lng->txt("role_protect_permissions");
-
-/************************************/
-/* adopt permissions form */
-/************************************/
-
- $output["message_middle"] = $this->lng->txt("adopt_perm_from_template");
-
- // send message for system role
- if ($this->object->getId() == SYSTEM_ROLE_ID)
- {
- $output["adopt"] = array();
- ilUtil::sendFailure($this->lng->txt("msg_sysrole_not_editable"));
- }
- else
- {
- // BEGIN ADOPT_PERMISSIONS
- $parent_role_ids = $rbacreview->getParentRoleIds($this->rolf_ref_id,true);
-
- // sort output for correct color changing
- ksort($parent_role_ids);
-
- foreach ($parent_role_ids as $key => $par)
+ elseif($objDefinition->isSystemObject($subtype))
{
- if ($par["obj_id"] != SYSTEM_ROLE_ID)
- {
- $radio = ilUtil::formRadioButton(0,"adopt",$par["obj_id"]);
- $output["adopt"][$key]["css_row_adopt"] = ilUtil::switchColor($key, "tblrow1", "tblrow2");
- $output["adopt"][$key]["check_adopt"] = $radio;
- $output["adopt"][$key]["type"] = ($par["type"] == 'role' ? 'Role' : 'Template');
- $output["adopt"][$key]["role_name"] = $par["title"];
- }
+ $translation = $this->lng->txt("obj_".$subtype);
}
-
- $output["formaction_adopt"] = $this->ctrl->getFormAction($this);
- // END ADOPT_PERMISSIONS
- }
-
- $output["formaction"] =
- $this->ctrl->getFormAction($this);
-
- $this->data = $output;
-
-
-/************************************/
-/* generate output */
-/************************************/
-
- $this->tpl->addBlockFile("ADM_CONTENT", "adm_content", "tpl.adm_perm_role.html",
- "Services/AccessControl");
-
- foreach ($rbac_objects as $obj_data)
- {
- // BEGIN object_operations
- $this->tpl->setCurrentBlock("object_operations");
-
- $obj_data["ops"] = ilUtil::sortArray($obj_data["ops"], 'order','asc',true,true);
-
- foreach ($obj_data["ops"] as $operation)
- {
- $ops_ids[] = $operation["ops_id"];
-
- $css_row = ilUtil::switchColor($key, "tblrow1", "tblrow2");
- $this->tpl->setVariable("CSS_ROW",$css_row);
- $this->tpl->setVariable("PERMISSION",$operation["name"]);
- $this->tpl->setVariable("CHECK_PERMISSION",$this->data["perm"][$obj_data["obj_id"]][$operation["ops_id"]]);
- $this->tpl->parseCurrentBlock();
- } // END object_operations
-
- // BEGIN object_type
- $this->tpl->setCurrentBlock("object_type");
- $this->tpl->setVariable("TXT_OBJ_TYPE",$obj_data["name"]);
-
-// TODO: move this if in a function and query all objects that may be disabled or inactive
- if ($this->objDefinition->getDevMode($obj_data["type"]))
+ else
{
- $this->tpl->setVariable("TXT_NOT_IMPL", "(".$this->lng->txt("not_implemented_yet").")");
+ $translation = $this->lng->txt('objs_'.$subtype);
}
-
- // js checkbox toggles
- $this->tpl->setVariable("JS_VARNAME","template_perm_".$obj_data["type"]);
- $this->tpl->setVariable("JS_ONCLICK",ilUtil::array_php2js($ops_ids));
- $this->tpl->setVariable("TXT_CHECKALL", $this->lng->txt("check_all"));
- $this->tpl->setVariable("TXT_UNCHECKALL", $this->lng->txt("uncheck_all"));
+ $tbl = new ilObjectRoleTemplatePermissionTableGUI(
+ $this,
+ 'perm',
+ $this->ref_id,
+ $this->obj_id,
+ $subtype,
+ false
+ );
+ $tbl->setShowChangeExistingObjects(false);
+ $tbl->parse();
+
+ $acc->addItem($translation, $tbl->getHTML());
+ }
+
+ $this->tpl->setVariable('ACCORDION',$acc->getHTML());
+
+ // Add options table
+ include_once './Services/AccessControl/classes/class.ilObjectRoleTemplateOptionsTableGUI.php';
+ $options = new ilObjectRoleTemplateOptionsTableGUI(
+ $this,
+ 'perm',
+ $this->ref_id,
+ $this->obj_id,
+ false
+ );
+ $options->setShowOptions(false);
+ $options->addMultiCommand(
+ 'permSave',
+ $this->lng->txt('save')
+ );
+
+ $options->parse();
+ $this->tpl->setVariable('OPTIONS_TABLE',$options->getHTML());
+ }
- $this->tpl->parseCurrentBlock();
- // END object_type
- }
-
- /*
- // BEGIN ADOPT PERMISSIONS
- foreach ($this->data["adopt"] as $key => $value)
- {
- $this->tpl->setCurrentBlock("ADOPT_PERM_ROW");
- $this->tpl->setVariable("CSS_ROW_ADOPT",$value["css_row_adopt"]);
- $this->tpl->setVariable("CHECK_ADOPT",$value["check_adopt"]);
- $this->tpl->setVariable("TYPE",$value["type"]);
- $this->tpl->setVariable("ROLE_NAME",$value["role_name"]);
- $this->tpl->parseCurrentBlock();
- }
-
- $this->tpl->setCurrentBlock("ADOPT_PERM_FORM");
- $this->tpl->setVariable("MESSAGE_MIDDLE",$this->data["message_middle"]);
- $this->tpl->setVariable("FORMACTION_ADOPT",$this->data["formaction_adopt"]);
- $this->tpl->setVariable("ADOPT",$this->lng->txt('copy'));
- $this->tpl->parseCurrentBlock();
- // END ADOPT PERMISSIONS
- */
-
- $this->tpl->setCurrentBlock("tblfooter_protected");
- $this->tpl->setVariable("COL_ANZ",3);
- $this->tpl->setVariable("CHECK_BOTTOM",$this->data["check_protected"]);
- $this->tpl->setVariable("MESSAGE_TABLE",$this->data["text_protected"]);
- $this->tpl->parseCurrentBlock();
-
- $this->tpl->setVariable("COL_ANZ_PLUS",4);
- $this->tpl->setVariable("TXT_SAVE",$this->data["txt_save"]);
- $this->tpl->setCurrentBlock("adm_content");
- $this->tpl->setVariable("TBL_TITLE_IMG",ilUtil::getImagePath("icon_".$this->object->getType().".svg"));
- $this->tpl->setVariable("TBL_TITLE_IMG_ALT",$this->lng->txt($this->object->getType()));
-
- // compute additional information in title
- if (substr($this->object->getTitle(),0,3) == "il_")
- {
- $desc = $this->lng->txt("predefined_template");//$this->lng->txt("obj_".$parent_node['type'])." (".$parent_node['obj_id'].") : ".$parent_node['title'];
- }
-
- $description = "
".$desc."";
-
- // translation for autogenerated roles
- if (substr($this->object->getTitle(),0,3) == "il_")
- {
- include_once('./Services/AccessControl/classes/class.ilObjRole.php');
- $title = ilObjRole::_getTranslation($this->object->getTitle())." (".$this->object->getTitle().")";
- }
- else
- {
- $title = $this->object->getTitle();
- }
-
- $this->tpl->setVariable("TBL_TITLE",$title.$description);
-
- $this->tpl->setVariable("TXT_PERMISSION",$this->data["txt_permission"]);
- $this->tpl->setVariable("FORMACTION",$this->data["formaction"]);
- $this->tpl->parseCurrentBlock();
- }
/**
@@ -562,40 +404,48 @@ function permObject()
*
* @access public
*/
- function permSaveObject()
+ protected function permSaveObject()
{
global $DIC;
- $rbacadmin = $DIC['rbacadmin'];
- $rbacsystem = $DIC['rbacsystem'];
- $rbacreview = $DIC['rbacreview'];
+ /**
+ * @var ilRbacSystem
+ */
+ $rbacsystem = $DIC->rbac()->system();
+
+ /**
+ * @var ilRbacAdmin
+ */
+ $rbacadmin = $DIC->rbac()->admin();
+
+ /**
+ * @var ilErrorHandling
+ */
+ $ilErr = $DIC['ilErr'];
+
+ /**
+ * @var ilObjectDefinition
+ */
$objDefinition = $DIC['objDefinition'];
+
if (!$rbacsystem->checkAccess('write',$this->rolf_ref_id))
{
- $this->ilias->raiseError($this->lng->txt("msg_no_perm_perm"),$this->ilias->error_obj->WARNING);
+ $ilErr->raiseError($this->lng->txt('msg_no_perm_perm'),$ilErr->MESSAGE);
+ return true;
}
- else
- {
- // Alle Template Eintraege loeschen
- $rbacadmin->deleteRolePermission($this->object->getId(), $this->rolf_ref_id);
+ // delete all existing template entries
+ $rbacadmin->deleteRolePermission($this->object->getId(), $this->ref_id);
- foreach ($_POST["template_perm"] as $key => $ops_array)
- {
- // Setzen der neuen template permissions
- $rbacadmin->setRolePermission($this->object->getId(), $key,$ops_array,$this->rolf_ref_id);
- }
+ foreach ($_POST["template_perm"] as $key => $ops_array)
+ {
+ $rbacadmin->setRolePermission($this->object->getId(), $key,$ops_array,$this->rolf_ref_id);
}
-
+
// update object data entry (to update last modification date)
$this->object->update();
- // set protected flag
- // not applicable for role templates
- #$rbacadmin->setProtected($this->rolf_ref_id,$this->object->getId(),ilUtil::tf2yn($_POST['protected']));
-
ilUtil::sendSuccess($this->lng->txt("saved_successfully"),true);
-
$this->ctrl->redirect($this, "perm");
}
@@ -644,26 +494,34 @@ function getAdminTabs()
{
$this->getTabs();
}
-
- function getTabs()
+
+ /**
+ * @inheritdoc
+ */
+ protected function getTabs()
{
global $DIC;
- $rbacsystem = $DIC['rbacsystem'];
+ $rbacsystem = $DIC->rbac()->system();
- if ($rbacsystem->checkAccess('write',$this->rolf_ref_id))
+ if($rbacsystem->checkAccess('write',$this->ref_id))
{
- $this->tabs_gui->addTarget("settings",
- $this->ctrl->getLinkTarget($this, "edit"),
- array("edit","update"), get_class($this));
-
- $this->tabs_gui->addTarget("default_perm_settings",
- $this->ctrl->getLinkTarget($this, "perm"),
- array("perm"), get_class($this));
+ $this->tabs_gui->addTab(
+ 'settings',
+ $this->lng->txt('settings'),
+ $this->ctrl->getLinkTarget($this,'edit')
+ );
+ }
+ if($rbacsystem->checkAccess('edit_permission',$this->ref_id))
+ {
+ $this->tabs_gui->addTab(
+ 'perm',
+ $this->lng->txt('default_perm_settings'),
+ $this->ctrl->getLinkTarget($this,'perm')
+ );
}
}
-
/**
* cancelObject is called when an operation is canceled, method links back
* @access public
@@ -675,12 +533,10 @@ function cancelObject()
-
/**
- * should be overwritten to add object specific items
- * (repository items are preloaded)
- */
- function addAdminLocatorItems($a_do_not_add_object = false)
+ * @inheritdoc
+ */
+ protected function addAdminLocatorItems($a_do_not_add_object = false)
{
global $DIC;
@@ -692,6 +548,7 @@ function addAdminLocatorItems($a_do_not_add_object = false)
ilObject::_lookupObjId($_GET["ref_id"])),
$this->ctrl->getLinkTargetByClass("ilobjrolefoldergui", "view"));
}
-
+
+
} // END class.ilObjRoleTemplateGUI
?>
diff --git a/Services/AccessControl/classes/class.ilObjectRoleTemplateOptionsTableGUI.php b/Services/AccessControl/classes/class.ilObjectRoleTemplateOptionsTableGUI.php
index 24f0d8213720..f41d779f530c 100644
--- a/Services/AccessControl/classes/class.ilObjectRoleTemplateOptionsTableGUI.php
+++ b/Services/AccessControl/classes/class.ilObjectRoleTemplateOptionsTableGUI.php
@@ -19,6 +19,7 @@ class ilObjectRoleTemplateOptionsTableGUI extends ilTable2GUI
private $obj_ref_id = null;
private $show_admin_permissions = true;
+ private $show_options = true;
/**
* Constructor
@@ -60,6 +61,24 @@ public function __construct($a_parent_obj,$a_parent_cmd, $a_obj_ref_id,$a_role_i
$this->setTopCommands(false);
}
+
+ /**
+ * Set show options
+ * @param bool show/hide options
+ *
+ */
+ public function setShowOptions($a_status)
+ {
+ $this->show_options = $a_status;
+ }
+
+ /**
+ * @return bool
+ */
+ public function getShowOptions()
+ {
+ return $this->show_options;
+ }
/**
@@ -91,6 +110,12 @@ public function fillRow($row)
$rbacreview = $DIC['rbacreview'];
+
+ if(!$this->getShowOptions())
+ {
+ return true;
+ }
+
if(isset($row['recursive']) and !$this->show_admin_permissions)
{
$this->tpl->setCurrentBlock('recursive');
@@ -134,7 +159,6 @@ public function parse()
$row[1]['protected'] = 1;
$this->setData($row);
-
}
}
-?>
\ No newline at end of file
+?>
diff --git a/Services/AccessControl/classes/class.ilObjectRoleTemplatePermissionTableGUI.php b/Services/AccessControl/classes/class.ilObjectRoleTemplatePermissionTableGUI.php
index 58e5e6f4c79d..a22148f5009d 100644
--- a/Services/AccessControl/classes/class.ilObjectRoleTemplatePermissionTableGUI.php
+++ b/Services/AccessControl/classes/class.ilObjectRoleTemplatePermissionTableGUI.php
@@ -23,6 +23,7 @@ class ilObjectRoleTemplatePermissionTableGUI extends ilTable2GUI
private $tpl_type = '';
private $show_admin_permissions = false;
+ private $show_change_existing_objects = true;
private static $template_permissions = NULL;
@@ -70,7 +71,23 @@ public function __construct($a_parent_obj,$a_parent_cmd, $a_ref_id,$a_role_id,$a
$this->initTemplatePermissions();
}
-
+
+ /**
+ * @param bool $a_status
+ */
+ public function setShowChangeExistingObjects($a_status)
+ {
+ $this->show_change_existing_objects = $a_status;
+ }
+
+ /**
+ * @return bool
+ */
+ public function getShowChangeExistingObjects()
+ {
+ return $this->show_change_existing_objects;
+ }
+
/**
*
* @return
@@ -174,7 +191,7 @@ public function fillRow($row)
$this->tpl->setCurrentBlock('ce_desc_td');
$this->tpl->setVariable('CE_DESC_TYPE',$this->getTemplateType());
$this->tpl->setVariable('CE_LONG',$this->lng->txt('change_existing_object_type_desc'));
-
+
if($objDefinition->isSystemObject($this->getTemplateType()))
{
$this->tpl->setVariable("TXT_CE",
@@ -189,7 +206,6 @@ public function fillRow($row)
? ilObjectPlugin::lookupTxtById($this->getTemplateType(),
"objs_".$this->getTemplateType())
: $this->lng->txt('objs_'.$this->getTemplateType());
-
$this->tpl->setVariable('TXT_CE',
$this->lng->txt('change_existing_prefix').' '.
$pl_txt.' '.
@@ -304,7 +320,10 @@ public function parse()
$rows[] = $perm;
}
- if(!$this->show_admin_permissions)
+ if(
+ !$this->show_admin_permissions &&
+ $this->getShowChangeExistingObjects()
+ )
{
$rows[] = array('show_ce' => 1);
}
diff --git a/Services/AccessControl/templates/default/tpl.role_row.html b/Services/AccessControl/templates/default/tpl.role_row.html
index 7e857233ac18..0db0c36b909e 100644
--- a/Services/AccessControl/templates/default/tpl.role_row.html
+++ b/Services/AccessControl/templates/default/tpl.role_row.html
@@ -1,10 +1,10 @@
-
- |
+ |
+ |
|
-
+ |
{VAL_TITLE}
@@ -17,13 +17,13 @@
{VAL_PRE}
|
-
+ |
{ROLE_TYPE}
|
-
+ |
{CONTEXT}
|
-
+ |
{COPY_TEXT}
diff --git a/Services/Badge/classes/class.ilBadgeHandler.php b/Services/Badge/classes/class.ilBadgeHandler.php
index 8a8e3102efe7..fe14b49e7fb8 100644
--- a/Services/Badge/classes/class.ilBadgeHandler.php
+++ b/Services/Badge/classes/class.ilBadgeHandler.php
@@ -672,7 +672,7 @@ public function sendNotification(array $a_user_map, $a_parent_ref_id = null)
$notification->setLongDescriptionVar("", $osd_params, "");
$notification->setAutoDisable(false);
$notification->setLink($url);
- $notification->setIconPath("templates/default/images/icon_bdga.svg");
+ $notification->setIconPath(ilUtil::getImagePath('icon_bdga.svg'));
$notification->setValidForSeconds(ilNotificationConfig::TTL_SHORT);
$notification->setVisibleForSeconds(ilNotificationConfig::DEFAULT_TTS);
$notification->notifyByUsers(array($user_id));
diff --git a/Services/COPage/classes/class.ilPCMediaObjectGUI.php b/Services/COPage/classes/class.ilPCMediaObjectGUI.php
index f49078b6527b..2d81a836e746 100755
--- a/Services/COPage/classes/class.ilPCMediaObjectGUI.php
+++ b/Services/COPage/classes/class.ilPCMediaObjectGUI.php
@@ -159,6 +159,7 @@ function executeCommand()
$this->pg_obj);
$ret = $this->ctrl->forwardCommand($image_map_edit);
$tpl->setContent($ret);
+ $this->checkFixSize();
break;
default:
@@ -292,6 +293,33 @@ function changeObjectReference()
}
}
+
+ /**
+ * Check fix size
+ */
+ protected function checkFixSize()
+ {
+ $std_alias_item = new ilMediaAliasItem($this->dom, $this->getHierId(), "Standard",
+ $this->content_obj->getPcId());
+ $std_item = $this->content_obj->getMediaObject()->getMediaItem("Standard");
+
+ $ok = false;
+ if (($std_alias_item->getWidth() != "" && $std_alias_item->getHeight() != ""))
+ {
+ $ok = true;
+ }
+ if ($std_alias_item->getWidth() == "" && $std_alias_item->getHeight() == ""
+ && $std_item->getWidth() != "" && $std_item->getHeight() != "")
+ {
+ $ok = true;
+ }
+
+ if (!$ok)
+ {
+ ilUtil::sendFailure($this->lng->txt("mob_no_fixed_size_map_editing"));
+ }
+ }
+
/**
* Insert media object from pool
*/
@@ -573,8 +601,10 @@ function initAliasForm()
// standard size
$radio_size = new ilRadioGroupInputGUI($lng->txt("size"), "st_derive_size");
$orig_size = $std_item->getOriginalSize();
- $op1 = new ilRadioOption($lng->txt("cont_default").
- " (".$orig_size["width"]." x ".$orig_size["height"].")", "y");
+ $add_str = ($orig_size["width"] != "" && $orig_size["height"] != "")
+ ? " (".$orig_size["width"]." x ".$orig_size["height"].")"
+ : "";
+ $op1 = new ilRadioOption($lng->txt("cont_default").$add_str, "y");
$op2 = new ilRadioOption($lng->txt("cont_custom"), "n");
$radio_size->addOption($op1);
@@ -692,8 +722,10 @@ function initAliasForm()
// full size
$radio_size = new ilRadioGroupInputGUI($lng->txt("size"), "full_derive_size");
$fw_size = $std_item->getOriginalSize();
- $op1 = new ilRadioOption($lng->txt("cont_default").
- " (".$fw_size["width"]." x ".$fw_size["height"].")", "y");
+ $add_str = ($fw_size["width"] != "" && $fw_size["height"] != "")
+ ? " (".$fw_size["width"]." x ".$fw_size["height"].")"
+ : "";
+ $op1 = new ilRadioOption($lng->txt("cont_default").$add_str, "y");
$op2 = new ilRadioOption($lng->txt("cont_custom"), "n");
$radio_size->addOption($op1);
@@ -1107,6 +1139,8 @@ function saveAliasProperties()
$this->updated = $this->pg_obj->update();
if ($this->updated === true)
{
+ ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
+ $this->ctrl->redirect($this, "editAlias");
$this->ctrl->returnToParent($this, "jump".$this->hier_id);
}
else
diff --git a/Services/COPage/classes/class.ilPageEditorSettings.php b/Services/COPage/classes/class.ilPageEditorSettings.php
index 8114072ae970..e4c8140c71e2 100644
--- a/Services/COPage/classes/class.ilPageEditorSettings.php
+++ b/Services/COPage/classes/class.ilPageEditorSettings.php
@@ -18,7 +18,8 @@ class ilPageEditorSettings
"scorm" => array("sahs"),
"glo" => array("gdf"),
"test" => array("qpl"),
- "rep" => array("root", "cat", "grp", "crs", "fold")
+ "rep" => array("root", "cat", "grp", "crs", "fold"),
+ "copa" => array("copa"),
);
/**
diff --git a/Services/COPage/classes/class.ilPageObject.php b/Services/COPage/classes/class.ilPageObject.php
index 88214d8af43d..b9f020b8aace 100755
--- a/Services/COPage/classes/class.ilPageObject.php
+++ b/Services/COPage/classes/class.ilPageObject.php
@@ -783,7 +783,6 @@ static function _writeParentId($a_parent_type, $a_pg_id, $a_par_id)
global $DIC;
$db = $DIC->database();
-
$db->manipulateF("UPDATE page_object SET parent_id = %s WHERE page_id = %s".
" AND parent_type = %s", array("integer", "integer", "text"),
array($a_par_id, $a_pg_id, $a_parent_type));
diff --git a/Services/COPage/xsl/page.xsl b/Services/COPage/xsl/page.xsl
index bdd6538c9cb4..306679fff495 100755
--- a/Services/COPage/xsl/page.xsl
+++ b/Services/COPage/xsl/page.xsl
@@ -2127,148 +2127,173 @@
-
-
- ilc_media_cont_
-
-
- ilc_media_cont_MediaContainer
-
+
+
+ Fullscreen
+ Standard
+
- display:table;
+
+ ilc_media_cont_
+ ilc_media_cont_MediaContainer
+
-
-
- display:table;float:left; clear:both; margin-left: 0px;
-
-
- display:table;float:right; clear:both; margin-right: 0px;
-
-
-
- display:table; margin-left: 0px;
-
-
- display:table; margin-right: 0px;
-
+
-
-
- Fullscreen
- Standard
-
-
-
-
+
+
-
-
+
+
+
+ curpurpose
+ standard
+
+
-
-
-
- curpurpose
- standard
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+ mobs/mm_/
+
+
+
+
+
+
+
+ mobs/mm_/
+
+
+
+
+
+
+
-
-
-
-
-
- mobs/mm_/
-
-
-
-
-
-
-
- mobs/mm_/
-
-
-
-
-
-
-
+
+
+
+ alias
+ mob
+ none
+
+
-
-
-
- alias
- mob
- none
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ display:table;
+
+ display:table;
+
+
+
+
+
+
+
+ display: table-caption; caption-side: bottom;
+
+
+
+
+
+
+
+
+
+
+
+
+
+ float:left; clear:both; margin-left: 0px;
+
+
+ float:right; clear:both; margin-right: 0px;
+
+
+
+
+ margin-left: 0px;
+
+
+ margin-right: 0px;
+
+
+
+
-
-
-
-
-
-
-
-
-
width:px;
-
-
-
-
-
-
-
-
@@ -2291,59 +2316,61 @@
-->
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ :
+
+
+
+
+
+ cmd[exec_:]
+
+
+
+
+
+
+
|