ILIAS  release_7 Revision v7.30-3-g800a261c036
class.ilTestQuestionBrowserTableGUI.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4require_once './Services/Table/classes/class.ilTable2GUI.php';
5require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionList.php';
6
7use ILIAS\UI\Factory as UIFactory;
8use ILIAS\UI\Renderer as UIRenderer;
9use ILIAS\Refinery\Factory as Refinery;
10use ILIAS\Modules\Test\QuestionPoolLinkedTitleBuilder;
11
23{
24 use QuestionPoolLinkedTitleBuilder;
25
27
28 const CONTEXT_PARAMETER = 'question_browse_context';
29 const CONTEXT_PAGE_VIEW = 'contextPageView';
30 const CONTEXT_LIST_VIEW = 'contextListView';
31
32 const MODE_PARAMETER = 'question_browse_mode';
33 const MODE_BROWSE_POOLS = 'modeBrowsePools';
34 const MODE_BROWSE_TESTS = 'modeBrowseTests';
35
36 const CMD_BROWSE_QUESTIONS = 'browseQuestions';
37 const CMD_APPLY_FILTER = 'applyFilter';
38 const CMD_RESET_FILTER = 'resetFilter';
39 const CMD_INSERT_QUESTIONS = 'insertQuestions';
40
41 protected $writeAccess = false;
42
46 protected $ctrl;
47 private $ui_factory;
48 private $ui_renderer;
49
53 protected $mainTpl;
54
58 protected $tabs;
59
63 protected $lng;
64
68 protected $tree;
69
73 protected $db;
74
78 protected $pluginAdmin;
79
83 protected $testOBJ;
84
88 protected $access;
89
93 protected $refinery;
94
107 public function __construct(
117 Refinery $refinery,
118 UIFactory $ui_factory,
119 UIRenderer $ui_renderer
120 ) {
121 $this->ctrl = $ctrl;
122 $this->mainTpl = $mainTpl;
123 $this->tabs = $tabs;
124 $this->lng = $lng;
125 $this->tree = $tree;
126 $this->db = $db;
127 $this->pluginAdmin = $pluginAdmin;
128 $this->testOBJ = $testOBJ;
129 $this->access = $access;
130 $this->refinery = $refinery;
131 $this->ui_factory = $ui_factory;
132 $this->ui_renderer = $ui_renderer;
133
134 $this->setId('qpl_brows_tabl_' . $this->testOBJ->getId());
135
136 parent::__construct($this, self::CMD_BROWSE_QUESTIONS);
137 $this->setFilterCommand(self::CMD_APPLY_FILTER);
138 $this->setResetCommand(self::CMD_RESET_FILTER);
139
140 $this->setFormName('questionbrowser');
141 $this->setStyle('table', 'fullwidth');
142 $this->addColumn('', '', '1%', true);
143 $this->addColumn($this->lng->txt("tst_question_title"), 'title', '');
144 $this->addColumn($this->lng->txt("description"), 'description', '');
145 $this->addColumn($this->lng->txt("tst_question_type"), 'ttype', '');
146 $this->addColumn($this->lng->txt("author"), 'author', '');
147 $this->addColumn($this->lng->txt('qst_lifecycle'), 'lifecycle', '');
148 $this->addColumn($this->lng->txt("create_date"), 'created', '');
149 $this->addColumn($this->lng->txt("last_update"), 'tstamp', ''); // name of col is proper "updated" but in data array the key is "tstamp"
150 $this->addColumn($this->getParentObjectLabel(), 'qpl', '');
151 $this->addColumn($this->lng->txt("working_time"), 'working_time', '');
152 $this->setSelectAllCheckbox('q_id');
153 $this->setRowTemplate("tpl.il_as_tst_question_browser_row.html", "Modules/Test");
154
155 $this->setFormAction($this->ctrl->getFormAction($this->getParentObject(), $this->getParentCmd()));
156 $this->setDefaultOrderField("title");
157 $this->setDefaultOrderDirection("asc");
158
159 $this->enable('sort');
160 //$this->enable('header');
161 $this->enable('select_all');
162 $this->initFilter();
163 $this->setDisableFilterHiding(true);
164 }
165
166 public function setWriteAccess($value)
167 {
168 $this->writeAccess = $value;
169 }
170
171 public function hasWriteAccess()
172 {
173 return $this->writeAccess;
174 }
175
176 public function init()
177 {
178 if ($this->hasWriteAccess()) {
179 $this->addMultiCommand(self::CMD_INSERT_QUESTIONS, $this->lng->txt('insert'));
180 }
181 }
182
183 public function executeCommand()
184 {
185 $this->handleParameters();
186 $this->handleTabs();
187
188 switch ($this->ctrl->getNextClass($this)) {
189 case strtolower(__CLASS__):
190 case '':
191
192 $cmd = $this->ctrl->getCmd() . 'Cmd';
193 return $this->$cmd();
194
195 default:
196
197 $this->ctrl->setReturn($this, self::CMD_BROWSE_QUESTIONS);
198 return parent::executeCommand();
199 }
200 }
201
202 private function browseQuestionsCmd()
203 {
204 $this->setData($this->getQuestionsData());
205
206 $this->mainTpl->setContent($this->ctrl->getHTML($this));
207 }
208
209 private function applyFilterCmd()
210 {
211 $this->writeFilterToSession();
212 $this->ctrl->redirect($this, self::CMD_BROWSE_QUESTIONS);
213 }
214
215 private function resetFilterCmd()
216 {
217 $this->resetFilter();
218 $this->ctrl->redirect($this, self::CMD_BROWSE_QUESTIONS);
219 }
220
221 private function insertQuestionsCmd()
222 {
223 $selected_array = (is_array($_POST['q_id'])) ? $_POST['q_id'] : array();
224 if (!count($selected_array)) {
225 ilUtil::sendInfo($this->lng->txt("tst_insert_missing_question"), true);
226 $this->ctrl->redirect($this, self::CMD_BROWSE_QUESTIONS);
227 }
228
229 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
230
231 $testQuestionSetConfig = $this->buildTestQuestionSetConfig();
232
233 $manscoring = false;
234
235 foreach ($selected_array as $key => $value) {
236 $last_question_id = $this->testOBJ->insertQuestion($testQuestionSetConfig, $value);
237
238 if (!$manscoring) {
239 $manscoring = $manscoring | assQuestion::_needsManualScoring($value);
240 }
241 }
242
243 $this->testOBJ->saveCompleteStatus($testQuestionSetConfig);
244
245 if ($manscoring) {
246 ilUtil::sendInfo($this->lng->txt("manscoring_hint"), true);
247 } else {
248 ilUtil::sendSuccess($this->lng->txt("tst_questions_inserted"), true);
249 }
250
251 //$this->ctrl->setParameter($this, 'q_id', $last_question_id); // for page view ?
252
253 $this->ctrl->redirectByClass($this->getBackTargetCmdClass(), $this->getBackTargetCommand());
254 }
255
256 private function handleParameters()
257 {
258 $this->ctrl->saveParameter($this, self::CONTEXT_PARAMETER);
259 if (isset($_GET[self::CONTEXT_PARAMETER])) {
260 $this->addHiddenInput(self::CONTEXT_PARAMETER, $_GET[self::CONTEXT_PARAMETER]);
261 } elseif (isset($_POST[self::CONTEXT_PARAMETER])) {
262 $this->addHiddenInput(self::CONTEXT_PARAMETER, $_POST[self::CONTEXT_PARAMETER]);
263 }
264
265 $this->ctrl->saveParameter($this, self::MODE_PARAMETER);
266 if (isset($_GET[self::MODE_PARAMETER])) {
267 $this->addHiddenInput(self::MODE_PARAMETER, $_GET[self::MODE_PARAMETER]);
268 } elseif (isset($_POST[self::MODE_PARAMETER])) {
269 $this->addHiddenInput(self::MODE_PARAMETER, $_POST[self::MODE_PARAMETER]);
270 }
271 }
272
273 private function fetchContextParameter()
274 {
275 if (isset($_POST[self::CONTEXT_PARAMETER])) {
277 }
278
279 if (isset($_GET[self::CONTEXT_PARAMETER])) {
281 }
282
283 return null;
284 }
285
286 private function fetchModeParameter()
287 {
288 if (isset($_POST[self::MODE_PARAMETER])) {
290 }
291
292 if (isset($_GET[self::MODE_PARAMETER])) {
294 }
295
296 return null;
297 }
298
299 private function handleTabs()
300 {
301 $this->tabs->clearTargets();
302 $this->tabs->clearSubTabs();
303
304 $this->tabs->setBackTarget(
305 $this->getBackTargetLabel(),
306 $this->getBackTargetUrl()
307 );
308
309 $this->tabs->addTab(
310 'browseQuestions',
313 );
314 }
315
316 private function getBackTargetLabel()
317 {
318 return $this->lng->txt('backtocallingtest');
319 }
320
321 private function getBackTargetUrl()
322 {
323 return $this->ctrl->getLinkTargetByClass(
324 $this->getBackTargetCmdClass(),
325 $this->getBackTargetCommand()
326 );
327 }
328
329 private function getBackTargetCmdClass()
330 {
331 switch ($this->fetchContextParameter()) {
333
334 return 'ilObjTestGUI';
335
337
338 return 'ilTestExpressPageObjectGUI';
339 }
340
341 return '';
342 }
343
344 private function getBackTargetCommand()
345 {
346 switch ($this->fetchContextParameter()) {
348
349 return 'questions';
350
352
353 return 'showPage';
354 }
355
356 return '';
357 }
358
359 private function getBrowseQuestionsTabLabel()
360 {
361 switch ($this->fetchModeParameter()) {
363
364 return $this->lng->txt('tst_browse_for_qpl_questions');
365
367
368 return $this->lng->txt('tst_browse_for_tst_questions');
369 }
370
371 return '';
372 }
373
374 private function getBrowseQuestionsTabUrl()
375 {
376 return $this->ctrl->getLinkTarget($this, self::CMD_BROWSE_QUESTIONS);
377 }
378
379 public function initFilter()
380 {
381 // title
382 include_once("./Services/Form/classes/class.ilTextInputGUI.php");
383 $ti = new ilTextInputGUI($this->lng->txt("tst_qbt_filter_question_title"), "title");
384 $ti->setMaxLength(64);
385 $ti->setSize(20);
386 $ti->setValidationRegexp('/(^[^%]+$)|(^$)/is');
387 $this->addFilterItem($ti);
388 $ti->readFromSession();
389 $this->filter["title"] = $ti->getValue();
390
391 // description
392 $ti = new ilTextInputGUI($this->lng->txt("description"), "description");
393 $ti->setMaxLength(64);
394 $ti->setSize(20);
395 $ti->setValidationRegexp('/(^[^%]+$)|(^$)/is');
396 $this->addFilterItem($ti);
397 $ti->readFromSession();
398 $this->filter["description"] = $ti->getValue();
399
400 // author
401 $ti = new ilTextInputGUI($this->lng->txt("author"), "author");
402 $ti->setMaxLength(64);
403 $ti->setSize(20);
404 $this->addFilterItem($ti);
405 $ti->setValidationRegexp('/(^[^%]+$)|(^$)/is');
406 $ti->readFromSession();
407 $this->filter["author"] = $ti->getValue();
408
409 // lifecycle
410 $lifecycleOptions = array_merge(
411 array('' => $this->lng->txt('qst_lifecycle_filter_all')),
412 ilAssQuestionLifecycle::getDraftInstance()->getSelectOptions($this->lng)
413 );
414 $lifecycleInp = new ilSelectInputGUI($this->lng->txt('qst_lifecycle'), 'lifecycle');
415 $lifecycleInp->setOptions($lifecycleOptions);
416 $this->addFilterItem($lifecycleInp);
417 $lifecycleInp->readFromSession();
418 $this->filter['lifecycle'] = $lifecycleInp->getValue();
419
420 // questiontype
421 include_once("./Services/Form/classes/class.ilSelectInputGUI.php");
422 include_once("./Modules/TestQuestionPool/classes/class.ilObjQuestionPool.php");
424 $options = array();
425 $options[""] = $this->lng->txt('filter_all_question_types');
426 foreach ($types as $translation => $row) {
427 $options[$row['type_tag']] = $translation;
428 }
429
430 $si = new ilSelectInputGUI($this->lng->txt("question_type"), "type");
431 $si->setOptions($options);
432 $this->addFilterItem($si);
433 $si->readFromSession();
434 $this->filter["type"] = $si->getValue();
435
436 // question pool
437 $ti = new ilTextInputGUI($this->getParentObjectLabel(), 'parent_title');
438 $ti->setMaxLength(64);
439 $ti->setSize(20);
440 $ti->setValidationRegexp('/(^[^%]+$)|(^$)/is');
441 $this->addFilterItem($ti);
442 $ti->readFromSession();
443 $this->filter['parent_title'] = $ti->getValue();
444
445 // repo root node
446 require_once 'Services/Form/classes/class.ilRepositorySelectorInputGUI.php';
447 $ri = new ilRepositorySelectorInputGUI($this->lng->txt('repository'), 'repository_root_node');
448 $ri->setHeaderMessage($this->lng->txt('question_browse_area_info'));
449 if ($this->fetchModeParameter() == self::MODE_BROWSE_TESTS) {
450 $ri->setClickableTypes(array('tst'));
451 } else {
452 $ri->setClickableTypes(array('qpl'));
453 }
454 $this->addFilterItem($ri);
455 $ri->readFromSession();
456 $this->filter['repository_root_node'] = $ri->getValue();
457 }
458
459 private function getParentObjectLabel()
460 {
461 switch ($this->fetchModeParameter()) {
463
464 return $this->lng->txt('qpl');
465
467
468 return $this->lng->txt('tst');
469 }
470
471 return '';
472 }
473
474 protected function getTranslatedLifecycle($lifecycle)
475 {
476 try {
477 return ilAssQuestionLifecycle::getInstance($lifecycle)->getTranslation($this->lng);
479 return '';
480 }
481 }
482
483 public function fillRow($data)
484 {
485 $this->tpl->setVariable("QUESTION_ID", $data["question_id"]);
486 $this->tpl->setVariable("QUESTION_TITLE", $data["title"]);
487 $this->tpl->setVariable("QUESTION_COMMENT", $data["description"]);
488 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
489 $this->tpl->setVariable("QUESTION_TYPE", assQuestion::_getQuestionTypeName($data["type_tag"]));
490 $this->tpl->setVariable("QUESTION_AUTHOR", $data["author"]);
491 $this->tpl->setVariable("QUESTION_LIFECYCLE", $this->getTranslatedLifecycle($data['lifecycle']));
492 $this->tpl->setVariable("QUESTION_CREATED", ilDatePresentation::formatDate(new ilDate($data['created'], IL_CAL_UNIX)));
493 $this->tpl->setVariable("QUESTION_UPDATED", ilDatePresentation::formatDate(new ilDate($data["tstamp"], IL_CAL_UNIX)));
494 $this->tpl->setVariable("QUESTION_POOL", $data['parent_title']);
495 $this->tpl->setVariable(
496 "QUESTION_POOL_OR_TEST_TITLE",
498 (int) $data["obj_fi"],
499 $data["parent_title"]
500 )
501 );
502 $this->tpl->setVariable("WORKING_TIME", $data['working_time']);
503 }
504
505 private function buildPossiblyLinkedQuestonPoolOrTestTitle(int $obj_id, string $parent_title) : string
506 {
507 switch ($this->fetchModeParameter()) {
509 return $this->buildPossiblyLinkedQuestonPoolTitle(
510 $this->ctrl,
511 $this->access,
512 $this->lng,
513 $this->ui_factory,
514 $this->ui_renderer,
515 $obj_id,
516 $parent_title
517 );
518
520 return $this->buildPossiblyLinkedTestTitle(
521 $this->ctrl,
522 $this->access,
523 $this->lng,
524 $this->ui_factory,
525 $this->ui_renderer,
526 $obj_id,
527 $parent_title
528 );
529 }
530
531 return '';
532 }
533
537 private function buildTestQuestionSetConfig()
538 {
539 require_once 'Modules/Test/classes/class.ilTestQuestionSetConfigFactory.php';
540
541 $testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory(
542 $this->tree,
543 $this->db,
544 $this->pluginAdmin,
545 $this->testOBJ
546 );
547
548 return $testQuestionSetConfigFactory->getQuestionSetConfig();
549 }
550
554 private function getQuestionsData()
555 {
556 $questionList = new ilAssQuestionList($this->db, $this->lng, $this->refinery, $this->pluginAdmin);
557
558 $questionList->setQuestionInstanceTypeFilter($this->getQuestionInstanceTypeFilter());
559 $questionList->setExcludeQuestionIdsFilter($this->testOBJ->getExistingQuestions());
560
561 $repositoryRootNode = self::REPOSITORY_ROOT_NODE_ID;
562
563 foreach ($this->getFilterItems() as $item) {
564 if ($item->getValue() !== false) {
565 switch ($item->getPostVar()) {
566 case 'title':
567 case 'description':
568 case 'author':
569 case 'lifecycle':
570 case 'type':
571 case 'parent_title':
572
573 $questionList->addFieldFilter($item->getPostVar(), $item->getValue());
574 break;
575
576 case 'repository_root_node':
577
578 $repositoryRootNode = $item->getValue();
579 }
580 }
581 }
582
583 $parentObjectIds = $this->getQuestionParentObjIds($repositoryRootNode);
584
585 if (!count($parentObjectIds)) {
586 return array();
587 }
588
589 $questionList->setParentObjIdsFilter($parentObjectIds);
590 $questionList->setParentObjectType($this->getQuestionParentObjectType());
591
592 $questionList->load();
593
594 return $questionList->getQuestionDataArray();
595 }
596
598 {
599 if ($this->fetchModeParameter() === self::MODE_BROWSE_TESTS) {
601 }
602
604 }
605
606 private function getQuestionParentObjIds($repositoryRootNode)
607 {
608 $parents = $this->tree->getSubTree(
609 $this->tree->getNodeData($repositoryRootNode),
610 true,
611 $this->getQuestionParentObjectType()
612 );
613
614 $parentIds = array();
615
616 foreach ($parents as $nodeData) {
617 if ($nodeData['obj_id'] == $this->testOBJ->getId()) {
618 continue;
619 }
620
621 $parentIds[ $nodeData['obj_id'] ] = $nodeData['obj_id'];
622 }
623
624 $parentIds = array_map('intval', array_values($parentIds));
625
626 if ($this->fetchModeParameter() == self::MODE_BROWSE_POOLS) {
627 $available_pools = array_map('intval', array_keys(ilObjQuestionPool::_getAvailableQuestionpools(true)));
628 return array_intersect($parentIds, $available_pools);
629 } elseif ($this->fetchModeParameter() == self::MODE_BROWSE_TESTS) {
630 // TODO bheyser: Move this to another place ...
631 return array_filter($parentIds, function ($obj_id) {
632 $refIds = ilObject::_getAllReferences($obj_id);
633 $refId = current($refIds);
634 return $this->access->checkAccess('write', '', $refId);
635 });
636 }
637
638 // Return no parent ids if the user wants to hack...
639 return array();
640 }
641
643 {
644 if ($this->fetchModeParameter() == self::MODE_BROWSE_TESTS) {
645 return 'tst';
646 }
647
648 return 'qpl';
649 }
650}
$_GET["client_id"]
$_POST["username"]
An exception for terminatinating execution or to throw for unit testing.
Builds data types.
Definition: Factory.php:20
const IL_CAL_UNIX
static _getQuestionTypeName($type_tag)
Return the translation for a given question type tag.
static _needsManualScoring($question_id)
This class provides processing control methods.
static formatDate(ilDateTime $date, $a_skip_day=false, $a_include_wd=false, $include_seconds=false)
Format a date @access public.
Class for single dates.
language handling
static _getQuestionTypes($all_tags=false, $fixOrder=false, $withDeprecatedTypes=true)
static _getAvailableQuestionpools($use_object_id=false, $equal_points=false, $could_be_offline=false, $showPath=false, $with_questioncount=false, $permission="read", $usr_id="")
Returns the available question pools for the active user.
static _getAllReferences($a_id)
get all reference ids of object
Administration class for plugins.
This class represents a repository selector in a property form.
This class represents a selection list property in a property form.
Class ilTable2GUI.
addHiddenInput($a_name, $a_value)
Add Hidden Input field.
setDisableFilterHiding($a_val=true)
Set disable filter hiding.
getFilterItems($a_optionals=false)
Get filter items.
setSelectAllCheckbox($a_select_all_checkbox, $a_select_all_on_top=false)
Set the name of the checkbox that should be toggled with a select all button.
setData($a_data)
set table data @access public
setResetCommand($a_val, $a_caption=null)
Set reset filter command.
setRowTemplate($a_template, $a_template_dir="")
Set row template.
addMultiCommand($a_cmd, $a_text)
Add Command button.
addFilterItem($a_input_item, $a_optional=false)
Add filter item.
setDefaultOrderField($a_defaultorderfield)
Set Default order field.
addColumn( $a_text, $a_sort_field="", $a_width="", $a_is_checkbox_action_column=false, $a_class="", $a_tooltip="", $a_tooltip_with_html=false)
Add a column to the header.
resetFilter()
Reset filter.
setId($a_val)
Set id.
writeFilterToSession()
Write filter values to session.
setFormName($a_formname="")
Set Form name.
setFormAction($a_form_action, $a_multipart=false)
Set Form action parameter.
setDefaultOrderDirection($a_defaultorderdirection)
Set Default order direction.
setFilterCommand($a_val, $a_caption=null)
Set filter command.
setStyle($a_element, $a_style)
enable($a_module_name)
enables particular modules of table
Tabs GUI.
fillRow($data)
Standard Version of Fill Row.
buildPossiblyLinkedQuestonPoolOrTestTitle(int $obj_id, string $parent_title)
__construct(ilCtrl $ctrl, ilGlobalTemplateInterface $mainTpl, ilTabsGUI $tabs, ilLanguage $lng, ilTree $tree, ilDBInterface $db, ilPluginAdmin $pluginAdmin, ilObjTest $testOBJ, ilAccessHandler $access, Refinery $refinery, UIFactory $ui_factory, UIRenderer $ui_renderer)
ilTestQuestionBrowserTableGUI constructor.
This class represents a text property in a property form.
Tree class data representation in hierachical trees using the Nested Set Model with Gaps by Joe Celco...
static sendInfo($a_info="", $a_keep=false)
Send Info Message to Screen.
filter()
Definition: filter.php:2
This is how the factory for UI elements looks.
Definition: Factory.php:18
An entity that renders components to a string output.
Definition: Renderer.php:15
Interface ilAccessHandler.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
$refId
Definition: xapitoken.php:40